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

Fixes #4960

* Switches to using enum classes with an underlying type to avoid
  undefined behaviour
diff --git a/Android.mk b/Android.mk
index 3a28b66..bf9e580 100644
--- a/Android.mk
+++ b/Android.mk
@@ -220,7 +220,8 @@
 		                --core-insts-output=$(1)/core.insts-unified1.inc \
 		                --glsl-insts-output=$(1)/glsl.std.450.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"
 $(LOCAL_PATH)/source/opcode.cpp: $(1)/core.insts-unified1.inc
 $(LOCAL_PATH)/source/operand.cpp: $(1)/operand.kinds-unified1.inc
@@ -294,7 +295,8 @@
 		                --extinst-debuginfo-grammar=$(SPV_DEBUGINFO_GRAMMAR) \
 		                --extinst-cldebuginfo100-grammar=$(SPV_CLDEBUGINFO100_GRAMMAR) \
 		                --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"
 # Generated header extension_enum.inc is transitively included by table.h, which is
 # used pervasively.  Capture the pervasive dependency.
diff --git a/BUILD.bazel b/BUILD.bazel
index 35dfd66..0af7700 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -137,7 +137,7 @@
     copts = COMMON_COPTS,
     includes = ["source"],
     deps = [
-        "@spirv_headers//:spirv_c_headers",
+        "@spirv_headers//:spirv_cpp11_headers",
     ],
 )
 
@@ -162,7 +162,7 @@
     deps = [
         ":generated_headers",
         ":spirv_tools_headers",
-        "@spirv_headers//:spirv_c_headers",
+        "@spirv_headers//:spirv_cpp11_headers",
         "@spirv_headers//:spirv_common_headers",
     ],
 )
diff --git a/BUILD.gn b/BUILD.gn
index e4c14f2..14d431b 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -69,6 +69,8 @@
       rebase_path(cldebuginfo100_insts_file, root_build_dir),
       "--operand-kinds-output",
       rebase_path(operand_kinds_file, root_build_dir),
+      "--output-language",
+      "c++"
     ]
   }
 }
@@ -101,6 +103,8 @@
       rebase_path(extension_enum_file, root_build_dir),
       "--enum-string-mapping-output",
       rebase_path(extension_map_file, root_build_dir),
+      "--output-language",
+      "c++"
     ]
     inputs = [
       core_json_file,
@@ -142,6 +146,8 @@
       rebase_path(glsl_json_file, root_build_dir),
       "--glsl-insts-output",
       rebase_path(glsl_insts_file, root_build_dir),
+      "--output-language",
+      "c++"
     ]
     inputs = [
       core_json_file,
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1b8fe92..7815a29 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -200,7 +200,7 @@
     if(NOT "${SPIRV_PERF}" STREQUAL "")
       target_compile_options(${TARGET} PRIVATE -fno-omit-frame-pointer)
     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
         "Use the clang sanitizer [address|memory|thread|...]")
       if(NOT "${SPIRV_USE_SANITIZER}" STREQUAL "")
diff --git a/DEPS b/DEPS
index 3a5f614..a134582 100644
--- a/DEPS
+++ b/DEPS
@@ -6,7 +6,7 @@
   'effcee_revision': '35912e1b7778ec2ddcff7e7188177761539e59e0',
   'googletest_revision': 'd9bb8412d60b993365abb53f00b6dad9b2c01b62',
   're2_revision': 'd2836d1b1c34c4e330a85a1006201db474bf2c8a',
-  'spirv_headers_revision': '85a1ed200d50660786c1a88d9166e871123cce39',
+  'spirv_headers_revision': '47f2465ee3e78ec5ec38f00b2c405d9475797228',
 }
 
 deps = {
diff --git a/build_defs.bzl b/build_defs.bzl
index 7189137..ed726ae 100644
--- a/build_defs.bzl
+++ b/build_defs.bzl
@@ -66,7 +66,8 @@
             "--extinst-debuginfo-grammar=$(location {1}) " +
             "--extinst-cldebuginfo100-grammar=$(location {2}) " +
             "--core-insts-output=$(location {3}) " +
-            "--operand-kinds-output=$(location {4})"
+            "--operand-kinds-output=$(location {4}) " +
+            "--output-language=c++"
         ).format(*fmtargs),
         cmd_bat = (
             "$(location :generate_grammar_tables) " +
@@ -74,7 +75,8 @@
             "--extinst-debuginfo-grammar=$(location {1}) " +
             "--extinst-cldebuginfo100-grammar=$(location {2}) " +
             "--core-insts-output=$(location {3}) " +
-            "--operand-kinds-output=$(location {4})"
+            "--operand-kinds-output=$(location {4}) " +
+            "--output-language=c++"
         ).format(*fmtargs),
         exec_tools = [":generate_grammar_tables"],
         visibility = ["//visibility:private"],
@@ -103,7 +105,8 @@
             "--extinst-debuginfo-grammar=$(location {1}) " +
             "--extinst-cldebuginfo100-grammar=$(location {2}) " +
             "--extension-enum-output=$(location {3}) " +
-            "--enum-string-mapping-output=$(location {4})"
+            "--enum-string-mapping-output=$(location {4}) " +
+            "--output-language=c++"
         ).format(*fmtargs),
         cmd_bat = (
             "$(location :generate_grammar_tables) " +
@@ -111,7 +114,8 @@
             "--extinst-debuginfo-grammar=$(location {1}) " +
             "--extinst-cldebuginfo100-grammar=$(location {2}) " +
             "--extension-enum-output=$(location {3}) " +
-            "--enum-string-mapping-output=$(location {4})"
+            "--enum-string-mapping-output=$(location {4}) " +
+            "--output-language=c++"
         ).format(*fmtargs),
         exec_tools = [":generate_grammar_tables"],
         visibility = ["//visibility:private"],
@@ -158,12 +162,14 @@
         cmd = (
             "$(location :generate_grammar_tables) " +
             "--extinst-glsl-grammar=$(location {0}) " +
-            "--glsl-insts-output=$(location {1})"
+            "--glsl-insts-output=$(location {1}) " +
+            "--output-language=c++"
         ).format(*fmtargs),
         cmd_bat = (
             "$(location :generate_grammar_tables) " +
             "--extinst-glsl-grammar=$(location {0}) " +
-            "--glsl-insts-output=$(location {1})"
+            "--glsl-insts-output=$(location {1}) " +
+            "--output-language=c++"
         ).format(*fmtargs),
         exec_tools = [":generate_grammar_tables"],
         visibility = ["//visibility:private"],
diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt
index 668579a..f904024 100644
--- a/source/CMakeLists.txt
+++ b/source/CMakeLists.txt
@@ -37,6 +37,7 @@
       --extinst-cldebuginfo100-grammar=${CLDEBUGINFO100_GRAMMAR_JSON_FILE}
       --core-insts-output=${GRAMMAR_INSTS_INC_FILE}
       --operand-kinds-output=${GRAMMAR_KINDS_INC_FILE}
+      --output-language=c++
     DEPENDS ${GRAMMAR_PROCESSING_SCRIPT}
             ${GRAMMAR_JSON_FILE}
             ${DEBUGINFO_GRAMMAR_JSON_FILE}
@@ -58,6 +59,7 @@
       --extinst-cldebuginfo100-grammar=${CLDEBUGINFO100_GRAMMAR_JSON_FILE}
       --extension-enum-output=${GRAMMAR_EXTENSION_ENUM_INC_FILE}
       --enum-string-mapping-output=${GRAMMAR_ENUM_STRING_MAPPING_INC_FILE}
+      --output-language=c++
     DEPENDS ${GRAMMAR_PROCESSING_SCRIPT}
             ${GRAMMAR_JSON_FILE}
             ${DEBUGINFO_GRAMMAR_JSON_FILE}
@@ -92,6 +94,7 @@
     COMMAND ${PYTHON_EXECUTABLE} ${GRAMMAR_PROCESSING_SCRIPT}
       --extinst-glsl-grammar=${GLSL_GRAMMAR_JSON_FILE}
       --glsl-insts-output=${GRAMMAR_INC_FILE}
+      --output-language=c++
     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}.")
   list(APPEND EXTINST_CPP_DEPENDS ${GRAMMAR_INC_FILE})
diff --git a/source/assembly_grammar.cpp b/source/assembly_grammar.cpp
index 4f5942a..6df823e 100644
--- a/source/assembly_grammar.cpp
+++ b/source/assembly_grammar.cpp
@@ -78,16 +78,16 @@
 
 // Associates an opcode with its name.
 struct SpecConstantOpcodeEntry {
-  SpvOp opcode;
+  spv::Op opcode;
   const char* name;
 };
 
 // All the opcodes allowed as the operation for OpSpecConstantOp.
-// The name does not have the usual "Op" prefix. For example opcode SpvOpIAdd
-// is associated with the name "IAdd".
+// The name does not have the usual "Op" prefix. For example opcode
+// spv::Op::IAdd is associated with the name "IAdd".
 //
 // clang-format off
-#define CASE(NAME) { SpvOp##NAME, #NAME }
+#define CASE(NAME) { spv::Op::Op##NAME, #NAME }
 const SpecConstantOpcodeEntry kOpSpecConstantOpcodes[] = {
     // Conversion
     CASE(SConvert),
@@ -173,7 +173,7 @@
 }
 
 CapabilitySet AssemblyGrammar::filterCapsAgainstTargetEnv(
-    const SpvCapability* cap_array, uint32_t count) const {
+    const spv::Capability* cap_array, uint32_t count) const {
   CapabilitySet cap_set;
   for (uint32_t i = 0; i < count; ++i) {
     spv_operand_desc cap_desc = {};
@@ -194,7 +194,7 @@
   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 {
   return spvOpcodeTableValueLookup(target_env_, opcodeTable_, opcode, desc);
 }
@@ -214,7 +214,7 @@
 }
 
 spv_result_t AssemblyGrammar::lookupSpecConstantOpcode(const char* name,
-                                                       SpvOp* opcode) const {
+                                                       spv::Op* opcode) const {
   const auto* last = kOpSpecConstantOpcodes + kNumOpSpecConstantOpcodes;
   const auto* found =
       std::find_if(kOpSpecConstantOpcodes, last,
@@ -226,7 +226,7 @@
   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* found =
       std::find_if(kOpSpecConstantOpcodes, last,
diff --git a/source/assembly_grammar.h b/source/assembly_grammar.h
index 17c2bd3..36fdd08 100644
--- a/source/assembly_grammar.h
+++ b/source/assembly_grammar.h
@@ -41,7 +41,7 @@
 
   // Removes capabilities not available in the current target environment and
   // returns the rest.
-  CapabilitySet filterCapsAgainstTargetEnv(const SpvCapability* cap_array,
+  CapabilitySet filterCapsAgainstTargetEnv(const spv::Capability* cap_array,
                                            uint32_t count) const;
 
   // Fills in the desc parameter with the information about the opcode
@@ -52,7 +52,7 @@
   // Fills in the desc parameter with the information about the opcode
   // of the valid. Returns SPV_SUCCESS if the opcode was found, and
   // 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
   // operand. Returns SPV_SUCCESS if the operand was found, and
@@ -82,11 +82,12 @@
   // the integer add opcode for OpSpecConstantOp.  On success, returns
   // SPV_SUCCESS and sends the discovered operation code through the opcode
   // 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
   // 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.
   //
diff --git a/source/binary.cpp b/source/binary.cpp
index 24d32f8..beb56be 100644
--- a/source/binary.cpp
+++ b/source/binary.cpp
@@ -156,7 +156,7 @@
   // Issues a diagnostic describing an exhaustion of input condition when
   // trying to decode an instruction operand, and returns
   // 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) {
     return diagnostic() << "End of input reached while decoding Op"
                         << spvOpcodeString(opcode) << " starting at word "
@@ -318,7 +318,7 @@
                         << inst_word_count;
   }
   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;
 
   // Advance past the opcode word.  But remember the of the start
@@ -418,7 +418,7 @@
                                   std::vector<uint32_t>* words,
                                   std::vector<spv_parsed_operand_t>* 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.
   spv_parsed_operand_t parsed_operand;
   parsed_operand.offset = uint16_t(_.word_index - inst_offset);
@@ -473,7 +473,7 @@
       if (!word) return diagnostic(SPV_ERROR_INVALID_ID) << "Id is 0";
       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.
         // Set the extended instruction set type for the current instruction.
         auto ext_inst_type_iter = _.import_id_to_ext_inst_type.find(word);
@@ -494,7 +494,7 @@
       break;
 
     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);
       spv_ext_inst_desc ext_inst;
       if (grammar_.lookupExtInst(inst->ext_inst_type, word, &ext_inst) ==
@@ -516,14 +516,14 @@
     } break;
 
     case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER: {
-      assert(SpvOpSpecConstantOp == opcode);
-      if (word > static_cast<uint32_t>(SpvOp::SpvOpMax) ||
-          grammar_.lookupSpecConstantOpcode(SpvOp(word))) {
+      assert(spv::Op::OpSpecConstantOp == opcode);
+      if (word > static_cast<uint32_t>(spv::Op::Max) ||
+          grammar_.lookupSpecConstantOpcode(spv::Op(word))) {
         return diagnostic()
                << "Invalid " << spvOperandTypeStr(type) << ": " << word;
       }
       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)
                << "OpSpecConstant opcode table out of sync";
       }
@@ -549,7 +549,7 @@
     case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER:
     case SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER:
       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
         // referenced by the selector Id.
         const uint32_t selector_id = peekAt(inst_offset + 1);
@@ -575,7 +575,8 @@
                               << " is not a scalar integer";
         }
       } 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
         // constant.
         assert(inst->type_id);
@@ -607,7 +608,7 @@
       parsed_operand.num_words = uint16_t(string_num_words);
       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.
         // There is only one string literal argument to OpExtInstImport,
         // so it's sufficient to guard this just on the opcode.
@@ -789,14 +790,14 @@
 
 void Parser::recordNumberType(size_t inst_offset,
                               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)) {
     NumberType info = {SPV_NUMBER_NONE, 0};
-    if (SpvOpTypeInt == opcode) {
+    if (spv::Op::OpTypeInt == opcode) {
       const bool is_signed = peekAt(inst_offset + 3) != 0;
       info.type = is_signed ? SPV_NUMBER_SIGNED_INT : SPV_NUMBER_UNSIGNED_INT;
       info.bit_width = peekAt(inst_offset + 2);
-    } else if (SpvOpTypeFloat == opcode) {
+    } else if (spv::Op::OpTypeFloat == opcode) {
       info.type = SPV_NUMBER_FLOATING;
       info.bit_width = peekAt(inst_offset + 2);
     }
diff --git a/source/diff/diff.cpp b/source/diff/diff.cpp
index 7ed41de..6daed32 100644
--- a/source/diff/diff.cpp
+++ b/source/diff/diff.cpp
@@ -44,8 +44,8 @@
 // different implementations produce identical results.
 using IdGroupMapByName = std::map<std::string, IdGroup>;
 using IdGroupMapByTypeId = std::map<uint32_t, IdGroup>;
-using IdGroupMapByOp = std::map<SpvOp, IdGroup>;
-using IdGroupMapByStorageClass = std::map<SpvStorageClass, IdGroup>;
+using IdGroupMapByOp = std::map<spv::Op, IdGroup>;
+using IdGroupMapByStorageClass = std::map<spv::StorageClass, IdGroup>;
 
 // 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
@@ -301,10 +301,10 @@
   // Get various properties from an id.  These Helper functions are passed to
   // `GroupIds` and `GroupIdsAndMatch` below (as the `get_group` argument).
   uint32_t GroupIdsHelperGetTypeId(const IdInstructions& id_to, uint32_t id);
-  SpvStorageClass GroupIdsHelperGetTypePointerStorageClass(
+  spv::StorageClass GroupIdsHelperGetTypePointerStorageClass(
       const IdInstructions& id_to, uint32_t id);
-  SpvOp GroupIdsHelperGetTypePointerTypeOp(const IdInstructions& id_to,
-                                           uint32_t id);
+  spv::Op GroupIdsHelperGetTypePointerTypeOp(const IdInstructions& id_to,
+                                             uint32_t id);
 
   // 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
@@ -414,8 +414,8 @@
   // Helper functions to retrieve information pertaining to an id
   const opt::Instruction* GetInst(const IdInstructions& id_to, uint32_t id);
   uint32_t GetConstantUint(const IdInstructions& id_to, uint32_t constant_id);
-  SpvExecutionModel GetExecutionModel(const opt::Module* module,
-                                      uint32_t entry_point_id);
+  spv::ExecutionModel GetExecutionModel(const opt::Module* module,
+                                        uint32_t entry_point_id);
   bool HasName(const IdInstructions& id_to, uint32_t id);
   // Get the OpName associated with an id
   std::string GetName(const IdInstructions& id_to, uint32_t id, bool* has_name);
@@ -424,20 +424,21 @@
   // string, and this improves diff between SPIR-V from those tools and others.
   std::string GetSanitizedName(const IdInstructions& id_to, uint32_t 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,
-                          SpvDecoration decoration, uint32_t* decoration_value);
+                          spv::Decoration decoration,
+                          uint32_t* decoration_value);
   const opt::Instruction* GetForwardPointerInst(const IdInstructions& id_to,
                                                 uint32_t id);
   bool IsIntType(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 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 IsPerVertexVariable(const IdInstructions& id_to, uint32_t type_id);
-  SpvStorageClass GetPerVertexStorageClass(const opt::Module* module,
-                                           uint32_t type_id);
+  spv::StorageClass GetPerVertexStorageClass(const opt::Module* module,
+                                             uint32_t type_id);
   spv_ext_inst_type_t GetExtInstType(const IdInstructions& id_to,
                                      uint32_t set_id);
   spv_number_kind_t GetNumberKind(const IdInstructions& id_to,
@@ -561,19 +562,19 @@
     uint32_t id_operand = 0;
 
     switch (inst.opcode()) {
-      case SpvOpName:
+      case spv::Op::OpName:
         info_map = &name_map_;
         break;
-      case SpvOpMemberName:
+      case spv::Op::OpMemberName:
         info_map = &name_map_;
         break;
-      case SpvOpDecorate:
+      case spv::Op::OpDecorate:
         info_map = &decoration_map_;
         break;
-      case SpvOpMemberDecorate:
+      case spv::Op::OpMemberDecorate:
         info_map = &decoration_map_;
         break;
-      case SpvOpTypeForwardPointer: {
+      case spv::Op::OpTypeForwardPointer: {
         uint32_t id = inst.GetSingleWordOperand(0);
         assert(id != 0);
 
@@ -731,10 +732,10 @@
   // Instead of comparing OpExecutionMode entry point ids as ids, compare them
   // through their corresponding execution model.  This simplifies traversing
   // the sorted list of instructions between src and dst modules.
-  if (a->opcode() == SpvOpExecutionMode) {
-    const SpvExecutionModel src_model =
+  if (a->opcode() == spv::Op::OpExecutionMode) {
+    const spv::ExecutionModel src_model =
         GetExecutionModel(src_inst_module, a->GetSingleWordOperand(0));
-    const SpvExecutionModel dst_model =
+    const spv::ExecutionModel dst_model =
         GetExecutionModel(dst_inst_module, b->GetSingleWordOperand(0));
 
     if (src_model < dst_model) {
@@ -818,17 +819,17 @@
   return GetInst(id_to, id)->type_id();
 }
 
-SpvStorageClass Differ::GroupIdsHelperGetTypePointerStorageClass(
+spv::StorageClass Differ::GroupIdsHelperGetTypePointerStorageClass(
     const IdInstructions& id_to, uint32_t id) {
   const opt::Instruction* inst = GetInst(id_to, id);
-  assert(inst && inst->opcode() == SpvOpTypePointer);
-  return SpvStorageClass(inst->GetSingleWordInOperand(0));
+  assert(inst && inst->opcode() == spv::Op::OpTypePointer);
+  return spv::StorageClass(inst->GetSingleWordInOperand(0));
 }
 
-SpvOp Differ::GroupIdsHelperGetTypePointerTypeOp(const IdInstructions& id_to,
-                                                 uint32_t id) {
+spv::Op Differ::GroupIdsHelperGetTypePointerTypeOp(const IdInstructions& id_to,
+                                                   uint32_t 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 opt::Instruction* type_inst = GetInst(id_to, type_id);
@@ -1020,7 +1021,7 @@
   }
   // For external instructions, make sure the set and opcode of the external
   // instruction matches too.
-  if (src_inst->opcode() == SpvOpExtInst) {
+  if (src_inst->opcode() == spv::Op::OpExtInst) {
     if (!DoOperandsMatch(src_inst, dst_inst, 0, 2)) {
       return false;
     }
@@ -1064,26 +1065,26 @@
   }
 
   switch (src_inst->opcode()) {
-    case SpvOpString:
-    case SpvOpSourceExtension:
-    case SpvOpModuleProcessed:
+    case spv::Op::OpString:
+    case spv::Op::OpSourceExtension:
+    case spv::Op::OpModuleProcessed:
       return DoesOperandMatch(src_inst->GetOperand(0), dst_inst->GetOperand(0));
-    case SpvOpSource:
+    case spv::Op::OpSource:
       return DoOperandsMatch(src_inst, dst_inst, 0, 2);
-    case SpvOpSourceContinued:
+    case spv::Op::OpSourceContinued:
       return true;
-    case SpvOpName:
+    case spv::Op::OpName:
       return DoOperandsMatch(src_inst, dst_inst, 0, 1);
-    case SpvOpMemberName:
+    case spv::Op::OpMemberName:
       return DoOperandsMatch(src_inst, dst_inst, 0, 2);
-    case SpvOpDecorate:
+    case spv::Op::OpDecorate:
       return DoOperandsMatch(src_inst, dst_inst, 0, 2);
-    case SpvOpMemberDecorate:
+    case spv::Op::OpMemberDecorate:
       return DoOperandsMatch(src_inst, dst_inst, 0, 3);
-    case SpvOpExtInst:
-    case SpvOpDecorationGroup:
-    case SpvOpGroupDecorate:
-    case SpvOpGroupMemberDecorate:
+    case spv::Op::OpExtInst:
+    case spv::Op::OpDecorationGroup:
+    case spv::Op::OpGroupDecorate:
+    case spv::Op::OpGroupMemberDecorate:
       return false;
     default:
       return false;
@@ -1095,9 +1096,9 @@
   // Variables must match by their built-in decorations.
   uint32_t src_built_in_decoration = 0, dst_built_in_decoration = 0;
   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(
-      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) {
     return false;
@@ -1107,7 +1108,7 @@
   }
 
   // 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 =
       GetVarTypeId(src_id_to_, src_id, &src_storage_class);
   const uint32_t dst_type_id =
@@ -1127,12 +1128,14 @@
         // 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
         // global as part of linking two stages (as done in ANGLE).
-        const bool src_is_io = src_storage_class == SpvStorageClassInput ||
-                               src_storage_class == SpvStorageClassOutput;
-        const bool dst_is_io = dst_storage_class == SpvStorageClassInput ||
-                               dst_storage_class == SpvStorageClassOutput;
-        const bool src_is_private = src_storage_class == SpvStorageClassPrivate;
-        const bool dst_is_private = dst_storage_class == SpvStorageClassPrivate;
+        const bool src_is_io = src_storage_class == spv::StorageClass::Input ||
+                               src_storage_class == spv::StorageClass::Output;
+        const bool dst_is_io = dst_storage_class == spv::StorageClass::Input ||
+                               dst_storage_class == spv::StorageClass::Output;
+        const bool src_is_private =
+            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))) {
           return false;
@@ -1277,16 +1280,16 @@
   // Otherwise, match them by SpecId.
   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) &&
-      GetDecorationValue(dst_id_to_, dst_id, SpvDecorationSpecId,
+      GetDecorationValue(dst_id_to_, dst_id, spv::Decoration::SpecId,
                          &dst_spec_id)) {
     return src_spec_id == dst_spec_id;
   }
 
   // There is no SpecId decoration, while not practical, still valid.
   // 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()) {
       return DoOperandsMatch(src_inst, dst_inst, 0,
                              src_inst->NumInOperandWords());
@@ -1327,13 +1330,13 @@
   // built-in decorations.
   uint32_t src_built_in_decoration;
   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)) {
     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(dst_id_to_, dst_id, &dst_storage_class);
 
@@ -1348,13 +1351,13 @@
     uint32_t src_binding = 0, dst_binding = 0;
 
     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(
-        dst_id_to_, dst_id, SpvDecorationDescriptorSet, &dst_set);
-    const bool src_has_binding =
-        GetDecorationValue(src_id_to_, src_id, SpvDecorationBinding, &src_set);
-    const bool dst_has_binding =
-        GetDecorationValue(dst_id_to_, dst_id, SpvDecorationBinding, &dst_set);
+        dst_id_to_, dst_id, spv::Decoration::DescriptorSet, &dst_set);
+    const bool src_has_binding = GetDecorationValue(
+        src_id_to_, src_id, spv::Decoration::Binding, &src_set);
+    const bool dst_has_binding = GetDecorationValue(
+        dst_id_to_, dst_id, spv::Decoration::Binding, &dst_set);
 
     if (src_has_set && dst_has_set && src_has_binding && dst_has_binding) {
       return src_set == dst_set && src_binding == dst_binding;
@@ -1367,9 +1370,9 @@
     uint32_t src_location, dst_location;
 
     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(
-        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) {
       return src_location == dst_location;
@@ -1384,25 +1387,25 @@
   // 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
   // have two instances of gl_PerVertex.
-  SpvStorageClass src_storage_class =
+  spv::StorageClass src_storage_class =
       GetPerVertexStorageClass(src_, src_type_id);
-  SpvStorageClass dst_storage_class =
+  spv::StorageClass dst_storage_class =
       GetPerVertexStorageClass(dst_, dst_type_id);
 
-  assert(src_storage_class == SpvStorageClassInput ||
-         src_storage_class == SpvStorageClassOutput);
-  assert(dst_storage_class == SpvStorageClassInput ||
-         dst_storage_class == SpvStorageClassOutput);
+  assert(src_storage_class == spv::StorageClass::Input ||
+         src_storage_class == spv::StorageClass::Output);
+  assert(dst_storage_class == spv::StorageClass::Input ||
+         dst_storage_class == spv::StorageClass::Output);
 
   return src_storage_class == dst_storage_class;
 }
 
 bool Differ::MatchPerVertexVariable(const opt::Instruction* src_inst,
                                     const opt::Instruction* dst_inst) {
-  SpvStorageClass src_storage_class =
-      SpvStorageClass(src_inst->GetSingleWordInOperand(0));
-  SpvStorageClass dst_storage_class =
-      SpvStorageClass(dst_inst->GetSingleWordInOperand(0));
+  spv::StorageClass src_storage_class =
+      spv::StorageClass(src_inst->GetSingleWordInOperand(0));
+  spv::StorageClass dst_storage_class =
+      spv::StorageClass(dst_inst->GetSingleWordInOperand(0));
 
   return src_storage_class == dst_storage_class;
 }
@@ -1479,7 +1482,7 @@
   InstructionList body;
   function.WhileEachInst(
       [&body](const opt::Instruction* inst) {
-        if (inst->opcode() == SpvOpLabel) {
+        if (inst->opcode() == spv::Op::OpLabel) {
           return false;
         }
         body.push_back(inst);
@@ -1694,12 +1697,12 @@
     default:
       // TODO: match functions based on OpFunctionCall?
       break;
-    case SpvOpAccessChain:
-    case SpvOpInBoundsAccessChain:
-    case SpvOpPtrAccessChain:
-    case SpvOpInBoundsPtrAccessChain:
-    case SpvOpLoad:
-    case SpvOpStore:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
+    case spv::Op::OpPtrAccessChain:
+    case spv::Op::OpInBoundsPtrAccessChain:
+    case spv::Op::OpLoad:
+    case spv::Op::OpStore:
       const uint32_t src_pointer_id = src_inst->GetSingleWordInOperand(0);
       const uint32_t dst_pointer_id = dst_inst->GetSingleWordInOperand(0);
       if (IsVariable(src_id_to_, src_pointer_id) &&
@@ -1727,23 +1730,24 @@
 uint32_t Differ::GetConstantUint(const IdInstructions& id_to,
                                  uint32_t constant_id) {
   const opt::Instruction* constant_inst = GetInst(id_to, constant_id);
-  assert(constant_inst->opcode() == SpvOpConstant);
-  assert(GetInst(id_to, constant_inst->type_id())->opcode() == SpvOpTypeInt);
+  assert(constant_inst->opcode() == spv::Op::OpConstant);
+  assert(GetInst(id_to, constant_inst->type_id())->opcode() ==
+         spv::Op::OpTypeInt);
 
   return constant_inst->GetSingleWordInOperand(0);
 }
 
-SpvExecutionModel Differ::GetExecutionModel(const opt::Module* module,
-                                            uint32_t entry_point_id) {
+spv::ExecutionModel Differ::GetExecutionModel(const opt::Module* module,
+                                              uint32_t entry_point_id) {
   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) {
-      return SpvExecutionModel(inst.GetSingleWordOperand(0));
+      return spv::ExecutionModel(inst.GetSingleWordOperand(0));
     }
   }
 
   assert(false && "Unreachable");
-  return SpvExecutionModel(0xFFF);
+  return spv::ExecutionModel(0xFFF);
 }
 
 bool Differ::HasName(const IdInstructions& id_to, uint32_t id) {
@@ -1751,7 +1755,7 @@
   assert(id < id_to.name_map_.size());
 
   for (const opt::Instruction* inst : id_to.name_map_[id]) {
-    if (inst->opcode() == SpvOpName) {
+    if (inst->opcode() == spv::Op::OpName) {
       return true;
     }
   }
@@ -1765,7 +1769,7 @@
   assert(id < id_to.name_map_.size());
 
   for (const opt::Instruction* inst : id_to.name_map_[id]) {
-    if (inst->opcode() == SpvOpName) {
+    if (inst->opcode() == spv::Op::OpName) {
       *has_name = true;
       return inst->GetOperand(1).AsString();
     }
@@ -1788,11 +1792,11 @@
 }
 
 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);
-  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.
   const uint32_t type_pointer_id = var_inst->type_id();
@@ -1803,15 +1807,15 @@
 }
 
 bool Differ::GetDecorationValue(const IdInstructions& id_to, uint32_t id,
-                                SpvDecoration decoration,
+                                spv::Decoration decoration,
                                 uint32_t* decoration_value) {
   assert(id != 0);
   assert(id < id_to.decoration_map_.size());
 
   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(1) == decoration) {
+        spv::Decoration(inst->GetSingleWordOperand(1)) == decoration) {
       *decoration_value = inst->GetSingleWordOperand(2);
       return true;
     }
@@ -1828,28 +1832,28 @@
 }
 
 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) {
-  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) {
   const opt::Instruction* constant_inst = GetInst(id_to, id);
-  if (constant_inst->opcode() != SpvOpConstant) {
+  if (constant_inst->opcode() != spv::Op::OpConstant) {
     return false;
   }
 
   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) {
-  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;
 }
 
@@ -1858,17 +1862,18 @@
   assert(type_id < id_to.decoration_map_.size());
 
   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(2) == SpvDecorationBuiltIn) {
-      SpvBuiltIn built_in = SpvBuiltIn(inst->GetSingleWordOperand(3));
+        spv::Decoration(inst->GetSingleWordOperand(2)) ==
+            spv::Decoration::BuiltIn) {
+      spv::BuiltIn built_in = spv::BuiltIn(inst->GetSingleWordOperand(3));
 
       // Only gl_PerVertex can have, and it can only have, the following
       // built-in decorations.
-      return built_in == SpvBuiltInPosition ||
-             built_in == SpvBuiltInPointSize ||
-             built_in == SpvBuiltInClipDistance ||
-             built_in == SpvBuiltInCullDistance;
+      return built_in == spv::BuiltIn::Position ||
+             built_in == spv::BuiltIn::PointSize ||
+             built_in == spv::BuiltIn::ClipDistance ||
+             built_in == spv::BuiltIn::CullDistance;
     }
   }
 
@@ -1877,12 +1882,12 @@
 
 bool Differ::IsPerVertexVariable(const IdInstructions& id_to, uint32_t var_id) {
   // 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);
   const opt::Instruction* type_inst = GetInst(id_to, type_id);
 
   // If array, get the element type.
-  if (type_inst->opcode() == SpvOpTypeArray) {
+  if (type_inst->opcode() == spv::Op::OpTypeArray) {
     type_id = type_inst->GetSingleWordInOperand(0);
   }
 
@@ -1890,21 +1895,21 @@
   return IsPerVertexType(id_to, type_id);
 }
 
-SpvStorageClass Differ::GetPerVertexStorageClass(const opt::Module* module,
-                                                 uint32_t type_id) {
+spv::StorageClass Differ::GetPerVertexStorageClass(const opt::Module* module,
+                                                   uint32_t type_id) {
   for (const opt::Instruction& inst : module->types_values()) {
     switch (inst.opcode()) {
-      case SpvOpTypeArray:
+      case spv::Op::OpTypeArray:
         // The gl_PerVertex instance could be an array, look for a variable of
         // the array type instead.
         if (inst.GetSingleWordInOperand(0) == type_id) {
           type_id = inst.result_id();
         }
         break;
-      case SpvOpTypePointer:
+      case spv::Op::OpTypePointer:
         // Find the storage class of the pointer to this type.
         if (inst.GetSingleWordInOperand(1) == type_id) {
-          return SpvStorageClass(inst.GetSingleWordInOperand(0));
+          return spv::StorageClass(inst.GetSingleWordInOperand(0));
         }
         break;
       default:
@@ -1915,7 +1920,7 @@
   // 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
   // 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,
@@ -1941,9 +1946,9 @@
     case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER:
     case SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER:
       switch (inst.opcode()) {
-        case SpvOpSwitch:
-        case SpvOpConstant:
-        case SpvOpSpecConstant:
+        case spv::Op::OpSwitch:
+        case spv::Op::OpConstant:
+        case spv::Op::OpSpecConstant:
           // Same kind of number as the selector (OpSwitch) or the type
           // (Op*Constant).
           return GetTypeNumberKind(id_to, inst.GetSingleWordOperand(0),
@@ -1969,12 +1974,12 @@
   }
 
   switch (type_inst->opcode()) {
-    case SpvOpTypeInt:
+    case spv::Op::OpTypeInt:
       *number_bit_width = type_inst->GetSingleWordOperand(1);
       return type_inst->GetSingleWordOperand(2) == 0 ? SPV_NUMBER_UNSIGNED_INT
                                                      : SPV_NUMBER_SIGNED_INT;
       break;
-    case SpvOpTypeFloat:
+    case spv::Op::OpTypeFloat:
       *number_bit_width = type_inst->GetSingleWordOperand(1);
       return SPV_NUMBER_FLOATING;
     default:
@@ -2092,7 +2097,7 @@
     return inst.GetSingleWordOperand(0);
   };
   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,
@@ -2116,17 +2121,17 @@
   //     - If leftover is unique, match
 
   // Group forwarded pointers by storage class first and loop over them.
-  GroupIdsAndMatch<SpvStorageClass>(
-      potential_id_map.src_ids, potential_id_map.dst_ids, SpvStorageClassMax,
-      &Differ::GroupIdsHelperGetTypePointerStorageClass,
+  GroupIdsAndMatch<spv::StorageClass>(
+      potential_id_map.src_ids, potential_id_map.dst_ids,
+      spv::StorageClass::Max, &Differ::GroupIdsHelperGetTypePointerStorageClass,
       [this](const IdGroup& src_group_by_storage_class,
              const IdGroup& dst_group_by_storage_class) {
 
         // Group them further by the type they are pointing to and loop over
         // them.
-        GroupIdsAndMatch<SpvOp>(
-            src_group_by_storage_class, dst_group_by_storage_class, SpvOpMax,
-            &Differ::GroupIdsHelperGetTypePointerTypeOp,
+        GroupIdsAndMatch<spv::Op>(
+            src_group_by_storage_class, dst_group_by_storage_class,
+            spv::Op::Max, &Differ::GroupIdsHelperGetTypePointerTypeOp,
             [this](const IdGroup& src_group_by_type_op,
                    const IdGroup& dst_group_by_type_op) {
 
@@ -2182,8 +2187,8 @@
     MatchIds(potential_id_map, [this, flexibility](
                                    const opt::Instruction* src_inst,
                                    const opt::Instruction* dst_inst) {
-      const SpvOp src_op = src_inst->opcode();
-      const SpvOp dst_op = dst_inst->opcode();
+      const spv::Op src_op = src_inst->opcode();
+      const spv::Op dst_op = dst_inst->opcode();
 
       // Don't match if the opcode is not the same.
       if (src_op != dst_op) {
@@ -2191,26 +2196,26 @@
       }
 
       switch (src_op) {
-        case SpvOpTypeVoid:
-        case SpvOpTypeBool:
-        case SpvOpTypeSampler:
+        case spv::Op::OpTypeVoid:
+        case spv::Op::OpTypeBool:
+        case spv::Op::OpTypeSampler:
           // void, bool and sampler are unique, match them.
           return true;
-        case SpvOpTypeInt:
-        case SpvOpTypeFloat:
-        case SpvOpTypeVector:
-        case SpvOpTypeMatrix:
-        case SpvOpTypeSampledImage:
-        case SpvOpTypeRuntimeArray:
-        case SpvOpTypePointer:
+        case spv::Op::OpTypeInt:
+        case spv::Op::OpTypeFloat:
+        case spv::Op::OpTypeVector:
+        case spv::Op::OpTypeMatrix:
+        case spv::Op::OpTypeSampledImage:
+        case spv::Op::OpTypeRuntimeArray:
+        case spv::Op::OpTypePointer:
           // Match these instructions when all operands match.
           assert(src_inst->NumInOperandWords() ==
                  dst_inst->NumInOperandWords());
           return DoOperandsMatch(src_inst, dst_inst, 0,
                                  src_inst->NumInOperandWords());
 
-        case SpvOpTypeFunction:
-        case SpvOpTypeImage:
+        case spv::Op::OpTypeFunction:
+        case spv::Op::OpTypeImage:
           // Match function types only if they have the same number of operands,
           // and they all match.
           // Match image types similarly, expecting the optional final parameter
@@ -2221,7 +2226,7 @@
           return DoOperandsMatch(src_inst, dst_inst, 0,
                                  src_inst->NumInOperandWords());
 
-        case SpvOpTypeArray:
+        case spv::Op::OpTypeArray:
           // 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
           // compared instead.
@@ -2238,7 +2243,7 @@
           // example if a spec contant is used).
           return DoOperandsMatch(src_inst, dst_inst, 1, 1);
 
-        case SpvOpTypeStruct:
+        case spv::Op::OpTypeStruct:
           return MatchOpTypeStruct(src_inst, dst_inst, flexibility);
 
         default:
@@ -2270,8 +2275,8 @@
     MatchIds(potential_id_map, [this, flexibility](
                                    const opt::Instruction* src_inst,
                                    const opt::Instruction* dst_inst) {
-      const SpvOp src_op = src_inst->opcode();
-      const SpvOp dst_op = dst_inst->opcode();
+      const spv::Op src_op = src_inst->opcode();
+      const spv::Op dst_op = dst_inst->opcode();
 
       // Don't match if the opcode is not the same.
       if (src_op != dst_op) {
@@ -2279,14 +2284,14 @@
       }
 
       switch (src_op) {
-        case SpvOpConstantTrue:
-        case SpvOpConstantFalse:
+        case spv::Op::OpConstantTrue:
+        case spv::Op::OpConstantFalse:
           // true and false are unique, match them.
           return true;
-        case SpvOpConstant:
+        case spv::Op::OpConstant:
           return MatchOpConstant(src_inst, dst_inst, flexibility);
-        case SpvOpConstantComposite:
-        case SpvOpSpecConstantComposite:
+        case spv::Op::OpConstantComposite:
+        case spv::Op::OpSpecConstantComposite:
           // Composite constants must match in type and value.
           //
           // TODO: match OpConstantNull with OpConstantComposite with all zeros
@@ -2299,7 +2304,7 @@
                                   dst_inst->GetOperand(0)) &&
                  DoOperandsMatch(src_inst, dst_inst, 0,
                                  src_inst->NumInOperandWords());
-        case SpvOpConstantSampler:
+        case spv::Op::OpConstantSampler:
           // Match sampler constants exactly.
           // TODO: Allow flexibility in parameters to better diff shaders where
           // the sampler param has changed.
@@ -2307,15 +2312,15 @@
                  dst_inst->NumInOperandWords());
           return DoOperandsMatch(src_inst, dst_inst, 0,
                                  src_inst->NumInOperandWords());
-        case SpvOpConstantNull:
+        case spv::Op::OpConstantNull:
           // Match null constants as long as the type matches.
           return DoesOperandMatch(src_inst->GetOperand(0),
                                   dst_inst->GetOperand(0));
 
-        case SpvOpSpecConstantTrue:
-        case SpvOpSpecConstantFalse:
-        case SpvOpSpecConstant:
-        case SpvOpSpecConstantOp:
+        case spv::Op::OpSpecConstantTrue:
+        case spv::Op::OpSpecConstantFalse:
+        case spv::Op::OpSpecConstant:
+        case spv::Op::OpSpecConstantOp:
           // Match spec constants by name if available, then by the SpecId
           // decoration.
           return MatchOpSpecConstant(src_inst, dst_inst);
@@ -2334,7 +2339,7 @@
     return inst.result_id();
   };
   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,
@@ -2350,8 +2355,8 @@
     MatchIds(potential_id_map,
              [this, flexibility](const opt::Instruction* src_inst,
                                  const opt::Instruction* dst_inst) {
-               assert(src_inst->opcode() == SpvOpVariable);
-               assert(dst_inst->opcode() == SpvOpVariable);
+               assert(src_inst->opcode() == spv::Op::OpVariable);
+               assert(dst_inst->opcode() == spv::Op::OpVariable);
 
                return MatchOpVariable(src_inst, dst_inst, flexibility);
              });
@@ -2597,7 +2602,7 @@
   parsed_inst->num_words = static_cast<uint16_t>(inst_binary.size());
   parsed_inst->opcode = static_cast<uint16_t>(inst.opcode());
   parsed_inst->ext_inst_type =
-      inst.opcode() == SpvOpExtInst
+      inst.opcode() == spv::Op::OpExtInst
           ? GetExtInstType(id_to, original_inst.GetSingleWordInOperand(0))
           : SPV_EXT_INST_TYPE_NONE;
   parsed_inst->type_id =
diff --git a/source/disassemble.cpp b/source/disassemble.cpp
index 1d61b9f..f862efd 100644
--- a/source/disassemble.cpp
+++ b/source/disassemble.cpp
@@ -244,7 +244,7 @@
 
 void InstructionDisassembler::EmitInstruction(
     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) {
     SetBlue();
@@ -268,7 +268,7 @@
     EmitOperand(inst, i);
   }
 
-  if (comment_ && opcode == SpvOpName) {
+  if (comment_ && opcode == spv::Op::OpName) {
     const spv_parsed_operand_t& operand = inst.operands[0];
     const uint32_t word = inst.words[operand.offset];
     stream_ << "  ; id %" << word;
@@ -290,8 +290,8 @@
 void InstructionDisassembler::EmitSectionComment(
     const spv_parsed_instruction_t& inst, bool& inserted_decoration_space,
     bool& inserted_debug_space, bool& inserted_type_space) {
-  auto opcode = static_cast<SpvOp>(inst.opcode);
-  if (comment_ && opcode == SpvOpFunction) {
+  auto opcode = static_cast<spv::Op>(inst.opcode);
+  if (comment_ && opcode == spv::Op::OpFunction) {
     stream_ << std::endl;
     stream_ << std::string(indent_, ' ');
     stream_ << "; Function " << name_mapper_(inst.result_id) << std::endl;
@@ -351,7 +351,7 @@
     } break;
     case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER: {
       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");
       SetRed();
       stream_ << opcode_desc->name;
diff --git a/source/enum_set.h b/source/enum_set.h
index d4d31e3..28ee5fe 100644
--- a/source/enum_set.h
+++ b/source/enum_set.h
@@ -200,8 +200,8 @@
   std::unique_ptr<OverflowSetType> overflow_ = {};
 };
 
-// A set of SpvCapability, optimized for small capability values.
-using CapabilitySet = EnumSet<SpvCapability>;
+// A set of spv::Capability, optimized for small capability values.
+using CapabilitySet = EnumSet<spv::Capability>;
 
 }  // namespace spvtools
 
diff --git a/source/enum_string_mapping.h b/source/enum_string_mapping.h
index af8f56b..b136584 100644
--- a/source/enum_string_mapping.h
+++ b/source/enum_string_mapping.h
@@ -29,7 +29,7 @@
 const char* ExtensionToString(Extension extension);
 
 // Returns text string corresponding to |capability|.
-const char* CapabilityToString(SpvCapability capability);
+const char* CapabilityToString(spv::Capability capability);
 
 }  // namespace spvtools
 
diff --git a/source/extensions.cpp b/source/extensions.cpp
index 049a3ad..ebf6bec 100644
--- a/source/extensions.cpp
+++ b/source/extensions.cpp
@@ -24,7 +24,9 @@
 namespace spvtools {
 
 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);
 
diff --git a/source/fuzz/added_function_reducer.cpp b/source/fuzz/added_function_reducer.cpp
index e7cb027..95cf9d6 100644
--- a/source/fuzz/added_function_reducer.cpp
+++ b/source/fuzz/added_function_reducer.cpp
@@ -130,7 +130,7 @@
                   binary_under_reduction.size());
   assert(ir_context != nullptr && "The binary should be parsable.");
   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;
     }
     if (irrelevant_pointee_global_variables.count(type_or_value.result_id())) {
@@ -202,7 +202,7 @@
   auto* ir_context = replay_result.transformed_module.get();
 
   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;
     }
     if (replay_result.transformation_context->GetFactManager()
diff --git a/source/fuzz/call_graph.cpp b/source/fuzz/call_graph.cpp
index c52bc34..d61a5f8 100644
--- a/source/fuzz/call_graph.cpp
+++ b/source/fuzz/call_graph.cpp
@@ -54,7 +54,7 @@
     // Consider every function call instruction in every block.
     for (auto& block : function) {
       for (auto& instruction : block) {
-        if (instruction.opcode() != SpvOpFunctionCall) {
+        if (instruction.opcode() != spv::Op::OpFunctionCall) {
           continue;
         }
         // Get the id of the function being called.
diff --git a/source/fuzz/fact_manager/constant_uniform_facts.cpp b/source/fuzz/fact_manager/constant_uniform_facts.cpp
index a629c0d..461859b 100644
--- a/source/fuzz/fact_manager/constant_uniform_facts.cpp
+++ b/source/fuzz/fact_manager/constant_uniform_facts.cpp
@@ -63,7 +63,7 @@
 bool ConstantUniformFacts::DataMatches(
     const opt::Instruction& constant_instruction,
     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;
   for (uint32_t i = 0; i < constant_instruction.NumInOperands(); i++) {
     data_in_constant.push_back(constant_instruction.GetSingleWordInOperand(i));
@@ -95,7 +95,7 @@
     uint32_t constant_id) const {
   std::vector<protobufs::UniformBufferElementDescriptor> result;
   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");
   auto type_id = constant_inst->type_id();
   for (auto& fact_and_type_id : facts_and_type_ids_) {
@@ -175,8 +175,9 @@
     return false;
   }
 
-  assert(SpvOpVariable == uniform_variable->opcode());
-  assert(SpvStorageClassUniform == uniform_variable->GetSingleWordInOperand(0));
+  assert(spv::Op::OpVariable == uniform_variable->opcode());
+  assert(spv::StorageClass::Uniform ==
+         spv::StorageClass(uniform_variable->GetSingleWordInOperand(0)));
 
   auto should_be_uniform_pointer_type =
       ir_context_->get_type_mgr()->GetType(uniform_variable->type_id());
@@ -184,7 +185,7 @@
     return false;
   }
   if (should_be_uniform_pointer_type->AsPointer()->storage_class() !=
-      SpvStorageClassUniform) {
+      spv::StorageClass::Uniform) {
     return false;
   }
   auto should_be_uniform_pointer_instruction =
diff --git a/source/fuzz/fact_manager/data_synonym_and_id_equation_facts.cpp b/source/fuzz/fact_manager/data_synonym_and_id_equation_facts.cpp
index a2c1f2c..b43b8ed 100644
--- a/source/fuzz/fact_manager/data_synonym_and_id_equation_facts.cpp
+++ b/source/fuzz/fact_manager/data_synonym_and_id_equation_facts.cpp
@@ -23,7 +23,7 @@
 size_t DataSynonymAndIdEquationFacts::OperationHash::operator()(
     const Operation& operation) const {
   std::u32string hash;
-  hash.push_back(operation.opcode);
+  hash.push_back(uint32_t(operation.opcode));
   for (auto operand : operation.operands) {
     hash.push_back(static_cast<uint32_t>(DataDescriptorHash()(operand)));
   }
@@ -104,7 +104,8 @@
   }
 
   // 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;
 }
 
@@ -119,7 +120,7 @@
 }
 
 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) {
   assert(synonymous_.Exists(lhs_dd) &&
          "The LHS must be known to the equivalence relation.");
@@ -155,21 +156,21 @@
   // Now try to work out corollaries implied by the new equation and existing
   // facts.
   switch (opcode) {
-    case SpvOpConvertSToF:
-    case SpvOpConvertUToF:
+    case spv::Op::OpConvertSToF:
+    case spv::Op::OpConvertUToF:
       ComputeConversionDataSynonymFacts(*rhs_dds[0]);
       break;
-    case SpvOpBitcast: {
+    case spv::Op::OpBitcast: {
       assert(DataDescriptorsAreWellFormedAndComparable(lhs_dd, *rhs_dds[0]) &&
              "Operands of OpBitcast equation fact must have compatible types");
       if (!synonymous_.IsEquivalent(lhs_dd, *rhs_dds[0])) {
         AddDataSynonymFactRecursive(lhs_dd, *rhs_dds[0]);
       }
     } break;
-    case SpvOpIAdd: {
+    case spv::Op::OpIAdd: {
       // Equation form: "a = b + c"
       for (const auto& equation : GetEquations(rhs_dds[0])) {
-        if (equation.opcode == SpvOpISub) {
+        if (equation.opcode == spv::Op::OpISub) {
           // Equation form: "a = (d - e) + c"
           if (synonymous_.IsEquivalent(*equation.operands[1], *rhs_dds[1])) {
             // Equation form: "a = (d - c) + c"
@@ -179,7 +180,7 @@
         }
       }
       for (const auto& equation : GetEquations(rhs_dds[1])) {
-        if (equation.opcode == SpvOpISub) {
+        if (equation.opcode == spv::Op::OpISub) {
           // Equation form: "a = b + (d - e)"
           if (synonymous_.IsEquivalent(*equation.operands[1], *rhs_dds[0])) {
             // Equation form: "a = b + (d - b)"
@@ -190,10 +191,10 @@
       }
       break;
     }
-    case SpvOpISub: {
+    case spv::Op::OpISub: {
       // Equation form: "a = b - c"
       for (const auto& equation : GetEquations(rhs_dds[0])) {
-        if (equation.opcode == SpvOpIAdd) {
+        if (equation.opcode == spv::Op::OpIAdd) {
           // Equation form: "a = (d + e) - c"
           if (synonymous_.IsEquivalent(*equation.operands[0], *rhs_dds[1])) {
             // Equation form: "a = (c + e) - c"
@@ -207,34 +208,34 @@
           }
         }
 
-        if (equation.opcode == SpvOpISub) {
+        if (equation.opcode == spv::Op::OpISub) {
           // Equation form: "a = (d - e) - c"
           if (synonymous_.IsEquivalent(*equation.operands[0], *rhs_dds[1])) {
             // Equation form: "a = (c - e) - c"
             // We can thus infer "a = -e"
-            AddEquationFactRecursive(lhs_dd, SpvOpSNegate,
+            AddEquationFactRecursive(lhs_dd, spv::Op::OpSNegate,
                                      {equation.operands[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)"
           if (synonymous_.IsEquivalent(*equation.operands[0], *rhs_dds[0])) {
             // Equation form: "a = b - (b + e)"
             // We can thus infer "a = -e"
-            AddEquationFactRecursive(lhs_dd, SpvOpSNegate,
+            AddEquationFactRecursive(lhs_dd, spv::Op::OpSNegate,
                                      {equation.operands[1]});
           }
           if (synonymous_.IsEquivalent(*equation.operands[1], *rhs_dds[0])) {
             // Equation form: "a = b - (d + b)"
             // We can thus infer "a = -d"
-            AddEquationFactRecursive(lhs_dd, SpvOpSNegate,
+            AddEquationFactRecursive(lhs_dd, spv::Op::OpSNegate,
                                      {equation.operands[0]});
           }
         }
-        if (equation.opcode == SpvOpISub) {
+        if (equation.opcode == spv::Op::OpISub) {
           // Equation form: "a = b - (d - e)"
           if (synonymous_.IsEquivalent(*equation.operands[0], *rhs_dds[0])) {
             // Equation form: "a = b - (b - e)"
@@ -245,8 +246,8 @@
       }
       break;
     }
-    case SpvOpLogicalNot:
-    case SpvOpSNegate: {
+    case spv::Op::OpLogicalNot:
+    case spv::Op::OpSNegate: {
       // Equation form: "a = !b" or "a = -b"
       for (const auto& equation : GetEquations(rhs_dds[0])) {
         if (equation.opcode == opcode) {
@@ -321,9 +322,9 @@
 
       for (const auto& equation : fact.second) {
         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);
-          } else if (equation.opcode == SpvOpConvertUToF) {
+          } else if (equation.opcode == spv::Op::OpConvertUToF) {
             convert_u_to_f_lhs.push_back(*dd_it);
           }
         }
@@ -808,9 +809,9 @@
   }
   // Neither end type is allowed to be void.
   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() ==
-          SpvOpTypeVoid) {
+          spv::Op::OpTypeVoid) {
     return false;
   }
   // If the end types are the same, the data descriptors are comparable.
diff --git a/source/fuzz/fact_manager/data_synonym_and_id_equation_facts.h b/source/fuzz/fact_manager/data_synonym_and_id_equation_facts.h
index 6652f30..36d92ca 100644
--- a/source/fuzz/fact_manager/data_synonym_and_id_equation_facts.h
+++ b/source/fuzz/fact_manager/data_synonym_and_id_equation_facts.h
@@ -79,7 +79,7 @@
   // This helper struct represents the right hand side of an equation as an
   // operator applied to a number of data descriptor operands.
   struct Operation {
-    SpvOp opcode;
+    spv::Op opcode;
     std::vector<const protobufs::DataDescriptor*> operands;
   };
 
@@ -144,7 +144,7 @@
   // corollaries, in the form of data synonym or equation facts, that follow
   // from this and other known facts.
   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);
 
   // Returns true if and only if |dd.object()| still exists in the module.
diff --git a/source/fuzz/fact_manager/fact_manager.cpp b/source/fuzz/fact_manager/fact_manager.cpp
index 40c0865..c99f690 100644
--- a/source/fuzz/fact_manager/fact_manager.cpp
+++ b/source/fuzz/fact_manager/fact_manager.cpp
@@ -64,7 +64,7 @@
 std::string ToString(const protobufs::FactIdEquation& fact) {
   std::stringstream stream;
   stream << fact.lhs_id();
-  stream << " " << static_cast<SpvOp>(fact.opcode());
+  stream << " " << fact.opcode();
   for (auto rhs_id : fact.rhs_id()) {
     stream << " " << rhs_id;
   }
@@ -255,11 +255,11 @@
   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) {
   protobufs::FactIdEquation fact;
   fact.set_lhs_id(lhs_id);
-  fact.set_opcode(opcode);
+  fact.set_opcode(uint32_t(opcode));
   for (auto an_rhs_id : rhs_id) {
     fact.add_rhs_id(an_rhs_id);
   }
diff --git a/source/fuzz/fact_manager/fact_manager.h b/source/fuzz/fact_manager/fact_manager.h
index ce28ae4..4453e44 100644
--- a/source/fuzz/fact_manager/fact_manager.h
+++ b/source/fuzz/fact_manager/fact_manager.h
@@ -83,7 +83,7 @@
   //   |lhs_id| = |opcode| |rhs_id[0]| ... |rhs_id[N-1]|
   //
   // 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);
 
   // Inspects all known facts and adds corollary facts; e.g. if we know that
diff --git a/source/fuzz/force_render_red.cpp b/source/fuzz/force_render_red.cpp
index 3267487..191fd71 100644
--- a/source/fuzz/force_render_red.cpp
+++ b/source/fuzz/force_render_red.cpp
@@ -36,8 +36,9 @@
   // Check that this is a fragment shader
   bool found_capability_shader = false;
   for (auto& capability : ir_context->capabilities()) {
-    assert(capability.opcode() == SpvOpCapability);
-    if (capability.GetSingleWordInOperand(0) == SpvCapabilityShader) {
+    assert(capability.opcode() == spv::Op::OpCapability);
+    if (spv::Capability(capability.GetSingleWordInOperand(0)) ==
+        spv::Capability::Shader) {
       found_capability_shader = true;
       break;
     }
@@ -51,7 +52,8 @@
 
   opt::Instruction* fragment_entry_point = nullptr;
   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;
       break;
     }
@@ -81,8 +83,9 @@
                                          MessageConsumer message_consumer) {
   opt::Instruction* output_variable = nullptr;
   for (auto& inst : ir_context->types_values()) {
-    if (inst.opcode() == SpvOpVariable &&
-        inst.GetSingleWordInOperand(0) == SpvStorageClassOutput) {
+    if (inst.opcode() == spv::Op::OpVariable &&
+        spv::StorageClass(inst.GetSingleWordInOperand(0)) ==
+            spv::StorageClass::Output) {
       if (output_variable != nullptr) {
         message_consumer(SPV_MSG_ERROR, nullptr, {},
                          "Only one output variable can be handled at present; "
@@ -144,10 +147,11 @@
                                uint32_t greater_than_instruction,
                                uint32_t in_operand_index) {
   return MakeUnique<TransformationReplaceConstantWithUniform>(
-      MakeIdUseDescriptor(constant_id,
-                          MakeInstructionDescriptor(greater_than_instruction,
-                                                    SpvOpFOrdGreaterThan, 0),
-                          in_operand_index),
+      MakeIdUseDescriptor(
+          constant_id,
+          MakeInstructionDescriptor(greater_than_instruction,
+                                    spv::Op::OpFOrdGreaterThan, 0),
+          in_operand_index),
       fact_manager.GetUniformDescriptorsForConstant(constant_id)[0],
       ir_context->TakeNextId(), ir_context->TakeNextId());
 }
@@ -204,20 +208,21 @@
   // Make the new exit block
   auto new_exit_block_id = ir_context->TakeNextId();
   {
-    auto label = MakeUnique<opt::Instruction>(ir_context.get(), SpvOpLabel, 0,
-                                              new_exit_block_id,
-                                              opt::Instruction::OperandList());
+    auto label = MakeUnique<opt::Instruction>(
+        ir_context.get(), spv::Op::OpLabel, 0, new_exit_block_id,
+        opt::Instruction::OperandList());
     auto new_exit_block = MakeUnique<opt::BasicBlock>(std::move(label));
-    new_exit_block->AddInstruction(MakeUnique<opt::Instruction>(
-        ir_context.get(), SpvOpReturn, 0, 0, opt::Instruction::OperandList()));
+    new_exit_block->AddInstruction(
+        MakeUnique<opt::Instruction>(ir_context.get(), spv::Op::OpReturn, 0, 0,
+                                     opt::Instruction::OperandList()));
     entry_point_function->AddBasicBlock(std::move(new_exit_block));
   }
 
   // Make the new entry block
   {
-    auto label = MakeUnique<opt::Instruction>(ir_context.get(), SpvOpLabel, 0,
-                                              ir_context->TakeNextId(),
-                                              opt::Instruction::OperandList());
+    auto label = MakeUnique<opt::Instruction>(
+        ir_context.get(), spv::Op::OpLabel, 0, ir_context->TakeNextId(),
+        opt::Instruction::OperandList());
     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
@@ -229,7 +234,7 @@
     auto temp_vec4 = opt::analysis::Vector(float_type, 4);
     auto vec4_id = ir_context->get_type_mgr()->GetId(&temp_vec4);
     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);
     auto red_id = red->result_id();
     new_entry_block->AddInstruction(std::move(red));
@@ -241,7 +246,7 @@
     opt::Instruction::OperandList op_store_operands = {variable_to_store_into,
                                                        value_to_be_stored};
     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
     // 'literal1 > literal2'. If we succeed, we will later replace each literal
@@ -313,7 +318,7 @@
               {SPV_OPERAND_TYPE_ID, {smaller_constant}},
               {SPV_OPERAND_TYPE_ID, {larger_constant}}};
           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),
               id_guaranteed_to_be_false, greater_than_operands));
 
@@ -344,9 +349,9 @@
     opt::Operand else_block = {SPV_OPERAND_TYPE_ID, {new_exit_block_id}};
     opt::Instruction::OperandList op_branch_conditional_operands = {
         false_condition, then_block, else_block};
-    new_entry_block->AddInstruction(
-        MakeUnique<opt::Instruction>(ir_context.get(), SpvOpBranchConditional,
-                                     0, 0, op_branch_conditional_operands));
+    new_entry_block->AddInstruction(MakeUnique<opt::Instruction>(
+        ir_context.get(), spv::Op::OpBranchConditional, 0, 0,
+        op_branch_conditional_operands));
 
     entry_point_function->InsertBasicBlockBefore(
         std::move(new_entry_block), entry_point_function->entry().get());
diff --git a/source/fuzz/fuzzer_pass.cpp b/source/fuzz/fuzzer_pass.cpp
index 6a87985..02d8aa1 100644
--- a/source/fuzz/fuzzer_pass.cpp
+++ b/source/fuzz/fuzzer_pass.cpp
@@ -131,14 +131,15 @@
     // should skip when searching from 'base' for the desired instruction.
     // (An instruction that has a result id is represented by its own opcode,
     // 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.
     uint32_t base = block->id();
 
     // Counts the number of times we have seen each opcode since we reset the
     // 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
     // only necessary to consider it as a base in case the first instruction
@@ -151,7 +152,7 @@
         base = inst_it->result_id();
         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.
       action(block, inst_it,
@@ -330,7 +331,7 @@
 }
 
 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
   // but distinct structs not being regarded as different.
   auto existing_id = fuzzerutil::MaybeGetPointerType(
@@ -345,7 +346,7 @@
 }
 
 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),
                                  storage_class);
 }
@@ -432,7 +433,7 @@
 
 uint32_t FuzzerPass::FindOrCreateGlobalUndef(uint32_t type_id) {
   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();
     }
   }
@@ -464,7 +465,7 @@
 
 std::pair<std::vector<uint32_t>, std::map<uint32_t, std::vector<uint32_t>>>
 FuzzerPass::GetAvailableBasicTypesAndPointers(
-    SpvStorageClass storage_class) const {
+    spv::StorageClass storage_class) const {
   // Records all of the basic types available in the module.
   std::set<uint32_t> basic_types;
 
@@ -480,23 +481,23 @@
     // For pointer types with basic pointee types, associate the pointer type
     // with the basic type.
     switch (inst.opcode()) {
-      case SpvOpTypeBool:
-      case SpvOpTypeFloat:
-      case SpvOpTypeInt:
-      case SpvOpTypeMatrix:
-      case SpvOpTypeVector:
+      case spv::Op::OpTypeBool:
+      case spv::Op::OpTypeFloat:
+      case spv::Op::OpTypeInt:
+      case spv::Op::OpTypeMatrix:
+      case spv::Op::OpTypeVector:
         // These are all basic types.
         basic_types.insert(inst.result_id());
         basic_type_to_pointers.insert({inst.result_id(), {}});
         break;
-      case SpvOpTypeArray:
+      case spv::Op::OpTypeArray:
         // An array type is basic if its base type is basic.
         if (basic_types.count(inst.GetSingleWordInOperand(0))) {
           basic_types.insert(inst.result_id());
           basic_type_to_pointers.insert({inst.result_id(), {}});
         }
         break;
-      case SpvOpTypeStruct: {
+      case spv::Op::OpTypeStruct: {
         // A struct type is basic if it does not have the Block/BufferBlock
         // decoration, and if all of its members are basic.
         if (!fuzzerutil::HasBlockOrBufferBlockDecoration(GetIRContext(),
@@ -515,11 +516,12 @@
         }
         break;
       }
-      case SpvOpTypePointer: {
+      case spv::Op::OpTypePointer: {
         // We are interested in the pointer if its pointee type is basic and it
         // has the right storage class.
         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)) {
           // 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
@@ -541,22 +543,22 @@
       GetIRContext()->get_def_use_mgr()->GetDef(scalar_or_composite_type_id);
   assert(type_instruction && "The type instruction must exist.");
   switch (type_instruction->opcode()) {
-    case SpvOpTypeBool:
+    case spv::Op::OpTypeBool:
       return FindOrCreateBoolConstant(false, is_irrelevant);
-    case SpvOpTypeFloat: {
+    case spv::Op::OpTypeFloat: {
       auto width = type_instruction->GetSingleWordInOperand(0);
       auto num_words = (width + 32 - 1) / 32;
       return FindOrCreateFloatConstant(std::vector<uint32_t>(num_words, 0),
                                        width, is_irrelevant);
     }
-    case SpvOpTypeInt: {
+    case spv::Op::OpTypeInt: {
       auto width = type_instruction->GetSingleWordInOperand(0);
       auto num_words = (width + 32 - 1) / 32;
       return FindOrCreateIntegerConstant(
           std::vector<uint32_t>(num_words, 0), width,
           type_instruction->GetSingleWordInOperand(1), is_irrelevant);
     }
-    case SpvOpTypeArray: {
+    case spv::Op::OpTypeArray: {
       auto component_type_id = type_instruction->GetSingleWordInOperand(0);
       auto num_components =
           fuzzerutil::GetArraySize(*type_instruction, GetIRContext());
@@ -566,8 +568,8 @@
               FindOrCreateZeroConstant(component_type_id, is_irrelevant)),
           scalar_or_composite_type_id, is_irrelevant);
     }
-    case SpvOpTypeMatrix:
-    case SpvOpTypeVector: {
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeVector: {
       auto component_type_id = type_instruction->GetSingleWordInOperand(0);
       auto num_components = type_instruction->GetSingleWordInOperand(1);
       return FindOrCreateCompositeConstant(
@@ -576,7 +578,7 @@
               FindOrCreateZeroConstant(component_type_id, is_irrelevant)),
           scalar_or_composite_type_id, is_irrelevant);
     }
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       assert(!fuzzerutil::HasBlockOrBufferBlockDecoration(
                  GetIRContext(), scalar_or_composite_type_id) &&
              "We do not construct constants of struct types decorated with "
@@ -646,7 +648,7 @@
 
     // |maybe_preheader| is a preheader if it branches unconditionally to
     // 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()) {
       return maybe_preheader;
     }
@@ -683,8 +685,8 @@
 
   // Find the first non-OpPhi and non-OpVariable instruction.
   auto non_phi_or_var_inst = &*block->begin();
-  while (non_phi_or_var_inst->opcode() == SpvOpPhi ||
-         non_phi_or_var_inst->opcode() == SpvOpVariable) {
+  while (non_phi_or_var_inst->opcode() == spv::Op::OpPhi ||
+         non_phi_or_var_inst->opcode() == spv::Op::OpVariable) {
     non_phi_or_var_inst = non_phi_or_var_inst->NextNode();
   }
 
@@ -706,7 +708,7 @@
   (void)pointer_type;
   assert(pointer_type && pointer_type->AsPointer() &&
          pointer_type->AsPointer()->storage_class() ==
-             SpvStorageClassFunction &&
+             spv::StorageClass::Function &&
          "The pointer_type_id must refer to a defined pointer type with "
          "storage class Function");
   auto function = fuzzerutil::FindFunction(GetIRContext(), function_id);
@@ -715,7 +717,7 @@
   // First we try to find a suitable existing variable.
   // All of the local variable declarations are located in the first block.
   for (auto& instruction : *function->begin()) {
-    if (instruction.opcode() != SpvOpVariable) {
+    if (instruction.opcode() != spv::Op::OpVariable) {
       continue;
     }
     // The existing OpVariable must have type |pointer_type_id|.
@@ -749,15 +751,16 @@
   (void)pointer_type;
   assert(
       pointer_type && pointer_type->AsPointer() &&
-      (pointer_type->AsPointer()->storage_class() == SpvStorageClassPrivate ||
+      (pointer_type->AsPointer()->storage_class() ==
+           spv::StorageClass::Private ||
        pointer_type->AsPointer()->storage_class() ==
-           SpvStorageClassWorkgroup) &&
+           spv::StorageClass::Workgroup) &&
       "The pointer_type_id must refer to a defined pointer type with storage "
       "class Private or Workgroup");
 
   // First we try to find a suitable existing variable.
   for (auto& instruction : GetIRContext()->module()->types_values()) {
-    if (instruction.opcode() != SpvOpVariable) {
+    if (instruction.opcode() != spv::Op::OpVariable) {
       continue;
     }
     // The existing OpVariable must have type |pointer_type_id|.
@@ -781,13 +784,13 @@
   uint32_t result_id = GetFuzzerContext()->GetFreshId();
 
   // A variable with storage class Workgroup shouldn't have an initializer.
-  if (storage_class == SpvStorageClassWorkgroup) {
+  if (storage_class == spv::StorageClass::Workgroup) {
     ApplyTransformation(TransformationAddGlobalVariable(
-        result_id, pointer_type_id, SpvStorageClassWorkgroup, 0,
+        result_id, pointer_type_id, spv::StorageClass::Workgroup, 0,
         pointee_value_is_irrelevant));
   } else {
     ApplyTransformation(TransformationAddGlobalVariable(
-        result_id, pointer_type_id, SpvStorageClassPrivate,
+        result_id, pointer_type_id, spv::StorageClass::Private,
         FindOrCreateZeroConstant(pointee_type_id, pointee_value_is_irrelevant),
         pointee_value_is_irrelevant));
   }
diff --git a/source/fuzz/fuzzer_pass.h b/source/fuzz/fuzzer_pass.h
index 2655b54..5c76be1 100644
--- a/source/fuzz/fuzzer_pass.h
+++ b/source/fuzz/fuzzer_pass.h
@@ -159,14 +159,14 @@
   // already exist) and storage class |storage_class|.  A transformation is
   // applied to add the pointer if it does not already exist.
   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
   // type of width and signedness specified by |width| and |is_signed|,
   // respectively.  If the pointer type or required integer base type do not
   // exist, transformations are applied to add them.
   uint32_t FindOrCreatePointerToIntegerType(uint32_t width, bool is_signed,
-                                            SpvStorageClass storage_class);
+                                            spv::StorageClass storage_class);
 
   // Returns the id of an OpConstant instruction, with a integer type of
   // width and signedness specified by |width| and |is_signed|, respectively,
@@ -239,7 +239,7 @@
   //   storage class, and the sequence will have multiple elements if there are
   //   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>>>
-  GetAvailableBasicTypesAndPointers(SpvStorageClass storage_class) const;
+  GetAvailableBasicTypesAndPointers(spv::StorageClass storage_class) const;
 
   // 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
diff --git a/source/fuzz/fuzzer_pass_add_access_chains.cpp b/source/fuzz/fuzzer_pass_add_access_chains.cpp
index 39f193d..85ca57d 100644
--- a/source/fuzz/fuzzer_pass_add_access_chains.cpp
+++ b/source/fuzz/fuzzer_pass_add_access_chains.cpp
@@ -34,15 +34,16 @@
              opt::BasicBlock::iterator inst_it,
              const protobufs::InstructionDescriptor& instruction_descriptor)
           -> void {
-        assert(inst_it->opcode() ==
-                   instruction_descriptor.target_instruction_opcode() &&
-               "The opcode of the instruction we might insert before must be "
-               "the same as the opcode in the descriptor for the instruction");
+        assert(
+            inst_it->opcode() ==
+                spv::Op(instruction_descriptor.target_instruction_opcode()) &&
+            "The opcode of the instruction we might insert before must be "
+            "the same as the opcode in the descriptor for the instruction");
 
         // Check whether it is legitimate to insert an access chain
         // instruction before this instruction.
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpAccessChain,
-                                                          inst_it)) {
+        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
+                spv::Op::OpAccessChain, inst_it)) {
           return;
         }
 
@@ -64,8 +65,8 @@
                     return false;
                   }
                   switch (instruction->opcode()) {
-                    case SpvOpConstantNull:
-                    case SpvOpUndef:
+                    case spv::Op::OpConstantNull:
+                    case spv::Op::OpUndef:
                       // Do not allow making an access chain from a null or
                       // undefined pointer.  (We can eliminate these cases
                       // before actually checking that the instruction is a
@@ -78,7 +79,7 @@
                   // make an access chain from it.
                   return context->get_def_use_mgr()
                              ->GetDef(instruction->type_id())
-                             ->opcode() == SpvOpTypePointer;
+                             ->opcode() == spv::Op::OpTypePointer;
                 });
 
         // At this point, |relevant_instructions| contains all the pointers
@@ -112,14 +113,14 @@
           }
           uint32_t bound;
           switch (subobject_type->opcode()) {
-            case SpvOpTypeArray:
+            case spv::Op::OpTypeArray:
               bound = fuzzerutil::GetArraySize(*subobject_type, GetIRContext());
               break;
-            case SpvOpTypeMatrix:
-            case SpvOpTypeVector:
+            case spv::Op::OpTypeMatrix:
+            case spv::Op::OpTypeVector:
               bound = subobject_type->GetSingleWordInOperand(1);
               break;
-            case SpvOpTypeStruct:
+            case spv::Op::OpTypeStruct:
               bound = fuzzerutil::GetNumberOfStructMembers(*subobject_type);
               break;
             default:
@@ -140,9 +141,9 @@
               GetFuzzerContext()->GetRandomIndexForAccessChain(bound);
 
           switch (subobject_type->opcode()) {
-            case SpvOpTypeArray:
-            case SpvOpTypeMatrix:
-            case SpvOpTypeVector: {
+            case spv::Op::OpTypeArray:
+            case spv::Op::OpTypeMatrix:
+            case spv::Op::OpTypeVector: {
               // The index will be clamped
 
               bool is_signed = GetFuzzerContext()->ChooseEven();
@@ -164,7 +165,7 @@
               subobject_type_id = subobject_type->GetSingleWordInOperand(0);
 
             } break;
-            case SpvOpTypeStruct:
+            case spv::Op::OpTypeStruct:
               index_ids.push_back(FindOrCreateIntegerConstant(
                   {index_value}, 32, GetFuzzerContext()->ChooseEven(), false));
               subobject_type_id =
@@ -178,7 +179,7 @@
         // pointer suitable for the access chain's result type exists, so we
         // create one if it does not.
         FindOrCreatePointerType(subobject_type_id,
-                                static_cast<SpvStorageClass>(
+                                static_cast<spv::StorageClass>(
                                     pointer_type->GetSingleWordInOperand(0)));
         // Apply the transformation to add an access chain.
         ApplyTransformation(TransformationAccessChain(
diff --git a/source/fuzz/fuzzer_pass_add_composite_extract.cpp b/source/fuzz/fuzzer_pass_add_composite_extract.cpp
index dbbec0c..c33ae44 100644
--- a/source/fuzz/fuzzer_pass_add_composite_extract.cpp
+++ b/source/fuzz/fuzzer_pass_add_composite_extract.cpp
@@ -53,8 +53,8 @@
           opt::Function* /*unused*/, opt::BasicBlock* /*unused*/,
           opt::BasicBlock::iterator inst_it,
           const protobufs::InstructionDescriptor& instruction_descriptor) {
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpCompositeExtract,
-                                                          inst_it)) {
+        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
+                spv::Op::OpCompositeExtract, inst_it)) {
           return;
         }
 
@@ -97,15 +97,15 @@
             assert(type_inst && "Composite instruction has invalid type id");
 
             switch (type_inst->opcode()) {
-              case SpvOpTypeArray:
+              case spv::Op::OpTypeArray:
                 number_of_members =
                     fuzzerutil::GetArraySize(*type_inst, GetIRContext());
                 break;
-              case SpvOpTypeVector:
-              case SpvOpTypeMatrix:
+              case spv::Op::OpTypeVector:
+              case spv::Op::OpTypeMatrix:
                 number_of_members = type_inst->GetSingleWordInOperand(1);
                 break;
-              case SpvOpTypeStruct:
+              case spv::Op::OpTypeStruct:
                 number_of_members = type_inst->NumInOperands();
                 break;
               default:
@@ -122,12 +122,12 @@
                     number_of_members));
 
             switch (type_inst->opcode()) {
-              case SpvOpTypeArray:
-              case SpvOpTypeVector:
-              case SpvOpTypeMatrix:
+              case spv::Op::OpTypeArray:
+              case spv::Op::OpTypeVector:
+              case spv::Op::OpTypeMatrix:
                 type_id = type_inst->GetSingleWordInOperand(0);
                 break;
-              case SpvOpTypeStruct:
+              case spv::Op::OpTypeStruct:
                 type_id = type_inst->GetSingleWordInOperand(indices.back());
                 break;
               default:
diff --git a/source/fuzz/fuzzer_pass_add_composite_inserts.cpp b/source/fuzz/fuzzer_pass_add_composite_inserts.cpp
index 2ac12de..048cdfd 100644
--- a/source/fuzz/fuzzer_pass_add_composite_inserts.cpp
+++ b/source/fuzz/fuzzer_pass_add_composite_inserts.cpp
@@ -36,10 +36,11 @@
              opt::BasicBlock::iterator instruction_iterator,
              const protobufs::InstructionDescriptor& instruction_descriptor)
           -> void {
-        assert(instruction_iterator->opcode() ==
-                   instruction_descriptor.target_instruction_opcode() &&
-               "The opcode of the instruction we might insert before must be "
-               "the same as the opcode in the descriptor for the instruction");
+        assert(
+            instruction_iterator->opcode() ==
+                spv::Op(instruction_descriptor.target_instruction_opcode()) &&
+            "The opcode of the instruction we might insert before must be "
+            "the same as the opcode in the descriptor for the instruction");
 
         // Randomly decide whether to try adding an OpCompositeInsert
         // instruction.
@@ -51,7 +52,7 @@
         // It must be possible to insert an OpCompositeInsert instruction
         // before |instruction_iterator|.
         if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
-                SpvOpCompositeInsert, instruction_iterator)) {
+                spv::Op::OpCompositeInsert, instruction_iterator)) {
           return;
         }
 
diff --git a/source/fuzz/fuzzer_pass_add_composite_types.cpp b/source/fuzz/fuzzer_pass_add_composite_types.cpp
index af36ad0..bb90991 100644
--- a/source/fuzz/fuzzer_pass_add_composite_types.cpp
+++ b/source/fuzz/fuzzer_pass_add_composite_types.cpp
@@ -114,15 +114,15 @@
   std::vector<uint32_t> candidates;
   for (auto& inst : GetIRContext()->types_values()) {
     switch (inst.opcode()) {
-      case SpvOpTypeArray:
-      case SpvOpTypeBool:
-      case SpvOpTypeFloat:
-      case SpvOpTypeInt:
-      case SpvOpTypeMatrix:
-      case SpvOpTypeVector:
+      case spv::Op::OpTypeArray:
+      case spv::Op::OpTypeBool:
+      case spv::Op::OpTypeFloat:
+      case spv::Op::OpTypeInt:
+      case spv::Op::OpTypeMatrix:
+      case spv::Op::OpTypeVector:
         candidates.push_back(inst.result_id());
         break;
-      case SpvOpTypeStruct: {
+      case spv::Op::OpTypeStruct: {
         if (!fuzzerutil::MembersHaveBuiltInDecoration(GetIRContext(),
                                                       inst.result_id()) &&
             !fuzzerutil::HasBlockOrBufferBlockDecoration(GetIRContext(),
diff --git a/source/fuzz/fuzzer_pass_add_copy_memory.cpp b/source/fuzz/fuzzer_pass_add_copy_memory.cpp
index 6551f49..d54d4ad 100644
--- a/source/fuzz/fuzzer_pass_add_copy_memory.cpp
+++ b/source/fuzz/fuzzer_pass_add_copy_memory.cpp
@@ -36,7 +36,7 @@
              opt::BasicBlock::iterator inst_it,
              const protobufs::InstructionDescriptor& instruction_descriptor) {
         // Check that we can insert an OpCopyMemory before this instruction.
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpCopyMemory,
+        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpCopyMemory,
                                                           inst_it)) {
           return;
         }
@@ -61,8 +61,8 @@
 
         // Decide whether to create global or local variable.
         auto storage_class = GetFuzzerContext()->ChooseEven()
-                                 ? SpvStorageClassPrivate
-                                 : SpvStorageClassFunction;
+                                 ? spv::StorageClass::Private
+                                 : spv::StorageClass::Function;
 
         auto pointee_type_id = fuzzerutil::GetPointeeTypeIdFromPointerType(
             GetIRContext(), inst->type_id());
diff --git a/source/fuzz/fuzzer_pass_add_equation_instructions.cpp b/source/fuzz/fuzzer_pass_add_equation_instructions.cpp
index 4bbded8..e720c4e 100644
--- a/source/fuzz/fuzzer_pass_add_equation_instructions.cpp
+++ b/source/fuzz/fuzzer_pass_add_equation_instructions.cpp
@@ -29,12 +29,14 @@
       return true;
     case 64:
       return ir_context->get_feature_mgr()->HasCapability(
-                 SpvCapabilityFloat64) &&
-             ir_context->get_feature_mgr()->HasCapability(SpvCapabilityInt64);
+                 spv::Capability::Float64) &&
+             ir_context->get_feature_mgr()->HasCapability(
+                 spv::Capability::Int64);
     case 16:
       return ir_context->get_feature_mgr()->HasCapability(
-                 SpvCapabilityFloat16) &&
-             ir_context->get_feature_mgr()->HasCapability(SpvCapabilityInt16);
+                 spv::Capability::Float16) &&
+             ir_context->get_feature_mgr()->HasCapability(
+                 spv::Capability::Int16);
     default:
       return false;
   }
@@ -66,7 +68,8 @@
         // as an example opcode for this check, to be representative of *some*
         // opcode that defines an equation, even though we may choose a
         // different opcode below.
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpIAdd, inst_it)) {
+        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpIAdd,
+                                                          inst_it)) {
           return;
         }
 
@@ -78,7 +81,7 @@
                 [this](opt::IRContext* /*unused*/,
                        opt::Instruction* instruction) -> bool {
                   return instruction->result_id() && instruction->type_id() &&
-                         instruction->opcode() != SpvOpUndef &&
+                         instruction->opcode() != spv::Op::OpUndef &&
                          !GetTransformationContext()
                               ->GetFactManager()
                               ->IdIsIrrelevant(instruction->result_id());
@@ -86,15 +89,16 @@
 
         // Try the opcodes for which we know how to make ids at random until
         // something works.
-        std::vector<SpvOp> candidate_opcodes = {
-            SpvOpIAdd,        SpvOpISub,        SpvOpLogicalNot, SpvOpSNegate,
-            SpvOpConvertUToF, SpvOpConvertSToF, SpvOpBitcast};
+        std::vector<spv::Op> candidate_opcodes = {
+            spv::Op::OpIAdd,    spv::Op::OpISub,        spv::Op::OpLogicalNot,
+            spv::Op::OpSNegate, spv::Op::OpConvertUToF, spv::Op::OpConvertSToF,
+            spv::Op::OpBitcast};
         do {
           auto opcode =
               GetFuzzerContext()->RemoveAtRandomIndex(&candidate_opcodes);
           switch (opcode) {
-            case SpvOpConvertSToF:
-            case SpvOpConvertUToF: {
+            case spv::Op::OpConvertSToF:
+            case spv::Op::OpConvertUToF: {
               std::vector<const opt::Instruction*> candidate_instructions;
               for (const auto* inst :
                    GetIntegerInstructions(available_instructions)) {
@@ -144,7 +148,7 @@
                   {operand->result_id()}, instruction_descriptor));
               return;
             }
-            case SpvOpBitcast: {
+            case spv::Op::OpBitcast: {
               const auto candidate_instructions =
                   GetNumericalInstructions(available_instructions);
 
@@ -197,8 +201,8 @@
                 return;
               }
             } break;
-            case SpvOpIAdd:
-            case SpvOpISub: {
+            case spv::Op::OpIAdd:
+            case spv::Op::OpISub: {
               // Instructions of integer (scalar or vector) result type are
               // suitable for these opcodes.
               auto integer_instructions =
@@ -251,7 +255,7 @@
               }
               break;
             }
-            case SpvOpLogicalNot: {
+            case spv::Op::OpLogicalNot: {
               // Choose any available instruction of boolean scalar/vector
               // result type and equate its negation with a fresh id.
               auto boolean_instructions =
@@ -268,7 +272,7 @@
               }
               break;
             }
-            case SpvOpSNegate: {
+            case spv::Op::OpSNegate: {
               // Similar to OpLogicalNot, but for signed integer negation.
               auto integer_instructions =
                   GetIntegerInstructions(available_instructions);
diff --git a/source/fuzz/fuzzer_pass_add_function_calls.cpp b/source/fuzz/fuzzer_pass_add_function_calls.cpp
index 033f4a2..70b8657 100644
--- a/source/fuzz/fuzzer_pass_add_function_calls.cpp
+++ b/source/fuzz/fuzzer_pass_add_function_calls.cpp
@@ -39,8 +39,8 @@
           -> void {
         // Check whether it is legitimate to insert a function call before the
         // instruction.
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpFunctionCall,
-                                                          inst_it)) {
+        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
+                spv::Op::OpFunctionCall, inst_it)) {
           return;
         }
 
@@ -112,8 +112,8 @@
   auto available_pointers = FindAvailableInstructions(
       caller_function, caller_block, caller_inst_it,
       [this, caller_block](opt::IRContext* /*unused*/, opt::Instruction* inst) {
-        if (inst->opcode() != SpvOpVariable ||
-            inst->opcode() != SpvOpFunctionParameter) {
+        if (inst->opcode() != spv::Op::OpVariable ||
+            inst->opcode() != spv::Op::OpFunctionParameter) {
           // Function parameters and variables are the only
           // kinds of pointer that can be used as actual
           // parameters.
@@ -172,15 +172,15 @@
     auto storage_class = param_type->AsPointer()->storage_class();
     auto pointee_type_id = fuzzerutil::GetPointeeTypeIdFromPointerType(
         GetIRContext(), param->type_id());
-    if (storage_class == SpvStorageClassFunction) {
+    if (storage_class == spv::StorageClass::Function) {
       // Add a new zero-initialized local variable to the current
       // function, noting that its pointee value is irrelevant.
       ApplyTransformation(TransformationAddLocalVariable(
           fresh_variable_id, param->type_id(), caller_function->result_id(),
           FindOrCreateZeroConstant(pointee_type_id, false), true));
     } else {
-      assert((storage_class == SpvStorageClassPrivate ||
-              storage_class == SpvStorageClassWorkgroup) &&
+      assert((storage_class == spv::StorageClass::Private ||
+              storage_class == spv::StorageClass::Workgroup) &&
              "Only Function, Private and Workgroup storage classes are "
              "supported at present.");
       // Add a new global variable to the module, zero-initializing it if
@@ -188,7 +188,7 @@
       // irrelevant.
       ApplyTransformation(TransformationAddGlobalVariable(
           fresh_variable_id, param->type_id(), storage_class,
-          storage_class == SpvStorageClassPrivate
+          storage_class == spv::StorageClass::Private
               ? FindOrCreateZeroConstant(pointee_type_id, false)
               : 0,
           true));
diff --git a/source/fuzz/fuzzer_pass_add_global_variables.cpp b/source/fuzz/fuzzer_pass_add_global_variables.cpp
index 061f44d..4106856 100644
--- a/source/fuzz/fuzzer_pass_add_global_variables.cpp
+++ b/source/fuzz/fuzzer_pass_add_global_variables.cpp
@@ -29,16 +29,17 @@
                  transformations, ignore_inapplicable_transformations) {}
 
 void FuzzerPassAddGlobalVariables::Apply() {
-  SpvStorageClass variable_storage_class = SpvStorageClassPrivate;
+  spv::StorageClass variable_storage_class = spv::StorageClass::Private;
   for (auto& entry_point : GetIRContext()->module()->entry_points()) {
     // If the execution model of some entry point is GLCompute,
     // 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 =
           GetFuzzerContext()->ChoosePercentage(
               GetFuzzerContext()->GetChanceOfChoosingWorkgroupStorageClass())
-              ? SpvStorageClassWorkgroup
-              : SpvStorageClassPrivate;
+              ? spv::StorageClass::Workgroup
+              : spv::StorageClass::Private;
       break;
     }
   }
@@ -87,7 +88,7 @@
     ApplyTransformation(TransformationAddGlobalVariable(
         GetFuzzerContext()->GetFreshId(), pointer_type_id,
         variable_storage_class,
-        variable_storage_class == SpvStorageClassPrivate
+        variable_storage_class == spv::StorageClass::Private
             ? FindOrCreateZeroConstant(basic_type, false)
             : 0,
         true));
diff --git a/source/fuzz/fuzzer_pass_add_loads.cpp b/source/fuzz/fuzzer_pass_add_loads.cpp
index ab91543..3660328 100644
--- a/source/fuzz/fuzzer_pass_add_loads.cpp
+++ b/source/fuzz/fuzzer_pass_add_loads.cpp
@@ -34,10 +34,11 @@
              opt::BasicBlock::iterator inst_it,
              const protobufs::InstructionDescriptor& instruction_descriptor)
           -> void {
-        assert(inst_it->opcode() ==
-                   instruction_descriptor.target_instruction_opcode() &&
-               "The opcode of the instruction we might insert before must be "
-               "the same as the opcode in the descriptor for the instruction");
+        assert(
+            inst_it->opcode() ==
+                spv::Op(instruction_descriptor.target_instruction_opcode()) &&
+            "The opcode of the instruction we might insert before must be "
+            "the same as the opcode in the descriptor for the instruction");
 
         // Randomly decide whether to try inserting a load here.
         if (!GetFuzzerContext()->ChoosePercentage(
@@ -47,10 +48,11 @@
 
         // Check whether it is legitimate to insert a load or atomic load before
         // this instruction.
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpLoad, inst_it)) {
+        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpLoad,
+                                                          inst_it)) {
           return;
         }
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpAtomicLoad,
+        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpAtomicLoad,
                                                           inst_it)) {
           return;
         }
@@ -64,8 +66,8 @@
                     return false;
                   }
                   switch (instruction->opcode()) {
-                    case SpvOpConstantNull:
-                    case SpvOpUndef:
+                    case spv::Op::OpConstantNull:
+                    case spv::Op::OpUndef:
                       // Do not allow loading from a null or undefined pointer;
                       // this might be OK if the block is dead, but for now we
                       // conservatively avoid it.
@@ -75,7 +77,7 @@
                   }
                   return context->get_def_use_mgr()
                              ->GetDef(instruction->type_id())
-                             ->opcode() == SpvOpTypePointer;
+                             ->opcode() == spv::Op::OpTypePointer;
                 });
 
         // At this point, |relevant_instructions| contains all the pointers
@@ -92,25 +94,25 @@
         uint32_t memory_scope_id = 0;
         uint32_t memory_semantics_id = 0;
 
-        auto storage_class = static_cast<SpvStorageClass>(
+        auto storage_class = static_cast<spv::StorageClass>(
             GetIRContext()
                 ->get_def_use_mgr()
                 ->GetDef(chosen_instruction->type_id())
                 ->GetSingleWordInOperand(0));
 
         switch (storage_class) {
-          case SpvStorageClassStorageBuffer:
-          case SpvStorageClassPhysicalStorageBuffer:
-          case SpvStorageClassWorkgroup:
-          case SpvStorageClassCrossWorkgroup:
-          case SpvStorageClassAtomicCounter:
-          case SpvStorageClassImage:
+          case spv::StorageClass::StorageBuffer:
+          case spv::StorageClass::PhysicalStorageBuffer:
+          case spv::StorageClass::Workgroup:
+          case spv::StorageClass::CrossWorkgroup:
+          case spv::StorageClass::AtomicCounter:
+          case spv::StorageClass::Image:
             if (GetFuzzerContext()->ChoosePercentage(
                     GetFuzzerContext()->GetChanceOfAddingAtomicLoad())) {
               is_atomic_load = true;
 
               memory_scope_id = FindOrCreateConstant(
-                  {SpvScopeInvocation},
+                  {uint32_t(spv::Scope::Invocation)},
                   FindOrCreateIntegerType(32, GetFuzzerContext()->ChooseEven()),
                   false);
 
diff --git a/source/fuzz/fuzzer_pass_add_local_variables.cpp b/source/fuzz/fuzzer_pass_add_local_variables.cpp
index a4e739f..f467f46 100644
--- a/source/fuzz/fuzzer_pass_add_local_variables.cpp
+++ b/source/fuzz/fuzzer_pass_add_local_variables.cpp
@@ -31,7 +31,7 @@
 
 void FuzzerPassAddLocalVariables::Apply() {
   auto basic_type_ids_and_pointers =
-      GetAvailableBasicTypesAndPointers(SpvStorageClassFunction);
+      GetAvailableBasicTypesAndPointers(spv::StorageClass::Function);
 
   // These are the basic types that are available to this fuzzer pass.
   auto& basic_types = basic_type_ids_and_pointers.first;
@@ -64,7 +64,7 @@
         // use it.
         pointer_type = GetFuzzerContext()->GetFreshId();
         ApplyTransformation(TransformationAddTypePointer(
-            pointer_type, SpvStorageClassFunction, basic_type));
+            pointer_type, spv::StorageClass::Function, basic_type));
         available_pointers_to_basic_type.push_back(pointer_type);
       } else {
         // There is - grab one.
diff --git a/source/fuzz/fuzzer_pass_add_opphi_synonyms.cpp b/source/fuzz/fuzzer_pass_add_opphi_synonyms.cpp
index 73b6b0a..d0b1275 100644
--- a/source/fuzz/fuzzer_pass_add_opphi_synonyms.cpp
+++ b/source/fuzz/fuzzer_pass_add_opphi_synonyms.cpp
@@ -176,8 +176,8 @@
     // - OpFunction does not yield a value;
     // - OpUndef yields an undefined value at each use, so it should never be a
     //   synonym of another id.
-    if (pair.second->opcode() == SpvOpFunction ||
-        pair.second->opcode() == SpvOpUndef) {
+    if (pair.second->opcode() == spv::Op::OpFunction ||
+        pair.second->opcode() == spv::Op::OpUndef) {
       continue;
     }
 
diff --git a/source/fuzz/fuzzer_pass_add_parameters.cpp b/source/fuzz/fuzzer_pass_add_parameters.cpp
index 1cb6a79..e663d89 100644
--- a/source/fuzz/fuzzer_pass_add_parameters.cpp
+++ b/source/fuzz/fuzzer_pass_add_parameters.cpp
@@ -79,7 +79,7 @@
         auto storage_class = fuzzerutil::GetStorageClassFromPointerType(
             GetIRContext(), current_type_id);
         switch (storage_class) {
-          case SpvStorageClassFunction: {
+          case spv::StorageClass::Function: {
             // In every caller find or create a local variable that has the
             // selected type.
             for (auto* instr :
@@ -91,8 +91,8 @@
               call_parameter_ids[instr->result_id()] = variable_id;
             }
           } break;
-          case SpvStorageClassPrivate:
-          case SpvStorageClassWorkgroup: {
+          case spv::StorageClass::Private:
+          case spv::StorageClass::Workgroup: {
             // If there exists at least one caller, find or create a global
             // variable that has the selected type.
             std::vector<opt::Instruction*> callers =
diff --git a/source/fuzz/fuzzer_pass_add_stores.cpp b/source/fuzz/fuzzer_pass_add_stores.cpp
index 606e4a6..0de02a5 100644
--- a/source/fuzz/fuzzer_pass_add_stores.cpp
+++ b/source/fuzz/fuzzer_pass_add_stores.cpp
@@ -34,10 +34,11 @@
              opt::BasicBlock::iterator inst_it,
              const protobufs::InstructionDescriptor& instruction_descriptor)
           -> void {
-        assert(inst_it->opcode() ==
-                   instruction_descriptor.target_instruction_opcode() &&
-               "The opcode of the instruction we might insert before must be "
-               "the same as the opcode in the descriptor for the instruction");
+        assert(
+            inst_it->opcode() ==
+                spv::Op(instruction_descriptor.target_instruction_opcode()) &&
+            "The opcode of the instruction we might insert before must be "
+            "the same as the opcode in the descriptor for the instruction");
 
         // Randomly decide whether to try inserting a store here.
         if (!GetFuzzerContext()->ChoosePercentage(
@@ -47,12 +48,12 @@
 
         // Check whether it is legitimate to insert a store before this
         // instruction.
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpStore,
+        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpStore,
                                                           inst_it)) {
           return;
         }
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpAtomicStore,
-                                                          inst_it)) {
+        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
+                spv::Op::OpAtomicStore, inst_it)) {
           return;
         }
 
@@ -67,7 +68,7 @@
                   }
                   auto type_inst = context->get_def_use_mgr()->GetDef(
                       instruction->type_id());
-                  if (type_inst->opcode() != SpvOpTypePointer) {
+                  if (type_inst->opcode() != spv::Op::OpTypePointer) {
                     // Not a pointer.
                     return false;
                   }
@@ -76,8 +77,8 @@
                     return false;
                   }
                   switch (instruction->opcode()) {
-                    case SpvOpConstantNull:
-                    case SpvOpUndef:
+                    case spv::Op::OpConstantNull:
+                    case spv::Op::OpUndef:
                       // Do not allow storing to a null or undefined pointer;
                       // this might be OK if the block is dead, but for now we
                       // conservatively avoid it.
@@ -126,24 +127,24 @@
         uint32_t memory_semantics_id = 0;
 
         auto storage_class =
-            static_cast<SpvStorageClass>(GetIRContext()
-                                             ->get_def_use_mgr()
-                                             ->GetDef(pointer->type_id())
-                                             ->GetSingleWordInOperand(0));
+            static_cast<spv::StorageClass>(GetIRContext()
+                                               ->get_def_use_mgr()
+                                               ->GetDef(pointer->type_id())
+                                               ->GetSingleWordInOperand(0));
 
         switch (storage_class) {
-          case SpvStorageClassStorageBuffer:
-          case SpvStorageClassPhysicalStorageBuffer:
-          case SpvStorageClassWorkgroup:
-          case SpvStorageClassCrossWorkgroup:
-          case SpvStorageClassAtomicCounter:
-          case SpvStorageClassImage:
+          case spv::StorageClass::StorageBuffer:
+          case spv::StorageClass::PhysicalStorageBuffer:
+          case spv::StorageClass::Workgroup:
+          case spv::StorageClass::CrossWorkgroup:
+          case spv::StorageClass::AtomicCounter:
+          case spv::StorageClass::Image:
             if (GetFuzzerContext()->ChoosePercentage(
                     GetFuzzerContext()->GetChanceOfAddingAtomicStore())) {
               is_atomic_store = true;
 
               memory_scope_id = FindOrCreateConstant(
-                  {SpvScopeInvocation},
+                  {uint32_t(spv::Scope::Invocation)},
                   FindOrCreateIntegerType(32, GetFuzzerContext()->ChooseEven()),
                   false);
 
diff --git a/source/fuzz/fuzzer_pass_add_synonyms.cpp b/source/fuzz/fuzzer_pass_add_synonyms.cpp
index 1d188de..5782732 100644
--- a/source/fuzz/fuzzer_pass_add_synonyms.cpp
+++ b/source/fuzz/fuzzer_pass_add_synonyms.cpp
@@ -44,7 +44,8 @@
         // 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
         // transformation.
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpIAdd, inst_it)) {
+        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpIAdd,
+                                                          inst_it)) {
           return;
         }
 
diff --git a/source/fuzz/fuzzer_pass_add_vector_shuffle_instructions.cpp b/source/fuzz/fuzzer_pass_add_vector_shuffle_instructions.cpp
index a29d1d3..4cddf55 100644
--- a/source/fuzz/fuzzer_pass_add_vector_shuffle_instructions.cpp
+++ b/source/fuzz/fuzzer_pass_add_vector_shuffle_instructions.cpp
@@ -35,10 +35,11 @@
              opt::BasicBlock::iterator instruction_iterator,
              const protobufs::InstructionDescriptor& instruction_descriptor)
           -> void {
-        assert(instruction_iterator->opcode() ==
-                   instruction_descriptor.target_instruction_opcode() &&
-               "The opcode of the instruction we might insert before must be "
-               "the same as the opcode in the descriptor for the instruction");
+        assert(
+            instruction_iterator->opcode() ==
+                spv::Op(instruction_descriptor.target_instruction_opcode()) &&
+            "The opcode of the instruction we might insert before must be "
+            "the same as the opcode in the descriptor for the instruction");
 
         // Randomly decide whether to try adding an OpVectorShuffle instruction.
         if (!GetFuzzerContext()->ChoosePercentage(
@@ -49,7 +50,7 @@
         // It must be valid to insert an OpVectorShuffle instruction
         // before |instruction_iterator|.
         if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
-                SpvOpVectorShuffle, instruction_iterator)) {
+                spv::Op::OpVectorShuffle, instruction_iterator)) {
           return;
         }
 
diff --git a/source/fuzz/fuzzer_pass_adjust_branch_weights.cpp b/source/fuzz/fuzzer_pass_adjust_branch_weights.cpp
index 94428f7..6bf46e1 100644
--- a/source/fuzz/fuzzer_pass_adjust_branch_weights.cpp
+++ b/source/fuzz/fuzzer_pass_adjust_branch_weights.cpp
@@ -33,7 +33,7 @@
   // For all OpBranchConditional instructions,
   // randomly applies the transformation.
   GetIRContext()->module()->ForEachInst([this](opt::Instruction* instruction) {
-    if (instruction->opcode() == SpvOpBranchConditional &&
+    if (instruction->opcode() == spv::Op::OpBranchConditional &&
         GetFuzzerContext()->ChoosePercentage(
             GetFuzzerContext()->GetChanceOfAdjustingBranchWeights())) {
       ApplyTransformation(TransformationAdjustBranchWeights(
diff --git a/source/fuzz/fuzzer_pass_adjust_function_controls.cpp b/source/fuzz/fuzzer_pass_adjust_function_controls.cpp
index 1c2bc8c..363edc7 100644
--- a/source/fuzz/fuzzer_pass_adjust_function_controls.cpp
+++ b/source/fuzz/fuzzer_pass_adjust_function_controls.cpp
@@ -40,21 +40,21 @@
       // For the new mask, we first randomly select one of three basic masks:
       // None, Inline or DontInline.  These are always valid (and are mutually
       // exclusive).
-      std::vector<uint32_t> basic_function_control_masks = {
-          SpvFunctionControlMaskNone, SpvFunctionControlInlineMask,
-          SpvFunctionControlDontInlineMask};
+      std::vector<spv::FunctionControlMask> basic_function_control_masks = {
+          spv::FunctionControlMask::MaskNone, spv::FunctionControlMask::Inline,
+          spv::FunctionControlMask::DontInline};
       uint32_t new_function_control_mask =
-          basic_function_control_masks[GetFuzzerContext()->RandomIndex(
-              basic_function_control_masks)];
+          uint32_t(basic_function_control_masks[GetFuzzerContext()->RandomIndex(
+              basic_function_control_masks)]);
 
       // 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
       // to consider dropping them, so we decide randomly in each case.
       for (auto mask_bit :
-           {SpvFunctionControlPureMask, SpvFunctionControlConstMask}) {
-        if ((existing_function_control_mask & mask_bit) &&
+           {spv::FunctionControlMask::Pure, spv::FunctionControlMask::Const}) {
+        if ((existing_function_control_mask & uint32_t(mask_bit)) &&
             GetFuzzerContext()->ChooseEven()) {
-          new_function_control_mask |= mask_bit;
+          new_function_control_mask |= uint32_t(mask_bit);
         }
       }
 
diff --git a/source/fuzz/fuzzer_pass_adjust_loop_controls.cpp b/source/fuzz/fuzzer_pass_adjust_loop_controls.cpp
index fe855ca..53dbe54 100644
--- a/source/fuzz/fuzzer_pass_adjust_loop_controls.cpp
+++ b/source/fuzz/fuzzer_pass_adjust_loop_controls.cpp
@@ -34,7 +34,7 @@
     for (auto& block : function) {
       if (auto merge_inst = block.GetMergeInst()) {
         // Ignore the instruction if it is not a loop merge.
-        if (merge_inst->opcode() != SpvOpLoopMerge) {
+        if (merge_inst->opcode() != spv::Op::OpLoopMerge) {
           continue;
         }
 
@@ -48,9 +48,10 @@
             TransformationSetLoopControl::kLoopControlMaskInOperandIndex);
 
         // First, set the new mask to one of None, Unroll or DontUnroll.
-        std::vector<uint32_t> basic_masks = {SpvLoopControlMaskNone,
-                                             SpvLoopControlUnrollMask,
-                                             SpvLoopControlDontUnrollMask};
+        std::vector<uint32_t> basic_masks = {
+            uint32_t(spv::LoopControlMask::MaskNone),
+            uint32_t(spv::LoopControlMask::Unroll),
+            uint32_t(spv::LoopControlMask::DontUnroll)};
         uint32_t new_mask =
             basic_masks[GetFuzzerContext()->RandomIndex(basic_masks)];
 
@@ -58,19 +59,20 @@
         // does, check which of these were present in the existing mask and
         // randomly decide whether to keep them.  They are just hints, so
         // removing them should not change the semantics of the module.
-        for (auto mask_bit :
-             {SpvLoopControlDependencyInfiniteMask,
-              SpvLoopControlDependencyLengthMask,
-              SpvLoopControlMinIterationsMask, SpvLoopControlMaxIterationsMask,
-              SpvLoopControlIterationMultipleMask}) {
-          if ((existing_mask & mask_bit) && GetFuzzerContext()->ChooseEven()) {
+        for (auto mask_bit : {spv::LoopControlMask::DependencyInfinite,
+                              spv::LoopControlMask::DependencyLength,
+                              spv::LoopControlMask::MinIterations,
+                              spv::LoopControlMask::MaxIterations,
+                              spv::LoopControlMask::IterationMultiple}) {
+          if ((existing_mask & uint32_t(mask_bit)) &&
+              GetFuzzerContext()->ChooseEven()) {
             // 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
             // in the original loop control mask, and we work under the
             // assumption that we are transforming a valid module, thus we don't
             // need to actually check whether the SPIR-V version being used
             // supports these loop control mask bits.
-            new_mask |= mask_bit;
+            new_mask |= uint32_t(mask_bit);
           }
         }
 
@@ -81,14 +83,14 @@
 
         // PeelCount and PartialCount are not compatible with DontUnroll, so
         // 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
           // whether to set it.  If it was set in the original mask and is not
           // selected for setting here, that amounts to dropping it.
           if (TransformationSetLoopControl::PeelCountIsSupported(
                   GetIRContext()) &&
               GetFuzzerContext()->ChooseEven()) {
-            new_mask |= SpvLoopControlPeelCountMask;
+            new_mask |= uint32_t(spv::LoopControlMask::PeelCount);
             // The peel count is chosen randomly - if PeelCount was already set
             // this will overwrite whatever peel count was previously used.
             peel_count = GetFuzzerContext()->GetRandomLoopControlPeelCount();
@@ -97,7 +99,7 @@
           if (TransformationSetLoopControl::PartialCountIsSupported(
                   GetIRContext()) &&
               GetFuzzerContext()->ChooseEven()) {
-            new_mask |= SpvLoopControlPartialCountMask;
+            new_mask |= uint32_t(spv::LoopControlMask::PartialCount);
             partial_count =
                 GetFuzzerContext()->GetRandomLoopControlPartialCount();
           }
diff --git a/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.cpp b/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.cpp
index d2ff40e..efae7d6 100644
--- a/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.cpp
+++ b/source/fuzz/fuzzer_pass_adjust_memory_operands_masks.cpp
@@ -47,8 +47,8 @@
         // From SPIR-V 1.4 onwards, OpCopyMemory and OpCopyMemorySized have a
         // second mask.
         switch (inst_it->opcode()) {
-          case SpvOpCopyMemory:
-          case SpvOpCopyMemorySized:
+          case spv::Op::OpCopyMemory:
+          case spv::Op::OpCopyMemorySized:
             if (TransformationSetMemoryOperandsMask::
                     MultipleMemoryOperandMasksAreSupported(GetIRContext())) {
               indices_of_available_masks_to_adjust.push_back(1);
@@ -75,24 +75,26 @@
               existing_mask_in_operand_index < inst_it->NumInOperands()
                   ? inst_it->GetSingleWordInOperand(
                         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:
           // - add Volatile if not already present
           // - toggle Nontemporal
           // The following ensures that we do at least one of these
-          bool add_volatile = !(existing_mask & SpvMemoryAccessVolatileMask) &&
-                              GetFuzzerContext()->ChooseEven();
+          bool add_volatile =
+              !(existing_mask & uint32_t(spv::MemoryAccessMask::Volatile)) &&
+              GetFuzzerContext()->ChooseEven();
           bool toggle_nontemporal =
               !add_volatile || GetFuzzerContext()->ChooseEven();
 
           // These bitwise operations use '|' to add Volatile if desired, and
           // '^' to toggle Nontemporal if desired.
           uint32_t new_mask =
-              (existing_mask | (add_volatile ? SpvMemoryAccessVolatileMask
-                                             : SpvMemoryAccessMaskNone)) ^
-              (toggle_nontemporal ? SpvMemoryAccessNontemporalMask
-                                  : SpvMemoryAccessMaskNone);
+              (existing_mask |
+               (add_volatile ? uint32_t(spv::MemoryAccessMask::Volatile)
+                             : uint32_t(spv::MemoryAccessMask::MaskNone))) ^
+              (toggle_nontemporal ? uint32_t(spv::MemoryAccessMask::Nontemporal)
+                                  : uint32_t(spv::MemoryAccessMask::MaskNone));
 
           TransformationSetMemoryOperandsMask transformation(
               MakeInstructionDescriptor(block, inst_it), new_mask, mask_index);
diff --git a/source/fuzz/fuzzer_pass_adjust_selection_controls.cpp b/source/fuzz/fuzzer_pass_adjust_selection_controls.cpp
index 7d8e6b5..fe0cf7a 100644
--- a/source/fuzz/fuzzer_pass_adjust_selection_controls.cpp
+++ b/source/fuzz/fuzzer_pass_adjust_selection_controls.cpp
@@ -34,7 +34,7 @@
     for (auto& block : function) {
       if (auto merge_inst = block.GetMergeInst()) {
         // Ignore the instruction if it is not a selection merge.
-        if (merge_inst->opcode() != SpvOpSelectionMerge) {
+        if (merge_inst->opcode() != spv::Op::OpSelectionMerge) {
           continue;
         }
 
@@ -48,13 +48,14 @@
         // The choices to change the selection control to are the set of valid
         // controls, minus the current control.
         std::vector<uint32_t> choices;
-        for (auto control :
-             {SpvSelectionControlMaskNone, SpvSelectionControlFlattenMask,
-              SpvSelectionControlDontFlattenMask}) {
-          if (control == merge_inst->GetSingleWordOperand(1)) {
+        for (auto control : {spv::SelectionControlMask::MaskNone,
+                             spv::SelectionControlMask::Flatten,
+                             spv::SelectionControlMask::DontFlatten}) {
+          if (control ==
+              spv::SelectionControlMask(merge_inst->GetSingleWordOperand(1))) {
             continue;
           }
-          choices.push_back(control);
+          choices.push_back(uint32_t(control));
         }
 
         // Apply the transformation and add it to the output transformation
diff --git a/source/fuzz/fuzzer_pass_apply_id_synonyms.cpp b/source/fuzz/fuzzer_pass_apply_id_synonyms.cpp
index 5c3b86b..0367a26 100644
--- a/source/fuzz/fuzzer_pass_apply_id_synonyms.cpp
+++ b/source/fuzz/fuzzer_pass_apply_id_synonyms.cpp
@@ -107,9 +107,9 @@
         // which case we need to be able to add an extract instruction to get
         // that element out.
         if (synonym_to_try->index_size() > 0 &&
-            !fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpCompositeExtract,
-                                                          use_inst) &&
-            use_inst->opcode() != SpvOpPhi) {
+            !fuzzerutil::CanInsertOpcodeBeforeInstruction(
+                spv::Op::OpCompositeExtract, use_inst) &&
+            use_inst->opcode() != spv::Op::OpPhi) {
           // We cannot insert an extract before this instruction, so this
           // synonym is no good.
           continue;
@@ -132,7 +132,7 @@
           id_with_which_to_replace_use = GetFuzzerContext()->GetFreshId();
           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;
           } else {
             auto parent_block_id =
@@ -182,7 +182,7 @@
 }
 
 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& dd2) {
   auto base_object_type_id_1 =
diff --git a/source/fuzz/fuzzer_pass_apply_id_synonyms.h b/source/fuzz/fuzzer_pass_apply_id_synonyms.h
index 3da9c5d..d1a0e1a 100644
--- a/source/fuzz/fuzzer_pass_apply_id_synonyms.h
+++ b/source/fuzz/fuzzer_pass_apply_id_synonyms.h
@@ -38,7 +38,7 @@
   // 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
   // type of integral components with possibly different signedness.
-  bool DataDescriptorsHaveCompatibleTypes(SpvOp opcode,
+  bool DataDescriptorsHaveCompatibleTypes(spv::Op opcode,
                                           uint32_t use_in_operand_index,
                                           const protobufs::DataDescriptor& dd1,
                                           const protobufs::DataDescriptor& dd2);
diff --git a/source/fuzz/fuzzer_pass_construct_composites.cpp b/source/fuzz/fuzzer_pass_construct_composites.cpp
index ff022fc..0ad630c 100644
--- a/source/fuzz/fuzzer_pass_construct_composites.cpp
+++ b/source/fuzz/fuzzer_pass_construct_composites.cpp
@@ -81,7 +81,7 @@
         // Check whether it is legitimate to insert a composite construction
         // before the instruction.
         if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
-                SpvOpCompositeConstruct, inst_it)) {
+                spv::Op::OpCompositeConstruct, inst_it)) {
           return;
         }
 
@@ -121,19 +121,19 @@
         auto composite_type_inst =
             GetIRContext()->get_def_use_mgr()->GetDef(chosen_composite_type);
         switch (composite_type_inst->opcode()) {
-          case SpvOpTypeArray:
+          case spv::Op::OpTypeArray:
             constructor_arguments = FindComponentsToConstructArray(
                 *composite_type_inst, type_id_to_available_instructions);
             break;
-          case SpvOpTypeMatrix:
+          case spv::Op::OpTypeMatrix:
             constructor_arguments = FindComponentsToConstructMatrix(
                 *composite_type_inst, type_id_to_available_instructions);
             break;
-          case SpvOpTypeStruct:
+          case spv::Op::OpTypeStruct:
             constructor_arguments = FindComponentsToConstructStruct(
                 *composite_type_inst, type_id_to_available_instructions);
             break;
-          case SpvOpTypeVector:
+          case spv::Op::OpTypeVector:
             constructor_arguments = FindComponentsToConstructVector(
                 *composite_type_inst, type_id_to_available_instructions);
             break;
@@ -156,7 +156,7 @@
 FuzzerPassConstructComposites::FindComponentsToConstructArray(
     const opt::Instruction& array_type_instruction,
     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.");
 
   // Get the element type for the array.
@@ -191,7 +191,7 @@
 FuzzerPassConstructComposites::FindComponentsToConstructMatrix(
     const opt::Instruction& matrix_type_instruction,
     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.");
 
   // Get the element type for the matrix.
@@ -221,7 +221,7 @@
 FuzzerPassConstructComposites::FindComponentsToConstructStruct(
     const opt::Instruction& struct_type_instruction,
     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.");
   std::vector<uint32_t> result;
   // Consider the type of each field of the struct.
@@ -251,7 +251,7 @@
 FuzzerPassConstructComposites::FindComponentsToConstructVector(
     const opt::Instruction& vector_type_instruction,
     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.");
 
   // Get details of the type underlying the vector, and the width of the vector,
diff --git a/source/fuzz/fuzzer_pass_copy_objects.cpp b/source/fuzz/fuzzer_pass_copy_objects.cpp
index 80cc2a5..725c33e 100644
--- a/source/fuzz/fuzzer_pass_copy_objects.cpp
+++ b/source/fuzz/fuzzer_pass_copy_objects.cpp
@@ -35,10 +35,11 @@
              opt::BasicBlock::iterator inst_it,
              const protobufs::InstructionDescriptor& instruction_descriptor)
           -> void {
-        assert(inst_it->opcode() ==
-                   instruction_descriptor.target_instruction_opcode() &&
-               "The opcode of the instruction we might insert before must be "
-               "the same as the opcode in the descriptor for the instruction");
+        assert(
+            inst_it->opcode() ==
+                spv::Op(instruction_descriptor.target_instruction_opcode()) &&
+            "The opcode of the instruction we might insert before must be "
+            "the same as the opcode in the descriptor for the instruction");
 
         if (GetTransformationContext()->GetFactManager()->BlockIsDead(
                 block->id())) {
@@ -48,7 +49,7 @@
 
         // Check whether it is legitimate to insert a copy before this
         // instruction.
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpCopyObject,
+        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpCopyObject,
                                                           inst_it)) {
           return;
         }
diff --git a/source/fuzz/fuzzer_pass_donate_modules.cpp b/source/fuzz/fuzzer_pass_donate_modules.cpp
index 29ede58..1696c74 100644
--- a/source/fuzz/fuzzer_pass_donate_modules.cpp
+++ b/source/fuzz/fuzzer_pass_donate_modules.cpp
@@ -88,7 +88,7 @@
   // module.
   for (const auto& capability_inst : donor_ir_context->capabilities()) {
     auto capability =
-        static_cast<SpvCapability>(capability_inst.GetSingleWordInOperand(0));
+        static_cast<spv::Capability>(capability_inst.GetSingleWordInOperand(0));
     if (!GetIRContext()->get_feature_mgr()->HasCapability(capability)) {
       return;
     }
@@ -122,27 +122,27 @@
   //  kinds of decoration.
 }
 
-SpvStorageClass FuzzerPassDonateModules::AdaptStorageClass(
-    SpvStorageClass donor_storage_class) {
+spv::StorageClass FuzzerPassDonateModules::AdaptStorageClass(
+    spv::StorageClass donor_storage_class) {
   switch (donor_storage_class) {
-    case SpvStorageClassFunction:
-    case SpvStorageClassPrivate:
-    case SpvStorageClassWorkgroup:
+    case spv::StorageClass::Function:
+    case spv::StorageClass::Private:
+    case spv::StorageClass::Workgroup:
       // We leave these alone
       return donor_storage_class;
-    case SpvStorageClassInput:
-    case SpvStorageClassOutput:
-    case SpvStorageClassUniform:
-    case SpvStorageClassUniformConstant:
-    case SpvStorageClassPushConstant:
-    case SpvStorageClassImage:
-    case SpvStorageClassStorageBuffer:
+    case spv::StorageClass::Input:
+    case spv::StorageClass::Output:
+    case spv::StorageClass::Uniform:
+    case spv::StorageClass::UniformConstant:
+    case spv::StorageClass::PushConstant:
+    case spv::StorageClass::Image:
+    case spv::StorageClass::StorageBuffer:
       // We change these to Private
-      return SpvStorageClassPrivate;
+      return spv::StorageClass::Private;
     default:
       // Handle other cases on demand.
       assert(false && "Currently unsupported storage class.");
-      return SpvStorageClassMax;
+      return spv::StorageClass::Max;
   }
 }
 
@@ -200,14 +200,14 @@
   // that its component types will have been considered previously, and that
   // |original_id_to_donated_id| will already contain an entry for them.
   switch (type_or_value.opcode()) {
-    case SpvOpTypeImage:
-    case SpvOpTypeSampledImage:
-    case SpvOpTypeSampler:
+    case spv::Op::OpTypeImage:
+    case spv::Op::OpTypeSampledImage:
+    case spv::Op::OpTypeSampler:
       // We do not donate types and variables that relate to images and
       // samplers, so we skip these types and subsequently skip anything that
       // depends on them.
       return;
-    case SpvOpTypeVoid: {
+    case spv::Op::OpTypeVoid: {
       // Void has to exist already in order for us to have an entry point.
       // Get the existing id of void.
       opt::analysis::Void void_type;
@@ -216,7 +216,7 @@
              "The module being transformed will always have 'void' type "
              "declared.");
     } break;
-    case SpvOpTypeBool: {
+    case spv::Op::OpTypeBool: {
       // 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.
       opt::analysis::Bool bool_type;
@@ -228,7 +228,7 @@
         ApplyTransformation(TransformationAddTypeBoolean(new_result_id));
       }
     } break;
-    case SpvOpTypeInt: {
+    case spv::Op::OpTypeInt: {
       // Int cannot be declared multiple times with the same width and
       // signedness, so check whether an existing identical Int type is
       // present and use its id if so.  Otherwise add a declaration of the
@@ -246,8 +246,8 @@
             TransformationAddTypeInt(new_result_id, width, is_signed));
       }
     } break;
-    case SpvOpTypeFloat: {
-      // Similar to SpvOpTypeInt.
+    case spv::Op::OpTypeFloat: {
+      // Similar to spv::Op::OpTypeInt.
       const uint32_t width = type_or_value.GetSingleWordInOperand(0);
       opt::analysis::Float float_type(width);
       auto float_type_id = GetIRContext()->get_type_mgr()->GetId(&float_type);
@@ -258,7 +258,7 @@
         ApplyTransformation(TransformationAddTypeFloat(new_result_id, width));
       }
     } break;
-    case SpvOpTypeVector: {
+    case spv::Op::OpTypeVector: {
       // It is not legal to have two Vector type declarations with identical
       // element types and element counts, so check whether an existing
       // identical Vector type is present and use its id if so.  Otherwise add
@@ -282,8 +282,8 @@
             new_result_id, component_type_id, component_count));
       }
     } break;
-    case SpvOpTypeMatrix: {
-      // Similar to SpvOpTypeVector.
+    case spv::Op::OpTypeMatrix: {
+      // Similar to spv::Op::OpTypeVector.
       uint32_t column_type_id = original_id_to_donated_id->at(
           type_or_value.GetSingleWordInOperand(0));
       auto column_type =
@@ -302,7 +302,7 @@
       }
 
     } break;
-    case SpvOpTypeArray: {
+    case spv::Op::OpTypeArray: {
       // 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
       // donor.
@@ -318,7 +318,7 @@
           original_id_to_donated_id->at(
               type_or_value.GetSingleWordInOperand(1))));
     } break;
-    case SpvOpTypeRuntimeArray: {
+    case spv::Op::OpTypeRuntimeArray: {
       // A runtime array is allowed as the final member of an SSBO.  During
       // donation we turn runtime arrays into fixed-size arrays.  For dead
       // code donations this is OK because the array is never indexed into at
@@ -341,8 +341,8 @@
               {GetFuzzerContext()->GetRandomSizeForNewArray()}, 32, false,
               false)));
     } break;
-    case SpvOpTypeStruct: {
-      // Similar to SpvOpTypeArray.
+    case spv::Op::OpTypeStruct: {
+      // Similar to spv::Op::OpTypeArray.
       std::vector<uint32_t> member_type_ids;
       for (uint32_t i = 0; i < type_or_value.NumInOperands(); i++) {
         auto component_type_id = type_or_value.GetSingleWordInOperand(i);
@@ -358,8 +358,8 @@
       ApplyTransformation(
           TransformationAddTypeStruct(new_result_id, member_type_ids));
     } break;
-    case SpvOpTypePointer: {
-      // Similar to SpvOpTypeArray.
+    case spv::Op::OpTypePointer: {
+      // Similar to spv::Op::OpTypeArray.
       uint32_t pointee_type_id = type_or_value.GetSingleWordInOperand(1);
       if (!original_id_to_donated_id->count(pointee_type_id)) {
         // We did not donate the pointee type for this pointer type, so we
@@ -369,11 +369,11 @@
       new_result_id = GetFuzzerContext()->GetFreshId();
       ApplyTransformation(TransformationAddTypePointer(
           new_result_id,
-          AdaptStorageClass(static_cast<SpvStorageClass>(
+          AdaptStorageClass(static_cast<spv::StorageClass>(
               type_or_value.GetSingleWordInOperand(0))),
           original_id_to_donated_id->at(pointee_type_id)));
     } break;
-    case SpvOpTypeFunction: {
+    case spv::Op::OpTypeFunction: {
       // It is not OK to have multiple function types that use identical ids
       // for their return and parameter types.  We thus go through all
       // existing function types to look for a match.  We do not use the
@@ -425,10 +425,11 @@
             argument_type_ids));
       }
     } break;
-    case SpvOpSpecConstantOp: {
+    case spv::Op::OpSpecConstantOp: {
       new_result_id = GetFuzzerContext()->GetFreshId();
       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
       // computing operands for OpSpecConstantOp.
@@ -447,20 +448,20 @@
       ApplyTransformation(TransformationAddSpecConstantOp(
           new_result_id, type_id, opcode, std::move(operands)));
     } break;
-    case SpvOpSpecConstantTrue:
-    case SpvOpSpecConstantFalse:
-    case SpvOpConstantTrue:
-    case SpvOpConstantFalse: {
+    case spv::Op::OpSpecConstantTrue:
+    case spv::Op::OpSpecConstantFalse:
+    case spv::Op::OpConstantTrue:
+    case spv::Op::OpConstantFalse: {
       // It is OK to have duplicate definitions of True and False, so add
       // these to the module, using a remapped Bool type.
       new_result_id = GetFuzzerContext()->GetFreshId();
-      auto value = type_or_value.opcode() == SpvOpConstantTrue ||
-                   type_or_value.opcode() == SpvOpSpecConstantTrue;
+      auto value = type_or_value.opcode() == spv::Op::OpConstantTrue ||
+                   type_or_value.opcode() == spv::Op::OpSpecConstantTrue;
       ApplyTransformation(
           TransformationAddConstantBoolean(new_result_id, value, false));
     } break;
-    case SpvOpSpecConstant:
-    case SpvOpConstant: {
+    case spv::Op::OpSpecConstant:
+    case spv::Op::OpConstant: {
       // It is OK to have duplicate constant definitions, so add this to the
       // module using a remapped result type.
       new_result_id = GetFuzzerContext()->GetFreshId();
@@ -472,8 +473,8 @@
           new_result_id, original_id_to_donated_id->at(type_or_value.type_id()),
           data_words, false));
     } break;
-    case SpvOpSpecConstantComposite:
-    case SpvOpConstantComposite: {
+    case spv::Op::OpSpecConstantComposite:
+    case spv::Op::OpConstantComposite: {
       assert(original_id_to_donated_id->count(type_or_value.type_id()) &&
              "Composite types for which it is possible to create a constant "
              "should have been donated.");
@@ -495,7 +496,7 @@
           new_result_id, original_id_to_donated_id->at(type_or_value.type_id()),
           constituent_ids, false));
     } break;
-    case SpvOpConstantNull: {
+    case spv::Op::OpConstantNull: {
       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 cannot donate the null constant.
@@ -509,7 +510,7 @@
           new_result_id,
           original_id_to_donated_id->at(type_or_value.type_id())));
     } break;
-    case SpvOpVariable: {
+    case spv::Op::OpVariable: {
       if (!original_id_to_donated_id->count(type_or_value.type_id())) {
         // We did not donate the pointer type associated with this variable,
         // so we cannot donate the variable.
@@ -536,11 +537,11 @@
       uint32_t remapped_pointer_type =
           original_id_to_donated_id->at(type_or_value.type_id());
       uint32_t initializer_id;
-      SpvStorageClass storage_class =
-          static_cast<SpvStorageClass>(type_or_value.GetSingleWordInOperand(
-              0)) == SpvStorageClassWorkgroup
-              ? SpvStorageClassWorkgroup
-              : SpvStorageClassPrivate;
+      spv::StorageClass storage_class =
+          static_cast<spv::StorageClass>(type_or_value.GetSingleWordInOperand(
+              0)) == spv::StorageClass::Workgroup
+              ? spv::StorageClass::Workgroup
+              : spv::StorageClass::Private;
       if (type_or_value.NumInOperands() == 1) {
         // The variable did not have an initializer.  Initialize it to zero
         // if it has Private storage class (to limit problems associated with
@@ -551,7 +552,7 @@
         //  could initialize Workgroup variables at the start of an entry
         //  point, and should do so if their uninitialized nature proves
         //  problematic.
-        initializer_id = storage_class == SpvStorageClassWorkgroup
+        initializer_id = storage_class == spv::StorageClass::Workgroup
                              ? 0
                              : FindOrCreateZeroConstant(
                                    fuzzerutil::GetPointeeTypeIdFromPointerType(
@@ -566,7 +567,7 @@
           TransformationAddGlobalVariable(new_result_id, remapped_pointer_type,
                                           storage_class, initializer_id, true));
     } break;
-    case SpvOpUndef: {
+    case spv::Op::OpUndef: {
       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
         // donate the undef.
@@ -638,7 +639,7 @@
         [this, &donated_instructions, donor_ir_context,
          &original_id_to_donated_id,
          &skipped_instructions](const opt::Instruction* instruction) {
-          if (instruction->opcode() == SpvOpArrayLength) {
+          if (instruction->opcode() == spv::Op::OpArrayLength) {
             // We treat OpArrayLength specially.
             HandleOpArrayLength(*instruction, original_id_to_donated_id,
                                 &donated_instructions);
@@ -682,70 +683,70 @@
   // Now consider instructions we specifically want to skip because we do not
   // yet support them.
   switch (instruction.opcode()) {
-    case SpvOpAtomicLoad:
-    case SpvOpAtomicStore:
-    case SpvOpAtomicExchange:
-    case SpvOpAtomicCompareExchange:
-    case SpvOpAtomicCompareExchangeWeak:
-    case SpvOpAtomicIIncrement:
-    case SpvOpAtomicIDecrement:
-    case SpvOpAtomicIAdd:
-    case SpvOpAtomicISub:
-    case SpvOpAtomicSMin:
-    case SpvOpAtomicUMin:
-    case SpvOpAtomicSMax:
-    case SpvOpAtomicUMax:
-    case SpvOpAtomicAnd:
-    case SpvOpAtomicOr:
-    case SpvOpAtomicXor:
+    case spv::Op::OpAtomicLoad:
+    case spv::Op::OpAtomicStore:
+    case spv::Op::OpAtomicExchange:
+    case spv::Op::OpAtomicCompareExchange:
+    case spv::Op::OpAtomicCompareExchangeWeak:
+    case spv::Op::OpAtomicIIncrement:
+    case spv::Op::OpAtomicIDecrement:
+    case spv::Op::OpAtomicIAdd:
+    case spv::Op::OpAtomicISub:
+    case spv::Op::OpAtomicSMin:
+    case spv::Op::OpAtomicUMin:
+    case spv::Op::OpAtomicSMax:
+    case spv::Op::OpAtomicUMax:
+    case spv::Op::OpAtomicAnd:
+    case spv::Op::OpAtomicOr:
+    case spv::Op::OpAtomicXor:
       // We conservatively ignore all atomic instructions at present.
       // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3276): Consider
       //  being less conservative here.
-    case SpvOpImageSampleImplicitLod:
-    case SpvOpImageSampleExplicitLod:
-    case SpvOpImageSampleDrefImplicitLod:
-    case SpvOpImageSampleDrefExplicitLod:
-    case SpvOpImageSampleProjImplicitLod:
-    case SpvOpImageSampleProjExplicitLod:
-    case SpvOpImageSampleProjDrefImplicitLod:
-    case SpvOpImageSampleProjDrefExplicitLod:
-    case SpvOpImageFetch:
-    case SpvOpImageGather:
-    case SpvOpImageDrefGather:
-    case SpvOpImageRead:
-    case SpvOpImageWrite:
-    case SpvOpImageSparseSampleImplicitLod:
-    case SpvOpImageSparseSampleExplicitLod:
-    case SpvOpImageSparseSampleDrefImplicitLod:
-    case SpvOpImageSparseSampleDrefExplicitLod:
-    case SpvOpImageSparseSampleProjImplicitLod:
-    case SpvOpImageSparseSampleProjExplicitLod:
-    case SpvOpImageSparseSampleProjDrefImplicitLod:
-    case SpvOpImageSparseSampleProjDrefExplicitLod:
-    case SpvOpImageSparseFetch:
-    case SpvOpImageSparseGather:
-    case SpvOpImageSparseDrefGather:
-    case SpvOpImageSparseRead:
-    case SpvOpImageSampleFootprintNV:
-    case SpvOpImage:
-    case SpvOpImageQueryFormat:
-    case SpvOpImageQueryLevels:
-    case SpvOpImageQueryLod:
-    case SpvOpImageQueryOrder:
-    case SpvOpImageQuerySamples:
-    case SpvOpImageQuerySize:
-    case SpvOpImageQuerySizeLod:
-    case SpvOpSampledImage:
+    case spv::Op::OpImageSampleImplicitLod:
+    case spv::Op::OpImageSampleExplicitLod:
+    case spv::Op::OpImageSampleDrefImplicitLod:
+    case spv::Op::OpImageSampleDrefExplicitLod:
+    case spv::Op::OpImageSampleProjImplicitLod:
+    case spv::Op::OpImageSampleProjExplicitLod:
+    case spv::Op::OpImageSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSampleProjDrefExplicitLod:
+    case spv::Op::OpImageFetch:
+    case spv::Op::OpImageGather:
+    case spv::Op::OpImageDrefGather:
+    case spv::Op::OpImageRead:
+    case spv::Op::OpImageWrite:
+    case spv::Op::OpImageSparseSampleImplicitLod:
+    case spv::Op::OpImageSparseSampleExplicitLod:
+    case spv::Op::OpImageSparseSampleDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleDrefExplicitLod:
+    case spv::Op::OpImageSparseSampleProjImplicitLod:
+    case spv::Op::OpImageSparseSampleProjExplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefExplicitLod:
+    case spv::Op::OpImageSparseFetch:
+    case spv::Op::OpImageSparseGather:
+    case spv::Op::OpImageSparseDrefGather:
+    case spv::Op::OpImageSparseRead:
+    case spv::Op::OpImageSampleFootprintNV:
+    case spv::Op::OpImage:
+    case spv::Op::OpImageQueryFormat:
+    case spv::Op::OpImageQueryLevels:
+    case spv::Op::OpImageQueryLod:
+    case spv::Op::OpImageQueryOrder:
+    case spv::Op::OpImageQuerySamples:
+    case spv::Op::OpImageQuerySize:
+    case spv::Op::OpImageQuerySizeLod:
+    case spv::Op::OpSampledImage:
       // We ignore all instructions related to accessing images, since we do not
       // donate images.
       return false;
-    case SpvOpLoad:
+    case spv::Op::OpLoad:
       switch (donor_ir_context->get_def_use_mgr()
                   ->GetDef(instruction.type_id())
                   ->opcode()) {
-        case SpvOpTypeImage:
-        case SpvOpTypeSampledImage:
-        case SpvOpTypeSampler:
+        case spv::Op::OpTypeImage:
+        case spv::Op::OpTypeSampledImage:
+        case spv::Op::OpTypeSampler:
           // Again, we ignore instructions that relate to accessing images.
           return false;
         default:
@@ -783,13 +784,13 @@
 bool FuzzerPassDonateModules::IsBasicType(
     const opt::Instruction& instruction) const {
   switch (instruction.opcode()) {
-    case SpvOpTypeArray:
-    case SpvOpTypeBool:
-    case SpvOpTypeFloat:
-    case SpvOpTypeInt:
-    case SpvOpTypeMatrix:
-    case SpvOpTypeStruct:
-    case SpvOpTypeVector:
+    case spv::Op::OpTypeArray:
+    case spv::Op::OpTypeBool:
+    case spv::Op::OpTypeFloat:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeStruct:
+    case spv::Op::OpTypeVector:
       return true;
     default:
       return false;
@@ -800,7 +801,7 @@
     const opt::Instruction& instruction,
     std::map<uint32_t, uint32_t>* original_id_to_donated_id,
     std::vector<protobufs::Instruction>* donated_instructions) const {
-  assert(instruction.opcode() == SpvOpArrayLength &&
+  assert(instruction.opcode() == spv::Op::OpArrayLength &&
          "Precondition: instruction must be OpArrayLength.");
   uint32_t donated_variable_id =
       original_id_to_donated_id->at(instruction.GetSingleWordInOperand(0));
@@ -809,12 +810,12 @@
   auto pointer_to_struct_instruction =
       GetIRContext()->get_def_use_mgr()->GetDef(
           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.");
   auto donated_struct_type_instruction =
       GetIRContext()->get_def_use_mgr()->GetDef(
           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.");
   assert(donated_struct_type_instruction->NumInOperands() ==
              instruction.GetSingleWordInOperand(1) + 1 &&
@@ -825,7 +826,7 @@
           donated_struct_type_instruction->NumInOperands() - 1);
   auto fixed_size_array_type_instruction =
       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.");
   auto array_size_id =
       fixed_size_array_type_instruction->GetSingleWordInOperand(1);
@@ -837,7 +838,8 @@
   }
 
   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()),
       opt::Instruction::OperandList({{SPV_OPERAND_TYPE_ID, {array_size_id}}})));
 }
@@ -892,7 +894,7 @@
   // more interesting value later.
   auto zero_constant = FindOrCreateZeroConstant(remapped_type_id, true);
   donated_instructions->push_back(MakeInstructionMessage(
-      SpvOpCopyObject, remapped_type_id,
+      spv::Op::OpCopyObject, remapped_type_id,
       original_id_to_donated_id->at(instruction.result_id()),
       opt::Instruction::OperandList({{SPV_OPERAND_TYPE_ID, {zero_constant}}})));
 }
@@ -926,8 +928,8 @@
         (void)(donor_ir_context);
         assert((donor_ir_context->get_def_use_mgr()
                         ->GetDef(operand_id)
-                        ->opcode() == SpvOpLabel ||
-                instruction.opcode() == SpvOpPhi) &&
+                        ->opcode() == spv::Op::OpLabel ||
+                instruction.opcode() == spv::Op::OpPhi) &&
                "Unsupported forward reference.");
         original_id_to_donated_id->insert(
             {operand_id, GetFuzzerContext()->GetFreshId()});
@@ -942,7 +944,7 @@
     input_operands.push_back({in_operand.type, operand_data});
   }
 
-  if (instruction.opcode() == SpvOpVariable &&
+  if (instruction.opcode() == spv::Op::OpVariable &&
       instruction.NumInOperands() == 1) {
     // This is an uninitialized local variable.  Initialize it to zero.
     input_operands.push_back(
@@ -1017,7 +1019,7 @@
 
   // Adjust OpPhi instructions in the |merge_block|.
   for (const auto& inst : *merge_block) {
-    if (inst.opcode() != SpvOpPhi) {
+    if (inst.opcode() != spv::Op::OpPhi) {
       break;
     }
 
@@ -1070,7 +1072,8 @@
   // live-safe.  Add them if not already present.
   FindOrCreateBoolType();  // Needed for comparisons
   FindOrCreatePointerToIntegerType(
-      32, false, SpvStorageClassFunction);  // Needed for adding loop limiters
+      32, false,
+      spv::StorageClass::Function);  // Needed for adding loop limiters
   FindOrCreateIntegerConstant({0}, 32, false,
                               false);  // Needed for initializing loop limiters
   FindOrCreateIntegerConstant({1}, 32, false,
@@ -1107,8 +1110,8 @@
   for (auto& block : function_to_donate) {
     for (auto& inst : block) {
       switch (inst.opcode()) {
-        case SpvOpAccessChain:
-        case SpvOpInBoundsAccessChain: {
+        case spv::Op::OpAccessChain:
+        case spv::Op::OpInBoundsAccessChain: {
           protobufs::AccessChainClampingInfo clamping_info;
           clamping_info.set_access_chain_id(
               original_id_to_donated_id.at(inst.result_id()));
@@ -1118,7 +1121,8 @@
           assert(base_object && "The base object must exist.");
           auto pointer_type = donor_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.");
 
           auto should_be_composite_type =
@@ -1138,7 +1142,8 @@
 
             // Get the bound for the component being indexed into.
             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
               // donate runtime arrays.  Instead, we donate a corresponding
               // fixed-size array for every runtime array.  We should thus
@@ -1148,7 +1153,7 @@
                   GetIRContext()->get_def_use_mgr()->GetDef(
                       original_id_to_donated_id.at(
                           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 "
                      "replaced by a fixed-sized array in the recipient.");
               // The size of this fixed-size array is a suitable bound.
@@ -1163,12 +1168,12 @@
                 donor_ir_context->get_def_use_mgr()->GetDef(index_id);
             auto index_type_inst = donor_ir_context->get_def_use_mgr()->GetDef(
                 index_inst->type_id());
-            assert(index_type_inst->opcode() == SpvOpTypeInt);
+            assert(index_type_inst->opcode() == spv::Op::OpTypeInt);
             opt::analysis::Integer* index_int_type =
                 donor_ir_context->get_type_mgr()
                     ->GetType(index_type_inst->result_id())
                     ->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
               // whose value is one less than the bound, to compare
               // against and to use as the clamped value.
@@ -1194,7 +1199,7 @@
   uint32_t kill_unreachable_return_value_id = 0;
   auto function_return_type_inst =
       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)) {
     kill_unreachable_return_value_id = FindOrCreateZeroConstant(
         original_id_to_donated_id.at(function_return_type_inst->result_id()),
diff --git a/source/fuzz/fuzzer_pass_donate_modules.h b/source/fuzz/fuzzer_pass_donate_modules.h
index 924dd35..004f158 100644
--- a/source/fuzz/fuzzer_pass_donate_modules.h
+++ b/source/fuzz/fuzzer_pass_donate_modules.h
@@ -45,7 +45,8 @@
  private:
   // 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.
-  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
   // populates |original_id_to_donated_id| with a mapping from the donor's id
diff --git a/source/fuzz/fuzzer_pass_expand_vector_reductions.cpp b/source/fuzz/fuzzer_pass_expand_vector_reductions.cpp
index 5bf0461..fecd82e 100644
--- a/source/fuzz/fuzzer_pass_expand_vector_reductions.cpp
+++ b/source/fuzz/fuzzer_pass_expand_vector_reductions.cpp
@@ -40,8 +40,8 @@
         }
 
         // |instruction| must be OpAny or OpAll.
-        if (instruction.opcode() != SpvOpAny &&
-            instruction.opcode() != SpvOpAll) {
+        if (instruction.opcode() != spv::Op::OpAny &&
+            instruction.opcode() != spv::Op::OpAll) {
           continue;
         }
 
diff --git a/source/fuzz/fuzzer_pass_flatten_conditional_branches.cpp b/source/fuzz/fuzzer_pass_flatten_conditional_branches.cpp
index 70fa6a1..86ffff4 100644
--- a/source/fuzz/fuzzer_pass_flatten_conditional_branches.cpp
+++ b/source/fuzz/fuzzer_pass_flatten_conditional_branches.cpp
@@ -48,8 +48,8 @@
       // Only consider this block if it is the header of a conditional, with a
       // non-irrelevant condition.
       if (block.GetMergeInst() &&
-          block.GetMergeInst()->opcode() == SpvOpSelectionMerge &&
-          block.terminator()->opcode() == SpvOpBranchConditional &&
+          block.GetMergeInst()->opcode() == spv::Op::OpSelectionMerge &&
+          block.terminator()->opcode() == spv::Op::OpBranchConditional &&
           !GetTransformationContext()->GetFactManager()->IdIsIrrelevant(
               block.terminator()->GetSingleWordInOperand(0))) {
         selection_headers.emplace_back(&block);
@@ -94,11 +94,11 @@
                                    ->get_def_use_mgr()
                                    ->GetDef(phi_instruction->type_id())
                                    ->opcode()) {
-                         case SpvOpTypeBool:
-                         case SpvOpTypeInt:
-                         case SpvOpTypeFloat:
-                         case SpvOpTypePointer:
-                         case SpvOpTypeVector:
+                         case spv::Op::OpTypeBool:
+                         case spv::Op::OpTypeInt:
+                         case spv::Op::OpTypeFloat:
+                         case spv::Op::OpTypePointer:
+                         case spv::Op::OpTypeVector:
                            return true;
                          default:
                            return false;
@@ -143,7 +143,7 @@
                 GetIRContext()->get_def_use_mgr()->GetDef(
                     phi_instruction->type_id());
             switch (type_instruction->opcode()) {
-              case SpvOpTypeVector: {
+              case spv::Op::OpTypeVector: {
                 uint32_t dimension =
                     type_instruction->GetSingleWordInOperand(1);
                 switch (dimension) {
diff --git a/source/fuzz/fuzzer_pass_inline_functions.cpp b/source/fuzz/fuzzer_pass_inline_functions.cpp
index 4024096..6839bbe 100644
--- a/source/fuzz/fuzzer_pass_inline_functions.cpp
+++ b/source/fuzz/fuzzer_pass_inline_functions.cpp
@@ -64,7 +64,7 @@
     auto* function_call_block =
         GetIRContext()->get_instr_block(function_call_instruction);
     if ((function_call_instruction != &*--function_call_block->tail() ||
-         function_call_block->terminator()->opcode() != SpvOpBranch) &&
+         function_call_block->terminator()->opcode() != spv::Op::OpBranch) &&
         !MaybeApplyTransformation(TransformationSplitBlock(
             MakeInstructionDescriptor(GetIRContext(),
                                       function_call_instruction->NextNode()),
diff --git a/source/fuzz/fuzzer_pass_make_vector_operations_dynamic.cpp b/source/fuzz/fuzzer_pass_make_vector_operations_dynamic.cpp
index b755d23..ec5fc4b 100644
--- a/source/fuzz/fuzzer_pass_make_vector_operations_dynamic.cpp
+++ b/source/fuzz/fuzzer_pass_make_vector_operations_dynamic.cpp
@@ -47,18 +47,20 @@
         }
 
         // Make sure |instruction| has only one indexing operand.
-        assert(instruction.NumInOperands() ==
-                   (instruction.opcode() == SpvOpCompositeExtract ? 2 : 3) &&
-               "FuzzerPassMakeVectorOperationsDynamic: the composite "
-               "instruction must have "
-               "only one indexing operand.");
+        assert(
+            instruction.NumInOperands() ==
+                (instruction.opcode() == spv::Op::OpCompositeExtract ? 2 : 3) &&
+            "FuzzerPassMakeVectorOperationsDynamic: the composite "
+            "instruction must have "
+            "only one indexing operand.");
 
         // Applies the make vector operation dynamic transformation.
         ApplyTransformation(TransformationMakeVectorOperationDynamic(
             instruction.result_id(),
             FindOrCreateIntegerConstant(
                 {instruction.GetSingleWordInOperand(
-                    instruction.opcode() == SpvOpCompositeExtract ? 1 : 2)},
+                    instruction.opcode() == spv::Op::OpCompositeExtract ? 1
+                                                                        : 2)},
                 32, GetFuzzerContext()->ChooseEven(), false)));
       }
     }
diff --git a/source/fuzz/fuzzer_pass_merge_function_returns.cpp b/source/fuzz/fuzzer_pass_merge_function_returns.cpp
index 220f707..48c1861 100644
--- a/source/fuzz/fuzzer_pass_merge_function_returns.cpp
+++ b/source/fuzz/fuzzer_pass_merge_function_returns.cpp
@@ -64,11 +64,11 @@
         [this, function](
             opt::BasicBlock* /*unused*/, opt::BasicBlock::iterator inst_it,
             const protobufs::InstructionDescriptor& instruction_descriptor) {
-          const SpvOp opcode = inst_it->opcode();
+          const spv::Op opcode = inst_it->opcode();
           switch (opcode) {
-            case SpvOpKill:
-            case SpvOpUnreachable:
-            case SpvOpTerminateInvocation: {
+            case spv::Op::OpKill:
+            case spv::Op::OpUnreachable:
+            case spv::Op::OpTerminateInvocation: {
               // This is an early termination instruction - we need to wrap it
               // so that it becomes a return.
               if (TransformationWrapEarlyTerminatorInFunction::
@@ -85,7 +85,7 @@
                   GetIRContext()->get_def_use_mgr()->GetDef(
                       function->type_id());
               uint32_t returned_value_id;
-              if (function_return_type->opcode() == SpvOpTypeVoid) {
+              if (function_return_type->opcode() == spv::Op::OpTypeVoid) {
                 // No value is needed.
                 returned_value_id = 0;
               } else if (fuzzerutil::CanCreateConstant(
@@ -130,7 +130,7 @@
 
     // If the entry block does not branch unconditionally to another block,
     // split it.
-    if (function->entry()->terminator()->opcode() != SpvOpBranch) {
+    if (function->entry()->terminator()->opcode() != spv::Op::OpBranch) {
       SplitBlockAfterOpPhiOrOpVariable(function->entry()->id());
     }
 
@@ -149,9 +149,9 @@
       if (GetIRContext()
               ->get_instr_block(merge_block)
               ->WhileEachInst([](opt::Instruction* inst) {
-                return inst->opcode() == SpvOpLabel ||
-                       inst->opcode() == SpvOpPhi ||
-                       inst->opcode() == SpvOpBranch;
+                return inst->opcode() == spv::Op::OpLabel ||
+                       inst->opcode() == spv::Op::OpPhi ||
+                       inst->opcode() == spv::Op::OpBranch;
               })) {
         actual_merge_blocks.emplace_back(merge_block);
         continue;
@@ -324,7 +324,8 @@
 
 bool FuzzerPassMergeFunctionReturns::IsEarlyTerminatorWrapper(
     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(
             GetIRContext(), opcode) == &function) {
       return true;
diff --git a/source/fuzz/fuzzer_pass_mutate_pointers.cpp b/source/fuzz/fuzzer_pass_mutate_pointers.cpp
index bbe0540..a7e9fdc 100644
--- a/source/fuzz/fuzzer_pass_mutate_pointers.cpp
+++ b/source/fuzz/fuzzer_pass_mutate_pointers.cpp
@@ -39,7 +39,8 @@
           return;
         }
 
-        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpLoad, inst_it)) {
+        if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpLoad,
+                                                          inst_it)) {
           return;
         }
 
diff --git a/source/fuzz/fuzzer_pass_obfuscate_constants.cpp b/source/fuzz/fuzzer_pass_obfuscate_constants.cpp
index f60c1b4..48ac589 100644
--- a/source/fuzz/fuzzer_pass_obfuscate_constants.cpp
+++ b/source/fuzz/fuzzer_pass_obfuscate_constants.cpp
@@ -37,21 +37,21 @@
 
 void FuzzerPassObfuscateConstants::ObfuscateBoolConstantViaConstantPair(
     uint32_t depth, const protobufs::IdUseDescriptor& bool_constant_use,
-    const std::vector<SpvOp>& greater_than_opcodes,
-    const std::vector<SpvOp>& less_than_opcodes, uint32_t constant_id_1,
+    const std::vector<spv::Op>& greater_than_opcodes,
+    const std::vector<spv::Op>& less_than_opcodes, uint32_t constant_id_1,
     uint32_t constant_id_2, bool first_constant_is_larger) {
   auto bool_constant_opcode = GetIRContext()
                                   ->get_def_use_mgr()
                                   ->GetDef(bool_constant_use.id_of_interest())
                                   ->opcode();
-  assert((bool_constant_opcode == SpvOpConstantFalse ||
-          bool_constant_opcode == SpvOpConstantTrue) &&
+  assert((bool_constant_opcode == spv::Op::OpConstantFalse ||
+          bool_constant_opcode == spv::Op::OpConstantTrue) &&
          "Precondition: this must be a usage of a boolean constant.");
 
   // Pick an opcode at random.  First randomly decide whether to generate
   // a 'greater than' or 'less than' kind of opcode, and then select a
   // random opcode from the resulting subset.
-  SpvOp comparison_opcode;
+  spv::Op comparison_opcode;
   if (GetFuzzerContext()->ChooseEven()) {
     comparison_opcode = greater_than_opcodes[GetFuzzerContext()->RandomIndex(
         greater_than_opcodes)];
@@ -68,9 +68,9 @@
                 comparison_opcode) != greater_than_opcodes.end();
   uint32_t lhs_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) ||
-      (bool_constant_opcode == SpvOpConstantFalse &&
+      (bool_constant_opcode == spv::Op::OpConstantFalse &&
        first_constant_is_larger != is_greater_than_opcode)) {
     lhs_id = constant_id_1;
     rhs_id = constant_id_2;
@@ -147,12 +147,12 @@
     first_constant_is_larger =
         float_constant_1->GetDouble() > float_constant_2->GetDouble();
   }
-  std::vector<SpvOp> greater_than_opcodes{
-      SpvOpFOrdGreaterThan, SpvOpFOrdGreaterThanEqual, SpvOpFUnordGreaterThan,
-      SpvOpFUnordGreaterThanEqual};
-  std::vector<SpvOp> less_than_opcodes{
-      SpvOpFOrdGreaterThan, SpvOpFOrdGreaterThanEqual, SpvOpFUnordGreaterThan,
-      SpvOpFUnordGreaterThanEqual};
+  std::vector<spv::Op> greater_than_opcodes{
+      spv::Op::OpFOrdGreaterThan, spv::Op::OpFOrdGreaterThanEqual,
+      spv::Op::OpFUnordGreaterThan, spv::Op::OpFUnordGreaterThanEqual};
+  std::vector<spv::Op> less_than_opcodes{
+      spv::Op::OpFOrdGreaterThan, spv::Op::OpFOrdGreaterThanEqual,
+      spv::Op::OpFUnordGreaterThan, spv::Op::OpFUnordGreaterThanEqual};
 
   ObfuscateBoolConstantViaConstantPair(
       depth, bool_constant_use, greater_than_opcodes, less_than_opcodes,
@@ -190,9 +190,10 @@
     first_constant_is_larger =
         signed_int_constant_1->GetS64() > signed_int_constant_2->GetS64();
   }
-  std::vector<SpvOp> greater_than_opcodes{SpvOpSGreaterThan,
-                                          SpvOpSGreaterThanEqual};
-  std::vector<SpvOp> less_than_opcodes{SpvOpSLessThan, SpvOpSLessThanEqual};
+  std::vector<spv::Op> greater_than_opcodes{spv::Op::OpSGreaterThan,
+                                            spv::Op::OpSGreaterThanEqual};
+  std::vector<spv::Op> less_than_opcodes{spv::Op::OpSLessThan,
+                                         spv::Op::OpSLessThanEqual};
 
   ObfuscateBoolConstantViaConstantPair(
       depth, bool_constant_use, greater_than_opcodes, less_than_opcodes,
@@ -232,9 +233,10 @@
     first_constant_is_larger =
         unsigned_int_constant_1->GetU64() > unsigned_int_constant_2->GetU64();
   }
-  std::vector<SpvOp> greater_than_opcodes{SpvOpUGreaterThan,
-                                          SpvOpUGreaterThanEqual};
-  std::vector<SpvOp> less_than_opcodes{SpvOpULessThan, SpvOpULessThanEqual};
+  std::vector<spv::Op> greater_than_opcodes{spv::Op::OpUGreaterThan,
+                                            spv::Op::OpUGreaterThanEqual};
+  std::vector<spv::Op> less_than_opcodes{spv::Op::OpULessThan,
+                                         spv::Op::OpULessThanEqual};
 
   ObfuscateBoolConstantViaConstantPair(
       depth, bool_constant_use, greater_than_opcodes, less_than_opcodes,
@@ -379,7 +381,7 @@
       uniform_descriptor.index());
   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
   // the result of a load from the chosen uniform.
@@ -394,11 +396,11 @@
               ->get_def_use_mgr()
               ->GetDef(constant_use.id_of_interest())
               ->opcode()) {
-    case SpvOpConstantTrue:
-    case SpvOpConstantFalse:
+    case spv::Op::OpConstantTrue:
+    case spv::Op::OpConstantFalse:
       ObfuscateBoolConstant(depth, constant_use);
       break;
-    case SpvOpConstant:
+    case spv::Op::OpConstant:
       ObfuscateScalarConstant(depth, constant_use);
       break;
     default:
@@ -410,7 +412,7 @@
 void FuzzerPassObfuscateConstants::MaybeAddConstantIdUse(
     const opt::Instruction& inst, uint32_t in_operand_index,
     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) {
   if (inst.GetInOperand(in_operand_index).type != SPV_OPERAND_TYPE_ID) {
     // The operand is not an id, so it cannot be a constant id.
@@ -420,15 +422,15 @@
   auto operand_definition =
       GetIRContext()->get_def_use_mgr()->GetDef(operand_id);
   switch (operand_definition->opcode()) {
-    case SpvOpConstantFalse:
-    case SpvOpConstantTrue:
-    case SpvOpConstant: {
+    case spv::Op::OpConstantFalse:
+    case spv::Op::OpConstantTrue:
+    case spv::Op::OpConstant: {
       // The operand is a constant id, so make an id use descriptor and record
       // it.
       protobufs::IdUseDescriptor id_use_descriptor;
       id_use_descriptor.set_id_of_interest(operand_id);
       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()
           ->set_base_instruction_result_id(base_instruction_result_id);
       id_use_descriptor.mutable_enclosing_instruction()
@@ -461,7 +463,7 @@
       // 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
       // 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.
       for (auto& inst : block) {
@@ -478,7 +480,7 @@
         // The instruction must not be an OpVariable, the only id that an
         // OpVariable uses is an initializer id, which has to remain
         // constant.
-        if (inst.opcode() != SpvOpVariable) {
+        if (inst.opcode() != spv::Op::OpVariable) {
           // Consider each operand of the instruction, and add a constant id
           // use for the operand if relevant.
           for (uint32_t in_operand_index = 0;
diff --git a/source/fuzz/fuzzer_pass_obfuscate_constants.h b/source/fuzz/fuzzer_pass_obfuscate_constants.h
index 30e64d2..bfef597 100644
--- a/source/fuzz/fuzzer_pass_obfuscate_constants.h
+++ b/source/fuzz/fuzzer_pass_obfuscate_constants.h
@@ -85,8 +85,8 @@
   // (similar for |less_than_opcodes|).
   void ObfuscateBoolConstantViaConstantPair(
       uint32_t depth, const protobufs::IdUseDescriptor& bool_constant_use,
-      const std::vector<SpvOp>& greater_than_opcodes,
-      const std::vector<SpvOp>& less_than_opcodes, uint32_t constant_id_1,
+      const std::vector<spv::Op>& greater_than_opcodes,
+      const std::vector<spv::Op>& less_than_opcodes, uint32_t constant_id_1,
       uint32_t constant_id_2, bool first_constant_is_larger);
 
   // A helper method to determine whether input operand |in_operand_index| of
@@ -96,7 +96,7 @@
   void MaybeAddConstantIdUse(
       const opt::Instruction& inst, uint32_t in_operand_index,
       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);
 
   // Returns a vector of unique words that denote constants. Every such constant
diff --git a/source/fuzz/fuzzer_pass_outline_functions.cpp b/source/fuzz/fuzzer_pass_outline_functions.cpp
index b90c12d..e64373a 100644
--- a/source/fuzz/fuzzer_pass_outline_functions.cpp
+++ b/source/fuzz/fuzzer_pass_outline_functions.cpp
@@ -137,12 +137,12 @@
          "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 (entry_block->begin()->opcode() == SpvOpPhi ||
-      entry_block->begin()->opcode() == SpvOpVariable) {
+  if (entry_block->begin()->opcode() == spv::Op::OpPhi ||
+      entry_block->begin()->opcode() == spv::Op::OpVariable) {
     // Find the first non-OpPhi and non-OpVariable instruction.
     auto non_phi_or_var_inst = &*entry_block->begin();
-    while (non_phi_or_var_inst->opcode() == SpvOpPhi ||
-           non_phi_or_var_inst->opcode() == SpvOpVariable) {
+    while (non_phi_or_var_inst->opcode() == spv::Op::OpPhi ||
+           non_phi_or_var_inst->opcode() == spv::Op::OpVariable) {
       non_phi_or_var_inst = non_phi_or_var_inst->NextNode();
     }
 
@@ -175,7 +175,7 @@
 
     // Find the first non-OpPhi instruction, after which to split.
     auto split_before = &*exit_block->begin();
-    while (split_before->opcode() == SpvOpPhi) {
+    while (split_before->opcode() == spv::Op::OpPhi) {
       split_before = split_before->NextNode();
     }
 
diff --git a/source/fuzz/fuzzer_pass_permute_function_variables.cpp b/source/fuzz/fuzzer_pass_permute_function_variables.cpp
index f8b9b45..2313f42 100644
--- a/source/fuzz/fuzzer_pass_permute_function_variables.cpp
+++ b/source/fuzz/fuzzer_pass_permute_function_variables.cpp
@@ -47,7 +47,7 @@
 
     std::vector<opt::Instruction*> variables;
     for (auto& instruction : *first_block) {
-      if (instruction.opcode() == SpvOpVariable) {
+      if (instruction.opcode() == spv::Op::OpVariable) {
         variables.push_back(&instruction);
       }
     }
diff --git a/source/fuzz/fuzzer_pass_permute_phi_operands.cpp b/source/fuzz/fuzzer_pass_permute_phi_operands.cpp
index 5fac981..7fbdd3b 100644
--- a/source/fuzz/fuzzer_pass_permute_phi_operands.cpp
+++ b/source/fuzz/fuzzer_pass_permute_phi_operands.cpp
@@ -40,7 +40,7 @@
              const protobufs::InstructionDescriptor& /*unused*/) {
         const auto& inst = *inst_it;
 
-        if (inst.opcode() != SpvOpPhi) {
+        if (inst.opcode() != spv::Op::OpPhi) {
           return;
         }
 
diff --git a/source/fuzz/fuzzer_pass_push_ids_through_variables.cpp b/source/fuzz/fuzzer_pass_push_ids_through_variables.cpp
index a6c07b4..c0397e1 100644
--- a/source/fuzz/fuzzer_pass_push_ids_through_variables.cpp
+++ b/source/fuzz/fuzzer_pass_push_ids_through_variables.cpp
@@ -35,10 +35,11 @@
              opt::BasicBlock::iterator instruction_iterator,
              const protobufs::InstructionDescriptor& instruction_descriptor)
           -> void {
-        assert(instruction_iterator->opcode() ==
-                   instruction_descriptor.target_instruction_opcode() &&
-               "The opcode of the instruction we might insert before must be "
-               "the same as the opcode in the descriptor for the instruction");
+        assert(
+            instruction_iterator->opcode() ==
+                spv::Op(instruction_descriptor.target_instruction_opcode()) &&
+            "The opcode of the instruction we might insert before must be "
+            "the same as the opcode in the descriptor for the instruction");
 
         // Randomly decide whether to try pushing an id through a variable.
         if (!GetFuzzerContext()->ChoosePercentage(
@@ -55,16 +56,16 @@
         // It must be valid to insert OpStore and OpLoad instructions
         // before the instruction to insert before.
         if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
-                SpvOpStore, instruction_iterator) ||
+                spv::Op::OpStore, instruction_iterator) ||
             !fuzzerutil::CanInsertOpcodeBeforeInstruction(
-                SpvOpLoad, instruction_iterator)) {
+                spv::Op::OpLoad, instruction_iterator)) {
           return;
         }
 
         // Randomly decides whether a global or local variable will be added.
         auto variable_storage_class = GetFuzzerContext()->ChooseEven()
-                                          ? SpvStorageClassPrivate
-                                          : SpvStorageClassFunction;
+                                          ? spv::StorageClass::Private
+                                          : spv::StorageClass::Function;
 
         // Gets the available basic and pointer types.
         auto basic_type_ids_and_pointers =
@@ -127,13 +128,13 @@
             GetIRContext()->get_def_use_mgr()->GetDef(basic_type_id);
         assert(type_inst);
         switch (type_inst->opcode()) {
-          case SpvOpTypeBool:
-          case SpvOpTypeFloat:
-          case SpvOpTypeInt:
-          case SpvOpTypeArray:
-          case SpvOpTypeMatrix:
-          case SpvOpTypeVector:
-          case SpvOpTypeStruct:
+          case spv::Op::OpTypeBool:
+          case spv::Op::OpTypeFloat:
+          case spv::Op::OpTypeInt:
+          case spv::Op::OpTypeArray:
+          case spv::Op::OpTypeMatrix:
+          case spv::Op::OpTypeVector:
+          case spv::Op::OpTypeStruct:
             break;
           default:
             return;
@@ -150,7 +151,8 @@
                                    value_instructions)]
                 ->result_id(),
             GetFuzzerContext()->GetFreshId(), GetFuzzerContext()->GetFreshId(),
-            variable_storage_class, initializer_id, instruction_descriptor));
+            uint32_t(variable_storage_class), initializer_id,
+            instruction_descriptor));
       });
 }
 
diff --git a/source/fuzz/fuzzer_pass_replace_branches_from_dead_blocks_with_exits.cpp b/source/fuzz/fuzzer_pass_replace_branches_from_dead_blocks_with_exits.cpp
index 995657c..52c0381 100644
--- a/source/fuzz/fuzzer_pass_replace_branches_from_dead_blocks_with_exits.cpp
+++ b/source/fuzz/fuzzer_pass_replace_branches_from_dead_blocks_with_exits.cpp
@@ -38,13 +38,13 @@
   // to be executed with the Fragment execution model.  We conservatively only
   // allow OpKill if every entry point in the module has the Fragment execution
   // model.
-  auto fragment_execution_model_guaranteed =
-      std::all_of(GetIRContext()->module()->entry_points().begin(),
-                  GetIRContext()->module()->entry_points().end(),
-                  [](const opt::Instruction& entry_point) -> bool {
-                    return entry_point.GetSingleWordInOperand(0) ==
-                           SpvExecutionModelFragment;
-                  });
+  auto fragment_execution_model_guaranteed = std::all_of(
+      GetIRContext()->module()->entry_points().begin(),
+      GetIRContext()->module()->entry_points().end(),
+      [](const opt::Instruction& entry_point) -> bool {
+        return spv::ExecutionModel(entry_point.GetSingleWordInOperand(0)) ==
+               spv::ExecutionModel::Fragment;
+      });
 
   // Transformations of this type can disable one another.  To avoid ordering
   // bias, we therefore build a set of candidate transformations to apply, and
@@ -71,20 +71,20 @@
       // 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
       // enclosing function.
-      std::vector<SpvOp> opcodes = {SpvOpUnreachable};
+      std::vector<spv::Op> opcodes = {spv::Op::OpUnreachable};
       if (fragment_execution_model_guaranteed) {
-        opcodes.emplace_back(SpvOpKill);
+        opcodes.emplace_back(spv::Op::OpKill);
       }
       auto function_return_type =
           GetIRContext()->get_type_mgr()->GetType(function.type_id());
       if (function_return_type->AsVoid()) {
-        opcodes.emplace_back(SpvOpReturn);
+        opcodes.emplace_back(spv::Op::OpReturn);
       } else if (fuzzerutil::CanCreateConstant(GetIRContext(),
                                                function.type_id())) {
         // 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
         // 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
       // candidate transformation.
@@ -92,7 +92,7 @@
       candidate_transformations.emplace_back(
           TransformationReplaceBranchFromDeadBlockWithExit(
               block.id(), opcode,
-              opcode == SpvOpReturnValue
+              opcode == spv::Op::OpReturnValue
                   ? FindOrCreateZeroConstant(function.type_id(), true)
                   : 0));
     }
diff --git a/source/fuzz/fuzzer_pass_replace_copy_memories_with_loads_stores.cpp b/source/fuzz/fuzzer_pass_replace_copy_memories_with_loads_stores.cpp
index af1aace..aabc6bc 100644
--- a/source/fuzz/fuzzer_pass_replace_copy_memories_with_loads_stores.cpp
+++ b/source/fuzz/fuzzer_pass_replace_copy_memories_with_loads_stores.cpp
@@ -41,7 +41,7 @@
     }
 
     // The instruction must be OpCopyMemory.
-    if (instruction->opcode() != SpvOpCopyMemory) {
+    if (instruction->opcode() != spv::Op::OpCopyMemory) {
       return;
     }
 
diff --git a/source/fuzz/fuzzer_pass_replace_copy_objects_with_stores_loads.cpp b/source/fuzz/fuzzer_pass_replace_copy_objects_with_stores_loads.cpp
index d0992a3..c1892be 100644
--- a/source/fuzz/fuzzer_pass_replace_copy_objects_with_stores_loads.cpp
+++ b/source/fuzz/fuzzer_pass_replace_copy_objects_with_stores_loads.cpp
@@ -40,7 +40,7 @@
       return;
     }
     // The instruction must be OpCopyObject.
-    if (instruction->opcode() != SpvOpCopyObject) {
+    if (instruction->opcode() != spv::Op::OpCopyObject) {
       return;
     }
     // The opcode of the type_id instruction cannot be a OpTypePointer,
@@ -48,21 +48,22 @@
     if (GetIRContext()
             ->get_def_use_mgr()
             ->GetDef(instruction->type_id())
-            ->opcode() == SpvOpTypePointer) {
+            ->opcode() == spv::Op::OpTypePointer) {
       return;
     }
     // It must be valid to insert OpStore and OpLoad instructions
     // before the instruction OpCopyObject.
-    if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpStore,
+    if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpStore,
                                                       instruction) ||
-        !fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpLoad, instruction)) {
+        !fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpLoad,
+                                                      instruction)) {
       return;
     }
 
     // Randomly decides whether a global or local variable will be added.
     auto variable_storage_class = GetFuzzerContext()->ChooseEven()
-                                      ? SpvStorageClassPrivate
-                                      : SpvStorageClassFunction;
+                                      ? spv::StorageClass::Private
+                                      : spv::StorageClass::Function;
 
     // Find or create a constant to initialize the variable from. The type of
     // |instruction| must be such that the function FindOrCreateConstant can be
@@ -79,7 +80,7 @@
     // Apply the transformation replacing OpCopyObject with Store and Load.
     ApplyTransformation(TransformationReplaceCopyObjectWithStoreLoad(
         instruction->result_id(), GetFuzzerContext()->GetFreshId(),
-        variable_storage_class, variable_initializer_id));
+        uint32_t(variable_storage_class), variable_initializer_id));
   });
 }
 
diff --git a/source/fuzz/fuzzer_pass_replace_irrelevant_ids.cpp b/source/fuzz/fuzzer_pass_replace_irrelevant_ids.cpp
index 4d55ae8..4c0bd85 100644
--- a/source/fuzz/fuzzer_pass_replace_irrelevant_ids.cpp
+++ b/source/fuzz/fuzzer_pass_replace_irrelevant_ids.cpp
@@ -73,7 +73,7 @@
   // we cannot use these as replacements.
   for (const auto& pair : GetIRContext()->get_def_use_mgr()->id_to_defs()) {
     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[type_id].push_back(pair.first);
     }
diff --git a/source/fuzz/fuzzer_pass_replace_loads_stores_with_copy_memories.cpp b/source/fuzz/fuzzer_pass_replace_loads_stores_with_copy_memories.cpp
index 38ac048..8d292ac 100644
--- a/source/fuzz/fuzzer_pass_replace_loads_stores_with_copy_memories.cpp
+++ b/source/fuzz/fuzzer_pass_replace_loads_stores_with_copy_memories.cpp
@@ -50,9 +50,9 @@
       std::unordered_map<uint32_t, opt::Instruction*> current_op_loads;
       for (auto& instruction : block) {
         // Add a potential OpLoad instruction.
-        if (instruction.opcode() == SpvOpLoad) {
+        if (instruction.opcode() == spv::Op::OpLoad) {
           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)) !=
               current_op_loads.end()) {
             // We have found the matching OpLoad instruction to the current
@@ -73,7 +73,7 @@
             opt::Instruction* source_id =
                 GetIRContext()->get_def_use_mgr()->GetDef(
                     it->second->GetSingleWordOperand(2));
-            SpvStorageClass storage_class =
+            spv::StorageClass storage_class =
                 fuzzerutil::GetStorageClassFromPointerType(
                     GetIRContext(), source_id->type_id());
             if (!TransformationReplaceLoadStoreWithCopyMemory::
diff --git a/source/fuzz/fuzzer_pass_replace_opphi_ids_from_dead_predecessors.cpp b/source/fuzz/fuzzer_pass_replace_opphi_ids_from_dead_predecessors.cpp
index ea90a7a..26475ab 100644
--- a/source/fuzz/fuzzer_pass_replace_opphi_ids_from_dead_predecessors.cpp
+++ b/source/fuzz/fuzzer_pass_replace_opphi_ids_from_dead_predecessors.cpp
@@ -50,7 +50,7 @@
               block->id(), [this, &function, block, &transformations](
                                opt::Instruction* instruction, uint32_t) {
                 // Only consider OpPhi instructions.
-                if (instruction->opcode() != SpvOpPhi) {
+                if (instruction->opcode() != spv::Op::OpPhi) {
                   return;
                 }
 
diff --git a/source/fuzz/fuzzer_pass_replace_opselects_with_conditional_branches.cpp b/source/fuzz/fuzzer_pass_replace_opselects_with_conditional_branches.cpp
index 72ed093..4691e0a 100644
--- a/source/fuzz/fuzzer_pass_replace_opselects_with_conditional_branches.cpp
+++ b/source/fuzz/fuzzer_pass_replace_opselects_with_conditional_branches.cpp
@@ -52,7 +52,7 @@
 
       for (auto& instruction : block) {
         // We only care about OpSelect instructions.
-        if (instruction.opcode() != SpvOpSelect) {
+        if (instruction.opcode() != spv::Op::OpSelect) {
           continue;
         }
 
@@ -69,7 +69,7 @@
                 ->get_def_use_mgr()
                 ->GetDef(fuzzerutil::GetTypeId(
                     GetIRContext(), instruction.GetSingleWordInOperand(0)))
-                ->opcode() != SpvOpTypeBool) {
+                ->opcode() != spv::Op::OpTypeBool) {
           continue;
         }
 
@@ -136,7 +136,7 @@
 
 bool FuzzerPassReplaceOpSelectsWithConditionalBranches::
     InstructionNeedsSplitBefore(opt::Instruction* instruction) {
-  assert(instruction && instruction->opcode() == SpvOpSelect &&
+  assert(instruction && instruction->opcode() == spv::Op::OpSelect &&
          "The instruction must be OpSelect.");
 
   auto block = GetIRContext()->get_instr_block(instruction);
@@ -163,7 +163,7 @@
   auto predecessor = GetIRContext()->get_instr_block(
       GetIRContext()->cfg()->preds(block->id())[0]);
   return predecessor->MergeBlockIdIfAny() ||
-         predecessor->terminator()->opcode() != SpvOpBranch;
+         predecessor->terminator()->opcode() != spv::Op::OpBranch;
 }
 
 }  // namespace fuzz
diff --git a/source/fuzz/fuzzer_pass_replace_parameter_with_global.cpp b/source/fuzz/fuzzer_pass_replace_parameter_with_global.cpp
index 7fb7b0d..d7eddca 100644
--- a/source/fuzz/fuzzer_pass_replace_parameter_with_global.cpp
+++ b/source/fuzz/fuzzer_pass_replace_parameter_with_global.cpp
@@ -72,7 +72,8 @@
     assert(replaced_param && "Unable to find a parameter to replace");
 
     // 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.
     FindOrCreateZeroConstant(replaced_param->type_id(), false);
diff --git a/source/fuzz/fuzzer_pass_split_blocks.cpp b/source/fuzz/fuzzer_pass_split_blocks.cpp
index 40a4151..5b4afcc 100644
--- a/source/fuzz/fuzzer_pass_split_blocks.cpp
+++ b/source/fuzz/fuzzer_pass_split_blocks.cpp
@@ -65,7 +65,7 @@
 
     // Counts the number of times we have seen each opcode since we reset the
     // 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
     // only necessary to consider it as a base in case the first instruction
@@ -78,7 +78,7 @@
         base = inst.result_id();
         skip_count.clear();
       }
-      const SpvOp opcode = inst.opcode();
+      const spv::Op opcode = inst.opcode();
       instruction_descriptors.emplace_back(MakeInstructionDescriptor(
           base, opcode, skip_count.count(opcode) ? skip_count.at(opcode) : 0));
       if (!inst.HasResultId()) {
diff --git a/source/fuzz/fuzzer_pass_swap_conditional_branch_operands.cpp b/source/fuzz/fuzzer_pass_swap_conditional_branch_operands.cpp
index f8bf111..72c8358 100644
--- a/source/fuzz/fuzzer_pass_swap_conditional_branch_operands.cpp
+++ b/source/fuzz/fuzzer_pass_swap_conditional_branch_operands.cpp
@@ -39,7 +39,7 @@
              const protobufs::InstructionDescriptor& instruction_descriptor) {
         const auto& inst = *inst_it;
 
-        if (inst.opcode() != SpvOpBranchConditional) {
+        if (inst.opcode() != spv::Op::OpBranchConditional) {
           return;
         }
 
diff --git a/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.cpp b/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.cpp
index ac2b156..2a1ad6e 100644
--- a/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.cpp
+++ b/source/fuzz/fuzzer_pass_toggle_access_chain_instruction.cpp
@@ -36,8 +36,9 @@
   // probabilistically applied.
   context->module()->ForEachInst([this,
                                   context](opt::Instruction* instruction) {
-    SpvOp opcode = instruction->opcode();
-    if ((opcode == SpvOpAccessChain || opcode == SpvOpInBoundsAccessChain) &&
+    spv::Op opcode = instruction->opcode();
+    if ((opcode == spv::Op::OpAccessChain ||
+         opcode == spv::Op::OpInBoundsAccessChain) &&
         GetFuzzerContext()->ChoosePercentage(
             GetFuzzerContext()->GetChanceOfTogglingAccessChainInstruction())) {
       auto instructionDescriptor =
diff --git a/source/fuzz/fuzzer_pass_wrap_vector_synonym.cpp b/source/fuzz/fuzzer_pass_wrap_vector_synonym.cpp
index 35adcfe..55fbe2c 100644
--- a/source/fuzz/fuzzer_pass_wrap_vector_synonym.cpp
+++ b/source/fuzz/fuzzer_pass_wrap_vector_synonym.cpp
@@ -52,7 +52,7 @@
         // It must be valid to insert an OpCompositeConstruct instruction
         // before |instruction_iterator|.
         if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
-                SpvOpCompositeConstruct, instruction_iterator)) {
+                spv::Op::OpCompositeConstruct, instruction_iterator)) {
           return;
         }
 
diff --git a/source/fuzz/fuzzer_util.cpp b/source/fuzz/fuzzer_util.cpp
index 1d368a9..e85ff2f 100644
--- a/source/fuzz/fuzzer_util.cpp
+++ b/source/fuzz/fuzzer_util.cpp
@@ -49,7 +49,7 @@
                             const std::vector<uint32_t>& words,
                             uint32_t type_id, bool is_irrelevant) {
   for (const auto& inst : ir_context->types_values()) {
-    if (inst.opcode() == SpvOpConstant && inst.type_id() == type_id &&
+    if (inst.opcode() == spv::Op::OpConstant && inst.type_id() == type_id &&
         inst.GetInOperand(0).words == words &&
         transformation_context.GetFactManager()->IdIsIrrelevant(
             inst.result_id()) == is_irrelevant) {
@@ -112,7 +112,7 @@
     // No instruction defining this id was found.
     return nullptr;
   }
-  if (inst->opcode() != SpvOpLabel) {
+  if (inst->opcode() != spv::Op::OpLabel) {
     // The instruction defining the id is not a label, so it cannot be a block
     // id.
     return nullptr;
@@ -138,7 +138,7 @@
   // makes sense here because we need to increment |phi_index| for each OpPhi
   // instruction.
   for (auto& inst : *bb_to) {
-    if (inst.opcode() != SpvOpPhi) {
+    if (inst.opcode() != spv::Op::OpPhi) {
       // The OpPhi instructions all occur at the start of the block; if we find
       // a non-OpPhi then we have seen them all.
       break;
@@ -189,24 +189,24 @@
   const auto* bb_from = MaybeFindBlock(ir_context, bb_from_id);
   assert(bb_from && "|bb_from_id| is invalid");
   assert(MaybeFindBlock(ir_context, bb_to_id) && "|bb_to_id| is invalid");
-  assert(bb_from->terminator()->opcode() == SpvOpBranch &&
+  assert(bb_from->terminator()->opcode() == spv::Op::OpBranch &&
          "Precondition on terminator of bb_from is not satisfied");
 
   // Get the id of the boolean constant to be used as the condition.
   auto condition_inst = ir_context->get_def_use_mgr()->GetDef(bool_id);
   assert(condition_inst &&
-         (condition_inst->opcode() == SpvOpConstantTrue ||
-          condition_inst->opcode() == SpvOpConstantFalse) &&
+         (condition_inst->opcode() == spv::Op::OpConstantTrue ||
+          condition_inst->opcode() == spv::Op::OpConstantFalse) &&
          "|bool_id| is invalid");
 
-  auto condition_value = condition_inst->opcode() == SpvOpConstantTrue;
+  auto condition_value = condition_inst->opcode() == spv::Op::OpConstantTrue;
   auto successor_id = bb_from->terminator()->GetSingleWordInOperand(0);
 
   // Add the dead branch, by turning OpBranch into OpBranchConditional, and
   // ordering the targets depending on whether the given boolean corresponds to
   // true or false.
   return opt::Instruction(
-      ir_context, SpvOpBranchConditional, 0, 0,
+      ir_context, spv::Op::OpBranchConditional, 0, 0,
       {{SPV_OPERAND_TYPE_ID, {bool_id}},
        {SPV_OPERAND_TYPE_ID, {condition_value ? successor_id : bb_to_id}},
        {SPV_OPERAND_TYPE_ID, {condition_value ? bb_to_id : successor_id}}});
@@ -228,7 +228,7 @@
   if (!from_to_edge_already_exists) {
     uint32_t phi_index = 0;
     for (auto& inst : *bb_to) {
-      if (inst.opcode() != SpvOpPhi) {
+      if (inst.opcode() != spv::Op::OpPhi) {
         break;
       }
       assert(phi_index < static_cast<uint32_t>(phi_ids.size()) &&
@@ -285,28 +285,30 @@
 }
 
 bool CanInsertOpcodeBeforeInstruction(
-    SpvOp opcode, const opt::BasicBlock::iterator& instruction_in_block) {
+    spv::Op opcode, const opt::BasicBlock::iterator& instruction_in_block) {
   if (instruction_in_block->PreviousNode() &&
-      (instruction_in_block->PreviousNode()->opcode() == SpvOpLoopMerge ||
-       instruction_in_block->PreviousNode()->opcode() == SpvOpSelectionMerge)) {
+      (instruction_in_block->PreviousNode()->opcode() == spv::Op::OpLoopMerge ||
+       instruction_in_block->PreviousNode()->opcode() ==
+           spv::Op::OpSelectionMerge)) {
     // We cannot insert directly after a merge instruction.
     return false;
   }
-  if (opcode != SpvOpVariable &&
-      instruction_in_block->opcode() == SpvOpVariable) {
+  if (opcode != spv::Op::OpVariable &&
+      instruction_in_block->opcode() == spv::Op::OpVariable) {
     // We cannot insert a non-OpVariable instruction directly before a
     // variable; variables in a function must be contiguous in the entry block.
     return false;
   }
   // We cannot insert a non-OpPhi instruction directly before an OpPhi, because
   // OpPhi instructions need to be contiguous at the start of a block.
-  return opcode == SpvOpPhi || instruction_in_block->opcode() != SpvOpPhi;
+  return opcode == spv::Op::OpPhi ||
+         instruction_in_block->opcode() != spv::Op::OpPhi;
 }
 
 bool CanMakeSynonymOf(opt::IRContext* ir_context,
                       const TransformationContext& transformation_context,
                       const opt::Instruction& inst) {
-  if (inst.opcode() == SpvOpSampledImage) {
+  if (inst.opcode() == spv::Op::OpSampledImage) {
     // The SPIR-V data rules say that only very specific instructions may
     // may consume the result id of an OpSampledImage, and this excludes the
     // instructions that are used for making synonyms.
@@ -326,15 +328,15 @@
     return false;
   }
   auto type_inst = ir_context->get_def_use_mgr()->GetDef(inst.type_id());
-  if (type_inst->opcode() == SpvOpTypeVoid) {
+  if (type_inst->opcode() == spv::Op::OpTypeVoid) {
     // We only make synonyms of instructions that define objects, and an object
     // cannot have void type.
     return false;
   }
-  if (type_inst->opcode() == SpvOpTypePointer) {
+  if (type_inst->opcode() == spv::Op::OpTypePointer) {
     switch (inst.opcode()) {
-      case SpvOpConstantNull:
-      case SpvOpUndef:
+      case spv::Op::OpConstantNull:
+      case spv::Op::OpUndef:
         // We disallow making synonyms of null or undefined pointers.  This is
         // to provide the property that if the original shader exhibited no bad
         // pointer accesses, the transformed shader will not either.
@@ -373,22 +375,22 @@
       context->get_def_use_mgr()->GetDef(base_object_type_id);
   assert(should_be_composite_type && "The type should exist.");
   switch (should_be_composite_type->opcode()) {
-    case SpvOpTypeArray: {
+    case spv::Op::OpTypeArray: {
       auto array_length = GetArraySize(*should_be_composite_type, context);
       if (array_length == 0 || index >= array_length) {
         return 0;
       }
       return should_be_composite_type->GetSingleWordInOperand(0);
     }
-    case SpvOpTypeMatrix:
-    case SpvOpTypeVector: {
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeVector: {
       auto count = should_be_composite_type->GetSingleWordInOperand(1);
       if (index >= count) {
         return 0;
       }
       return should_be_composite_type->GetSingleWordInOperand(0);
     }
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       if (index >= GetNumberOfStructMembers(*should_be_composite_type)) {
         return 0;
       }
@@ -415,7 +417,7 @@
 
 uint32_t GetNumberOfStructMembers(
     const opt::Instruction& struct_type_instruction) {
-  assert(struct_type_instruction.opcode() == SpvOpTypeStruct &&
+  assert(struct_type_instruction.opcode() == spv::Op::OpTypeStruct &&
          "An OpTypeStruct instruction is required here.");
   return struct_type_instruction.NumInOperands();
 }
@@ -436,15 +438,15 @@
 uint32_t GetBoundForCompositeIndex(const opt::Instruction& composite_type_inst,
                                    opt::IRContext* ir_context) {
   switch (composite_type_inst.opcode()) {
-    case SpvOpTypeArray:
+    case spv::Op::OpTypeArray:
       return fuzzerutil::GetArraySize(composite_type_inst, ir_context);
-    case SpvOpTypeMatrix:
-    case SpvOpTypeVector:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeVector:
       return composite_type_inst.GetSingleWordInOperand(1);
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       return fuzzerutil::GetNumberOfStructMembers(composite_type_inst);
     }
-    case SpvOpTypeRuntimeArray:
+    case spv::Op::OpTypeRuntimeArray:
       assert(false &&
              "GetBoundForCompositeIndex should not be invoked with an "
              "OpTypeRuntimeArray, which does not have a static bound.");
@@ -455,27 +457,27 @@
   }
 }
 
-SpvMemorySemanticsMask GetMemorySemanticsForStorageClass(
-    SpvStorageClass storage_class) {
+spv::MemorySemanticsMask GetMemorySemanticsForStorageClass(
+    spv::StorageClass storage_class) {
   switch (storage_class) {
-    case SpvStorageClassWorkgroup:
-      return SpvMemorySemanticsWorkgroupMemoryMask;
+    case spv::StorageClass::Workgroup:
+      return spv::MemorySemanticsMask::WorkgroupMemory;
 
-    case SpvStorageClassStorageBuffer:
-    case SpvStorageClassPhysicalStorageBuffer:
-      return SpvMemorySemanticsUniformMemoryMask;
+    case spv::StorageClass::StorageBuffer:
+    case spv::StorageClass::PhysicalStorageBuffer:
+      return spv::MemorySemanticsMask::UniformMemory;
 
-    case SpvStorageClassCrossWorkgroup:
-      return SpvMemorySemanticsCrossWorkgroupMemoryMask;
+    case spv::StorageClass::CrossWorkgroup:
+      return spv::MemorySemanticsMask::CrossWorkgroupMemory;
 
-    case SpvStorageClassAtomicCounter:
-      return SpvMemorySemanticsAtomicCounterMemoryMask;
+    case spv::StorageClass::AtomicCounter:
+      return spv::MemorySemanticsMask::AtomicCounterMemory;
 
-    case SpvStorageClassImage:
-      return SpvMemorySemanticsImageMemoryMask;
+    case spv::StorageClass::Image:
+      return spv::MemorySemanticsMask::ImageMemory;
 
     default:
-      return SpvMemorySemanticsMaskNone;
+      return spv::MemorySemanticsMask::MaskNone;
   }
 }
 
@@ -562,8 +564,8 @@
       [&result](const opt::Instruction* use_instruction,
                 uint32_t /*unused*/) -> bool {
         switch (use_instruction->opcode()) {
-          case SpvOpLoopMerge:
-          case SpvOpSelectionMerge:
+          case spv::Op::OpLoopMerge:
+          case spv::Op::OpSelectionMerge:
             result = true;
             return false;
           default:
@@ -581,7 +583,7 @@
       [ir_context, &result](opt::Instruction* use_instruction,
                             uint32_t use_index) -> bool {
         switch (use_instruction->opcode()) {
-          case SpvOpLoopMerge:
+          case spv::Op::OpLoopMerge:
             // The merge block operand is the first operand in OpLoopMerge.
             if (use_index == 0) {
               result = ir_context->get_instr_block(use_instruction)->id();
@@ -599,7 +601,7 @@
                           const std::vector<uint32_t>& type_ids) {
   // Look through the existing types for a match.
   for (auto& type_or_value : ir_context->types_values()) {
-    if (type_or_value.opcode() != SpvOpTypeFunction) {
+    if (type_or_value.opcode() != spv::Op::OpTypeFunction) {
       // We are only interested in function types.
       continue;
     }
@@ -641,8 +643,8 @@
 
 bool FunctionContainsOpKillOrUnreachable(const opt::Function& function) {
   for (auto& block : function) {
-    if (block.terminator()->opcode() == SpvOpKill ||
-        block.terminator()->opcode() == SpvOpUnreachable) {
+    if (block.terminator()->opcode() == spv::Op::OpKill ||
+        block.terminator()->opcode() == spv::Op::OpUnreachable) {
       return true;
     }
   }
@@ -669,7 +671,7 @@
       context->get_instr_block(use_instruction)->GetParent();
   // If the id a function parameter, it needs to be associated with the
   // function containing the use.
-  if (defining_instruction->opcode() == SpvOpFunctionParameter) {
+  if (defining_instruction->opcode() == spv::Op::OpFunctionParameter) {
     return InstructionIsFunctionParameter(defining_instruction,
                                           enclosing_function);
   }
@@ -687,7 +689,7 @@
     return false;
   }
   auto dominator_analysis = context->GetDominatorAnalysis(enclosing_function);
-  if (use_instruction->opcode() == SpvOpPhi) {
+  if (use_instruction->opcode() == spv::Op::OpPhi) {
     // In the case where the use is an operand to OpPhi, it is actually the
     // *parent* block associated with the operand that must be dominated by
     // the synonym.
@@ -710,7 +712,7 @@
       context->get_instr_block(instruction)->GetParent();
   // If the id a function parameter, it needs to be associated with the
   // function containing the instruction.
-  if (id_definition->opcode() == SpvOpFunctionParameter) {
+  if (id_definition->opcode() == spv::Op::OpFunctionParameter) {
     return InstructionIsFunctionParameter(id_definition,
                                           function_enclosing_instruction);
   }
@@ -732,7 +734,7 @@
     // the instruction.
     return true;
   }
-  if (id_definition->opcode() == SpvOpVariable &&
+  if (id_definition->opcode() == spv::Op::OpVariable &&
       function_enclosing_instruction ==
           context->get_instr_block(id)->GetParent()) {
     assert(!context->IsReachable(*context->get_instr_block(instruction)) &&
@@ -747,7 +749,7 @@
 
 bool InstructionIsFunctionParameter(opt::Instruction* instruction,
                                     opt::Function* function) {
-  if (instruction->opcode() != SpvOpFunctionParameter) {
+  if (instruction->opcode() != spv::Op::OpFunctionParameter) {
     return false;
   }
   bool found_parameter = false;
@@ -767,7 +769,8 @@
 }
 
 uint32_t GetPointeeTypeIdFromPointerType(opt::Instruction* pointer_type_inst) {
-  assert(pointer_type_inst && pointer_type_inst->opcode() == SpvOpTypePointer &&
+  assert(pointer_type_inst &&
+         pointer_type_inst->opcode() == spv::Op::OpTypePointer &&
          "Precondition: |pointer_type_inst| must be OpTypePointer.");
   return pointer_type_inst->GetSingleWordInOperand(1);
 }
@@ -778,26 +781,28 @@
       context->get_def_use_mgr()->GetDef(pointer_type_id));
 }
 
-SpvStorageClass GetStorageClassFromPointerType(
+spv::StorageClass GetStorageClassFromPointerType(
     opt::Instruction* pointer_type_inst) {
-  assert(pointer_type_inst && pointer_type_inst->opcode() == SpvOpTypePointer &&
+  assert(pointer_type_inst &&
+         pointer_type_inst->opcode() == spv::Op::OpTypePointer &&
          "Precondition: |pointer_type_inst| must be OpTypePointer.");
-  return static_cast<SpvStorageClass>(
+  return static_cast<spv::StorageClass>(
       pointer_type_inst->GetSingleWordInOperand(0));
 }
 
-SpvStorageClass GetStorageClassFromPointerType(opt::IRContext* context,
-                                               uint32_t pointer_type_id) {
+spv::StorageClass GetStorageClassFromPointerType(opt::IRContext* context,
+                                                 uint32_t pointer_type_id) {
   return GetStorageClassFromPointerType(
       context->get_def_use_mgr()->GetDef(pointer_type_id));
 }
 
 uint32_t MaybeGetPointerType(opt::IRContext* context, uint32_t pointee_type_id,
-                             SpvStorageClass storage_class) {
+                             spv::StorageClass storage_class) {
   for (auto& inst : context->types_values()) {
     switch (inst.opcode()) {
-      case SpvOpTypePointer:
-        if (inst.GetSingleWordInOperand(0) == storage_class &&
+      case spv::Op::OpTypePointer:
+        if (spv::StorageClass(inst.GetSingleWordInOperand(0)) ==
+                storage_class &&
             inst.GetSingleWordInOperand(1) == pointee_type_id) {
           return inst.result_id();
         }
@@ -818,30 +823,30 @@
 bool IsNullConstantSupported(opt::IRContext* ir_context,
                              const opt::Instruction& type_inst) {
   switch (type_inst.opcode()) {
-    case SpvOpTypeArray:
-    case SpvOpTypeBool:
-    case SpvOpTypeDeviceEvent:
-    case SpvOpTypeEvent:
-    case SpvOpTypeFloat:
-    case SpvOpTypeInt:
-    case SpvOpTypeMatrix:
-    case SpvOpTypeQueue:
-    case SpvOpTypeReserveId:
-    case SpvOpTypeVector:
-    case SpvOpTypeStruct:
+    case spv::Op::OpTypeArray:
+    case spv::Op::OpTypeBool:
+    case spv::Op::OpTypeDeviceEvent:
+    case spv::Op::OpTypeEvent:
+    case spv::Op::OpTypeFloat:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeQueue:
+    case spv::Op::OpTypeReserveId:
+    case spv::Op::OpTypeVector:
+    case spv::Op::OpTypeStruct:
       return true;
-    case SpvOpTypePointer:
+    case spv::Op::OpTypePointer:
       // Null pointers are allowed if the VariablePointers capability is
       // enabled, or if the VariablePointersStorageBuffer capability is enabled
       // and the pointer type has StorageBuffer as its storage class.
       if (ir_context->get_feature_mgr()->HasCapability(
-              SpvCapabilityVariablePointers)) {
+              spv::Capability::VariablePointers)) {
         return true;
       }
       if (ir_context->get_feature_mgr()->HasCapability(
-              SpvCapabilityVariablePointersStorageBuffer)) {
-        return type_inst.GetSingleWordInOperand(0) ==
-               SpvStorageClassStorageBuffer;
+              spv::Capability::VariablePointersStorageBuffer)) {
+        return spv::StorageClass(type_inst.GetSingleWordInOperand(0)) ==
+               spv::StorageClass::StorageBuffer;
       }
       return false;
     default:
@@ -885,22 +890,22 @@
 
 opt::Instruction* AddGlobalVariable(opt::IRContext* context, uint32_t result_id,
                                     uint32_t type_id,
-                                    SpvStorageClass storage_class,
+                                    spv::StorageClass storage_class,
                                     uint32_t initializer_id) {
   // Check various preconditions.
   assert(result_id != 0 && "Result id can't be 0");
 
-  assert((storage_class == SpvStorageClassPrivate ||
-          storage_class == SpvStorageClassWorkgroup) &&
+  assert((storage_class == spv::StorageClass::Private ||
+          storage_class == spv::StorageClass::Workgroup) &&
          "Variable's storage class must be either Private or Workgroup");
 
   auto* type_inst = context->get_def_use_mgr()->GetDef(type_id);
   (void)type_inst;  // Variable becomes unused in release mode.
-  assert(type_inst && type_inst->opcode() == SpvOpTypePointer &&
+  assert(type_inst && type_inst->opcode() == spv::Op::OpTypePointer &&
          GetStorageClassFromPointerType(type_inst) == storage_class &&
          "Variable's type is invalid");
 
-  if (storage_class == SpvStorageClassWorkgroup) {
+  if (storage_class == spv::StorageClass::Workgroup) {
     assert(initializer_id == 0);
   }
 
@@ -922,7 +927,7 @@
   }
 
   auto new_instruction = MakeUnique<opt::Instruction>(
-      context, SpvOpVariable, type_id, result_id, std::move(operands));
+      context, spv::Op::OpVariable, type_id, result_id, std::move(operands));
   auto result = new_instruction.get();
   context->module()->AddGlobalValue(std::move(new_instruction));
 
@@ -940,8 +945,9 @@
 
   auto* type_inst = context->get_def_use_mgr()->GetDef(type_id);
   (void)type_inst;  // Variable becomes unused in release mode.
-  assert(type_inst && type_inst->opcode() == SpvOpTypePointer &&
-         GetStorageClassFromPointerType(type_inst) == SpvStorageClassFunction &&
+  assert(type_inst && type_inst->opcode() == spv::Op::OpTypePointer &&
+         GetStorageClassFromPointerType(type_inst) ==
+             spv::StorageClass::Function &&
          "Variable's type is invalid");
 
   const auto* constant_inst =
@@ -956,10 +962,10 @@
   assert(function && "Function id is invalid");
 
   auto new_instruction = MakeUnique<opt::Instruction>(
-      context, SpvOpVariable, type_id, result_id,
-      opt::Instruction::OperandList{
-          {SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}},
-          {SPV_OPERAND_TYPE_ID, {initializer_id}}});
+      context, spv::Op::OpVariable, type_id, result_id,
+      opt::Instruction::OperandList{{SPV_OPERAND_TYPE_STORAGE_CLASS,
+                                     {uint32_t(spv::StorageClass::Function)}},
+                                    {SPV_OPERAND_TYPE_ID, {initializer_id}}});
   auto result = new_instruction.get();
   function->begin()->begin()->InsertBefore(std::move(new_instruction));
 
@@ -1022,7 +1028,7 @@
   std::vector<opt::Instruction*> result;
   ir_context->get_def_use_mgr()->ForEachUser(
       function_id, [&result, function_id](opt::Instruction* inst) {
-        if (inst->opcode() == SpvOpFunctionCall &&
+        if (inst->opcode() == spv::Op::OpFunctionCall &&
             inst->GetSingleWordInOperand(0) == function_id) {
           result.push_back(inst);
         }
@@ -1137,7 +1143,7 @@
   }
 
   ir_context->AddType(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpTypeFunction, 0, result_id, std::move(operands)));
+      ir_context, spv::Op::OpTypeFunction, 0, result_id, std::move(operands)));
 
   UpdateModuleIdBound(ir_context, result_id);
 }
@@ -1186,7 +1192,7 @@
 uint32_t MaybeGetStructType(opt::IRContext* ir_context,
                             const std::vector<uint32_t>& component_type_ids) {
   for (auto& type_or_value : ir_context->types_values()) {
-    if (type_or_value.opcode() != SpvOpTypeStruct ||
+    if (type_or_value.opcode() != spv::Op::OpTypeStruct ||
         type_or_value.NumInOperands() !=
             static_cast<uint32_t>(component_type_ids.size())) {
       continue;
@@ -1219,11 +1225,11 @@
   assert(type_inst && "|scalar_or_composite_type_id| is invalid");
 
   switch (type_inst->opcode()) {
-    case SpvOpTypeBool:
+    case spv::Op::OpTypeBool:
       return MaybeGetBoolConstant(ir_context, transformation_context, false,
                                   is_irrelevant);
-    case SpvOpTypeFloat:
-    case SpvOpTypeInt: {
+    case spv::Op::OpTypeFloat:
+    case spv::Op::OpTypeInt: {
       const auto width = type_inst->GetSingleWordInOperand(0);
       std::vector<uint32_t> words = {0};
       if (width > 32) {
@@ -1233,7 +1239,7 @@
       return MaybeGetScalarConstant(ir_context, transformation_context, words,
                                     scalar_or_composite_type_id, is_irrelevant);
     }
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       std::vector<uint32_t> component_ids;
       for (uint32_t i = 0; i < type_inst->NumInOperands(); ++i) {
         const auto component_type_id = type_inst->GetSingleWordInOperand(i);
@@ -1260,8 +1266,8 @@
           ir_context, transformation_context, component_ids,
           scalar_or_composite_type_id, is_irrelevant);
     }
-    case SpvOpTypeMatrix:
-    case SpvOpTypeVector: {
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeVector: {
       const auto component_type_id = type_inst->GetSingleWordInOperand(0);
 
       auto component_id = MaybeGetZeroConstant(
@@ -1284,7 +1290,7 @@
           std::vector<uint32_t>(component_count, component_id),
           scalar_or_composite_type_id, is_irrelevant);
     }
-    case SpvOpTypeArray: {
+    case spv::Op::OpTypeArray: {
       const auto component_type_id = type_inst->GetSingleWordInOperand(0);
 
       auto component_id = MaybeGetZeroConstant(
@@ -1319,16 +1325,16 @@
   assert(spvOpcodeGeneratesType(type_instr->opcode()) &&
          "A type-generating opcode was expected.");
   switch (type_instr->opcode()) {
-    case SpvOpTypeBool:
-    case SpvOpTypeInt:
-    case SpvOpTypeFloat:
-    case SpvOpTypeMatrix:
-    case SpvOpTypeVector:
+    case spv::Op::OpTypeBool:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeFloat:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeVector:
       return true;
-    case SpvOpTypeArray:
+    case spv::Op::OpTypeArray:
       return CanCreateConstant(ir_context,
                                type_instr->GetSingleWordInOperand(0));
-    case SpvOpTypeStruct:
+    case spv::Op::OpTypeStruct:
       if (HasBlockOrBufferBlockDecoration(ir_context, type_id)) {
         return false;
       }
@@ -1377,7 +1383,7 @@
   assert(IsCompositeType(type) && "|composite_type_id| is invalid");
 
   for (const auto& inst : ir_context->types_values()) {
-    if (inst.opcode() == SpvOpConstantComposite &&
+    if (inst.opcode() == spv::Op::OpConstantComposite &&
         inst.type_id() == composite_type_id &&
         transformation_context.GetFactManager()->IdIsIrrelevant(
             inst.result_id()) == is_irrelevant &&
@@ -1457,7 +1463,8 @@
     bool is_irrelevant) {
   if (auto type_id = MaybeGetBoolType(ir_context)) {
     for (const auto& inst : ir_context->types_values()) {
-      if (inst.opcode() == (value ? SpvOpConstantTrue : SpvOpConstantFalse) &&
+      if (inst.opcode() ==
+              (value ? spv::Op::OpConstantTrue : spv::Op::OpConstantFalse) &&
           inst.type_id() == type_id &&
           transformation_context.GetFactManager()->IdIsIrrelevant(
               inst.result_id()) == is_irrelevant) {
@@ -1552,13 +1559,13 @@
 
 opt::Instruction* GetLastInsertBeforeInstruction(opt::IRContext* ir_context,
                                                  uint32_t block_id,
-                                                 SpvOp opcode) {
+                                                 spv::Op opcode) {
   // CFG::block uses std::map::at which throws an exception when |block_id| is
   // invalid. The error message is unhelpful, though. Thus, we test that
   // |block_id| is valid here.
   const auto* label_inst = ir_context->get_def_use_mgr()->GetDef(block_id);
   (void)label_inst;  // Make compilers happy in release mode.
-  assert(label_inst && label_inst->opcode() == SpvOpLabel &&
+  assert(label_inst && label_inst->opcode() == spv::Op::OpLabel &&
          "|block_id| is invalid");
 
   auto* block = ir_context->cfg()->block(block_id);
@@ -1624,7 +1631,7 @@
         assert(composite_type_being_accessed->AsStruct());
         auto constant_index_instruction = ir_context->get_def_use_mgr()->GetDef(
             use_instruction->GetSingleWordInOperand(index_in_operand));
-        assert(constant_index_instruction->opcode() == SpvOpConstant);
+        assert(constant_index_instruction->opcode() == spv::Op::OpConstant);
         uint32_t member_index =
             constant_index_instruction->GetSingleWordInOperand(0);
         composite_type_being_accessed =
@@ -1641,7 +1648,7 @@
     }
   }
 
-  if (use_instruction->opcode() == SpvOpFunctionCall &&
+  if (use_instruction->opcode() == spv::Op::OpFunctionCall &&
       use_in_operand_index > 0) {
     // This is a function call argument.  It is not allowed to have pointer
     // type.
@@ -1663,7 +1670,7 @@
     }
   }
 
-  if (use_instruction->opcode() == SpvOpImageTexelPointer &&
+  if (use_instruction->opcode() == spv::Op::OpImageTexelPointer &&
       use_in_operand_index == 2) {
     // The OpImageTexelPointer instruction has a Sample parameter that in some
     // situations must be an id for the value 0.  To guard against disrupting
@@ -1671,38 +1678,38 @@
     return false;
   }
 
-  if (ir_context->get_feature_mgr()->HasCapability(SpvCapabilityShader)) {
+  if (ir_context->get_feature_mgr()->HasCapability(spv::Capability::Shader)) {
     // With the Shader capability, memory scope and memory semantics operands
     // are required to be constants, so they cannot be replaced arbitrarily.
     switch (use_instruction->opcode()) {
-      case SpvOpAtomicLoad:
-      case SpvOpAtomicStore:
-      case SpvOpAtomicExchange:
-      case SpvOpAtomicIIncrement:
-      case SpvOpAtomicIDecrement:
-      case SpvOpAtomicIAdd:
-      case SpvOpAtomicISub:
-      case SpvOpAtomicSMin:
-      case SpvOpAtomicUMin:
-      case SpvOpAtomicSMax:
-      case SpvOpAtomicUMax:
-      case SpvOpAtomicAnd:
-      case SpvOpAtomicOr:
-      case SpvOpAtomicXor:
+      case spv::Op::OpAtomicLoad:
+      case spv::Op::OpAtomicStore:
+      case spv::Op::OpAtomicExchange:
+      case spv::Op::OpAtomicIIncrement:
+      case spv::Op::OpAtomicIDecrement:
+      case spv::Op::OpAtomicIAdd:
+      case spv::Op::OpAtomicISub:
+      case spv::Op::OpAtomicSMin:
+      case spv::Op::OpAtomicUMin:
+      case spv::Op::OpAtomicSMax:
+      case spv::Op::OpAtomicUMax:
+      case spv::Op::OpAtomicAnd:
+      case spv::Op::OpAtomicOr:
+      case spv::Op::OpAtomicXor:
         if (use_in_operand_index == 1 || use_in_operand_index == 2) {
           return false;
         }
         break;
-      case SpvOpAtomicCompareExchange:
+      case spv::Op::OpAtomicCompareExchange:
         if (use_in_operand_index == 1 || use_in_operand_index == 2 ||
             use_in_operand_index == 3) {
           return false;
         }
         break;
-      case SpvOpAtomicCompareExchangeWeak:
-      case SpvOpAtomicFlagTestAndSet:
-      case SpvOpAtomicFlagClear:
-      case SpvOpAtomicFAddEXT:
+      case spv::Op::OpAtomicCompareExchangeWeak:
+      case spv::Op::OpAtomicFlagTestAndSet:
+      case spv::Op::OpAtomicFlagClear:
+      case spv::Op::OpAtomicFAddEXT:
         assert(false && "Not allowed with the Shader capability.");
       default:
         break;
@@ -1715,17 +1722,17 @@
 bool MembersHaveBuiltInDecoration(opt::IRContext* ir_context,
                                   uint32_t struct_type_id) {
   const auto* type_inst = ir_context->get_def_use_mgr()->GetDef(struct_type_id);
-  assert(type_inst && type_inst->opcode() == SpvOpTypeStruct &&
+  assert(type_inst && type_inst->opcode() == spv::Op::OpTypeStruct &&
          "|struct_type_id| is not a result id of an OpTypeStruct");
 
   uint32_t builtin_count = 0;
   ir_context->get_def_use_mgr()->ForEachUser(
       type_inst,
       [struct_type_id, &builtin_count](const opt::Instruction* user) {
-        if (user->opcode() == SpvOpMemberDecorate &&
+        if (user->opcode() == spv::Op::OpMemberDecorate &&
             user->GetSingleWordInOperand(0) == struct_type_id &&
-            static_cast<SpvDecoration>(user->GetSingleWordInOperand(2)) ==
-                SpvDecorationBuiltIn) {
+            static_cast<spv::Decoration>(user->GetSingleWordInOperand(2)) ==
+                spv::Decoration::BuiltIn) {
           ++builtin_count;
         }
       });
@@ -1738,9 +1745,11 @@
 }
 
 bool HasBlockOrBufferBlockDecoration(opt::IRContext* ir_context, uint32_t id) {
-  for (auto decoration : {SpvDecorationBlock, SpvDecorationBufferBlock}) {
+  for (auto decoration :
+       {spv::Decoration::Block, spv::Decoration::BufferBlock}) {
     if (!ir_context->get_decoration_mgr()->WhileEachDecoration(
-            id, decoration, [](const opt::Instruction & /*unused*/) -> bool {
+            id, uint32_t(decoration),
+            [](const opt::Instruction & /*unused*/) -> bool {
               return false;
             })) {
       return true;
@@ -1762,7 +1771,7 @@
     if (before_split) {
       // If the instruction comes before the split and its opcode is
       // OpSampledImage, record its result id.
-      if (instruction.opcode() == SpvOpSampledImage) {
+      if (instruction.opcode() == spv::Op::OpSampledImage) {
         sampled_image_result_ids.insert(instruction.result_id());
       }
     } else {
@@ -1784,110 +1793,110 @@
 
 bool InstructionHasNoSideEffects(const opt::Instruction& instruction) {
   switch (instruction.opcode()) {
-    case SpvOpUndef:
-    case SpvOpAccessChain:
-    case SpvOpInBoundsAccessChain:
-    case SpvOpArrayLength:
-    case SpvOpVectorExtractDynamic:
-    case SpvOpVectorInsertDynamic:
-    case SpvOpVectorShuffle:
-    case SpvOpCompositeConstruct:
-    case SpvOpCompositeExtract:
-    case SpvOpCompositeInsert:
-    case SpvOpCopyObject:
-    case SpvOpTranspose:
-    case SpvOpConvertFToU:
-    case SpvOpConvertFToS:
-    case SpvOpConvertSToF:
-    case SpvOpConvertUToF:
-    case SpvOpUConvert:
-    case SpvOpSConvert:
-    case SpvOpFConvert:
-    case SpvOpQuantizeToF16:
-    case SpvOpSatConvertSToU:
-    case SpvOpSatConvertUToS:
-    case SpvOpBitcast:
-    case SpvOpSNegate:
-    case SpvOpFNegate:
-    case SpvOpIAdd:
-    case SpvOpFAdd:
-    case SpvOpISub:
-    case SpvOpFSub:
-    case SpvOpIMul:
-    case SpvOpFMul:
-    case SpvOpUDiv:
-    case SpvOpSDiv:
-    case SpvOpFDiv:
-    case SpvOpUMod:
-    case SpvOpSRem:
-    case SpvOpSMod:
-    case SpvOpFRem:
-    case SpvOpFMod:
-    case SpvOpVectorTimesScalar:
-    case SpvOpMatrixTimesScalar:
-    case SpvOpVectorTimesMatrix:
-    case SpvOpMatrixTimesVector:
-    case SpvOpMatrixTimesMatrix:
-    case SpvOpOuterProduct:
-    case SpvOpDot:
-    case SpvOpIAddCarry:
-    case SpvOpISubBorrow:
-    case SpvOpUMulExtended:
-    case SpvOpSMulExtended:
-    case SpvOpAny:
-    case SpvOpAll:
-    case SpvOpIsNan:
-    case SpvOpIsInf:
-    case SpvOpIsFinite:
-    case SpvOpIsNormal:
-    case SpvOpSignBitSet:
-    case SpvOpLessOrGreater:
-    case SpvOpOrdered:
-    case SpvOpUnordered:
-    case SpvOpLogicalEqual:
-    case SpvOpLogicalNotEqual:
-    case SpvOpLogicalOr:
-    case SpvOpLogicalAnd:
-    case SpvOpLogicalNot:
-    case SpvOpSelect:
-    case SpvOpIEqual:
-    case SpvOpINotEqual:
-    case SpvOpUGreaterThan:
-    case SpvOpSGreaterThan:
-    case SpvOpUGreaterThanEqual:
-    case SpvOpSGreaterThanEqual:
-    case SpvOpULessThan:
-    case SpvOpSLessThan:
-    case SpvOpULessThanEqual:
-    case SpvOpSLessThanEqual:
-    case SpvOpFOrdEqual:
-    case SpvOpFUnordEqual:
-    case SpvOpFOrdNotEqual:
-    case SpvOpFUnordNotEqual:
-    case SpvOpFOrdLessThan:
-    case SpvOpFUnordLessThan:
-    case SpvOpFOrdGreaterThan:
-    case SpvOpFUnordGreaterThan:
-    case SpvOpFOrdLessThanEqual:
-    case SpvOpFUnordLessThanEqual:
-    case SpvOpFOrdGreaterThanEqual:
-    case SpvOpFUnordGreaterThanEqual:
-    case SpvOpShiftRightLogical:
-    case SpvOpShiftRightArithmetic:
-    case SpvOpShiftLeftLogical:
-    case SpvOpBitwiseOr:
-    case SpvOpBitwiseXor:
-    case SpvOpBitwiseAnd:
-    case SpvOpNot:
-    case SpvOpBitFieldInsert:
-    case SpvOpBitFieldSExtract:
-    case SpvOpBitFieldUExtract:
-    case SpvOpBitReverse:
-    case SpvOpBitCount:
-    case SpvOpCopyLogical:
-    case SpvOpPhi:
-    case SpvOpPtrEqual:
-    case SpvOpPtrNotEqual:
+    case spv::Op::OpUndef:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
+    case spv::Op::OpArrayLength:
+    case spv::Op::OpVectorExtractDynamic:
+    case spv::Op::OpVectorInsertDynamic:
+    case spv::Op::OpVectorShuffle:
+    case spv::Op::OpCompositeConstruct:
+    case spv::Op::OpCompositeExtract:
+    case spv::Op::OpCompositeInsert:
+    case spv::Op::OpCopyObject:
+    case spv::Op::OpTranspose:
+    case spv::Op::OpConvertFToU:
+    case spv::Op::OpConvertFToS:
+    case spv::Op::OpConvertSToF:
+    case spv::Op::OpConvertUToF:
+    case spv::Op::OpUConvert:
+    case spv::Op::OpSConvert:
+    case spv::Op::OpFConvert:
+    case spv::Op::OpQuantizeToF16:
+    case spv::Op::OpSatConvertSToU:
+    case spv::Op::OpSatConvertUToS:
+    case spv::Op::OpBitcast:
+    case spv::Op::OpSNegate:
+    case spv::Op::OpFNegate:
+    case spv::Op::OpIAdd:
+    case spv::Op::OpFAdd:
+    case spv::Op::OpISub:
+    case spv::Op::OpFSub:
+    case spv::Op::OpIMul:
+    case spv::Op::OpFMul:
+    case spv::Op::OpUDiv:
+    case spv::Op::OpSDiv:
+    case spv::Op::OpFDiv:
+    case spv::Op::OpUMod:
+    case spv::Op::OpSRem:
+    case spv::Op::OpSMod:
+    case spv::Op::OpFRem:
+    case spv::Op::OpFMod:
+    case spv::Op::OpVectorTimesScalar:
+    case spv::Op::OpMatrixTimesScalar:
+    case spv::Op::OpVectorTimesMatrix:
+    case spv::Op::OpMatrixTimesVector:
+    case spv::Op::OpMatrixTimesMatrix:
+    case spv::Op::OpOuterProduct:
+    case spv::Op::OpDot:
+    case spv::Op::OpIAddCarry:
+    case spv::Op::OpISubBorrow:
+    case spv::Op::OpUMulExtended:
+    case spv::Op::OpSMulExtended:
+    case spv::Op::OpAny:
+    case spv::Op::OpAll:
+    case spv::Op::OpIsNan:
+    case spv::Op::OpIsInf:
+    case spv::Op::OpIsFinite:
+    case spv::Op::OpIsNormal:
+    case spv::Op::OpSignBitSet:
+    case spv::Op::OpLessOrGreater:
+    case spv::Op::OpOrdered:
+    case spv::Op::OpUnordered:
+    case spv::Op::OpLogicalEqual:
+    case spv::Op::OpLogicalNotEqual:
+    case spv::Op::OpLogicalOr:
+    case spv::Op::OpLogicalAnd:
+    case spv::Op::OpLogicalNot:
+    case spv::Op::OpSelect:
+    case spv::Op::OpIEqual:
+    case spv::Op::OpINotEqual:
+    case spv::Op::OpUGreaterThan:
+    case spv::Op::OpSGreaterThan:
+    case spv::Op::OpUGreaterThanEqual:
+    case spv::Op::OpSGreaterThanEqual:
+    case spv::Op::OpULessThan:
+    case spv::Op::OpSLessThan:
+    case spv::Op::OpULessThanEqual:
+    case spv::Op::OpSLessThanEqual:
+    case spv::Op::OpFOrdEqual:
+    case spv::Op::OpFUnordEqual:
+    case spv::Op::OpFOrdNotEqual:
+    case spv::Op::OpFUnordNotEqual:
+    case spv::Op::OpFOrdLessThan:
+    case spv::Op::OpFUnordLessThan:
+    case spv::Op::OpFOrdGreaterThan:
+    case spv::Op::OpFUnordGreaterThan:
+    case spv::Op::OpFOrdLessThanEqual:
+    case spv::Op::OpFUnordLessThanEqual:
+    case spv::Op::OpFOrdGreaterThanEqual:
+    case spv::Op::OpFUnordGreaterThanEqual:
+    case spv::Op::OpShiftRightLogical:
+    case spv::Op::OpShiftRightArithmetic:
+    case spv::Op::OpShiftLeftLogical:
+    case spv::Op::OpBitwiseOr:
+    case spv::Op::OpBitwiseXor:
+    case spv::Op::OpBitwiseAnd:
+    case spv::Op::OpNot:
+    case spv::Op::OpBitFieldInsert:
+    case spv::Op::OpBitFieldSExtract:
+    case spv::Op::OpBitFieldUExtract:
+    case spv::Op::OpBitReverse:
+    case spv::Op::OpBitCount:
+    case spv::Op::OpCopyLogical:
+    case spv::Op::OpPhi:
+    case spv::Op::OpPtrEqual:
+    case spv::Op::OpPtrNotEqual:
       return true;
     default:
       return false;
@@ -1975,7 +1984,7 @@
 
     for (const auto& inst : block) {
       for (uint32_t i = 0; i < inst.NumInOperands();
-           i += inst.opcode() == SpvOpPhi ? 2 : 1) {
+           i += inst.opcode() == spv::Op::OpPhi ? 2 : 1) {
         const auto& operand = inst.GetInOperand(i);
         if (!spvIsInIdType(operand.type)) {
           continue;
@@ -1994,7 +2003,7 @@
           continue;
         }
 
-        auto domination_target_id = inst.opcode() == SpvOpPhi
+        auto domination_target_id = inst.opcode() == spv::Op::OpPhi
                                         ? inst.GetSingleWordInOperand(i + 1)
                                         : block.id();
 
@@ -2021,68 +2030,68 @@
 // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3582): Add all
 //  opcodes that are agnostic to signedness of operands to function.
 //  This is not exhaustive yet.
-bool IsAgnosticToSignednessOfOperand(SpvOp opcode,
+bool IsAgnosticToSignednessOfOperand(spv::Op opcode,
                                      uint32_t use_in_operand_index) {
   switch (opcode) {
-    case SpvOpSNegate:
-    case SpvOpNot:
-    case SpvOpIAdd:
-    case SpvOpISub:
-    case SpvOpIMul:
-    case SpvOpSDiv:
-    case SpvOpSRem:
-    case SpvOpSMod:
-    case SpvOpShiftRightLogical:
-    case SpvOpShiftRightArithmetic:
-    case SpvOpShiftLeftLogical:
-    case SpvOpBitwiseOr:
-    case SpvOpBitwiseXor:
-    case SpvOpBitwiseAnd:
-    case SpvOpIEqual:
-    case SpvOpINotEqual:
-    case SpvOpULessThan:
-    case SpvOpSLessThan:
-    case SpvOpUGreaterThan:
-    case SpvOpSGreaterThan:
-    case SpvOpULessThanEqual:
-    case SpvOpSLessThanEqual:
-    case SpvOpUGreaterThanEqual:
-    case SpvOpSGreaterThanEqual:
+    case spv::Op::OpSNegate:
+    case spv::Op::OpNot:
+    case spv::Op::OpIAdd:
+    case spv::Op::OpISub:
+    case spv::Op::OpIMul:
+    case spv::Op::OpSDiv:
+    case spv::Op::OpSRem:
+    case spv::Op::OpSMod:
+    case spv::Op::OpShiftRightLogical:
+    case spv::Op::OpShiftRightArithmetic:
+    case spv::Op::OpShiftLeftLogical:
+    case spv::Op::OpBitwiseOr:
+    case spv::Op::OpBitwiseXor:
+    case spv::Op::OpBitwiseAnd:
+    case spv::Op::OpIEqual:
+    case spv::Op::OpINotEqual:
+    case spv::Op::OpULessThan:
+    case spv::Op::OpSLessThan:
+    case spv::Op::OpUGreaterThan:
+    case spv::Op::OpSGreaterThan:
+    case spv::Op::OpULessThanEqual:
+    case spv::Op::OpSLessThanEqual:
+    case spv::Op::OpUGreaterThanEqual:
+    case spv::Op::OpSGreaterThanEqual:
       return true;
 
-    case SpvOpAtomicStore:
-    case SpvOpAtomicExchange:
-    case SpvOpAtomicIAdd:
-    case SpvOpAtomicISub:
-    case SpvOpAtomicSMin:
-    case SpvOpAtomicUMin:
-    case SpvOpAtomicSMax:
-    case SpvOpAtomicUMax:
-    case SpvOpAtomicAnd:
-    case SpvOpAtomicOr:
-    case SpvOpAtomicXor:
-    case SpvOpAtomicFAddEXT:  // Capability AtomicFloat32AddEXT,
+    case spv::Op::OpAtomicStore:
+    case spv::Op::OpAtomicExchange:
+    case spv::Op::OpAtomicIAdd:
+    case spv::Op::OpAtomicISub:
+    case spv::Op::OpAtomicSMin:
+    case spv::Op::OpAtomicUMin:
+    case spv::Op::OpAtomicSMax:
+    case spv::Op::OpAtomicUMax:
+    case spv::Op::OpAtomicAnd:
+    case spv::Op::OpAtomicOr:
+    case spv::Op::OpAtomicXor:
+    case spv::Op::OpAtomicFAddEXT:  // Capability AtomicFloat32AddEXT,
       // AtomicFloat64AddEXT.
       assert(use_in_operand_index != 0 &&
              "Signedness check should not occur on a pointer operand.");
       return use_in_operand_index == 1 || use_in_operand_index == 2;
 
-    case SpvOpAtomicCompareExchange:
-    case SpvOpAtomicCompareExchangeWeak:  // Capability Kernel.
+    case spv::Op::OpAtomicCompareExchange:
+    case spv::Op::OpAtomicCompareExchangeWeak:  // Capability Kernel.
       assert(use_in_operand_index != 0 &&
              "Signedness check should not occur on a pointer operand.");
       return use_in_operand_index >= 1 && use_in_operand_index <= 3;
 
-    case SpvOpAtomicLoad:
-    case SpvOpAtomicIIncrement:
-    case SpvOpAtomicIDecrement:
-    case SpvOpAtomicFlagTestAndSet:  // Capability Kernel.
-    case SpvOpAtomicFlagClear:       // Capability Kernel.
+    case spv::Op::OpAtomicLoad:
+    case spv::Op::OpAtomicIIncrement:
+    case spv::Op::OpAtomicIDecrement:
+    case spv::Op::OpAtomicFlagTestAndSet:  // Capability Kernel.
+    case spv::Op::OpAtomicFlagClear:       // Capability Kernel.
       assert(use_in_operand_index != 0 &&
              "Signedness check should not occur on a pointer operand.");
       return use_in_operand_index >= 1;
 
-    case SpvOpAccessChain:
+    case spv::Op::OpAccessChain:
       // The signedness of indices does not matter.
       return use_in_operand_index > 0;
 
@@ -2093,7 +2102,7 @@
   }
 }
 
-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 type_id_2) {
   assert(ir_context->get_type_mgr()->GetType(type_id_1) &&
diff --git a/source/fuzz/fuzzer_util.h b/source/fuzz/fuzzer_util.h
index 54aa14a..374e32e 100644
--- a/source/fuzz/fuzzer_util.h
+++ b/source/fuzz/fuzzer_util.h
@@ -111,7 +111,7 @@
 // Determines whether it is OK to insert an instruction with opcode |opcode|
 // before |instruction_in_block|.
 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|.
 // |transformation_context| is used to verify that the result id of |inst|
@@ -170,8 +170,8 @@
                                    opt::IRContext* ir_context);
 
 // Returns memory semantics mask for specific storage class.
-SpvMemorySemanticsMask GetMemorySemanticsForStorageClass(
-    SpvStorageClass storage_class);
+spv::MemorySemanticsMask GetMemorySemanticsForStorageClass(
+    spv::StorageClass storage_class);
 
 // Returns true if and only if |context| is valid, according to the validator
 // instantiated with |validator_options|.  |consumer| is used for error
@@ -258,18 +258,18 @@
 
 // Given |pointer_type_inst|, which must be an OpTypePointer instruction,
 // returns the associated storage class.
-SpvStorageClass GetStorageClassFromPointerType(
+spv::StorageClass GetStorageClassFromPointerType(
     opt::Instruction* pointer_type_inst);
 
 // Given |pointer_type_id|, which must be the id of a pointer type, returns the
 // associated storage class.
-SpvStorageClass GetStorageClassFromPointerType(opt::IRContext* context,
-                                               uint32_t pointer_type_id);
+spv::StorageClass GetStorageClassFromPointerType(opt::IRContext* context,
+                                                 uint32_t pointer_type_id);
 
 // Returns the id of a pointer with pointee type |pointee_type_id| and storage
 // class |storage_class|, if it exists, and 0 otherwise.
 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|,
 // returns the index of the operand restricted to the input operands.
@@ -309,7 +309,7 @@
 // Returns a pointer to the new global variable instruction.
 opt::Instruction* AddGlobalVariable(opt::IRContext* context, uint32_t result_id,
                                     uint32_t type_id,
-                                    SpvStorageClass storage_class,
+                                    spv::StorageClass storage_class,
                                     uint32_t initializer_id);
 
 // Adds an instruction to the start of |function_id|, of the form:
@@ -541,7 +541,7 @@
 // opcode |opcode| can be inserted, or nullptr if there is no such instruction.
 opt::Instruction* GetLastInsertBeforeInstruction(opt::IRContext* ir_context,
                                                  uint32_t block_id,
-                                                 SpvOp opcode);
+                                                 spv::Op opcode);
 
 // Checks whether various conditions hold related to the acceptability of
 // replacing the id use at |use_in_operand_index| of |use_instruction| with a
@@ -608,14 +608,14 @@
 // behaviour depending on the signedness of the operand at
 // |use_in_operand_index|.
 // 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);
 
 // 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
 // an operand of |opcode| of the first type with an id of the second type
 // 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 type_id_2);
 
diff --git a/source/fuzz/instruction_descriptor.cpp b/source/fuzz/instruction_descriptor.cpp
index fb1ff76..120d8f8 100644
--- a/source/fuzz/instruction_descriptor.cpp
+++ b/source/fuzz/instruction_descriptor.cpp
@@ -40,8 +40,9 @@
              "The skipped instruction count should only be incremented "
              "after the instruction base has been found.");
     }
-    if (found_base && instruction.opcode() ==
-                          instruction_descriptor.target_instruction_opcode()) {
+    if (found_base &&
+        instruction.opcode() ==
+            spv::Op(instruction_descriptor.target_instruction_opcode())) {
       if (num_ignored == instruction_descriptor.num_opcodes_to_ignore()) {
         return &instruction;
       }
@@ -52,11 +53,11 @@
 }
 
 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) {
   protobufs::InstructionDescriptor result;
   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);
   return result;
 }
@@ -64,7 +65,7 @@
 protobufs::InstructionDescriptor MakeInstructionDescriptor(
     const opt::BasicBlock& block,
     const opt::BasicBlock::const_iterator& inst_it) {
-  const SpvOp opcode =
+  const spv::Op opcode =
       inst_it->opcode();    // The opcode of the instruction being described.
   uint32_t skip_count = 0;  // The number of these opcodes we have skipped when
   // searching backwards.
diff --git a/source/fuzz/instruction_descriptor.h b/source/fuzz/instruction_descriptor.h
index 2ccd15a..063cad4 100644
--- a/source/fuzz/instruction_descriptor.h
+++ b/source/fuzz/instruction_descriptor.h
@@ -32,7 +32,7 @@
 // components.  See the protobuf definition for details of what these
 // components mean.
 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);
 
 // Returns an instruction descriptor that describing the instruction at
diff --git a/source/fuzz/instruction_message.cpp b/source/fuzz/instruction_message.cpp
index 9503932..7e8ac71 100644
--- a/source/fuzz/instruction_message.cpp
+++ b/source/fuzz/instruction_message.cpp
@@ -20,10 +20,10 @@
 namespace fuzz {
 
 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) {
   protobufs::Instruction result;
-  result.set_opcode(opcode);
+  result.set_opcode(uint32_t(opcode));
   result.set_result_type_id(result_type_id);
   result.set_result_id(result_id);
   for (auto& operand : input_operands) {
@@ -71,7 +71,7 @@
   }
   // Create and return the 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(),
       in_operands);
 }
diff --git a/source/fuzz/instruction_message.h b/source/fuzz/instruction_message.h
index fcbb4c7..e1312f4 100644
--- a/source/fuzz/instruction_message.h
+++ b/source/fuzz/instruction_message.h
@@ -26,7 +26,7 @@
 
 // Creates an Instruction protobuf message from its component parts.
 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);
 
 // Creates an Instruction protobuf message from a parsed instruction.
diff --git a/source/fuzz/transformation_access_chain.cpp b/source/fuzz/transformation_access_chain.cpp
index 3fe9e65..1e7f87b 100644
--- a/source/fuzz/transformation_access_chain.cpp
+++ b/source/fuzz/transformation_access_chain.cpp
@@ -63,7 +63,7 @@
   }
   // The type must indeed be a pointer.
   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;
   }
 
@@ -75,7 +75,7 @@
     return false;
   }
   if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
-          SpvOpAccessChain, instruction_to_insert_before)) {
+          spv::Op::OpAccessChain, instruction_to_insert_before)) {
     return false;
   }
 
@@ -83,8 +83,8 @@
   // we do not want to allow accessing such pointers.  This might be acceptable
   // in dead blocks, but we conservatively avoid it.
   switch (pointer->opcode()) {
-    case SpvOpConstantNull:
-    case SpvOpUndef:
+    case spv::Op::OpConstantNull:
+    case spv::Op::OpUndef:
       assert(
           false &&
           "Access chains should not be created from null/undefined pointers");
@@ -117,7 +117,7 @@
 
     // Check whether the object is a struct.
     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.
 
       bool successful;
@@ -202,7 +202,7 @@
   // associated with pointers to isomorphic structs being regarded as the same.
   return fuzzerutil::MaybeGetPointerType(
              ir_context, subobject_type_id,
-             static_cast<SpvStorageClass>(
+             static_cast<spv::StorageClass>(
                  pointer_type->GetSingleWordInOperand(0))) != 0;
 }
 
@@ -243,7 +243,7 @@
 
     // Check whether the object is a struct.
     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.
 
       index_value =
@@ -290,7 +290,8 @@
       //   %fresh_ids.first = OpULessThanEqual %bool %int_id %bound_minus_one.
       fuzzerutil::UpdateModuleIdBound(ir_context, fresh_ids.first());
       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(
               {{SPV_OPERAND_TYPE_ID, {index_instruction->result_id()}},
                {SPV_OPERAND_TYPE_ID, {bound_minus_one_id}}}));
@@ -306,7 +307,7 @@
       //                           %bound_minus_one
       fuzzerutil::UpdateModuleIdBound(ir_context, fresh_ids.second());
       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(),
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID, {fresh_ids.first()}},
@@ -334,13 +335,14 @@
   // of the original pointer.
   uint32_t result_type = fuzzerutil::MaybeGetPointerType(
       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
   // id bound.
   fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
-  auto access_chain_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpAccessChain, result_type, message_.fresh_id(), operands);
+  auto access_chain_instruction =
+      MakeUnique<opt::Instruction>(ir_context, spv::Op::OpAccessChain,
+                                   result_type, message_.fresh_id(), operands);
   auto access_chain_instruction_ptr = access_chain_instruction.get();
   instruction_to_insert_before->InsertBefore(
       std::move(access_chain_instruction));
@@ -367,7 +369,7 @@
     opt::IRContext* ir_context, uint32_t index_id,
     uint32_t object_type_id) const {
   assert(ir_context->get_def_use_mgr()->GetDef(object_type_id)->opcode() ==
-             SpvOpTypeStruct &&
+             spv::Op::OpTypeStruct &&
          "Precondition: the type must be a struct type.");
   if (!ValidIndexToComposite(ir_context, index_id, object_type_id)) {
     return {false, 0};
@@ -408,14 +410,14 @@
   // The index type must be 32-bit integer.
   auto index_type =
       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) {
     return false;
   }
 
   // If the object being traversed is a struct, the id must correspond to an
   // in-bound constant.
-  if (object_type_def->opcode() == SpvOpTypeStruct) {
+  if (object_type_def->opcode() == spv::Op::OpTypeStruct) {
     if (!spvOpcodeIsConstant(index_instruction->opcode())) {
       return false;
     }
diff --git a/source/fuzz/transformation_add_bit_instruction_synonym.cpp b/source/fuzz/transformation_add_bit_instruction_synonym.cpp
index 636c0a3..4b26c2b 100644
--- a/source/fuzz/transformation_add_bit_instruction_synonym.cpp
+++ b/source/fuzz/transformation_add_bit_instruction_synonym.cpp
@@ -87,10 +87,10 @@
   // synonym fact.  The helper function should take care of invalidating
   // analyses before adding facts.
   switch (bit_instruction->opcode()) {
-    case SpvOpBitwiseOr:
-    case SpvOpBitwiseXor:
-    case SpvOpBitwiseAnd:
-    case SpvOpNot:
+    case spv::Op::OpBitwiseOr:
+    case spv::Op::OpBitwiseXor:
+    case spv::Op::OpBitwiseAnd:
+    case spv::Op::OpNot:
       AddOpBitwiseOrOpNotSynonym(ir_context, transformation_context,
                                  bit_instruction);
       break;
@@ -106,10 +106,10 @@
   //  Right now we only support certain operations. When this issue is addressed
   //  the following conditional can use the function |spvOpcodeIsBit|.
   // |instruction| must be defined and must be a supported bit instruction.
-  if (!instruction || (instruction->opcode() != SpvOpBitwiseOr &&
-                       instruction->opcode() != SpvOpBitwiseXor &&
-                       instruction->opcode() != SpvOpBitwiseAnd &&
-                       instruction->opcode() != SpvOpNot)) {
+  if (!instruction || (instruction->opcode() != spv::Op::OpBitwiseOr &&
+                       instruction->opcode() != spv::Op::OpBitwiseXor &&
+                       instruction->opcode() != spv::Op::OpBitwiseAnd &&
+                       instruction->opcode() != spv::Op::OpNot)) {
     return false;
   }
 
@@ -119,7 +119,7 @@
     return false;
   }
 
-  if (instruction->opcode() == SpvOpNot) {
+  if (instruction->opcode() == spv::Op::OpNot) {
     auto operand = instruction->GetInOperand(0).words[0];
     auto operand_inst = ir_context->get_def_use_mgr()->GetDef(operand);
     auto operand_type =
@@ -171,10 +171,10 @@
   // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3557):
   //  Right now, only certain operations are supported.
   switch (bit_instruction->opcode()) {
-    case SpvOpBitwiseOr:
-    case SpvOpBitwiseXor:
-    case SpvOpBitwiseAnd:
-    case SpvOpNot:
+    case spv::Op::OpBitwiseOr:
+    case spv::Op::OpBitwiseXor:
+    case spv::Op::OpBitwiseAnd:
+    case spv::Op::OpNot:
       return (2 + bit_instruction->NumInOperands()) *
                  ir_context->get_type_mgr()
                      ->GetType(bit_instruction->type_id())
@@ -220,7 +220,7 @@
     for (auto operand = bit_instruction->begin() + 2;
          operand != bit_instruction->end(); operand++) {
       auto bit_extract =
-          opt::Instruction(ir_context, SpvOpBitFieldUExtract,
+          opt::Instruction(ir_context, spv::Op::OpBitFieldUExtract,
                            bit_instruction->type_id(), *fresh_id++,
                            {{SPV_OPERAND_TYPE_ID, operand->words},
                             {SPV_OPERAND_TYPE_ID, {offset}},
@@ -246,12 +246,13 @@
   // first two bits of the result.
   uint32_t offset = fuzzerutil::MaybeGetIntegerConstant(
       ir_context, *transformation_context, {1}, 32, false, false);
-  auto bit_insert = opt::Instruction(
-      ir_context, SpvOpBitFieldInsert, bit_instruction->type_id(), *fresh_id++,
-      {{SPV_OPERAND_TYPE_ID, {extracted_bit_instructions[0]}},
-       {SPV_OPERAND_TYPE_ID, {extracted_bit_instructions[1]}},
-       {SPV_OPERAND_TYPE_ID, {offset}},
-       {SPV_OPERAND_TYPE_ID, {count}}});
+  auto bit_insert =
+      opt::Instruction(ir_context, spv::Op::OpBitFieldInsert,
+                       bit_instruction->type_id(), *fresh_id++,
+                       {{SPV_OPERAND_TYPE_ID, {extracted_bit_instructions[0]}},
+                        {SPV_OPERAND_TYPE_ID, {extracted_bit_instructions[1]}},
+                        {SPV_OPERAND_TYPE_ID, {offset}},
+                        {SPV_OPERAND_TYPE_ID, {count}}});
   bit_instruction->InsertBefore(MakeUnique<opt::Instruction>(bit_insert));
   fuzzerutil::UpdateModuleIdBound(ir_context, bit_insert.result_id());
 
@@ -260,7 +261,7 @@
     offset = fuzzerutil::MaybeGetIntegerConstant(
         ir_context, *transformation_context, {i}, 32, false, false);
     bit_insert = opt::Instruction(
-        ir_context, SpvOpBitFieldInsert, bit_instruction->type_id(),
+        ir_context, spv::Op::OpBitFieldInsert, bit_instruction->type_id(),
         *fresh_id++,
         {{SPV_OPERAND_TYPE_ID, {bit_insert.result_id()}},
          {SPV_OPERAND_TYPE_ID, {extracted_bit_instructions[i]}},
diff --git a/source/fuzz/transformation_add_constant_boolean.cpp b/source/fuzz/transformation_add_constant_boolean.cpp
index 3935432..89c2e57 100644
--- a/source/fuzz/transformation_add_constant_boolean.cpp
+++ b/source/fuzz/transformation_add_constant_boolean.cpp
@@ -43,7 +43,8 @@
   // Add the boolean constant to the module, ensuring the module's id bound is
   // high enough.
   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(),
       opt::Instruction::OperandList());
   auto new_instruction_ptr = new_instruction.get();
diff --git a/source/fuzz/transformation_add_constant_composite.cpp b/source/fuzz/transformation_add_constant_composite.cpp
index 89007ab..b8ee8be 100644
--- a/source/fuzz/transformation_add_constant_composite.cpp
+++ b/source/fuzz/transformation_add_constant_composite.cpp
@@ -53,7 +53,7 @@
   // struct - whether its decorations are OK.
   std::vector<uint32_t> constituent_type_ids;
   switch (composite_type_instruction->opcode()) {
-    case SpvOpTypeArray:
+    case spv::Op::OpTypeArray:
       for (uint32_t index = 0;
            index <
            fuzzerutil::GetArraySize(*composite_type_instruction, ir_context);
@@ -62,8 +62,8 @@
             composite_type_instruction->GetSingleWordInOperand(0));
       }
       break;
-    case SpvOpTypeMatrix:
-    case SpvOpTypeVector:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeVector:
       for (uint32_t index = 0;
            index < composite_type_instruction->GetSingleWordInOperand(1);
            index++) {
@@ -71,7 +71,7 @@
             composite_type_instruction->GetSingleWordInOperand(0));
       }
       break;
-    case SpvOpTypeStruct:
+    case spv::Op::OpTypeStruct:
       // We do not create constants of structs decorated with Block nor
       // 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
@@ -120,7 +120,7 @@
     in_operands.push_back({SPV_OPERAND_TYPE_ID, {constituent_id}});
   }
   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);
   auto new_instruction_ptr = new_instruction.get();
   ir_context->module()->AddGlobalValue(std::move(new_instruction));
diff --git a/source/fuzz/transformation_add_constant_null.cpp b/source/fuzz/transformation_add_constant_null.cpp
index c0f7367..7b83bae 100644
--- a/source/fuzz/transformation_add_constant_null.cpp
+++ b/source/fuzz/transformation_add_constant_null.cpp
@@ -48,8 +48,8 @@
 void TransformationAddConstantNull::Apply(
     opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   auto new_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpConstantNull, message_.type_id(), message_.fresh_id(),
-      opt::Instruction::OperandList());
+      ir_context, spv::Op::OpConstantNull, message_.type_id(),
+      message_.fresh_id(), opt::Instruction::OperandList());
   auto new_instruction_ptr = new_instruction.get();
   ir_context->module()->AddGlobalValue(std::move(new_instruction));
   fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
diff --git a/source/fuzz/transformation_add_constant_scalar.cpp b/source/fuzz/transformation_add_constant_scalar.cpp
index a2d95fb..45989d4 100644
--- a/source/fuzz/transformation_add_constant_scalar.cpp
+++ b/source/fuzz/transformation_add_constant_scalar.cpp
@@ -65,7 +65,7 @@
     opt::IRContext* ir_context,
     TransformationContext* transformation_context) const {
   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(
           {{SPV_OPERAND_TYPE_LITERAL_INTEGER,
             std::vector<uint32_t>(message_.word().begin(),
diff --git a/source/fuzz/transformation_add_copy_memory.cpp b/source/fuzz/transformation_add_copy_memory.cpp
index 5eb4bdc..9d1f325 100644
--- a/source/fuzz/transformation_add_copy_memory.cpp
+++ b/source/fuzz/transformation_add_copy_memory.cpp
@@ -27,12 +27,12 @@
 
 TransformationAddCopyMemory::TransformationAddCopyMemory(
     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) {
   *message_.mutable_instruction_descriptor() = instruction_descriptor;
   message_.set_fresh_id(fresh_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);
 }
 
@@ -53,7 +53,8 @@
   // Check that we can insert OpCopyMemory before |instruction_descriptor|.
   auto iter = fuzzerutil::GetIteratorForInstruction(
       ir_context->get_instr_block(inst), inst);
-  if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpCopyMemory, iter)) {
+  if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpCopyMemory,
+                                                    iter)) {
     return false;
   }
 
@@ -65,8 +66,10 @@
   }
 
   // |storage_class| is either Function or Private.
-  if (message_.storage_class() != SpvStorageClassFunction &&
-      message_.storage_class() != SpvStorageClassPrivate) {
+  if (spv::StorageClass(message_.storage_class()) !=
+          spv::StorageClass::Function &&
+      spv::StorageClass(message_.storage_class()) !=
+          spv::StorageClass::Private) {
     return false;
   }
 
@@ -76,7 +79,7 @@
   // OpTypePointer with |message_.storage_class| exists.
   if (!fuzzerutil::MaybeGetPointerType(
           ir_context, pointee_type_id,
-          static_cast<SpvStorageClass>(message_.storage_class()))) {
+          static_cast<spv::StorageClass>(message_.storage_class()))) {
     return false;
   }
 
@@ -103,20 +106,20 @@
       ir_context->get_instr_block(insert_before_inst);
 
   // 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(
       ir_context,
       fuzzerutil::GetPointeeTypeIdFromPointerType(
           ir_context, fuzzerutil::GetTypeId(ir_context, message_.source_id())),
       storage_class);
 
-  if (storage_class == SpvStorageClassPrivate) {
+  if (storage_class == spv::StorageClass::Private) {
     opt::Instruction* new_global =
         fuzzerutil::AddGlobalVariable(ir_context, message_.fresh_id(), type_id,
                                       storage_class, message_.initializer_id());
     ir_context->get_def_use_mgr()->AnalyzeInstDefUse(new_global);
   } else {
-    assert(storage_class == SpvStorageClassFunction &&
+    assert(storage_class == spv::StorageClass::Function &&
            "Storage class can be either Private or Function");
     opt::Function* enclosing_function = enclosing_block->GetParent();
     opt::Instruction* new_local = fuzzerutil::AddLocalVariable(
@@ -130,7 +133,7 @@
       enclosing_block, insert_before_inst);
 
   auto new_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpCopyMemory, 0, 0,
+      ir_context, spv::Op::OpCopyMemory, 0, 0,
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {message_.fresh_id()}},
           {SPV_OPERAND_TYPE_ID, {message_.source_id()}}});
@@ -160,7 +163,8 @@
 bool TransformationAddCopyMemory::IsInstructionSupported(
     opt::IRContext* ir_context, opt::Instruction* inst) {
   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;
   }
 
diff --git a/source/fuzz/transformation_add_copy_memory.h b/source/fuzz/transformation_add_copy_memory.h
index b25652f..053b629 100644
--- a/source/fuzz/transformation_add_copy_memory.h
+++ b/source/fuzz/transformation_add_copy_memory.h
@@ -30,7 +30,7 @@
 
   TransformationAddCopyMemory(
       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);
 
   // - |instruction_descriptor| must point to a valid instruction in the module.
diff --git a/source/fuzz/transformation_add_dead_block.cpp b/source/fuzz/transformation_add_dead_block.cpp
index df700ce..930adc1 100644
--- a/source/fuzz/transformation_add_dead_block.cpp
+++ b/source/fuzz/transformation_add_dead_block.cpp
@@ -61,7 +61,7 @@
   }
 
   // It must end with OpBranch.
-  if (existing_block->terminator()->opcode() != SpvOpBranch) {
+  if (existing_block->terminator()->opcode() != spv::Op::OpBranch) {
     return false;
   }
 
@@ -122,27 +122,27 @@
   auto enclosing_function = existing_block->GetParent();
   std::unique_ptr<opt::BasicBlock> new_block =
       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()));
   new_block->AddInstruction(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpBranch, 0, 0,
+      ir_context, spv::Op::OpBranch, 0, 0,
       opt::Instruction::OperandList(
           {{SPV_OPERAND_TYPE_ID, {successor_block_id}}})));
 
   // Turn the original block into a selection merge, with its original successor
   // as the merge block.
   existing_block->terminator()->InsertBefore(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpSelectionMerge, 0, 0,
+      ir_context, spv::Op::OpSelectionMerge, 0, 0,
       opt::Instruction::OperandList(
           {{SPV_OPERAND_TYPE_ID, {successor_block_id}},
            {SPV_OPERAND_TYPE_SELECTION_CONTROL,
-            {SpvSelectionControlMaskNone}}})));
+            {uint32_t(spv::SelectionControlMask::MaskNone)}}})));
 
   // 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
   // targets, and such that at runtime control will always transfer to the
   // original successor.
-  existing_block->terminator()->SetOpcode(SpvOpBranchConditional);
+  existing_block->terminator()->SetOpcode(spv::Op::OpBranchConditional);
   existing_block->terminator()->SetInOperands(
       {{SPV_OPERAND_TYPE_ID, {bool_id}},
        {SPV_OPERAND_TYPE_ID,
diff --git a/source/fuzz/transformation_add_dead_break.cpp b/source/fuzz/transformation_add_dead_break.cpp
index 32080ca..07ed4dc 100644
--- a/source/fuzz/transformation_add_dead_break.cpp
+++ b/source/fuzz/transformation_add_dead_break.cpp
@@ -142,7 +142,7 @@
   }
 
   // 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
     // branch.
     return false;
diff --git a/source/fuzz/transformation_add_dead_continue.cpp b/source/fuzz/transformation_add_dead_continue.cpp
index f2b9ab3..c534801 100644
--- a/source/fuzz/transformation_add_dead_continue.cpp
+++ b/source/fuzz/transformation_add_dead_continue.cpp
@@ -55,7 +55,7 @@
   }
 
   // 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
     // branch.
     return false;
diff --git a/source/fuzz/transformation_add_early_terminator_wrapper.cpp b/source/fuzz/transformation_add_early_terminator_wrapper.cpp
index 547398a..28e0186 100644
--- a/source/fuzz/transformation_add_early_terminator_wrapper.cpp
+++ b/source/fuzz/transformation_add_early_terminator_wrapper.cpp
@@ -28,17 +28,17 @@
 TransformationAddEarlyTerminatorWrapper::
     TransformationAddEarlyTerminatorWrapper(uint32_t function_fresh_id,
                                             uint32_t label_fresh_id,
-                                            SpvOp opcode) {
+                                            spv::Op opcode) {
   message_.set_function_fresh_id(function_fresh_id);
   message_.set_label_fresh_id(label_fresh_id);
-  message_.set_opcode(opcode);
+  message_.set_opcode(uint32_t(opcode));
 }
 
 bool TransformationAddEarlyTerminatorWrapper::IsApplicable(
     opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
-  assert((message_.opcode() == SpvOpKill ||
-          message_.opcode() == SpvOpUnreachable ||
-          message_.opcode() == SpvOpTerminateInvocation) &&
+  assert((spv::Op(message_.opcode()) == spv::Op::OpKill ||
+          spv::Op(message_.opcode()) == spv::Op::OpUnreachable ||
+          spv::Op(message_.opcode()) == spv::Op::OpTerminateInvocation) &&
          "Invalid opcode.");
 
   if (!fuzzerutil::IsFreshId(ir_context, message_.function_fresh_id())) {
@@ -66,26 +66,29 @@
   // %label_fresh_id = OpLabel
   //                   OpKill|Unreachable|TerminateInvocation
   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()));
   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()));
 
   // Create a zero-argument void function.
   auto void_type_id = fuzzerutil::MaybeGetVoidType(ir_context);
   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(
-          {{SPV_OPERAND_TYPE_FUNCTION_CONTROL, {SpvFunctionControlMaskNone}},
+          {{SPV_OPERAND_TYPE_FUNCTION_CONTROL,
+            {uint32_t(spv::FunctionControlMask::MaskNone)}},
            {SPV_OPERAND_TYPE_TYPE_ID,
             {fuzzerutil::FindFunctionType(ir_context, {void_type_id})}}})));
 
   // Add the basic block to the function as the sole block, and add the function
   // to the module.
   function->AddBasicBlock(std::move(basic_block));
-  function->SetFunctionEnd(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpFunctionEnd, 0, 0, opt::Instruction::OperandList()));
+  function->SetFunctionEnd(
+      MakeUnique<opt::Instruction>(ir_context, spv::Op::OpFunctionEnd, 0, 0,
+                                   opt::Instruction::OperandList()));
   ir_context->module()->AddFunction(std::move(function));
 
   ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
diff --git a/source/fuzz/transformation_add_early_terminator_wrapper.h b/source/fuzz/transformation_add_early_terminator_wrapper.h
index 97cc527..5d0201d 100644
--- a/source/fuzz/transformation_add_early_terminator_wrapper.h
+++ b/source/fuzz/transformation_add_early_terminator_wrapper.h
@@ -30,7 +30,7 @@
 
   TransformationAddEarlyTerminatorWrapper(uint32_t function_fresh_id,
                                           uint32_t label_fresh_id,
-                                          SpvOp opcode);
+                                          spv::Op opcode);
 
   // - |message_.function_fresh_id| and |message_.label_fresh_id| must be fresh
   //   and distinct.
diff --git a/source/fuzz/transformation_add_function.cpp b/source/fuzz/transformation_add_function.cpp
index 06cd657..1f61ede 100644
--- a/source/fuzz/transformation_add_function.cpp
+++ b/source/fuzz/transformation_add_function.cpp
@@ -178,7 +178,7 @@
   }
   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 "
          "OpFunction.");
 
@@ -189,7 +189,7 @@
   } else {
     // Inform the fact manager that all blocks in the function are dead.
     for (auto& inst : message_.instruction()) {
-      if (inst.opcode() == SpvOpLabel) {
+      if (spv::Op(inst.opcode()) == spv::Op::OpLabel) {
         transformation_context->GetFactManager()->AddFactBlockIsDead(
             inst.result_id());
       }
@@ -202,16 +202,16 @@
   // parameters to other functions knowing that it is OK if they get
   // over-written.
   for (auto& instruction : message_.instruction()) {
-    switch (instruction.opcode()) {
-      case SpvOpFunctionParameter:
+    switch (spv::Op(instruction.opcode())) {
+      case spv::Op::OpFunctionParameter:
         if (ir_context->get_def_use_mgr()
                 ->GetDef(instruction.result_type_id())
-                ->opcode() == SpvOpTypePointer) {
+                ->opcode() == spv::Op::OpTypePointer) {
           transformation_context->GetFactManager()
               ->AddFactValueOfPointeeIsIrrelevant(instruction.result_id());
         }
         break;
-      case SpvOpVariable:
+      case spv::Op::OpVariable:
         transformation_context->GetFactManager()
             ->AddFactValueOfPointeeIsIrrelevant(instruction.result_id());
         break;
@@ -239,7 +239,7 @@
 
   // A function must start with OpFunction.
   auto function_begin = message_.instruction(0);
-  if (function_begin.opcode() != SpvOpFunction) {
+  if (spv::Op(function_begin.opcode()) != spv::Op::OpFunction) {
     return false;
   }
 
@@ -256,8 +256,8 @@
   // Iterate through all function parameter instructions, adding parameters to
   // the new function.
   while (instruction_index < num_instructions &&
-         message_.instruction(instruction_index).opcode() ==
-             SpvOpFunctionParameter) {
+         spv::Op(message_.instruction(instruction_index).opcode()) ==
+             spv::Op::OpFunctionParameter) {
     new_function->AddParameter(InstructionFromMessage(
         ir_context, message_.instruction(instruction_index)));
     instruction_index++;
@@ -265,16 +265,19 @@
 
   // After the parameters, there needs to be a label.
   if (instruction_index == num_instructions ||
-      message_.instruction(instruction_index).opcode() != SpvOpLabel) {
+      spv::Op(message_.instruction(instruction_index).opcode()) !=
+          spv::Op::OpLabel) {
     return false;
   }
 
   // Iterate through the instructions block by block until the end of the
   // function is reached.
   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.
-    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.
     std::unique_ptr<opt::BasicBlock> block =
@@ -285,9 +288,10 @@
     // of the function, adding each such instruction to the block.
     instruction_index++;
     while (instruction_index < num_instructions &&
-           message_.instruction(instruction_index).opcode() !=
-               SpvOpFunctionEnd &&
-           message_.instruction(instruction_index).opcode() != SpvOpLabel) {
+           spv::Op(message_.instruction(instruction_index).opcode()) !=
+               spv::Op::OpFunctionEnd &&
+           spv::Op(message_.instruction(instruction_index).opcode()) !=
+               spv::Op::OpLabel) {
       block->AddInstruction(InstructionFromMessage(
           ir_context, message_.instruction(instruction_index)));
       instruction_index++;
@@ -298,7 +302,8 @@
   // Having considered all the blocks, we should be at the last instruction and
   // it needs to be OpFunctionEnd.
   if (instruction_index != num_instructions - 1 ||
-      message_.instruction(instruction_index).opcode() != SpvOpFunctionEnd) {
+      spv::Op(message_.instruction(instruction_index).opcode()) !=
+          spv::Op::OpFunctionEnd) {
     return false;
   }
   // Set the function's final instruction, add the function to the module and
@@ -339,20 +344,20 @@
   for (auto& block : *added_function) {
     for (auto& inst : block) {
       switch (inst.opcode()) {
-        case SpvOpKill:
-        case SpvOpUnreachable:
+        case spv::Op::OpKill:
+        case spv::Op::OpUnreachable:
           if (!TryToTurnKillOrUnreachableIntoReturn(ir_context, added_function,
                                                     &inst)) {
             return false;
           }
           break;
-        case SpvOpAccessChain:
-        case SpvOpInBoundsAccessChain:
+        case spv::Op::OpAccessChain:
+        case spv::Op::OpInBoundsAccessChain:
           if (!TryToClampAccessChainIndices(ir_context, &inst)) {
             return false;
           }
           break;
-        case SpvOpFunctionCall:
+        case spv::Op::OpFunctionCall:
           // A livesafe function my only call other livesafe functions.
           if (!transformation_context.GetFactManager()->FunctionIsLivesafe(
                   inst.GetSingleWordInOperand(0))) {
@@ -404,7 +409,7 @@
   auto loop_limit_constant_id_instr =
       ir_context->get_def_use_mgr()->GetDef(message_.loop_limit_constant_id());
   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
     // appropriate opcode.
     return false;
@@ -412,7 +417,7 @@
 
   auto loop_limit_type = ir_context->get_def_use_mgr()->GetDef(
       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) {
     // The type of the loop limit constant must be 32-bit integer.  It
     // doesn't actually matter whether the integer is signed or not.
@@ -457,7 +462,7 @@
 
   // Look for 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 =
       ir_context->get_type_mgr()->GetId(&pointer_to_unsigned_int_type);
   if (!pointer_to_unsigned_int_type_id) {
@@ -477,13 +482,13 @@
 
   // Declare the loop limiter variable at the start of the function's entry
   // 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>(
-      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(),
-      opt::Instruction::OperandList(
-          {{SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}},
-           {SPV_OPERAND_TYPE_ID, {zero_id}}})));
+      opt::Instruction::OperandList({{SPV_OPERAND_TYPE_STORAGE_CLASS,
+                                      {uint32_t(spv::StorageClass::Function)}},
+                                     {SPV_OPERAND_TYPE_ID, {zero_id}}})));
   // Update the module's id bound since we have added the loop limiter
   // variable id.
   fuzzerutil::UpdateModuleIdBound(ir_context,
@@ -589,10 +594,11 @@
     auto back_edge_block = ir_context->cfg()->block(back_edge_block_id);
     auto back_edge_block_terminator = back_edge_block->terminator();
     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;
     } else {
-      assert(back_edge_block_terminator->opcode() == SpvOpBranchConditional);
+      assert(back_edge_block_terminator->opcode() ==
+             spv::Op::OpBranchConditional);
       assert(((back_edge_block_terminator->GetSingleWordInOperand(1) ==
                    loop_header->id() &&
                back_edge_block_terminator->GetSingleWordInOperand(2) ==
@@ -613,7 +619,7 @@
     // Add a load from the loop limiter variable, of the form:
     //   %t1 = OpLoad %uint32 %loop_limiter
     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(),
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {message_.loop_limiter_variable_id()}}})));
@@ -621,7 +627,7 @@
     // Increment the loaded value:
     //   %t2 = OpIAdd %uint32 %t1 %one
     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(),
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {loop_limiter_info.load_id()}},
@@ -630,7 +636,7 @@
     // Store the incremented value back to the loop limiter variable:
     //   OpStore %loop_limiter %t2
     new_instructions.push_back(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpStore, 0, 0,
+        ir_context, spv::Op::OpStore, 0, 0,
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {message_.loop_limiter_variable_id()}},
              {SPV_OPERAND_TYPE_ID, {loop_limiter_info.increment_id()}}})));
@@ -641,17 +647,18 @@
     //   %t3 = OpULessThan %bool %t1 %loop_limit
     new_instructions.push_back(MakeUnique<opt::Instruction>(
         ir_context,
-        compare_using_greater_than_equal ? SpvOpUGreaterThanEqual
-                                         : SpvOpULessThan,
+        compare_using_greater_than_equal ? spv::Op::OpUGreaterThanEqual
+                                         : spv::Op::OpULessThan,
         bool_type_id, loop_limiter_info.compare_id(),
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {loop_limiter_info.load_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>(
           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(),
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID,
@@ -669,11 +676,11 @@
       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(
           0, {loop_limiter_info.logical_op_id()});
     } 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");
 
       // Check that, if the merge block starts with OpPhi instructions, suitable
@@ -689,7 +696,7 @@
       // Augment OpPhi instructions at the loop merge with the given ids.
       uint32_t phi_index = 0;
       for (auto& inst : *merge_block) {
-        if (inst.opcode() != SpvOpPhi) {
+        if (inst.opcode() != spv::Op::OpPhi) {
           break;
         }
         assert(phi_index <
@@ -702,7 +709,7 @@
       }
 
       // 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(
           {{SPV_OPERAND_TYPE_ID, {loop_limiter_info.compare_id()}},
            {SPV_OPERAND_TYPE_ID, {loop_header->MergeBlockId()}},
@@ -724,18 +731,18 @@
 bool TransformationAddFunction::TryToTurnKillOrUnreachableIntoReturn(
     opt::IRContext* ir_context, opt::Function* added_function,
     opt::Instruction* kill_or_unreachable_inst) const {
-  assert((kill_or_unreachable_inst->opcode() == SpvOpKill ||
-          kill_or_unreachable_inst->opcode() == SpvOpUnreachable) &&
+  assert((kill_or_unreachable_inst->opcode() == spv::Op::OpKill ||
+          kill_or_unreachable_inst->opcode() == spv::Op::OpUnreachable) &&
          "Precondition: instruction must be OpKill or OpUnreachable.");
 
   // Get the function's return type.
   auto function_return_type_inst =
       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
     // OpReturn.
-    kill_or_unreachable_inst->SetOpcode(SpvOpReturn);
+    kill_or_unreachable_inst->SetOpcode(spv::Op::OpReturn);
   } else {
     // The function has non-void return type, so change this instruction
     // to OpReturnValue, using the value id provided with the
@@ -749,7 +756,7 @@
             ->type_id() != function_return_type_inst->result_id()) {
       return false;
     }
-    kill_or_unreachable_inst->SetOpcode(SpvOpReturnValue);
+    kill_or_unreachable_inst->SetOpcode(spv::Op::OpReturnValue);
     kill_or_unreachable_inst->SetInOperands(
         {{SPV_OPERAND_TYPE_ID, {message_.kill_unreachable_return_value_id()}}});
   }
@@ -758,8 +765,8 @@
 
 bool TransformationAddFunction::TryToClampAccessChainIndices(
     opt::IRContext* ir_context, opt::Instruction* access_chain_inst) const {
-  assert((access_chain_inst->opcode() == SpvOpAccessChain ||
-          access_chain_inst->opcode() == SpvOpInBoundsAccessChain) &&
+  assert((access_chain_inst->opcode() == spv::Op::OpAccessChain ||
+          access_chain_inst->opcode() == spv::Op::OpInBoundsAccessChain) &&
          "Precondition: instruction must be OpAccessChain or "
          "OpInBoundsAccessChain.");
 
@@ -793,7 +800,7 @@
   assert(base_object && "The base object must exist.");
   auto pointer_type =
       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.");
   auto should_be_composite_type = ir_context->get_def_use_mgr()->GetDef(
       pointer_type->GetSingleWordInOperand(1));
@@ -824,18 +831,18 @@
     auto index_inst = ir_context->get_def_use_mgr()->GetDef(index_id);
     auto index_type_inst =
         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);
     opt::analysis::Integer* index_int_type =
         ir_context->get_type_mgr()
             ->GetType(index_type_inst->result_id())
             ->AsInteger();
 
-    if (index_inst->opcode() != SpvOpConstant ||
+    if (index_inst->opcode() != spv::Op::OpConstant ||
         index_inst->GetSingleWordInOperand(0) >= bound) {
       // The index is either non-constant or an out-of-bounds constant, so we
       // 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 "
              "constants.");
       opt::analysis::IntConstant bound_minus_one(index_int_type, {bound - 1});
@@ -866,7 +873,7 @@
       // Compare the index with the bound via an instruction of the form:
       //   %t1 = OpULessThanEqual %bool %index %bound_minus_one
       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(
               {{SPV_OPERAND_TYPE_ID, {index_inst->result_id()}},
                {SPV_OPERAND_TYPE_ID, {bound_minus_one_id}}})));
@@ -874,7 +881,8 @@
       // Select the index if in-bounds, otherwise one less than the bound:
       //   %t2 = OpSelect %int_type %t1 %index %bound_minus_one
       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(
               {{SPV_OPERAND_TYPE_ID, {compare_id}},
                {SPV_OPERAND_TYPE_ID, {index_inst->result_id()}},
@@ -899,20 +907,20 @@
     uint32_t index_id) {
   uint32_t sub_object_type_id;
   switch (composite_type_inst.opcode()) {
-    case SpvOpTypeArray:
-    case SpvOpTypeRuntimeArray:
+    case spv::Op::OpTypeArray:
+    case spv::Op::OpTypeRuntimeArray:
       sub_object_type_id = composite_type_inst.GetSingleWordInOperand(0);
       break;
-    case SpvOpTypeMatrix:
-    case SpvOpTypeVector:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeVector:
       sub_object_type_id = composite_type_inst.GetSingleWordInOperand(0);
       break;
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       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()
                  ->GetDef(index_inst->type_id())
-                 ->opcode() == SpvOpTypeInt);
+                 ->opcode() == spv::Op::OpTypeInt);
       assert(ir_context->get_def_use_mgr()
                  ->GetDef(index_inst->type_id())
                  ->GetSingleWordInOperand(0) == 32);
diff --git a/source/fuzz/transformation_add_global_undef.cpp b/source/fuzz/transformation_add_global_undef.cpp
index ec0574a..5aca19d 100644
--- a/source/fuzz/transformation_add_global_undef.cpp
+++ b/source/fuzz/transformation_add_global_undef.cpp
@@ -39,14 +39,14 @@
   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.
   return type != nullptr && opt::IsTypeInst(type->opcode()) &&
-         type->opcode() != SpvOpTypeFunction &&
-         type->opcode() != SpvOpTypePointer;
+         type->opcode() != spv::Op::OpTypeFunction &&
+         type->opcode() != spv::Op::OpTypePointer;
 }
 
 void TransformationAddGlobalUndef::Apply(
     opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   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());
   auto new_instruction_ptr = new_instruction.get();
   ir_context->module()->AddGlobalValue(std::move(new_instruction));
diff --git a/source/fuzz/transformation_add_global_variable.cpp b/source/fuzz/transformation_add_global_variable.cpp
index 814d01b..6e82d59 100644
--- a/source/fuzz/transformation_add_global_variable.cpp
+++ b/source/fuzz/transformation_add_global_variable.cpp
@@ -24,11 +24,11 @@
     : message_(std::move(message)) {}
 
 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) {
   message_.set_fresh_id(fresh_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_value_is_irrelevant(value_is_irrelevant);
 }
@@ -41,10 +41,10 @@
   }
 
   // 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) {
-    case SpvStorageClassPrivate:
-    case SpvStorageClassWorkgroup:
+    case spv::StorageClass::Private:
+    case spv::StorageClass::Workgroup:
       break;
     default:
       assert(false && "Unsupported storage class.");
@@ -66,7 +66,7 @@
   }
   if (message_.initializer_id()) {
     // An initializer is not allowed if the storage class is Workgroup.
-    if (storage_class == SpvStorageClassWorkgroup) {
+    if (storage_class == spv::StorageClass::Workgroup) {
       assert(false &&
              "By construction this transformation should not have an "
              "initializer when Workgroup storage class is used.");
@@ -95,7 +95,7 @@
     TransformationContext* transformation_context) const {
   opt::Instruction* new_instruction = fuzzerutil::AddGlobalVariable(
       ir_context, message_.fresh_id(), message_.type_id(),
-      static_cast<SpvStorageClass>(message_.storage_class()),
+      static_cast<spv::StorageClass>(message_.storage_class()),
       message_.initializer_id());
 
   // Inform the def-use manager about the new instruction.
diff --git a/source/fuzz/transformation_add_global_variable.h b/source/fuzz/transformation_add_global_variable.h
index d74d48a..0178219 100644
--- a/source/fuzz/transformation_add_global_variable.h
+++ b/source/fuzz/transformation_add_global_variable.h
@@ -29,7 +29,7 @@
       protobufs::TransformationAddGlobalVariable message);
 
   TransformationAddGlobalVariable(uint32_t fresh_id, uint32_t type_id,
-                                  SpvStorageClass storage_class,
+                                  spv::StorageClass storage_class,
                                   uint32_t initializer_id,
                                   bool value_is_irrelevant);
 
diff --git a/source/fuzz/transformation_add_image_sample_unused_components.cpp b/source/fuzz/transformation_add_image_sample_unused_components.cpp
index 1ead82b..018fed4 100644
--- a/source/fuzz/transformation_add_image_sample_unused_components.cpp
+++ b/source/fuzz/transformation_add_image_sample_unused_components.cpp
@@ -73,7 +73,7 @@
   // It must be an OpCompositeConstruct instruction such that it can be checked
   // that the original components are present.
   if (coordinate_with_unused_components_instruction->opcode() !=
-      SpvOpCompositeConstruct) {
+      spv::Op::OpCompositeConstruct) {
     return false;
   }
 
diff --git a/source/fuzz/transformation_add_local_variable.cpp b/source/fuzz/transformation_add_local_variable.cpp
index 21768d2..9ee210c 100644
--- a/source/fuzz/transformation_add_local_variable.cpp
+++ b/source/fuzz/transformation_add_local_variable.cpp
@@ -43,8 +43,10 @@
   // function storage class.
   auto type_instruction =
       ir_context->get_def_use_mgr()->GetDef(message_.type_id());
-  if (!type_instruction || type_instruction->opcode() != SpvOpTypePointer ||
-      type_instruction->GetSingleWordInOperand(0) != SpvStorageClassFunction) {
+  if (!type_instruction ||
+      type_instruction->opcode() != spv::Op::OpTypePointer ||
+      spv::StorageClass(type_instruction->GetSingleWordInOperand(0)) !=
+          spv::StorageClass::Function) {
     return false;
   }
   // The initializer must...
diff --git a/source/fuzz/transformation_add_loop_preheader.cpp b/source/fuzz/transformation_add_loop_preheader.cpp
index 71ab18d..4b66b69 100644
--- a/source/fuzz/transformation_add_loop_preheader.cpp
+++ b/source/fuzz/transformation_add_loop_preheader.cpp
@@ -120,8 +120,8 @@
         // If |use_inst| is not a branch or merge instruction, it should not be
         // changed.
         if (!use_inst->IsBranch() &&
-            use_inst->opcode() != SpvOpSelectionMerge &&
-            use_inst->opcode() != SpvOpLoopMerge) {
+            use_inst->opcode() != spv::Op::OpSelectionMerge &&
+            use_inst->opcode() != spv::Op::OpLoopMerge) {
           return;
         }
 
@@ -134,7 +134,7 @@
   // Make a new block for the preheader.
   std::unique_ptr<opt::BasicBlock> preheader = MakeUnique<opt::BasicBlock>(
       std::unique_ptr<opt::Instruction>(new opt::Instruction(
-          ir_context, SpvOpLabel, 0, message_.fresh_id(), {})));
+          ir_context, spv::Op::OpLabel, 0, message_.fresh_id(), {})));
 
   uint32_t phi_ids_used = 0;
 
@@ -183,7 +183,7 @@
       fuzzerutil::UpdateModuleIdBound(ir_context, fresh_phi_id);
 
       preheader->AddInstruction(std::unique_ptr<opt::Instruction>(
-          new opt::Instruction(ir_context, SpvOpPhi, phi_inst->type_id(),
+          new opt::Instruction(ir_context, spv::Op::OpPhi, phi_inst->type_id(),
                                fresh_phi_id, preheader_in_operands)));
 
       // Update the OpPhi instruction in the header so that it refers to the
@@ -202,7 +202,7 @@
   // Add an unconditional branch from the preheader to the header.
   preheader->AddInstruction(
       std::unique_ptr<opt::Instruction>(new opt::Instruction(
-          ir_context, SpvOpBranch, 0, 0,
+          ir_context, spv::Op::OpBranch, 0, 0,
           std::initializer_list<opt::Operand>{opt::Operand(
               spv_operand_type_t::SPV_OPERAND_TYPE_ID, {loop_header->id()})})));
 
diff --git a/source/fuzz/transformation_add_loop_to_create_int_constant_synonym.cpp b/source/fuzz/transformation_add_loop_to_create_int_constant_synonym.cpp
index 657fafa..00030e7 100644
--- a/source/fuzz/transformation_add_loop_to_create_int_constant_synonym.cpp
+++ b/source/fuzz/transformation_add_loop_to_create_int_constant_synonym.cpp
@@ -262,13 +262,13 @@
   // Create the loop header block.
   std::unique_ptr<opt::BasicBlock> loop_block =
       MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpLabel, 0, message_.loop_id(),
+          ir_context, spv::Op::OpLabel, 0, message_.loop_id(),
           opt::Instruction::OperandList{}));
 
   // Add OpPhi instructions to retrieve the current value of the counter and of
   // the temporary variable that will be decreased at each operation.
   loop_block->AddInstruction(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpPhi, const_0_def->type_id(), message_.ctr_id(),
+      ir_context, spv::Op::OpPhi, const_0_def->type_id(), message_.ctr_id(),
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {const_0_id}},
           {SPV_OPERAND_TYPE_ID, {pred_id}},
@@ -276,7 +276,8 @@
           {SPV_OPERAND_TYPE_ID, {last_loop_block_id}}}));
 
   loop_block->AddInstruction(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpPhi, initial_val_def->type_id(), message_.temp_id(),
+      ir_context, spv::Op::OpPhi, initial_val_def->type_id(),
+      message_.temp_id(),
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {message_.initial_val_id()}},
           {SPV_OPERAND_TYPE_ID, {pred_id}},
@@ -291,7 +292,7 @@
   // Add an instruction to subtract the step value from the temporary value.
   // The value of this id will converge to the constant in the last iteration.
   other_instructions.push_back(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpISub, initial_val_def->type_id(),
+      ir_context, spv::Op::OpISub, initial_val_def->type_id(),
       message_.eventual_syn_id(),
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {message_.temp_id()}},
@@ -299,15 +300,15 @@
 
   // Add an instruction to increment the counter.
   other_instructions.push_back(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpIAdd, const_0_def->type_id(),
+      ir_context, spv::Op::OpIAdd, const_0_def->type_id(),
       message_.incremented_ctr_id(),
       opt::Instruction::OperandList{{SPV_OPERAND_TYPE_ID, {message_.ctr_id()}},
                                     {SPV_OPERAND_TYPE_ID, {const_1_id}}}));
 
   // Add an instruction to decide whether the condition holds.
   other_instructions.push_back(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpSLessThan, fuzzerutil::MaybeGetBoolType(ir_context),
-      message_.cond_id(),
+      ir_context, spv::Op::OpSLessThan,
+      fuzzerutil::MaybeGetBoolType(ir_context), message_.cond_id(),
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {message_.incremented_ctr_id()}},
           {SPV_OPERAND_TYPE_ID, {message_.num_iterations_id()}}}));
@@ -316,18 +317,19 @@
   // the existing block, the continue block is the last block in the loop
   // (either the loop itself or the additional block).
   std::unique_ptr<opt::Instruction> merge_inst = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpLoopMerge, 0, 0,
+      ir_context, spv::Op::OpLoopMerge, 0, 0,
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {message_.block_after_loop_id()}},
           {SPV_OPERAND_TYPE_ID, {last_loop_block_id}},
-          {SPV_OPERAND_TYPE_LOOP_CONTROL, {SpvLoopControlMaskNone}}});
+          {SPV_OPERAND_TYPE_LOOP_CONTROL,
+           {uint32_t(spv::LoopControlMask::MaskNone)}}});
 
   // Define a conditional branch instruction, branching to the loop header if
   // the condition holds, and to the existing block otherwise. This instruction
   // will be added to the last block in the loop.
   std::unique_ptr<opt::Instruction> conditional_branch =
       MakeUnique<opt::Instruction>(
-          ir_context, SpvOpBranchConditional, 0, 0,
+          ir_context, spv::Op::OpBranchConditional, 0, 0,
           opt::Instruction::OperandList{
               {SPV_OPERAND_TYPE_ID, {message_.cond_id()}},
               {SPV_OPERAND_TYPE_ID, {message_.loop_id()}},
@@ -340,7 +342,7 @@
 
     std::unique_ptr<opt::BasicBlock> additional_block =
         MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
-            ir_context, SpvOpLabel, 0, message_.additional_block_id(),
+            ir_context, spv::Op::OpLabel, 0, message_.additional_block_id(),
             opt::Instruction::OperandList{}));
 
     for (auto& instruction : other_instructions) {
@@ -354,7 +356,7 @@
 
     // Add an unconditional branch from the header to the additional block.
     loop_block->AddInstruction(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpBranch, 0, 0,
+        ir_context, spv::Op::OpBranch, 0, 0,
         opt::Instruction::OperandList{
             {SPV_OPERAND_TYPE_ID, {message_.additional_block_id()}}}));
 
@@ -384,14 +386,14 @@
   ir_context->get_def_use_mgr()->ForEachUse(
       message_.block_after_loop_id(),
       [this](opt::Instruction* instruction, uint32_t operand_index) {
-        assert(instruction->opcode() != SpvOpLoopMerge &&
-               instruction->opcode() != SpvOpSelectionMerge &&
+        assert(instruction->opcode() != spv::Op::OpLoopMerge &&
+               instruction->opcode() != spv::Op::OpSelectionMerge &&
                "The block should not be referenced by OpLoopMerge or "
                "OpSelectionMerge, by construction.");
         // Replace all uses of the label inside branch instructions.
-        if (instruction->opcode() == SpvOpBranch ||
-            instruction->opcode() == SpvOpBranchConditional ||
-            instruction->opcode() == SpvOpSwitch) {
+        if (instruction->opcode() == spv::Op::OpBranch ||
+            instruction->opcode() == spv::Op::OpBranchConditional ||
+            instruction->opcode() == spv::Op::OpSwitch) {
           instruction->SetOperand(operand_index, {message_.loop_id()});
         }
       });
@@ -410,7 +412,7 @@
   // |message_.initial_value_id|, since this is the value that is decremented in
   // the loop.
   block_after_loop->begin()->InsertBefore(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpPhi, initial_val_def->type_id(), message_.syn_id(),
+      ir_context, spv::Op::OpPhi, initial_val_def->type_id(), message_.syn_id(),
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {message_.eventual_syn_id()}},
           {SPV_OPERAND_TYPE_ID, {last_loop_block_id}}}));
diff --git a/source/fuzz/transformation_add_no_contraction_decoration.cpp b/source/fuzz/transformation_add_no_contraction_decoration.cpp
index 992a216..07a31e5 100644
--- a/source/fuzz/transformation_add_no_contraction_decoration.cpp
+++ b/source/fuzz/transformation_add_no_contraction_decoration.cpp
@@ -43,8 +43,8 @@
 void TransformationAddNoContractionDecoration::Apply(
     opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   // Add a NoContraction decoration targeting |message_.result_id|.
-  ir_context->get_decoration_mgr()->AddDecoration(message_.result_id(),
-                                                  SpvDecorationNoContraction);
+  ir_context->get_decoration_mgr()->AddDecoration(
+      message_.result_id(), uint32_t(spv::Decoration::NoContraction));
 }
 
 protobufs::Transformation TransformationAddNoContractionDecoration::ToMessage()
@@ -54,50 +54,50 @@
   return result;
 }
 
-bool TransformationAddNoContractionDecoration::IsArithmetic(uint32_t opcode) {
+bool TransformationAddNoContractionDecoration::IsArithmetic(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpSNegate:
-    case SpvOpFNegate:
-    case SpvOpIAdd:
-    case SpvOpFAdd:
-    case SpvOpISub:
-    case SpvOpFSub:
-    case SpvOpIMul:
-    case SpvOpFMul:
-    case SpvOpUDiv:
-    case SpvOpSDiv:
-    case SpvOpFDiv:
-    case SpvOpUMod:
-    case SpvOpSRem:
-    case SpvOpSMod:
-    case SpvOpFRem:
-    case SpvOpFMod:
-    case SpvOpVectorTimesScalar:
-    case SpvOpMatrixTimesScalar:
-    case SpvOpVectorTimesMatrix:
-    case SpvOpMatrixTimesVector:
-    case SpvOpMatrixTimesMatrix:
-    case SpvOpOuterProduct:
-    case SpvOpDot:
-    case SpvOpIAddCarry:
-    case SpvOpISubBorrow:
-    case SpvOpUMulExtended:
-    case SpvOpSMulExtended:
-    case SpvOpAny:
-    case SpvOpAll:
-    case SpvOpIsNan:
-    case SpvOpIsInf:
-    case SpvOpIsFinite:
-    case SpvOpIsNormal:
-    case SpvOpSignBitSet:
-    case SpvOpLessOrGreater:
-    case SpvOpOrdered:
-    case SpvOpUnordered:
-    case SpvOpLogicalEqual:
-    case SpvOpLogicalNotEqual:
-    case SpvOpLogicalOr:
-    case SpvOpLogicalAnd:
-    case SpvOpLogicalNot:
+    case spv::Op::OpSNegate:
+    case spv::Op::OpFNegate:
+    case spv::Op::OpIAdd:
+    case spv::Op::OpFAdd:
+    case spv::Op::OpISub:
+    case spv::Op::OpFSub:
+    case spv::Op::OpIMul:
+    case spv::Op::OpFMul:
+    case spv::Op::OpUDiv:
+    case spv::Op::OpSDiv:
+    case spv::Op::OpFDiv:
+    case spv::Op::OpUMod:
+    case spv::Op::OpSRem:
+    case spv::Op::OpSMod:
+    case spv::Op::OpFRem:
+    case spv::Op::OpFMod:
+    case spv::Op::OpVectorTimesScalar:
+    case spv::Op::OpMatrixTimesScalar:
+    case spv::Op::OpVectorTimesMatrix:
+    case spv::Op::OpMatrixTimesVector:
+    case spv::Op::OpMatrixTimesMatrix:
+    case spv::Op::OpOuterProduct:
+    case spv::Op::OpDot:
+    case spv::Op::OpIAddCarry:
+    case spv::Op::OpISubBorrow:
+    case spv::Op::OpUMulExtended:
+    case spv::Op::OpSMulExtended:
+    case spv::Op::OpAny:
+    case spv::Op::OpAll:
+    case spv::Op::OpIsNan:
+    case spv::Op::OpIsInf:
+    case spv::Op::OpIsFinite:
+    case spv::Op::OpIsNormal:
+    case spv::Op::OpSignBitSet:
+    case spv::Op::OpLessOrGreater:
+    case spv::Op::OpOrdered:
+    case spv::Op::OpUnordered:
+    case spv::Op::OpLogicalEqual:
+    case spv::Op::OpLogicalNotEqual:
+    case spv::Op::OpLogicalOr:
+    case spv::Op::OpLogicalAnd:
+    case spv::Op::OpLogicalNot:
       return true;
     default:
       return false;
diff --git a/source/fuzz/transformation_add_no_contraction_decoration.h b/source/fuzz/transformation_add_no_contraction_decoration.h
index 2f78d42..4235dc1 100644
--- a/source/fuzz/transformation_add_no_contraction_decoration.h
+++ b/source/fuzz/transformation_add_no_contraction_decoration.h
@@ -50,7 +50,7 @@
 
   // Returns true if and only if |opcode| is the opcode of an arithmetic
   // instruction, as defined by the SPIR-V specification.
-  static bool IsArithmetic(uint32_t opcode);
+  static bool IsArithmetic(spv::Op opcode);
 
  private:
   protobufs::TransformationAddNoContractionDecoration message_;
diff --git a/source/fuzz/transformation_add_opphi_synonym.cpp b/source/fuzz/transformation_add_opphi_synonym.cpp
index 3c4698a..31c56b6 100644
--- a/source/fuzz/transformation_add_opphi_synonym.cpp
+++ b/source/fuzz/transformation_add_opphi_synonym.cpp
@@ -142,8 +142,8 @@
   // Add a new OpPhi instructions at the beginning of the block.
   ir_context->get_instr_block(message_.block_id())
       ->begin()
-      .InsertBefore(MakeUnique<opt::Instruction>(ir_context, SpvOpPhi, type_id,
-                                                 message_.fresh_id(),
+      .InsertBefore(MakeUnique<opt::Instruction>(ir_context, spv::Op::OpPhi,
+                                                 type_id, message_.fresh_id(),
                                                  std::move(operand_list)));
 
   // Update the module id bound.
@@ -186,9 +186,9 @@
   if (type->AsPointer()) {
     auto storage_class = type->AsPointer()->storage_class();
     return ir_context->get_feature_mgr()->HasCapability(
-               SpvCapabilityVariablePointers) &&
-           (storage_class == SpvStorageClassWorkgroup ||
-            storage_class == SpvStorageClassStorageBuffer);
+               spv::Capability::VariablePointers) &&
+           (storage_class == spv::StorageClass::Workgroup ||
+            storage_class == spv::StorageClass::StorageBuffer);
   }
 
   // We do not allow other types.
diff --git a/source/fuzz/transformation_add_parameter.cpp b/source/fuzz/transformation_add_parameter.cpp
index 48de3e8..8bd2ed7 100644
--- a/source/fuzz/transformation_add_parameter.cpp
+++ b/source/fuzz/transformation_add_parameter.cpp
@@ -112,7 +112,7 @@
 
   // Add new parameters to the function.
   function->AddParameter(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpFunctionParameter, new_parameter_type_id,
+      ir_context, spv::Op::OpFunctionParameter, new_parameter_type_id,
       message_.parameter_fresh_id(), opt::Instruction::OperandList()));
 
   fuzzerutil::UpdateModuleIdBound(ir_context, message_.parameter_fresh_id());
@@ -178,16 +178,16 @@
   //  Think about other type instructions we can add here.
   opt::Instruction* type_inst = ir_context->get_def_use_mgr()->GetDef(type_id);
   switch (type_inst->opcode()) {
-    case SpvOpTypeBool:
-    case SpvOpTypeInt:
-    case SpvOpTypeFloat:
-    case SpvOpTypeMatrix:
-    case SpvOpTypeVector:
+    case spv::Op::OpTypeBool:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeFloat:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeVector:
       return true;
-    case SpvOpTypeArray:
+    case spv::Op::OpTypeArray:
       return IsParameterTypeSupported(ir_context,
                                       type_inst->GetSingleWordInOperand(0));
-    case SpvOpTypeStruct:
+    case spv::Op::OpTypeStruct:
       if (fuzzerutil::HasBlockOrBufferBlockDecoration(ir_context, type_id)) {
         return false;
       }
@@ -198,13 +198,13 @@
         }
       }
       return true;
-    case SpvOpTypePointer: {
-      SpvStorageClass storage_class =
-          static_cast<SpvStorageClass>(type_inst->GetSingleWordInOperand(0));
+    case spv::Op::OpTypePointer: {
+      spv::StorageClass storage_class =
+          static_cast<spv::StorageClass>(type_inst->GetSingleWordInOperand(0));
       switch (storage_class) {
-        case SpvStorageClassPrivate:
-        case SpvStorageClassFunction:
-        case SpvStorageClassWorkgroup: {
+        case spv::StorageClass::Private:
+        case spv::StorageClass::Function:
+        case spv::StorageClass::Workgroup: {
           return IsParameterTypeSupported(ir_context,
                                           type_inst->GetSingleWordInOperand(1));
         }
diff --git a/source/fuzz/transformation_add_relaxed_decoration.cpp b/source/fuzz/transformation_add_relaxed_decoration.cpp
index b66a1a8..6cd4ecb 100644
--- a/source/fuzz/transformation_add_relaxed_decoration.cpp
+++ b/source/fuzz/transformation_add_relaxed_decoration.cpp
@@ -54,7 +54,7 @@
     opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   // Add a RelaxedPrecision decoration targeting |message_.result_id|.
   ir_context->get_decoration_mgr()->AddDecoration(
-      message_.result_id(), SpvDecorationRelaxedPrecision);
+      message_.result_id(), uint32_t(spv::Decoration::RelaxedPrecision));
 }
 
 protobufs::Transformation TransformationAddRelaxedDecoration::ToMessage()
@@ -64,77 +64,77 @@
   return result;
 }
 
-bool TransformationAddRelaxedDecoration::IsNumeric(uint32_t opcode) {
+bool TransformationAddRelaxedDecoration::IsNumeric(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpConvertFToU:
-    case SpvOpConvertFToS:
-    case SpvOpConvertSToF:
-    case SpvOpConvertUToF:
-    case SpvOpUConvert:
-    case SpvOpSConvert:
-    case SpvOpFConvert:
-    case SpvOpConvertPtrToU:
-    case SpvOpSatConvertSToU:
-    case SpvOpSatConvertUToS:
-    case SpvOpVectorExtractDynamic:
-    case SpvOpVectorInsertDynamic:
-    case SpvOpVectorShuffle:
-    case SpvOpTranspose:
-    case SpvOpSNegate:
-    case SpvOpFNegate:
-    case SpvOpIAdd:
-    case SpvOpFAdd:
-    case SpvOpISub:
-    case SpvOpFSub:
-    case SpvOpIMul:
-    case SpvOpFMul:
-    case SpvOpUDiv:
-    case SpvOpSDiv:
-    case SpvOpFDiv:
-    case SpvOpUMod:
-    case SpvOpSRem:
-    case SpvOpSMod:
-    case SpvOpFRem:
-    case SpvOpFMod:
-    case SpvOpVectorTimesScalar:
-    case SpvOpMatrixTimesScalar:
-    case SpvOpVectorTimesMatrix:
-    case SpvOpMatrixTimesVector:
-    case SpvOpMatrixTimesMatrix:
-    case SpvOpOuterProduct:
-    case SpvOpDot:
-    case SpvOpIAddCarry:
-    case SpvOpISubBorrow:
-    case SpvOpUMulExtended:
-    case SpvOpSMulExtended:
-    case SpvOpShiftRightLogical:
-    case SpvOpShiftRightArithmetic:
-    case SpvOpShiftLeftLogical:
-    case SpvOpBitwiseOr:
-    case SpvOpBitwiseXor:
-    case SpvOpBitwiseAnd:
-    case SpvOpNot:
-    case SpvOpBitFieldInsert:
-    case SpvOpBitFieldSExtract:
-    case SpvOpBitFieldUExtract:
-    case SpvOpBitReverse:
-    case SpvOpBitCount:
-    case SpvOpAtomicLoad:
-    case SpvOpAtomicStore:
-    case SpvOpAtomicExchange:
-    case SpvOpAtomicCompareExchange:
-    case SpvOpAtomicCompareExchangeWeak:
-    case SpvOpAtomicIIncrement:
-    case SpvOpAtomicIDecrement:
-    case SpvOpAtomicIAdd:
-    case SpvOpAtomicISub:
-    case SpvOpAtomicSMin:
-    case SpvOpAtomicUMin:
-    case SpvOpAtomicSMax:
-    case SpvOpAtomicUMax:
-    case SpvOpAtomicAnd:
-    case SpvOpAtomicOr:
-    case SpvOpAtomicXor:
+    case spv::Op::OpConvertFToU:
+    case spv::Op::OpConvertFToS:
+    case spv::Op::OpConvertSToF:
+    case spv::Op::OpConvertUToF:
+    case spv::Op::OpUConvert:
+    case spv::Op::OpSConvert:
+    case spv::Op::OpFConvert:
+    case spv::Op::OpConvertPtrToU:
+    case spv::Op::OpSatConvertSToU:
+    case spv::Op::OpSatConvertUToS:
+    case spv::Op::OpVectorExtractDynamic:
+    case spv::Op::OpVectorInsertDynamic:
+    case spv::Op::OpVectorShuffle:
+    case spv::Op::OpTranspose:
+    case spv::Op::OpSNegate:
+    case spv::Op::OpFNegate:
+    case spv::Op::OpIAdd:
+    case spv::Op::OpFAdd:
+    case spv::Op::OpISub:
+    case spv::Op::OpFSub:
+    case spv::Op::OpIMul:
+    case spv::Op::OpFMul:
+    case spv::Op::OpUDiv:
+    case spv::Op::OpSDiv:
+    case spv::Op::OpFDiv:
+    case spv::Op::OpUMod:
+    case spv::Op::OpSRem:
+    case spv::Op::OpSMod:
+    case spv::Op::OpFRem:
+    case spv::Op::OpFMod:
+    case spv::Op::OpVectorTimesScalar:
+    case spv::Op::OpMatrixTimesScalar:
+    case spv::Op::OpVectorTimesMatrix:
+    case spv::Op::OpMatrixTimesVector:
+    case spv::Op::OpMatrixTimesMatrix:
+    case spv::Op::OpOuterProduct:
+    case spv::Op::OpDot:
+    case spv::Op::OpIAddCarry:
+    case spv::Op::OpISubBorrow:
+    case spv::Op::OpUMulExtended:
+    case spv::Op::OpSMulExtended:
+    case spv::Op::OpShiftRightLogical:
+    case spv::Op::OpShiftRightArithmetic:
+    case spv::Op::OpShiftLeftLogical:
+    case spv::Op::OpBitwiseOr:
+    case spv::Op::OpBitwiseXor:
+    case spv::Op::OpBitwiseAnd:
+    case spv::Op::OpNot:
+    case spv::Op::OpBitFieldInsert:
+    case spv::Op::OpBitFieldSExtract:
+    case spv::Op::OpBitFieldUExtract:
+    case spv::Op::OpBitReverse:
+    case spv::Op::OpBitCount:
+    case spv::Op::OpAtomicLoad:
+    case spv::Op::OpAtomicStore:
+    case spv::Op::OpAtomicExchange:
+    case spv::Op::OpAtomicCompareExchange:
+    case spv::Op::OpAtomicCompareExchangeWeak:
+    case spv::Op::OpAtomicIIncrement:
+    case spv::Op::OpAtomicIDecrement:
+    case spv::Op::OpAtomicIAdd:
+    case spv::Op::OpAtomicISub:
+    case spv::Op::OpAtomicSMin:
+    case spv::Op::OpAtomicUMin:
+    case spv::Op::OpAtomicSMax:
+    case spv::Op::OpAtomicUMax:
+    case spv::Op::OpAtomicAnd:
+    case spv::Op::OpAtomicOr:
+    case spv::Op::OpAtomicXor:
       return true;
     default:
       return false;
@@ -147,4 +147,4 @@
 }
 
 }  // namespace fuzz
-}  // namespace spvtools
\ No newline at end of file
+}  // namespace spvtools
diff --git a/source/fuzz/transformation_add_relaxed_decoration.h b/source/fuzz/transformation_add_relaxed_decoration.h
index c016349..e13594e 100644
--- a/source/fuzz/transformation_add_relaxed_decoration.h
+++ b/source/fuzz/transformation_add_relaxed_decoration.h
@@ -52,7 +52,7 @@
   // Returns true if and only if |opcode| is the opcode of an instruction
   // that operates on 32-bit integers and 32-bit floats
   // as defined by the SPIR-V specification.
-  static bool IsNumeric(uint32_t opcode);
+  static bool IsNumeric(spv::Op opcode);
 
  private:
   protobufs::TransformationAddRelaxedDecoration message_;
diff --git a/source/fuzz/transformation_add_spec_constant_op.cpp b/source/fuzz/transformation_add_spec_constant_op.cpp
index 19c5e85..685f0a4 100644
--- a/source/fuzz/transformation_add_spec_constant_op.cpp
+++ b/source/fuzz/transformation_add_spec_constant_op.cpp
@@ -26,11 +26,11 @@
     : message_(std::move(message)) {}
 
 TransformationAddSpecConstantOp::TransformationAddSpecConstantOp(
-    uint32_t fresh_id, uint32_t type_id, SpvOp opcode,
+    uint32_t fresh_id, uint32_t type_id, spv::Op opcode,
     const opt::Instruction::OperandList& operands) {
   message_.set_fresh_id(fresh_id);
   message_.set_type_id(type_id);
-  message_.set_opcode(opcode);
+  message_.set_opcode(uint32_t(opcode));
   for (const auto& operand : operands) {
     auto* op = message_.add_operand();
     op->set_operand_type(operand.type);
@@ -70,8 +70,8 @@
   }
 
   ir_context->AddGlobalValue(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpSpecConstantOp, message_.type_id(), message_.fresh_id(),
-      std::move(operands)));
+      ir_context, spv::Op::OpSpecConstantOp, message_.type_id(),
+      message_.fresh_id(), std::move(operands)));
 
   fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
 }
diff --git a/source/fuzz/transformation_add_spec_constant_op.h b/source/fuzz/transformation_add_spec_constant_op.h
index 29851fd..665f66a 100644
--- a/source/fuzz/transformation_add_spec_constant_op.h
+++ b/source/fuzz/transformation_add_spec_constant_op.h
@@ -29,7 +29,7 @@
       protobufs::TransformationAddSpecConstantOp message);
 
   TransformationAddSpecConstantOp(
-      uint32_t fresh_id, uint32_t type_id, SpvOp opcode,
+      uint32_t fresh_id, uint32_t type_id, spv::Op opcode,
       const opt::Instruction::OperandList& operands);
 
   // - |fresh_id| is a fresh result id in the module.
diff --git a/source/fuzz/transformation_add_synonym.cpp b/source/fuzz/transformation_add_synonym.cpp
index 69269e5..00df9cf 100644
--- a/source/fuzz/transformation_add_synonym.cpp
+++ b/source/fuzz/transformation_add_synonym.cpp
@@ -82,7 +82,7 @@
   // Check that we can insert |message._synonymous_instruction| before
   // |message_.insert_before| instruction. We use OpIAdd to represent some
   // instruction that can produce a synonym.
-  if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpIAdd,
+  if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpIAdd,
                                                     insert_before_inst)) {
     return false;
   }
@@ -147,7 +147,8 @@
   // Instruction must have a result id, type id. We skip OpUndef and
   // OpConstantNull.
   if (!inst || !inst->result_id() || !inst->type_id() ||
-      inst->opcode() == SpvOpUndef || inst->opcode() == SpvOpConstantNull) {
+      inst->opcode() == spv::Op::OpUndef ||
+      inst->opcode() == spv::Op::OpConstantNull) {
     return false;
   }
 
@@ -208,7 +209,7 @@
   auto synonym_type_id =
       fuzzerutil::GetTypeId(ir_context, message_.result_id());
   assert(synonym_type_id && "Synonym has invalid type id");
-  auto opcode = SpvOpNop;
+  auto opcode = spv::Op::OpNop;
   const auto* synonym_type =
       ir_context->get_type_mgr()->GetType(synonym_type_id);
   assert(synonym_type && "Synonym has invalid type");
@@ -219,30 +220,30 @@
 
   switch (message_.synonym_type()) {
     case protobufs::TransformationAddSynonym::SUB_ZERO:
-      opcode = is_integral ? SpvOpISub : SpvOpFSub;
+      opcode = is_integral ? spv::Op::OpISub : spv::Op::OpFSub;
       break;
     case protobufs::TransformationAddSynonym::MUL_ONE:
-      opcode = is_integral ? SpvOpIMul : SpvOpFMul;
+      opcode = is_integral ? spv::Op::OpIMul : spv::Op::OpFMul;
       break;
     case protobufs::TransformationAddSynonym::ADD_ZERO:
-      opcode = is_integral ? SpvOpIAdd : SpvOpFAdd;
+      opcode = is_integral ? spv::Op::OpIAdd : spv::Op::OpFAdd;
       break;
     case protobufs::TransformationAddSynonym::LOGICAL_OR:
-      opcode = SpvOpLogicalOr;
+      opcode = spv::Op::OpLogicalOr;
       break;
     case protobufs::TransformationAddSynonym::LOGICAL_AND:
-      opcode = SpvOpLogicalAnd;
+      opcode = spv::Op::OpLogicalAnd;
       break;
     case protobufs::TransformationAddSynonym::BITWISE_OR:
-      opcode = SpvOpBitwiseOr;
+      opcode = spv::Op::OpBitwiseOr;
       break;
     case protobufs::TransformationAddSynonym::BITWISE_XOR:
-      opcode = SpvOpBitwiseXor;
+      opcode = spv::Op::OpBitwiseXor;
       break;
 
     case protobufs::TransformationAddSynonym::COPY_OBJECT:
       return MakeUnique<opt::Instruction>(
-          ir_context, SpvOpCopyObject, synonym_type_id,
+          ir_context, spv::Op::OpCopyObject, synonym_type_id,
           message_.synonym_fresh_id(),
           opt::Instruction::OperandList{
               {SPV_OPERAND_TYPE_ID, {message_.result_id()}}});
diff --git a/source/fuzz/transformation_add_type_array.cpp b/source/fuzz/transformation_add_type_array.cpp
index 45bc8df..d00d0e4 100644
--- a/source/fuzz/transformation_add_type_array.cpp
+++ b/source/fuzz/transformation_add_type_array.cpp
@@ -72,7 +72,7 @@
   in_operands.push_back({SPV_OPERAND_TYPE_ID, {message_.element_type_id()}});
   in_operands.push_back({SPV_OPERAND_TYPE_ID, {message_.size_id()}});
   auto type_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpTypeArray, 0, message_.fresh_id(), in_operands);
+      ir_context, spv::Op::OpTypeArray, 0, message_.fresh_id(), in_operands);
   auto type_instruction_ptr = type_instruction.get();
   ir_context->module()->AddType(std::move(type_instruction));
 
diff --git a/source/fuzz/transformation_add_type_boolean.cpp b/source/fuzz/transformation_add_type_boolean.cpp
index 30ff43e..47fc744 100644
--- a/source/fuzz/transformation_add_type_boolean.cpp
+++ b/source/fuzz/transformation_add_type_boolean.cpp
@@ -43,7 +43,7 @@
     opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   opt::Instruction::OperandList empty_operands;
   auto type_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpTypeBool, 0, message_.fresh_id(), empty_operands);
+      ir_context, spv::Op::OpTypeBool, 0, message_.fresh_id(), empty_operands);
   auto type_instruction_ptr = type_instruction.get();
   ir_context->module()->AddType(std::move(type_instruction));
 
diff --git a/source/fuzz/transformation_add_type_float.cpp b/source/fuzz/transformation_add_type_float.cpp
index 1b88b25..1943ffa 100644
--- a/source/fuzz/transformation_add_type_float.cpp
+++ b/source/fuzz/transformation_add_type_float.cpp
@@ -40,7 +40,8 @@
   switch (message_.width()) {
     case 16:
       // The Float16 capability must be present.
-      if (!ir_context->get_feature_mgr()->HasCapability(SpvCapabilityFloat16)) {
+      if (!ir_context->get_feature_mgr()->HasCapability(
+              spv::Capability::Float16)) {
         return false;
       }
       break;
@@ -49,7 +50,8 @@
       break;
     case 64:
       // The Float64 capability must be present.
-      if (!ir_context->get_feature_mgr()->HasCapability(SpvCapabilityFloat64)) {
+      if (!ir_context->get_feature_mgr()->HasCapability(
+              spv::Capability::Float64)) {
         return false;
       }
       break;
@@ -66,7 +68,7 @@
 void TransformationAddTypeFloat::Apply(
     opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   auto type_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpTypeFloat, 0, message_.fresh_id(),
+      ir_context, spv::Op::OpTypeFloat, 0, message_.fresh_id(),
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.width()}}});
   auto type_instruction_ptr = type_instruction.get();
diff --git a/source/fuzz/transformation_add_type_int.cpp b/source/fuzz/transformation_add_type_int.cpp
index d4ef981..35663f9 100644
--- a/source/fuzz/transformation_add_type_int.cpp
+++ b/source/fuzz/transformation_add_type_int.cpp
@@ -42,13 +42,15 @@
   switch (message_.width()) {
     case 8:
       // The Int8 capability must be present.
-      if (!ir_context->get_feature_mgr()->HasCapability(SpvCapabilityInt8)) {
+      if (!ir_context->get_feature_mgr()->HasCapability(
+              spv::Capability::Int8)) {
         return false;
       }
       break;
     case 16:
       // The Int16 capability must be present.
-      if (!ir_context->get_feature_mgr()->HasCapability(SpvCapabilityInt16)) {
+      if (!ir_context->get_feature_mgr()->HasCapability(
+              spv::Capability::Int16)) {
         return false;
       }
       break;
@@ -57,7 +59,8 @@
       break;
     case 64:
       // The Int64 capability must be present.
-      if (!ir_context->get_feature_mgr()->HasCapability(SpvCapabilityInt64)) {
+      if (!ir_context->get_feature_mgr()->HasCapability(
+              spv::Capability::Int64)) {
         return false;
       }
       break;
@@ -75,7 +78,7 @@
 void TransformationAddTypeInt::Apply(opt::IRContext* ir_context,
                                      TransformationContext* /*unused*/) const {
   auto type_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpTypeInt, 0, message_.fresh_id(),
+      ir_context, spv::Op::OpTypeInt, 0, message_.fresh_id(),
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.width()}},
           {SPV_OPERAND_TYPE_LITERAL_INTEGER,
diff --git a/source/fuzz/transformation_add_type_matrix.cpp b/source/fuzz/transformation_add_type_matrix.cpp
index b574b01..e3f1786 100644
--- a/source/fuzz/transformation_add_type_matrix.cpp
+++ b/source/fuzz/transformation_add_type_matrix.cpp
@@ -53,7 +53,7 @@
   in_operands.push_back(
       {SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.column_count()}});
   auto type_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpTypeMatrix, 0, message_.fresh_id(), in_operands);
+      ir_context, spv::Op::OpTypeMatrix, 0, message_.fresh_id(), in_operands);
   auto type_instruction_ptr = type_instruction.get();
   ir_context->module()->AddType(std::move(type_instruction));
 
diff --git a/source/fuzz/transformation_add_type_pointer.cpp b/source/fuzz/transformation_add_type_pointer.cpp
index c6c3945..c112615 100644
--- a/source/fuzz/transformation_add_type_pointer.cpp
+++ b/source/fuzz/transformation_add_type_pointer.cpp
@@ -24,9 +24,9 @@
     : message_(std::move(message)) {}
 
 TransformationAddTypePointer::TransformationAddTypePointer(
-    uint32_t fresh_id, SpvStorageClass storage_class, uint32_t base_type_id) {
+    uint32_t fresh_id, spv::StorageClass storage_class, uint32_t base_type_id) {
   message_.set_fresh_id(fresh_id);
-  message_.set_storage_class(storage_class);
+  message_.set_storage_class(uint32_t(storage_class));
   message_.set_base_type_id(base_type_id);
 }
 
@@ -48,7 +48,7 @@
       {SPV_OPERAND_TYPE_STORAGE_CLASS, {message_.storage_class()}},
       {SPV_OPERAND_TYPE_ID, {message_.base_type_id()}}};
   auto type_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpTypePointer, 0, message_.fresh_id(), in_operands);
+      ir_context, spv::Op::OpTypePointer, 0, message_.fresh_id(), in_operands);
   auto type_instruction_ptr = type_instruction.get();
   ir_context->module()->AddType(std::move(type_instruction));
 
diff --git a/source/fuzz/transformation_add_type_pointer.h b/source/fuzz/transformation_add_type_pointer.h
index 8468c14..e4ef9d8 100644
--- a/source/fuzz/transformation_add_type_pointer.h
+++ b/source/fuzz/transformation_add_type_pointer.h
@@ -28,7 +28,8 @@
   explicit TransformationAddTypePointer(
       protobufs::TransformationAddTypePointer message);
 
-  TransformationAddTypePointer(uint32_t fresh_id, SpvStorageClass storage_class,
+  TransformationAddTypePointer(uint32_t fresh_id,
+                               spv::StorageClass storage_class,
                                uint32_t base_type_id);
 
   // - |message_.fresh_id| must not be used by the module
diff --git a/source/fuzz/transformation_add_type_struct.cpp b/source/fuzz/transformation_add_type_struct.cpp
index d7f0711..95fbbba 100644
--- a/source/fuzz/transformation_add_type_struct.cpp
+++ b/source/fuzz/transformation_add_type_struct.cpp
@@ -79,8 +79,9 @@
     operands.push_back({SPV_OPERAND_TYPE_ID, {type_id}});
   }
 
-  auto type_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpTypeStruct, 0, message_.fresh_id(), std::move(operands));
+  auto type_instruction =
+      MakeUnique<opt::Instruction>(ir_context, spv::Op::OpTypeStruct, 0,
+                                   message_.fresh_id(), std::move(operands));
   auto type_instruction_ptr = type_instruction.get();
   ir_context->AddType(std::move(type_instruction));
 
diff --git a/source/fuzz/transformation_add_type_vector.cpp b/source/fuzz/transformation_add_type_vector.cpp
index 4da0ff0..a7b0fa7 100644
--- a/source/fuzz/transformation_add_type_vector.cpp
+++ b/source/fuzz/transformation_add_type_vector.cpp
@@ -57,7 +57,7 @@
          "Precondition: component count must be in range [2, 4].");
 
   auto type_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpTypeVector, 0, message_.fresh_id(),
+      ir_context, spv::Op::OpTypeVector, 0, message_.fresh_id(),
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {message_.component_type_id()}},
           {SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.component_count()}}});
diff --git a/source/fuzz/transformation_adjust_branch_weights.cpp b/source/fuzz/transformation_adjust_branch_weights.cpp
index 21fef25..2651938 100644
--- a/source/fuzz/transformation_adjust_branch_weights.cpp
+++ b/source/fuzz/transformation_adjust_branch_weights.cpp
@@ -47,7 +47,7 @@
     return false;
   }
 
-  SpvOp opcode = static_cast<SpvOp>(
+  spv::Op opcode = static_cast<spv::Op>(
       message_.instruction_descriptor().target_instruction_opcode());
 
   assert(instruction->opcode() == opcode &&
@@ -55,7 +55,7 @@
          "descriptor.");
 
   // Must be an OpBranchConditional instruction.
-  if (opcode != SpvOpBranchConditional) {
+  if (opcode != spv::Op::OpBranchConditional) {
     return false;
   }
 
diff --git a/source/fuzz/transformation_composite_construct.cpp b/source/fuzz/transformation_composite_construct.cpp
index 2d8e599..075b33d 100644
--- a/source/fuzz/transformation_composite_construct.cpp
+++ b/source/fuzz/transformation_composite_construct.cpp
@@ -121,7 +121,7 @@
 
   // Insert an OpCompositeConstruct instruction.
   auto new_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpCompositeConstruct, message_.composite_type_id(),
+      ir_context, spv::Op::OpCompositeConstruct, message_.composite_type_id(),
       message_.fresh_id(), in_operands);
   auto new_instruction_ptr = new_instruction.get();
   insert_before.InsertBefore(std::move(new_instruction));
diff --git a/source/fuzz/transformation_composite_extract.cpp b/source/fuzz/transformation_composite_extract.cpp
index 0fbd4e1..7118432 100644
--- a/source/fuzz/transformation_composite_extract.cpp
+++ b/source/fuzz/transformation_composite_extract.cpp
@@ -67,7 +67,7 @@
   }
 
   if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
-          SpvOpCompositeExtract, instruction_to_insert_before)) {
+          spv::Op::OpCompositeExtract, instruction_to_insert_before)) {
     return false;
   }
 
@@ -93,7 +93,7 @@
       FindInstruction(message_.instruction_to_insert_before(), ir_context);
   opt::Instruction* new_instruction =
       insert_before->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpCompositeExtract, extracted_type,
+          ir_context, spv::Op::OpCompositeExtract, extracted_type,
           message_.fresh_id(), extract_operands));
   ir_context->get_def_use_mgr()->AnalyzeInstDefUse(new_instruction);
   ir_context->set_instr_block(new_instruction,
diff --git a/source/fuzz/transformation_composite_insert.cpp b/source/fuzz/transformation_composite_insert.cpp
index 60fa562..2f69c95 100644
--- a/source/fuzz/transformation_composite_insert.cpp
+++ b/source/fuzz/transformation_composite_insert.cpp
@@ -102,7 +102,7 @@
   // It must be possible to insert an OpCompositeInsert before this
   // instruction.
   return fuzzerutil::CanInsertOpcodeBeforeInstruction(
-      SpvOpCompositeInsert, instruction_to_insert_before);
+      spv::Op::OpCompositeInsert, instruction_to_insert_before);
 }
 
 void TransformationCompositeInsert::Apply(
@@ -126,8 +126,8 @@
   auto insert_before =
       FindInstruction(message_.instruction_to_insert_before(), ir_context);
   auto new_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpCompositeInsert, composite_type_id, message_.fresh_id(),
-      std::move(in_operands));
+      ir_context, spv::Op::OpCompositeInsert, composite_type_id,
+      message_.fresh_id(), std::move(in_operands));
   auto new_instruction_ptr = new_instruction.get();
   insert_before->InsertBefore(std::move(new_instruction));
 
diff --git a/source/fuzz/transformation_duplicate_region_with_selection.cpp b/source/fuzz/transformation_duplicate_region_with_selection.cpp
index db88610..9176bf7 100644
--- a/source/fuzz/transformation_duplicate_region_with_selection.cpp
+++ b/source/fuzz/transformation_duplicate_region_with_selection.cpp
@@ -77,7 +77,7 @@
   // The entry and exit block ids must refer to blocks.
   for (auto block_id : {message_.entry_block_id(), message_.exit_block_id()}) {
     auto block_label = ir_context->get_def_use_mgr()->GetDef(block_id);
-    if (!block_label || block_label->opcode() != SpvOpLabel) {
+    if (!block_label || block_label->opcode() != spv::Op::OpLabel) {
       return false;
     }
   }
@@ -297,7 +297,7 @@
   // in the same function.
   std::unique_ptr<opt::BasicBlock> new_entry_block =
       MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpLabel, 0, message_.new_entry_fresh_id(),
+          ir_context, spv::Op::OpLabel, 0, message_.new_entry_fresh_id(),
           opt::Instruction::OperandList()));
   auto entry_block = ir_context->cfg()->block(message_.entry_block_id());
   auto enclosing_function = entry_block->GetParent();
@@ -310,7 +310,7 @@
   // Construct the merge block.
   std::unique_ptr<opt::BasicBlock> merge_block =
       MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpLabel, 0, message_.merge_label_fresh_id(),
+          ir_context, spv::Op::OpLabel, 0, message_.merge_label_fresh_id(),
           opt::Instruction::OperandList()));
 
   // Get the maps from the protobuf.
@@ -361,7 +361,7 @@
   exit_block->ForEachSuccessorLabel([this, ir_context](uint32_t label_id) {
     auto block = ir_context->cfg()->block(label_id);
     for (auto& instr : *block) {
-      if (instr.opcode() == SpvOpPhi) {
+      if (instr.opcode() == spv::Op::OpPhi) {
         instr.ForEachId([this](uint32_t* id) {
           if (*id == message_.exit_block_id()) {
             *id = message_.merge_label_fresh_id();
@@ -390,7 +390,7 @@
   // occurrence of |entry_block_pred_id| to the id of |new_entry|, because we
   // will insert |new_entry| before |entry_block|.
   for (auto& instr : *entry_block) {
-    if (instr.opcode() == SpvOpPhi) {
+    if (instr.opcode() == spv::Op::OpPhi) {
       instr.ForEachId([this, entry_block_pred_id](uint32_t* id) {
         if (*id == entry_block_pred_id) {
           *id = message_.new_entry_fresh_id();
@@ -421,7 +421,7 @@
 
     std::unique_ptr<opt::BasicBlock> duplicated_block =
         MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
-            ir_context, SpvOpLabel, 0,
+            ir_context, spv::Op::OpLabel, 0,
             original_label_to_duplicate_label.at(block->id()),
             opt::Instruction::OperandList()));
 
@@ -430,12 +430,12 @@
       // handled separately.
       if (block == exit_block && instr.IsBlockTerminator()) {
         switch (instr.opcode()) {
-          case SpvOpBranch:
-          case SpvOpBranchConditional:
-          case SpvOpReturn:
-          case SpvOpReturnValue:
-          case SpvOpUnreachable:
-          case SpvOpKill:
+          case spv::Op::OpBranch:
+          case spv::Op::OpBranchConditional:
+          case spv::Op::OpReturn:
+          case spv::Op::OpReturnValue:
+          case spv::Op::OpUnreachable:
+          case spv::Op::OpKill:
             continue;
           default:
             assert(false &&
@@ -497,7 +497,7 @@
         // the end of the region, as long as the result id is valid for use
         // with OpPhi.
         merge_block->AddInstruction(MakeUnique<opt::Instruction>(
-            ir_context, SpvOpPhi, instr.type_id(),
+            ir_context, spv::Op::OpPhi, instr.type_id(),
             original_id_to_phi_id.at(instr.result_id()),
             opt::Instruction::OperandList({
                 {SPV_OPERAND_TYPE_ID, {instr.result_id()}},
@@ -537,14 +537,14 @@
   // false, the execution proceeds in the first block of the
   // duplicated region.
   new_entry_block->AddInstruction(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpSelectionMerge, 0, 0,
+      ir_context, spv::Op::OpSelectionMerge, 0, 0,
       opt::Instruction::OperandList(
           {{SPV_OPERAND_TYPE_ID, {message_.merge_label_fresh_id()}},
            {SPV_OPERAND_TYPE_SELECTION_CONTROL,
-            {SpvSelectionControlMaskNone}}})));
+            {uint32_t(spv::SelectionControlMask::MaskNone)}}})));
 
   new_entry_block->AddInstruction(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpBranchConditional, 0, 0,
+      ir_context, spv::Op::OpBranchConditional, 0, 0,
       opt::Instruction::OperandList(
           {{SPV_OPERAND_TYPE_ID, {message_.condition_id()}},
            {SPV_OPERAND_TYPE_ID, {message_.entry_block_id()}},
@@ -563,7 +563,7 @@
   // |exit_block| and at the end of |duplicated_exit_block|, so that
   // the execution proceeds in the |merge_block|.
   opt::Instruction merge_branch_instr = opt::Instruction(
-      ir_context, SpvOpBranch, 0, 0,
+      ir_context, spv::Op::OpBranch, 0, 0,
       opt::Instruction::OperandList(
           {{SPV_OPERAND_TYPE_ID, {message_.merge_label_fresh_id()}}}));
   exit_block->AddInstruction(MakeUnique<opt::Instruction>(merge_branch_instr));
@@ -584,14 +584,14 @@
           return;
         }
         switch (user->opcode()) {
-          case SpvOpSwitch:
-          case SpvOpBranch:
-          case SpvOpBranchConditional:
-          case SpvOpLoopMerge:
-          case SpvOpSelectionMerge: {
+          case spv::Op::OpSwitch:
+          case spv::Op::OpBranch:
+          case spv::Op::OpBranchConditional:
+          case spv::Op::OpLoopMerge:
+          case spv::Op::OpSelectionMerge: {
             user->SetOperand(operand_index, {message_.new_entry_fresh_id()});
           } break;
-          case SpvOpName:
+          case spv::Op::OpName:
             break;
           default:
             assert(false &&
@@ -605,8 +605,8 @@
 
   opt::Instruction* merge_block_terminator = merge_block->terminator();
   switch (merge_block_terminator->opcode()) {
-    case SpvOpReturnValue:
-    case SpvOpBranchConditional: {
+    case spv::Op::OpReturnValue:
+    case spv::Op::OpBranchConditional: {
       uint32_t operand = merge_block_terminator->GetSingleWordInOperand(0);
       if (original_id_to_phi_id.count(operand)) {
         merge_block_terminator->SetInOperand(
@@ -699,19 +699,19 @@
       ir_context->get_def_use_mgr()->GetDef(instr.type_id());
 
   // It is invalid to apply OpPhi to void-typed values.
-  if (instr_type->opcode() == SpvOpTypeVoid) {
+  if (instr_type->opcode() == spv::Op::OpTypeVoid) {
     return false;
   }
 
   // Using pointers with OpPhi requires capability VariablePointers.
-  if (instr_type->opcode() == SpvOpTypePointer &&
+  if (instr_type->opcode() == spv::Op::OpTypePointer &&
       !ir_context->get_feature_mgr()->HasCapability(
-          SpvCapabilityVariablePointers)) {
+          spv::Capability::VariablePointers)) {
     return false;
   }
 
   // OpTypeSampledImage cannot be the result type of an OpPhi instruction.
-  if (instr_type->opcode() == SpvOpTypeSampledImage) {
+  if (instr_type->opcode() == spv::Op::OpTypeSampledImage) {
     return false;
   }
   return true;
diff --git a/source/fuzz/transformation_equation_instruction.cpp b/source/fuzz/transformation_equation_instruction.cpp
index 1e5dae9..72487a8 100644
--- a/source/fuzz/transformation_equation_instruction.cpp
+++ b/source/fuzz/transformation_equation_instruction.cpp
@@ -25,10 +25,11 @@
     : message_(std::move(message)) {}
 
 TransformationEquationInstruction::TransformationEquationInstruction(
-    uint32_t fresh_id, SpvOp opcode, const std::vector<uint32_t>& in_operand_id,
+    uint32_t fresh_id, spv::Op opcode,
+    const std::vector<uint32_t>& in_operand_id,
     const protobufs::InstructionDescriptor& instruction_to_insert_before) {
   message_.set_fresh_id(fresh_id);
-  message_.set_opcode(opcode);
+  message_.set_opcode(uint32_t(opcode));
   for (auto id : in_operand_id) {
     message_.add_in_operand_id(id);
   }
@@ -57,7 +58,7 @@
     if (!inst) {
       return false;
     }
-    if (inst->opcode() == SpvOpUndef) {
+    if (inst->opcode() == spv::Op::OpUndef) {
       return false;
     }
     if (transformation_context.GetFactManager()->IdIsIrrelevant(id)) {
@@ -88,7 +89,7 @@
       FindInstruction(message_.instruction_to_insert_before(), ir_context);
   opt::Instruction* new_instruction =
       insert_before->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, static_cast<SpvOp>(message_.opcode()),
+          ir_context, static_cast<spv::Op>(message_.opcode()),
           MaybeGetResultTypeId(ir_context), message_.fresh_id(),
           std::move(in_operands)));
 
@@ -101,7 +102,7 @@
   if (!transformation_context->GetFactManager()->IdIsIrrelevant(
           message_.fresh_id())) {
     transformation_context->GetFactManager()->AddFactIdEquation(
-        message_.fresh_id(), static_cast<SpvOp>(message_.opcode()), rhs_id);
+        message_.fresh_id(), static_cast<spv::Op>(message_.opcode()), rhs_id);
   }
 }
 
@@ -113,10 +114,10 @@
 
 uint32_t TransformationEquationInstruction::MaybeGetResultTypeId(
     opt::IRContext* ir_context) const {
-  auto opcode = static_cast<SpvOp>(message_.opcode());
+  auto opcode = static_cast<spv::Op>(message_.opcode());
   switch (opcode) {
-    case SpvOpConvertUToF:
-    case SpvOpConvertSToF: {
+    case spv::Op::OpConvertUToF:
+    case spv::Op::OpConvertSToF: {
       if (message_.in_operand_id_size() != 1) {
         return 0;
       }
@@ -148,7 +149,7 @@
                                              type->AsInteger()->width());
       }
     }
-    case SpvOpBitcast: {
+    case spv::Op::OpBitcast: {
       if (message_.in_operand_id_size() != 1) {
         return 0;
       }
@@ -210,8 +211,8 @@
         return 0;
       }
     }
-    case SpvOpIAdd:
-    case SpvOpISub: {
+    case spv::Op::OpIAdd:
+    case spv::Op::OpISub: {
       if (message_.in_operand_id_size() != 2) {
         return 0;
       }
@@ -249,7 +250,7 @@
              "A type must have been found for the first operand.");
       return first_operand_type_id;
     }
-    case SpvOpLogicalNot: {
+    case spv::Op::OpLogicalNot: {
       if (message_.in_operand_id().size() != 1) {
         return 0;
       }
@@ -267,7 +268,7 @@
       }
       return operand_inst->type_id();
     }
-    case SpvOpSNegate: {
+    case spv::Op::OpSNegate: {
       if (message_.in_operand_id().size() != 1) {
         return 0;
       }
diff --git a/source/fuzz/transformation_equation_instruction.h b/source/fuzz/transformation_equation_instruction.h
index ae32a1a..40118d9 100644
--- a/source/fuzz/transformation_equation_instruction.h
+++ b/source/fuzz/transformation_equation_instruction.h
@@ -31,7 +31,7 @@
       protobufs::TransformationEquationInstruction message);
 
   TransformationEquationInstruction(
-      uint32_t fresh_id, SpvOp opcode,
+      uint32_t fresh_id, spv::Op opcode,
       const std::vector<uint32_t>& in_operand_id,
       const protobufs::InstructionDescriptor& instruction_to_insert_before);
 
diff --git a/source/fuzz/transformation_expand_vector_reduction.cpp b/source/fuzz/transformation_expand_vector_reduction.cpp
index bafcf92..4c13ec1 100644
--- a/source/fuzz/transformation_expand_vector_reduction.cpp
+++ b/source/fuzz/transformation_expand_vector_reduction.cpp
@@ -44,7 +44,8 @@
   }
 
   // |instruction| must be OpAny or OpAll.
-  if (instruction->opcode() != SpvOpAny && instruction->opcode() != SpvOpAll) {
+  if (instruction->opcode() != spv::Op::OpAny &&
+      instruction->opcode() != spv::Op::OpAll) {
     return false;
   }
 
@@ -92,10 +93,11 @@
 
   for (uint32_t i = 0; i < vector_component_count; i++) {
     // Extracts the i-th |vector| component.
-    auto vector_component = opt::Instruction(
-        ir_context, SpvOpCompositeExtract, instruction->type_id(), *fresh_id++,
-        {{SPV_OPERAND_TYPE_ID, {vector->result_id()}},
-         {SPV_OPERAND_TYPE_LITERAL_INTEGER, {i}}});
+    auto vector_component =
+        opt::Instruction(ir_context, spv::Op::OpCompositeExtract,
+                         instruction->type_id(), *fresh_id++,
+                         {{SPV_OPERAND_TYPE_ID, {vector->result_id()}},
+                          {SPV_OPERAND_TYPE_LITERAL_INTEGER, {i}}});
     instruction->InsertBefore(MakeUnique<opt::Instruction>(vector_component));
     fuzzerutil::UpdateModuleIdBound(ir_context, vector_component.result_id());
     vector_components.push_back(vector_component.result_id());
@@ -104,7 +106,8 @@
   // The first two |vector| components are used in the first logical operation.
   auto logical_instruction = opt::Instruction(
       ir_context,
-      instruction->opcode() == SpvOpAny ? SpvOpLogicalOr : SpvOpLogicalAnd,
+      instruction->opcode() == spv::Op::OpAny ? spv::Op::OpLogicalOr
+                                              : spv::Op::OpLogicalAnd,
       instruction->type_id(), *fresh_id++,
       {{SPV_OPERAND_TYPE_ID, {vector_components[0]}},
        {SPV_OPERAND_TYPE_ID, {vector_components[1]}}});
diff --git a/source/fuzz/transformation_flatten_conditional_branch.cpp b/source/fuzz/transformation_flatten_conditional_branch.cpp
index 127e762..f8d1c33 100644
--- a/source/fuzz/transformation_flatten_conditional_branch.cpp
+++ b/source/fuzz/transformation_flatten_conditional_branch.cpp
@@ -48,12 +48,12 @@
 
   // The block must have been found and it must be a selection header.
   if (!header_block || !header_block->GetMergeInst() ||
-      header_block->GetMergeInst()->opcode() != SpvOpSelectionMerge) {
+      header_block->GetMergeInst()->opcode() != spv::Op::OpSelectionMerge) {
     return false;
   }
 
   // The header block must end with an OpBranchConditional instruction.
-  if (header_block->terminator()->opcode() != SpvOpBranchConditional) {
+  if (header_block->terminator()->opcode() != spv::Op::OpBranchConditional) {
     return false;
   }
 
@@ -164,14 +164,14 @@
                opt::Instruction* phi_result_type =
                    ir_context->get_def_use_mgr()->GetDef(inst->type_id());
                switch (phi_result_type->opcode()) {
-                 case SpvOpTypeBool:
-                 case SpvOpTypeInt:
-                 case SpvOpTypeFloat:
-                 case SpvOpTypePointer:
+                 case spv::Op::OpTypeBool:
+                 case spv::Op::OpTypeInt:
+                 case spv::Op::OpTypeFloat:
+                 case spv::Op::OpTypePointer:
                    // Fine: OpSelect can work directly on scalar and pointer
                    // types.
                    return true;
-                 case SpvOpTypeVector: {
+                 case spv::Op::OpTypeVector: {
                    // In its restricted form, OpSelect can only select between
                    // vectors if the condition of the select is a boolean
                    // boolean vector.  We thus require the appropriate boolean
@@ -288,8 +288,8 @@
 
       current_block->ForEachInst(
           [&problematic_instructions](opt::Instruction* instruction) {
-            if (instruction->opcode() != SpvOpLabel &&
-                instruction->opcode() != SpvOpBranch &&
+            if (instruction->opcode() != spv::Op::OpLabel &&
+                instruction->opcode() != spv::Op::OpBranch &&
                 !fuzzerutil::InstructionHasNoSideEffects(*instruction)) {
               problematic_instructions.push_back(instruction);
             }
@@ -381,7 +381,7 @@
   // Add a new, unconditional, branch instruction from the current header to
   // |after_header|.
   header_block->AddInstruction(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpBranch, 0, 0,
+      ir_context, spv::Op::OpBranch, 0, 0,
       opt::Instruction::OperandList{{SPV_OPERAND_TYPE_ID, {after_header}}}));
 
   // If the first branch to be laid out exists, change the branch instruction so
@@ -437,8 +437,8 @@
         std::set<opt::Instruction*>* instructions_that_need_ids) {
   uint32_t merge_block_id = header->MergeBlockIdIfAny();
   assert(merge_block_id &&
-         header->GetMergeInst()->opcode() == SpvOpSelectionMerge &&
-         header->terminator()->opcode() == SpvOpBranchConditional &&
+         header->GetMergeInst()->opcode() == spv::Op::OpSelectionMerge &&
+         header->terminator()->opcode() == spv::Op::OpBranchConditional &&
          "|header| must be the header of a conditional.");
 
   // |header| must be reachable.
@@ -508,7 +508,7 @@
     }
 
     // The terminator instruction for the block must be OpBranch.
-    if (block->terminator()->opcode() != SpvOpBranch) {
+    if (block->terminator()->opcode() != spv::Op::OpBranch) {
       return false;
     }
 
@@ -524,7 +524,7 @@
         [ir_context, instructions_that_need_ids,
          &synonym_base_objects](opt::Instruction* instruction) {
           // We can ignore OpLabel instructions.
-          if (instruction->opcode() == SpvOpLabel) {
+          if (instruction->opcode() == spv::Op::OpLabel) {
             return true;
           }
 
@@ -539,7 +539,7 @@
 
           // If the instruction is a branch, it must be an unconditional branch.
           if (instruction->IsBranch()) {
-            return instruction->opcode() == SpvOpBranch;
+            return instruction->opcode() == spv::Op::OpBranch;
           }
 
           // We cannot go ahead if we encounter an instruction that cannot be
@@ -644,7 +644,7 @@
 
   // Add an unconditional branch from |execute_block| to |merge_block|.
   execute_block->AddInstruction(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpBranch, 0, 0,
+      ir_context, spv::Op::OpBranch, 0, 0,
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {merge_block->id()}}}));
 
@@ -668,10 +668,10 @@
     }
 
     // Create a new block using |fresh_ids.alternative_block_id| for its label.
-    auto alternative_block_temp =
-        MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
-            ir_context, SpvOpLabel, 0, wrapper_info.alternative_block_id(),
-            opt::Instruction::OperandList{}));
+    auto alternative_block_temp = MakeUnique<opt::BasicBlock>(
+        MakeUnique<opt::Instruction>(ir_context, spv::Op::OpLabel, 0,
+                                     wrapper_info.alternative_block_id(),
+                                     opt::Instruction::OperandList{}));
 
     // Keep the original result id of the instruction in a variable.
     uint32_t original_result_id = instruction->result_id();
@@ -685,14 +685,14 @@
       // If there is an available id to copy from, the placeholder instruction
       // will be %placeholder_result_id = OpCopyObject %type %value_to_copy_id
       alternative_block_temp->AddInstruction(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpCopyObject, instruction->type_id(),
+          ir_context, spv::Op::OpCopyObject, instruction->type_id(),
           wrapper_info.placeholder_result_id(),
           opt::Instruction::OperandList{
               {SPV_OPERAND_TYPE_ID, {wrapper_info.value_to_copy_id()}}}));
     } else {
       // If there is no such id, use an OpUndef instruction.
       alternative_block_temp->AddInstruction(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpUndef, instruction->type_id(),
+          ir_context, spv::Op::OpUndef, instruction->type_id(),
           wrapper_info.placeholder_result_id(),
           opt::Instruction::OperandList{}));
     }
@@ -702,7 +702,7 @@
 
     // Add an unconditional branch from the new block to the merge block.
     alternative_block_temp->AddInstruction(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpBranch, 0, 0,
+        ir_context, spv::Op::OpBranch, 0, 0,
         opt::Instruction::OperandList{
             {SPV_OPERAND_TYPE_ID, {merge_block->id()}}}));
 
@@ -714,7 +714,7 @@
     // merge block, which will either take the value of the result of the
     // instruction or the placeholder value defined in the alternative block.
     merge_block->begin().InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpPhi, instruction->type_id(), original_result_id,
+        ir_context, spv::Op::OpPhi, instruction->type_id(), original_result_id,
         opt::Instruction::OperandList{
             {SPV_OPERAND_TYPE_ID, {instruction->result_id()}},
             {SPV_OPERAND_TYPE_ID, {execute_block->id()}},
@@ -738,16 +738,17 @@
 
   // Add an OpSelectionMerge instruction to the block.
   block->AddInstruction(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpSelectionMerge, 0, 0,
-      opt::Instruction::OperandList{{SPV_OPERAND_TYPE_ID, {merge_block->id()}},
-                                    {SPV_OPERAND_TYPE_SELECTION_CONTROL,
-                                     {SpvSelectionControlMaskNone}}}));
+      ir_context, spv::Op::OpSelectionMerge, 0, 0,
+      opt::Instruction::OperandList{
+          {SPV_OPERAND_TYPE_ID, {merge_block->id()}},
+          {SPV_OPERAND_TYPE_SELECTION_CONTROL,
+           {uint32_t(spv::SelectionControlMask::MaskNone)}}}));
 
   // Add an OpBranchConditional, to the block, using |condition_id| as the
   // condition and branching to |if_block_id| if the condition is true and to
   // |else_block_id| if the condition is false.
   block->AddInstruction(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpBranchConditional, 0, 0,
+      ir_context, spv::Op::OpBranchConditional, 0, 0,
       opt::Instruction::OperandList{{SPV_OPERAND_TYPE_ID, {condition_id}},
                                     {SPV_OPERAND_TYPE_ID, {if_block_id}},
                                     {SPV_OPERAND_TYPE_ID, {else_block_id}}}));
@@ -764,26 +765,26 @@
 
   // We cannot handle barrier instructions, while we should be able to handle
   // all other instructions by enclosing them inside a conditional.
-  if (instruction.opcode() == SpvOpControlBarrier ||
-      instruction.opcode() == SpvOpMemoryBarrier ||
-      instruction.opcode() == SpvOpNamedBarrierInitialize ||
-      instruction.opcode() == SpvOpMemoryNamedBarrier ||
-      instruction.opcode() == SpvOpTypeNamedBarrier) {
+  if (instruction.opcode() == spv::Op::OpControlBarrier ||
+      instruction.opcode() == spv::Op::OpMemoryBarrier ||
+      instruction.opcode() == spv::Op::OpNamedBarrierInitialize ||
+      instruction.opcode() == spv::Op::OpMemoryNamedBarrier ||
+      instruction.opcode() == spv::Op::OpTypeNamedBarrier) {
     return false;
   }
 
   // We cannot handle OpSampledImage instructions, as they need to be in the
   // same block as their use.
-  if (instruction.opcode() == SpvOpSampledImage) {
+  if (instruction.opcode() == spv::Op::OpSampledImage) {
     return false;
   }
 
   // We cannot handle a sampled image load, because we re-work loads using
   // conditional branches and OpPhi instructions, and the result type of OpPhi
   // cannot be OpTypeSampledImage.
-  if (instruction.opcode() == SpvOpLoad &&
+  if (instruction.opcode() == spv::Op::OpLoad &&
       ir_context->get_def_use_mgr()->GetDef(instruction.type_id())->opcode() ==
-          SpvOpTypeSampledImage) {
+          spv::Op::OpTypeSampledImage) {
     return false;
   }
 
@@ -863,7 +864,7 @@
     in_operands.emplace_back(branch_condition_operand);
   }
   block->begin()->InsertBefore(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpCompositeConstruct,
+      ir_context, spv::Op::OpCompositeConstruct,
       fuzzerutil::MaybeGetVectorType(
           ir_context, fuzzerutil::MaybeGetBoolType(ir_context), dimension),
       fresh_id, in_operands));
@@ -906,7 +907,7 @@
         opt::Operand selector_operand = branch_condition_operand;
         opt::Instruction* type_inst =
             ir_context->get_def_use_mgr()->GetDef(phi_inst->type_id());
-        if (type_inst->opcode() == SpvOpTypeVector) {
+        if (type_inst->opcode() == spv::Op::OpTypeVector) {
           uint32_t dimension = type_inst->GetSingleWordInOperand(1);
           switch (dimension) {
             case 2:
@@ -1012,7 +1013,7 @@
           operands.emplace_back(phi_inst->GetInOperand(2));
           operands.emplace_back(phi_inst->GetInOperand(0));
         }
-        phi_inst->SetOpcode(SpvOpSelect);
+        phi_inst->SetOpcode(spv::Op::OpSelect);
         phi_inst->SetInOperands(std::move(operands));
       });
 
diff --git a/source/fuzz/transformation_function_call.cpp b/source/fuzz/transformation_function_call.cpp
index 0f88ce5..e96a230 100644
--- a/source/fuzz/transformation_function_call.cpp
+++ b/source/fuzz/transformation_function_call.cpp
@@ -49,7 +49,7 @@
   // The function must exist
   auto callee_inst =
       ir_context->get_def_use_mgr()->GetDef(message_.callee_id());
-  if (!callee_inst || callee_inst->opcode() != SpvOpFunction) {
+  if (!callee_inst || callee_inst->opcode() != spv::Op::OpFunction) {
     return false;
   }
 
@@ -60,7 +60,7 @@
 
   auto callee_type_inst = ir_context->get_def_use_mgr()->GetDef(
       callee_inst->GetSingleWordInOperand(1));
-  assert(callee_type_inst->opcode() == SpvOpTypeFunction &&
+  assert(callee_type_inst->opcode() == spv::Op::OpTypeFunction &&
          "Bad function type.");
 
   // The number of expected function arguments must match the number of given
@@ -78,7 +78,7 @@
   if (!insert_before) {
     return false;
   }
-  if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpFunctionCall,
+  if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpFunctionCall,
                                                     insert_before)) {
     return false;
   }
@@ -116,10 +116,10 @@
     }
     opt::Instruction* arg_type_inst =
         ir_context->get_def_use_mgr()->GetDef(arg_inst->type_id());
-    if (arg_type_inst->opcode() == SpvOpTypePointer) {
+    if (arg_type_inst->opcode() == spv::Op::OpTypePointer) {
       switch (arg_inst->opcode()) {
-        case SpvOpFunctionParameter:
-        case SpvOpVariable:
+        case spv::Op::OpFunctionParameter:
+        case spv::Op::OpVariable:
           // These are OK
           break;
         default:
@@ -173,7 +173,7 @@
   // Insert the function call before the instruction specified in the message.
   FindInstruction(message_.instruction_to_insert_before(), ir_context)
       ->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpFunctionCall, return_type, message_.fresh_id(),
+          ir_context, spv::Op::OpFunctionCall, return_type, message_.fresh_id(),
           operands));
   // Invalidate all analyses since we have changed the module.
   ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
diff --git a/source/fuzz/transformation_inline_function.cpp b/source/fuzz/transformation_inline_function.cpp
index a48b817..69e88fd 100644
--- a/source/fuzz/transformation_inline_function.cpp
+++ b/source/fuzz/transformation_inline_function.cpp
@@ -62,7 +62,8 @@
       ir_context->get_instr_block(function_call_instruction);
   if (function_call_instruction !=
           &*--function_call_instruction_block->tail() ||
-      function_call_instruction_block->terminator()->opcode() != SpvOpBranch) {
+      function_call_instruction_block->terminator()->opcode() !=
+          spv::Op::OpBranch) {
     return false;
   }
 
@@ -143,7 +144,7 @@
   for (auto& entry_block_instruction : *called_function->entry()) {
     opt::Instruction* inlined_instruction;
 
-    if (entry_block_instruction.opcode() == SpvOpVariable) {
+    if (entry_block_instruction.opcode() == spv::Op::OpVariable) {
       // All OpVariable instructions in a function must be in the first block
       // in the function.
       inlined_instruction = caller_function->begin()->begin()->InsertBefore(
@@ -206,7 +207,7 @@
         block_containing_function_call->id(),
         [ir_context, new_return_block_id, successor_block](
             opt::Instruction* use_instruction, uint32_t operand_index) {
-          if (use_instruction->opcode() == SpvOpPhi &&
+          if (use_instruction->opcode() == spv::Op::OpPhi &&
               ir_context->get_instr_block(use_instruction) == successor_block) {
             use_instruction->SetOperand(operand_index, {new_return_block_id});
           }
@@ -234,7 +235,7 @@
   // |function_call_instruction| must be defined and must be an OpFunctionCall
   // instruction.
   if (!function_call_instruction ||
-      function_call_instruction->opcode() != SpvOpFunctionCall) {
+      function_call_instruction->opcode() != spv::Op::OpFunctionCall) {
     return false;
   }
 
@@ -331,13 +332,14 @@
             ->terminator()
             ->GetSingleWordInOperand(0);
     switch (instruction_to_be_inlined->opcode()) {
-      case SpvOpReturn:
+      case spv::Op::OpReturn:
         instruction_to_be_inlined->AddOperand(
             {SPV_OPERAND_TYPE_ID, {successor_block_id}});
         break;
-      case SpvOpReturnValue: {
+      case spv::Op::OpReturnValue: {
         instruction_to_be_inlined->InsertBefore(MakeUnique<opt::Instruction>(
-            ir_context, SpvOpCopyObject, function_call_instruction->type_id(),
+            ir_context, spv::Op::OpCopyObject,
+            function_call_instruction->type_id(),
             function_call_instruction->result_id(),
             opt::Instruction::OperandList(
                 {{SPV_OPERAND_TYPE_ID,
@@ -348,7 +350,7 @@
       default:
         break;
     }
-    instruction_to_be_inlined->SetOpcode(SpvOpBranch);
+    instruction_to_be_inlined->SetOpcode(spv::Op::OpBranch);
   }
 }
 
diff --git a/source/fuzz/transformation_invert_comparison_operator.cpp b/source/fuzz/transformation_invert_comparison_operator.cpp
index ed7358f..49801e3 100644
--- a/source/fuzz/transformation_invert_comparison_operator.cpp
+++ b/source/fuzz/transformation_invert_comparison_operator.cpp
@@ -47,7 +47,8 @@
   auto iter = fuzzerutil::GetIteratorForInstruction(block, inst);
   ++iter;
   assert(iter != block->end() && "Instruction can't be the last in the block");
-  assert(fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpLogicalNot, iter) &&
+  assert(fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpLogicalNot,
+                                                      iter) &&
          "Can't insert negation after comparison operator");
 
   // |message_.fresh_id| must be fresh.
@@ -65,7 +66,7 @@
   ++iter;
 
   iter.InsertBefore(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpLogicalNot, inst->type_id(), inst->result_id(),
+      ir_context, spv::Op::OpLogicalNot, inst->type_id(), inst->result_id(),
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {message_.fresh_id()}}}));
 
@@ -82,88 +83,88 @@
 }
 
 bool TransformationInvertComparisonOperator::IsInversionSupported(
-    SpvOp opcode) {
+    spv::Op opcode) {
   switch (opcode) {
-    case SpvOpSGreaterThan:
-    case SpvOpSGreaterThanEqual:
-    case SpvOpSLessThan:
-    case SpvOpSLessThanEqual:
-    case SpvOpUGreaterThan:
-    case SpvOpUGreaterThanEqual:
-    case SpvOpULessThan:
-    case SpvOpULessThanEqual:
-    case SpvOpIEqual:
-    case SpvOpINotEqual:
-    case SpvOpFOrdEqual:
-    case SpvOpFUnordEqual:
-    case SpvOpFOrdNotEqual:
-    case SpvOpFUnordNotEqual:
-    case SpvOpFOrdLessThan:
-    case SpvOpFUnordLessThan:
-    case SpvOpFOrdLessThanEqual:
-    case SpvOpFUnordLessThanEqual:
-    case SpvOpFOrdGreaterThan:
-    case SpvOpFUnordGreaterThan:
-    case SpvOpFOrdGreaterThanEqual:
-    case SpvOpFUnordGreaterThanEqual:
+    case spv::Op::OpSGreaterThan:
+    case spv::Op::OpSGreaterThanEqual:
+    case spv::Op::OpSLessThan:
+    case spv::Op::OpSLessThanEqual:
+    case spv::Op::OpUGreaterThan:
+    case spv::Op::OpUGreaterThanEqual:
+    case spv::Op::OpULessThan:
+    case spv::Op::OpULessThanEqual:
+    case spv::Op::OpIEqual:
+    case spv::Op::OpINotEqual:
+    case spv::Op::OpFOrdEqual:
+    case spv::Op::OpFUnordEqual:
+    case spv::Op::OpFOrdNotEqual:
+    case spv::Op::OpFUnordNotEqual:
+    case spv::Op::OpFOrdLessThan:
+    case spv::Op::OpFUnordLessThan:
+    case spv::Op::OpFOrdLessThanEqual:
+    case spv::Op::OpFUnordLessThanEqual:
+    case spv::Op::OpFOrdGreaterThan:
+    case spv::Op::OpFUnordGreaterThan:
+    case spv::Op::OpFOrdGreaterThanEqual:
+    case spv::Op::OpFUnordGreaterThanEqual:
       return true;
     default:
       return false;
   }
 }
 
-SpvOp TransformationInvertComparisonOperator::InvertOpcode(SpvOp opcode) {
+spv::Op TransformationInvertComparisonOperator::InvertOpcode(spv::Op opcode) {
   assert(IsInversionSupported(opcode) && "Inversion must be supported");
 
   switch (opcode) {
-    case SpvOpSGreaterThan:
-      return SpvOpSLessThanEqual;
-    case SpvOpSGreaterThanEqual:
-      return SpvOpSLessThan;
-    case SpvOpSLessThan:
-      return SpvOpSGreaterThanEqual;
-    case SpvOpSLessThanEqual:
-      return SpvOpSGreaterThan;
-    case SpvOpUGreaterThan:
-      return SpvOpULessThanEqual;
-    case SpvOpUGreaterThanEqual:
-      return SpvOpULessThan;
-    case SpvOpULessThan:
-      return SpvOpUGreaterThanEqual;
-    case SpvOpULessThanEqual:
-      return SpvOpUGreaterThan;
-    case SpvOpIEqual:
-      return SpvOpINotEqual;
-    case SpvOpINotEqual:
-      return SpvOpIEqual;
-    case SpvOpFOrdEqual:
-      return SpvOpFUnordNotEqual;
-    case SpvOpFUnordEqual:
-      return SpvOpFOrdNotEqual;
-    case SpvOpFOrdNotEqual:
-      return SpvOpFUnordEqual;
-    case SpvOpFUnordNotEqual:
-      return SpvOpFOrdEqual;
-    case SpvOpFOrdLessThan:
-      return SpvOpFUnordGreaterThanEqual;
-    case SpvOpFUnordLessThan:
-      return SpvOpFOrdGreaterThanEqual;
-    case SpvOpFOrdLessThanEqual:
-      return SpvOpFUnordGreaterThan;
-    case SpvOpFUnordLessThanEqual:
-      return SpvOpFOrdGreaterThan;
-    case SpvOpFOrdGreaterThan:
-      return SpvOpFUnordLessThanEqual;
-    case SpvOpFUnordGreaterThan:
-      return SpvOpFOrdLessThanEqual;
-    case SpvOpFOrdGreaterThanEqual:
-      return SpvOpFUnordLessThan;
-    case SpvOpFUnordGreaterThanEqual:
-      return SpvOpFOrdLessThan;
+    case spv::Op::OpSGreaterThan:
+      return spv::Op::OpSLessThanEqual;
+    case spv::Op::OpSGreaterThanEqual:
+      return spv::Op::OpSLessThan;
+    case spv::Op::OpSLessThan:
+      return spv::Op::OpSGreaterThanEqual;
+    case spv::Op::OpSLessThanEqual:
+      return spv::Op::OpSGreaterThan;
+    case spv::Op::OpUGreaterThan:
+      return spv::Op::OpULessThanEqual;
+    case spv::Op::OpUGreaterThanEqual:
+      return spv::Op::OpULessThan;
+    case spv::Op::OpULessThan:
+      return spv::Op::OpUGreaterThanEqual;
+    case spv::Op::OpULessThanEqual:
+      return spv::Op::OpUGreaterThan;
+    case spv::Op::OpIEqual:
+      return spv::Op::OpINotEqual;
+    case spv::Op::OpINotEqual:
+      return spv::Op::OpIEqual;
+    case spv::Op::OpFOrdEqual:
+      return spv::Op::OpFUnordNotEqual;
+    case spv::Op::OpFUnordEqual:
+      return spv::Op::OpFOrdNotEqual;
+    case spv::Op::OpFOrdNotEqual:
+      return spv::Op::OpFUnordEqual;
+    case spv::Op::OpFUnordNotEqual:
+      return spv::Op::OpFOrdEqual;
+    case spv::Op::OpFOrdLessThan:
+      return spv::Op::OpFUnordGreaterThanEqual;
+    case spv::Op::OpFUnordLessThan:
+      return spv::Op::OpFOrdGreaterThanEqual;
+    case spv::Op::OpFOrdLessThanEqual:
+      return spv::Op::OpFUnordGreaterThan;
+    case spv::Op::OpFUnordLessThanEqual:
+      return spv::Op::OpFOrdGreaterThan;
+    case spv::Op::OpFOrdGreaterThan:
+      return spv::Op::OpFUnordLessThanEqual;
+    case spv::Op::OpFUnordGreaterThan:
+      return spv::Op::OpFOrdLessThanEqual;
+    case spv::Op::OpFOrdGreaterThanEqual:
+      return spv::Op::OpFUnordLessThan;
+    case spv::Op::OpFUnordGreaterThanEqual:
+      return spv::Op::OpFOrdLessThan;
     default:
       // The program will fail in the debug mode because of the assertion
       // at the beginning of the function.
-      return SpvOpNop;
+      return spv::Op::OpNop;
   }
 }
 
diff --git a/source/fuzz/transformation_invert_comparison_operator.h b/source/fuzz/transformation_invert_comparison_operator.h
index f00f62b..39c2fe0 100644
--- a/source/fuzz/transformation_invert_comparison_operator.h
+++ b/source/fuzz/transformation_invert_comparison_operator.h
@@ -50,11 +50,11 @@
   protobufs::Transformation ToMessage() const override;
 
   // Returns true if |opcode| is supported by this transformation.
-  static bool IsInversionSupported(SpvOp opcode);
+  static bool IsInversionSupported(spv::Op opcode);
 
  private:
   // Returns an inverted |opcode| (e.g. < becomes >=, == becomes != etc.)
-  static SpvOp InvertOpcode(SpvOp opcode);
+  static spv::Op InvertOpcode(spv::Op opcode);
 
   protobufs::TransformationInvertComparisonOperator message_;
 };
diff --git a/source/fuzz/transformation_load.cpp b/source/fuzz/transformation_load.cpp
index bf48d99..1cfde77 100644
--- a/source/fuzz/transformation_load.cpp
+++ b/source/fuzz/transformation_load.cpp
@@ -52,15 +52,15 @@
   // The type must indeed be a pointer type.
   auto pointer_type = ir_context->get_def_use_mgr()->GetDef(pointer->type_id());
   assert(pointer_type && "Type id must be defined.");
-  if (pointer_type->opcode() != SpvOpTypePointer) {
+  if (pointer_type->opcode() != spv::Op::OpTypePointer) {
     return false;
   }
   // We do not want to allow loading from null or undefined pointers, as it is
   // not clear how punishing the consequences of doing so are from a semantics
   // point of view.
   switch (pointer->opcode()) {
-    case SpvOpConstantNull:
-    case SpvOpUndef:
+    case spv::Op::OpConstantNull:
+    case spv::Op::OpUndef:
       return false;
     default:
       break;
@@ -74,13 +74,13 @@
     return false;
   }
   // ... and it must be legitimate to insert a load before it.
-  if (!message_.is_atomic() &&
-      !fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpLoad, insert_before)) {
+  if (!message_.is_atomic() && !fuzzerutil::CanInsertOpcodeBeforeInstruction(
+                                   spv::Op::OpLoad, insert_before)) {
     return false;
   }
 
   if (message_.is_atomic() && !fuzzerutil::CanInsertOpcodeBeforeInstruction(
-                                  SpvOpAtomicLoad, insert_before)) {
+                                  spv::Op::OpAtomicLoad, insert_before)) {
     return false;
   }
 
@@ -99,10 +99,10 @@
     }
     // The memory scope and memory semantics instructions must have the
     // 'OpConstant' opcode.
-    if (memory_scope_instruction->opcode() != SpvOpConstant) {
+    if (memory_scope_instruction->opcode() != spv::Op::OpConstant) {
       return false;
     }
-    if (memory_semantics_instruction->opcode() != SpvOpConstant) {
+    if (memory_semantics_instruction->opcode() != spv::Op::OpConstant) {
       return false;
     }
     // The memory scope and memory semantics need to be available before
@@ -119,12 +119,12 @@
     // operand type with signedness does not matters.
     if (ir_context->get_def_use_mgr()
             ->GetDef(memory_scope_instruction->type_id())
-            ->opcode() != SpvOpTypeInt) {
+            ->opcode() != spv::Op::OpTypeInt) {
       return false;
     }
     if (ir_context->get_def_use_mgr()
             ->GetDef(memory_semantics_instruction->type_id())
-            ->opcode() != SpvOpTypeInt) {
+            ->opcode() != spv::Op::OpTypeInt) {
       return false;
     }
 
@@ -146,20 +146,20 @@
       return false;
     }
 
-    // The memory scope constant value must be that of SpvScopeInvocation.
+    // The memory scope constant value must be that of spv::Scope::Invocation.
     auto memory_scope_const_value =
-        memory_scope_instruction->GetSingleWordInOperand(0);
-    if (memory_scope_const_value != SpvScopeInvocation) {
+        spv::Scope(memory_scope_instruction->GetSingleWordInOperand(0));
+    if (memory_scope_const_value != spv::Scope::Invocation) {
       return false;
     }
 
     // The memory semantics constant value must match the storage class of the
     // pointer being loaded from.
-    auto memory_semantics_const_value = static_cast<SpvMemorySemanticsMask>(
+    auto memory_semantics_const_value = static_cast<spv::MemorySemanticsMask>(
         memory_semantics_instruction->GetSingleWordInOperand(0));
     if (memory_semantics_const_value !=
         fuzzerutil::GetMemorySemanticsForStorageClass(
-            static_cast<SpvStorageClass>(
+            static_cast<spv::StorageClass>(
                 pointer_type->GetSingleWordInOperand(0)))) {
       return false;
     }
@@ -180,7 +180,7 @@
     auto insert_before =
         FindInstruction(message_.instruction_to_insert_before(), ir_context);
     auto new_instruction = MakeUnique<opt::Instruction>(
-        ir_context, SpvOpAtomicLoad, result_type, message_.fresh_id(),
+        ir_context, spv::Op::OpAtomicLoad, result_type, message_.fresh_id(),
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {message_.pointer_id()}},
              {SPV_OPERAND_TYPE_SCOPE_ID, {message_.memory_scope_id()}},
@@ -201,7 +201,7 @@
     auto insert_before =
         FindInstruction(message_.instruction_to_insert_before(), ir_context);
     auto new_instruction = MakeUnique<opt::Instruction>(
-        ir_context, SpvOpLoad, result_type, message_.fresh_id(),
+        ir_context, spv::Op::OpLoad, result_type, message_.fresh_id(),
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {message_.pointer_id()}}}));
     auto new_instruction_ptr = new_instruction.get();
diff --git a/source/fuzz/transformation_load.h b/source/fuzz/transformation_load.h
index 57b4a53..6622918 100644
--- a/source/fuzz/transformation_load.h
+++ b/source/fuzz/transformation_load.h
@@ -37,7 +37,7 @@
   // - |message_.is_atomic| must be true if want to work with OpAtomicLoad
   // - If |is_atomic| is true then |message_memory_scope_id| must be the id of
   //   an OpConstant 32 bit integer instruction with the value
-  //   SpvScopeInvocation.
+  //   spv::Scope::Invocation.
   // - If |is_atomic| is true then |message_.memory_semantics_id| must be the id
   //   of an OpConstant 32 bit integer instruction with the values
   //   SpvMemorySemanticsWorkgroupMemoryMask or
diff --git a/source/fuzz/transformation_make_vector_operation_dynamic.cpp b/source/fuzz/transformation_make_vector_operation_dynamic.cpp
index bd0664c..ecc8dca 100644
--- a/source/fuzz/transformation_make_vector_operation_dynamic.cpp
+++ b/source/fuzz/transformation_make_vector_operation_dynamic.cpp
@@ -62,19 +62,19 @@
   // The OpVectorInsertDynamic instruction has the vector and component operands
   // in reverse order in relation to the OpCompositeInsert corresponding
   // operands.
-  if (instruction->opcode() == SpvOpCompositeInsert) {
+  if (instruction->opcode() == spv::Op::OpCompositeInsert) {
     std::swap(instruction->GetInOperand(0), instruction->GetInOperand(1));
   }
 
   // Sets the literal operand to the equivalent constant.
   instruction->SetInOperand(
-      instruction->opcode() == SpvOpCompositeExtract ? 1 : 2,
+      instruction->opcode() == spv::Op::OpCompositeExtract ? 1 : 2,
       {message_.constant_index_id()});
 
   // Sets the |instruction| opcode to the corresponding vector dynamic opcode.
-  instruction->SetOpcode(instruction->opcode() == SpvOpCompositeExtract
-                             ? SpvOpVectorExtractDynamic
-                             : SpvOpVectorInsertDynamic);
+  instruction->SetOpcode(instruction->opcode() == spv::Op::OpCompositeExtract
+                             ? spv::Op::OpVectorExtractDynamic
+                             : spv::Op::OpVectorInsertDynamic);
 }
 
 protobufs::Transformation TransformationMakeVectorOperationDynamic::ToMessage()
@@ -88,15 +88,15 @@
     opt::IRContext* ir_context, opt::Instruction* instruction) {
   // |instruction| must be defined and must be an OpCompositeExtract/Insert
   // instruction.
-  if (!instruction || (instruction->opcode() != SpvOpCompositeExtract &&
-                       instruction->opcode() != SpvOpCompositeInsert)) {
+  if (!instruction || (instruction->opcode() != spv::Op::OpCompositeExtract &&
+                       instruction->opcode() != spv::Op::OpCompositeInsert)) {
     return false;
   }
 
   // The composite must be a vector.
   auto composite_instruction =
       ir_context->get_def_use_mgr()->GetDef(instruction->GetSingleWordInOperand(
-          instruction->opcode() == SpvOpCompositeExtract ? 0 : 1));
+          instruction->opcode() == spv::Op::OpCompositeExtract ? 0 : 1));
   if (!ir_context->get_type_mgr()
            ->GetType(composite_instruction->type_id())
            ->AsVector()) {
diff --git a/source/fuzz/transformation_merge_function_returns.cpp b/source/fuzz/transformation_merge_function_returns.cpp
index 022e1b6..b35e358 100644
--- a/source/fuzz/transformation_merge_function_returns.cpp
+++ b/source/fuzz/transformation_merge_function_returns.cpp
@@ -50,7 +50,7 @@
   }
 
   // The entry block must end in an unconditional branch.
-  if (function->entry()->terminator()->opcode() != SpvOpBranch) {
+  if (function->entry()->terminator()->opcode() != spv::Op::OpBranch) {
     return false;
   }
 
@@ -134,9 +134,9 @@
     bool all_instructions_allowed =
         ir_context->get_instr_block(merge_block)
             ->WhileEachInst([](opt::Instruction* inst) {
-              return inst->opcode() == SpvOpLabel ||
-                     inst->opcode() == SpvOpPhi ||
-                     inst->opcode() == SpvOpBranch;
+              return inst->opcode() == spv::Op::OpLabel ||
+                     inst->opcode() == spv::Op::OpPhi ||
+                     inst->opcode() == spv::Op::OpBranch;
             });
     if (!all_instructions_allowed) {
       return false;
@@ -286,7 +286,7 @@
     }
 
     // Replace the return instruction with an unconditional branch.
-    ret_block->terminator()->SetOpcode(SpvOpBranch);
+    ret_block->terminator()->SetOpcode(spv::Op::OpBranch);
     ret_block->terminator()->SetInOperands(
         {{SPV_OPERAND_TYPE_ID, {merge_block_id}}});
   }
@@ -410,7 +410,7 @@
 
       // Insert the instruction.
       merge_block->begin()->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpPhi, function->type_id(), maybe_return_val_id,
+          ir_context, spv::Op::OpPhi, function->type_id(), maybe_return_val_id,
           std::move(operand_list)));
 
       fuzzerutil::UpdateModuleIdBound(ir_context, maybe_return_val_id);
@@ -448,14 +448,14 @@
 
       // Insert the instruction.
       merge_block->begin()->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpPhi, bool_type, is_returning_id,
+          ir_context, spv::Op::OpPhi, bool_type, is_returning_id,
           std::move(operand_list)));
 
       fuzzerutil::UpdateModuleIdBound(ir_context, is_returning_id);
     }
 
     // Change the branching instruction of the block.
-    assert(merge_block->terminator()->opcode() == SpvOpBranch &&
+    assert(merge_block->terminator()->opcode() == spv::Op::OpBranch &&
            "Each block should branch unconditionally to the next.");
 
     // Add a new entry to the map corresponding to the merge block of the
@@ -483,14 +483,14 @@
 
     // The block should branch to |enclosing_merge| if |is_returning_id| is
     // true, to |original_succ| otherwise.
-    merge_block->terminator()->SetOpcode(SpvOpBranchConditional);
+    merge_block->terminator()->SetOpcode(spv::Op::OpBranchConditional);
     merge_block->terminator()->SetInOperands(
         {{SPV_OPERAND_TYPE_ID, {is_returning_id}},
          {SPV_OPERAND_TYPE_ID, {enclosing_merge}},
          {SPV_OPERAND_TYPE_ID, {original_succ}}});
   }
 
-  assert(function->entry()->terminator()->opcode() == SpvOpBranch &&
+  assert(function->entry()->terminator()->opcode() == spv::Op::OpBranch &&
          "The entry block should branch unconditionally to another block.");
   uint32_t block_after_entry =
       function->entry()->terminator()->GetSingleWordInOperand(0);
@@ -498,7 +498,7 @@
   // Create the header for the new outer loop.
   auto outer_loop_header =
       MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpLabel, 0, message_.outer_header_id(),
+          ir_context, spv::Op::OpLabel, 0, message_.outer_header_id(),
           opt::Instruction::OperandList()));
 
   fuzzerutil::UpdateModuleIdBound(ir_context, message_.outer_header_id());
@@ -506,15 +506,16 @@
   // Add the instruction:
   //   OpLoopMerge %outer_return_id %unreachable_continue_id None
   outer_loop_header->AddInstruction(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpLoopMerge, 0, 0,
+      ir_context, spv::Op::OpLoopMerge, 0, 0,
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {message_.outer_return_id()}},
           {SPV_OPERAND_TYPE_ID, {message_.unreachable_continue_id()}},
-          {SPV_OPERAND_TYPE_LOOP_CONTROL, {SpvLoopControlMaskNone}}}));
+          {SPV_OPERAND_TYPE_LOOP_CONTROL,
+           {uint32_t(spv::LoopControlMask::MaskNone)}}}));
 
   // Add unconditional branch to %block_after_entry.
   outer_loop_header->AddInstruction(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpBranch, 0, 0,
+      ir_context, spv::Op::OpBranch, 0, 0,
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {block_after_entry}}}));
 
@@ -531,7 +532,7 @@
   ir_context->get_def_use_mgr()->ForEachUse(
       function->entry()->id(),
       [this](opt::Instruction* use_instruction, uint32_t use_operand_index) {
-        if (use_instruction->opcode() == SpvOpPhi) {
+        if (use_instruction->opcode() == spv::Op::OpPhi) {
           use_instruction->SetOperand(use_operand_index,
                                       {message_.outer_header_id()});
         }
@@ -540,7 +541,7 @@
   // Create the merge block for the loop (and return block for the function).
   auto outer_return_block =
       MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpLabel, 0, message_.outer_return_id(),
+          ir_context, spv::Op::OpLabel, 0, message_.outer_return_id(),
           opt::Instruction::OperandList()));
 
   fuzzerutil::UpdateModuleIdBound(ir_context, message_.outer_return_id());
@@ -561,20 +562,20 @@
 
     // Insert the OpPhi instruction.
     outer_return_block->AddInstruction(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpPhi, function->type_id(), message_.return_val_id(),
-        std::move(operand_list)));
+        ir_context, spv::Op::OpPhi, function->type_id(),
+        message_.return_val_id(), std::move(operand_list)));
 
     fuzzerutil::UpdateModuleIdBound(ir_context, message_.return_val_id());
 
     // Insert the OpReturnValue instruction.
     outer_return_block->AddInstruction(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpReturnValue, 0, 0,
+        ir_context, spv::Op::OpReturnValue, 0, 0,
         opt::Instruction::OperandList{
             {SPV_OPERAND_TYPE_ID, {message_.return_val_id()}}}));
   } else {
     // Insert an OpReturn instruction (the function is void).
     outer_return_block->AddInstruction(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpReturn, 0, 0, opt::Instruction::OperandList{}));
+        ir_context, spv::Op::OpReturn, 0, 0, opt::Instruction::OperandList{}));
   }
 
   // Insert the new return block at the end of the function.
@@ -583,7 +584,7 @@
   // Create the unreachable continue block associated with the enclosing loop.
   auto unreachable_continue_block =
       MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpLabel, 0, message_.unreachable_continue_id(),
+          ir_context, spv::Op::OpLabel, 0, message_.unreachable_continue_id(),
           opt::Instruction::OperandList()));
 
   fuzzerutil::UpdateModuleIdBound(ir_context,
@@ -591,7 +592,7 @@
 
   // Insert an branch back to the loop header, to create a back edge.
   unreachable_continue_block->AddInstruction(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpBranch, 0, 0,
+      ir_context, spv::Op::OpBranch, 0, 0,
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {message_.outer_header_id()}}}));
 
@@ -751,7 +752,7 @@
                   // The usage is OK if it is inside an OpPhi instruction in the
                   // merge block.
                   return block_use == merge_block &&
-                         inst_use->opcode() == SpvOpPhi;
+                         inst_use->opcode() == spv::Op::OpPhi;
                 });
           });
 
diff --git a/source/fuzz/transformation_move_instruction_down.cpp b/source/fuzz/transformation_move_instruction_down.cpp
index c8139e7..4d5d9f0 100644
--- a/source/fuzz/transformation_move_instruction_down.cpp
+++ b/source/fuzz/transformation_move_instruction_down.cpp
@@ -26,7 +26,7 @@
 
 std::string GetExtensionSet(opt::IRContext* ir_context,
                             const opt::Instruction& op_ext_inst) {
-  assert(op_ext_inst.opcode() == SpvOpExtInst && "Wrong opcode");
+  assert(op_ext_inst.opcode() == spv::Op::OpExtInst && "Wrong opcode");
 
   const auto* ext_inst_import = ir_context->get_def_use_mgr()->GetDef(
       op_ext_inst.GetSingleWordInOperand(0));
@@ -142,112 +142,112 @@
 bool TransformationMoveInstructionDown::IsSimpleInstruction(
     opt::IRContext* ir_context, const opt::Instruction& inst) {
   switch (inst.opcode()) {
-    case SpvOpNop:
-    case SpvOpUndef:
-    case SpvOpAccessChain:
-    case SpvOpInBoundsAccessChain:
+    case spv::Op::OpNop:
+    case spv::Op::OpUndef:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
       // OpAccessChain and OpInBoundsAccessChain are considered simple
       // instructions since they result in a pointer to the object in memory,
       // not the object itself.
-    case SpvOpVectorExtractDynamic:
-    case SpvOpVectorInsertDynamic:
-    case SpvOpVectorShuffle:
-    case SpvOpCompositeConstruct:
-    case SpvOpCompositeExtract:
-    case SpvOpCompositeInsert:
-    case SpvOpCopyObject:
-    case SpvOpTranspose:
-    case SpvOpConvertFToU:
-    case SpvOpConvertFToS:
-    case SpvOpConvertSToF:
-    case SpvOpConvertUToF:
-    case SpvOpUConvert:
-    case SpvOpSConvert:
-    case SpvOpFConvert:
-    case SpvOpQuantizeToF16:
-    case SpvOpSatConvertSToU:
-    case SpvOpSatConvertUToS:
-    case SpvOpBitcast:
-    case SpvOpSNegate:
-    case SpvOpFNegate:
-    case SpvOpIAdd:
-    case SpvOpFAdd:
-    case SpvOpISub:
-    case SpvOpFSub:
-    case SpvOpIMul:
-    case SpvOpFMul:
-    case SpvOpUDiv:
-    case SpvOpSDiv:
-    case SpvOpFDiv:
-    case SpvOpUMod:
-    case SpvOpSRem:
-    case SpvOpSMod:
-    case SpvOpFRem:
-    case SpvOpFMod:
-    case SpvOpVectorTimesScalar:
-    case SpvOpMatrixTimesScalar:
-    case SpvOpVectorTimesMatrix:
-    case SpvOpMatrixTimesVector:
-    case SpvOpMatrixTimesMatrix:
-    case SpvOpOuterProduct:
-    case SpvOpDot:
-    case SpvOpIAddCarry:
-    case SpvOpISubBorrow:
-    case SpvOpUMulExtended:
-    case SpvOpSMulExtended:
-    case SpvOpAny:
-    case SpvOpAll:
-    case SpvOpIsNan:
-    case SpvOpIsInf:
-    case SpvOpIsFinite:
-    case SpvOpIsNormal:
-    case SpvOpSignBitSet:
-    case SpvOpLessOrGreater:
-    case SpvOpOrdered:
-    case SpvOpUnordered:
-    case SpvOpLogicalEqual:
-    case SpvOpLogicalNotEqual:
-    case SpvOpLogicalOr:
-    case SpvOpLogicalAnd:
-    case SpvOpLogicalNot:
-    case SpvOpSelect:
-    case SpvOpIEqual:
-    case SpvOpINotEqual:
-    case SpvOpUGreaterThan:
-    case SpvOpSGreaterThan:
-    case SpvOpUGreaterThanEqual:
-    case SpvOpSGreaterThanEqual:
-    case SpvOpULessThan:
-    case SpvOpSLessThan:
-    case SpvOpULessThanEqual:
-    case SpvOpSLessThanEqual:
-    case SpvOpFOrdEqual:
-    case SpvOpFUnordEqual:
-    case SpvOpFOrdNotEqual:
-    case SpvOpFUnordNotEqual:
-    case SpvOpFOrdLessThan:
-    case SpvOpFUnordLessThan:
-    case SpvOpFOrdGreaterThan:
-    case SpvOpFUnordGreaterThan:
-    case SpvOpFOrdLessThanEqual:
-    case SpvOpFUnordLessThanEqual:
-    case SpvOpFOrdGreaterThanEqual:
-    case SpvOpFUnordGreaterThanEqual:
-    case SpvOpShiftRightLogical:
-    case SpvOpShiftRightArithmetic:
-    case SpvOpShiftLeftLogical:
-    case SpvOpBitwiseOr:
-    case SpvOpBitwiseXor:
-    case SpvOpBitwiseAnd:
-    case SpvOpNot:
-    case SpvOpBitFieldInsert:
-    case SpvOpBitFieldSExtract:
-    case SpvOpBitFieldUExtract:
-    case SpvOpBitReverse:
-    case SpvOpBitCount:
-    case SpvOpCopyLogical:
+    case spv::Op::OpVectorExtractDynamic:
+    case spv::Op::OpVectorInsertDynamic:
+    case spv::Op::OpVectorShuffle:
+    case spv::Op::OpCompositeConstruct:
+    case spv::Op::OpCompositeExtract:
+    case spv::Op::OpCompositeInsert:
+    case spv::Op::OpCopyObject:
+    case spv::Op::OpTranspose:
+    case spv::Op::OpConvertFToU:
+    case spv::Op::OpConvertFToS:
+    case spv::Op::OpConvertSToF:
+    case spv::Op::OpConvertUToF:
+    case spv::Op::OpUConvert:
+    case spv::Op::OpSConvert:
+    case spv::Op::OpFConvert:
+    case spv::Op::OpQuantizeToF16:
+    case spv::Op::OpSatConvertSToU:
+    case spv::Op::OpSatConvertUToS:
+    case spv::Op::OpBitcast:
+    case spv::Op::OpSNegate:
+    case spv::Op::OpFNegate:
+    case spv::Op::OpIAdd:
+    case spv::Op::OpFAdd:
+    case spv::Op::OpISub:
+    case spv::Op::OpFSub:
+    case spv::Op::OpIMul:
+    case spv::Op::OpFMul:
+    case spv::Op::OpUDiv:
+    case spv::Op::OpSDiv:
+    case spv::Op::OpFDiv:
+    case spv::Op::OpUMod:
+    case spv::Op::OpSRem:
+    case spv::Op::OpSMod:
+    case spv::Op::OpFRem:
+    case spv::Op::OpFMod:
+    case spv::Op::OpVectorTimesScalar:
+    case spv::Op::OpMatrixTimesScalar:
+    case spv::Op::OpVectorTimesMatrix:
+    case spv::Op::OpMatrixTimesVector:
+    case spv::Op::OpMatrixTimesMatrix:
+    case spv::Op::OpOuterProduct:
+    case spv::Op::OpDot:
+    case spv::Op::OpIAddCarry:
+    case spv::Op::OpISubBorrow:
+    case spv::Op::OpUMulExtended:
+    case spv::Op::OpSMulExtended:
+    case spv::Op::OpAny:
+    case spv::Op::OpAll:
+    case spv::Op::OpIsNan:
+    case spv::Op::OpIsInf:
+    case spv::Op::OpIsFinite:
+    case spv::Op::OpIsNormal:
+    case spv::Op::OpSignBitSet:
+    case spv::Op::OpLessOrGreater:
+    case spv::Op::OpOrdered:
+    case spv::Op::OpUnordered:
+    case spv::Op::OpLogicalEqual:
+    case spv::Op::OpLogicalNotEqual:
+    case spv::Op::OpLogicalOr:
+    case spv::Op::OpLogicalAnd:
+    case spv::Op::OpLogicalNot:
+    case spv::Op::OpSelect:
+    case spv::Op::OpIEqual:
+    case spv::Op::OpINotEqual:
+    case spv::Op::OpUGreaterThan:
+    case spv::Op::OpSGreaterThan:
+    case spv::Op::OpUGreaterThanEqual:
+    case spv::Op::OpSGreaterThanEqual:
+    case spv::Op::OpULessThan:
+    case spv::Op::OpSLessThan:
+    case spv::Op::OpULessThanEqual:
+    case spv::Op::OpSLessThanEqual:
+    case spv::Op::OpFOrdEqual:
+    case spv::Op::OpFUnordEqual:
+    case spv::Op::OpFOrdNotEqual:
+    case spv::Op::OpFUnordNotEqual:
+    case spv::Op::OpFOrdLessThan:
+    case spv::Op::OpFUnordLessThan:
+    case spv::Op::OpFOrdGreaterThan:
+    case spv::Op::OpFUnordGreaterThan:
+    case spv::Op::OpFOrdLessThanEqual:
+    case spv::Op::OpFUnordLessThanEqual:
+    case spv::Op::OpFOrdGreaterThanEqual:
+    case spv::Op::OpFUnordGreaterThanEqual:
+    case spv::Op::OpShiftRightLogical:
+    case spv::Op::OpShiftRightArithmetic:
+    case spv::Op::OpShiftLeftLogical:
+    case spv::Op::OpBitwiseOr:
+    case spv::Op::OpBitwiseXor:
+    case spv::Op::OpBitwiseAnd:
+    case spv::Op::OpNot:
+    case spv::Op::OpBitFieldInsert:
+    case spv::Op::OpBitFieldSExtract:
+    case spv::Op::OpBitFieldUExtract:
+    case spv::Op::OpBitReverse:
+    case spv::Op::OpBitCount:
+    case spv::Op::OpCopyLogical:
       return true;
-    case SpvOpExtInst: {
+    case spv::Op::OpExtInst: {
       const auto* ext_inst_import =
           ir_context->get_def_use_mgr()->GetDef(inst.GetSingleWordInOperand(0));
 
@@ -346,53 +346,53 @@
     opt::IRContext* ir_context, const opt::Instruction& inst) {
   switch (inst.opcode()) {
       // Some simple instructions.
-    case SpvOpLoad:
-    case SpvOpCopyMemory:
+    case spv::Op::OpLoad:
+    case spv::Op::OpCopyMemory:
       // Image instructions.
-    case SpvOpImageSampleImplicitLod:
-    case SpvOpImageSampleExplicitLod:
-    case SpvOpImageSampleDrefImplicitLod:
-    case SpvOpImageSampleDrefExplicitLod:
-    case SpvOpImageSampleProjImplicitLod:
-    case SpvOpImageSampleProjExplicitLod:
-    case SpvOpImageSampleProjDrefImplicitLod:
-    case SpvOpImageSampleProjDrefExplicitLod:
-    case SpvOpImageFetch:
-    case SpvOpImageGather:
-    case SpvOpImageDrefGather:
-    case SpvOpImageRead:
-    case SpvOpImageSparseSampleImplicitLod:
-    case SpvOpImageSparseSampleExplicitLod:
-    case SpvOpImageSparseSampleDrefImplicitLod:
-    case SpvOpImageSparseSampleDrefExplicitLod:
-    case SpvOpImageSparseSampleProjImplicitLod:
-    case SpvOpImageSparseSampleProjExplicitLod:
-    case SpvOpImageSparseSampleProjDrefImplicitLod:
-    case SpvOpImageSparseSampleProjDrefExplicitLod:
-    case SpvOpImageSparseFetch:
-    case SpvOpImageSparseGather:
-    case SpvOpImageSparseDrefGather:
-    case SpvOpImageSparseRead:
+    case spv::Op::OpImageSampleImplicitLod:
+    case spv::Op::OpImageSampleExplicitLod:
+    case spv::Op::OpImageSampleDrefImplicitLod:
+    case spv::Op::OpImageSampleDrefExplicitLod:
+    case spv::Op::OpImageSampleProjImplicitLod:
+    case spv::Op::OpImageSampleProjExplicitLod:
+    case spv::Op::OpImageSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSampleProjDrefExplicitLod:
+    case spv::Op::OpImageFetch:
+    case spv::Op::OpImageGather:
+    case spv::Op::OpImageDrefGather:
+    case spv::Op::OpImageRead:
+    case spv::Op::OpImageSparseSampleImplicitLod:
+    case spv::Op::OpImageSparseSampleExplicitLod:
+    case spv::Op::OpImageSparseSampleDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleDrefExplicitLod:
+    case spv::Op::OpImageSparseSampleProjImplicitLod:
+    case spv::Op::OpImageSparseSampleProjExplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefExplicitLod:
+    case spv::Op::OpImageSparseFetch:
+    case spv::Op::OpImageSparseGather:
+    case spv::Op::OpImageSparseDrefGather:
+    case spv::Op::OpImageSparseRead:
       // Atomic instructions.
-    case SpvOpAtomicLoad:
-    case SpvOpAtomicExchange:
-    case SpvOpAtomicCompareExchange:
-    case SpvOpAtomicCompareExchangeWeak:
-    case SpvOpAtomicIIncrement:
-    case SpvOpAtomicIDecrement:
-    case SpvOpAtomicIAdd:
-    case SpvOpAtomicISub:
-    case SpvOpAtomicSMin:
-    case SpvOpAtomicUMin:
-    case SpvOpAtomicSMax:
-    case SpvOpAtomicUMax:
-    case SpvOpAtomicAnd:
-    case SpvOpAtomicOr:
-    case SpvOpAtomicXor:
-    case SpvOpAtomicFlagTestAndSet:
+    case spv::Op::OpAtomicLoad:
+    case spv::Op::OpAtomicExchange:
+    case spv::Op::OpAtomicCompareExchange:
+    case spv::Op::OpAtomicCompareExchangeWeak:
+    case spv::Op::OpAtomicIIncrement:
+    case spv::Op::OpAtomicIDecrement:
+    case spv::Op::OpAtomicIAdd:
+    case spv::Op::OpAtomicISub:
+    case spv::Op::OpAtomicSMin:
+    case spv::Op::OpAtomicUMin:
+    case spv::Op::OpAtomicSMax:
+    case spv::Op::OpAtomicUMax:
+    case spv::Op::OpAtomicAnd:
+    case spv::Op::OpAtomicOr:
+    case spv::Op::OpAtomicXor:
+    case spv::Op::OpAtomicFlagTestAndSet:
       return true;
       // Extensions.
-    case SpvOpExtInst: {
+    case spv::Op::OpExtInst: {
       if (GetExtensionSet(ir_context, inst) != kExtensionSetName) {
         return false;
       }
@@ -419,53 +419,53 @@
 
   switch (inst.opcode()) {
       // Simple instructions.
-    case SpvOpLoad:
+    case spv::Op::OpLoad:
       // Image instructions.
-    case SpvOpImageSampleImplicitLod:
-    case SpvOpImageSampleExplicitLod:
-    case SpvOpImageSampleDrefImplicitLod:
-    case SpvOpImageSampleDrefExplicitLod:
-    case SpvOpImageSampleProjImplicitLod:
-    case SpvOpImageSampleProjExplicitLod:
-    case SpvOpImageSampleProjDrefImplicitLod:
-    case SpvOpImageSampleProjDrefExplicitLod:
-    case SpvOpImageFetch:
-    case SpvOpImageGather:
-    case SpvOpImageDrefGather:
-    case SpvOpImageRead:
-    case SpvOpImageSparseSampleImplicitLod:
-    case SpvOpImageSparseSampleExplicitLod:
-    case SpvOpImageSparseSampleDrefImplicitLod:
-    case SpvOpImageSparseSampleDrefExplicitLod:
-    case SpvOpImageSparseSampleProjImplicitLod:
-    case SpvOpImageSparseSampleProjExplicitLod:
-    case SpvOpImageSparseSampleProjDrefImplicitLod:
-    case SpvOpImageSparseSampleProjDrefExplicitLod:
-    case SpvOpImageSparseFetch:
-    case SpvOpImageSparseGather:
-    case SpvOpImageSparseDrefGather:
-    case SpvOpImageSparseRead:
+    case spv::Op::OpImageSampleImplicitLod:
+    case spv::Op::OpImageSampleExplicitLod:
+    case spv::Op::OpImageSampleDrefImplicitLod:
+    case spv::Op::OpImageSampleDrefExplicitLod:
+    case spv::Op::OpImageSampleProjImplicitLod:
+    case spv::Op::OpImageSampleProjExplicitLod:
+    case spv::Op::OpImageSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSampleProjDrefExplicitLod:
+    case spv::Op::OpImageFetch:
+    case spv::Op::OpImageGather:
+    case spv::Op::OpImageDrefGather:
+    case spv::Op::OpImageRead:
+    case spv::Op::OpImageSparseSampleImplicitLod:
+    case spv::Op::OpImageSparseSampleExplicitLod:
+    case spv::Op::OpImageSparseSampleDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleDrefExplicitLod:
+    case spv::Op::OpImageSparseSampleProjImplicitLod:
+    case spv::Op::OpImageSparseSampleProjExplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefExplicitLod:
+    case spv::Op::OpImageSparseFetch:
+    case spv::Op::OpImageSparseGather:
+    case spv::Op::OpImageSparseDrefGather:
+    case spv::Op::OpImageSparseRead:
       // Atomic instructions.
-    case SpvOpAtomicLoad:
-    case SpvOpAtomicExchange:
-    case SpvOpAtomicCompareExchange:
-    case SpvOpAtomicCompareExchangeWeak:
-    case SpvOpAtomicIIncrement:
-    case SpvOpAtomicIDecrement:
-    case SpvOpAtomicIAdd:
-    case SpvOpAtomicISub:
-    case SpvOpAtomicSMin:
-    case SpvOpAtomicUMin:
-    case SpvOpAtomicSMax:
-    case SpvOpAtomicUMax:
-    case SpvOpAtomicAnd:
-    case SpvOpAtomicOr:
-    case SpvOpAtomicXor:
-    case SpvOpAtomicFlagTestAndSet:
+    case spv::Op::OpAtomicLoad:
+    case spv::Op::OpAtomicExchange:
+    case spv::Op::OpAtomicCompareExchange:
+    case spv::Op::OpAtomicCompareExchangeWeak:
+    case spv::Op::OpAtomicIIncrement:
+    case spv::Op::OpAtomicIDecrement:
+    case spv::Op::OpAtomicIAdd:
+    case spv::Op::OpAtomicISub:
+    case spv::Op::OpAtomicSMin:
+    case spv::Op::OpAtomicUMin:
+    case spv::Op::OpAtomicSMax:
+    case spv::Op::OpAtomicUMax:
+    case spv::Op::OpAtomicAnd:
+    case spv::Op::OpAtomicOr:
+    case spv::Op::OpAtomicXor:
+    case spv::Op::OpAtomicFlagTestAndSet:
       return inst.GetSingleWordInOperand(0);
-    case SpvOpCopyMemory:
+    case spv::Op::OpCopyMemory:
       return inst.GetSingleWordInOperand(1);
-    case SpvOpExtInst: {
+    case spv::Op::OpExtInst: {
       assert(GetExtensionSet(ir_context, inst) == kExtensionSetName &&
              "Extension set is not supported");
 
@@ -493,31 +493,31 @@
     opt::IRContext* ir_context, const opt::Instruction& inst) {
   switch (inst.opcode()) {
       // Simple Instructions.
-    case SpvOpStore:
-    case SpvOpCopyMemory:
+    case spv::Op::OpStore:
+    case spv::Op::OpCopyMemory:
       // Image instructions.
-    case SpvOpImageWrite:
+    case spv::Op::OpImageWrite:
       // Atomic instructions.
-    case SpvOpAtomicStore:
-    case SpvOpAtomicExchange:
-    case SpvOpAtomicCompareExchange:
-    case SpvOpAtomicCompareExchangeWeak:
-    case SpvOpAtomicIIncrement:
-    case SpvOpAtomicIDecrement:
-    case SpvOpAtomicIAdd:
-    case SpvOpAtomicISub:
-    case SpvOpAtomicSMin:
-    case SpvOpAtomicUMin:
-    case SpvOpAtomicSMax:
-    case SpvOpAtomicUMax:
-    case SpvOpAtomicAnd:
-    case SpvOpAtomicOr:
-    case SpvOpAtomicXor:
-    case SpvOpAtomicFlagTestAndSet:
-    case SpvOpAtomicFlagClear:
+    case spv::Op::OpAtomicStore:
+    case spv::Op::OpAtomicExchange:
+    case spv::Op::OpAtomicCompareExchange:
+    case spv::Op::OpAtomicCompareExchangeWeak:
+    case spv::Op::OpAtomicIIncrement:
+    case spv::Op::OpAtomicIDecrement:
+    case spv::Op::OpAtomicIAdd:
+    case spv::Op::OpAtomicISub:
+    case spv::Op::OpAtomicSMin:
+    case spv::Op::OpAtomicUMin:
+    case spv::Op::OpAtomicSMax:
+    case spv::Op::OpAtomicUMax:
+    case spv::Op::OpAtomicAnd:
+    case spv::Op::OpAtomicOr:
+    case spv::Op::OpAtomicXor:
+    case spv::Op::OpAtomicFlagTestAndSet:
+    case spv::Op::OpAtomicFlagClear:
       return true;
       // Extensions.
-    case SpvOpExtInst: {
+    case spv::Op::OpExtInst: {
       if (GetExtensionSet(ir_context, inst) != kExtensionSetName) {
         return false;
       }
@@ -537,28 +537,28 @@
          "|inst| is not a memory write instruction");
 
   switch (inst.opcode()) {
-    case SpvOpStore:
-    case SpvOpCopyMemory:
-    case SpvOpImageWrite:
-    case SpvOpAtomicStore:
-    case SpvOpAtomicExchange:
-    case SpvOpAtomicCompareExchange:
-    case SpvOpAtomicCompareExchangeWeak:
-    case SpvOpAtomicIIncrement:
-    case SpvOpAtomicIDecrement:
-    case SpvOpAtomicIAdd:
-    case SpvOpAtomicISub:
-    case SpvOpAtomicSMin:
-    case SpvOpAtomicUMin:
-    case SpvOpAtomicSMax:
-    case SpvOpAtomicUMax:
-    case SpvOpAtomicAnd:
-    case SpvOpAtomicOr:
-    case SpvOpAtomicXor:
-    case SpvOpAtomicFlagTestAndSet:
-    case SpvOpAtomicFlagClear:
+    case spv::Op::OpStore:
+    case spv::Op::OpCopyMemory:
+    case spv::Op::OpImageWrite:
+    case spv::Op::OpAtomicStore:
+    case spv::Op::OpAtomicExchange:
+    case spv::Op::OpAtomicCompareExchange:
+    case spv::Op::OpAtomicCompareExchangeWeak:
+    case spv::Op::OpAtomicIIncrement:
+    case spv::Op::OpAtomicIDecrement:
+    case spv::Op::OpAtomicIAdd:
+    case spv::Op::OpAtomicISub:
+    case spv::Op::OpAtomicSMin:
+    case spv::Op::OpAtomicUMin:
+    case spv::Op::OpAtomicSMax:
+    case spv::Op::OpAtomicUMax:
+    case spv::Op::OpAtomicAnd:
+    case spv::Op::OpAtomicOr:
+    case spv::Op::OpAtomicXor:
+    case spv::Op::OpAtomicFlagTestAndSet:
+    case spv::Op::OpAtomicFlagClear:
       return inst.GetSingleWordInOperand(0);
-    case SpvOpExtInst: {
+    case spv::Op::OpExtInst: {
       assert(GetExtensionSet(ir_context, inst) == kExtensionSetName &&
              "Extension set is not supported");
 
@@ -590,9 +590,9 @@
 bool TransformationMoveInstructionDown::IsBarrierInstruction(
     const opt::Instruction& inst) {
   switch (inst.opcode()) {
-    case SpvOpMemoryBarrier:
-    case SpvOpControlBarrier:
-    case SpvOpMemoryNamedBarrier:
+    case spv::Op::OpMemoryBarrier:
+    case spv::Op::OpControlBarrier:
+    case spv::Op::OpMemoryNamedBarrier:
       return true;
     default:
       return false;
diff --git a/source/fuzz/transformation_mutate_pointer.cpp b/source/fuzz/transformation_mutate_pointer.cpp
index 516a0d6..a1620cc 100644
--- a/source/fuzz/transformation_mutate_pointer.cpp
+++ b/source/fuzz/transformation_mutate_pointer.cpp
@@ -51,7 +51,7 @@
   // Check that it is possible to insert OpLoad and OpStore before
   // |insert_before_inst|. We are only using OpLoad here since the result does
   // not depend on the opcode.
-  if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpLoad,
+  if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpLoad,
                                                     insert_before_inst)) {
     return false;
   }
@@ -100,7 +100,7 @@
 
   // Back up the original value.
   auto backup_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpLoad, pointee_type_id, message_.fresh_id(),
+      ir_context, spv::Op::OpLoad, pointee_type_id, message_.fresh_id(),
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {message_.pointer_id()}}});
   auto backup_instruction_ptr = backup_instruction.get();
@@ -110,7 +110,7 @@
 
   // Insert a new value.
   auto new_value_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpStore, 0, 0,
+      ir_context, spv::Op::OpStore, 0, 0,
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {message_.pointer_id()}},
           {SPV_OPERAND_TYPE_ID,
@@ -123,7 +123,7 @@
 
   // Restore the original value.
   auto restore_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpStore, 0, 0,
+      ir_context, spv::Op::OpStore, 0, 0,
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {message_.pointer_id()}},
           {SPV_OPERAND_TYPE_ID, {message_.fresh_id()}}});
@@ -145,8 +145,9 @@
     opt::IRContext* ir_context, const opt::Instruction& inst) {
   // |inst| must have both result id and type id and it may not cause undefined
   // behaviour.
-  if (!inst.result_id() || !inst.type_id() || inst.opcode() == SpvOpUndef ||
-      inst.opcode() == SpvOpConstantNull) {
+  if (!inst.result_id() || !inst.type_id() ||
+      inst.opcode() == spv::Op::OpUndef ||
+      inst.opcode() == spv::Op::OpConstantNull) {
     return false;
   }
 
@@ -155,15 +156,16 @@
   assert(type_inst != nullptr && "|inst| has invalid type id");
 
   // |inst| must be a pointer.
-  if (type_inst->opcode() != SpvOpTypePointer) {
+  if (type_inst->opcode() != spv::Op::OpTypePointer) {
     return false;
   }
 
   // |inst| must have a supported storage class.
-  switch (static_cast<SpvStorageClass>(type_inst->GetSingleWordInOperand(0))) {
-    case SpvStorageClassFunction:
-    case SpvStorageClassPrivate:
-    case SpvStorageClassWorkgroup:
+  switch (
+      static_cast<spv::StorageClass>(type_inst->GetSingleWordInOperand(0))) {
+    case spv::StorageClass::Function:
+    case spv::StorageClass::Private:
+    case spv::StorageClass::Workgroup:
       break;
     default:
       return false;
diff --git a/source/fuzz/transformation_outline_function.cpp b/source/fuzz/transformation_outline_function.cpp
index 3140fa6..4ab68d0 100644
--- a/source/fuzz/transformation_outline_function.cpp
+++ b/source/fuzz/transformation_outline_function.cpp
@@ -107,7 +107,7 @@
   // The entry and exit block ids must indeed refer to blocks.
   for (auto block_id : {message_.entry_block(), message_.exit_block()}) {
     auto block_label = ir_context->get_def_use_mgr()->GetDef(block_id);
-    if (!block_label || block_label->opcode() != SpvOpLabel) {
+    if (!block_label || block_label->opcode() != spv::Op::OpLabel) {
       return false;
     }
   }
@@ -118,7 +118,7 @@
   // The entry block cannot start with OpVariable - this would mean that
   // outlining would remove a variable from the function containing the region
   // being outlined.
-  if (entry_block->begin()->opcode() == SpvOpVariable) {
+  if (entry_block->begin()->opcode() == spv::Op::OpVariable) {
     return false;
   }
 
@@ -136,7 +136,7 @@
   // The entry block cannot start with OpPhi.  This is to keep the
   // transformation logic simple.  (Another transformation to split the OpPhis
   // from a block could be applied to avoid this scenario.)
-  if (entry_block->begin()->opcode() == SpvOpPhi) {
+  if (entry_block->begin()->opcode() == spv::Op::OpPhi) {
     return false;
   }
 
@@ -257,10 +257,10 @@
     auto input_id_inst = ir_context->get_def_use_mgr()->GetDef(id);
     if (ir_context->get_def_use_mgr()
             ->GetDef(input_id_inst->type_id())
-            ->opcode() == SpvOpTypePointer) {
+            ->opcode() == spv::Op::OpTypePointer) {
       switch (input_id_inst->opcode()) {
-        case SpvOpFunctionParameter:
-        case SpvOpVariable:
+        case spv::Op::OpFunctionParameter:
+        case spv::Op::OpVariable:
           // These are OK.
           break;
         default:
@@ -286,7 +286,7 @@
         // function)
         || ir_context->get_def_use_mgr()
                    ->GetDef(fuzzerutil::GetTypeId(ir_context, id))
-                   ->opcode() == SpvOpTypePointer) {
+                   ->opcode() == spv::Op::OpTypePointer) {
       return false;
     }
   }
@@ -608,7 +608,7 @@
         auto output_id_type =
             ir_context->get_def_use_mgr()->GetDef(output_id)->type_id();
         if (ir_context->get_def_use_mgr()->GetDef(output_id_type)->opcode() ==
-            SpvOpTypeVoid) {
+            spv::Op::OpTypeVoid) {
           // We cannot add a void field to a struct.  We instead use OpUndef to
           // handle void output ids.
           continue;
@@ -617,7 +617,7 @@
       }
       // Add a new struct type to the module.
       ir_context->module()->AddType(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpTypeStruct, 0,
+          ir_context, spv::Op::OpTypeStruct, 0,
           message_.new_function_struct_return_type_id(),
           std::move(struct_member_types)));
       // The return type for the function is the newly-created struct.
@@ -638,7 +638,7 @@
     // Add a new function type to the module, and record that this is the type
     // id for the new function.
     ir_context->module()->AddType(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpTypeFunction, 0, message_.new_function_type_id(),
+        ir_context, spv::Op::OpTypeFunction, 0, message_.new_function_type_id(),
         function_type_operands));
     function_type_id = message_.new_function_type_id();
   }
@@ -647,10 +647,11 @@
   // and the return type and function type prepared above.
   std::unique_ptr<opt::Function> outlined_function =
       MakeUnique<opt::Function>(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpFunction, return_type_id, message_.new_function_id(),
+          ir_context, spv::Op::OpFunction, return_type_id,
+          message_.new_function_id(),
           opt::Instruction::OperandList(
               {{spv_operand_type_t ::SPV_OPERAND_TYPE_LITERAL_INTEGER,
-                {SpvFunctionControlMaskNone}},
+                {uint32_t(spv::FunctionControlMask::MaskNone)}},
                {spv_operand_type_t::SPV_OPERAND_TYPE_ID,
                 {function_type_id}}})));
 
@@ -659,7 +660,7 @@
   for (auto id : region_input_ids) {
     uint32_t fresh_id = input_id_to_fresh_id_map.at(id);
     outlined_function->AddParameter(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpFunctionParameter,
+        ir_context, spv::Op::OpFunctionParameter,
         ir_context->get_def_use_mgr()->GetDef(id)->type_id(), fresh_id,
         opt::Instruction::OperandList()));
 
@@ -788,7 +789,8 @@
   // |message_.new_function_region_entry_block| as its id.
   std::unique_ptr<opt::BasicBlock> outlined_region_entry_block =
       MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpLabel, 0, message_.new_function_region_entry_block(),
+          ir_context, spv::Op::OpLabel, 0,
+          message_.new_function_region_entry_block(),
           opt::Instruction::OperandList()));
 
   if (&original_region_entry_block == &original_region_exit_block) {
@@ -854,8 +856,8 @@
   // the cloned exit block.
   for (auto inst_it = outlined_region_exit_block->begin();
        inst_it != outlined_region_exit_block->end();) {
-    if (inst_it->opcode() == SpvOpLoopMerge ||
-        inst_it->opcode() == SpvOpSelectionMerge) {
+    if (inst_it->opcode() == spv::Op::OpLoopMerge ||
+        inst_it->opcode() == spv::Op::OpSelectionMerge) {
       inst_it = inst_it.Erase();
     } else if (inst_it->IsBlockTerminator()) {
       inst_it = inst_it.Erase();
@@ -870,7 +872,7 @@
     // The case where there are no region output ids is simple: we just add
     // OpReturn.
     outlined_region_exit_block->AddInstruction(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpReturn, 0, 0, opt::Instruction::OperandList()));
+        ir_context, spv::Op::OpReturn, 0, 0, opt::Instruction::OperandList()));
   } else {
     // In the case where there are output ids, we add an OpCompositeConstruct
     // instruction to pack all the non-void output values into a struct, and
@@ -879,23 +881,24 @@
     for (uint32_t id : region_output_ids) {
       if (ir_context->get_def_use_mgr()
               ->GetDef(output_id_to_type_id.at(id))
-              ->opcode() != SpvOpTypeVoid) {
+              ->opcode() != spv::Op::OpTypeVoid) {
         struct_member_operands.push_back(
             {SPV_OPERAND_TYPE_ID, {output_id_to_fresh_id_map.at(id)}});
       }
     }
     outlined_region_exit_block->AddInstruction(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeConstruct,
+        ir_context, spv::Op::OpCompositeConstruct,
         message_.new_function_struct_return_type_id(),
         message_.new_callee_result_id(), struct_member_operands));
     outlined_region_exit_block->AddInstruction(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpReturnValue, 0, 0,
+        ir_context, spv::Op::OpReturnValue, 0, 0,
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {message_.new_callee_result_id()}}})));
   }
 
-  outlined_function->SetFunctionEnd(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpFunctionEnd, 0, 0, opt::Instruction::OperandList()));
+  outlined_function->SetFunctionEnd(
+      MakeUnique<opt::Instruction>(ir_context, spv::Op::OpFunctionEnd, 0, 0,
+                                   opt::Instruction::OperandList()));
 }
 
 void TransformationOutlineFunction::ShrinkOriginalRegion(
@@ -963,7 +966,7 @@
   }
 
   original_region_entry_block->AddInstruction(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpFunctionCall, return_type_id,
+      ir_context, spv::Op::OpFunctionCall, return_type_id,
       message_.new_caller_result_id(), function_call_operands));
 
   // If there are output ids, the function call will return a struct.  For each
@@ -975,15 +978,15 @@
   for (uint32_t output_id : region_output_ids) {
     uint32_t output_type_id = output_id_to_type_id.at(output_id);
     if (ir_context->get_def_use_mgr()->GetDef(output_type_id)->opcode() ==
-        SpvOpTypeVoid) {
+        spv::Op::OpTypeVoid) {
       original_region_entry_block->AddInstruction(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpUndef, output_type_id, output_id,
+          ir_context, spv::Op::OpUndef, output_type_id, output_id,
           opt::Instruction::OperandList()));
       // struct_member_index is not incremented since there was no struct member
       // associated with this void-typed output id.
     } else {
       original_region_entry_block->AddInstruction(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpCompositeExtract, output_type_id, output_id,
+          ir_context, spv::Op::OpCompositeExtract, output_type_id, output_id,
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID, {message_.new_caller_result_id()}},
                {SPV_OPERAND_TYPE_LITERAL_INTEGER, {struct_member_index}}})));
diff --git a/source/fuzz/transformation_permute_function_parameters.cpp b/source/fuzz/transformation_permute_function_parameters.cpp
index 5663d72..b666cdf 100644
--- a/source/fuzz/transformation_permute_function_parameters.cpp
+++ b/source/fuzz/transformation_permute_function_parameters.cpp
@@ -43,7 +43,7 @@
   // Check that function exists
   const auto* function =
       fuzzerutil::FindFunction(ir_context, message_.function_id());
-  if (!function || function->DefInst().opcode() != SpvOpFunction ||
+  if (!function || function->DefInst().opcode() != spv::Op::OpFunction ||
       fuzzerutil::FunctionIsEntryPoint(ir_context, function->result_id())) {
     return false;
   }
diff --git a/source/fuzz/transformation_permute_phi_operands.cpp b/source/fuzz/transformation_permute_phi_operands.cpp
index 7ee7a82..f2f4057 100644
--- a/source/fuzz/transformation_permute_phi_operands.cpp
+++ b/source/fuzz/transformation_permute_phi_operands.cpp
@@ -39,7 +39,7 @@
   // Check that |message_.result_id| is valid.
   const auto* inst =
       ir_context->get_def_use_mgr()->GetDef(message_.result_id());
-  if (!inst || inst->opcode() != SpvOpPhi) {
+  if (!inst || inst->opcode() != spv::Op::OpPhi) {
     return false;
   }
 
diff --git a/source/fuzz/transformation_propagate_instruction_down.cpp b/source/fuzz/transformation_propagate_instruction_down.cpp
index c3b7c4d..4b98784 100644
--- a/source/fuzz/transformation_propagate_instruction_down.cpp
+++ b/source/fuzz/transformation_propagate_instruction_down.cpp
@@ -144,7 +144,7 @@
         ->block(merge_block_id)
         ->begin()
         ->InsertBefore(MakeUnique<opt::Instruction>(
-            ir_context, SpvOpPhi, inst_to_propagate->type_id(),
+            ir_context, spv::Op::OpPhi, inst_to_propagate->type_id(),
             message_.phi_fresh_id(), std::move(in_operands)));
 
     fuzzerutil::UpdateModuleIdBound(ir_context, message_.phi_fresh_id());
@@ -234,115 +234,115 @@
   return result;
 }
 
-bool TransformationPropagateInstructionDown::IsOpcodeSupported(SpvOp opcode) {
+bool TransformationPropagateInstructionDown::IsOpcodeSupported(spv::Op opcode) {
   // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3605):
   //  We only support "simple" instructions that don't work with memory.
   //  We should extend this so that we support the ones that modify the memory
   //  too.
   switch (opcode) {
-    case SpvOpUndef:
-    case SpvOpAccessChain:
-    case SpvOpInBoundsAccessChain:
-    case SpvOpArrayLength:
-    case SpvOpVectorExtractDynamic:
-    case SpvOpVectorInsertDynamic:
-    case SpvOpVectorShuffle:
-    case SpvOpCompositeConstruct:
-    case SpvOpCompositeExtract:
-    case SpvOpCompositeInsert:
-    case SpvOpCopyObject:
-    case SpvOpTranspose:
-    case SpvOpConvertFToU:
-    case SpvOpConvertFToS:
-    case SpvOpConvertSToF:
-    case SpvOpConvertUToF:
-    case SpvOpUConvert:
-    case SpvOpSConvert:
-    case SpvOpFConvert:
-    case SpvOpQuantizeToF16:
-    case SpvOpSatConvertSToU:
-    case SpvOpSatConvertUToS:
-    case SpvOpBitcast:
-    case SpvOpSNegate:
-    case SpvOpFNegate:
-    case SpvOpIAdd:
-    case SpvOpFAdd:
-    case SpvOpISub:
-    case SpvOpFSub:
-    case SpvOpIMul:
-    case SpvOpFMul:
-    case SpvOpUDiv:
-    case SpvOpSDiv:
-    case SpvOpFDiv:
-    case SpvOpUMod:
-    case SpvOpSRem:
-    case SpvOpSMod:
-    case SpvOpFRem:
-    case SpvOpFMod:
-    case SpvOpVectorTimesScalar:
-    case SpvOpMatrixTimesScalar:
-    case SpvOpVectorTimesMatrix:
-    case SpvOpMatrixTimesVector:
-    case SpvOpMatrixTimesMatrix:
-    case SpvOpOuterProduct:
-    case SpvOpDot:
-    case SpvOpIAddCarry:
-    case SpvOpISubBorrow:
-    case SpvOpUMulExtended:
-    case SpvOpSMulExtended:
-    case SpvOpAny:
-    case SpvOpAll:
-    case SpvOpIsNan:
-    case SpvOpIsInf:
-    case SpvOpIsFinite:
-    case SpvOpIsNormal:
-    case SpvOpSignBitSet:
-    case SpvOpLessOrGreater:
-    case SpvOpOrdered:
-    case SpvOpUnordered:
-    case SpvOpLogicalEqual:
-    case SpvOpLogicalNotEqual:
-    case SpvOpLogicalOr:
-    case SpvOpLogicalAnd:
-    case SpvOpLogicalNot:
-    case SpvOpSelect:
-    case SpvOpIEqual:
-    case SpvOpINotEqual:
-    case SpvOpUGreaterThan:
-    case SpvOpSGreaterThan:
-    case SpvOpUGreaterThanEqual:
-    case SpvOpSGreaterThanEqual:
-    case SpvOpULessThan:
-    case SpvOpSLessThan:
-    case SpvOpULessThanEqual:
-    case SpvOpSLessThanEqual:
-    case SpvOpFOrdEqual:
-    case SpvOpFUnordEqual:
-    case SpvOpFOrdNotEqual:
-    case SpvOpFUnordNotEqual:
-    case SpvOpFOrdLessThan:
-    case SpvOpFUnordLessThan:
-    case SpvOpFOrdGreaterThan:
-    case SpvOpFUnordGreaterThan:
-    case SpvOpFOrdLessThanEqual:
-    case SpvOpFUnordLessThanEqual:
-    case SpvOpFOrdGreaterThanEqual:
-    case SpvOpFUnordGreaterThanEqual:
-    case SpvOpShiftRightLogical:
-    case SpvOpShiftRightArithmetic:
-    case SpvOpShiftLeftLogical:
-    case SpvOpBitwiseOr:
-    case SpvOpBitwiseXor:
-    case SpvOpBitwiseAnd:
-    case SpvOpNot:
-    case SpvOpBitFieldInsert:
-    case SpvOpBitFieldSExtract:
-    case SpvOpBitFieldUExtract:
-    case SpvOpBitReverse:
-    case SpvOpBitCount:
-    case SpvOpCopyLogical:
-    case SpvOpPtrEqual:
-    case SpvOpPtrNotEqual:
+    case spv::Op::OpUndef:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
+    case spv::Op::OpArrayLength:
+    case spv::Op::OpVectorExtractDynamic:
+    case spv::Op::OpVectorInsertDynamic:
+    case spv::Op::OpVectorShuffle:
+    case spv::Op::OpCompositeConstruct:
+    case spv::Op::OpCompositeExtract:
+    case spv::Op::OpCompositeInsert:
+    case spv::Op::OpCopyObject:
+    case spv::Op::OpTranspose:
+    case spv::Op::OpConvertFToU:
+    case spv::Op::OpConvertFToS:
+    case spv::Op::OpConvertSToF:
+    case spv::Op::OpConvertUToF:
+    case spv::Op::OpUConvert:
+    case spv::Op::OpSConvert:
+    case spv::Op::OpFConvert:
+    case spv::Op::OpQuantizeToF16:
+    case spv::Op::OpSatConvertSToU:
+    case spv::Op::OpSatConvertUToS:
+    case spv::Op::OpBitcast:
+    case spv::Op::OpSNegate:
+    case spv::Op::OpFNegate:
+    case spv::Op::OpIAdd:
+    case spv::Op::OpFAdd:
+    case spv::Op::OpISub:
+    case spv::Op::OpFSub:
+    case spv::Op::OpIMul:
+    case spv::Op::OpFMul:
+    case spv::Op::OpUDiv:
+    case spv::Op::OpSDiv:
+    case spv::Op::OpFDiv:
+    case spv::Op::OpUMod:
+    case spv::Op::OpSRem:
+    case spv::Op::OpSMod:
+    case spv::Op::OpFRem:
+    case spv::Op::OpFMod:
+    case spv::Op::OpVectorTimesScalar:
+    case spv::Op::OpMatrixTimesScalar:
+    case spv::Op::OpVectorTimesMatrix:
+    case spv::Op::OpMatrixTimesVector:
+    case spv::Op::OpMatrixTimesMatrix:
+    case spv::Op::OpOuterProduct:
+    case spv::Op::OpDot:
+    case spv::Op::OpIAddCarry:
+    case spv::Op::OpISubBorrow:
+    case spv::Op::OpUMulExtended:
+    case spv::Op::OpSMulExtended:
+    case spv::Op::OpAny:
+    case spv::Op::OpAll:
+    case spv::Op::OpIsNan:
+    case spv::Op::OpIsInf:
+    case spv::Op::OpIsFinite:
+    case spv::Op::OpIsNormal:
+    case spv::Op::OpSignBitSet:
+    case spv::Op::OpLessOrGreater:
+    case spv::Op::OpOrdered:
+    case spv::Op::OpUnordered:
+    case spv::Op::OpLogicalEqual:
+    case spv::Op::OpLogicalNotEqual:
+    case spv::Op::OpLogicalOr:
+    case spv::Op::OpLogicalAnd:
+    case spv::Op::OpLogicalNot:
+    case spv::Op::OpSelect:
+    case spv::Op::OpIEqual:
+    case spv::Op::OpINotEqual:
+    case spv::Op::OpUGreaterThan:
+    case spv::Op::OpSGreaterThan:
+    case spv::Op::OpUGreaterThanEqual:
+    case spv::Op::OpSGreaterThanEqual:
+    case spv::Op::OpULessThan:
+    case spv::Op::OpSLessThan:
+    case spv::Op::OpULessThanEqual:
+    case spv::Op::OpSLessThanEqual:
+    case spv::Op::OpFOrdEqual:
+    case spv::Op::OpFUnordEqual:
+    case spv::Op::OpFOrdNotEqual:
+    case spv::Op::OpFUnordNotEqual:
+    case spv::Op::OpFOrdLessThan:
+    case spv::Op::OpFUnordLessThan:
+    case spv::Op::OpFOrdGreaterThan:
+    case spv::Op::OpFUnordGreaterThan:
+    case spv::Op::OpFOrdLessThanEqual:
+    case spv::Op::OpFUnordLessThanEqual:
+    case spv::Op::OpFOrdGreaterThanEqual:
+    case spv::Op::OpFUnordGreaterThanEqual:
+    case spv::Op::OpShiftRightLogical:
+    case spv::Op::OpShiftRightArithmetic:
+    case spv::Op::OpShiftLeftLogical:
+    case spv::Op::OpBitwiseOr:
+    case spv::Op::OpBitwiseXor:
+    case spv::Op::OpBitwiseAnd:
+    case spv::Op::OpNot:
+    case spv::Op::OpBitFieldInsert:
+    case spv::Op::OpBitFieldSExtract:
+    case spv::Op::OpBitFieldUExtract:
+    case spv::Op::OpBitReverse:
+    case spv::Op::OpBitCount:
+    case spv::Op::OpCopyLogical:
+    case spv::Op::OpPtrEqual:
+    case spv::Op::OpPtrNotEqual:
       return true;
     default:
       return false;
@@ -408,7 +408,7 @@
   // use |inst|.
   for (auto successor_id : successor_ids) {
     for (const auto& maybe_phi_inst : *ir_context->cfg()->block(successor_id)) {
-      if (maybe_phi_inst.opcode() != SpvOpPhi) {
+      if (maybe_phi_inst.opcode() != spv::Op::OpPhi) {
         // OpPhis can be intermixed with OpLine and OpNoLine.
         continue;
       }
@@ -446,7 +446,7 @@
         // |phi_block_id| dominates |user|'s block (or its predecessor if the
         // user is an OpPhi). We can't use fuzzerutil::IdIsAvailableAtUse since
         // the id in question hasn't yet been created in the module.
-        auto block_id_to_dominate = user->opcode() == SpvOpPhi
+        auto block_id_to_dominate = user->opcode() == spv::Op::OpPhi
                                         ? user->GetSingleWordOperand(index + 1)
                                         : user_block->id();
 
@@ -465,7 +465,7 @@
 
 opt::Instruction*
 TransformationPropagateInstructionDown::GetFirstInsertBeforeInstruction(
-    opt::IRContext* ir_context, uint32_t block_id, SpvOp opcode) {
+    opt::IRContext* ir_context, uint32_t block_id, spv::Op opcode) {
   auto* block = ir_context->cfg()->block(block_id);
 
   auto it = block->begin();
@@ -572,7 +572,7 @@
   // OpPhi instructions cannot have operands of pointer types.
   if (propagate_type->AsPointer() &&
       !ir_context->get_feature_mgr()->HasCapability(
-          SpvCapabilityVariablePointersStorageBuffer)) {
+          spv::Capability::VariablePointersStorageBuffer)) {
     return 0;
   }
 
diff --git a/source/fuzz/transformation_propagate_instruction_down.h b/source/fuzz/transformation_propagate_instruction_down.h
index 560d7dc..9133928 100644
--- a/source/fuzz/transformation_propagate_instruction_down.h
+++ b/source/fuzz/transformation_propagate_instruction_down.h
@@ -120,12 +120,12 @@
                                                      uint32_t block_id);
 
   // Returns true if |opcode| is supported by this transformation.
-  static bool IsOpcodeSupported(SpvOp opcode);
+  static bool IsOpcodeSupported(spv::Op opcode);
 
   // Returns the first instruction in the |block| that allows us to insert
   // |opcode| above itself. Returns nullptr is no such instruction exists.
   static opt::Instruction* GetFirstInsertBeforeInstruction(
-      opt::IRContext* ir_context, uint32_t block_id, SpvOp opcode);
+      opt::IRContext* ir_context, uint32_t block_id, spv::Op opcode);
 
   // Returns a result id of a basic block, where an OpPhi instruction can be
   // inserted. Returns nullptr if it's not possible to create an OpPhi. The
diff --git a/source/fuzz/transformation_propagate_instruction_up.cpp b/source/fuzz/transformation_propagate_instruction_up.cpp
index bf0e663..f9674fa 100644
--- a/source/fuzz/transformation_propagate_instruction_up.cpp
+++ b/source/fuzz/transformation_propagate_instruction_up.cpp
@@ -23,7 +23,7 @@
 
 uint32_t GetResultIdFromLabelId(const opt::Instruction& phi_inst,
                                 uint32_t label_id) {
-  assert(phi_inst.opcode() == SpvOpPhi && "|phi_inst| is not an OpPhi");
+  assert(phi_inst.opcode() == spv::Op::OpPhi && "|phi_inst| is not an OpPhi");
 
   for (uint32_t i = 1; i < phi_inst.NumInOperands(); i += 2) {
     if (phi_inst.GetSingleWordInOperand(i) == label_id) {
@@ -66,7 +66,7 @@
     assert(dependency && "Operand has invalid id");
 
     if (ir_context->get_instr_block(dependency) == inst_block &&
-        dependency->opcode() != SpvOpPhi) {
+        dependency->opcode() != spv::Op::OpPhi) {
       // |dependency| is "valid" if it's an OpPhi from the same basic block or
       // an instruction from a different basic block.
       return false;
@@ -173,7 +173,7 @@
         continue;
       }
 
-      assert(dependency_inst->opcode() == SpvOpPhi &&
+      assert(dependency_inst->opcode() == spv::Op::OpPhi &&
              "Propagated instruction can depend only on OpPhis from the same "
              "basic block or instructions from different basic blocks");
 
@@ -191,7 +191,7 @@
 
   // Insert an OpPhi instruction into the basic block of |inst|.
   ir_context->get_instr_block(inst)->begin()->InsertBefore(
-      MakeUnique<opt::Instruction>(ir_context, SpvOpPhi, inst->type_id(),
+      MakeUnique<opt::Instruction>(ir_context, spv::Op::OpPhi, inst->type_id(),
                                    inst->result_id(),
                                    std::move(op_phi_operands)));
 
@@ -210,115 +210,115 @@
   return result;
 }
 
-bool TransformationPropagateInstructionUp::IsOpcodeSupported(SpvOp opcode) {
+bool TransformationPropagateInstructionUp::IsOpcodeSupported(spv::Op opcode) {
   // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3605):
   //  We only support "simple" instructions that don't work with memory.
   //  We should extend this so that we support the ones that modify the memory
   //  too.
   switch (opcode) {
-    case SpvOpUndef:
-    case SpvOpAccessChain:
-    case SpvOpInBoundsAccessChain:
-    case SpvOpArrayLength:
-    case SpvOpVectorExtractDynamic:
-    case SpvOpVectorInsertDynamic:
-    case SpvOpVectorShuffle:
-    case SpvOpCompositeConstruct:
-    case SpvOpCompositeExtract:
-    case SpvOpCompositeInsert:
-    case SpvOpCopyObject:
-    case SpvOpTranspose:
-    case SpvOpConvertFToU:
-    case SpvOpConvertFToS:
-    case SpvOpConvertSToF:
-    case SpvOpConvertUToF:
-    case SpvOpUConvert:
-    case SpvOpSConvert:
-    case SpvOpFConvert:
-    case SpvOpQuantizeToF16:
-    case SpvOpSatConvertSToU:
-    case SpvOpSatConvertUToS:
-    case SpvOpBitcast:
-    case SpvOpSNegate:
-    case SpvOpFNegate:
-    case SpvOpIAdd:
-    case SpvOpFAdd:
-    case SpvOpISub:
-    case SpvOpFSub:
-    case SpvOpIMul:
-    case SpvOpFMul:
-    case SpvOpUDiv:
-    case SpvOpSDiv:
-    case SpvOpFDiv:
-    case SpvOpUMod:
-    case SpvOpSRem:
-    case SpvOpSMod:
-    case SpvOpFRem:
-    case SpvOpFMod:
-    case SpvOpVectorTimesScalar:
-    case SpvOpMatrixTimesScalar:
-    case SpvOpVectorTimesMatrix:
-    case SpvOpMatrixTimesVector:
-    case SpvOpMatrixTimesMatrix:
-    case SpvOpOuterProduct:
-    case SpvOpDot:
-    case SpvOpIAddCarry:
-    case SpvOpISubBorrow:
-    case SpvOpUMulExtended:
-    case SpvOpSMulExtended:
-    case SpvOpAny:
-    case SpvOpAll:
-    case SpvOpIsNan:
-    case SpvOpIsInf:
-    case SpvOpIsFinite:
-    case SpvOpIsNormal:
-    case SpvOpSignBitSet:
-    case SpvOpLessOrGreater:
-    case SpvOpOrdered:
-    case SpvOpUnordered:
-    case SpvOpLogicalEqual:
-    case SpvOpLogicalNotEqual:
-    case SpvOpLogicalOr:
-    case SpvOpLogicalAnd:
-    case SpvOpLogicalNot:
-    case SpvOpSelect:
-    case SpvOpIEqual:
-    case SpvOpINotEqual:
-    case SpvOpUGreaterThan:
-    case SpvOpSGreaterThan:
-    case SpvOpUGreaterThanEqual:
-    case SpvOpSGreaterThanEqual:
-    case SpvOpULessThan:
-    case SpvOpSLessThan:
-    case SpvOpULessThanEqual:
-    case SpvOpSLessThanEqual:
-    case SpvOpFOrdEqual:
-    case SpvOpFUnordEqual:
-    case SpvOpFOrdNotEqual:
-    case SpvOpFUnordNotEqual:
-    case SpvOpFOrdLessThan:
-    case SpvOpFUnordLessThan:
-    case SpvOpFOrdGreaterThan:
-    case SpvOpFUnordGreaterThan:
-    case SpvOpFOrdLessThanEqual:
-    case SpvOpFUnordLessThanEqual:
-    case SpvOpFOrdGreaterThanEqual:
-    case SpvOpFUnordGreaterThanEqual:
-    case SpvOpShiftRightLogical:
-    case SpvOpShiftRightArithmetic:
-    case SpvOpShiftLeftLogical:
-    case SpvOpBitwiseOr:
-    case SpvOpBitwiseXor:
-    case SpvOpBitwiseAnd:
-    case SpvOpNot:
-    case SpvOpBitFieldInsert:
-    case SpvOpBitFieldSExtract:
-    case SpvOpBitFieldUExtract:
-    case SpvOpBitReverse:
-    case SpvOpBitCount:
-    case SpvOpCopyLogical:
-    case SpvOpPtrEqual:
-    case SpvOpPtrNotEqual:
+    case spv::Op::OpUndef:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
+    case spv::Op::OpArrayLength:
+    case spv::Op::OpVectorExtractDynamic:
+    case spv::Op::OpVectorInsertDynamic:
+    case spv::Op::OpVectorShuffle:
+    case spv::Op::OpCompositeConstruct:
+    case spv::Op::OpCompositeExtract:
+    case spv::Op::OpCompositeInsert:
+    case spv::Op::OpCopyObject:
+    case spv::Op::OpTranspose:
+    case spv::Op::OpConvertFToU:
+    case spv::Op::OpConvertFToS:
+    case spv::Op::OpConvertSToF:
+    case spv::Op::OpConvertUToF:
+    case spv::Op::OpUConvert:
+    case spv::Op::OpSConvert:
+    case spv::Op::OpFConvert:
+    case spv::Op::OpQuantizeToF16:
+    case spv::Op::OpSatConvertSToU:
+    case spv::Op::OpSatConvertUToS:
+    case spv::Op::OpBitcast:
+    case spv::Op::OpSNegate:
+    case spv::Op::OpFNegate:
+    case spv::Op::OpIAdd:
+    case spv::Op::OpFAdd:
+    case spv::Op::OpISub:
+    case spv::Op::OpFSub:
+    case spv::Op::OpIMul:
+    case spv::Op::OpFMul:
+    case spv::Op::OpUDiv:
+    case spv::Op::OpSDiv:
+    case spv::Op::OpFDiv:
+    case spv::Op::OpUMod:
+    case spv::Op::OpSRem:
+    case spv::Op::OpSMod:
+    case spv::Op::OpFRem:
+    case spv::Op::OpFMod:
+    case spv::Op::OpVectorTimesScalar:
+    case spv::Op::OpMatrixTimesScalar:
+    case spv::Op::OpVectorTimesMatrix:
+    case spv::Op::OpMatrixTimesVector:
+    case spv::Op::OpMatrixTimesMatrix:
+    case spv::Op::OpOuterProduct:
+    case spv::Op::OpDot:
+    case spv::Op::OpIAddCarry:
+    case spv::Op::OpISubBorrow:
+    case spv::Op::OpUMulExtended:
+    case spv::Op::OpSMulExtended:
+    case spv::Op::OpAny:
+    case spv::Op::OpAll:
+    case spv::Op::OpIsNan:
+    case spv::Op::OpIsInf:
+    case spv::Op::OpIsFinite:
+    case spv::Op::OpIsNormal:
+    case spv::Op::OpSignBitSet:
+    case spv::Op::OpLessOrGreater:
+    case spv::Op::OpOrdered:
+    case spv::Op::OpUnordered:
+    case spv::Op::OpLogicalEqual:
+    case spv::Op::OpLogicalNotEqual:
+    case spv::Op::OpLogicalOr:
+    case spv::Op::OpLogicalAnd:
+    case spv::Op::OpLogicalNot:
+    case spv::Op::OpSelect:
+    case spv::Op::OpIEqual:
+    case spv::Op::OpINotEqual:
+    case spv::Op::OpUGreaterThan:
+    case spv::Op::OpSGreaterThan:
+    case spv::Op::OpUGreaterThanEqual:
+    case spv::Op::OpSGreaterThanEqual:
+    case spv::Op::OpULessThan:
+    case spv::Op::OpSLessThan:
+    case spv::Op::OpULessThanEqual:
+    case spv::Op::OpSLessThanEqual:
+    case spv::Op::OpFOrdEqual:
+    case spv::Op::OpFUnordEqual:
+    case spv::Op::OpFOrdNotEqual:
+    case spv::Op::OpFUnordNotEqual:
+    case spv::Op::OpFOrdLessThan:
+    case spv::Op::OpFUnordLessThan:
+    case spv::Op::OpFOrdGreaterThan:
+    case spv::Op::OpFUnordGreaterThan:
+    case spv::Op::OpFOrdLessThanEqual:
+    case spv::Op::OpFUnordLessThanEqual:
+    case spv::Op::OpFOrdGreaterThanEqual:
+    case spv::Op::OpFUnordGreaterThanEqual:
+    case spv::Op::OpShiftRightLogical:
+    case spv::Op::OpShiftRightArithmetic:
+    case spv::Op::OpShiftLeftLogical:
+    case spv::Op::OpBitwiseOr:
+    case spv::Op::OpBitwiseXor:
+    case spv::Op::OpBitwiseAnd:
+    case spv::Op::OpNot:
+    case spv::Op::OpBitFieldInsert:
+    case spv::Op::OpBitFieldSExtract:
+    case spv::Op::OpBitFieldUExtract:
+    case spv::Op::OpBitReverse:
+    case spv::Op::OpBitCount:
+    case spv::Op::OpCopyLogical:
+    case spv::Op::OpPtrEqual:
+    case spv::Op::OpPtrNotEqual:
       return true;
     default:
       return false;
@@ -338,7 +338,7 @@
     // - it must be supported by this transformation
     // - it may depend only on instructions from different basic blocks or on
     //   OpPhi instructions from the same basic block.
-    if (inst.opcode() == SpvOpPhi || !IsOpcodeSupported(inst.opcode()) ||
+    if (inst.opcode() == spv::Op::OpPhi || !IsOpcodeSupported(inst.opcode()) ||
         !inst.type_id() || !inst.result_id()) {
       continue;
     }
@@ -353,7 +353,7 @@
     }
 
     if (!ir_context->get_feature_mgr()->HasCapability(
-            SpvCapabilityVariablePointersStorageBuffer) &&
+            spv::Capability::VariablePointersStorageBuffer) &&
         ContainsPointers(*inst_type)) {
       // OpPhi supports pointer operands only with VariablePointers or
       // VariablePointersStorageBuffer capabilities.
@@ -377,7 +377,7 @@
     opt::IRContext* ir_context, uint32_t block_id) {
   // Check that |block_id| is valid.
   const auto* label_inst = ir_context->get_def_use_mgr()->GetDef(block_id);
-  if (!label_inst || label_inst->opcode() != SpvOpLabel) {
+  if (!label_inst || label_inst->opcode() != spv::Op::OpLabel) {
     return false;
   }
 
diff --git a/source/fuzz/transformation_propagate_instruction_up.h b/source/fuzz/transformation_propagate_instruction_up.h
index 0ca051b..93aa365 100644
--- a/source/fuzz/transformation_propagate_instruction_up.h
+++ b/source/fuzz/transformation_propagate_instruction_up.h
@@ -80,7 +80,7 @@
                                                      uint32_t block_id);
 
   // Returns true if |opcode| is supported by this transformation.
-  static bool IsOpcodeSupported(SpvOp opcode);
+  static bool IsOpcodeSupported(spv::Op opcode);
 
   protobufs::TransformationPropagateInstructionUp message_;
 };
diff --git a/source/fuzz/transformation_push_id_through_variable.cpp b/source/fuzz/transformation_push_id_through_variable.cpp
index 55a57a1..2372d70 100644
--- a/source/fuzz/transformation_push_id_through_variable.cpp
+++ b/source/fuzz/transformation_push_id_through_variable.cpp
@@ -53,9 +53,9 @@
 
   // It must be valid to insert the OpStore and OpLoad instruction before it.
   if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
-          SpvOpStore, instruction_to_insert_before) ||
+          spv::Op::OpStore, instruction_to_insert_before) ||
       !fuzzerutil::CanInsertOpcodeBeforeInstruction(
-          SpvOpLoad, instruction_to_insert_before)) {
+          spv::Op::OpLoad, instruction_to_insert_before)) {
     return false;
   }
 
@@ -75,14 +75,16 @@
   // A pointer type instruction pointing to the value type must be defined.
   auto pointer_type_id = fuzzerutil::MaybeGetPointerType(
       ir_context, value_instruction->type_id(),
-      static_cast<SpvStorageClass>(message_.variable_storage_class()));
+      static_cast<spv::StorageClass>(message_.variable_storage_class()));
   if (!pointer_type_id) {
     return false;
   }
 
   // |message_.variable_storage_class| must be private or function.
-  assert((message_.variable_storage_class() == SpvStorageClassPrivate ||
-          message_.variable_storage_class() == SpvStorageClassFunction) &&
+  assert((message_.variable_storage_class() ==
+              (uint32_t)spv::StorageClass::Private ||
+          message_.variable_storage_class() ==
+              (uint32_t)spv::StorageClass::Function) &&
          "The variable storage class must be private or function.");
 
   // Check that initializer is valid.
@@ -111,14 +113,15 @@
   // A pointer type instruction pointing to the value type must be defined.
   auto pointer_type_id = fuzzerutil::MaybeGetPointerType(
       ir_context, value_instruction->type_id(),
-      static_cast<SpvStorageClass>(message_.variable_storage_class()));
+      static_cast<spv::StorageClass>(message_.variable_storage_class()));
   assert(pointer_type_id && "The required pointer type must be available.");
 
   // Adds whether a global or local variable.
-  if (message_.variable_storage_class() == SpvStorageClassPrivate) {
+  if (spv::StorageClass(message_.variable_storage_class()) ==
+      spv::StorageClass::Private) {
     opt::Instruction* global_variable = fuzzerutil::AddGlobalVariable(
         ir_context, message_.variable_id(), pointer_type_id,
-        SpvStorageClassPrivate, message_.initializer_id());
+        spv::StorageClass::Private, message_.initializer_id());
     ir_context->get_def_use_mgr()->AnalyzeInstDefUse(global_variable);
   } else {
     opt::Function* function =
@@ -138,13 +141,13 @@
   fuzzerutil::UpdateModuleIdBound(ir_context, message_.value_synonym_id());
   opt::Instruction* load_instruction =
       insert_before->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpLoad, value_instruction->type_id(),
+          ir_context, spv::Op::OpLoad, value_instruction->type_id(),
           message_.value_synonym_id(),
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID, {message_.variable_id()}}})));
   opt::Instruction* store_instruction =
       load_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpStore, 0, 0,
+          ir_context, spv::Op::OpStore, 0, 0,
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID, {message_.variable_id()}},
                {SPV_OPERAND_TYPE_ID, {message_.value_id()}}})));
diff --git a/source/fuzz/transformation_replace_add_sub_mul_with_carrying_extended.cpp b/source/fuzz/transformation_replace_add_sub_mul_with_carrying_extended.cpp
index e1977a6..03e9737 100644
--- a/source/fuzz/transformation_replace_add_sub_mul_with_carrying_extended.cpp
+++ b/source/fuzz/transformation_replace_add_sub_mul_with_carrying_extended.cpp
@@ -97,20 +97,20 @@
 
   // Determine the opcode of the new instruction that computes the result into a
   // struct.
-  SpvOp new_instruction_opcode;
+  spv::Op new_instruction_opcode;
 
   switch (original_instruction->opcode()) {
-    case SpvOpIAdd:
-      new_instruction_opcode = SpvOpIAddCarry;
+    case spv::Op::OpIAdd:
+      new_instruction_opcode = spv::Op::OpIAddCarry;
       break;
-    case SpvOpISub:
-      new_instruction_opcode = SpvOpISubBorrow;
+    case spv::Op::OpISub:
+      new_instruction_opcode = spv::Op::OpISubBorrow;
       break;
-    case SpvOpIMul:
+    case spv::Op::OpIMul:
       if (!operand_is_signed) {
-        new_instruction_opcode = SpvOpUMulExtended;
+        new_instruction_opcode = spv::Op::OpUMulExtended;
       } else {
-        new_instruction_opcode = SpvOpSMulExtended;
+        new_instruction_opcode = spv::Op::OpSMulExtended;
       }
       break;
     default:
@@ -148,7 +148,7 @@
   // takes the first component of the struct which represents low-order bits of
   // the operation. This is the original result.
   original_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpCompositeExtract, original_instruction->type_id(),
+      ir_context, spv::Op::OpCompositeExtract, original_instruction->type_id(),
       message_.result_id(),
       opt::Instruction::OperandList(
           {{SPV_OPERAND_TYPE_ID, {message_.struct_fresh_id()}},
@@ -168,9 +168,9 @@
 
   // Only instructions OpIAdd, OpISub, OpIMul are supported.
   switch (instruction_opcode) {
-    case SpvOpIAdd:
-    case SpvOpISub:
-    case SpvOpIMul:
+    case spv::Op::OpIAdd:
+    case spv::Op::OpISub:
+    case spv::Op::OpIMul:
       break;
     default:
       return false;
@@ -201,8 +201,8 @@
   auto type = ir_context->get_type_mgr()->GetType(instruction.type_id());
 
   switch (instruction_opcode) {
-    case SpvOpIAdd:
-    case SpvOpISub: {
+    case spv::Op::OpIAdd:
+    case spv::Op::OpISub: {
       // In case of OpIAdd and OpISub if the operand is a vector, the component
       // type must be unsigned. Otherwise (if the operand is an int), the
       // operand must be unsigned.
diff --git a/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.cpp b/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.cpp
index 2429351..efd1555 100644
--- a/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.cpp
+++ b/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.cpp
@@ -28,7 +28,8 @@
 // operator |binop|, returns true if it is certain that 'lhs binop rhs'
 // evaluates to |required_value|.
 template <typename T>
-bool float_binop_evaluates_to(T lhs, T rhs, SpvOp binop, bool required_value) {
+bool float_binop_evaluates_to(T lhs, T rhs, spv::Op binop,
+                              bool required_value) {
   // Infinity and NaN values are conservatively treated as out of scope.
   if (!std::isfinite(lhs) || !std::isfinite(rhs)) {
     return false;
@@ -37,20 +38,20 @@
   // The following captures the binary operators that spirv-fuzz can actually
   // generate when turning a boolean constant into a binary expression.
   switch (binop) {
-    case SpvOpFOrdGreaterThanEqual:
-    case SpvOpFUnordGreaterThanEqual:
+    case spv::Op::OpFOrdGreaterThanEqual:
+    case spv::Op::OpFUnordGreaterThanEqual:
       binop_result = (lhs >= rhs);
       break;
-    case SpvOpFOrdGreaterThan:
-    case SpvOpFUnordGreaterThan:
+    case spv::Op::OpFOrdGreaterThan:
+    case spv::Op::OpFUnordGreaterThan:
       binop_result = (lhs > rhs);
       break;
-    case SpvOpFOrdLessThanEqual:
-    case SpvOpFUnordLessThanEqual:
+    case spv::Op::OpFOrdLessThanEqual:
+    case spv::Op::OpFUnordLessThanEqual:
       binop_result = (lhs <= rhs);
       break;
-    case SpvOpFOrdLessThan:
-    case SpvOpFUnordLessThan:
+    case spv::Op::OpFOrdLessThan:
+    case spv::Op::OpFUnordLessThan:
       binop_result = (lhs < rhs);
       break;
     default:
@@ -61,20 +62,20 @@
 
 // Analogous to 'float_binop_evaluates_to', but for signed int values.
 template <typename T>
-bool signed_int_binop_evaluates_to(T lhs, T rhs, SpvOp binop,
+bool signed_int_binop_evaluates_to(T lhs, T rhs, spv::Op binop,
                                    bool required_value) {
   bool binop_result;
   switch (binop) {
-    case SpvOpSGreaterThanEqual:
+    case spv::Op::OpSGreaterThanEqual:
       binop_result = (lhs >= rhs);
       break;
-    case SpvOpSGreaterThan:
+    case spv::Op::OpSGreaterThan:
       binop_result = (lhs > rhs);
       break;
-    case SpvOpSLessThanEqual:
+    case spv::Op::OpSLessThanEqual:
       binop_result = (lhs <= rhs);
       break;
-    case SpvOpSLessThan:
+    case spv::Op::OpSLessThan:
       binop_result = (lhs < rhs);
       break;
     default:
@@ -85,20 +86,20 @@
 
 // Analogous to 'float_binop_evaluates_to', but for unsigned int values.
 template <typename T>
-bool unsigned_int_binop_evaluates_to(T lhs, T rhs, SpvOp binop,
+bool unsigned_int_binop_evaluates_to(T lhs, T rhs, spv::Op binop,
                                      bool required_value) {
   bool binop_result;
   switch (binop) {
-    case SpvOpUGreaterThanEqual:
+    case spv::Op::OpUGreaterThanEqual:
       binop_result = (lhs >= rhs);
       break;
-    case SpvOpUGreaterThan:
+    case spv::Op::OpUGreaterThan:
       binop_result = (lhs > rhs);
       break;
-    case SpvOpULessThanEqual:
+    case spv::Op::OpULessThanEqual:
       binop_result = (lhs <= rhs);
       break;
-    case SpvOpULessThan:
+    case spv::Op::OpULessThan:
       binop_result = (lhs < rhs);
       break;
     default:
@@ -118,12 +119,12 @@
 TransformationReplaceBooleanConstantWithConstantBinary::
     TransformationReplaceBooleanConstantWithConstantBinary(
         const protobufs::IdUseDescriptor& id_use_descriptor, uint32_t lhs_id,
-        uint32_t rhs_id, SpvOp comparison_opcode,
+        uint32_t rhs_id, spv::Op comparison_opcode,
         uint32_t fresh_id_for_binary_operation) {
   *message_.mutable_id_use_descriptor() = id_use_descriptor;
   message_.set_lhs_id(lhs_id);
   message_.set_rhs_id(rhs_id);
-  message_.set_opcode(comparison_opcode);
+  message_.set_opcode(uint32_t(comparison_opcode));
   message_.set_fresh_id_for_binary_operation(fresh_id_for_binary_operation);
 }
 
@@ -141,8 +142,8 @@
   if (!boolean_constant) {
     return false;
   }
-  if (!(boolean_constant->opcode() == SpvOpConstantFalse ||
-        boolean_constant->opcode() == SpvOpConstantTrue)) {
+  if (!(boolean_constant->opcode() == spv::Op::OpConstantFalse ||
+        boolean_constant->opcode() == spv::Op::OpConstantTrue)) {
     return false;
   }
 
@@ -152,7 +153,7 @@
   if (!lhs_constant_inst) {
     return false;
   }
-  if (lhs_constant_inst->opcode() != SpvOpConstant) {
+  if (lhs_constant_inst->opcode() != spv::Op::OpConstant) {
     return false;
   }
 
@@ -162,7 +163,7 @@
   if (!rhs_constant_inst) {
     return false;
   }
-  if (rhs_constant_inst->opcode() != SpvOpConstant) {
+  if (rhs_constant_inst->opcode() != spv::Op::OpConstant) {
     return false;
   }
 
@@ -176,9 +177,10 @@
       ir_context->get_constant_mgr()->FindDeclaredConstant(message_.lhs_id());
   auto rhs_constant =
       ir_context->get_constant_mgr()->FindDeclaredConstant(message_.rhs_id());
-  bool expected_result = (boolean_constant->opcode() == SpvOpConstantTrue);
+  bool expected_result =
+      (boolean_constant->opcode() == spv::Op::OpConstantTrue);
 
-  const auto binary_opcode = static_cast<SpvOp>(message_.opcode());
+  const auto binary_opcode = static_cast<spv::Op>(message_.opcode());
 
   // We consider the floating point, signed and unsigned integer cases
   // separately.  In each case the logic is very similar.
@@ -247,7 +249,7 @@
   // a binary operator before an OpVariable, but in any case (b) the
   // constant we would be replacing is the initializer constant of the
   // OpVariable, and this cannot be the result of a binary operation.
-  if (instruction->opcode() == SpvOpVariable) {
+  if (instruction->opcode() == spv::Op::OpVariable) {
     return false;
   }
 
@@ -268,7 +270,7 @@
       {SPV_OPERAND_TYPE_ID, {message_.lhs_id()}},
       {SPV_OPERAND_TYPE_ID, {message_.rhs_id()}}};
   auto binary_instruction = MakeUnique<opt::Instruction>(
-      ir_context, static_cast<SpvOp>(message_.opcode()),
+      ir_context, static_cast<spv::Op>(message_.opcode()),
       ir_context->get_type_mgr()->GetId(&bool_type),
       message_.fresh_id_for_binary_operation(), operands);
   opt::Instruction* result = binary_instruction.get();
@@ -279,7 +281,7 @@
   // If |instruction_before_which_to_insert| is an OpPhi instruction,
   // then |binary_instruction| will be inserted into the parent block associated
   // with the OpPhi variable operand.
-  if (instruction_containing_constant_use->opcode() == SpvOpPhi) {
+  if (instruction_containing_constant_use->opcode() == spv::Op::OpPhi) {
     instruction_before_which_to_insert =
         ir_context->cfg()
             ->block(instruction_containing_constant_use->GetSingleWordInOperand(
@@ -293,8 +295,9 @@
   {
     opt::Instruction* previous_node =
         instruction_before_which_to_insert->PreviousNode();
-    if (previous_node && (previous_node->opcode() == SpvOpLoopMerge ||
-                          previous_node->opcode() == SpvOpSelectionMerge)) {
+    if (previous_node &&
+        (previous_node->opcode() == spv::Op::OpLoopMerge ||
+         previous_node->opcode() == spv::Op::OpSelectionMerge)) {
       instruction_before_which_to_insert = previous_node;
     }
   }
diff --git a/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h b/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h
index 97c66bf..4d48bf2 100644
--- a/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h
+++ b/source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h
@@ -32,7 +32,7 @@
 
   TransformationReplaceBooleanConstantWithConstantBinary(
       const protobufs::IdUseDescriptor& id_use_descriptor, uint32_t lhs_id,
-      uint32_t rhs_id, SpvOp comparison_opcode,
+      uint32_t rhs_id, spv::Op comparison_opcode,
       uint32_t fresh_id_for_binary_operation);
 
   // - |message_.fresh_id_for_binary_operation| must not already be used by the
diff --git a/source/fuzz/transformation_replace_branch_from_dead_block_with_exit.cpp b/source/fuzz/transformation_replace_branch_from_dead_block_with_exit.cpp
index 9ea7cb6..4150bb1 100644
--- a/source/fuzz/transformation_replace_branch_from_dead_block_with_exit.cpp
+++ b/source/fuzz/transformation_replace_branch_from_dead_block_with_exit.cpp
@@ -26,10 +26,10 @@
 
 TransformationReplaceBranchFromDeadBlockWithExit::
     TransformationReplaceBranchFromDeadBlockWithExit(uint32_t block_id,
-                                                     SpvOp opcode,
+                                                     spv::Op opcode,
                                                      uint32_t return_value_id) {
   message_.set_block_id(block_id);
-  message_.set_opcode(opcode);
+  message_.set_opcode(uint32_t(opcode));
   message_.set_return_value_id(return_value_id);
 }
 
@@ -45,11 +45,11 @@
     return false;
   }
   auto function_return_type_id = block->GetParent()->type_id();
-  switch (message_.opcode()) {
-    case SpvOpKill:
+  switch (spv::Op(message_.opcode())) {
+    case spv::Op::OpKill:
       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) {
           // OpKill is only allowed in a fragment shader.  This is a
           // conservative check: if the module contains a non-fragment entry
           // point then adding an OpKill might lead to OpKill being used in a
@@ -58,15 +58,15 @@
         }
       }
       break;
-    case SpvOpReturn:
+    case spv::Op::OpReturn:
       if (ir_context->get_def_use_mgr()
               ->GetDef(function_return_type_id)
-              ->opcode() != SpvOpTypeVoid) {
+              ->opcode() != spv::Op::OpTypeVoid) {
         // OpReturn is only allowed in a function with void return type.
         return false;
       }
       break;
-    case SpvOpReturnValue: {
+    case spv::Op::OpReturnValue: {
       // If the terminator is to be changed to OpReturnValue, with
       // |message_.return_value_id| being the value that will be returned, then
       // |message_.return_value_id| must have a compatible type and be available
@@ -83,7 +83,7 @@
       break;
     }
     default:
-      assert(message_.opcode() == SpvOpUnreachable &&
+      assert(spv::Op(message_.opcode()) == spv::Op::OpUnreachable &&
              "Invalid early exit opcode.");
       break;
   }
@@ -95,7 +95,7 @@
   // If the successor block has OpPhi instructions then arguments related to
   // |message_.block_id| need to be removed from these instruction.
   auto block = ir_context->get_instr_block(message_.block_id());
-  assert(block->terminator()->opcode() == SpvOpBranch &&
+  assert(block->terminator()->opcode() == spv::Op::OpBranch &&
          "Precondition: the block must end with OpBranch.");
   auto successor = ir_context->get_instr_block(
       block->terminator()->GetSingleWordInOperand(0));
@@ -114,12 +114,12 @@
 
   // Rewrite the terminator of |message_.block_id|.
   opt::Instruction::OperandList new_terminator_in_operands;
-  if (message_.opcode() == SpvOpReturnValue) {
+  if (spv::Op(message_.opcode()) == spv::Op::OpReturnValue) {
     new_terminator_in_operands.push_back(
         {SPV_OPERAND_TYPE_ID, {message_.return_value_id()}});
   }
   auto terminator = block->terminator();
-  terminator->SetOpcode(static_cast<SpvOp>(message_.opcode()));
+  terminator->SetOpcode(static_cast<spv::Op>(message_.opcode()));
   terminator->SetInOperands(std::move(new_terminator_in_operands));
   ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
 }
@@ -145,7 +145,7 @@
     return false;
   }
   // The block's terminator must be OpBranch.
-  if (block.terminator()->opcode() != SpvOpBranch) {
+  if (block.terminator()->opcode() != spv::Op::OpBranch) {
     return false;
   }
   if (ir_context->GetStructuredCFGAnalysis()->IsInContinueConstruct(
@@ -164,7 +164,7 @@
   // Make sure that domination rules are satisfied when we remove the branch
   // from the |block| to its |successor|.
   return fuzzerutil::NewTerminatorPreservesDominationRules(
-      ir_context, block.id(), {ir_context, SpvOpUnreachable});
+      ir_context, block.id(), {ir_context, spv::Op::OpUnreachable});
 }
 
 }  // namespace fuzz
diff --git a/source/fuzz/transformation_replace_branch_from_dead_block_with_exit.h b/source/fuzz/transformation_replace_branch_from_dead_block_with_exit.h
index 89667fc..9a5d42e 100644
--- a/source/fuzz/transformation_replace_branch_from_dead_block_with_exit.h
+++ b/source/fuzz/transformation_replace_branch_from_dead_block_with_exit.h
@@ -30,7 +30,7 @@
       protobufs::TransformationReplaceBranchFromDeadBlockWithExit message);
 
   TransformationReplaceBranchFromDeadBlockWithExit(uint32_t block_id,
-                                                   SpvOp opcode,
+                                                   spv::Op opcode,
                                                    uint32_t return_value_id);
 
   // - |message_.block_id| must be the id of a dead block that is not part of
diff --git a/source/fuzz/transformation_replace_constant_with_uniform.cpp b/source/fuzz/transformation_replace_constant_with_uniform.cpp
index c6698c0..7174e6a 100644
--- a/source/fuzz/transformation_replace_constant_with_uniform.cpp
+++ b/source/fuzz/transformation_replace_constant_with_uniform.cpp
@@ -67,15 +67,15 @@
   // The type id for the access chain is a uniform pointer with base type
   // matching the given constant id type.
   auto type_and_pointer_type =
-      ir_context->get_type_mgr()->GetTypeAndPointerType(constant_type_id,
-                                                        SpvStorageClassUniform);
+      ir_context->get_type_mgr()->GetTypeAndPointerType(
+          constant_type_id, spv::StorageClass::Uniform);
   assert(type_and_pointer_type.first != nullptr);
   assert(type_and_pointer_type.second != nullptr);
   auto pointer_to_uniform_constant_type_id =
       ir_context->get_type_mgr()->GetId(type_and_pointer_type.second.get());
 
   return MakeUnique<opt::Instruction>(
-      ir_context, SpvOpAccessChain, pointer_to_uniform_constant_type_id,
+      ir_context, spv::Op::OpAccessChain, pointer_to_uniform_constant_type_id,
       message_.fresh_id_for_access_chain(), operands_for_access_chain);
 }
 
@@ -84,9 +84,9 @@
     spvtools::opt::IRContext* ir_context, uint32_t constant_type_id) const {
   opt::Instruction::OperandList operands_for_load = {
       {SPV_OPERAND_TYPE_ID, {message_.fresh_id_for_access_chain()}}};
-  return MakeUnique<opt::Instruction>(ir_context, SpvOpLoad, constant_type_id,
-                                      message_.fresh_id_for_load(),
-                                      operands_for_load);
+  return MakeUnique<opt::Instruction>(
+      ir_context, spv::Op::OpLoad, constant_type_id,
+      message_.fresh_id_for_load(), operands_for_load);
 }
 
 opt::Instruction*
@@ -99,7 +99,7 @@
   }
 
   // The use might be in an OpPhi instruction.
-  if (result->opcode() == SpvOpPhi) {
+  if (result->opcode() == spv::Op::OpPhi) {
     // OpPhi instructions must be the first instructions in a block. Thus, we
     // can't insert above the OpPhi instruction. Given the predecessor block
     // that corresponds to the id use, get the last instruction in that block
@@ -108,18 +108,19 @@
         ir_context,
         result->GetSingleWordInOperand(
             message_.id_use_descriptor().in_operand_index() + 1),
-        SpvOpLoad);
+        spv::Op::OpLoad);
   }
 
   // The only operand that we could've replaced in the OpBranchConditional is
   // the condition id. But that operand has a boolean type and uniform variables
   // can't store booleans (see the spec on OpTypeBool). Thus, |result| can't be
   // an OpBranchConditional.
-  assert(result->opcode() != SpvOpBranchConditional &&
+  assert(result->opcode() != spv::Op::OpBranchConditional &&
          "OpBranchConditional has no operands to replace");
 
-  assert(fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpLoad, result) &&
-         "We should be able to insert OpLoad and OpAccessChain at this point");
+  assert(
+      fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpLoad, result) &&
+      "We should be able to insert OpLoad and OpAccessChain at this point");
   return result;
 }
 
@@ -191,15 +192,15 @@
 
   // The use must not be a variable initializer; these are required to be
   // constants, so it would be illegal to replace one with a uniform access.
-  if (instruction_using_constant->opcode() == SpvOpVariable) {
+  if (instruction_using_constant->opcode() == spv::Op::OpVariable) {
     return false;
   }
 
   // The module needs to have a uniform pointer type suitable for indexing into
   // the uniform variable, i.e. matching the type of the constant we wish to
   // replace with a uniform.
-  opt::analysis::Pointer pointer_to_type_of_constant(declared_constant->type(),
-                                                     SpvStorageClassUniform);
+  opt::analysis::Pointer pointer_to_type_of_constant(
+      declared_constant->type(), spv::StorageClass::Uniform);
   if (!ir_context->get_type_mgr()->GetId(&pointer_to_type_of_constant)) {
     return false;
   }
diff --git a/source/fuzz/transformation_replace_copy_memory_with_load_store.cpp b/source/fuzz/transformation_replace_copy_memory_with_load_store.cpp
index de9d1fd..8f14145 100644
--- a/source/fuzz/transformation_replace_copy_memory_with_load_store.cpp
+++ b/source/fuzz/transformation_replace_copy_memory_with_load_store.cpp
@@ -45,7 +45,7 @@
   auto copy_memory_instruction = FindInstruction(
       message_.copy_memory_instruction_descriptor(), ir_context);
   if (!copy_memory_instruction ||
-      copy_memory_instruction->opcode() != SpvOpCopyMemory) {
+      copy_memory_instruction->opcode() != spv::Op::OpCopyMemory) {
     return false;
   }
   return true;
@@ -57,7 +57,7 @@
       message_.copy_memory_instruction_descriptor(), ir_context);
   // |copy_memory_instruction| must be defined.
   assert(copy_memory_instruction &&
-         copy_memory_instruction->opcode() == SpvOpCopyMemory &&
+         copy_memory_instruction->opcode() == spv::Op::OpCopyMemory &&
          "The required OpCopyMemory instruction must be defined.");
 
   // Integrity check: Both operands must be pointers.
@@ -78,8 +78,8 @@
   (void)target_type_opcode;
   (void)source_type_opcode;
 
-  assert(target_type_opcode == SpvOpTypePointer &&
-         source_type_opcode == SpvOpTypePointer &&
+  assert(target_type_opcode == spv::Op::OpTypePointer &&
+         source_type_opcode == spv::Op::OpTypePointer &&
          "Operands must be of type OpTypePointer");
 
   // Integrity check: |source| and |target| must point to the same type.
@@ -100,12 +100,12 @@
   fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
   FindInstruction(message_.copy_memory_instruction_descriptor(), ir_context)
       ->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpStore, 0, 0,
+          ir_context, spv::Op::OpStore, 0, 0,
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID, {target->result_id()}},
                {SPV_OPERAND_TYPE_ID, {message_.fresh_id()}}})))
       ->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpLoad, target_pointee_type, message_.fresh_id(),
+          ir_context, spv::Op::OpLoad, target_pointee_type, message_.fresh_id(),
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID, {source->result_id()}}})));
 
diff --git a/source/fuzz/transformation_replace_copy_object_with_store_load.cpp b/source/fuzz/transformation_replace_copy_object_with_store_load.cpp
index e0643bf..f08a734 100644
--- a/source/fuzz/transformation_replace_copy_object_with_store_load.cpp
+++ b/source/fuzz/transformation_replace_copy_object_with_store_load.cpp
@@ -46,7 +46,7 @@
 
   // This must be a defined OpCopyObject instruction.
   if (!copy_object_instruction ||
-      copy_object_instruction->opcode() != SpvOpCopyObject) {
+      copy_object_instruction->opcode() != spv::Op::OpCopyObject) {
     return false;
   }
 
@@ -54,14 +54,14 @@
   // because we cannot define a pointer to pointer.
   if (ir_context->get_def_use_mgr()
           ->GetDef(copy_object_instruction->type_id())
-          ->opcode() == SpvOpTypePointer) {
+          ->opcode() == spv::Op::OpTypePointer) {
     return false;
   }
 
   // A pointer type instruction pointing to the value type must be defined.
   auto pointer_type_id = fuzzerutil::MaybeGetPointerType(
       ir_context, copy_object_instruction->type_id(),
-      static_cast<SpvStorageClass>(message_.variable_storage_class()));
+      static_cast<spv::StorageClass>(message_.variable_storage_class()));
   if (!pointer_type_id) {
     return false;
   }
@@ -74,8 +74,10 @@
     return false;
   }
   // |message_.variable_storage_class| must be Private or Function.
-  return message_.variable_storage_class() == SpvStorageClassPrivate ||
-         message_.variable_storage_class() == SpvStorageClassFunction;
+  return spv::StorageClass(message_.variable_storage_class()) ==
+             spv::StorageClass::Private ||
+         spv::StorageClass(message_.variable_storage_class()) ==
+             spv::StorageClass::Function;
 }
 
 void TransformationReplaceCopyObjectWithStoreLoad::Apply(
@@ -85,7 +87,7 @@
       ir_context->get_def_use_mgr()->GetDef(message_.copy_object_result_id());
   // |copy_object_instruction| must be defined.
   assert(copy_object_instruction &&
-         copy_object_instruction->opcode() == SpvOpCopyObject &&
+         copy_object_instruction->opcode() == spv::Op::OpCopyObject &&
          "The required OpCopyObject instruction must be defined.");
 
   opt::BasicBlock* enclosing_block =
@@ -96,14 +98,15 @@
   // A pointer type instruction pointing to the value type must be defined.
   auto pointer_type_id = fuzzerutil::MaybeGetPointerType(
       ir_context, copy_object_instruction->type_id(),
-      static_cast<SpvStorageClass>(message_.variable_storage_class()));
+      static_cast<spv::StorageClass>(message_.variable_storage_class()));
   assert(pointer_type_id && "The required pointer type must be available.");
 
   // Adds a global or local variable (according to the storage class).
-  if (message_.variable_storage_class() == SpvStorageClassPrivate) {
+  if (spv::StorageClass(message_.variable_storage_class()) ==
+      spv::StorageClass::Private) {
     opt::Instruction* new_global = fuzzerutil::AddGlobalVariable(
         ir_context, message_.fresh_variable_id(), pointer_type_id,
-        SpvStorageClassPrivate, message_.variable_initializer_id());
+        spv::StorageClass::Private, message_.variable_initializer_id());
     ir_context->get_def_use_mgr()->AnalyzeInstDefUse(new_global);
   } else {
     opt::Function* function =
@@ -120,13 +123,13 @@
   fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_variable_id());
   opt::Instruction* load_instruction =
       copy_object_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpLoad, copy_object_instruction->type_id(),
+          ir_context, spv::Op::OpLoad, copy_object_instruction->type_id(),
           message_.copy_object_result_id(),
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID, {message_.fresh_variable_id()}}})));
   opt::Instruction* store_instruction =
       load_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpStore, 0, 0,
+          ir_context, spv::Op::OpStore, 0, 0,
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID, {message_.fresh_variable_id()}},
                {SPV_OPERAND_TYPE_ID, {src_operand}}})));
diff --git a/source/fuzz/transformation_replace_irrelevant_id.cpp b/source/fuzz/transformation_replace_irrelevant_id.cpp
index a71f96a..7f64063 100644
--- a/source/fuzz/transformation_replace_irrelevant_id.cpp
+++ b/source/fuzz/transformation_replace_irrelevant_id.cpp
@@ -65,7 +65,7 @@
   }
 
   // The replacement id must not be the result of an OpFunction instruction.
-  if (replacement_id_def->opcode() == SpvOpFunction) {
+  if (replacement_id_def->opcode() == spv::Op::OpFunction) {
     return false;
   }
 
@@ -130,7 +130,7 @@
     AttemptsToReplaceVariableInitializerWithNonConstant(
         const opt::Instruction& use_instruction,
         const opt::Instruction& replacement_for_use) {
-  return use_instruction.opcode() == SpvOpVariable &&
+  return use_instruction.opcode() == spv::Op::OpVariable &&
          !spvOpcodeIsConstant(replacement_for_use.opcode());
 }
 
diff --git a/source/fuzz/transformation_replace_linear_algebra_instruction.cpp b/source/fuzz/transformation_replace_linear_algebra_instruction.cpp
index 2430cca..fb7b294 100644
--- a/source/fuzz/transformation_replace_linear_algebra_instruction.cpp
+++ b/source/fuzz/transformation_replace_linear_algebra_instruction.cpp
@@ -68,28 +68,28 @@
       FindInstruction(message_.instruction_descriptor(), ir_context);
 
   switch (linear_algebra_instruction->opcode()) {
-    case SpvOpTranspose:
+    case spv::Op::OpTranspose:
       ReplaceOpTranspose(ir_context, linear_algebra_instruction);
       break;
-    case SpvOpVectorTimesScalar:
+    case spv::Op::OpVectorTimesScalar:
       ReplaceOpVectorTimesScalar(ir_context, linear_algebra_instruction);
       break;
-    case SpvOpMatrixTimesScalar:
+    case spv::Op::OpMatrixTimesScalar:
       ReplaceOpMatrixTimesScalar(ir_context, linear_algebra_instruction);
       break;
-    case SpvOpVectorTimesMatrix:
+    case spv::Op::OpVectorTimesMatrix:
       ReplaceOpVectorTimesMatrix(ir_context, linear_algebra_instruction);
       break;
-    case SpvOpMatrixTimesVector:
+    case spv::Op::OpMatrixTimesVector:
       ReplaceOpMatrixTimesVector(ir_context, linear_algebra_instruction);
       break;
-    case SpvOpMatrixTimesMatrix:
+    case spv::Op::OpMatrixTimesMatrix:
       ReplaceOpMatrixTimesMatrix(ir_context, linear_algebra_instruction);
       break;
-    case SpvOpOuterProduct:
+    case spv::Op::OpOuterProduct:
       ReplaceOpOuterProduct(ir_context, linear_algebra_instruction);
       break;
-    case SpvOpDot:
+    case spv::Op::OpDot:
       ReplaceOpDot(ir_context, linear_algebra_instruction);
       break;
     default:
@@ -112,7 +112,7 @@
   // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3354):
   // Right now we only support certain operations.
   switch (instruction->opcode()) {
-    case SpvOpTranspose: {
+    case spv::Op::OpTranspose: {
       // For each matrix row, |2 * matrix_column_count| OpCompositeExtract and 1
       // OpCompositeConstruct will be inserted.
       auto matrix_instruction = ir_context->get_def_use_mgr()->GetDef(
@@ -130,7 +130,7 @@
                                       ->element_count();
       return matrix_row_count * (2 * matrix_column_count + 1);
     }
-    case SpvOpVectorTimesScalar:
+    case spv::Op::OpVectorTimesScalar:
       // For each vector component, 1 OpCompositeExtract and 1 OpFMul will be
       // inserted.
       return 2 *
@@ -140,7 +140,7 @@
                                ->type_id())
                  ->AsVector()
                  ->element_count();
-    case SpvOpMatrixTimesScalar: {
+    case spv::Op::OpMatrixTimesScalar: {
       // For each matrix column, |1 + column.size| OpCompositeExtract,
       // |column.size| OpFMul and 1 OpCompositeConstruct instructions will be
       // inserted.
@@ -154,7 +154,7 @@
                       ->AsVector()
                       ->element_count());
     }
-    case SpvOpVectorTimesMatrix: {
+    case spv::Op::OpVectorTimesMatrix: {
       // For each vector component, 1 OpCompositeExtract instruction will be
       // inserted. For each matrix column, |1 + vector_component_count|
       // OpCompositeExtract, |vector_component_count| OpFMul and
@@ -175,7 +175,7 @@
               ->element_count();
       return vector_component_count * (3 * matrix_column_count + 1);
     }
-    case SpvOpMatrixTimesVector: {
+    case spv::Op::OpMatrixTimesVector: {
       // For each matrix column, |1 + matrix_row_count| OpCompositeExtract
       // will be inserted. For each matrix row, |matrix_column_count| OpFMul and
       // |matrix_column_count - 1| OpFAdd instructions will be inserted. For
@@ -197,7 +197,7 @@
       return 3 * matrix_column_count * matrix_row_count +
              2 * matrix_column_count - matrix_row_count;
     }
-    case SpvOpMatrixTimesMatrix: {
+    case spv::Op::OpMatrixTimesMatrix: {
       // For each matrix 2 column, 1 OpCompositeExtract, 1 OpCompositeConstruct,
       // |3 * matrix_1_row_count * matrix_1_column_count| OpCompositeExtract,
       // |matrix_1_row_count * matrix_1_column_count| OpFMul,
@@ -228,7 +228,7 @@
       return matrix_2_column_count *
              (2 + matrix_1_row_count * (5 * matrix_1_column_count - 1));
     }
-    case SpvOpOuterProduct: {
+    case spv::Op::OpOuterProduct: {
       // For each |vector_2| component, |vector_1_component_count + 1|
       // OpCompositeExtract, |vector_1_component_count| OpFMul and 1
       // OpCompositeConstruct instructions will be inserted.
@@ -248,7 +248,7 @@
               ->element_count();
       return 2 * vector_2_component_count * (vector_1_component_count + 1);
     }
-    case SpvOpDot:
+    case spv::Op::OpDot:
       // For each pair of vector components, 2 OpCompositeExtract and 1 OpFMul
       // will be inserted. The first two OpFMul instructions will result the
       // first OpFAdd instruction to be inserted. For each remaining OpFMul, 1
@@ -299,7 +299,7 @@
       // Extracts the matrix column.
       uint32_t matrix_column_id = message_.fresh_ids(fresh_id_index++);
       linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpCompositeExtract,
+          ir_context, spv::Op::OpCompositeExtract,
           ir_context->get_type_mgr()->GetId(matrix_column_type),
           matrix_column_id,
           opt::Instruction::OperandList(
@@ -309,7 +309,7 @@
       // Extracts the matrix column component.
       column_component_ids[j] = message_.fresh_ids(fresh_id_index++);
       linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpCompositeExtract,
+          ir_context, spv::Op::OpCompositeExtract,
           ir_context->get_type_mgr()->GetId(matrix_column_component_type),
           column_component_ids[j],
           opt::Instruction::OperandList(
@@ -324,14 +324,14 @@
     }
     result_column_ids[i] = message_.fresh_ids(fresh_id_index++);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeConstruct,
+        ir_context, spv::Op::OpCompositeConstruct,
         ir_context->get_type_mgr()->GetId(resulting_matrix_column_type),
         result_column_ids[i], opt::Instruction::OperandList(in_operands)));
   }
 
   // The OpTranspose instruction is changed to an OpCompositeConstruct
   // instruction.
-  linear_algebra_instruction->SetOpcode(SpvOpCompositeConstruct);
+  linear_algebra_instruction->SetOpcode(spv::Op::OpCompositeConstruct);
   linear_algebra_instruction->SetInOperand(0, {result_column_ids[0]});
   for (uint32_t i = 1; i < result_column_ids.size(); i++) {
     linear_algebra_instruction->AddOperand(
@@ -363,7 +363,8 @@
     uint32_t vector_extract_id = message_.fresh_ids(fresh_id_index++);
     fuzzerutil::UpdateModuleIdBound(ir_context, vector_extract_id);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeExtract, scalar->type_id(), vector_extract_id,
+        ir_context, spv::Op::OpCompositeExtract, scalar->type_id(),
+        vector_extract_id,
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {vector->result_id()}},
              {SPV_OPERAND_TYPE_LITERAL_INTEGER, {i}}})));
@@ -373,7 +374,7 @@
     float_multiplication_ids[i] = float_multiplication_id;
     fuzzerutil::UpdateModuleIdBound(ir_context, float_multiplication_id);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpFMul, scalar->type_id(), float_multiplication_id,
+        ir_context, spv::Op::OpFMul, scalar->type_id(), float_multiplication_id,
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {vector_extract_id}},
              {SPV_OPERAND_TYPE_ID, {scalar->result_id()}}})));
@@ -381,7 +382,7 @@
 
   // The OpVectorTimesScalar instruction is changed to an OpCompositeConstruct
   // instruction.
-  linear_algebra_instruction->SetOpcode(SpvOpCompositeConstruct);
+  linear_algebra_instruction->SetOpcode(spv::Op::OpCompositeConstruct);
   linear_algebra_instruction->SetInOperand(0, {float_multiplication_ids[0]});
   linear_algebra_instruction->SetInOperand(1, {float_multiplication_ids[1]});
   for (uint32_t i = 2; i < float_multiplication_ids.size(); i++) {
@@ -418,7 +419,7 @@
     uint32_t matrix_extract_id = message_.fresh_ids(fresh_id_index++);
     fuzzerutil::UpdateModuleIdBound(ir_context, matrix_extract_id);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeExtract,
+        ir_context, spv::Op::OpCompositeExtract,
         ir_context->get_type_mgr()->GetId(matrix_column_type),
         matrix_extract_id,
         opt::Instruction::OperandList(
@@ -432,8 +433,8 @@
       uint32_t column_extract_id = message_.fresh_ids(fresh_id_index++);
       fuzzerutil::UpdateModuleIdBound(ir_context, column_extract_id);
       linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpCompositeExtract, scalar_instruction->type_id(),
-          column_extract_id,
+          ir_context, spv::Op::OpCompositeExtract,
+          scalar_instruction->type_id(), column_extract_id,
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID, {matrix_extract_id}},
                {SPV_OPERAND_TYPE_LITERAL_INTEGER, {j}}})));
@@ -442,7 +443,7 @@
       float_multiplication_ids[j] = message_.fresh_ids(fresh_id_index++);
       fuzzerutil::UpdateModuleIdBound(ir_context, float_multiplication_ids[j]);
       linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpFMul, scalar_instruction->type_id(),
+          ir_context, spv::Op::OpFMul, scalar_instruction->type_id(),
           float_multiplication_ids[j],
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID, {column_extract_id}},
@@ -458,14 +459,14 @@
     composite_construct_ids[i] = message_.fresh_ids(fresh_id_index++);
     fuzzerutil::UpdateModuleIdBound(ir_context, composite_construct_ids[i]);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeConstruct,
+        ir_context, spv::Op::OpCompositeConstruct,
         ir_context->get_type_mgr()->GetId(matrix_column_type),
         composite_construct_ids[i], composite_construct_in_operands));
   }
 
   // The OpMatrixTimesScalar instruction is changed to an OpCompositeConstruct
   // instruction.
-  linear_algebra_instruction->SetOpcode(SpvOpCompositeConstruct);
+  linear_algebra_instruction->SetOpcode(spv::Op::OpCompositeConstruct);
   linear_algebra_instruction->SetInOperand(0, {composite_construct_ids[0]});
   linear_algebra_instruction->SetInOperand(1, {composite_construct_ids[1]});
   for (uint32_t i = 2; i < composite_construct_ids.size(); i++) {
@@ -495,7 +496,7 @@
   for (uint32_t i = 0; i < vector_component_count; i++) {
     vector_component_ids[i] = message_.fresh_ids(fresh_id_index++);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeExtract,
+        ir_context, spv::Op::OpCompositeExtract,
         ir_context->get_type_mgr()->GetId(vector_component_type),
         vector_component_ids[i],
         opt::Instruction::OperandList(
@@ -520,7 +521,7 @@
     // Extracts matrix column.
     uint32_t matrix_extract_id = message_.fresh_ids(fresh_id_index++);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeExtract,
+        ir_context, spv::Op::OpCompositeExtract,
         ir_context->get_type_mgr()->GetId(matrix_column_type),
         matrix_extract_id,
         opt::Instruction::OperandList(
@@ -532,7 +533,7 @@
       // Extracts column component.
       uint32_t column_extract_id = message_.fresh_ids(fresh_id_index++);
       linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpCompositeExtract,
+          ir_context, spv::Op::OpCompositeExtract,
           ir_context->get_type_mgr()->GetId(vector_component_type),
           column_extract_id,
           opt::Instruction::OperandList(
@@ -542,7 +543,7 @@
       // Multiplies corresponding vector and column components.
       float_multiplication_ids[j] = message_.fresh_ids(fresh_id_index++);
       linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpFMul,
+          ir_context, spv::Op::OpFMul,
           ir_context->get_type_mgr()->GetId(vector_component_type),
           float_multiplication_ids[j],
           opt::Instruction::OperandList(
@@ -555,7 +556,7 @@
     uint32_t float_add_id = message_.fresh_ids(fresh_id_index++);
     float_add_ids.push_back(float_add_id);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpFAdd,
+        ir_context, spv::Op::OpFAdd,
         ir_context->get_type_mgr()->GetId(vector_component_type), float_add_id,
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {float_multiplication_ids[0]}},
@@ -564,7 +565,7 @@
       float_add_id = message_.fresh_ids(fresh_id_index++);
       float_add_ids.push_back(float_add_id);
       linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpFAdd,
+          ir_context, spv::Op::OpFAdd,
           ir_context->get_type_mgr()->GetId(vector_component_type),
           float_add_id,
           opt::Instruction::OperandList(
@@ -577,7 +578,7 @@
 
   // The OpVectorTimesMatrix instruction is changed to an OpCompositeConstruct
   // instruction.
-  linear_algebra_instruction->SetOpcode(SpvOpCompositeConstruct);
+  linear_algebra_instruction->SetOpcode(spv::Op::OpCompositeConstruct);
   linear_algebra_instruction->SetInOperand(0, {result_component_ids[0]});
   linear_algebra_instruction->SetInOperand(1, {result_component_ids[1]});
   for (uint32_t i = 2; i < result_component_ids.size(); i++) {
@@ -611,7 +612,7 @@
   for (uint32_t i = 0; i < matrix_column_count; i++) {
     matrix_column_ids[i] = message_.fresh_ids(fresh_id_index++);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeExtract,
+        ir_context, spv::Op::OpCompositeExtract,
         ir_context->get_type_mgr()->GetId(matrix_column_type),
         matrix_column_ids[i],
         opt::Instruction::OperandList(
@@ -632,7 +633,7 @@
   for (uint32_t i = 0; i < matrix_column_count; i++) {
     vector_component_ids[i] = message_.fresh_ids(fresh_id_index++);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeExtract,
+        ir_context, spv::Op::OpCompositeExtract,
         ir_context->get_type_mgr()->GetId(vector_component_type),
         vector_component_ids[i],
         opt::Instruction::OperandList(
@@ -647,7 +648,7 @@
       // Extracts column component.
       uint32_t column_extract_id = message_.fresh_ids(fresh_id_index++);
       linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpCompositeExtract,
+          ir_context, spv::Op::OpCompositeExtract,
           ir_context->get_type_mgr()->GetId(vector_component_type),
           column_extract_id,
           opt::Instruction::OperandList(
@@ -657,7 +658,7 @@
       // Multiplies corresponding vector and column components.
       float_multiplication_ids[j] = message_.fresh_ids(fresh_id_index++);
       linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpFMul,
+          ir_context, spv::Op::OpFMul,
           ir_context->get_type_mgr()->GetId(vector_component_type),
           float_multiplication_ids[j],
           opt::Instruction::OperandList(
@@ -670,7 +671,7 @@
     uint32_t float_add_id = message_.fresh_ids(fresh_id_index++);
     float_add_ids.push_back(float_add_id);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpFAdd,
+        ir_context, spv::Op::OpFAdd,
         ir_context->get_type_mgr()->GetId(vector_component_type), float_add_id,
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {float_multiplication_ids[0]}},
@@ -679,7 +680,7 @@
       float_add_id = message_.fresh_ids(fresh_id_index++);
       float_add_ids.push_back(float_add_id);
       linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpFAdd,
+          ir_context, spv::Op::OpFAdd,
           ir_context->get_type_mgr()->GetId(vector_component_type),
           float_add_id,
           opt::Instruction::OperandList(
@@ -692,7 +693,7 @@
 
   // The OpMatrixTimesVector instruction is changed to an OpCompositeConstruct
   // instruction.
-  linear_algebra_instruction->SetOpcode(SpvOpCompositeConstruct);
+  linear_algebra_instruction->SetOpcode(spv::Op::OpCompositeConstruct);
   linear_algebra_instruction->SetInOperand(0, {result_component_ids[0]});
   linear_algebra_instruction->SetInOperand(1, {result_component_ids[1]});
   for (uint32_t i = 2; i < result_component_ids.size(); i++) {
@@ -743,7 +744,7 @@
     // Extracts matrix 2 column.
     uint32_t matrix_2_column_id = message_.fresh_ids(fresh_id_index++);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeExtract,
+        ir_context, spv::Op::OpCompositeExtract,
         ir_context->get_type_mgr()->GetId(matrix_2_column_type),
         matrix_2_column_id,
         opt::Instruction::OperandList(
@@ -757,7 +758,7 @@
         // Extracts matrix 1 column.
         uint32_t matrix_1_column_id = message_.fresh_ids(fresh_id_index++);
         linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-            ir_context, SpvOpCompositeExtract,
+            ir_context, spv::Op::OpCompositeExtract,
             ir_context->get_type_mgr()->GetId(matrix_1_column_type),
             matrix_1_column_id,
             opt::Instruction::OperandList(
@@ -768,7 +769,7 @@
         uint32_t matrix_1_column_component_id =
             message_.fresh_ids(fresh_id_index++);
         linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-            ir_context, SpvOpCompositeExtract,
+            ir_context, spv::Op::OpCompositeExtract,
             ir_context->get_type_mgr()->GetId(matrix_1_column_component_type),
             matrix_1_column_component_id,
             opt::Instruction::OperandList(
@@ -779,7 +780,7 @@
         uint32_t matrix_2_column_component_id =
             message_.fresh_ids(fresh_id_index++);
         linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-            ir_context, SpvOpCompositeExtract,
+            ir_context, spv::Op::OpCompositeExtract,
             ir_context->get_type_mgr()->GetId(matrix_1_column_component_type),
             matrix_2_column_component_id,
             opt::Instruction::OperandList(
@@ -789,7 +790,7 @@
         // Multiplies corresponding matrix 1 and matrix 2 column components.
         float_multiplication_ids[k] = message_.fresh_ids(fresh_id_index++);
         linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-            ir_context, SpvOpFMul,
+            ir_context, spv::Op::OpFMul,
             ir_context->get_type_mgr()->GetId(matrix_1_column_component_type),
             float_multiplication_ids[k],
             opt::Instruction::OperandList(
@@ -802,7 +803,7 @@
       uint32_t float_add_id = message_.fresh_ids(fresh_id_index++);
       float_add_ids.push_back(float_add_id);
       linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpFAdd,
+          ir_context, spv::Op::OpFAdd,
           ir_context->get_type_mgr()->GetId(matrix_1_column_component_type),
           float_add_id,
           opt::Instruction::OperandList(
@@ -812,7 +813,7 @@
         float_add_id = message_.fresh_ids(fresh_id_index++);
         float_add_ids.push_back(float_add_id);
         linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-            ir_context, SpvOpFAdd,
+            ir_context, spv::Op::OpFAdd,
             ir_context->get_type_mgr()->GetId(matrix_1_column_component_type),
             float_add_id,
             opt::Instruction::OperandList(
@@ -830,14 +831,14 @@
     }
     result_column_ids[i] = message_.fresh_ids(fresh_id_index++);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeConstruct,
+        ir_context, spv::Op::OpCompositeConstruct,
         ir_context->get_type_mgr()->GetId(matrix_1_column_type),
         result_column_ids[i], opt::Instruction::OperandList(in_operands)));
   }
 
   // The OpMatrixTimesMatrix instruction is changed to an OpCompositeConstruct
   // instruction.
-  linear_algebra_instruction->SetOpcode(SpvOpCompositeConstruct);
+  linear_algebra_instruction->SetOpcode(spv::Op::OpCompositeConstruct);
   linear_algebra_instruction->SetInOperand(0, {result_column_ids[0]});
   linear_algebra_instruction->SetInOperand(1, {result_column_ids[1]});
   for (uint32_t i = 2; i < result_column_ids.size(); i++) {
@@ -880,7 +881,7 @@
     // Extracts |vector_2| component.
     uint32_t vector_2_component_id = message_.fresh_ids(fresh_id_index++);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeExtract,
+        ir_context, spv::Op::OpCompositeExtract,
         ir_context->get_type_mgr()->GetId(vector_1_component_type),
         vector_2_component_id,
         opt::Instruction::OperandList(
@@ -892,7 +893,7 @@
       // Extracts |vector_1| component.
       uint32_t vector_1_component_id = message_.fresh_ids(fresh_id_index++);
       linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpCompositeExtract,
+          ir_context, spv::Op::OpCompositeExtract,
           ir_context->get_type_mgr()->GetId(vector_1_component_type),
           vector_1_component_id,
           opt::Instruction::OperandList(
@@ -902,7 +903,7 @@
       // Multiplies |vector_1| and |vector_2| components.
       column_component_ids[j] = message_.fresh_ids(fresh_id_index++);
       linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpFMul,
+          ir_context, spv::Op::OpFMul,
           ir_context->get_type_mgr()->GetId(vector_1_component_type),
           column_component_ids[j],
           opt::Instruction::OperandList(
@@ -917,13 +918,13 @@
     }
     result_column_ids[i] = message_.fresh_ids(fresh_id_index++);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeConstruct, vector_1_instruction->type_id(),
-        result_column_ids[i], in_operands));
+        ir_context, spv::Op::OpCompositeConstruct,
+        vector_1_instruction->type_id(), result_column_ids[i], in_operands));
   }
 
   // The OpOuterProduct instruction is changed to an OpCompositeConstruct
   // instruction.
-  linear_algebra_instruction->SetOpcode(SpvOpCompositeConstruct);
+  linear_algebra_instruction->SetOpcode(spv::Op::OpCompositeConstruct);
   linear_algebra_instruction->SetInOperand(0, {result_column_ids[0]});
   linear_algebra_instruction->SetInOperand(1, {result_column_ids[1]});
   for (uint32_t i = 2; i < result_column_ids.size(); i++) {
@@ -956,7 +957,7 @@
     uint32_t vector_1_extract_id = message_.fresh_ids(fresh_id_index++);
     fuzzerutil::UpdateModuleIdBound(ir_context, vector_1_extract_id);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeExtract,
+        ir_context, spv::Op::OpCompositeExtract,
         linear_algebra_instruction->type_id(), vector_1_extract_id,
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {vector_1->result_id()}},
@@ -966,7 +967,7 @@
     uint32_t vector_2_extract_id = message_.fresh_ids(fresh_id_index++);
     fuzzerutil::UpdateModuleIdBound(ir_context, vector_2_extract_id);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeExtract,
+        ir_context, spv::Op::OpCompositeExtract,
         linear_algebra_instruction->type_id(), vector_2_extract_id,
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {vector_2->result_id()}},
@@ -976,7 +977,7 @@
     float_multiplication_ids[i] = message_.fresh_ids(fresh_id_index++);
     fuzzerutil::UpdateModuleIdBound(ir_context, float_multiplication_ids[i]);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpFMul, linear_algebra_instruction->type_id(),
+        ir_context, spv::Op::OpFMul, linear_algebra_instruction->type_id(),
         float_multiplication_ids[i],
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {vector_1_extract_id}},
@@ -986,7 +987,7 @@
   // If the vector has 2 components, then there will be 2 float multiplication
   // instructions.
   if (vectors_component_count == 2) {
-    linear_algebra_instruction->SetOpcode(SpvOpFAdd);
+    linear_algebra_instruction->SetOpcode(spv::Op::OpFAdd);
     linear_algebra_instruction->SetInOperand(0, {float_multiplication_ids[0]});
     linear_algebra_instruction->SetInOperand(1, {float_multiplication_ids[1]});
   } else {
@@ -997,7 +998,7 @@
     float_add_ids.push_back(float_add_id);
     fuzzerutil::UpdateModuleIdBound(ir_context, float_add_id);
     linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpFAdd, linear_algebra_instruction->type_id(),
+        ir_context, spv::Op::OpFAdd, linear_algebra_instruction->type_id(),
         float_add_id,
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {float_multiplication_ids[0]}},
@@ -1010,7 +1011,7 @@
       fuzzerutil::UpdateModuleIdBound(ir_context, float_add_id);
       float_add_ids.push_back(float_add_id);
       linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpFAdd, linear_algebra_instruction->type_id(),
+          ir_context, spv::Op::OpFAdd, linear_algebra_instruction->type_id(),
           float_add_id,
           opt::Instruction::OperandList(
               {{SPV_OPERAND_TYPE_ID, {float_multiplication_ids[i]}},
@@ -1019,7 +1020,7 @@
 
     // The last OpFAdd instruction is got by changing some of the OpDot
     // instruction attributes.
-    linear_algebra_instruction->SetOpcode(SpvOpFAdd);
+    linear_algebra_instruction->SetOpcode(spv::Op::OpFAdd);
     linear_algebra_instruction->SetInOperand(
         0, {float_multiplication_ids[float_multiplication_ids.size() - 1]});
     linear_algebra_instruction->SetInOperand(
diff --git a/source/fuzz/transformation_replace_load_store_with_copy_memory.cpp b/source/fuzz/transformation_replace_load_store_with_copy_memory.cpp
index e75337f..36610f2 100644
--- a/source/fuzz/transformation_replace_load_store_with_copy_memory.cpp
+++ b/source/fuzz/transformation_replace_load_store_with_copy_memory.cpp
@@ -48,14 +48,14 @@
   // The OpLoad instruction must be defined.
   auto load_instruction =
       FindInstruction(message_.load_instruction_descriptor(), ir_context);
-  if (!load_instruction || load_instruction->opcode() != SpvOpLoad) {
+  if (!load_instruction || load_instruction->opcode() != spv::Op::OpLoad) {
     return false;
   }
 
   // The OpStore instruction must be defined.
   auto store_instruction =
       FindInstruction(message_.store_instruction_descriptor(), ir_context);
-  if (!store_instruction || store_instruction->opcode() != SpvOpStore) {
+  if (!store_instruction || store_instruction->opcode() != spv::Op::OpStore) {
     return false;
   }
 
@@ -69,7 +69,7 @@
   // Get storage class of the variable pointed by the source operand in OpLoad.
   opt::Instruction* source_id = ir_context->get_def_use_mgr()->GetDef(
       load_instruction->GetSingleWordOperand(2));
-  SpvStorageClass storage_class = fuzzerutil::GetStorageClassFromPointerType(
+  spv::StorageClass storage_class = fuzzerutil::GetStorageClassFromPointerType(
       ir_context, source_id->type_id());
 
   // Iterate over all instructions between |load_instruction| and
@@ -99,11 +99,11 @@
   // OpLoad and OpStore instructions must be defined.
   auto load_instruction =
       FindInstruction(message_.load_instruction_descriptor(), ir_context);
-  assert(load_instruction && load_instruction->opcode() == SpvOpLoad &&
+  assert(load_instruction && load_instruction->opcode() == spv::Op::OpLoad &&
          "The required OpLoad instruction must be defined.");
   auto store_instruction =
       FindInstruction(message_.store_instruction_descriptor(), ir_context);
-  assert(store_instruction && store_instruction->opcode() == SpvOpStore &&
+  assert(store_instruction && store_instruction->opcode() == spv::Op::OpStore &&
          "The required OpStore instruction must be defined.");
 
   // Intermediate values of the OpLoad and the OpStore must match.
@@ -121,7 +121,7 @@
 
   // Insert the OpCopyMemory instruction before the OpStore instruction.
   store_instruction->InsertBefore(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpCopyMemory, 0, 0,
+      ir_context, spv::Op::OpCopyMemory, 0, 0,
       opt::Instruction::OperandList(
           {{SPV_OPERAND_TYPE_ID, {target_variable_id}},
            {SPV_OPERAND_TYPE_ID, {source_variable_id}}})));
@@ -133,14 +133,14 @@
 }
 
 bool TransformationReplaceLoadStoreWithCopyMemory::IsMemoryWritingOpCode(
-    SpvOp op_code) {
+    spv::Op op_code) {
   if (spvOpcodeIsAtomicOp(op_code)) {
-    return op_code != SpvOpAtomicLoad;
+    return op_code != spv::Op::OpAtomicLoad;
   }
   switch (op_code) {
-    case SpvOpStore:
-    case SpvOpCopyMemory:
-    case SpvOpCopyMemorySized:
+    case spv::Op::OpStore:
+    case spv::Op::OpCopyMemory:
+    case spv::Op::OpCopyMemorySized:
       return true;
     default:
       return false;
@@ -148,10 +148,10 @@
 }
 
 bool TransformationReplaceLoadStoreWithCopyMemory::IsMemoryBarrierOpCode(
-    SpvOp op_code) {
+    spv::Op op_code) {
   switch (op_code) {
-    case SpvOpMemoryBarrier:
-    case SpvOpMemoryNamedBarrier:
+    case spv::Op::OpMemoryBarrier:
+    case spv::Op::OpMemoryNamedBarrier:
       return true;
     default:
       return false;
@@ -159,13 +159,13 @@
 }
 
 bool TransformationReplaceLoadStoreWithCopyMemory::
-    IsStorageClassSafeAcrossMemoryBarriers(SpvStorageClass storage_class) {
+    IsStorageClassSafeAcrossMemoryBarriers(spv::StorageClass storage_class) {
   switch (storage_class) {
-    case SpvStorageClassUniformConstant:
-    case SpvStorageClassInput:
-    case SpvStorageClassUniform:
-    case SpvStorageClassPrivate:
-    case SpvStorageClassFunction:
+    case spv::StorageClass::UniformConstant:
+    case spv::StorageClass::Input:
+    case spv::StorageClass::Uniform:
+    case spv::StorageClass::Private:
+    case spv::StorageClass::Function:
       return true;
     default:
       return false;
diff --git a/source/fuzz/transformation_replace_load_store_with_copy_memory.h b/source/fuzz/transformation_replace_load_store_with_copy_memory.h
index bb4d27e..43c754e 100644
--- a/source/fuzz/transformation_replace_load_store_with_copy_memory.h
+++ b/source/fuzz/transformation_replace_load_store_with_copy_memory.h
@@ -52,17 +52,17 @@
 
   // Checks if the instruction that has an |op_code| might write to
   // the source operand of the OpLoad instruction.
-  static bool IsMemoryWritingOpCode(SpvOp op_code);
+  static bool IsMemoryWritingOpCode(spv::Op op_code);
 
   // Checks if the instruction that has an |op_code| is a memory barrier that
   // could interfere with the source operand of the OpLoad instruction
-  static bool IsMemoryBarrierOpCode(SpvOp op_code);
+  static bool IsMemoryBarrierOpCode(spv::Op op_code);
 
   // Checks if the |storage_class| of the source operand of the OpLoad
   // instruction implies that this variable cannot change (due to other threads)
   // across memory barriers.
   static bool IsStorageClassSafeAcrossMemoryBarriers(
-      SpvStorageClass storage_class);
+      spv::StorageClass storage_class);
 
   std::unordered_set<uint32_t> GetFreshIds() const override;
 
diff --git a/source/fuzz/transformation_replace_opphi_id_from_dead_predecessor.cpp b/source/fuzz/transformation_replace_opphi_id_from_dead_predecessor.cpp
index 84ca1ab..eeda68d 100644
--- a/source/fuzz/transformation_replace_opphi_id_from_dead_predecessor.cpp
+++ b/source/fuzz/transformation_replace_opphi_id_from_dead_predecessor.cpp
@@ -38,7 +38,7 @@
     const TransformationContext& transformation_context) const {
   // |opphi_id| must be the id of an OpPhi instruction.
   auto opphi_def = ir_context->get_def_use_mgr()->GetDef(message_.opphi_id());
-  if (!opphi_def || opphi_def->opcode() != SpvOpPhi) {
+  if (!opphi_def || opphi_def->opcode() != spv::Op::OpPhi) {
     return false;
   }
 
diff --git a/source/fuzz/transformation_replace_opselect_with_conditional_branch.cpp b/source/fuzz/transformation_replace_opselect_with_conditional_branch.cpp
index c0e6e44..b2010a9 100644
--- a/source/fuzz/transformation_replace_opselect_with_conditional_branch.cpp
+++ b/source/fuzz/transformation_replace_opselect_with_conditional_branch.cpp
@@ -50,7 +50,7 @@
       ir_context->get_def_use_mgr()->GetDef(message_.select_id());
 
   // The instruction must exist and it must be an OpSelect instruction.
-  if (!instruction || instruction->opcode() != SpvOpSelect) {
+  if (!instruction || instruction->opcode() != spv::Op::OpSelect) {
     return false;
   }
 
@@ -90,7 +90,7 @@
   // The predecessor must not be the header of a construct and it must end with
   // OpBranch.
   if (predecessor->GetMergeInst() != nullptr ||
-      predecessor->terminator()->opcode() != SpvOpBranch) {
+      predecessor->terminator()->opcode() != spv::Op::OpBranch) {
     return false;
   }
 
@@ -115,13 +115,14 @@
       fuzzerutil::UpdateModuleIdBound(ir_context, id);
 
       // Create the new block.
-      auto new_block = MakeUnique<opt::BasicBlock>(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpLabel, 0, id, opt::Instruction::OperandList{}));
+      auto new_block = MakeUnique<opt::BasicBlock>(
+          MakeUnique<opt::Instruction>(ir_context, spv::Op::OpLabel, 0, id,
+                                       opt::Instruction::OperandList{}));
 
       // Add an unconditional branch from the new block to the instruction
       // block.
       new_block->AddInstruction(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpBranch, 0, 0,
+          ir_context, spv::Op::OpBranch, 0, 0,
           opt::Instruction::OperandList{{SPV_OPERAND_TYPE_ID, {block->id()}}}));
 
       // Insert the new block right after the predecessor of the instruction
@@ -136,10 +137,11 @@
   // Add an OpSelectionMerge instruction to the predecessor block, where the
   // merge block is the instruction block.
   predecessor->AddInstruction(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpSelectionMerge, 0, 0,
-      opt::Instruction::OperandList{{SPV_OPERAND_TYPE_ID, {block->id()}},
-                                    {SPV_OPERAND_TYPE_SELECTION_CONTROL,
-                                     {SpvSelectionControlMaskNone}}}));
+      ir_context, spv::Op::OpSelectionMerge, 0, 0,
+      opt::Instruction::OperandList{
+          {SPV_OPERAND_TYPE_ID, {block->id()}},
+          {SPV_OPERAND_TYPE_SELECTION_CONTROL,
+           {uint32_t(spv::SelectionControlMask::MaskNone)}}}));
 
   // |if_block| will be the true block, if it has been created, the instruction
   // block otherwise.
@@ -158,7 +160,7 @@
   // Add a conditional branching instruction to the predecessor, branching to
   // |if_block| if the condition is true and to |if_false| otherwise.
   predecessor->AddInstruction(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpBranchConditional, 0, 0,
+      ir_context, spv::Op::OpBranchConditional, 0, 0,
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {instruction->GetSingleWordInOperand(0)}},
           {SPV_OPERAND_TYPE_ID, {if_block}},
@@ -177,7 +179,7 @@
   // Replace the OpSelect instruction in the merge block with an OpPhi.
   // This:          OpSelect %type %cond %if %else
   // will become:   OpPhi %type %if %if_pred %else %else_pred
-  instruction->SetOpcode(SpvOpPhi);
+  instruction->SetOpcode(spv::Op::OpPhi);
   std::vector<opt::Operand> operands;
 
   operands.emplace_back(instruction->GetInOperand(1));
diff --git a/source/fuzz/transformation_replace_parameter_with_global.cpp b/source/fuzz/transformation_replace_parameter_with_global.cpp
index caf6716..e80dfe9 100644
--- a/source/fuzz/transformation_replace_parameter_with_global.cpp
+++ b/source/fuzz/transformation_replace_parameter_with_global.cpp
@@ -41,7 +41,7 @@
   // Check that |parameter_id| is valid.
   const auto* param_inst =
       ir_context->get_def_use_mgr()->GetDef(message_.parameter_id());
-  if (!param_inst || param_inst->opcode() != SpvOpFunctionParameter) {
+  if (!param_inst || param_inst->opcode() != spv::Op::OpFunctionParameter) {
     return false;
   }
 
@@ -69,7 +69,7 @@
 
   // Check that pointer type for the global variable exists in the module.
   if (!fuzzerutil::MaybeGetPointerType(ir_context, param_inst->type_id(),
-                                       SpvStorageClassPrivate)) {
+                                       spv::StorageClass::Private)) {
     return false;
   }
 
@@ -91,8 +91,8 @@
   fuzzerutil::AddGlobalVariable(
       ir_context, message_.global_variable_fresh_id(),
       fuzzerutil::MaybeGetPointerType(ir_context, param_inst->type_id(),
-                                      SpvStorageClassPrivate),
-      SpvStorageClassPrivate,
+                                      spv::StorageClass::Private),
+      spv::StorageClass::Private,
       fuzzerutil::MaybeGetZeroConstant(ir_context, *transformation_context,
                                        param_inst->type_id(), false));
 
@@ -103,16 +103,17 @@
   // Insert an OpLoad instruction right after OpVariable instructions.
   auto it = function->begin()->begin();
   while (it != function->begin()->end() &&
-         !fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpLoad, it)) {
+         !fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpLoad, it)) {
     ++it;
   }
 
-  assert(fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpLoad, it) &&
+  assert(fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpLoad, it) &&
          "Can't insert OpLoad or OpCopyMemory into the first basic block of "
          "the function");
 
   it.InsertBefore(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpLoad, param_inst->type_id(), param_inst->result_id(),
+      ir_context, spv::Op::OpLoad, param_inst->type_id(),
+      param_inst->result_id(),
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {message_.global_variable_fresh_id()}}}));
 
@@ -132,13 +133,14 @@
 
   // Update all relevant OpFunctionCall instructions.
   for (auto* inst : fuzzerutil::GetCallers(ir_context, function->result_id())) {
-    assert(fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpStore, inst) &&
-           "Can't insert OpStore right before the function call");
+    assert(
+        fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpStore, inst) &&
+        "Can't insert OpStore right before the function call");
 
     // Insert an OpStore before the OpFunctionCall. +1 since the first
     // operand of OpFunctionCall is an id of the function.
     inst->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpStore, 0, 0,
+        ir_context, spv::Op::OpStore, 0, 0,
         opt::Instruction::OperandList{
             {SPV_OPERAND_TYPE_ID, {message_.global_variable_fresh_id()}},
             {SPV_OPERAND_TYPE_ID,
diff --git a/source/fuzz/transformation_replace_params_with_struct.cpp b/source/fuzz/transformation_replace_params_with_struct.cpp
index 13eeccb..c8af14a 100644
--- a/source/fuzz/transformation_replace_params_with_struct.cpp
+++ b/source/fuzz/transformation_replace_params_with_struct.cpp
@@ -142,7 +142,7 @@
 
   // Add new parameter to the function.
   function->AddParameter(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpFunctionParameter, struct_type_id,
+      ir_context, spv::Op::OpFunctionParameter, struct_type_id,
       message_.fresh_parameter_id(), opt::Instruction::OperandList()));
 
   fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_parameter_id());
@@ -182,8 +182,8 @@
     auto fresh_composite_id =
         caller_id_to_fresh_composite_id.at(inst->result_id());
     inst->InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeConstruct, struct_type_id, fresh_composite_id,
-        std::move(composite_components)));
+        ir_context, spv::Op::OpCompositeConstruct, struct_type_id,
+        fresh_composite_id, std::move(composite_components)));
 
     // Add a new operand to the OpFunctionCall instruction.
     inst->AddOperand({SPV_OPERAND_TYPE_ID, {fresh_composite_id}});
@@ -200,19 +200,19 @@
     // Skip all OpVariable instructions.
     auto iter = function->begin()->begin();
     while (iter != function->begin()->end() &&
-           !fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpCompositeExtract,
-                                                         iter)) {
+           !fuzzerutil::CanInsertOpcodeBeforeInstruction(
+               spv::Op::OpCompositeExtract, iter)) {
       ++iter;
     }
 
-    assert(fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpCompositeExtract,
-                                                        iter) &&
+    assert(fuzzerutil::CanInsertOpcodeBeforeInstruction(
+               spv::Op::OpCompositeExtract, iter) &&
            "Can't extract parameter's value from the structure");
 
     // Insert OpCompositeExtract instructions to unpack parameters' values from
     // the struct type.
     iter.InsertBefore(MakeUnique<opt::Instruction>(
-        ir_context, SpvOpCompositeExtract, param_inst->type_id(),
+        ir_context, spv::Op::OpCompositeExtract, param_inst->type_id(),
         param_inst->result_id(),
         opt::Instruction::OperandList{
             {SPV_OPERAND_TYPE_ID, {message_.fresh_parameter_id()}},
diff --git a/source/fuzz/transformation_set_function_control.cpp b/source/fuzz/transformation_set_function_control.cpp
index 02a8c9f..ef48171 100644
--- a/source/fuzz/transformation_set_function_control.cpp
+++ b/source/fuzz/transformation_set_function_control.cpp
@@ -40,9 +40,9 @@
 
   // Check (via an assertion) that function control mask doesn't have any bad
   // bits set.
-  uint32_t acceptable_function_control_bits =
-      SpvFunctionControlInlineMask | SpvFunctionControlDontInlineMask |
-      SpvFunctionControlPureMask | SpvFunctionControlConstMask;
+  uint32_t acceptable_function_control_bits = uint32_t(
+      spv::FunctionControlMask::Inline | spv::FunctionControlMask::DontInline |
+      spv::FunctionControlMask::Pure | spv::FunctionControlMask::Const);
   // The following is to keep release-mode compilers happy as this variable is
   // only used in an assertion.
   (void)(acceptable_function_control_bits);
@@ -51,17 +51,19 @@
 
   // Check (via an assertion) that function control mask does not have both
   // Inline and DontInline bits set.
-  assert(!((message_.function_control() & SpvFunctionControlInlineMask) &&
-           (message_.function_control() & SpvFunctionControlDontInlineMask)) &&
+  assert(!((message_.function_control() &
+            (uint32_t)spv::FunctionControlMask::Inline) &&
+           (message_.function_control() &
+            (uint32_t)spv::FunctionControlMask::DontInline)) &&
          "It is not OK to set both the 'Inline' and 'DontInline' bits of a "
          "function control mask");
 
   // Check that Const and Pure are only present if they were present on the
   // original function
   for (auto mask_bit :
-       {SpvFunctionControlPureMask, SpvFunctionControlConstMask}) {
-    if ((message_.function_control() & mask_bit) &&
-        !(existing_function_control_mask & mask_bit)) {
+       {spv::FunctionControlMask::Pure, spv::FunctionControlMask::Const}) {
+    if ((message_.function_control() & uint32_t(mask_bit)) &&
+        !(existing_function_control_mask & uint32_t(mask_bit))) {
       return false;
     }
   }
diff --git a/source/fuzz/transformation_set_loop_control.cpp b/source/fuzz/transformation_set_loop_control.cpp
index 1449960..dc9ee7c 100644
--- a/source/fuzz/transformation_set_loop_control.cpp
+++ b/source/fuzz/transformation_set_loop_control.cpp
@@ -38,18 +38,20 @@
     return false;
   }
   auto merge_inst = block->GetMergeInst();
-  if (!merge_inst || merge_inst->opcode() != SpvOpLoopMerge) {
+  if (!merge_inst || merge_inst->opcode() != spv::Op::OpLoopMerge) {
     return false;
   }
 
   // We assert that the transformation does not try to set any meaningless bits
   // of the loop control mask.
-  uint32_t all_loop_control_mask_bits_set =
-      SpvLoopControlUnrollMask | SpvLoopControlDontUnrollMask |
-      SpvLoopControlDependencyInfiniteMask |
-      SpvLoopControlDependencyLengthMask | SpvLoopControlMinIterationsMask |
-      SpvLoopControlMaxIterationsMask | SpvLoopControlIterationMultipleMask |
-      SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask;
+  uint32_t all_loop_control_mask_bits_set = uint32_t(
+      spv::LoopControlMask::Unroll | spv::LoopControlMask::DontUnroll |
+      spv::LoopControlMask::DependencyInfinite |
+      spv::LoopControlMask::DependencyLength |
+      spv::LoopControlMask::MinIterations |
+      spv::LoopControlMask::MaxIterations |
+      spv::LoopControlMask::IterationMultiple |
+      spv::LoopControlMask::PeelCount | spv::LoopControlMask::PartialCount);
 
   // The variable is only used in an assertion; the following keeps release-mode
   // compilers happy.
@@ -65,10 +67,11 @@
 
   // Check that there is no attempt to set one of the loop controls that
   // requires guarantees to hold.
-  for (SpvLoopControlMask mask :
-       {SpvLoopControlDependencyInfiniteMask,
-        SpvLoopControlDependencyLengthMask, SpvLoopControlMinIterationsMask,
-        SpvLoopControlMaxIterationsMask, SpvLoopControlIterationMultipleMask}) {
+  for (spv::LoopControlMask mask : {spv::LoopControlMask::DependencyInfinite,
+                                    spv::LoopControlMask::DependencyLength,
+                                    spv::LoopControlMask::MinIterations,
+                                    spv::LoopControlMask::MaxIterations,
+                                    spv::LoopControlMask::IterationMultiple}) {
     // We have a problem if this loop control bit was not set in the original
     // loop control mask but is set by the transformation.
     if (LoopControlBitIsAddedByTransformation(mask,
@@ -78,33 +81,36 @@
   }
 
   // Check that PeelCount and PartialCount are supported if used.
-  if ((message_.loop_control() & SpvLoopControlPeelCountMask) &&
+  if ((message_.loop_control() & uint32_t(spv::LoopControlMask::PeelCount)) &&
       !PeelCountIsSupported(ir_context)) {
     return false;
   }
 
-  if ((message_.loop_control() & SpvLoopControlPartialCountMask) &&
+  if ((message_.loop_control() &
+       uint32_t(spv::LoopControlMask::PartialCount)) &&
       !PartialCountIsSupported(ir_context)) {
     return false;
   }
 
   if (message_.peel_count() > 0 &&
-      !(message_.loop_control() & SpvLoopControlPeelCountMask)) {
+      !(message_.loop_control() & uint32_t(spv::LoopControlMask::PeelCount))) {
     // Peel count provided, but peel count mask bit not set.
     return false;
   }
 
   if (message_.partial_count() > 0 &&
-      !(message_.loop_control() & SpvLoopControlPartialCountMask)) {
+      !(message_.loop_control() &
+        uint32_t(spv::LoopControlMask::PartialCount))) {
     // Partial count provided, but partial count mask bit not set.
     return false;
   }
 
   // We must not set both 'don't unroll' and one of 'peel count' or 'partial
   // count'.
-  return !((message_.loop_control() & SpvLoopControlDontUnrollMask) &&
-           (message_.loop_control() &
-            (SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask)));
+  return !(
+      (message_.loop_control() & uint32_t(spv::LoopControlMask::DontUnroll)) &&
+      (message_.loop_control() & uint32_t(spv::LoopControlMask::PeelCount |
+                                          spv::LoopControlMask::PartialCount)));
 }
 
 void TransformationSetLoopControl::Apply(
@@ -133,13 +139,14 @@
 
   uint32_t literal_index = 0;  // Indexes into the literals from the original
   // instruction.
-  for (SpvLoopControlMask mask :
-       {SpvLoopControlDependencyLengthMask, SpvLoopControlMinIterationsMask,
-        SpvLoopControlMaxIterationsMask, SpvLoopControlIterationMultipleMask}) {
+  for (spv::LoopControlMask mask : {spv::LoopControlMask::DependencyLength,
+                                    spv::LoopControlMask::MinIterations,
+                                    spv::LoopControlMask::MaxIterations,
+                                    spv::LoopControlMask::IterationMultiple}) {
     // Check whether the bit was set in the original loop control mask.
-    if (existing_loop_control_mask & mask) {
+    if (existing_loop_control_mask & uint32_t(mask)) {
       // Check whether the bit is set in the new loop control mask.
-      if (message_.loop_control() & mask) {
+      if (message_.loop_control() & uint32_t(mask)) {
         // Add the associated literal to our sequence of replacement operands.
         new_operands.push_back(
             {SPV_OPERAND_TYPE_LITERAL_INTEGER,
@@ -154,13 +161,13 @@
 
   // If PeelCount is set in the new mask, |message_.peel_count| provides the
   // associated peel count.
-  if (message_.loop_control() & SpvLoopControlPeelCountMask) {
+  if (message_.loop_control() & uint32_t(spv::LoopControlMask::PeelCount)) {
     new_operands.push_back(
         {SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.peel_count()}});
   }
 
   // Similar, but for PartialCount.
-  if (message_.loop_control() & SpvLoopControlPartialCountMask) {
+  if (message_.loop_control() & uint32_t(spv::LoopControlMask::PartialCount)) {
     new_operands.push_back(
         {SPV_OPERAND_TYPE_LITERAL_INTEGER, {message_.partial_count()}});
   }
@@ -177,10 +184,11 @@
 }
 
 bool TransformationSetLoopControl::LoopControlBitIsAddedByTransformation(
-    SpvLoopControlMask loop_control_single_bit_mask,
+    spv::LoopControlMask loop_control_single_bit_mask,
     uint32_t existing_loop_control_mask) const {
-  return !(loop_control_single_bit_mask & existing_loop_control_mask) &&
-         (loop_control_single_bit_mask & message_.loop_control());
+  return !(uint32_t(loop_control_single_bit_mask) &
+           existing_loop_control_mask) &&
+         (uint32_t(loop_control_single_bit_mask) & message_.loop_control());
 }
 
 bool TransformationSetLoopControl::PartialCountIsSupported(
diff --git a/source/fuzz/transformation_set_loop_control.h b/source/fuzz/transformation_set_loop_control.h
index bc17c8a..d57447b 100644
--- a/source/fuzz/transformation_set_loop_control.h
+++ b/source/fuzz/transformation_set_loop_control.h
@@ -71,7 +71,7 @@
   // Returns true if and only if |loop_single_bit_mask| is *not* set in
   // |existing_loop_control| but *is* set in |message_.loop_control|.
   bool LoopControlBitIsAddedByTransformation(
-      SpvLoopControlMask loop_control_single_bit_mask,
+      spv::LoopControlMask loop_control_single_bit_mask,
       uint32_t existing_loop_control_mask) const;
 
   protobufs::TransformationSetLoopControl message_;
diff --git a/source/fuzz/transformation_set_memory_operands_mask.cpp b/source/fuzz/transformation_set_memory_operands_mask.cpp
index 5a986ad..16d591a 100644
--- a/source/fuzz/transformation_set_memory_operands_mask.cpp
+++ b/source/fuzz/transformation_set_memory_operands_mask.cpp
@@ -48,10 +48,13 @@
     // which they were applied during fuzzing, hence why these are assertions
     // rather than applicability checks.
     assert(message_.memory_operands_mask_index() == 1);
-    assert(message_.memory_access_instruction().target_instruction_opcode() ==
-               SpvOpCopyMemory ||
-           message_.memory_access_instruction().target_instruction_opcode() ==
-               SpvOpCopyMemorySized);
+    assert(
+        spv::Op(
+            message_.memory_access_instruction().target_instruction_opcode()) ==
+            spv::Op::OpCopyMemory ||
+        spv::Op(
+            message_.memory_access_instruction().target_instruction_opcode()) ==
+            spv::Op::OpCopyMemorySized);
     assert(MultipleMemoryOperandMasksAreSupported(ir_context) &&
            "Multiple memory operand masks are not supported for this SPIR-V "
            "version.");
@@ -73,12 +76,12 @@
   uint32_t original_mask =
       original_mask_in_operand_index < instruction->NumInOperands()
           ? instruction->GetSingleWordInOperand(original_mask_in_operand_index)
-          : static_cast<uint32_t>(SpvMemoryAccessMaskNone);
+          : static_cast<uint32_t>(spv::MemoryAccessMask::MaskNone);
   uint32_t new_mask = message_.memory_operands_mask();
 
   // Volatile must not be removed
-  if ((original_mask & SpvMemoryAccessVolatileMask) &&
-      !(new_mask & SpvMemoryAccessVolatileMask)) {
+  if ((original_mask & uint32_t(spv::MemoryAccessMask::Volatile)) &&
+      !(new_mask & uint32_t(spv::MemoryAccessMask::Volatile))) {
     return false;
   }
 
@@ -87,10 +90,10 @@
   // their Volatile and Nontemporal flags to the same value (this works
   // because valid manipulation of Volatile is checked above, and the manner
   // in which Nontemporal is manipulated does not matter).
-  return (original_mask | SpvMemoryAccessVolatileMask |
-          SpvMemoryAccessNontemporalMask) ==
-         (new_mask | SpvMemoryAccessVolatileMask |
-          SpvMemoryAccessNontemporalMask);
+  return (original_mask | uint32_t(spv::MemoryAccessMask::Volatile) |
+          uint32_t(spv::MemoryAccessMask::Nontemporal)) ==
+         (new_mask | uint32_t(spv::MemoryAccessMask::Volatile) |
+          uint32_t(spv::MemoryAccessMask::Nontemporal));
 }
 
 void TransformationSetMemoryOperandsMask::Apply(
@@ -106,8 +109,8 @@
     if (message_.memory_operands_mask_index() == 1 &&
         GetInOperandIndexForMask(*instruction, 0) >=
             instruction->NumInOperands()) {
-      instruction->AddOperand(
-          {SPV_OPERAND_TYPE_MEMORY_ACCESS, {SpvMemoryAccessMaskNone}});
+      instruction->AddOperand({SPV_OPERAND_TYPE_MEMORY_ACCESS,
+                               {uint32_t(spv::MemoryAccessMask::MaskNone)}});
     }
 
     instruction->AddOperand(
@@ -129,10 +132,10 @@
 bool TransformationSetMemoryOperandsMask::IsMemoryAccess(
     const opt::Instruction& instruction) {
   switch (instruction.opcode()) {
-    case SpvOpLoad:
-    case SpvOpStore:
-    case SpvOpCopyMemory:
-    case SpvOpCopyMemorySized:
+    case spv::Op::OpLoad:
+    case spv::Op::OpStore:
+    case spv::Op::OpCopyMemory:
+    case spv::Op::OpCopyMemorySized:
       return true;
     default:
       return false;
@@ -145,16 +148,16 @@
   // for the instruction.
   uint32_t first_mask_in_operand_index = 0;
   switch (instruction.opcode()) {
-    case SpvOpLoad:
+    case spv::Op::OpLoad:
       first_mask_in_operand_index = kOpLoadMemoryOperandsMaskIndex;
       break;
-    case SpvOpStore:
+    case spv::Op::OpStore:
       first_mask_in_operand_index = kOpStoreMemoryOperandsMaskIndex;
       break;
-    case SpvOpCopyMemory:
+    case spv::Op::OpCopyMemory:
       first_mask_in_operand_index = kOpCopyMemoryFirstMemoryOperandsMaskIndex;
       break;
-    case SpvOpCopyMemorySized:
+    case spv::Op::OpCopyMemorySized:
       first_mask_in_operand_index =
           kOpCopyMemorySizedFirstMemoryOperandsMaskIndex;
       break;
@@ -192,12 +195,12 @@
   // Consider each bit that might have an associated extra input operand, and
   // count how many there are expected to be.
   uint32_t first_mask_extra_operand_count = 0;
-  for (auto mask_bit :
-       {SpvMemoryAccessAlignedMask, SpvMemoryAccessMakePointerAvailableMask,
-        SpvMemoryAccessMakePointerAvailableKHRMask,
-        SpvMemoryAccessMakePointerVisibleMask,
-        SpvMemoryAccessMakePointerVisibleKHRMask}) {
-    if (first_mask & mask_bit) {
+  for (auto mask_bit : {spv::MemoryAccessMask::Aligned,
+                        spv::MemoryAccessMask::MakePointerAvailable,
+                        spv::MemoryAccessMask::MakePointerAvailableKHR,
+                        spv::MemoryAccessMask::MakePointerVisible,
+                        spv::MemoryAccessMask::MakePointerVisibleKHR}) {
+    if (first_mask & uint32_t(mask_bit)) {
       first_mask_extra_operand_count++;
     }
   }
diff --git a/source/fuzz/transformation_set_selection_control.cpp b/source/fuzz/transformation_set_selection_control.cpp
index 6dddbdf..c6f68d9 100644
--- a/source/fuzz/transformation_set_selection_control.cpp
+++ b/source/fuzz/transformation_set_selection_control.cpp
@@ -29,14 +29,17 @@
 
 bool TransformationSetSelectionControl::IsApplicable(
     opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
-  assert((message_.selection_control() == SpvSelectionControlMaskNone ||
-          message_.selection_control() == SpvSelectionControlFlattenMask ||
-          message_.selection_control() == SpvSelectionControlDontFlattenMask) &&
+  assert((spv::SelectionControlMask(message_.selection_control()) ==
+              spv::SelectionControlMask::MaskNone ||
+          spv::SelectionControlMask(message_.selection_control()) ==
+              spv::SelectionControlMask::Flatten ||
+          spv::SelectionControlMask(message_.selection_control()) ==
+              spv::SelectionControlMask::DontFlatten) &&
          "Selection control should never be set to something other than "
          "'None', 'Flatten' or 'DontFlatten'");
   if (auto block = ir_context->get_instr_block(message_.block_id())) {
     if (auto merge_inst = block->GetMergeInst()) {
-      return merge_inst->opcode() == SpvOpSelectionMerge;
+      return merge_inst->opcode() == spv::Op::OpSelectionMerge;
     }
   }
   // Either the block did not exit, or did not end with OpSelectionMerge.
diff --git a/source/fuzz/transformation_split_block.cpp b/source/fuzz/transformation_split_block.cpp
index e15dffa..959bedc 100644
--- a/source/fuzz/transformation_split_block.cpp
+++ b/source/fuzz/transformation_split_block.cpp
@@ -64,19 +64,19 @@
          " block split point exists.");
 
   if (split_before->PreviousNode() &&
-      split_before->PreviousNode()->opcode() == SpvOpSelectionMerge) {
+      split_before->PreviousNode()->opcode() == spv::Op::OpSelectionMerge) {
     // We cannot split directly after a selection merge: this would separate
     // the merge from its associated branch or switch operation.
     return false;
   }
-  if (split_before->opcode() == SpvOpVariable) {
+  if (split_before->opcode() == spv::Op::OpVariable) {
     // We cannot split directly after a variable; variables in a function
     // must be contiguous in the entry block.
     return false;
   }
   // We cannot split before an OpPhi unless the OpPhi has exactly one
   // associated incoming edge.
-  if (split_before->opcode() == SpvOpPhi &&
+  if (split_before->opcode() == spv::Op::OpPhi &&
       split_before->NumInOperands() != 2) {
     return false;
   }
@@ -110,7 +110,7 @@
   // The split does not automatically add a branch between the two parts of
   // the original block, so we add one.
   auto branch_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpBranch, 0, 0,
+      ir_context, spv::Op::OpBranch, 0, 0,
       std::initializer_list<opt::Operand>{opt::Operand(
           spv_operand_type_t::SPV_OPERAND_TYPE_ID, {message_.fresh_id()})});
   auto branch_instruction_ptr = branch_instruction.get();
diff --git a/source/fuzz/transformation_store.cpp b/source/fuzz/transformation_store.cpp
index c00cd34..6ba1c55 100644
--- a/source/fuzz/transformation_store.cpp
+++ b/source/fuzz/transformation_store.cpp
@@ -48,7 +48,7 @@
   // The pointer type must indeed be a pointer.
   auto pointer_type = ir_context->get_def_use_mgr()->GetDef(pointer->type_id());
   assert(pointer_type && "Type id must be defined.");
-  if (pointer_type->opcode() != SpvOpTypePointer) {
+  if (pointer_type->opcode() != spv::Op::OpTypePointer) {
     return false;
   }
 
@@ -59,8 +59,8 @@
 
   // We do not want to allow storing to null or undefined pointers.
   switch (pointer->opcode()) {
-    case SpvOpConstantNull:
-    case SpvOpUndef:
+    case spv::Op::OpConstantNull:
+    case spv::Op::OpUndef:
       return false;
     default:
       break;
@@ -75,11 +75,11 @@
   }
   // ... and it must be legitimate to insert a store before it.
   if (!message_.is_atomic() && !fuzzerutil::CanInsertOpcodeBeforeInstruction(
-                                   SpvOpStore, insert_before)) {
+                                   spv::Op::OpStore, insert_before)) {
     return false;
   }
   if (message_.is_atomic() && !fuzzerutil::CanInsertOpcodeBeforeInstruction(
-                                  SpvOpAtomicStore, insert_before)) {
+                                  spv::Op::OpAtomicStore, insert_before)) {
     return false;
   }
 
@@ -125,10 +125,10 @@
     }
     // The memory scope and memory semantics instructions must have the
     // 'OpConstant' opcode.
-    if (memory_scope_instruction->opcode() != SpvOpConstant) {
+    if (memory_scope_instruction->opcode() != spv::Op::OpConstant) {
       return false;
     }
-    if (memory_semantics_instruction->opcode() != SpvOpConstant) {
+    if (memory_semantics_instruction->opcode() != spv::Op::OpConstant) {
       return false;
     }
     // The memory scope and memory semantics need to be available before
@@ -145,12 +145,12 @@
     // operand type with signedness does not matters.
     if (ir_context->get_def_use_mgr()
             ->GetDef(memory_scope_instruction->type_id())
-            ->opcode() != SpvOpTypeInt) {
+            ->opcode() != spv::Op::OpTypeInt) {
       return false;
     }
     if (ir_context->get_def_use_mgr()
             ->GetDef(memory_semantics_instruction->type_id())
-            ->opcode() != SpvOpTypeInt) {
+            ->opcode() != spv::Op::OpTypeInt) {
       return false;
     }
 
@@ -172,20 +172,20 @@
       return false;
     }
 
-    // The memory scope constant value must be that of SpvScopeInvocation.
+    // The memory scope constant value must be that of spv::Scope::Invocation.
     auto memory_scope_const_value =
         memory_scope_instruction->GetSingleWordInOperand(0);
-    if (memory_scope_const_value != SpvScopeInvocation) {
+    if (spv::Scope(memory_scope_const_value) != spv::Scope::Invocation) {
       return false;
     }
 
     // The memory semantics constant value must match the storage class of the
     // pointer being loaded from.
-    auto memory_semantics_const_value = static_cast<SpvMemorySemanticsMask>(
+    auto memory_semantics_const_value = static_cast<spv::MemorySemanticsMask>(
         memory_semantics_instruction->GetSingleWordInOperand(0));
     if (memory_semantics_const_value !=
         fuzzerutil::GetMemorySemanticsForStorageClass(
-            static_cast<SpvStorageClass>(
+            static_cast<spv::StorageClass>(
                 pointer_type->GetSingleWordInOperand(0)))) {
       return false;
     }
@@ -203,7 +203,7 @@
     auto insert_before =
         FindInstruction(message_.instruction_to_insert_before(), ir_context);
     auto new_instruction = MakeUnique<opt::Instruction>(
-        ir_context, SpvOpAtomicStore, 0, 0,
+        ir_context, spv::Op::OpAtomicStore, 0, 0,
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {message_.pointer_id()}},
              {SPV_OPERAND_TYPE_SCOPE_ID, {message_.memory_scope_id()}},
@@ -223,7 +223,7 @@
     auto insert_before =
         FindInstruction(message_.instruction_to_insert_before(), ir_context);
     auto new_instruction = MakeUnique<opt::Instruction>(
-        ir_context, SpvOpStore, 0, 0,
+        ir_context, spv::Op::OpStore, 0, 0,
         opt::Instruction::OperandList(
             {{SPV_OPERAND_TYPE_ID, {message_.pointer_id()}},
              {SPV_OPERAND_TYPE_ID, {message_.value_id()}}}));
diff --git a/source/fuzz/transformation_store.h b/source/fuzz/transformation_store.h
index 638713b..5b55ce6 100644
--- a/source/fuzz/transformation_store.h
+++ b/source/fuzz/transformation_store.h
@@ -38,7 +38,7 @@
   // - |message_.is_atomic| must be true if want to work with OpAtomicStore.
   // - If |is_atomic| is true then |message_memory_scope_id| must be the id of
   //   an OpConstant 32 bit integer instruction with the value
-  //   SpvScopeInvocation.
+  //   spv::Scope::Invocation.
   // - If |is_atomic| is true then |message_.memory_semantics_id| must be the id
   //   of an OpConstant 32 bit integer instruction with the values
   //   SpvMemorySemanticsWorkgroupMemoryMask or
diff --git a/source/fuzz/transformation_swap_commutable_operands.cpp b/source/fuzz/transformation_swap_commutable_operands.cpp
index a02e95a..1512144 100644
--- a/source/fuzz/transformation_swap_commutable_operands.cpp
+++ b/source/fuzz/transformation_swap_commutable_operands.cpp
@@ -35,9 +35,9 @@
       FindInstruction(message_.instruction_descriptor(), ir_context);
   if (instruction == nullptr) return false;
 
-  SpvOp opcode = static_cast<SpvOp>(
+  spv::Op opcode = static_cast<spv::Op>(
       message_.instruction_descriptor().target_instruction_opcode());
-  assert(instruction->opcode() == opcode &&
+  assert(spv::Op(instruction->opcode()) == opcode &&
          "The located instruction must have the same opcode as in the "
          "descriptor.");
   return spvOpcodeIsCommutativeBinaryOperator(opcode);
diff --git a/source/fuzz/transformation_swap_conditional_branch_operands.cpp b/source/fuzz/transformation_swap_conditional_branch_operands.cpp
index 340836d..520a6a8 100644
--- a/source/fuzz/transformation_swap_conditional_branch_operands.cpp
+++ b/source/fuzz/transformation_swap_conditional_branch_operands.cpp
@@ -38,7 +38,7 @@
   const auto* inst =
       FindInstruction(message_.instruction_descriptor(), ir_context);
   return fuzzerutil::IsFreshId(ir_context, message_.fresh_id()) && inst &&
-         inst->opcode() == SpvOpBranchConditional;
+         inst->opcode() == spv::Op::OpBranchConditional;
 }
 
 void TransformationSwapConditionalBranchOperands::Apply(
@@ -53,13 +53,15 @@
   // Compute the last instruction in the |block| that allows us to insert
   // OpLogicalNot above it.
   auto iter = fuzzerutil::GetIteratorForInstruction(block, branch_inst);
-  if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpLogicalNot, iter)) {
+  if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpLogicalNot,
+                                                    iter)) {
     // There might be a merge instruction before OpBranchConditional.
     --iter;
   }
 
-  assert(fuzzerutil::CanInsertOpcodeBeforeInstruction(SpvOpLogicalNot, iter) &&
-         "We should now be able to insert SpvOpLogicalNot before |iter|");
+  assert(fuzzerutil::CanInsertOpcodeBeforeInstruction(spv::Op::OpLogicalNot,
+                                                      iter) &&
+         "We should now be able to insert spv::Op::OpLogicalNot before |iter|");
 
   // Get the instruction whose result is used as a condition for
   // OpBranchConditional.
@@ -70,7 +72,7 @@
   // We are swapping the labels in OpBranchConditional. This means that we must
   // invert the guard as well. We are using OpLogicalNot for that purpose here.
   auto new_instruction = MakeUnique<opt::Instruction>(
-      ir_context, SpvOpLogicalNot, condition_inst->type_id(),
+      ir_context, spv::Op::OpLogicalNot, condition_inst->type_id(),
       message_.fresh_id(),
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {condition_inst->result_id()}}});
diff --git a/source/fuzz/transformation_swap_function_variables.cpp b/source/fuzz/transformation_swap_function_variables.cpp
index aec32fe..14ba7bb 100644
--- a/source/fuzz/transformation_swap_function_variables.cpp
+++ b/source/fuzz/transformation_swap_function_variables.cpp
@@ -43,8 +43,8 @@
     return false;
   }
   // Both instructions must be variables.
-  if (instruction1->opcode() != SpvOpVariable ||
-      instruction2->opcode() != SpvOpVariable) {
+  if (instruction1->opcode() != spv::Op::OpVariable ||
+      instruction2->opcode() != spv::Op::OpVariable) {
     return false;
   }
 
diff --git a/source/fuzz/transformation_toggle_access_chain_instruction.cpp b/source/fuzz/transformation_toggle_access_chain_instruction.cpp
index 34523fe..ae6ab9a 100644
--- a/source/fuzz/transformation_toggle_access_chain_instruction.cpp
+++ b/source/fuzz/transformation_toggle_access_chain_instruction.cpp
@@ -39,14 +39,15 @@
     return false;
   }
 
-  SpvOp opcode = static_cast<SpvOp>(
+  spv::Op opcode = static_cast<spv::Op>(
       message_.instruction_descriptor().target_instruction_opcode());
 
   assert(instruction->opcode() == opcode &&
          "The located instruction must have the same opcode as in the "
          "descriptor.");
 
-  if (opcode == SpvOpAccessChain || opcode == SpvOpInBoundsAccessChain) {
+  if (opcode == spv::Op::OpAccessChain ||
+      opcode == spv::Op::OpInBoundsAccessChain) {
     return true;
   }
 
@@ -57,15 +58,15 @@
     opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
   auto instruction =
       FindInstruction(message_.instruction_descriptor(), ir_context);
-  SpvOp opcode = instruction->opcode();
+  spv::Op opcode = instruction->opcode();
 
-  if (opcode == SpvOpAccessChain) {
-    instruction->SetOpcode(SpvOpInBoundsAccessChain);
+  if (opcode == spv::Op::OpAccessChain) {
+    instruction->SetOpcode(spv::Op::OpInBoundsAccessChain);
   } else {
-    assert(opcode == SpvOpInBoundsAccessChain &&
+    assert(opcode == spv::Op::OpInBoundsAccessChain &&
            "The located instruction must be an OpInBoundsAccessChain "
            "instruction.");
-    instruction->SetOpcode(SpvOpAccessChain);
+    instruction->SetOpcode(spv::Op::OpAccessChain);
   }
 }
 
diff --git a/source/fuzz/transformation_vector_shuffle.cpp b/source/fuzz/transformation_vector_shuffle.cpp
index 742a2c8..8ba557c 100644
--- a/source/fuzz/transformation_vector_shuffle.cpp
+++ b/source/fuzz/transformation_vector_shuffle.cpp
@@ -108,7 +108,7 @@
   // It must be legitimate to insert an OpVectorShuffle before the identified
   // instruction.
   return fuzzerutil::CanInsertOpcodeBeforeInstruction(
-      SpvOpVectorShuffle, instruction_to_insert_before);
+      spv::Op::OpVectorShuffle, instruction_to_insert_before);
 }
 
 void TransformationVectorShuffle::Apply(
@@ -134,8 +134,8 @@
       FindInstruction(message_.instruction_to_insert_before(), ir_context);
   opt::Instruction* new_instruction =
       insert_before->InsertBefore(MakeUnique<opt::Instruction>(
-          ir_context, SpvOpVectorShuffle, result_type_id, message_.fresh_id(),
-          shuffle_operands));
+          ir_context, spv::Op::OpVectorShuffle, result_type_id,
+          message_.fresh_id(), shuffle_operands));
   fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
   // Inform the def-use manager about the new instruction and record its basic
   // block.
diff --git a/source/fuzz/transformation_wrap_early_terminator_in_function.cpp b/source/fuzz/transformation_wrap_early_terminator_in_function.cpp
index 468d809..f59d78a 100644
--- a/source/fuzz/transformation_wrap_early_terminator_in_function.cpp
+++ b/source/fuzz/transformation_wrap_early_terminator_in_function.cpp
@@ -52,9 +52,9 @@
     return false;
   }
   switch (early_terminator->opcode()) {
-    case SpvOpKill:
-    case SpvOpUnreachable:
-    case SpvOpTerminateInvocation:
+    case spv::Op::OpKill:
+    case spv::Op::OpUnreachable:
+    case spv::Op::OpTerminateInvocation:
       break;
     default:
       return false;
@@ -119,7 +119,7 @@
       MaybeGetWrapperFunction(ir_context, early_terminator->opcode());
 
   iterator->InsertBefore(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpFunctionCall, wrapper_function->type_id(),
+      ir_context, spv::Op::OpFunctionCall, wrapper_function->type_id(),
       message_.fresh_id(),
       opt::Instruction::OperandList(
           {{SPV_OPERAND_TYPE_ID, {wrapper_function->result_id()}}})));
@@ -130,9 +130,9 @@
            ->AsVoid()) {
     new_in_operands.push_back(
         {SPV_OPERAND_TYPE_ID, {message_.returned_value_id()}});
-    early_terminator->SetOpcode(SpvOpReturnValue);
+    early_terminator->SetOpcode(spv::Op::OpReturnValue);
   } else {
-    early_terminator->SetOpcode(SpvOpReturn);
+    early_terminator->SetOpcode(spv::Op::OpReturn);
   }
   early_terminator->SetInOperands(std::move(new_in_operands));
 
@@ -153,10 +153,10 @@
 
 opt::Function*
 TransformationWrapEarlyTerminatorInFunction::MaybeGetWrapperFunction(
-    opt::IRContext* ir_context, SpvOp early_terminator_opcode) {
-  assert((early_terminator_opcode == SpvOpKill ||
-          early_terminator_opcode == SpvOpUnreachable ||
-          early_terminator_opcode == SpvOpTerminateInvocation) &&
+    opt::IRContext* ir_context, spv::Op early_terminator_opcode) {
+  assert((early_terminator_opcode == spv::Op::OpKill ||
+          early_terminator_opcode == spv::Op::OpUnreachable ||
+          early_terminator_opcode == spv::Op::OpTerminateInvocation) &&
          "Invalid opcode.");
   auto void_type_id = fuzzerutil::MaybeGetVoidType(ir_context);
   if (!void_type_id) {
diff --git a/source/fuzz/transformation_wrap_early_terminator_in_function.h b/source/fuzz/transformation_wrap_early_terminator_in_function.h
index d6e5551..d824783 100644
--- a/source/fuzz/transformation_wrap_early_terminator_in_function.h
+++ b/source/fuzz/transformation_wrap_early_terminator_in_function.h
@@ -60,8 +60,8 @@
 
   protobufs::Transformation ToMessage() const override;
 
-  static opt::Function* MaybeGetWrapperFunction(opt::IRContext* ir_context,
-                                                SpvOp early_terminator_opcode);
+  static opt::Function* MaybeGetWrapperFunction(
+      opt::IRContext* ir_context, spv::Op early_terminator_opcode);
 
  private:
   protobufs::TransformationWrapEarlyTerminatorInFunction message_;
diff --git a/source/fuzz/transformation_wrap_region_in_selection.cpp b/source/fuzz/transformation_wrap_region_in_selection.cpp
index 01c98cc..a63d1ac 100644
--- a/source/fuzz/transformation_wrap_region_in_selection.cpp
+++ b/source/fuzz/transformation_wrap_region_in_selection.cpp
@@ -53,14 +53,14 @@
     TransformationContext* transformation_context) const {
   auto* new_header_block =
       ir_context->cfg()->block(message_.region_entry_block_id());
-  assert(new_header_block->terminator()->opcode() == SpvOpBranch &&
+  assert(new_header_block->terminator()->opcode() == spv::Op::OpBranch &&
          "This condition should have been checked in the IsApplicable");
 
   const auto successor_id =
       new_header_block->terminator()->GetSingleWordInOperand(0);
 
   // Change |entry_block|'s terminator to |OpBranchConditional|.
-  new_header_block->terminator()->SetOpcode(SpvOpBranchConditional);
+  new_header_block->terminator()->SetOpcode(spv::Op::OpBranchConditional);
   new_header_block->terminator()->SetInOperands(
       {{SPV_OPERAND_TYPE_ID,
         {fuzzerutil::MaybeGetBoolConstant(ir_context, *transformation_context,
@@ -70,11 +70,11 @@
 
   // Insert OpSelectionMerge before the terminator.
   new_header_block->terminator()->InsertBefore(MakeUnique<opt::Instruction>(
-      ir_context, SpvOpSelectionMerge, 0, 0,
+      ir_context, spv::Op::OpSelectionMerge, 0, 0,
       opt::Instruction::OperandList{
           {SPV_OPERAND_TYPE_ID, {message_.region_exit_block_id()}},
           {SPV_OPERAND_TYPE_SELECTION_CONTROL,
-           {SpvSelectionControlMaskNone}}}));
+           {uint32_t(spv::SelectionControlMask::MaskNone)}}}));
 
   // We've change the module so we must invalidate analyses.
   ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
@@ -130,7 +130,7 @@
   }
 
   // |header_block_candidate| must have an OpBranch terminator.
-  if (header_block_candidate->terminator()->opcode() != SpvOpBranch) {
+  if (header_block_candidate->terminator()->opcode() != spv::Op::OpBranch) {
     return false;
   }
 
diff --git a/source/fuzz/transformation_wrap_vector_synonym.cpp b/source/fuzz/transformation_wrap_vector_synonym.cpp
index 490bcd7..3b1543d 100644
--- a/source/fuzz/transformation_wrap_vector_synonym.cpp
+++ b/source/fuzz/transformation_wrap_vector_synonym.cpp
@@ -83,7 +83,7 @@
   }
 
   auto vec1_type = ir_context->get_def_use_mgr()->GetDef(vec1_type_id);
-  if (vec1_type->opcode() != SpvOpTypeVector) {
+  if (vec1_type->opcode() != spv::Op::OpTypeVector) {
     return false;
   }
 
@@ -178,18 +178,18 @@
   auto type_instruction =
       ir_context->get_def_use_mgr()->GetDef(instruction.type_id());
 
-  if ((type_instruction->opcode() != SpvOpTypeInt &&
-       type_instruction->opcode() != SpvOpTypeFloat)) {
+  if ((type_instruction->opcode() != spv::Op::OpTypeInt &&
+       type_instruction->opcode() != spv::Op::OpTypeFloat)) {
     return false;
   }
 
   switch (instruction.opcode()) {
-    case SpvOpIAdd:
-    case SpvOpISub:
-    case SpvOpIMul:
-    case SpvOpFAdd:
-    case SpvOpFSub:
-    case SpvOpFMul:
+    case spv::Op::OpIAdd:
+    case spv::Op::OpISub:
+    case spv::Op::OpIMul:
+    case spv::Op::OpFAdd:
+    case spv::Op::OpFSub:
+    case spv::Op::OpFMul:
       return true;
     default:
       return false;
diff --git a/source/fuzz/uniform_buffer_element_descriptor.cpp b/source/fuzz/uniform_buffer_element_descriptor.cpp
index 90fd85e..55e84de 100644
--- a/source/fuzz/uniform_buffer_element_descriptor.cpp
+++ b/source/fuzz/uniform_buffer_element_descriptor.cpp
@@ -49,10 +49,11 @@
 
   for (auto& inst : context->types_values()) {
     // Consider all global variables with uniform storage class.
-    if (inst.opcode() != SpvOpVariable) {
+    if (inst.opcode() != spv::Op::OpVariable) {
       continue;
     }
-    if (inst.GetSingleWordInOperand(0) != SpvStorageClassUniform) {
+    if (spv::StorageClass(inst.GetSingleWordInOperand(0)) !=
+        spv::StorageClass::Uniform) {
       continue;
     }
 
@@ -60,7 +61,7 @@
     // matching that in |uniform_buffer_element|.
     bool descriptor_set_matches = false;
     context->get_decoration_mgr()->ForEachDecoration(
-        inst.result_id(), SpvDecorationDescriptorSet,
+        inst.result_id(), uint32_t(spv::Decoration::DescriptorSet),
         [&descriptor_set_matches, &uniform_buffer_element_descriptor](
             const opt::Instruction& decoration_inst) {
           const uint32_t kDescriptorSetOperandIndex = 2;
@@ -79,7 +80,7 @@
     // in |uniform_buffer_element|.
     bool binding_matches = false;
     context->get_decoration_mgr()->ForEachDecoration(
-        inst.result_id(), SpvDecorationBinding,
+        inst.result_id(), uint32_t(spv::Decoration::Binding),
         [&binding_matches, &uniform_buffer_element_descriptor](
             const opt::Instruction& decoration_inst) {
           const uint32_t kBindingOperandIndex = 2;
diff --git a/source/instruction.h b/source/instruction.h
index 9e7dccd..2acbb57 100644
--- a/source/instruction.h
+++ b/source/instruction.h
@@ -26,7 +26,7 @@
   // Normally, both opcode and extInstType contain valid data.
   // However, when the assembler parses !<number> as the first word in
   // an instruction and opcode and extInstType are invalid.
-  SpvOp opcode;
+  spv::Op opcode;
   spv_ext_inst_type_t extInstType;
 
   // The Id of the result type, if this instruction has one.  Zero otherwise.
diff --git a/source/latest_version_spirv_header.h b/source/latest_version_spirv_header.h
index e4f28e4..f6ab5c8 100644
--- a/source/latest_version_spirv_header.h
+++ b/source/latest_version_spirv_header.h
@@ -15,6 +15,6 @@
 #ifndef SOURCE_LATEST_VERSION_SPIRV_HEADER_H_
 #define SOURCE_LATEST_VERSION_SPIRV_HEADER_H_
 
-#include "spirv/unified1/spirv.h"
+#include "spirv/unified1/spirv.hpp11"
 
 #endif  // SOURCE_LATEST_VERSION_SPIRV_HEADER_H_
diff --git a/source/link/linker.cpp b/source/link/linker.cpp
index 3b388cc..e50391a 100644
--- a/source/link/linker.cpp
+++ b/source/link/linker.cpp
@@ -57,12 +57,12 @@
 
 // Stores various information about an imported or exported symbol.
 struct LinkageSymbolInfo {
-  SpvId id;          // ID of the symbol
-  SpvId type_id;     // ID of the type of the symbol
+  spv::Id id;        // ID of the symbol
+  spv::Id type_id;   // ID of the type of the symbol
   std::string name;  // unique name defining the symbol and used for matching
                      // imports and exports together
-  std::vector<SpvId> parameter_ids;  // ID of the parameters of the symbol, if
-                                     // it is a function
+  std::vector<spv::Id> parameter_ids;  // ID of the parameters of the symbol, if
+                                       // it is a function
 };
 struct LinkageEntry {
   LinkageSymbolInfo imported_symbol;
@@ -226,7 +226,7 @@
              << " (input module " << (i + 1) << ").";
   }
 
-  header->magic_number = SpvMagicNumber;
+  header->magic_number = spv::MagicNumber;
   header->version = linked_version;
   header->generator = SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS_LINKER, 0);
   header->bound = max_id_bound;
@@ -367,7 +367,7 @@
     std::vector<uint32_t> processed_words =
         spvtools::utils::MakeVector(processed_string);
     linked_module->AddDebug3Inst(std::unique_ptr<Instruction>(
-        new Instruction(linked_context, SpvOpModuleProcessed, 0u, 0u,
+        new Instruction(linked_context, spv::Op::OpModuleProcessed, 0u, 0u,
                         {{SPV_OPERAND_TYPE_LITERAL_STRING, processed_words}})));
   }
 
@@ -377,7 +377,7 @@
           std::unique_ptr<Instruction>(inst.Clone(linked_context)));
 
   // TODO(pierremoreau): Since the modules have not been validate, should we
-  //                     expect SpvStorageClassFunction variables outside
+  //                     expect spv::StorageClass::Function variables outside
   //                     functions?
   for (const auto& module : input_modules) {
     for (const auto& inst : module->types_values()) {
@@ -414,16 +414,18 @@
 
   // Figure out the imports and exports
   for (const auto& decoration : linked_context.annotations()) {
-    if (decoration.opcode() != SpvOpDecorate ||
-        decoration.GetSingleWordInOperand(1u) != SpvDecorationLinkageAttributes)
+    if (decoration.opcode() != spv::Op::OpDecorate ||
+        spv::Decoration(decoration.GetSingleWordInOperand(1u)) !=
+            spv::Decoration::LinkageAttributes)
       continue;
 
-    const SpvId id = decoration.GetSingleWordInOperand(0u);
+    const spv::Id id = decoration.GetSingleWordInOperand(0u);
     // Ignore if the targeted symbol is a built-in
     bool is_built_in = false;
     for (const auto& id_decoration :
          decoration_manager.GetDecorationsFor(id, false)) {
-      if (id_decoration->GetSingleWordInOperand(1u) == SpvDecorationBuiltIn) {
+      if (spv::Decoration(id_decoration->GetSingleWordInOperand(1u)) ==
+          spv::Decoration::BuiltIn) {
         is_built_in = true;
         break;
       }
@@ -447,9 +449,9 @@
       return DiagnosticStream(position, consumer, "", SPV_ERROR_INVALID_BINARY)
              << "ID " << id << " is never defined:\n";
 
-    if (def_inst->opcode() == SpvOpVariable) {
+    if (def_inst->opcode() == spv::Op::OpVariable) {
       symbol_info.type_id = def_inst->type_id();
-    } else if (def_inst->opcode() == SpvOpFunction) {
+    } else if (def_inst->opcode() == spv::Op::OpFunction) {
       symbol_info.type_id = def_inst->GetSingleWordInOperand(1u);
 
       // range-based for loop calls begin()/end(), but never cbegin()/cend(),
@@ -467,9 +469,9 @@
              << " LinkageAttributes; " << id << " is neither of them.\n";
     }
 
-    if (type == SpvLinkageTypeImport)
+    if (spv::LinkageType(type) == spv::LinkageType::Import)
       imports.push_back(symbol_info);
-    else if (type == SpvLinkageTypeExport)
+    else if (spv::LinkageType(type) == spv::LinkageType::Export)
       exports[symbol_info.name].push_back(symbol_info);
   }
 
@@ -585,7 +587,7 @@
   // TODO(pierremoreau): This will not work if the decoration is applied
   //                     through a group, but the linker does not support that
   //                     either.
-  std::unordered_set<SpvId> imports;
+  std::unordered_set<spv::Id> imports;
   if (options.GetAllowPartialLinkage()) {
     imports.reserve(linkings_to_do.size());
     for (const auto& linking_entry : linkings_to_do)
@@ -601,9 +603,11 @@
     // * if we do not allow partial linkage, remove all import annotations;
     // * otherwise, remove the annotation only if there was a corresponding
     //   export.
-    if (inst->opcode() == SpvOpDecorate &&
-        inst->GetSingleWordOperand(1u) == SpvDecorationLinkageAttributes &&
-        inst->GetSingleWordOperand(3u) == SpvLinkageTypeImport &&
+    if (inst->opcode() == spv::Op::OpDecorate &&
+        spv::Decoration(inst->GetSingleWordOperand(1u)) ==
+            spv::Decoration::LinkageAttributes &&
+        spv::LinkageType(inst->GetSingleWordOperand(3u)) ==
+            spv::LinkageType::Import &&
         (!options.GetAllowPartialLinkage() ||
          imports.find(inst->GetSingleWordOperand(0u)) != imports.end())) {
       linked_context->KillInst(&*inst);
@@ -616,9 +620,11 @@
     for (auto inst = next; inst != linked_context->annotation_end();
          inst = next) {
       ++next;
-      if (inst->opcode() == SpvOpDecorate &&
-          inst->GetSingleWordOperand(1u) == SpvDecorationLinkageAttributes &&
-          inst->GetSingleWordOperand(3u) == SpvLinkageTypeExport) {
+      if (inst->opcode() == spv::Op::OpDecorate &&
+          spv::Decoration(inst->GetSingleWordOperand(1u)) ==
+              spv::Decoration::LinkageAttributes &&
+          spv::LinkageType(inst->GetSingleWordOperand(3u)) ==
+              spv::LinkageType::Export) {
         linked_context->KillInst(&*inst);
       }
     }
@@ -628,10 +634,11 @@
   // not allowed
   if (!options.GetCreateLibrary() && !options.GetAllowPartialLinkage()) {
     for (auto& inst : linked_context->capabilities())
-      if (inst.GetSingleWordInOperand(0u) == SpvCapabilityLinkage) {
+      if (spv::Capability(inst.GetSingleWordInOperand(0u)) ==
+          spv::Capability::Linkage) {
         linked_context->KillInst(&inst);
         // The RemoveDuplicatesPass did remove duplicated capabilities, so we
-        // now there aren’t more SpvCapabilityLinkage further down.
+        // now there aren’t more spv::Capability::Linkage further down.
         break;
       }
   }
@@ -671,7 +678,7 @@
 
   size_t num_global_values = 0u;
   for (const auto& inst : linked_context.module()->types_values()) {
-    num_global_values += inst.opcode() == SpvOpVariable;
+    num_global_values += inst.opcode() == spv::Op::OpVariable;
   }
   if (num_global_values >= SPV_LIMIT_GLOBAL_VARIABLES_MAX)
     DiagnosticStream(position, consumer, "", SPV_WARNING)
diff --git a/source/lint/divergence_analysis.cpp b/source/lint/divergence_analysis.cpp
index b5a72b4..fe32e1a 100644
--- a/source/lint/divergence_analysis.cpp
+++ b/source/lint/divergence_analysis.cpp
@@ -19,7 +19,6 @@
 #include "source/opt/dataflow.h"
 #include "source/opt/function.h"
 #include "source/opt/instruction.h"
-#include "spirv/unified1/spirv.h"
 
 namespace spvtools {
 namespace lint {
@@ -32,7 +31,7 @@
   uint32_t block_id;
   if (inst->IsBlockTerminator()) {
     block_id = context().get_instr_block(inst)->id();
-  } else if (inst->opcode() == SpvOpLabel) {
+  } else if (inst->opcode() == spv::Op::OpLabel) {
     block_id = inst->result_id();
     opt::BasicBlock* bb = context().cfg()->block(block_id);
     // Only enqueue phi instructions, as other uses don't affect divergence.
@@ -54,7 +53,7 @@
 
 opt::DataFlowAnalysis::VisitResult DivergenceAnalysis::Visit(
     opt::Instruction* inst) {
-  if (inst->opcode() == SpvOpLabel) {
+  if (inst->opcode() == spv::Op::OpLabel) {
     return VisitBlock(inst->result_id());
   } else {
     return VisitInstruction(inst);
@@ -128,12 +127,12 @@
   // Device/QueueFamily could satisfy fully uniform.
   uint32_t id = inst->result_id();
   // Handle divergence roots.
-  if (inst->opcode() == SpvOpFunctionParameter) {
+  if (inst->opcode() == spv::Op::OpFunctionParameter) {
     divergence_source_[id] = 0;
     return divergence_[id] = DivergenceLevel::kDivergent;
   } else if (inst->IsLoad()) {
     spvtools::opt::Instruction* var = inst->GetBaseAddress();
-    if (var->opcode() != SpvOpVariable) {
+    if (var->opcode() != spv::Op::OpVariable) {
       // Assume divergent.
       divergence_source_[id] = 0;
       return DivergenceLevel::kDivergent;
@@ -166,29 +165,30 @@
   uint32_t def_id = var->result_id();
   DivergenceLevel ret;
   switch (type->storage_class()) {
-    case SpvStorageClassFunction:
-    case SpvStorageClassGeneric:
-    case SpvStorageClassAtomicCounter:
-    case SpvStorageClassStorageBuffer:
-    case SpvStorageClassPhysicalStorageBuffer:
-    case SpvStorageClassOutput:
-    case SpvStorageClassWorkgroup:
-    case SpvStorageClassImage:  // Image atomics probably aren't uniform.
-    case SpvStorageClassPrivate:
+    case spv::StorageClass::Function:
+    case spv::StorageClass::Generic:
+    case spv::StorageClass::AtomicCounter:
+    case spv::StorageClass::StorageBuffer:
+    case spv::StorageClass::PhysicalStorageBuffer:
+    case spv::StorageClass::Output:
+    case spv::StorageClass::Workgroup:
+    case spv::StorageClass::Image:  // Image atomics probably aren't uniform.
+    case spv::StorageClass::Private:
       ret = DivergenceLevel::kDivergent;
       break;
-    case SpvStorageClassInput:
+    case spv::StorageClass::Input:
       ret = DivergenceLevel::kDivergent;
       // If this variable has a Flat decoration, it is partially uniform.
       // TODO(kuhar): Track access chain indices and also consider Flat members
       // of a structure.
       context().get_decoration_mgr()->WhileEachDecoration(
-          def_id, SpvDecorationFlat, [&ret](const opt::Instruction&) {
+          def_id, static_cast<uint32_t>(spv::Decoration::Flat),
+          [&ret](const opt::Instruction&) {
             ret = DivergenceLevel::kPartiallyUniform;
             return false;
           });
       break;
-    case SpvStorageClassUniformConstant:
+    case spv::StorageClass::UniformConstant:
       // May be a storage image which is also written to; mark those as
       // divergent.
       if (!var->IsVulkanStorageImage() || var->IsReadOnlyPointer()) {
@@ -197,9 +197,10 @@
         ret = DivergenceLevel::kDivergent;
       }
       break;
-    case SpvStorageClassUniform:
-    case SpvStorageClassPushConstant:
-    case SpvStorageClassCrossWorkgroup:  // Not for shaders; default uniform.
+    case spv::StorageClass::Uniform:
+    case spv::StorageClass::PushConstant:
+    case spv::StorageClass::CrossWorkgroup:  // Not for shaders; default
+                                             // uniform.
     default:
       ret = DivergenceLevel::kUniform;
       break;
@@ -216,7 +217,7 @@
       function->entry().get(), [this](const opt::BasicBlock* bb) {
         uint32_t id = bb->id();
         if (bb->terminator() == nullptr ||
-            bb->terminator()->opcode() != SpvOpBranch) {
+            bb->terminator()->opcode() != spv::Op::OpBranch) {
           follow_unconditional_branches_[id] = id;
         } else {
           uint32_t target_id = bb->terminator()->GetSingleWordInOperand(0);
diff --git a/source/lint/lint_divergent_derivatives.cpp b/source/lint/lint_divergent_derivatives.cpp
index 512847b..82d5ac6 100644
--- a/source/lint/lint_divergent_derivatives.cpp
+++ b/source/lint/lint_divergent_derivatives.cpp
@@ -27,7 +27,6 @@
 #include "source/opt/instruction.h"
 #include "source/opt/ir_context.h"
 #include "spirv-tools/libspirv.h"
-#include "spirv/unified1/spirv.h"
 
 namespace spvtools {
 namespace lint {
@@ -43,7 +42,7 @@
     ss << id;
   } else {
     opt::Instruction* inst_name = names.begin()->second;
-    if (inst_name->opcode() == SpvOpName) {
+    if (inst_name->opcode() == spv::Op::OpName) {
       ss << names.begin()->second->GetInOperand(0).AsString();
       ss << "[" << id << "]";
     } else {
@@ -54,26 +53,26 @@
 }
 
 bool InstructionHasDerivative(const opt::Instruction& inst) {
-  static const SpvOp derivative_opcodes[] = {
+  static const spv::Op derivative_opcodes[] = {
       // Implicit derivatives.
-      SpvOpImageSampleImplicitLod,
-      SpvOpImageSampleDrefImplicitLod,
-      SpvOpImageSampleProjImplicitLod,
-      SpvOpImageSampleProjDrefImplicitLod,
-      SpvOpImageSparseSampleImplicitLod,
-      SpvOpImageSparseSampleDrefImplicitLod,
-      SpvOpImageSparseSampleProjImplicitLod,
-      SpvOpImageSparseSampleProjDrefImplicitLod,
+      spv::Op::OpImageSampleImplicitLod,
+      spv::Op::OpImageSampleDrefImplicitLod,
+      spv::Op::OpImageSampleProjImplicitLod,
+      spv::Op::OpImageSampleProjDrefImplicitLod,
+      spv::Op::OpImageSparseSampleImplicitLod,
+      spv::Op::OpImageSparseSampleDrefImplicitLod,
+      spv::Op::OpImageSparseSampleProjImplicitLod,
+      spv::Op::OpImageSparseSampleProjDrefImplicitLod,
       // Explicit derivatives.
-      SpvOpDPdx,
-      SpvOpDPdy,
-      SpvOpFwidth,
-      SpvOpDPdxFine,
-      SpvOpDPdyFine,
-      SpvOpFwidthFine,
-      SpvOpDPdxCoarse,
-      SpvOpDPdyCoarse,
-      SpvOpFwidthCoarse,
+      spv::Op::OpDPdx,
+      spv::Op::OpDPdy,
+      spv::Op::OpFwidth,
+      spv::Op::OpDPdxFine,
+      spv::Op::OpDPdyFine,
+      spv::Op::OpFwidthFine,
+      spv::Op::OpDPdxCoarse,
+      spv::Op::OpDPdyCoarse,
+      spv::Op::OpFwidthCoarse,
   };
   return std::find(std::begin(derivative_opcodes), std::end(derivative_opcodes),
                    inst.opcode()) != std::end(derivative_opcodes);
@@ -97,13 +96,14 @@
   opt::analysis::DefUseManager* def_use = context->get_def_use_mgr();
   opt::CFG* cfg = context->cfg();
   while (id != 0) {
-    bool is_block = def_use->GetDef(id)->opcode() == SpvOpLabel;
+    bool is_block = def_use->GetDef(id)->opcode() == spv::Op::OpLabel;
     if (is_block) {
       Warn(context, nullptr)
           << "block " << GetFriendlyName(context, id) << " is divergent";
       uint32_t source = div.GetDivergenceSource(id);
       // Skip intermediate blocks.
-      while (source != 0 && def_use->GetDef(source)->opcode() == SpvOpLabel) {
+      while (source != 0 &&
+             def_use->GetDef(source)->opcode() == spv::Op::OpLabel) {
         id = source;
         source = div.GetDivergenceSource(id);
       }
@@ -122,7 +122,7 @@
       opt::Instruction* source_def =
           source == 0 ? nullptr : def_use->GetDef(source);
       // First print data -> data dependencies.
-      while (source != 0 && source_def->opcode() != SpvOpLabel) {
+      while (source != 0 && source_def->opcode() != spv::Op::OpLabel) {
         Warn(context, def_use->GetDef(id))
             << "because " << GetFriendlyName(context, id) << " uses value "
             << GetFriendlyName(context, source)
diff --git a/source/lint/linter.cpp b/source/lint/linter.cpp
index e4ed04e..7480676 100644
--- a/source/lint/linter.cpp
+++ b/source/lint/linter.cpp
@@ -19,7 +19,6 @@
 #include "source/opt/ir_context.h"
 #include "spirv-tools/libspirv.h"
 #include "spirv-tools/libspirv.hpp"
-#include "spirv/unified1/spirv.h"
 
 namespace spvtools {
 
diff --git a/source/name_mapper.cpp b/source/name_mapper.cpp
index 3b31d33..b2d0f44 100644
--- a/source/name_mapper.cpp
+++ b/source/name_mapper.cpp
@@ -100,18 +100,18 @@
 void FriendlyNameMapper::SaveBuiltInName(uint32_t target_id,
                                          uint32_t built_in) {
 #define GLCASE(name)                  \
-  case SpvBuiltIn##name:              \
+  case spv::BuiltIn::name:            \
     SaveName(target_id, "gl_" #name); \
     return;
 #define GLCASE2(name, suggested)           \
-  case SpvBuiltIn##name:                   \
+  case spv::BuiltIn::name:                 \
     SaveName(target_id, "gl_" #suggested); \
     return;
 #define CASE(name)              \
-  case SpvBuiltIn##name:        \
+  case spv::BuiltIn::name:      \
     SaveName(target_id, #name); \
     return;
-  switch (built_in) {
+  switch (spv::BuiltIn(built_in)) {
     GLCASE(Position)
     GLCASE(PointSize)
     GLCASE(ClipDistance)
@@ -170,28 +170,28 @@
 spv_result_t FriendlyNameMapper::ParseInstruction(
     const spv_parsed_instruction_t& inst) {
   const auto result_id = inst.result_id;
-  switch (inst.opcode) {
-    case SpvOpName:
+  switch (spv::Op(inst.opcode)) {
+    case spv::Op::OpName:
       SaveName(inst.words[1], spvDecodeLiteralStringOperand(inst, 1));
       break;
-    case SpvOpDecorate:
+    case spv::Op::OpDecorate:
       // Decorations come after OpName.  So OpName will take precedence over
       // decorations.
       //
       // In theory, we should also handle OpGroupDecorate.  But that's unlikely
       // to occur.
-      if (inst.words[2] == SpvDecorationBuiltIn) {
+      if (spv::Decoration(inst.words[2]) == spv::Decoration::BuiltIn) {
         assert(inst.num_words > 3);
         SaveBuiltInName(inst.words[1], inst.words[3]);
       }
       break;
-    case SpvOpTypeVoid:
+    case spv::Op::OpTypeVoid:
       SaveName(result_id, "void");
       break;
-    case SpvOpTypeBool:
+    case spv::Op::OpTypeBool:
       SaveName(result_id, "bool");
       break;
-    case SpvOpTypeInt: {
+    case spv::Op::OpTypeInt: {
       std::string signedness;
       std::string root;
       const auto bit_width = inst.words[2];
@@ -216,7 +216,7 @@
       if (0 == inst.words[3]) signedness = "u";
       SaveName(result_id, signedness + root);
     } break;
-    case SpvOpTypeFloat: {
+    case spv::Op::OpTypeFloat: {
       const auto bit_width = inst.words[2];
       switch (bit_width) {
         case 16:
@@ -233,68 +233,68 @@
           break;
       }
     } break;
-    case SpvOpTypeVector:
+    case spv::Op::OpTypeVector:
       SaveName(result_id, std::string("v") + to_string(inst.words[3]) +
                               NameForId(inst.words[2]));
       break;
-    case SpvOpTypeMatrix:
+    case spv::Op::OpTypeMatrix:
       SaveName(result_id, std::string("mat") + to_string(inst.words[3]) +
                               NameForId(inst.words[2]));
       break;
-    case SpvOpTypeArray:
+    case spv::Op::OpTypeArray:
       SaveName(result_id, std::string("_arr_") + NameForId(inst.words[2]) +
                               "_" + NameForId(inst.words[3]));
       break;
-    case SpvOpTypeRuntimeArray:
+    case spv::Op::OpTypeRuntimeArray:
       SaveName(result_id,
                std::string("_runtimearr_") + NameForId(inst.words[2]));
       break;
-    case SpvOpTypePointer:
+    case spv::Op::OpTypePointer:
       SaveName(result_id, std::string("_ptr_") +
                               NameForEnumOperand(SPV_OPERAND_TYPE_STORAGE_CLASS,
                                                  inst.words[2]) +
                               "_" + NameForId(inst.words[3]));
       break;
-    case SpvOpTypePipe:
+    case spv::Op::OpTypePipe:
       SaveName(result_id,
                std::string("Pipe") +
                    NameForEnumOperand(SPV_OPERAND_TYPE_ACCESS_QUALIFIER,
                                       inst.words[2]));
       break;
-    case SpvOpTypeEvent:
+    case spv::Op::OpTypeEvent:
       SaveName(result_id, "Event");
       break;
-    case SpvOpTypeDeviceEvent:
+    case spv::Op::OpTypeDeviceEvent:
       SaveName(result_id, "DeviceEvent");
       break;
-    case SpvOpTypeReserveId:
+    case spv::Op::OpTypeReserveId:
       SaveName(result_id, "ReserveId");
       break;
-    case SpvOpTypeQueue:
+    case spv::Op::OpTypeQueue:
       SaveName(result_id, "Queue");
       break;
-    case SpvOpTypeOpaque:
+    case spv::Op::OpTypeOpaque:
       SaveName(result_id, std::string("Opaque_") +
                               Sanitize(spvDecodeLiteralStringOperand(inst, 1)));
       break;
-    case SpvOpTypePipeStorage:
+    case spv::Op::OpTypePipeStorage:
       SaveName(result_id, "PipeStorage");
       break;
-    case SpvOpTypeNamedBarrier:
+    case spv::Op::OpTypeNamedBarrier:
       SaveName(result_id, "NamedBarrier");
       break;
-    case SpvOpTypeStruct:
+    case spv::Op::OpTypeStruct:
       // Structs are mapped rather simplisitically. Just indicate that they
       // are a struct and then give the raw Id number.
       SaveName(result_id, std::string("_struct_") + to_string(result_id));
       break;
-    case SpvOpConstantTrue:
+    case spv::Op::OpConstantTrue:
       SaveName(result_id, "true");
       break;
-    case SpvOpConstantFalse:
+    case spv::Op::OpConstantFalse:
       SaveName(result_id, "false");
       break;
-    case SpvOpConstant: {
+    case spv::Op::OpConstant: {
       std::ostringstream value;
       EmitNumericLiteral(&value, inst, inst.operands[2]);
       auto value_str = value.str();
diff --git a/source/opcode.cpp b/source/opcode.cpp
index 3f92729..c5006af 100644
--- a/source/opcode.cpp
+++ b/source/opcode.cpp
@@ -64,7 +64,7 @@
   return "Unknown";
 }
 
-uint32_t spvOpcodeMake(uint16_t wordCount, SpvOp opcode) {
+uint32_t spvOpcodeMake(uint16_t wordCount, spv::Op opcode) {
   return ((uint32_t)opcode) | (((uint32_t)wordCount) << 16);
 }
 
@@ -125,7 +125,7 @@
 
 spv_result_t spvOpcodeTableValueLookup(spv_target_env env,
                                        const spv_opcode_table table,
-                                       const SpvOp opcode,
+                                       const spv::Op opcode,
                                        spv_opcode_desc* pEntry) {
   if (!table) return SPV_ERROR_INVALID_TABLE;
   if (!pEntry) return SPV_ERROR_INVALID_POINTER;
@@ -166,7 +166,7 @@
   return SPV_ERROR_INVALID_LOOKUP;
 }
 
-void spvInstructionCopy(const uint32_t* words, const SpvOp opcode,
+void spvInstructionCopy(const uint32_t* words, const spv::Op opcode,
                         const uint16_t wordCount, const spv_endianness_t endian,
                         spv_instruction_t* pInst) {
   pInst->opcode = opcode;
@@ -177,7 +177,7 @@
       uint16_t thisWordCount;
       uint16_t thisOpcode;
       spvOpcodeSplit(pInst->words[wordIndex], &thisWordCount, &thisOpcode);
-      assert(opcode == static_cast<SpvOp>(thisOpcode) &&
+      assert(opcode == static_cast<spv::Op>(thisOpcode) &&
              wordCount == thisWordCount && "Endianness failed!");
     }
   }
@@ -186,7 +186,7 @@
 const char* spvOpcodeString(const uint32_t opcode) {
   const auto beg = kOpcodeTableEntries;
   const auto end = kOpcodeTableEntries + ARRAY_SIZE(kOpcodeTableEntries);
-  spv_opcode_desc_t needle = {"",    static_cast<SpvOp>(opcode),
+  spv_opcode_desc_t needle = {"",    static_cast<spv::Op>(opcode),
                               0,     nullptr,
                               0,     {},
                               false, false,
@@ -196,7 +196,7 @@
     return lhs.opcode < rhs.opcode;
   };
   auto it = std::lower_bound(beg, end, needle, comp);
-  if (it != end && it->opcode == opcode) {
+  if (it != end && it->opcode == spv::Op(opcode)) {
     return it->name;
   }
 
@@ -204,140 +204,144 @@
   return "unknown";
 }
 
-int32_t spvOpcodeIsScalarType(const SpvOp opcode) {
+const char* spvOpcodeString(const spv::Op opcode) {
+  return spvOpcodeString(static_cast<uint32_t>(opcode));
+}
+
+int32_t spvOpcodeIsScalarType(const spv::Op opcode) {
   switch (opcode) {
-    case SpvOpTypeInt:
-    case SpvOpTypeFloat:
-    case SpvOpTypeBool:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeFloat:
+    case spv::Op::OpTypeBool:
       return true;
     default:
       return false;
   }
 }
 
-int32_t spvOpcodeIsSpecConstant(const SpvOp opcode) {
+int32_t spvOpcodeIsSpecConstant(const spv::Op opcode) {
   switch (opcode) {
-    case SpvOpSpecConstantTrue:
-    case SpvOpSpecConstantFalse:
-    case SpvOpSpecConstant:
-    case SpvOpSpecConstantComposite:
-    case SpvOpSpecConstantOp:
+    case spv::Op::OpSpecConstantTrue:
+    case spv::Op::OpSpecConstantFalse:
+    case spv::Op::OpSpecConstant:
+    case spv::Op::OpSpecConstantComposite:
+    case spv::Op::OpSpecConstantOp:
       return true;
     default:
       return false;
   }
 }
 
-int32_t spvOpcodeIsConstant(const SpvOp opcode) {
+int32_t spvOpcodeIsConstant(const spv::Op opcode) {
   switch (opcode) {
-    case SpvOpConstantTrue:
-    case SpvOpConstantFalse:
-    case SpvOpConstant:
-    case SpvOpConstantComposite:
-    case SpvOpConstantSampler:
-    case SpvOpConstantNull:
-    case SpvOpSpecConstantTrue:
-    case SpvOpSpecConstantFalse:
-    case SpvOpSpecConstant:
-    case SpvOpSpecConstantComposite:
-    case SpvOpSpecConstantOp:
+    case spv::Op::OpConstantTrue:
+    case spv::Op::OpConstantFalse:
+    case spv::Op::OpConstant:
+    case spv::Op::OpConstantComposite:
+    case spv::Op::OpConstantSampler:
+    case spv::Op::OpConstantNull:
+    case spv::Op::OpSpecConstantTrue:
+    case spv::Op::OpSpecConstantFalse:
+    case spv::Op::OpSpecConstant:
+    case spv::Op::OpSpecConstantComposite:
+    case spv::Op::OpSpecConstantOp:
       return true;
     default:
       return false;
   }
 }
 
-bool spvOpcodeIsConstantOrUndef(const SpvOp opcode) {
-  return opcode == SpvOpUndef || spvOpcodeIsConstant(opcode);
+bool spvOpcodeIsConstantOrUndef(const spv::Op opcode) {
+  return opcode == spv::Op::OpUndef || spvOpcodeIsConstant(opcode);
 }
 
-bool spvOpcodeIsScalarSpecConstant(const SpvOp opcode) {
+bool spvOpcodeIsScalarSpecConstant(const spv::Op opcode) {
   switch (opcode) {
-    case SpvOpSpecConstantTrue:
-    case SpvOpSpecConstantFalse:
-    case SpvOpSpecConstant:
+    case spv::Op::OpSpecConstantTrue:
+    case spv::Op::OpSpecConstantFalse:
+    case spv::Op::OpSpecConstant:
       return true;
     default:
       return false;
   }
 }
 
-int32_t spvOpcodeIsComposite(const SpvOp opcode) {
+int32_t spvOpcodeIsComposite(const spv::Op opcode) {
   switch (opcode) {
-    case SpvOpTypeVector:
-    case SpvOpTypeMatrix:
-    case SpvOpTypeArray:
-    case SpvOpTypeStruct:
-    case SpvOpTypeCooperativeMatrixNV:
+    case spv::Op::OpTypeVector:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeArray:
+    case spv::Op::OpTypeStruct:
+    case spv::Op::OpTypeCooperativeMatrixNV:
       return true;
     default:
       return false;
   }
 }
 
-bool spvOpcodeReturnsLogicalVariablePointer(const SpvOp opcode) {
+bool spvOpcodeReturnsLogicalVariablePointer(const spv::Op opcode) {
   switch (opcode) {
-    case SpvOpVariable:
-    case SpvOpAccessChain:
-    case SpvOpInBoundsAccessChain:
-    case SpvOpFunctionParameter:
-    case SpvOpImageTexelPointer:
-    case SpvOpCopyObject:
-    case SpvOpSelect:
-    case SpvOpPhi:
-    case SpvOpFunctionCall:
-    case SpvOpPtrAccessChain:
-    case SpvOpLoad:
-    case SpvOpConstantNull:
+    case spv::Op::OpVariable:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
+    case spv::Op::OpFunctionParameter:
+    case spv::Op::OpImageTexelPointer:
+    case spv::Op::OpCopyObject:
+    case spv::Op::OpSelect:
+    case spv::Op::OpPhi:
+    case spv::Op::OpFunctionCall:
+    case spv::Op::OpPtrAccessChain:
+    case spv::Op::OpLoad:
+    case spv::Op::OpConstantNull:
       return true;
     default:
       return false;
   }
 }
 
-int32_t spvOpcodeReturnsLogicalPointer(const SpvOp opcode) {
+int32_t spvOpcodeReturnsLogicalPointer(const spv::Op opcode) {
   switch (opcode) {
-    case SpvOpVariable:
-    case SpvOpAccessChain:
-    case SpvOpInBoundsAccessChain:
-    case SpvOpFunctionParameter:
-    case SpvOpImageTexelPointer:
-    case SpvOpCopyObject:
+    case spv::Op::OpVariable:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
+    case spv::Op::OpFunctionParameter:
+    case spv::Op::OpImageTexelPointer:
+    case spv::Op::OpCopyObject:
       return true;
     default:
       return false;
   }
 }
 
-int32_t spvOpcodeGeneratesType(SpvOp op) {
+int32_t spvOpcodeGeneratesType(spv::Op op) {
   switch (op) {
-    case SpvOpTypeVoid:
-    case SpvOpTypeBool:
-    case SpvOpTypeInt:
-    case SpvOpTypeFloat:
-    case SpvOpTypeVector:
-    case SpvOpTypeMatrix:
-    case SpvOpTypeImage:
-    case SpvOpTypeSampler:
-    case SpvOpTypeSampledImage:
-    case SpvOpTypeArray:
-    case SpvOpTypeRuntimeArray:
-    case SpvOpTypeStruct:
-    case SpvOpTypeOpaque:
-    case SpvOpTypePointer:
-    case SpvOpTypeFunction:
-    case SpvOpTypeEvent:
-    case SpvOpTypeDeviceEvent:
-    case SpvOpTypeReserveId:
-    case SpvOpTypeQueue:
-    case SpvOpTypePipe:
-    case SpvOpTypePipeStorage:
-    case SpvOpTypeNamedBarrier:
-    case SpvOpTypeAccelerationStructureNV:
-    case SpvOpTypeCooperativeMatrixNV:
-    // case SpvOpTypeAccelerationStructureKHR: covered by
-    // SpvOpTypeAccelerationStructureNV
-    case SpvOpTypeRayQueryKHR:
+    case spv::Op::OpTypeVoid:
+    case spv::Op::OpTypeBool:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeFloat:
+    case spv::Op::OpTypeVector:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeImage:
+    case spv::Op::OpTypeSampler:
+    case spv::Op::OpTypeSampledImage:
+    case spv::Op::OpTypeArray:
+    case spv::Op::OpTypeRuntimeArray:
+    case spv::Op::OpTypeStruct:
+    case spv::Op::OpTypeOpaque:
+    case spv::Op::OpTypePointer:
+    case spv::Op::OpTypeFunction:
+    case spv::Op::OpTypeEvent:
+    case spv::Op::OpTypeDeviceEvent:
+    case spv::Op::OpTypeReserveId:
+    case spv::Op::OpTypeQueue:
+    case spv::Op::OpTypePipe:
+    case spv::Op::OpTypePipeStorage:
+    case spv::Op::OpTypeNamedBarrier:
+    case spv::Op::OpTypeAccelerationStructureNV:
+    case spv::Op::OpTypeCooperativeMatrixNV:
+    // case spv::Op::OpTypeAccelerationStructureKHR: covered by
+    // spv::Op::OpTypeAccelerationStructureNV
+    case spv::Op::OpTypeRayQueryKHR:
       return true;
     default:
       // In particular, OpTypeForwardPointer does not generate a type,
@@ -348,15 +352,15 @@
   return 0;
 }
 
-bool spvOpcodeIsDecoration(const SpvOp opcode) {
+bool spvOpcodeIsDecoration(const spv::Op opcode) {
   switch (opcode) {
-    case SpvOpDecorate:
-    case SpvOpDecorateId:
-    case SpvOpMemberDecorate:
-    case SpvOpGroupDecorate:
-    case SpvOpGroupMemberDecorate:
-    case SpvOpDecorateStringGOOGLE:
-    case SpvOpMemberDecorateStringGOOGLE:
+    case spv::Op::OpDecorate:
+    case spv::Op::OpDecorateId:
+    case spv::Op::OpMemberDecorate:
+    case spv::Op::OpGroupDecorate:
+    case spv::Op::OpGroupMemberDecorate:
+    case spv::Op::OpDecorateStringGOOGLE:
+    case spv::Op::OpMemberDecorateStringGOOGLE:
       return true;
     default:
       break;
@@ -364,402 +368,403 @@
   return false;
 }
 
-bool spvOpcodeIsLoad(const SpvOp opcode) {
+bool spvOpcodeIsLoad(const spv::Op opcode) {
   switch (opcode) {
-    case SpvOpLoad:
-    case SpvOpImageSampleExplicitLod:
-    case SpvOpImageSampleImplicitLod:
-    case SpvOpImageSampleDrefImplicitLod:
-    case SpvOpImageSampleDrefExplicitLod:
-    case SpvOpImageSampleProjImplicitLod:
-    case SpvOpImageSampleProjExplicitLod:
-    case SpvOpImageSampleProjDrefImplicitLod:
-    case SpvOpImageSampleProjDrefExplicitLod:
-    case SpvOpImageFetch:
-    case SpvOpImageGather:
-    case SpvOpImageDrefGather:
-    case SpvOpImageRead:
-    case SpvOpImageSparseSampleImplicitLod:
-    case SpvOpImageSparseSampleExplicitLod:
-    case SpvOpImageSparseSampleDrefExplicitLod:
-    case SpvOpImageSparseSampleDrefImplicitLod:
-    case SpvOpImageSparseFetch:
-    case SpvOpImageSparseGather:
-    case SpvOpImageSparseDrefGather:
-    case SpvOpImageSparseRead:
+    case spv::Op::OpLoad:
+    case spv::Op::OpImageSampleExplicitLod:
+    case spv::Op::OpImageSampleImplicitLod:
+    case spv::Op::OpImageSampleDrefImplicitLod:
+    case spv::Op::OpImageSampleDrefExplicitLod:
+    case spv::Op::OpImageSampleProjImplicitLod:
+    case spv::Op::OpImageSampleProjExplicitLod:
+    case spv::Op::OpImageSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSampleProjDrefExplicitLod:
+    case spv::Op::OpImageFetch:
+    case spv::Op::OpImageGather:
+    case spv::Op::OpImageDrefGather:
+    case spv::Op::OpImageRead:
+    case spv::Op::OpImageSparseSampleImplicitLod:
+    case spv::Op::OpImageSparseSampleExplicitLod:
+    case spv::Op::OpImageSparseSampleDrefExplicitLod:
+    case spv::Op::OpImageSparseSampleDrefImplicitLod:
+    case spv::Op::OpImageSparseFetch:
+    case spv::Op::OpImageSparseGather:
+    case spv::Op::OpImageSparseDrefGather:
+    case spv::Op::OpImageSparseRead:
       return true;
     default:
       return false;
   }
 }
 
-bool spvOpcodeIsBranch(SpvOp opcode) {
+bool spvOpcodeIsBranch(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpBranch:
-    case SpvOpBranchConditional:
-    case SpvOpSwitch:
+    case spv::Op::OpBranch:
+    case spv::Op::OpBranchConditional:
+    case spv::Op::OpSwitch:
       return true;
     default:
       return false;
   }
 }
 
-bool spvOpcodeIsAtomicWithLoad(const SpvOp opcode) {
+bool spvOpcodeIsAtomicWithLoad(const spv::Op opcode) {
   switch (opcode) {
-    case SpvOpAtomicLoad:
-    case SpvOpAtomicExchange:
-    case SpvOpAtomicCompareExchange:
-    case SpvOpAtomicCompareExchangeWeak:
-    case SpvOpAtomicIIncrement:
-    case SpvOpAtomicIDecrement:
-    case SpvOpAtomicIAdd:
-    case SpvOpAtomicFAddEXT:
-    case SpvOpAtomicISub:
-    case SpvOpAtomicSMin:
-    case SpvOpAtomicUMin:
-    case SpvOpAtomicFMinEXT:
-    case SpvOpAtomicSMax:
-    case SpvOpAtomicUMax:
-    case SpvOpAtomicFMaxEXT:
-    case SpvOpAtomicAnd:
-    case SpvOpAtomicOr:
-    case SpvOpAtomicXor:
-    case SpvOpAtomicFlagTestAndSet:
+    case spv::Op::OpAtomicLoad:
+    case spv::Op::OpAtomicExchange:
+    case spv::Op::OpAtomicCompareExchange:
+    case spv::Op::OpAtomicCompareExchangeWeak:
+    case spv::Op::OpAtomicIIncrement:
+    case spv::Op::OpAtomicIDecrement:
+    case spv::Op::OpAtomicIAdd:
+    case spv::Op::OpAtomicFAddEXT:
+    case spv::Op::OpAtomicISub:
+    case spv::Op::OpAtomicSMin:
+    case spv::Op::OpAtomicUMin:
+    case spv::Op::OpAtomicFMinEXT:
+    case spv::Op::OpAtomicSMax:
+    case spv::Op::OpAtomicUMax:
+    case spv::Op::OpAtomicFMaxEXT:
+    case spv::Op::OpAtomicAnd:
+    case spv::Op::OpAtomicOr:
+    case spv::Op::OpAtomicXor:
+    case spv::Op::OpAtomicFlagTestAndSet:
       return true;
     default:
       return false;
   }
 }
 
-bool spvOpcodeIsAtomicOp(const SpvOp opcode) {
-  return (spvOpcodeIsAtomicWithLoad(opcode) || opcode == SpvOpAtomicStore ||
-          opcode == SpvOpAtomicFlagClear);
+bool spvOpcodeIsAtomicOp(const spv::Op opcode) {
+  return (spvOpcodeIsAtomicWithLoad(opcode) ||
+          opcode == spv::Op::OpAtomicStore ||
+          opcode == spv::Op::OpAtomicFlagClear);
 }
 
-bool spvOpcodeIsReturn(SpvOp opcode) {
+bool spvOpcodeIsReturn(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpReturn:
-    case SpvOpReturnValue:
+    case spv::Op::OpReturn:
+    case spv::Op::OpReturnValue:
       return true;
     default:
       return false;
   }
 }
 
-bool spvOpcodeIsAbort(SpvOp opcode) {
+bool spvOpcodeIsAbort(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpKill:
-    case SpvOpUnreachable:
-    case SpvOpTerminateInvocation:
-    case SpvOpTerminateRayKHR:
-    case SpvOpIgnoreIntersectionKHR:
-    case SpvOpEmitMeshTasksEXT:
+    case spv::Op::OpKill:
+    case spv::Op::OpUnreachable:
+    case spv::Op::OpTerminateInvocation:
+    case spv::Op::OpTerminateRayKHR:
+    case spv::Op::OpIgnoreIntersectionKHR:
+    case spv::Op::OpEmitMeshTasksEXT:
       return true;
     default:
       return false;
   }
 }
 
-bool spvOpcodeIsReturnOrAbort(SpvOp opcode) {
+bool spvOpcodeIsReturnOrAbort(spv::Op opcode) {
   return spvOpcodeIsReturn(opcode) || spvOpcodeIsAbort(opcode);
 }
 
-bool spvOpcodeIsBlockTerminator(SpvOp opcode) {
+bool spvOpcodeIsBlockTerminator(spv::Op opcode) {
   return spvOpcodeIsBranch(opcode) || spvOpcodeIsReturnOrAbort(opcode);
 }
 
-bool spvOpcodeIsBaseOpaqueType(SpvOp opcode) {
+bool spvOpcodeIsBaseOpaqueType(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpTypeImage:
-    case SpvOpTypeSampler:
-    case SpvOpTypeSampledImage:
-    case SpvOpTypeOpaque:
-    case SpvOpTypeEvent:
-    case SpvOpTypeDeviceEvent:
-    case SpvOpTypeReserveId:
-    case SpvOpTypeQueue:
-    case SpvOpTypePipe:
-    case SpvOpTypeForwardPointer:
-    case SpvOpTypePipeStorage:
-    case SpvOpTypeNamedBarrier:
+    case spv::Op::OpTypeImage:
+    case spv::Op::OpTypeSampler:
+    case spv::Op::OpTypeSampledImage:
+    case spv::Op::OpTypeOpaque:
+    case spv::Op::OpTypeEvent:
+    case spv::Op::OpTypeDeviceEvent:
+    case spv::Op::OpTypeReserveId:
+    case spv::Op::OpTypeQueue:
+    case spv::Op::OpTypePipe:
+    case spv::Op::OpTypeForwardPointer:
+    case spv::Op::OpTypePipeStorage:
+    case spv::Op::OpTypeNamedBarrier:
       return true;
     default:
       return false;
   }
 }
 
-bool spvOpcodeIsNonUniformGroupOperation(SpvOp opcode) {
+bool spvOpcodeIsNonUniformGroupOperation(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpGroupNonUniformElect:
-    case SpvOpGroupNonUniformAll:
-    case SpvOpGroupNonUniformAny:
-    case SpvOpGroupNonUniformAllEqual:
-    case SpvOpGroupNonUniformBroadcast:
-    case SpvOpGroupNonUniformBroadcastFirst:
-    case SpvOpGroupNonUniformBallot:
-    case SpvOpGroupNonUniformInverseBallot:
-    case SpvOpGroupNonUniformBallotBitExtract:
-    case SpvOpGroupNonUniformBallotBitCount:
-    case SpvOpGroupNonUniformBallotFindLSB:
-    case SpvOpGroupNonUniformBallotFindMSB:
-    case SpvOpGroupNonUniformShuffle:
-    case SpvOpGroupNonUniformShuffleXor:
-    case SpvOpGroupNonUniformShuffleUp:
-    case SpvOpGroupNonUniformShuffleDown:
-    case SpvOpGroupNonUniformIAdd:
-    case SpvOpGroupNonUniformFAdd:
-    case SpvOpGroupNonUniformIMul:
-    case SpvOpGroupNonUniformFMul:
-    case SpvOpGroupNonUniformSMin:
-    case SpvOpGroupNonUniformUMin:
-    case SpvOpGroupNonUniformFMin:
-    case SpvOpGroupNonUniformSMax:
-    case SpvOpGroupNonUniformUMax:
-    case SpvOpGroupNonUniformFMax:
-    case SpvOpGroupNonUniformBitwiseAnd:
-    case SpvOpGroupNonUniformBitwiseOr:
-    case SpvOpGroupNonUniformBitwiseXor:
-    case SpvOpGroupNonUniformLogicalAnd:
-    case SpvOpGroupNonUniformLogicalOr:
-    case SpvOpGroupNonUniformLogicalXor:
-    case SpvOpGroupNonUniformQuadBroadcast:
-    case SpvOpGroupNonUniformQuadSwap:
-    case SpvOpGroupNonUniformRotateKHR:
+    case spv::Op::OpGroupNonUniformElect:
+    case spv::Op::OpGroupNonUniformAll:
+    case spv::Op::OpGroupNonUniformAny:
+    case spv::Op::OpGroupNonUniformAllEqual:
+    case spv::Op::OpGroupNonUniformBroadcast:
+    case spv::Op::OpGroupNonUniformBroadcastFirst:
+    case spv::Op::OpGroupNonUniformBallot:
+    case spv::Op::OpGroupNonUniformInverseBallot:
+    case spv::Op::OpGroupNonUniformBallotBitExtract:
+    case spv::Op::OpGroupNonUniformBallotBitCount:
+    case spv::Op::OpGroupNonUniformBallotFindLSB:
+    case spv::Op::OpGroupNonUniformBallotFindMSB:
+    case spv::Op::OpGroupNonUniformShuffle:
+    case spv::Op::OpGroupNonUniformShuffleXor:
+    case spv::Op::OpGroupNonUniformShuffleUp:
+    case spv::Op::OpGroupNonUniformShuffleDown:
+    case spv::Op::OpGroupNonUniformIAdd:
+    case spv::Op::OpGroupNonUniformFAdd:
+    case spv::Op::OpGroupNonUniformIMul:
+    case spv::Op::OpGroupNonUniformFMul:
+    case spv::Op::OpGroupNonUniformSMin:
+    case spv::Op::OpGroupNonUniformUMin:
+    case spv::Op::OpGroupNonUniformFMin:
+    case spv::Op::OpGroupNonUniformSMax:
+    case spv::Op::OpGroupNonUniformUMax:
+    case spv::Op::OpGroupNonUniformFMax:
+    case spv::Op::OpGroupNonUniformBitwiseAnd:
+    case spv::Op::OpGroupNonUniformBitwiseOr:
+    case spv::Op::OpGroupNonUniformBitwiseXor:
+    case spv::Op::OpGroupNonUniformLogicalAnd:
+    case spv::Op::OpGroupNonUniformLogicalOr:
+    case spv::Op::OpGroupNonUniformLogicalXor:
+    case spv::Op::OpGroupNonUniformQuadBroadcast:
+    case spv::Op::OpGroupNonUniformQuadSwap:
+    case spv::Op::OpGroupNonUniformRotateKHR:
       return true;
     default:
       return false;
   }
 }
 
-bool spvOpcodeIsScalarizable(SpvOp opcode) {
+bool spvOpcodeIsScalarizable(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpPhi:
-    case SpvOpCopyObject:
-    case SpvOpConvertFToU:
-    case SpvOpConvertFToS:
-    case SpvOpConvertSToF:
-    case SpvOpConvertUToF:
-    case SpvOpUConvert:
-    case SpvOpSConvert:
-    case SpvOpFConvert:
-    case SpvOpQuantizeToF16:
-    case SpvOpVectorInsertDynamic:
-    case SpvOpSNegate:
-    case SpvOpFNegate:
-    case SpvOpIAdd:
-    case SpvOpFAdd:
-    case SpvOpISub:
-    case SpvOpFSub:
-    case SpvOpIMul:
-    case SpvOpFMul:
-    case SpvOpUDiv:
-    case SpvOpSDiv:
-    case SpvOpFDiv:
-    case SpvOpUMod:
-    case SpvOpSRem:
-    case SpvOpSMod:
-    case SpvOpFRem:
-    case SpvOpFMod:
-    case SpvOpVectorTimesScalar:
-    case SpvOpIAddCarry:
-    case SpvOpISubBorrow:
-    case SpvOpUMulExtended:
-    case SpvOpSMulExtended:
-    case SpvOpShiftRightLogical:
-    case SpvOpShiftRightArithmetic:
-    case SpvOpShiftLeftLogical:
-    case SpvOpBitwiseOr:
-    case SpvOpBitwiseAnd:
-    case SpvOpNot:
-    case SpvOpBitFieldInsert:
-    case SpvOpBitFieldSExtract:
-    case SpvOpBitFieldUExtract:
-    case SpvOpBitReverse:
-    case SpvOpBitCount:
-    case SpvOpIsNan:
-    case SpvOpIsInf:
-    case SpvOpIsFinite:
-    case SpvOpIsNormal:
-    case SpvOpSignBitSet:
-    case SpvOpLessOrGreater:
-    case SpvOpOrdered:
-    case SpvOpUnordered:
-    case SpvOpLogicalEqual:
-    case SpvOpLogicalNotEqual:
-    case SpvOpLogicalOr:
-    case SpvOpLogicalAnd:
-    case SpvOpLogicalNot:
-    case SpvOpSelect:
-    case SpvOpIEqual:
-    case SpvOpINotEqual:
-    case SpvOpUGreaterThan:
-    case SpvOpSGreaterThan:
-    case SpvOpUGreaterThanEqual:
-    case SpvOpSGreaterThanEqual:
-    case SpvOpULessThan:
-    case SpvOpSLessThan:
-    case SpvOpULessThanEqual:
-    case SpvOpSLessThanEqual:
-    case SpvOpFOrdEqual:
-    case SpvOpFUnordEqual:
-    case SpvOpFOrdNotEqual:
-    case SpvOpFUnordNotEqual:
-    case SpvOpFOrdLessThan:
-    case SpvOpFUnordLessThan:
-    case SpvOpFOrdGreaterThan:
-    case SpvOpFUnordGreaterThan:
-    case SpvOpFOrdLessThanEqual:
-    case SpvOpFUnordLessThanEqual:
-    case SpvOpFOrdGreaterThanEqual:
-    case SpvOpFUnordGreaterThanEqual:
+    case spv::Op::OpPhi:
+    case spv::Op::OpCopyObject:
+    case spv::Op::OpConvertFToU:
+    case spv::Op::OpConvertFToS:
+    case spv::Op::OpConvertSToF:
+    case spv::Op::OpConvertUToF:
+    case spv::Op::OpUConvert:
+    case spv::Op::OpSConvert:
+    case spv::Op::OpFConvert:
+    case spv::Op::OpQuantizeToF16:
+    case spv::Op::OpVectorInsertDynamic:
+    case spv::Op::OpSNegate:
+    case spv::Op::OpFNegate:
+    case spv::Op::OpIAdd:
+    case spv::Op::OpFAdd:
+    case spv::Op::OpISub:
+    case spv::Op::OpFSub:
+    case spv::Op::OpIMul:
+    case spv::Op::OpFMul:
+    case spv::Op::OpUDiv:
+    case spv::Op::OpSDiv:
+    case spv::Op::OpFDiv:
+    case spv::Op::OpUMod:
+    case spv::Op::OpSRem:
+    case spv::Op::OpSMod:
+    case spv::Op::OpFRem:
+    case spv::Op::OpFMod:
+    case spv::Op::OpVectorTimesScalar:
+    case spv::Op::OpIAddCarry:
+    case spv::Op::OpISubBorrow:
+    case spv::Op::OpUMulExtended:
+    case spv::Op::OpSMulExtended:
+    case spv::Op::OpShiftRightLogical:
+    case spv::Op::OpShiftRightArithmetic:
+    case spv::Op::OpShiftLeftLogical:
+    case spv::Op::OpBitwiseOr:
+    case spv::Op::OpBitwiseAnd:
+    case spv::Op::OpNot:
+    case spv::Op::OpBitFieldInsert:
+    case spv::Op::OpBitFieldSExtract:
+    case spv::Op::OpBitFieldUExtract:
+    case spv::Op::OpBitReverse:
+    case spv::Op::OpBitCount:
+    case spv::Op::OpIsNan:
+    case spv::Op::OpIsInf:
+    case spv::Op::OpIsFinite:
+    case spv::Op::OpIsNormal:
+    case spv::Op::OpSignBitSet:
+    case spv::Op::OpLessOrGreater:
+    case spv::Op::OpOrdered:
+    case spv::Op::OpUnordered:
+    case spv::Op::OpLogicalEqual:
+    case spv::Op::OpLogicalNotEqual:
+    case spv::Op::OpLogicalOr:
+    case spv::Op::OpLogicalAnd:
+    case spv::Op::OpLogicalNot:
+    case spv::Op::OpSelect:
+    case spv::Op::OpIEqual:
+    case spv::Op::OpINotEqual:
+    case spv::Op::OpUGreaterThan:
+    case spv::Op::OpSGreaterThan:
+    case spv::Op::OpUGreaterThanEqual:
+    case spv::Op::OpSGreaterThanEqual:
+    case spv::Op::OpULessThan:
+    case spv::Op::OpSLessThan:
+    case spv::Op::OpULessThanEqual:
+    case spv::Op::OpSLessThanEqual:
+    case spv::Op::OpFOrdEqual:
+    case spv::Op::OpFUnordEqual:
+    case spv::Op::OpFOrdNotEqual:
+    case spv::Op::OpFUnordNotEqual:
+    case spv::Op::OpFOrdLessThan:
+    case spv::Op::OpFUnordLessThan:
+    case spv::Op::OpFOrdGreaterThan:
+    case spv::Op::OpFUnordGreaterThan:
+    case spv::Op::OpFOrdLessThanEqual:
+    case spv::Op::OpFUnordLessThanEqual:
+    case spv::Op::OpFOrdGreaterThanEqual:
+    case spv::Op::OpFUnordGreaterThanEqual:
       return true;
     default:
       return false;
   }
 }
 
-bool spvOpcodeIsDebug(SpvOp opcode) {
+bool spvOpcodeIsDebug(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpName:
-    case SpvOpMemberName:
-    case SpvOpSource:
-    case SpvOpSourceContinued:
-    case SpvOpSourceExtension:
-    case SpvOpString:
-    case SpvOpLine:
-    case SpvOpNoLine:
-    case SpvOpModuleProcessed:
+    case spv::Op::OpName:
+    case spv::Op::OpMemberName:
+    case spv::Op::OpSource:
+    case spv::Op::OpSourceContinued:
+    case spv::Op::OpSourceExtension:
+    case spv::Op::OpString:
+    case spv::Op::OpLine:
+    case spv::Op::OpNoLine:
+    case spv::Op::OpModuleProcessed:
       return true;
     default:
       return false;
   }
 }
 
-bool spvOpcodeIsCommutativeBinaryOperator(SpvOp opcode) {
+bool spvOpcodeIsCommutativeBinaryOperator(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpPtrEqual:
-    case SpvOpPtrNotEqual:
-    case SpvOpIAdd:
-    case SpvOpFAdd:
-    case SpvOpIMul:
-    case SpvOpFMul:
-    case SpvOpDot:
-    case SpvOpIAddCarry:
-    case SpvOpUMulExtended:
-    case SpvOpSMulExtended:
-    case SpvOpBitwiseOr:
-    case SpvOpBitwiseXor:
-    case SpvOpBitwiseAnd:
-    case SpvOpOrdered:
-    case SpvOpUnordered:
-    case SpvOpLogicalEqual:
-    case SpvOpLogicalNotEqual:
-    case SpvOpLogicalOr:
-    case SpvOpLogicalAnd:
-    case SpvOpIEqual:
-    case SpvOpINotEqual:
-    case SpvOpFOrdEqual:
-    case SpvOpFUnordEqual:
-    case SpvOpFOrdNotEqual:
-    case SpvOpFUnordNotEqual:
+    case spv::Op::OpPtrEqual:
+    case spv::Op::OpPtrNotEqual:
+    case spv::Op::OpIAdd:
+    case spv::Op::OpFAdd:
+    case spv::Op::OpIMul:
+    case spv::Op::OpFMul:
+    case spv::Op::OpDot:
+    case spv::Op::OpIAddCarry:
+    case spv::Op::OpUMulExtended:
+    case spv::Op::OpSMulExtended:
+    case spv::Op::OpBitwiseOr:
+    case spv::Op::OpBitwiseXor:
+    case spv::Op::OpBitwiseAnd:
+    case spv::Op::OpOrdered:
+    case spv::Op::OpUnordered:
+    case spv::Op::OpLogicalEqual:
+    case spv::Op::OpLogicalNotEqual:
+    case spv::Op::OpLogicalOr:
+    case spv::Op::OpLogicalAnd:
+    case spv::Op::OpIEqual:
+    case spv::Op::OpINotEqual:
+    case spv::Op::OpFOrdEqual:
+    case spv::Op::OpFUnordEqual:
+    case spv::Op::OpFOrdNotEqual:
+    case spv::Op::OpFUnordNotEqual:
       return true;
     default:
       return false;
   }
 }
 
-bool spvOpcodeIsLinearAlgebra(SpvOp opcode) {
+bool spvOpcodeIsLinearAlgebra(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpTranspose:
-    case SpvOpVectorTimesScalar:
-    case SpvOpMatrixTimesScalar:
-    case SpvOpVectorTimesMatrix:
-    case SpvOpMatrixTimesVector:
-    case SpvOpMatrixTimesMatrix:
-    case SpvOpOuterProduct:
-    case SpvOpDot:
+    case spv::Op::OpTranspose:
+    case spv::Op::OpVectorTimesScalar:
+    case spv::Op::OpMatrixTimesScalar:
+    case spv::Op::OpVectorTimesMatrix:
+    case spv::Op::OpMatrixTimesVector:
+    case spv::Op::OpMatrixTimesMatrix:
+    case spv::Op::OpOuterProduct:
+    case spv::Op::OpDot:
       return true;
     default:
       return false;
   }
 }
 
-bool spvOpcodeIsImageSample(const SpvOp opcode) {
+bool spvOpcodeIsImageSample(const spv::Op opcode) {
   switch (opcode) {
-    case SpvOpImageSampleImplicitLod:
-    case SpvOpImageSampleExplicitLod:
-    case SpvOpImageSampleDrefImplicitLod:
-    case SpvOpImageSampleDrefExplicitLod:
-    case SpvOpImageSampleProjImplicitLod:
-    case SpvOpImageSampleProjExplicitLod:
-    case SpvOpImageSampleProjDrefImplicitLod:
-    case SpvOpImageSampleProjDrefExplicitLod:
-    case SpvOpImageSparseSampleImplicitLod:
-    case SpvOpImageSparseSampleExplicitLod:
-    case SpvOpImageSparseSampleDrefImplicitLod:
-    case SpvOpImageSparseSampleDrefExplicitLod:
+    case spv::Op::OpImageSampleImplicitLod:
+    case spv::Op::OpImageSampleExplicitLod:
+    case spv::Op::OpImageSampleDrefImplicitLod:
+    case spv::Op::OpImageSampleDrefExplicitLod:
+    case spv::Op::OpImageSampleProjImplicitLod:
+    case spv::Op::OpImageSampleProjExplicitLod:
+    case spv::Op::OpImageSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSampleProjDrefExplicitLod:
+    case spv::Op::OpImageSparseSampleImplicitLod:
+    case spv::Op::OpImageSparseSampleExplicitLod:
+    case spv::Op::OpImageSparseSampleDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleDrefExplicitLod:
       return true;
     default:
       return false;
   }
 }
 
-std::vector<uint32_t> spvOpcodeMemorySemanticsOperandIndices(SpvOp opcode) {
+std::vector<uint32_t> spvOpcodeMemorySemanticsOperandIndices(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpMemoryBarrier:
+    case spv::Op::OpMemoryBarrier:
       return {1};
-    case SpvOpAtomicStore:
-    case SpvOpControlBarrier:
-    case SpvOpAtomicFlagClear:
-    case SpvOpMemoryNamedBarrier:
+    case spv::Op::OpAtomicStore:
+    case spv::Op::OpControlBarrier:
+    case spv::Op::OpAtomicFlagClear:
+    case spv::Op::OpMemoryNamedBarrier:
       return {2};
-    case SpvOpAtomicLoad:
-    case SpvOpAtomicExchange:
-    case SpvOpAtomicIIncrement:
-    case SpvOpAtomicIDecrement:
-    case SpvOpAtomicIAdd:
-    case SpvOpAtomicFAddEXT:
-    case SpvOpAtomicISub:
-    case SpvOpAtomicSMin:
-    case SpvOpAtomicUMin:
-    case SpvOpAtomicSMax:
-    case SpvOpAtomicUMax:
-    case SpvOpAtomicAnd:
-    case SpvOpAtomicOr:
-    case SpvOpAtomicXor:
-    case SpvOpAtomicFlagTestAndSet:
+    case spv::Op::OpAtomicLoad:
+    case spv::Op::OpAtomicExchange:
+    case spv::Op::OpAtomicIIncrement:
+    case spv::Op::OpAtomicIDecrement:
+    case spv::Op::OpAtomicIAdd:
+    case spv::Op::OpAtomicFAddEXT:
+    case spv::Op::OpAtomicISub:
+    case spv::Op::OpAtomicSMin:
+    case spv::Op::OpAtomicUMin:
+    case spv::Op::OpAtomicSMax:
+    case spv::Op::OpAtomicUMax:
+    case spv::Op::OpAtomicAnd:
+    case spv::Op::OpAtomicOr:
+    case spv::Op::OpAtomicXor:
+    case spv::Op::OpAtomicFlagTestAndSet:
       return {4};
-    case SpvOpAtomicCompareExchange:
-    case SpvOpAtomicCompareExchangeWeak:
+    case spv::Op::OpAtomicCompareExchange:
+    case spv::Op::OpAtomicCompareExchangeWeak:
       return {4, 5};
     default:
       return {};
   }
 }
 
-bool spvOpcodeIsAccessChain(SpvOp opcode) {
+bool spvOpcodeIsAccessChain(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpAccessChain:
-    case SpvOpInBoundsAccessChain:
-    case SpvOpPtrAccessChain:
-    case SpvOpInBoundsPtrAccessChain:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
+    case spv::Op::OpPtrAccessChain:
+    case spv::Op::OpInBoundsPtrAccessChain:
       return true;
     default:
       return false;
   }
 }
 
-bool spvOpcodeIsBit(SpvOp opcode) {
+bool spvOpcodeIsBit(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpShiftRightLogical:
-    case SpvOpShiftRightArithmetic:
-    case SpvOpShiftLeftLogical:
-    case SpvOpBitwiseOr:
-    case SpvOpBitwiseXor:
-    case SpvOpBitwiseAnd:
-    case SpvOpNot:
-    case SpvOpBitReverse:
-    case SpvOpBitCount:
+    case spv::Op::OpShiftRightLogical:
+    case spv::Op::OpShiftRightArithmetic:
+    case spv::Op::OpShiftLeftLogical:
+    case spv::Op::OpBitwiseOr:
+    case spv::Op::OpBitwiseXor:
+    case spv::Op::OpBitwiseAnd:
+    case spv::Op::OpNot:
+    case spv::Op::OpBitReverse:
+    case spv::Op::OpBitCount:
       return true;
     default:
       return false;
diff --git a/source/opcode.h b/source/opcode.h
index 77a0bed..217aeb2 100644
--- a/source/opcode.h
+++ b/source/opcode.h
@@ -29,7 +29,7 @@
 const char* spvGeneratorStr(uint32_t generator);
 
 // Combines word_count and opcode enumerant in single word.
-uint32_t spvOpcodeMake(uint16_t word_count, SpvOp opcode);
+uint32_t spvOpcodeMake(uint16_t word_count, spv::Op opcode);
 
 // Splits word into into two constituent parts: word_count and opcode.
 void spvOpcodeSplit(const uint32_t word, uint16_t* word_count,
@@ -45,115 +45,118 @@
 // SPV_SUCCESS and writes a handle of the table entry into *entry.
 spv_result_t spvOpcodeTableValueLookup(spv_target_env,
                                        const spv_opcode_table table,
-                                       const SpvOp opcode,
+                                       const spv::Op opcode,
                                        spv_opcode_desc* entry);
 
 // Copies an instruction's word and fixes the endianness to host native. The
 // source instruction's stream/opcode/endianness is in the words/opcode/endian
 // parameter. The word_count parameter specifies the number of words to copy.
 // Writes copied instruction into *inst.
-void spvInstructionCopy(const uint32_t* words, const SpvOp opcode,
+void spvInstructionCopy(const uint32_t* words, const spv::Op opcode,
                         const uint16_t word_count,
                         const spv_endianness_t endian, spv_instruction_t* inst);
 
 // Determine if the given opcode is a scalar type. Returns zero if false,
 // non-zero otherwise.
-int32_t spvOpcodeIsScalarType(const SpvOp opcode);
+int32_t spvOpcodeIsScalarType(const spv::Op opcode);
 
 // Determines if the given opcode is a specialization constant. Returns zero if
 // false, non-zero otherwise.
-int32_t spvOpcodeIsSpecConstant(const SpvOp opcode);
+int32_t spvOpcodeIsSpecConstant(const spv::Op opcode);
 
 // Determines if the given opcode is a constant. Returns zero if false, non-zero
 // otherwise.
-int32_t spvOpcodeIsConstant(const SpvOp opcode);
+int32_t spvOpcodeIsConstant(const spv::Op opcode);
 
 // Returns true if the given opcode is a constant or undef.
-bool spvOpcodeIsConstantOrUndef(const SpvOp opcode);
+bool spvOpcodeIsConstantOrUndef(const spv::Op opcode);
 
 // Returns true if the given opcode is a scalar specialization constant.
-bool spvOpcodeIsScalarSpecConstant(const SpvOp opcode);
+bool spvOpcodeIsScalarSpecConstant(const spv::Op opcode);
 
 // Determines if the given opcode is a composite type. Returns zero if false,
 // non-zero otherwise.
-int32_t spvOpcodeIsComposite(const SpvOp opcode);
+int32_t spvOpcodeIsComposite(const spv::Op opcode);
 
 // Determines if the given opcode results in a pointer when using the logical
 // addressing model. Returns zero if false, non-zero otherwise.
-int32_t spvOpcodeReturnsLogicalPointer(const SpvOp opcode);
+int32_t spvOpcodeReturnsLogicalPointer(const spv::Op opcode);
 
 // Returns whether the given opcode could result in a pointer or a variable
 // pointer when using the logical addressing model.
-bool spvOpcodeReturnsLogicalVariablePointer(const SpvOp opcode);
+bool spvOpcodeReturnsLogicalVariablePointer(const spv::Op opcode);
 
 // Determines if the given opcode generates a type. Returns zero if false,
 // non-zero otherwise.
-int32_t spvOpcodeGeneratesType(SpvOp opcode);
+int32_t spvOpcodeGeneratesType(spv::Op opcode);
 
 // Returns true if the opcode adds a decoration to an id.
-bool spvOpcodeIsDecoration(const SpvOp opcode);
+bool spvOpcodeIsDecoration(const spv::Op opcode);
 
 // Returns true if the opcode is a load from memory into a result id.  This
 // function only considers core instructions.
-bool spvOpcodeIsLoad(const SpvOp opcode);
+bool spvOpcodeIsLoad(const spv::Op opcode);
 
 // Returns true if the opcode is an atomic operation that uses the original
 // value.
-bool spvOpcodeIsAtomicWithLoad(const SpvOp opcode);
+bool spvOpcodeIsAtomicWithLoad(const spv::Op opcode);
 
 // Returns true if the opcode is an atomic operation.
-bool spvOpcodeIsAtomicOp(const SpvOp opcode);
+bool spvOpcodeIsAtomicOp(const spv::Op opcode);
 
 // Returns true if the given opcode is a branch instruction.
-bool spvOpcodeIsBranch(SpvOp opcode);
+bool spvOpcodeIsBranch(spv::Op opcode);
 
 // Returns true if the given opcode is a return instruction.
-bool spvOpcodeIsReturn(SpvOp opcode);
+bool spvOpcodeIsReturn(spv::Op opcode);
 
 // Returns true if the given opcode aborts execution.  To abort means that after
 // executing that instruction, no other instructions will be executed regardless
 // of the context in which the instruction appears.  Note that `OpUnreachable`
 // is considered an abort even if its behaviour is undefined.
-bool spvOpcodeIsAbort(SpvOp opcode);
+bool spvOpcodeIsAbort(spv::Op opcode);
 
 // Returns true if the given opcode is a return instruction or it aborts
 // execution.
-bool spvOpcodeIsReturnOrAbort(SpvOp opcode);
+bool spvOpcodeIsReturnOrAbort(spv::Op opcode);
 
 // Returns true if the given opcode is a basic block terminator.
-bool spvOpcodeIsBlockTerminator(SpvOp opcode);
+bool spvOpcodeIsBlockTerminator(spv::Op opcode);
 
 // Returns true if the given opcode always defines an opaque type.
-bool spvOpcodeIsBaseOpaqueType(SpvOp opcode);
+bool spvOpcodeIsBaseOpaqueType(spv::Op opcode);
 
 // Returns true if the given opcode is a non-uniform group operation.
-bool spvOpcodeIsNonUniformGroupOperation(SpvOp opcode);
+bool spvOpcodeIsNonUniformGroupOperation(spv::Op opcode);
 
 // Returns true if the opcode with vector inputs could be divided into a series
 // of independent scalar operations that would give the same result.
-bool spvOpcodeIsScalarizable(SpvOp opcode);
+bool spvOpcodeIsScalarizable(spv::Op opcode);
 
 // Returns true if the given opcode is a debug instruction.
-bool spvOpcodeIsDebug(SpvOp opcode);
+bool spvOpcodeIsDebug(spv::Op opcode);
 
 // Returns true for opcodes that are binary operators,
 // where the order of the operands is irrelevant.
-bool spvOpcodeIsCommutativeBinaryOperator(SpvOp opcode);
+bool spvOpcodeIsCommutativeBinaryOperator(spv::Op opcode);
 
 // Returns true for opcodes that represent linear algebra instructions.
-bool spvOpcodeIsLinearAlgebra(SpvOp opcode);
+bool spvOpcodeIsLinearAlgebra(spv::Op opcode);
 
 // Returns true for opcodes that represent image sample instructions.
-bool spvOpcodeIsImageSample(SpvOp opcode);
+bool spvOpcodeIsImageSample(spv::Op opcode);
 
 // Returns a vector containing the indices of the memory semantics <id>
 // operands for |opcode|.
-std::vector<uint32_t> spvOpcodeMemorySemanticsOperandIndices(SpvOp opcode);
+std::vector<uint32_t> spvOpcodeMemorySemanticsOperandIndices(spv::Op opcode);
 
 // Returns true for opcodes that represent access chain instructions.
-bool spvOpcodeIsAccessChain(SpvOp opcode);
+bool spvOpcodeIsAccessChain(spv::Op opcode);
 
 // Returns true for opcodes that represent bit instructions.
-bool spvOpcodeIsBit(SpvOp opcode);
+bool spvOpcodeIsBit(spv::Op opcode);
+
+// Gets the name of an instruction, without the "Op" prefix.
+const char* spvOpcodeString(const spv::Op opcode);
 
 #endif  // SOURCE_OPCODE_H_
diff --git a/source/operand.cpp b/source/operand.cpp
index 0c255a3..31a6c59 100644
--- a/source/operand.cpp
+++ b/source/operand.cpp
@@ -512,7 +512,7 @@
 }
 
 std::function<bool(unsigned)> spvOperandCanBeForwardDeclaredFunction(
-    SpvOp opcode) {
+    spv::Op opcode) {
   std::function<bool(unsigned index)> out;
   if (spvOpcodeGeneratesType(opcode)) {
     // All types can use forward pointers.
@@ -520,57 +520,57 @@
     return out;
   }
   switch (opcode) {
-    case SpvOpExecutionMode:
-    case SpvOpExecutionModeId:
-    case SpvOpEntryPoint:
-    case SpvOpName:
-    case SpvOpMemberName:
-    case SpvOpSelectionMerge:
-    case SpvOpDecorate:
-    case SpvOpMemberDecorate:
-    case SpvOpDecorateId:
-    case SpvOpDecorateStringGOOGLE:
-    case SpvOpMemberDecorateStringGOOGLE:
-    case SpvOpBranch:
-    case SpvOpLoopMerge:
+    case spv::Op::OpExecutionMode:
+    case spv::Op::OpExecutionModeId:
+    case spv::Op::OpEntryPoint:
+    case spv::Op::OpName:
+    case spv::Op::OpMemberName:
+    case spv::Op::OpSelectionMerge:
+    case spv::Op::OpDecorate:
+    case spv::Op::OpMemberDecorate:
+    case spv::Op::OpDecorateId:
+    case spv::Op::OpDecorateStringGOOGLE:
+    case spv::Op::OpMemberDecorateStringGOOGLE:
+    case spv::Op::OpBranch:
+    case spv::Op::OpLoopMerge:
       out = [](unsigned) { return true; };
       break;
-    case SpvOpGroupDecorate:
-    case SpvOpGroupMemberDecorate:
-    case SpvOpBranchConditional:
-    case SpvOpSwitch:
+    case spv::Op::OpGroupDecorate:
+    case spv::Op::OpGroupMemberDecorate:
+    case spv::Op::OpBranchConditional:
+    case spv::Op::OpSwitch:
       out = [](unsigned index) { return index != 0; };
       break;
 
-    case SpvOpFunctionCall:
+    case spv::Op::OpFunctionCall:
       // The Function parameter.
       out = [](unsigned index) { return index == 2; };
       break;
 
-    case SpvOpPhi:
+    case spv::Op::OpPhi:
       out = [](unsigned index) { return index > 1; };
       break;
 
-    case SpvOpEnqueueKernel:
+    case spv::Op::OpEnqueueKernel:
       // The Invoke parameter.
       out = [](unsigned index) { return index == 8; };
       break;
 
-    case SpvOpGetKernelNDrangeSubGroupCount:
-    case SpvOpGetKernelNDrangeMaxSubGroupSize:
+    case spv::Op::OpGetKernelNDrangeSubGroupCount:
+    case spv::Op::OpGetKernelNDrangeMaxSubGroupSize:
       // The Invoke parameter.
       out = [](unsigned index) { return index == 3; };
       break;
 
-    case SpvOpGetKernelWorkGroupSize:
-    case SpvOpGetKernelPreferredWorkGroupSizeMultiple:
+    case spv::Op::OpGetKernelWorkGroupSize:
+    case spv::Op::OpGetKernelPreferredWorkGroupSizeMultiple:
       // The Invoke parameter.
       out = [](unsigned index) { return index == 2; };
       break;
-    case SpvOpTypeForwardPointer:
+    case spv::Op::OpTypeForwardPointer:
       out = [](unsigned index) { return index == 0; };
       break;
-    case SpvOpTypeArray:
+    case spv::Op::OpTypeArray:
       out = [](unsigned index) { return index == 1; };
       break;
     default:
diff --git a/source/operand.h b/source/operand.h
index 7c73c6f..a3010d9 100644
--- a/source/operand.h
+++ b/source/operand.h
@@ -139,7 +139,7 @@
 // of the operand can be forward declared. This function will
 // used in the SSA validation stage of the pipeline
 std::function<bool(unsigned)> spvOperandCanBeForwardDeclaredFunction(
-    SpvOp opcode);
+    spv::Op opcode);
 
 // Takes the instruction key of a debug info extension instruction
 // and returns a function object that will return true if the index
diff --git a/source/opt/aggressive_dead_code_elim_pass.cpp b/source/opt/aggressive_dead_code_elim_pass.cpp
index 7fa5c8a..6b2fa24 100644
--- a/source/opt/aggressive_dead_code_elim_pass.cpp
+++ b/source/opt/aggressive_dead_code_elim_pass.cpp
@@ -49,33 +49,33 @@
 // ordering if both instructions have the same opcode.
 //
 // Desired priority:
-// SpvOpGroupDecorate
-// SpvOpGroupMemberDecorate
-// SpvOpDecorate
-// SpvOpMemberDecorate
-// SpvOpDecorateId
-// SpvOpDecorateStringGOOGLE
-// SpvOpDecorationGroup
+// spv::Op::OpGroupDecorate
+// spv::Op::OpGroupMemberDecorate
+// spv::Op::OpDecorate
+// spv::Op::OpMemberDecorate
+// spv::Op::OpDecorateId
+// spv::Op::OpDecorateStringGOOGLE
+// spv::Op::OpDecorationGroup
 struct DecorationLess {
   bool operator()(const Instruction* lhs, const Instruction* rhs) const {
     assert(lhs && rhs);
-    SpvOp lhsOp = lhs->opcode();
-    SpvOp rhsOp = rhs->opcode();
+    spv::Op lhsOp = lhs->opcode();
+    spv::Op rhsOp = rhs->opcode();
     if (lhsOp != rhsOp) {
 #define PRIORITY_CASE(opcode)                          \
   if (lhsOp == opcode && rhsOp != opcode) return true; \
   if (rhsOp == opcode && lhsOp != opcode) return false;
       // OpGroupDecorate and OpGroupMember decorate are highest priority to
       // eliminate dead targets early and simplify subsequent checks.
-      PRIORITY_CASE(SpvOpGroupDecorate)
-      PRIORITY_CASE(SpvOpGroupMemberDecorate)
-      PRIORITY_CASE(SpvOpDecorate)
-      PRIORITY_CASE(SpvOpMemberDecorate)
-      PRIORITY_CASE(SpvOpDecorateId)
-      PRIORITY_CASE(SpvOpDecorateStringGOOGLE)
+      PRIORITY_CASE(spv::Op::OpGroupDecorate)
+      PRIORITY_CASE(spv::Op::OpGroupMemberDecorate)
+      PRIORITY_CASE(spv::Op::OpDecorate)
+      PRIORITY_CASE(spv::Op::OpMemberDecorate)
+      PRIORITY_CASE(spv::Op::OpDecorateId)
+      PRIORITY_CASE(spv::Op::OpDecorateStringGOOGLE)
       // OpDecorationGroup is lowest priority to ensure use/def chains remain
       // usable for instructions that target this group.
-      PRIORITY_CASE(SpvOpDecorationGroup)
+      PRIORITY_CASE(spv::Op::OpDecorationGroup)
 #undef PRIORITY_CASE
     }
 
@@ -86,25 +86,26 @@
 
 }  // namespace
 
-bool AggressiveDCEPass::IsVarOfStorage(uint32_t varId, uint32_t storageClass) {
+bool AggressiveDCEPass::IsVarOfStorage(uint32_t varId,
+                                       spv::StorageClass storageClass) {
   if (varId == 0) return false;
   const Instruction* varInst = get_def_use_mgr()->GetDef(varId);
-  const SpvOp op = varInst->opcode();
-  if (op != SpvOpVariable) return false;
+  const spv::Op op = varInst->opcode();
+  if (op != spv::Op::OpVariable) return false;
   const uint32_t varTypeId = varInst->type_id();
   const Instruction* varTypeInst = get_def_use_mgr()->GetDef(varTypeId);
-  if (varTypeInst->opcode() != SpvOpTypePointer) return false;
-  return varTypeInst->GetSingleWordInOperand(kTypePointerStorageClassInIdx) ==
-         storageClass;
+  if (varTypeInst->opcode() != spv::Op::OpTypePointer) return false;
+  return spv::StorageClass(varTypeInst->GetSingleWordInOperand(
+             kTypePointerStorageClassInIdx)) == storageClass;
 }
 
 bool AggressiveDCEPass::IsLocalVar(uint32_t varId, Function* func) {
-  if (IsVarOfStorage(varId, SpvStorageClassFunction)) {
+  if (IsVarOfStorage(varId, spv::StorageClass::Function)) {
     return true;
   }
 
-  if (!IsVarOfStorage(varId, SpvStorageClassPrivate) &&
-      !IsVarOfStorage(varId, SpvStorageClassWorkgroup)) {
+  if (!IsVarOfStorage(varId, spv::StorageClass::Private) &&
+      !IsVarOfStorage(varId, spv::StorageClass::Workgroup)) {
     return false;
   }
 
@@ -122,21 +123,21 @@
     if (blk && blk->GetParent() != func) return;
 
     switch (user->opcode()) {
-      case SpvOpAccessChain:
-      case SpvOpInBoundsAccessChain:
-      case SpvOpCopyObject:
+      case spv::Op::OpAccessChain:
+      case spv::Op::OpInBoundsAccessChain:
+      case spv::Op::OpCopyObject:
         this->AddStores(func, user->result_id());
         break;
-      case SpvOpLoad:
+      case spv::Op::OpLoad:
         break;
-      case SpvOpCopyMemory:
-      case SpvOpCopyMemorySized:
+      case spv::Op::OpCopyMemory:
+      case spv::Op::OpCopyMemorySized:
         if (user->GetSingleWordInOperand(kCopyMemoryTargetAddrInIdx) == ptrId) {
           AddToWorklist(user);
         }
         break;
       // If default, assume it stores e.g. frexp, modf, function call
-      case SpvOpStore:
+      case spv::Op::OpStore:
       default:
         AddToWorklist(user);
         break;
@@ -154,7 +155,7 @@
   // Only allow NonSemantic.Shader.DebugInfo.100, we cannot safely optimise
   // around unknown extended instruction sets even if they are non-semantic
   for (auto& inst : context()->module()->ext_inst_imports()) {
-    assert(inst.opcode() == SpvOpExtInstImport &&
+    assert(inst.opcode() == spv::Op::OpExtInstImport &&
            "Expecting an import of an extension's instruction set.");
     const std::string extension_name = inst.GetInOperand(0).AsString();
     if (spvtools::utils::starts_with(extension_name, "NonSemantic.") &&
@@ -172,11 +173,11 @@
     // This must be a decoration group. We go through annotations in a specific
     // order. So if this is not used by any group or group member decorates, it
     // is dead.
-    assert(tInst->opcode() == SpvOpDecorationGroup);
+    assert(tInst->opcode() == spv::Op::OpDecorationGroup);
     bool dead = true;
     get_def_use_mgr()->ForEachUser(tInst, [&dead](Instruction* user) {
-      if (user->opcode() == SpvOpGroupDecorate ||
-          user->opcode() == SpvOpGroupMemberDecorate)
+      if (user->opcode() == spv::Op::OpGroupDecorate ||
+          user->opcode() == spv::Op::OpGroupMemberDecorate)
         dead = false;
     });
     return dead;
@@ -197,7 +198,7 @@
 
 void AggressiveDCEPass::AddBranch(uint32_t labelId, BasicBlock* bp) {
   std::unique_ptr<Instruction> newBranch(
-      new Instruction(context(), SpvOpBranch, 0, 0,
+      new Instruction(context(), spv::Op::OpBranch, 0, 0,
                       {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {labelId}}}));
   context()->AnalyzeDefUse(&*newBranch);
   context()->set_instr_block(&*newBranch, bp);
@@ -206,8 +207,8 @@
 
 void AggressiveDCEPass::AddBreaksAndContinuesToWorklist(
     Instruction* mergeInst) {
-  assert(mergeInst->opcode() == SpvOpSelectionMerge ||
-         mergeInst->opcode() == SpvOpLoopMerge);
+  assert(mergeInst->opcode() == spv::Op::OpSelectionMerge ||
+         mergeInst->opcode() == spv::Op::OpLoopMerge);
 
   BasicBlock* header = context()->get_instr_block(mergeInst);
   const uint32_t mergeId = mergeInst->GetSingleWordInOperand(0);
@@ -223,7 +224,7 @@
     }
   });
 
-  if (mergeInst->opcode() != SpvOpLoopMerge) {
+  if (mergeInst->opcode() != spv::Op::OpLoopMerge) {
     return;
   }
 
@@ -231,26 +232,27 @@
   const uint32_t contId =
       mergeInst->GetSingleWordInOperand(kLoopMergeContinueBlockIdInIdx);
   get_def_use_mgr()->ForEachUser(contId, [&contId, this](Instruction* user) {
-    SpvOp op = user->opcode();
-    if (op == SpvOpBranchConditional || op == SpvOpSwitch) {
+    spv::Op op = user->opcode();
+    if (op == spv::Op::OpBranchConditional || op == spv::Op::OpSwitch) {
       // A conditional branch or switch can only be a continue if it does not
       // have a merge instruction or its merge block is not the continue block.
       Instruction* hdrMerge = GetMergeInstruction(user);
-      if (hdrMerge != nullptr && hdrMerge->opcode() == SpvOpSelectionMerge) {
+      if (hdrMerge != nullptr &&
+          hdrMerge->opcode() == spv::Op::OpSelectionMerge) {
         uint32_t hdrMergeId =
             hdrMerge->GetSingleWordInOperand(kSelectionMergeMergeBlockIdInIdx);
         if (hdrMergeId == contId) return;
         // Need to mark merge instruction too
         AddToWorklist(hdrMerge);
       }
-    } else if (op == SpvOpBranch) {
+    } else if (op == spv::Op::OpBranch) {
       // An unconditional branch can only be a continue if it is not
       // branching to its own merge block.
       BasicBlock* blk = context()->get_instr_block(user);
       Instruction* hdrBranch = GetHeaderBranch(blk);
       if (hdrBranch == nullptr) return;
       Instruction* hdrMerge = GetMergeInstruction(hdrBranch);
-      if (hdrMerge->opcode() == SpvOpLoopMerge) return;
+      if (hdrMerge->opcode() == spv::Op::OpLoopMerge) return;
       uint32_t hdrMergeId =
           hdrMerge->GetSingleWordInOperand(kSelectionMergeMergeBlockIdInIdx);
       if (contId == hdrMergeId) return;
@@ -277,11 +279,11 @@
     uint32_t merge_block_id = 0;
     (*bi)->ForEachInst([this, &modified, &merge_block_id](Instruction* inst) {
       if (IsLive(inst)) return;
-      if (inst->opcode() == SpvOpLabel) return;
+      if (inst->opcode() == spv::Op::OpLabel) return;
       // If dead instruction is selection merge, remember merge block
       // for new branch at end of block
-      if (inst->opcode() == SpvOpSelectionMerge ||
-          inst->opcode() == SpvOpLoopMerge)
+      if (inst->opcode() == spv::Op::OpSelectionMerge ||
+          inst->opcode() == spv::Op::OpLoopMerge)
         merge_block_id = inst->GetSingleWordInOperand(0);
       to_kill_.push_back(inst);
       modified = true;
@@ -295,19 +297,19 @@
       }
 
       auto merge_terminator = (*bi)->terminator();
-      if (merge_terminator->opcode() == SpvOpUnreachable) {
+      if (merge_terminator->opcode() == spv::Op::OpUnreachable) {
         // The merge was unreachable. This is undefined behaviour so just
         // return (or return an undef). Then mark the new return as live.
         auto func_ret_type_inst = get_def_use_mgr()->GetDef(func->type_id());
-        if (func_ret_type_inst->opcode() == SpvOpTypeVoid) {
-          merge_terminator->SetOpcode(SpvOpReturn);
+        if (func_ret_type_inst->opcode() == spv::Op::OpTypeVoid) {
+          merge_terminator->SetOpcode(spv::Op::OpReturn);
         } else {
           // Find an undef for the return value and make sure it gets kept by
           // the pass.
           auto undef_id = Type2Undef(func->type_id());
           auto undef = get_def_use_mgr()->GetDef(undef_id);
           live_insts_.Set(undef->unique_id());
-          merge_terminator->SetOpcode(SpvOpReturnValue);
+          merge_terminator->SetOpcode(spv::Op::OpReturnValue);
           merge_terminator->SetInOperands({{SPV_OPERAND_TYPE_ID, {undef_id}}});
           get_def_use_mgr()->AnalyzeInstUse(merge_terminator);
         }
@@ -369,11 +371,11 @@
     // We only care about OpDecorateId instructions because the are the only
     // decorations that will reference an id that will have to be kept live
     // because of that use.
-    if (dec->opcode() != SpvOpDecorateId) {
+    if (dec->opcode() != spv::Op::OpDecorateId) {
       continue;
     }
-    if (dec->GetSingleWordInOperand(1) ==
-        SpvDecorationHlslCounterBufferGOOGLE) {
+    if (spv::Decoration(dec->GetSingleWordInOperand(1)) ==
+        spv::Decoration::HlslCounterBufferGOOGLE) {
       // These decorations should not force the use id to be live.  It will be
       // removed if either the target or the in operand are dead.
       continue;
@@ -391,7 +393,7 @@
 }
 
 std::vector<uint32_t> AggressiveDCEPass::GetLoadedVariables(Instruction* inst) {
-  if (inst->opcode() == SpvOpFunctionCall) {
+  if (inst->opcode() == spv::Op::OpFunctionCall) {
     return GetLoadedVariablesFromFunctionCall(inst);
   }
   uint32_t var_id = GetLoadedVariableFromNonFunctionCalls(inst);
@@ -409,11 +411,11 @@
   }
 
   switch (inst->opcode()) {
-    case SpvOpLoad:
-    case SpvOpImageTexelPointer:
+    case spv::Op::OpLoad:
+    case spv::Op::OpImageTexelPointer:
       return GetVariableId(inst->GetSingleWordInOperand(kLoadSourceAddrInIdx));
-    case SpvOpCopyMemory:
-    case SpvOpCopyMemorySized:
+    case spv::Op::OpCopyMemory:
+    case spv::Op::OpCopyMemorySized:
       return GetVariableId(
           inst->GetSingleWordInOperand(kCopyMemorySourceAddrInIdx));
     default:
@@ -436,7 +438,7 @@
 
 std::vector<uint32_t> AggressiveDCEPass::GetLoadedVariablesFromFunctionCall(
     const Instruction* inst) {
-  assert(inst->opcode() == SpvOpFunctionCall);
+  assert(inst->opcode() == spv::Op::OpFunctionCall);
   std::vector<uint32_t> live_variables;
   inst->ForEachInId([this, &live_variables](const uint32_t* operand_id) {
     if (!IsPtr(*operand_id)) return;
@@ -481,7 +483,7 @@
   // the loop, so the loop construct must be live.  We exclude the label because
   // it does not matter how many times it is executed.  This could be extended
   // to more instructions, but we will need it for now.
-  if (inst->opcode() != SpvOpLabel)
+  if (inst->opcode() != spv::Op::OpLabel)
     MarkLoopConstructAsLiveIfLoopHeader(basic_block);
 
   Instruction* next_branch_inst = GetBranchForNextHeader(basic_block);
@@ -491,8 +493,8 @@
     AddToWorklist(mergeInst);
   }
 
-  if (inst->opcode() == SpvOpLoopMerge ||
-      inst->opcode() == SpvOpSelectionMerge) {
+  if (inst->opcode() == spv::Op::OpLoopMerge ||
+      inst->opcode() == spv::Op::OpSelectionMerge) {
     AddBreaksAndContinuesToWorklist(inst);
   }
 }
@@ -529,27 +531,27 @@
   // cleaned up.
   for (auto& bi : structured_order) {
     for (auto ii = bi->begin(); ii != bi->end(); ++ii) {
-      SpvOp op = ii->opcode();
+      spv::Op op = ii->opcode();
       if (ii->IsBranch()) {
         continue;
       }
       switch (op) {
-        case SpvOpStore: {
+        case spv::Op::OpStore: {
           uint32_t var_id = 0;
           (void)GetPtr(&*ii, &var_id);
           if (!IsLocalVar(var_id, func)) AddToWorklist(&*ii);
         } break;
-        case SpvOpCopyMemory:
-        case SpvOpCopyMemorySized: {
+        case spv::Op::OpCopyMemory:
+        case spv::Op::OpCopyMemorySized: {
           uint32_t var_id = 0;
           uint32_t target_addr_id =
               ii->GetSingleWordInOperand(kCopyMemoryTargetAddrInIdx);
           (void)GetPtr(target_addr_id, &var_id);
           if (!IsLocalVar(var_id, func)) AddToWorklist(&*ii);
         } break;
-        case SpvOpLoopMerge:
-        case SpvOpSelectionMerge:
-        case SpvOpUnreachable:
+        case spv::Op::OpLoopMerge:
+        case spv::Op::OpSelectionMerge:
+        case spv::Op::OpUnreachable:
           break;
         default: {
           // Function calls, atomics, function params, function returns, etc.
@@ -579,7 +581,7 @@
         auto storage_class = var->GetSingleWordInOperand(0u);
         // Vulkan support outputs without an associated input, but not inputs
         // without an associated output.
-        if (storage_class == SpvStorageClassOutput) {
+        if (spv::StorageClass(storage_class) == spv::StorageClass::Output) {
           AddToWorklist(var);
         }
       }
@@ -588,24 +590,29 @@
     }
   }
   for (auto& anno : get_module()->annotations()) {
-    if (anno.opcode() == SpvOpDecorate) {
+    if (anno.opcode() == spv::Op::OpDecorate) {
       // Keep workgroup size.
-      if (anno.GetSingleWordInOperand(1u) == SpvDecorationBuiltIn &&
-          anno.GetSingleWordInOperand(2u) == SpvBuiltInWorkgroupSize) {
+      if (spv::Decoration(anno.GetSingleWordInOperand(1u)) ==
+              spv::Decoration::BuiltIn &&
+          spv::BuiltIn(anno.GetSingleWordInOperand(2u)) ==
+              spv::BuiltIn::WorkgroupSize) {
         AddToWorklist(&anno);
       }
 
       if (context()->preserve_bindings()) {
         // Keep all bindings.
-        if ((anno.GetSingleWordInOperand(1u) == SpvDecorationDescriptorSet) ||
-            (anno.GetSingleWordInOperand(1u) == SpvDecorationBinding)) {
+        if ((spv::Decoration(anno.GetSingleWordInOperand(1u)) ==
+             spv::Decoration::DescriptorSet) ||
+            (spv::Decoration(anno.GetSingleWordInOperand(1u)) ==
+             spv::Decoration::Binding)) {
           AddToWorklist(&anno);
         }
       }
 
       if (context()->preserve_spec_constants()) {
         // Keep all specialization constant instructions
-        if (anno.GetSingleWordInOperand(1u) == SpvDecorationSpecId) {
+        if (spv::Decoration(anno.GetSingleWordInOperand(1u)) ==
+            spv::Decoration::SpecId) {
           AddToWorklist(&anno);
         }
       }
@@ -624,7 +631,7 @@
     debug_global_seen = true;
     dbg.ForEachInId([this](const uint32_t* iid) {
       Instruction* in_inst = get_def_use_mgr()->GetDef(*iid);
-      if (in_inst->opcode() == SpvOpVariable) return;
+      if (in_inst->opcode() == spv::Op::OpVariable) return;
       AddToWorklist(in_inst);
     });
   }
@@ -647,19 +654,19 @@
 Pass::Status AggressiveDCEPass::ProcessImpl() {
   // Current functionality assumes shader capability
   // TODO(greg-lunarg): Handle additional capabilities
-  if (!context()->get_feature_mgr()->HasCapability(SpvCapabilityShader))
+  if (!context()->get_feature_mgr()->HasCapability(spv::Capability::Shader))
     return Status::SuccessWithoutChange;
 
   // Current functionality assumes relaxed logical addressing (see
   // instruction.h)
   // TODO(greg-lunarg): Handle non-logical addressing
-  if (context()->get_feature_mgr()->HasCapability(SpvCapabilityAddresses))
+  if (context()->get_feature_mgr()->HasCapability(spv::Capability::Addresses))
     return Status::SuccessWithoutChange;
 
   // The variable pointer extension is no longer needed to use the capability,
   // so we have to look for the capability.
   if (context()->get_feature_mgr()->HasCapability(
-          SpvCapabilityVariablePointersStorageBuffer))
+          spv::Capability::VariablePointersStorageBuffer))
     return Status::SuccessWithoutChange;
 
   // If any extensions in the module are not explicitly supported,
@@ -743,7 +750,7 @@
   bool modified = false;
   Instruction* instruction = &*get_module()->debug2_begin();
   while (instruction) {
-    if (instruction->opcode() != SpvOpName) {
+    if (instruction->opcode() != spv::Op::OpName) {
       instruction = instruction->NextNode();
       continue;
     }
@@ -764,22 +771,22 @@
   std::sort(annotations.begin(), annotations.end(), DecorationLess());
   for (auto annotation : annotations) {
     switch (annotation->opcode()) {
-      case SpvOpDecorate:
-      case SpvOpMemberDecorate:
-      case SpvOpDecorateStringGOOGLE:
-      case SpvOpMemberDecorateStringGOOGLE:
+      case spv::Op::OpDecorate:
+      case spv::Op::OpMemberDecorate:
+      case spv::Op::OpDecorateStringGOOGLE:
+      case spv::Op::OpMemberDecorateStringGOOGLE:
         if (IsTargetDead(annotation)) {
           context()->KillInst(annotation);
           modified = true;
         }
         break;
-      case SpvOpDecorateId:
+      case spv::Op::OpDecorateId:
         if (IsTargetDead(annotation)) {
           context()->KillInst(annotation);
           modified = true;
         } else {
-          if (annotation->GetSingleWordInOperand(1) ==
-              SpvDecorationHlslCounterBufferGOOGLE) {
+          if (spv::Decoration(annotation->GetSingleWordInOperand(1)) ==
+              spv::Decoration::HlslCounterBufferGOOGLE) {
             // HlslCounterBuffer will reference an id other than the target.
             // If that id is dead, then the decoration can be removed as well.
             uint32_t counter_buffer_id = annotation->GetSingleWordInOperand(2);
@@ -792,7 +799,7 @@
           }
         }
         break;
-      case SpvOpGroupDecorate: {
+      case spv::Op::OpGroupDecorate: {
         // Go through the targets of this group decorate. Remove each dead
         // target. If all targets are dead, remove this decoration.
         bool dead = true;
@@ -818,7 +825,7 @@
         }
         break;
       }
-      case SpvOpGroupMemberDecorate: {
+      case spv::Op::OpGroupMemberDecorate: {
         // Go through the targets of this group member decorate. Remove each
         // dead target (and member index). If all targets are dead, remove this
         // decoration.
@@ -846,7 +853,7 @@
         }
         break;
       }
-      case SpvOpDecorationGroup:
+      case spv::Op::OpDecorationGroup:
         // By the time we hit decoration groups we've checked everything that
         // can target them. So if they have no uses they must be dead.
         if (get_def_use_mgr()->NumUsers(annotation) == 0) {
@@ -887,7 +894,7 @@
       // this live as it does not have a result id. This is a little too
       // conservative since it is not known if the structure type that needed
       // it is still live. TODO(greg-lunarg): Only save if needed.
-      if (val.opcode() == SpvOpTypeForwardPointer) {
+      if (val.opcode() == spv::Op::OpTypeForwardPointer) {
         uint32_t ptr_ty_id = val.GetSingleWordInOperand(0);
         Instruction* ptr_ty_inst = get_def_use_mgr()->GetDef(ptr_ty_id);
         if (IsLive(ptr_ty_inst)) continue;
@@ -1083,8 +1090,9 @@
 }
 
 bool AggressiveDCEPass::HasCall(Function* func) {
-  return !func->WhileEachInst(
-      [](Instruction* inst) { return inst->opcode() != SpvOpFunctionCall; });
+  return !func->WhileEachInst([](Instruction* inst) {
+    return inst->opcode() != spv::Op::OpFunctionCall;
+  });
 }
 
 void AggressiveDCEPass::MarkFirstBlockAsLive(Function* func) {
diff --git a/source/opt/aggressive_dead_code_elim_pass.h b/source/opt/aggressive_dead_code_elim_pass.h
index c1291dc..99c4739 100644
--- a/source/opt/aggressive_dead_code_elim_pass.h
+++ b/source/opt/aggressive_dead_code_elim_pass.h
@@ -65,7 +65,7 @@
 
   // Return true if |varId| is a variable of |storageClass|. |varId| must either
   // be 0 or the result of an instruction.
-  bool IsVarOfStorage(uint32_t varId, uint32_t storageClass);
+  bool IsVarOfStorage(uint32_t varId, spv::StorageClass storageClass);
 
   // Return true if the instance of the variable |varId| can only be access in
   // |func|.  For example, a function scope variable, or a private variable
diff --git a/source/opt/amd_ext_to_khr.cpp b/source/opt/amd_ext_to_khr.cpp
index dd9bafd..e42114e 100644
--- a/source/opt/amd_ext_to_khr.cpp
+++ b/source/opt/amd_ext_to_khr.cpp
@@ -136,19 +136,19 @@
 // Returns a folding rule that will replace the opcode with |opcode| and add
 // the capabilities required.  The folding rule assumes it is folding an
 // OpGroup*NonUniformAMD instruction from the SPV_AMD_shader_ballot extension.
-template <SpvOp new_opcode>
+template <spv::Op new_opcode>
 bool ReplaceGroupNonuniformOperationOpCode(
     IRContext* ctx, Instruction* inst,
     const std::vector<const analysis::Constant*>&) {
   switch (new_opcode) {
-    case SpvOpGroupNonUniformIAdd:
-    case SpvOpGroupNonUniformFAdd:
-    case SpvOpGroupNonUniformUMin:
-    case SpvOpGroupNonUniformSMin:
-    case SpvOpGroupNonUniformFMin:
-    case SpvOpGroupNonUniformUMax:
-    case SpvOpGroupNonUniformSMax:
-    case SpvOpGroupNonUniformFMax:
+    case spv::Op::OpGroupNonUniformIAdd:
+    case spv::Op::OpGroupNonUniformFAdd:
+    case spv::Op::OpGroupNonUniformUMin:
+    case spv::Op::OpGroupNonUniformSMin:
+    case spv::Op::OpGroupNonUniformFMin:
+    case spv::Op::OpGroupNonUniformUMax:
+    case spv::Op::OpGroupNonUniformSMax:
+    case spv::Op::OpGroupNonUniformFMax:
       break;
     default:
       assert(
@@ -157,21 +157,21 @@
   }
 
   switch (inst->opcode()) {
-    case SpvOpGroupIAddNonUniformAMD:
-    case SpvOpGroupFAddNonUniformAMD:
-    case SpvOpGroupUMinNonUniformAMD:
-    case SpvOpGroupSMinNonUniformAMD:
-    case SpvOpGroupFMinNonUniformAMD:
-    case SpvOpGroupUMaxNonUniformAMD:
-    case SpvOpGroupSMaxNonUniformAMD:
-    case SpvOpGroupFMaxNonUniformAMD:
+    case spv::Op::OpGroupIAddNonUniformAMD:
+    case spv::Op::OpGroupFAddNonUniformAMD:
+    case spv::Op::OpGroupUMinNonUniformAMD:
+    case spv::Op::OpGroupSMinNonUniformAMD:
+    case spv::Op::OpGroupFMinNonUniformAMD:
+    case spv::Op::OpGroupUMaxNonUniformAMD:
+    case spv::Op::OpGroupSMaxNonUniformAMD:
+    case spv::Op::OpGroupFMaxNonUniformAMD:
       break;
     default:
       assert(false &&
              "Should be replacing a group non uniform arithmetic operation.");
   }
 
-  ctx->AddCapability(SpvCapabilityGroupNonUniformArithmetic);
+  ctx->AddCapability(spv::Capability::GroupNonUniformArithmetic);
   inst->SetOpcode(new_opcode);
   return true;
 }
@@ -215,8 +215,8 @@
   analysis::ConstantManager* const_mgr = ctx->get_constant_mgr();
 
   ctx->AddExtension("SPV_KHR_shader_ballot");
-  ctx->AddCapability(SpvCapabilityGroupNonUniformBallot);
-  ctx->AddCapability(SpvCapabilityGroupNonUniformShuffle);
+  ctx->AddCapability(spv::Capability::GroupNonUniformBallot);
+  ctx->AddCapability(spv::Capability::GroupNonUniformShuffle);
 
   InstructionBuilder ir_builder(
       ctx, inst,
@@ -226,8 +226,8 @@
   uint32_t offset_id = inst->GetSingleWordInOperand(3);
 
   // Get the subgroup invocation id.
-  uint32_t var_id =
-      ctx->GetBuiltinInputVarId(SpvBuiltInSubgroupLocalInvocationId);
+  uint32_t var_id = ctx->GetBuiltinInputVarId(
+      uint32_t(spv::BuiltIn::SubgroupLocalInvocationId));
   assert(var_id != 0 && "Could not get SubgroupLocalInvocationId variable.");
   Instruction* var_inst = ctx->get_def_use_mgr()->GetDef(var_id);
   Instruction* var_ptr_type =
@@ -239,35 +239,38 @@
   uint32_t quad_mask = ir_builder.GetUintConstantId(3);
 
   // This gives the offset in the group of 4 of this invocation.
-  Instruction* quad_idx = ir_builder.AddBinaryOp(uint_type_id, SpvOpBitwiseAnd,
-                                                 id->result_id(), quad_mask);
+  Instruction* quad_idx = ir_builder.AddBinaryOp(
+      uint_type_id, spv::Op::OpBitwiseAnd, id->result_id(), quad_mask);
 
   // Get the invocation id of the first invocation in the group of 4.
-  Instruction* quad_ldr = ir_builder.AddBinaryOp(
-      uint_type_id, SpvOpBitwiseXor, id->result_id(), quad_idx->result_id());
+  Instruction* quad_ldr =
+      ir_builder.AddBinaryOp(uint_type_id, spv::Op::OpBitwiseXor,
+                             id->result_id(), quad_idx->result_id());
 
   // Get the offset of the target invocation from the offset vector.
   Instruction* my_offset =
-      ir_builder.AddBinaryOp(uint_type_id, SpvOpVectorExtractDynamic, offset_id,
-                             quad_idx->result_id());
+      ir_builder.AddBinaryOp(uint_type_id, spv::Op::OpVectorExtractDynamic,
+                             offset_id, quad_idx->result_id());
 
   // Determine the index of the invocation to read from.
-  Instruction* target_inv = ir_builder.AddBinaryOp(
-      uint_type_id, SpvOpIAdd, quad_ldr->result_id(), my_offset->result_id());
+  Instruction* target_inv =
+      ir_builder.AddBinaryOp(uint_type_id, spv::Op::OpIAdd,
+                             quad_ldr->result_id(), my_offset->result_id());
 
   // Do the group operations
   uint32_t uint_max_id = ir_builder.GetUintConstantId(0xFFFFFFFF);
-  uint32_t subgroup_scope = ir_builder.GetUintConstantId(SpvScopeSubgroup);
+  uint32_t subgroup_scope =
+      ir_builder.GetUintConstantId(uint32_t(spv::Scope::Subgroup));
   const auto* ballot_value_const = const_mgr->GetConstant(
       type_mgr->GetUIntVectorType(4),
       {uint_max_id, uint_max_id, uint_max_id, uint_max_id});
   Instruction* ballot_value =
       const_mgr->GetDefiningInstruction(ballot_value_const);
   Instruction* is_active = ir_builder.AddNaryOp(
-      type_mgr->GetBoolTypeId(), SpvOpGroupNonUniformBallotBitExtract,
+      type_mgr->GetBoolTypeId(), spv::Op::OpGroupNonUniformBallotBitExtract,
       {subgroup_scope, ballot_value->result_id(), target_inv->result_id()});
   Instruction* shuffle =
-      ir_builder.AddNaryOp(inst->type_id(), SpvOpGroupNonUniformShuffle,
+      ir_builder.AddNaryOp(inst->type_id(), spv::Op::OpGroupNonUniformShuffle,
                            {subgroup_scope, data_id, target_inv->result_id()});
 
   // Create the null constant to use in the select.
@@ -276,7 +279,7 @@
   Instruction* null_inst = const_mgr->GetDefiningInstruction(null);
 
   // Build the select.
-  inst->SetOpcode(SpvOpSelect);
+  inst->SetOpcode(spv::Op::OpSelect);
   Instruction::OperandList new_operands;
   new_operands.push_back({SPV_OPERAND_TYPE_ID, {is_active->result_id()}});
   new_operands.push_back({SPV_OPERAND_TYPE_ID, {shuffle->result_id()}});
@@ -327,8 +330,8 @@
   analysis::DefUseManager* def_use_mgr = ctx->get_def_use_mgr();
   analysis::ConstantManager* const_mgr = ctx->get_constant_mgr();
 
-  ctx->AddCapability(SpvCapabilityGroupNonUniformBallot);
-  ctx->AddCapability(SpvCapabilityGroupNonUniformShuffle);
+  ctx->AddCapability(spv::Capability::GroupNonUniformBallot);
+  ctx->AddCapability(spv::Capability::GroupNonUniformShuffle);
 
   InstructionBuilder ir_builder(
       ctx, inst,
@@ -338,7 +341,7 @@
   uint32_t data_id = inst->GetSingleWordInOperand(2);
 
   Instruction* mask_inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(3));
-  assert(mask_inst->opcode() == SpvOpConstantComposite &&
+  assert(mask_inst->opcode() == spv::Op::OpConstantComposite &&
          "The mask is suppose to be a vector constant.");
   assert(mask_inst->NumInOperands() == 3 &&
          "The mask is suppose to have 3 components.");
@@ -348,8 +351,8 @@
   uint32_t uint_z = mask_inst->GetSingleWordInOperand(2);
 
   // Get the subgroup invocation id.
-  uint32_t var_id =
-      ctx->GetBuiltinInputVarId(SpvBuiltInSubgroupLocalInvocationId);
+  uint32_t var_id = ctx->GetBuiltinInputVarId(
+      uint32_t(spv::BuiltIn::SubgroupLocalInvocationId));
   ctx->AddExtension("SPV_KHR_shader_ballot");
   assert(var_id != 0 && "Could not get SubgroupLocalInvocationId variable.");
   Instruction* var_inst = ctx->get_def_use_mgr()->GetDef(var_id);
@@ -361,28 +364,30 @@
 
   // Do the bitwise operations.
   uint32_t mask_extended = ir_builder.GetUintConstantId(0xFFFFFFE0);
-  Instruction* and_mask = ir_builder.AddBinaryOp(uint_type_id, SpvOpBitwiseOr,
-                                                 uint_x, mask_extended);
-  Instruction* and_result = ir_builder.AddBinaryOp(
-      uint_type_id, SpvOpBitwiseAnd, id->result_id(), and_mask->result_id());
+  Instruction* and_mask = ir_builder.AddBinaryOp(
+      uint_type_id, spv::Op::OpBitwiseOr, uint_x, mask_extended);
+  Instruction* and_result =
+      ir_builder.AddBinaryOp(uint_type_id, spv::Op::OpBitwiseAnd,
+                             id->result_id(), and_mask->result_id());
   Instruction* or_result = ir_builder.AddBinaryOp(
-      uint_type_id, SpvOpBitwiseOr, and_result->result_id(), uint_y);
+      uint_type_id, spv::Op::OpBitwiseOr, and_result->result_id(), uint_y);
   Instruction* target_inv = ir_builder.AddBinaryOp(
-      uint_type_id, SpvOpBitwiseXor, or_result->result_id(), uint_z);
+      uint_type_id, spv::Op::OpBitwiseXor, or_result->result_id(), uint_z);
 
   // Do the group operations
   uint32_t uint_max_id = ir_builder.GetUintConstantId(0xFFFFFFFF);
-  uint32_t subgroup_scope = ir_builder.GetUintConstantId(SpvScopeSubgroup);
+  uint32_t subgroup_scope =
+      ir_builder.GetUintConstantId(uint32_t(spv::Scope::Subgroup));
   const auto* ballot_value_const = const_mgr->GetConstant(
       type_mgr->GetUIntVectorType(4),
       {uint_max_id, uint_max_id, uint_max_id, uint_max_id});
   Instruction* ballot_value =
       const_mgr->GetDefiningInstruction(ballot_value_const);
   Instruction* is_active = ir_builder.AddNaryOp(
-      type_mgr->GetBoolTypeId(), SpvOpGroupNonUniformBallotBitExtract,
+      type_mgr->GetBoolTypeId(), spv::Op::OpGroupNonUniformBallotBitExtract,
       {subgroup_scope, ballot_value->result_id(), target_inv->result_id()});
   Instruction* shuffle =
-      ir_builder.AddNaryOp(inst->type_id(), SpvOpGroupNonUniformShuffle,
+      ir_builder.AddNaryOp(inst->type_id(), spv::Op::OpGroupNonUniformShuffle,
                            {subgroup_scope, data_id, target_inv->result_id()});
 
   // Create the null constant to use in the select.
@@ -391,7 +396,7 @@
   Instruction* null_inst = const_mgr->GetDefiningInstruction(null);
 
   // Build the select.
-  inst->SetOpcode(SpvOpSelect);
+  inst->SetOpcode(spv::Op::OpSelect);
   Instruction::OperandList new_operands;
   new_operands.push_back({SPV_OPERAND_TYPE_ID, {is_active->result_id()}});
   new_operands.push_back({SPV_OPERAND_TYPE_ID, {shuffle->result_id()}});
@@ -420,9 +425,9 @@
 // Also adding the capabilities and builtins that are needed.
 bool ReplaceWriteInvocation(IRContext* ctx, Instruction* inst,
                             const std::vector<const analysis::Constant*>&) {
-  uint32_t var_id =
-      ctx->GetBuiltinInputVarId(SpvBuiltInSubgroupLocalInvocationId);
-  ctx->AddCapability(SpvCapabilitySubgroupBallotKHR);
+  uint32_t var_id = ctx->GetBuiltinInputVarId(
+      uint32_t(spv::BuiltIn::SubgroupLocalInvocationId));
+  ctx->AddCapability(spv::Capability::SubgroupBallotKHR);
   ctx->AddExtension("SPV_KHR_shader_ballot");
   assert(var_id != 0 && "Could not get SubgroupLocalInvocationId variable.");
   Instruction* var_inst = ctx->get_def_use_mgr()->GetDef(var_id);
@@ -437,11 +442,11 @@
   analysis::Bool bool_type;
   uint32_t bool_type_id = ctx->get_type_mgr()->GetTypeInstruction(&bool_type);
   Instruction* cmp =
-      ir_builder.AddBinaryOp(bool_type_id, SpvOpIEqual, t->result_id(),
+      ir_builder.AddBinaryOp(bool_type_id, spv::Op::OpIEqual, t->result_id(),
                              inst->GetSingleWordInOperand(4));
 
   // Build a select.
-  inst->SetOpcode(SpvOpSelect);
+  inst->SetOpcode(spv::Op::OpSelect);
   Instruction::OperandList new_operands;
   new_operands.push_back({SPV_OPERAND_TYPE_ID, {cmp->result_id()}});
   new_operands.push_back(inst->GetInOperand(3));
@@ -479,14 +484,15 @@
   analysis::TypeManager* type_mgr = context->get_type_mgr();
   analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
 
-  uint32_t var_id = context->GetBuiltinInputVarId(SpvBuiltInSubgroupLtMask);
+  uint32_t var_id =
+      context->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::SubgroupLtMask));
   assert(var_id != 0 && "Could not get SubgroupLtMask variable.");
-  context->AddCapability(SpvCapabilityGroupNonUniformBallot);
+  context->AddCapability(spv::Capability::GroupNonUniformBallot);
   Instruction* var_inst = def_use_mgr->GetDef(var_id);
   Instruction* var_ptr_type = def_use_mgr->GetDef(var_inst->type_id());
   Instruction* var_type =
       def_use_mgr->GetDef(var_ptr_type->GetSingleWordInOperand(1));
-  assert(var_type->opcode() == SpvOpTypeVector &&
+  assert(var_type->opcode() == spv::Op::OpTypeVector &&
          "Variable is suppose to be a vector of 4 ints");
 
   // Get the type for the shuffle.
@@ -509,11 +515,12 @@
   Instruction* shuffle = ir_builder.AddVectorShuffle(
       shuffle_type_id, load->result_id(), load->result_id(), {0, 1});
   Instruction* bitcast = ir_builder.AddUnaryOp(
-      mask_inst->type_id(), SpvOpBitcast, shuffle->result_id());
-  Instruction* t = ir_builder.AddBinaryOp(mask_inst->type_id(), SpvOpBitwiseAnd,
-                                          bitcast->result_id(), mask_id);
+      mask_inst->type_id(), spv::Op::OpBitcast, shuffle->result_id());
+  Instruction* t =
+      ir_builder.AddBinaryOp(mask_inst->type_id(), spv::Op::OpBitwiseAnd,
+                             bitcast->result_id(), mask_id);
 
-  inst->SetOpcode(SpvOpBitCount);
+  inst->SetOpcode(spv::Op::OpBitCount);
   inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {t->result_id()}}});
   context->UpdateDefUse(inst);
   return true;
@@ -599,11 +606,11 @@
 
   // Negate the input values.
   Instruction* nx =
-      ir_builder.AddUnaryOp(float_type_id, SpvOpFNegate, x->result_id());
+      ir_builder.AddUnaryOp(float_type_id, spv::Op::OpFNegate, x->result_id());
   Instruction* ny =
-      ir_builder.AddUnaryOp(float_type_id, SpvOpFNegate, y->result_id());
+      ir_builder.AddUnaryOp(float_type_id, spv::Op::OpFNegate, y->result_id());
   Instruction* nz =
-      ir_builder.AddUnaryOp(float_type_id, SpvOpFNegate, z->result_id());
+      ir_builder.AddUnaryOp(float_type_id, spv::Op::OpFNegate, z->result_id());
 
   // Get the abolsute values of the inputs.
   Instruction* ax = ir_builder.AddNaryExtendedInstruction(
@@ -614,12 +621,12 @@
       float_type_id, glsl405_ext_inst_id, GLSLstd450FAbs, {z->result_id()});
 
   // Find which values are negative.  Used in later computations.
-  Instruction* is_z_neg = ir_builder.AddBinaryOp(bool_id, SpvOpFOrdLessThan,
-                                                 z->result_id(), f0_const_id);
-  Instruction* is_y_neg = ir_builder.AddBinaryOp(bool_id, SpvOpFOrdLessThan,
-                                                 y->result_id(), f0_const_id);
-  Instruction* is_x_neg = ir_builder.AddBinaryOp(bool_id, SpvOpFOrdLessThan,
-                                                 x->result_id(), f0_const_id);
+  Instruction* is_z_neg = ir_builder.AddBinaryOp(
+      bool_id, spv::Op::OpFOrdLessThan, z->result_id(), f0_const_id);
+  Instruction* is_y_neg = ir_builder.AddBinaryOp(
+      bool_id, spv::Op::OpFOrdLessThan, y->result_id(), f0_const_id);
+  Instruction* is_x_neg = ir_builder.AddBinaryOp(
+      bool_id, spv::Op::OpFOrdLessThan, x->result_id(), f0_const_id);
 
   // Compute cubema
   Instruction* amax_x_y = ir_builder.AddNaryExtendedInstruction(
@@ -628,19 +635,21 @@
   Instruction* amax = ir_builder.AddNaryExtendedInstruction(
       float_type_id, glsl405_ext_inst_id, GLSLstd450FMax,
       {az->result_id(), amax_x_y->result_id()});
-  Instruction* cubema = ir_builder.AddBinaryOp(float_type_id, SpvOpFMul,
+  Instruction* cubema = ir_builder.AddBinaryOp(float_type_id, spv::Op::OpFMul,
                                                f2_const_id, amax->result_id());
 
   // Do the comparisons needed for computing cubesc and cubetc.
   Instruction* is_z_max =
-      ir_builder.AddBinaryOp(bool_id, SpvOpFOrdGreaterThanEqual,
+      ir_builder.AddBinaryOp(bool_id, spv::Op::OpFOrdGreaterThanEqual,
                              az->result_id(), amax_x_y->result_id());
-  Instruction* not_is_z_max =
-      ir_builder.AddUnaryOp(bool_id, SpvOpLogicalNot, is_z_max->result_id());
-  Instruction* y_gr_x = ir_builder.AddBinaryOp(
-      bool_id, SpvOpFOrdGreaterThanEqual, ay->result_id(), ax->result_id());
-  Instruction* is_y_max = ir_builder.AddBinaryOp(
-      bool_id, SpvOpLogicalAnd, not_is_z_max->result_id(), y_gr_x->result_id());
+  Instruction* not_is_z_max = ir_builder.AddUnaryOp(
+      bool_id, spv::Op::OpLogicalNot, is_z_max->result_id());
+  Instruction* y_gr_x =
+      ir_builder.AddBinaryOp(bool_id, spv::Op::OpFOrdGreaterThanEqual,
+                             ay->result_id(), ax->result_id());
+  Instruction* is_y_max =
+      ir_builder.AddBinaryOp(bool_id, spv::Op::OpLogicalAnd,
+                             not_is_z_max->result_id(), y_gr_x->result_id());
 
   // Select the correct value for cubesc.
   Instruction* cubesc_case_1 = ir_builder.AddSelect(
@@ -667,10 +676,10 @@
   Instruction* denom = ir_builder.AddCompositeConstruct(
       v2_float_type_id, {cubema->result_id(), cubema->result_id()});
   Instruction* div = ir_builder.AddBinaryOp(
-      v2_float_type_id, SpvOpFDiv, cube->result_id(), denom->result_id());
+      v2_float_type_id, spv::Op::OpFDiv, cube->result_id(), denom->result_id());
 
   // Get the final result by adding 0.5 to |div|.
-  inst->SetOpcode(SpvOpFAdd);
+  inst->SetOpcode(spv::Op::OpFAdd);
   Instruction::OperandList new_operands;
   new_operands.push_back({SPV_OPERAND_TYPE_ID, {div->result_id()}});
   new_operands.push_back({SPV_OPERAND_TYPE_ID, {vec_const_id}});
@@ -752,22 +761,23 @@
       float_type_id, glsl405_ext_inst_id, GLSLstd450FAbs, {z->result_id()});
 
   // Find which values are negative.  Used in later computations.
-  Instruction* is_z_neg = ir_builder.AddBinaryOp(bool_id, SpvOpFOrdLessThan,
-                                                 z->result_id(), f0_const_id);
-  Instruction* is_y_neg = ir_builder.AddBinaryOp(bool_id, SpvOpFOrdLessThan,
-                                                 y->result_id(), f0_const_id);
-  Instruction* is_x_neg = ir_builder.AddBinaryOp(bool_id, SpvOpFOrdLessThan,
-                                                 x->result_id(), f0_const_id);
+  Instruction* is_z_neg = ir_builder.AddBinaryOp(
+      bool_id, spv::Op::OpFOrdLessThan, z->result_id(), f0_const_id);
+  Instruction* is_y_neg = ir_builder.AddBinaryOp(
+      bool_id, spv::Op::OpFOrdLessThan, y->result_id(), f0_const_id);
+  Instruction* is_x_neg = ir_builder.AddBinaryOp(
+      bool_id, spv::Op::OpFOrdLessThan, x->result_id(), f0_const_id);
 
   // Find the max value.
   Instruction* amax_x_y = ir_builder.AddNaryExtendedInstruction(
       float_type_id, glsl405_ext_inst_id, GLSLstd450FMax,
       {ax->result_id(), ay->result_id()});
   Instruction* is_z_max =
-      ir_builder.AddBinaryOp(bool_id, SpvOpFOrdGreaterThanEqual,
+      ir_builder.AddBinaryOp(bool_id, spv::Op::OpFOrdGreaterThanEqual,
                              az->result_id(), amax_x_y->result_id());
-  Instruction* y_gr_x = ir_builder.AddBinaryOp(
-      bool_id, SpvOpFOrdGreaterThanEqual, ay->result_id(), ax->result_id());
+  Instruction* y_gr_x =
+      ir_builder.AddBinaryOp(bool_id, spv::Op::OpFOrdGreaterThanEqual,
+                             ay->result_id(), ax->result_id());
 
   // Get the value for each case.
   Instruction* case_z = ir_builder.AddSelect(
@@ -783,7 +793,7 @@
                            case_y->result_id(), case_x->result_id());
 
   // Get the final result by adding 0.5 to |div|.
-  inst->SetOpcode(SpvOpSelect);
+  inst->SetOpcode(spv::Op::OpSelect);
   Instruction::OperandList new_operands;
   new_operands.push_back({SPV_OPERAND_TYPE_ID, {is_z_max->result_id()}});
   new_operands.push_back({SPV_OPERAND_TYPE_ID, {case_z->result_id()}});
@@ -813,11 +823,12 @@
       ctx, inst,
       IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
   ctx->AddExtension("SPV_KHR_shader_clock");
-  ctx->AddCapability(SpvCapabilityShaderClockKHR);
+  ctx->AddCapability(spv::Capability::ShaderClockKHR);
 
-  inst->SetOpcode(SpvOpReadClockKHR);
+  inst->SetOpcode(spv::Op::OpReadClockKHR);
   Instruction::OperandList args;
-  uint32_t subgroup_scope_id = ir_builder.GetUintConstantId(SpvScopeSubgroup);
+  uint32_t subgroup_scope_id =
+      ir_builder.GetUintConstantId(uint32_t(spv::Scope::Subgroup));
   args.push_back({SPV_OPERAND_TYPE_ID, {subgroup_scope_id}});
   inst->SetInOperands(std::move(args));
   ctx->UpdateDefUse(inst);
@@ -831,22 +842,22 @@
 
  protected:
   virtual void AddFoldingRules() override {
-    rules_[SpvOpGroupIAddNonUniformAMD].push_back(
-        ReplaceGroupNonuniformOperationOpCode<SpvOpGroupNonUniformIAdd>);
-    rules_[SpvOpGroupFAddNonUniformAMD].push_back(
-        ReplaceGroupNonuniformOperationOpCode<SpvOpGroupNonUniformFAdd>);
-    rules_[SpvOpGroupUMinNonUniformAMD].push_back(
-        ReplaceGroupNonuniformOperationOpCode<SpvOpGroupNonUniformUMin>);
-    rules_[SpvOpGroupSMinNonUniformAMD].push_back(
-        ReplaceGroupNonuniformOperationOpCode<SpvOpGroupNonUniformSMin>);
-    rules_[SpvOpGroupFMinNonUniformAMD].push_back(
-        ReplaceGroupNonuniformOperationOpCode<SpvOpGroupNonUniformFMin>);
-    rules_[SpvOpGroupUMaxNonUniformAMD].push_back(
-        ReplaceGroupNonuniformOperationOpCode<SpvOpGroupNonUniformUMax>);
-    rules_[SpvOpGroupSMaxNonUniformAMD].push_back(
-        ReplaceGroupNonuniformOperationOpCode<SpvOpGroupNonUniformSMax>);
-    rules_[SpvOpGroupFMaxNonUniformAMD].push_back(
-        ReplaceGroupNonuniformOperationOpCode<SpvOpGroupNonUniformFMax>);
+    rules_[spv::Op::OpGroupIAddNonUniformAMD].push_back(
+        ReplaceGroupNonuniformOperationOpCode<spv::Op::OpGroupNonUniformIAdd>);
+    rules_[spv::Op::OpGroupFAddNonUniformAMD].push_back(
+        ReplaceGroupNonuniformOperationOpCode<spv::Op::OpGroupNonUniformFAdd>);
+    rules_[spv::Op::OpGroupUMinNonUniformAMD].push_back(
+        ReplaceGroupNonuniformOperationOpCode<spv::Op::OpGroupNonUniformUMin>);
+    rules_[spv::Op::OpGroupSMinNonUniformAMD].push_back(
+        ReplaceGroupNonuniformOperationOpCode<spv::Op::OpGroupNonUniformSMin>);
+    rules_[spv::Op::OpGroupFMinNonUniformAMD].push_back(
+        ReplaceGroupNonuniformOperationOpCode<spv::Op::OpGroupNonUniformFMin>);
+    rules_[spv::Op::OpGroupUMaxNonUniformAMD].push_back(
+        ReplaceGroupNonuniformOperationOpCode<spv::Op::OpGroupNonUniformUMax>);
+    rules_[spv::Op::OpGroupSMaxNonUniformAMD].push_back(
+        ReplaceGroupNonuniformOperationOpCode<spv::Op::OpGroupNonUniformSMax>);
+    rules_[spv::Op::OpGroupFMaxNonUniformAMD].push_back(
+        ReplaceGroupNonuniformOperationOpCode<spv::Op::OpGroupNonUniformFMax>);
 
     uint32_t extension_id =
         context()->module()->GetExtInstImportId("SPV_AMD_shader_ballot");
@@ -934,7 +945,7 @@
 
   std::vector<Instruction*> to_be_killed;
   for (Instruction& inst : context()->module()->extensions()) {
-    if (inst.opcode() == SpvOpExtension) {
+    if (inst.opcode() == spv::Op::OpExtension) {
       if (ext_to_remove.count(inst.GetInOperand(0).AsString()) != 0) {
         to_be_killed.push_back(&inst);
       }
@@ -942,7 +953,7 @@
   }
 
   for (Instruction& inst : context()->ext_inst_imports()) {
-    if (inst.opcode() == SpvOpExtInstImport) {
+    if (inst.opcode() == spv::Op::OpExtInstImport) {
       if (ext_to_remove.count(inst.GetInOperand(0).AsString()) != 0) {
         to_be_killed.push_back(&inst);
       }
diff --git a/source/opt/analyze_live_input_pass.cpp b/source/opt/analyze_live_input_pass.cpp
index f54206f..529e684 100644
--- a/source/opt/analyze_live_input_pass.cpp
+++ b/source/opt/analyze_live_input_pass.cpp
@@ -22,7 +22,7 @@
 
 Pass::Status AnalyzeLiveInputPass::Process() {
   // Current functionality assumes shader capability
-  if (!context()->get_feature_mgr()->HasCapability(SpvCapabilityShader))
+  if (!context()->get_feature_mgr()->HasCapability(spv::Capability::Shader))
     return Status::SuccessWithoutChange;
   Pass::Status status = DoLiveInputAnalysis();
   return status;
@@ -32,10 +32,10 @@
   // Current functionality only supports frag, tesc, tese or geom shaders.
   // Report failure for any other stage.
   auto stage = context()->GetStage();
-  if (stage != SpvExecutionModelFragment &&
-      stage != SpvExecutionModelTessellationControl &&
-      stage != SpvExecutionModelTessellationEvaluation &&
-      stage != SpvExecutionModelGeometry)
+  if (stage != spv::ExecutionModel::Fragment &&
+      stage != spv::ExecutionModel::TessellationControl &&
+      stage != spv::ExecutionModel::TessellationEvaluation &&
+      stage != spv::ExecutionModel::Geometry)
     return Status::Failure;
   context()->get_liveness_mgr()->GetLiveness(live_locs_, live_builtins_);
   return Status::SuccessWithoutChange;
diff --git a/source/opt/basic_block.cpp b/source/opt/basic_block.cpp
index e82a744..2c56344 100644
--- a/source/opt/basic_block.cpp
+++ b/source/opt/basic_block.cpp
@@ -58,7 +58,7 @@
   if (iter != cbegin()) {
     --iter;
     const auto opcode = iter->opcode();
-    if (opcode == SpvOpLoopMerge || opcode == SpvOpSelectionMerge) {
+    if (opcode == spv::Op::OpLoopMerge || opcode == spv::Op::OpSelectionMerge) {
       result = &*iter;
     }
   }
@@ -73,7 +73,7 @@
   if (iter != begin()) {
     --iter;
     const auto opcode = iter->opcode();
-    if (opcode == SpvOpLoopMerge || opcode == SpvOpSelectionMerge) {
+    if (opcode == spv::Op::OpLoopMerge || opcode == spv::Op::OpSelectionMerge) {
       result = &*iter;
     }
   }
@@ -82,7 +82,7 @@
 
 const Instruction* BasicBlock::GetLoopMergeInst() const {
   if (auto* merge = GetMergeInst()) {
-    if (merge->opcode() == SpvOpLoopMerge) {
+    if (merge->opcode() == spv::Op::OpLoopMerge) {
       return merge;
     }
   }
@@ -91,7 +91,7 @@
 
 Instruction* BasicBlock::GetLoopMergeInst() {
   if (auto* merge = GetMergeInst()) {
-    if (merge->opcode() == SpvOpLoopMerge) {
+    if (merge->opcode() == spv::Op::OpLoopMerge) {
       return merge;
     }
   }
@@ -100,7 +100,7 @@
 
 void BasicBlock::KillAllInsts(bool killLabel) {
   ForEachInst([killLabel](Instruction* ip) {
-    if (killLabel || ip->opcode() != SpvOpLabel) {
+    if (killLabel || ip->opcode() != spv::Op::OpLabel) {
       ip->context()->KillInst(ip);
     }
   });
@@ -118,10 +118,10 @@
     const std::function<bool(const uint32_t)>& f) const {
   const auto br = &insts_.back();
   switch (br->opcode()) {
-    case SpvOpBranch:
+    case spv::Op::OpBranch:
       return f(br->GetOperand(0).words[0]);
-    case SpvOpBranchConditional:
-    case SpvOpSwitch: {
+    case spv::Op::OpBranchConditional:
+    case spv::Op::OpSwitch: {
       bool is_first = true;
       return br->WhileEachInId([&is_first, &f](const uint32_t* idp) {
         if (!is_first) return f(*idp);
@@ -138,13 +138,13 @@
     const std::function<void(uint32_t*)>& f) {
   auto br = &insts_.back();
   switch (br->opcode()) {
-    case SpvOpBranch: {
+    case spv::Op::OpBranch: {
       uint32_t tmp_id = br->GetOperand(0).words[0];
       f(&tmp_id);
       if (tmp_id != br->GetOperand(0).words[0]) br->SetOperand(0, {tmp_id});
     } break;
-    case SpvOpBranchConditional:
-    case SpvOpSwitch: {
+    case spv::Op::OpBranchConditional:
+    case spv::Op::OpSwitch: {
       bool is_first = true;
       br->ForEachInId([&is_first, &f](uint32_t* idp) {
         if (!is_first) f(idp);
@@ -171,7 +171,8 @@
   --ii;
   if (ii == insts_.begin()) return;
   --ii;
-  if (ii->opcode() == SpvOpSelectionMerge || ii->opcode() == SpvOpLoopMerge) {
+  if (ii->opcode() == spv::Op::OpSelectionMerge ||
+      ii->opcode() == spv::Op::OpLoopMerge) {
     ii->ForEachInId([&f](const uint32_t* idp) { f(*idp); });
   }
 }
@@ -182,9 +183,9 @@
   uint32_t mbid = 0;
   if (merge_ii != cbegin()) {
     --merge_ii;
-    if (merge_ii->opcode() == SpvOpLoopMerge) {
+    if (merge_ii->opcode() == spv::Op::OpLoopMerge) {
       mbid = merge_ii->GetSingleWordInOperand(kLoopMergeMergeBlockIdInIdx);
-    } else if (merge_ii->opcode() == SpvOpSelectionMerge) {
+    } else if (merge_ii->opcode() == spv::Op::OpSelectionMerge) {
       mbid = merge_ii->GetSingleWordInOperand(kSelectionMergeMergeBlockIdInIdx);
     }
   }
@@ -204,7 +205,7 @@
   uint32_t cbid = 0;
   if (merge_ii != cbegin()) {
     --merge_ii;
-    if (merge_ii->opcode() == SpvOpLoopMerge) {
+    if (merge_ii->opcode() == spv::Op::OpLoopMerge) {
       cbid = merge_ii->GetSingleWordInOperand(kLoopMergeContinueBlockIdInIdx);
     }
   }
@@ -241,9 +242,9 @@
                                         iterator iter) {
   assert(!insts_.empty());
 
-  std::unique_ptr<BasicBlock> new_block_temp =
-      MakeUnique<BasicBlock>(MakeUnique<Instruction>(
-          context, SpvOpLabel, 0, label_id, std::initializer_list<Operand>{}));
+  std::unique_ptr<BasicBlock> new_block_temp = MakeUnique<BasicBlock>(
+      MakeUnique<Instruction>(context, spv::Op::OpLabel, 0, label_id,
+                              std::initializer_list<Operand>{}));
   BasicBlock* new_block = new_block_temp.get();
   function_->InsertBasicBlockAfter(std::move(new_block_temp), this);
 
diff --git a/source/opt/basic_block.h b/source/opt/basic_block.h
index dd3b2e2..24d5fce 100644
--- a/source/opt/basic_block.h
+++ b/source/opt/basic_block.h
@@ -319,7 +319,7 @@
   Instruction* inst = &insts_.front();
   while (inst != nullptr) {
     Instruction* next_instruction = inst->NextNode();
-    if (inst->opcode() != SpvOpPhi) break;
+    if (inst->opcode() != spv::Op::OpPhi) break;
     if (!inst->WhileEachInst(f, run_on_debug_line_insts)) return false;
     inst = next_instruction;
   }
diff --git a/source/opt/block_merge_util.cpp b/source/opt/block_merge_util.cpp
index 83c702c..222eaa6 100644
--- a/source/opt/block_merge_util.cpp
+++ b/source/opt/block_merge_util.cpp
@@ -34,14 +34,15 @@
 
 // Returns true if |id| is the merge target of a merge instruction.
 bool IsMerge(IRContext* context, uint32_t id) {
-  return !context->get_def_use_mgr()->WhileEachUse(id, [](Instruction* user,
-                                                          uint32_t index) {
-    SpvOp op = user->opcode();
-    if ((op == SpvOpLoopMerge || op == SpvOpSelectionMerge) && index == 0u) {
-      return false;
-    }
-    return true;
-  });
+  return !context->get_def_use_mgr()->WhileEachUse(
+      id, [](Instruction* user, uint32_t index) {
+        spv::Op op = user->opcode();
+        if ((op == spv::Op::OpLoopMerge || op == spv::Op::OpSelectionMerge) &&
+            index == 0u) {
+          return false;
+        }
+        return true;
+      });
 }
 
 // Returns true if |block| is the merge target of a merge instruction.
@@ -53,8 +54,8 @@
 bool IsContinue(IRContext* context, uint32_t id) {
   return !context->get_def_use_mgr()->WhileEachUse(
       id, [](Instruction* user, uint32_t index) {
-        SpvOp op = user->opcode();
-        if (op == SpvOpLoopMerge && index == 1u) {
+        spv::Op op = user->opcode();
+        if (op == spv::Op::OpLoopMerge && index == 1u) {
           return false;
         }
         return true;
@@ -82,7 +83,7 @@
   auto ii = block->end();
   --ii;
   Instruction* br = &*ii;
-  if (br->opcode() != SpvOpBranch) {
+  if (br->opcode() != spv::Op::OpBranch) {
     return false;
   }
 
@@ -119,9 +120,10 @@
     // The merge must be a loop merge because a selection merge cannot be
     // followed by an unconditional branch.
     BasicBlock* succ_block = context->get_instr_block(lab_id);
-    SpvOp succ_term_op = succ_block->terminator()->opcode();
-    assert(merge_inst->opcode() == SpvOpLoopMerge);
-    if (succ_term_op != SpvOpBranch && succ_term_op != SpvOpBranchConditional) {
+    spv::Op succ_term_op = succ_block->terminator()->opcode();
+    assert(merge_inst->opcode() == spv::Op::OpLoopMerge);
+    if (succ_term_op != spv::Op::OpBranch &&
+        succ_term_op != spv::Op::OpBranchConditional) {
       return false;
     }
   }
diff --git a/source/opt/ccp_pass.cpp b/source/opt/ccp_pass.cpp
index 5f85502..7b59d3e 100644
--- a/source/opt/ccp_pass.cpp
+++ b/source/opt/ccp_pass.cpp
@@ -136,7 +136,7 @@
 
   // If this is a copy operation, and the RHS is a known constant, assign its
   // value to the LHS.
-  if (instr->opcode() == SpvOpCopyObject) {
+  if (instr->opcode() == spv::Op::OpCopyObject) {
     uint32_t rhs_id = instr->GetSingleWordInOperand(0);
     auto it = values_.find(rhs_id);
     if (it != values_.end()) {
@@ -211,10 +211,10 @@
 
   *dest_bb = nullptr;
   uint32_t dest_label = 0;
-  if (instr->opcode() == SpvOpBranch) {
+  if (instr->opcode() == spv::Op::OpBranch) {
     // An unconditional jump always goes to its unique destination.
     dest_label = instr->GetSingleWordInOperand(0);
-  } else if (instr->opcode() == SpvOpBranchConditional) {
+  } else if (instr->opcode() == spv::Op::OpBranchConditional) {
     // For a conditional branch, determine whether the predicate selector has a
     // known value in |values_|.  If it does, set the destination block
     // according to the selector's boolean value.
@@ -243,7 +243,7 @@
     // For an OpSwitch, extract the value taken by the switch selector and check
     // which of the target literals it matches.  The branch associated with that
     // literal is the taken branch.
-    assert(instr->opcode() == SpvOpSwitch);
+    assert(instr->opcode() == spv::Op::OpSwitch);
     if (instr->GetOperand(0).words.size() != 1) {
       // If the selector is wider than 32-bits, return varying. TODO(dnovillo):
       // Add support for wider constants.
@@ -290,7 +290,7 @@
 SSAPropagator::PropStatus CCPPass::VisitInstruction(Instruction* instr,
                                                     BasicBlock** dest_bb) {
   *dest_bb = nullptr;
-  if (instr->opcode() == SpvOpPhi) {
+  if (instr->opcode() == spv::Op::OpPhi) {
     return VisitPhi(instr);
   } else if (instr->IsBranch()) {
     return VisitBranch(instr, dest_bb);
diff --git a/source/opt/cfg.cpp b/source/opt/cfg.cpp
index a0248d5..2a4b9bd 100644
--- a/source/opt/cfg.cpp
+++ b/source/opt/cfg.cpp
@@ -36,9 +36,9 @@
 CFG::CFG(Module* module)
     : module_(module),
       pseudo_entry_block_(std::unique_ptr<Instruction>(
-          new Instruction(module->context(), SpvOpLabel, 0, 0, {}))),
+          new Instruction(module->context(), spv::Op::OpLabel, 0, 0, {}))),
       pseudo_exit_block_(std::unique_ptr<Instruction>(new Instruction(
-          module->context(), SpvOpLabel, 0, kMaxResultId, {}))) {
+          module->context(), spv::Op::OpLabel, 0, kMaxResultId, {}))) {
   for (auto& fn : *module) {
     for (auto& blk : fn) {
       RegisterBlock(&blk);
@@ -81,7 +81,7 @@
                                  BasicBlock* end,
                                  std::list<BasicBlock*>* order) {
   assert(module_->context()->get_feature_mgr()->HasCapability(
-             SpvCapabilityShader) &&
+             spv::Capability::Shader) &&
          "This only works on structured control flow");
 
   // Compute structured successors and do DFS.
@@ -228,7 +228,7 @@
   // Create the new header bb basic bb.
   // Leave the phi instructions behind.
   auto iter = bb->begin();
-  while (iter->opcode() == SpvOpPhi) {
+  while (iter->opcode() == spv::Op::OpPhi) {
     ++iter;
   }
 
@@ -304,7 +304,7 @@
       context, bb,
       IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
   bb->AddInstruction(
-      MakeUnique<Instruction>(context, SpvOpBranch, 0, 0,
+      MakeUnique<Instruction>(context, spv::Op::OpBranch, 0, 0,
                               std::initializer_list<Operand>{
                                   {SPV_OPERAND_TYPE_ID, {new_header->id()}}}));
   context->AnalyzeUses(bb->terminator());
diff --git a/source/opt/code_sink.cpp b/source/opt/code_sink.cpp
index cd77797..35a8df2 100644
--- a/source/opt/code_sink.cpp
+++ b/source/opt/code_sink.cpp
@@ -50,7 +50,8 @@
 }
 
 bool CodeSinkingPass::SinkInstruction(Instruction* inst) {
-  if (inst->opcode() != SpvOpLoad && inst->opcode() != SpvOpAccessChain) {
+  if (inst->opcode() != spv::Op::OpLoad &&
+      inst->opcode() != spv::Op::OpAccessChain) {
     return false;
   }
 
@@ -60,7 +61,7 @@
 
   if (BasicBlock* target_bb = FindNewBasicBlockFor(inst)) {
     Instruction* pos = &*target_bb->begin();
-    while (pos->opcode() == SpvOpPhi) {
+    while (pos->opcode() == spv::Op::OpPhi) {
       pos = pos->NextNode();
     }
 
@@ -79,7 +80,7 @@
   std::unordered_set<uint32_t> bbs_with_uses;
   get_def_use_mgr()->ForEachUse(
       inst, [&bbs_with_uses, this](Instruction* use, uint32_t idx) {
-        if (use->opcode() != SpvOpPhi) {
+        if (use->opcode() != spv::Op::OpPhi) {
           BasicBlock* use_bb = context()->get_instr_block(use);
           if (use_bb) {
             bbs_with_uses.insert(use_bb->id());
@@ -99,7 +100,7 @@
     // of succ_bb, then |inst| can be moved to succ_bb.  If succ_bb, has move
     // then one predecessor, then moving |inst| into succ_bb could cause it to
     // be executed more often, so the search has to stop.
-    if (bb->terminator()->opcode() == SpvOpBranch) {
+    if (bb->terminator()->opcode() == spv::Op::OpBranch) {
       uint32_t succ_bb_id = bb->terminator()->GetSingleWordInOperand(0);
       if (cfg()->preds(succ_bb_id).size() == 1) {
         bb = context()->get_instr_block(succ_bb_id);
@@ -113,7 +114,8 @@
     // instruction or an OpLoopMerge, then it is a break or continue.  We could
     // figure it out, but not worth doing it now.
     Instruction* merge_inst = bb->GetMergeInst();
-    if (merge_inst == nullptr || merge_inst->opcode() != SpvOpSelectionMerge) {
+    if (merge_inst == nullptr ||
+        merge_inst->opcode() != spv::Op::OpSelectionMerge) {
       break;
     }
 
@@ -173,7 +175,7 @@
   }
 
   Instruction* base_ptr = inst->GetBaseAddress();
-  if (base_ptr->opcode() != SpvOpVariable) {
+  if (base_ptr->opcode() != spv::Op::OpVariable) {
     return true;
   }
 
@@ -185,7 +187,8 @@
     return true;
   }
 
-  if (base_ptr->GetSingleWordInOperand(0) != SpvStorageClassUniform) {
+  if (spv::StorageClass(base_ptr->GetSingleWordInOperand(0)) !=
+      spv::StorageClass::Uniform) {
     return true;
   }
 
@@ -200,41 +203,41 @@
   bool has_sync = false;
   get_module()->ForEachInst([this, &has_sync](Instruction* inst) {
     switch (inst->opcode()) {
-      case SpvOpMemoryBarrier: {
+      case spv::Op::OpMemoryBarrier: {
         uint32_t mem_semantics_id = inst->GetSingleWordInOperand(1);
         if (IsSyncOnUniform(mem_semantics_id)) {
           has_sync = true;
         }
         break;
       }
-      case SpvOpControlBarrier:
-      case SpvOpAtomicLoad:
-      case SpvOpAtomicStore:
-      case SpvOpAtomicExchange:
-      case SpvOpAtomicIIncrement:
-      case SpvOpAtomicIDecrement:
-      case SpvOpAtomicIAdd:
-      case SpvOpAtomicFAddEXT:
-      case SpvOpAtomicISub:
-      case SpvOpAtomicSMin:
-      case SpvOpAtomicUMin:
-      case SpvOpAtomicFMinEXT:
-      case SpvOpAtomicSMax:
-      case SpvOpAtomicUMax:
-      case SpvOpAtomicFMaxEXT:
-      case SpvOpAtomicAnd:
-      case SpvOpAtomicOr:
-      case SpvOpAtomicXor:
-      case SpvOpAtomicFlagTestAndSet:
-      case SpvOpAtomicFlagClear: {
+      case spv::Op::OpControlBarrier:
+      case spv::Op::OpAtomicLoad:
+      case spv::Op::OpAtomicStore:
+      case spv::Op::OpAtomicExchange:
+      case spv::Op::OpAtomicIIncrement:
+      case spv::Op::OpAtomicIDecrement:
+      case spv::Op::OpAtomicIAdd:
+      case spv::Op::OpAtomicFAddEXT:
+      case spv::Op::OpAtomicISub:
+      case spv::Op::OpAtomicSMin:
+      case spv::Op::OpAtomicUMin:
+      case spv::Op::OpAtomicFMinEXT:
+      case spv::Op::OpAtomicSMax:
+      case spv::Op::OpAtomicUMax:
+      case spv::Op::OpAtomicFMaxEXT:
+      case spv::Op::OpAtomicAnd:
+      case spv::Op::OpAtomicOr:
+      case spv::Op::OpAtomicXor:
+      case spv::Op::OpAtomicFlagTestAndSet:
+      case spv::Op::OpAtomicFlagClear: {
         uint32_t mem_semantics_id = inst->GetSingleWordInOperand(2);
         if (IsSyncOnUniform(mem_semantics_id)) {
           has_sync = true;
         }
         break;
       }
-      case SpvOpAtomicCompareExchange:
-      case SpvOpAtomicCompareExchangeWeak:
+      case spv::Op::OpAtomicCompareExchange:
+      case spv::Op::OpAtomicCompareExchangeWeak:
         if (IsSyncOnUniform(inst->GetSingleWordInOperand(2)) ||
             IsSyncOnUniform(inst->GetSingleWordInOperand(3))) {
           has_sync = true;
@@ -259,28 +262,30 @@
 
   // If it does not affect uniform memory, then it is does not apply to uniform
   // memory.
-  if ((mem_semantics_int & SpvMemorySemanticsUniformMemoryMask) == 0) {
+  if ((mem_semantics_int & uint32_t(spv::MemorySemanticsMask::UniformMemory)) ==
+      0) {
     return false;
   }
 
   // Check if there is an acquire or release.  If so not, this it does not add
   // any memory constraints.
-  return (mem_semantics_int & (SpvMemorySemanticsAcquireMask |
-                               SpvMemorySemanticsAcquireReleaseMask |
-                               SpvMemorySemanticsReleaseMask)) != 0;
+  return (mem_semantics_int &
+          uint32_t(spv::MemorySemanticsMask::Acquire |
+                   spv::MemorySemanticsMask::AcquireRelease |
+                   spv::MemorySemanticsMask::Release)) != 0;
 }
 
 bool CodeSinkingPass::HasPossibleStore(Instruction* var_inst) {
-  assert(var_inst->opcode() == SpvOpVariable ||
-         var_inst->opcode() == SpvOpAccessChain ||
-         var_inst->opcode() == SpvOpPtrAccessChain);
+  assert(var_inst->opcode() == spv::Op::OpVariable ||
+         var_inst->opcode() == spv::Op::OpAccessChain ||
+         var_inst->opcode() == spv::Op::OpPtrAccessChain);
 
   return get_def_use_mgr()->WhileEachUser(var_inst, [this](Instruction* use) {
     switch (use->opcode()) {
-      case SpvOpStore:
+      case spv::Op::OpStore:
         return true;
-      case SpvOpAccessChain:
-      case SpvOpPtrAccessChain:
+      case spv::Op::OpAccessChain:
+      case spv::Op::OpPtrAccessChain:
         return HasPossibleStore(use);
       default:
         return false;
diff --git a/source/opt/combine_access_chains.cpp b/source/opt/combine_access_chains.cpp
index 142897a..99ec796 100644
--- a/source/opt/combine_access_chains.cpp
+++ b/source/opt/combine_access_chains.cpp
@@ -44,10 +44,10 @@
       function.entry().get(), [&modified, this](BasicBlock* block) {
         block->ForEachInst([&modified, this](Instruction* inst) {
           switch (inst->opcode()) {
-            case SpvOpAccessChain:
-            case SpvOpInBoundsAccessChain:
-            case SpvOpPtrAccessChain:
-            case SpvOpInBoundsPtrAccessChain:
+            case spv::Op::OpAccessChain:
+            case spv::Op::OpInBoundsAccessChain:
+            case spv::Op::OpPtrAccessChain:
+            case spv::Op::OpInBoundsPtrAccessChain:
               modified |= CombineAccessChain(inst);
               break;
             default:
@@ -76,10 +76,10 @@
 uint32_t CombineAccessChains::GetArrayStride(const Instruction* inst) {
   uint32_t array_stride = 0;
   context()->get_decoration_mgr()->WhileEachDecoration(
-      inst->type_id(), SpvDecorationArrayStride,
+      inst->type_id(), uint32_t(spv::Decoration::ArrayStride),
       [&array_stride](const Instruction& decoration) {
-        assert(decoration.opcode() != SpvOpDecorateId);
-        if (decoration.opcode() == SpvOpDecorate) {
+        assert(decoration.opcode() != spv::Op::OpDecorateId);
+        if (decoration.opcode() == spv::Op::OpDecorate) {
           array_stride = decoration.GetSingleWordInOperand(1);
         } else {
           array_stride = decoration.GetSingleWordInOperand(2);
@@ -200,18 +200,18 @@
 }
 
 bool CombineAccessChains::CombineAccessChain(Instruction* inst) {
-  assert((inst->opcode() == SpvOpPtrAccessChain ||
-          inst->opcode() == SpvOpAccessChain ||
-          inst->opcode() == SpvOpInBoundsAccessChain ||
-          inst->opcode() == SpvOpInBoundsPtrAccessChain) &&
+  assert((inst->opcode() == spv::Op::OpPtrAccessChain ||
+          inst->opcode() == spv::Op::OpAccessChain ||
+          inst->opcode() == spv::Op::OpInBoundsAccessChain ||
+          inst->opcode() == spv::Op::OpInBoundsPtrAccessChain) &&
          "Wrong opcode. Expected an access chain.");
 
   Instruction* ptr_input =
       context()->get_def_use_mgr()->GetDef(inst->GetSingleWordInOperand(0));
-  if (ptr_input->opcode() != SpvOpAccessChain &&
-      ptr_input->opcode() != SpvOpInBoundsAccessChain &&
-      ptr_input->opcode() != SpvOpPtrAccessChain &&
-      ptr_input->opcode() != SpvOpInBoundsPtrAccessChain) {
+  if (ptr_input->opcode() != spv::Op::OpAccessChain &&
+      ptr_input->opcode() != spv::Op::OpInBoundsAccessChain &&
+      ptr_input->opcode() != spv::Op::OpPtrAccessChain &&
+      ptr_input->opcode() != spv::Op::OpInBoundsPtrAccessChain) {
     return false;
   }
 
@@ -246,7 +246,7 @@
   } else if (inst->NumInOperands() == 1) {
     // |inst| is a no-op, change it to a copy. Instruction simplification will
     // clean it up.
-    inst->SetOpcode(SpvOpCopyObject);
+    inst->SetOpcode(spv::Op::OpCopyObject);
   } else {
     std::vector<Operand> new_operands;
     if (!CreateNewInputOperands(ptr_input, inst, &new_operands)) return false;
@@ -259,23 +259,25 @@
   return true;
 }
 
-SpvOp CombineAccessChains::UpdateOpcode(SpvOp base_opcode, SpvOp input_opcode) {
-  auto IsInBounds = [](SpvOp opcode) {
-    return opcode == SpvOpInBoundsPtrAccessChain ||
-           opcode == SpvOpInBoundsAccessChain;
+spv::Op CombineAccessChains::UpdateOpcode(spv::Op base_opcode,
+                                          spv::Op input_opcode) {
+  auto IsInBounds = [](spv::Op opcode) {
+    return opcode == spv::Op::OpInBoundsPtrAccessChain ||
+           opcode == spv::Op::OpInBoundsAccessChain;
   };
 
-  if (input_opcode == SpvOpInBoundsPtrAccessChain) {
-    if (!IsInBounds(base_opcode)) return SpvOpPtrAccessChain;
-  } else if (input_opcode == SpvOpInBoundsAccessChain) {
-    if (!IsInBounds(base_opcode)) return SpvOpAccessChain;
+  if (input_opcode == spv::Op::OpInBoundsPtrAccessChain) {
+    if (!IsInBounds(base_opcode)) return spv::Op::OpPtrAccessChain;
+  } else if (input_opcode == spv::Op::OpInBoundsAccessChain) {
+    if (!IsInBounds(base_opcode)) return spv::Op::OpAccessChain;
   }
 
   return input_opcode;
 }
 
-bool CombineAccessChains::IsPtrAccessChain(SpvOp opcode) {
-  return opcode == SpvOpPtrAccessChain || opcode == SpvOpInBoundsPtrAccessChain;
+bool CombineAccessChains::IsPtrAccessChain(spv::Op opcode) {
+  return opcode == spv::Op::OpPtrAccessChain ||
+         opcode == spv::Op::OpInBoundsPtrAccessChain;
 }
 
 bool CombineAccessChains::Has64BitIndices(Instruction* inst) {
diff --git a/source/opt/combine_access_chains.h b/source/opt/combine_access_chains.h
index 531209e..32ee50d 100644
--- a/source/opt/combine_access_chains.h
+++ b/source/opt/combine_access_chains.h
@@ -68,10 +68,10 @@
                       std::vector<Operand>* new_operands);
 
   // Returns the opcode to use for the combined access chain.
-  SpvOp UpdateOpcode(SpvOp base_opcode, SpvOp input_opcode);
+  spv::Op UpdateOpcode(spv::Op base_opcode, spv::Op input_opcode);
 
   // Returns true if |opcode| is a pointer access chain.
-  bool IsPtrAccessChain(SpvOp opcode);
+  bool IsPtrAccessChain(spv::Op opcode);
 
   // Returns true if |inst| (an access chain) has 64-bit indices.
   bool Has64BitIndices(Instruction* inst);
diff --git a/source/opt/const_folding_rules.cpp b/source/opt/const_folding_rules.cpp
index 0ad755c..64475a6 100644
--- a/source/opt/const_folding_rules.cpp
+++ b/source/opt/const_folding_rules.cpp
@@ -124,7 +124,7 @@
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants)
              -> const analysis::Constant* {
-    assert(inst->opcode() == SpvOpVectorShuffle);
+    assert(inst->opcode() == spv::Op::OpVectorShuffle);
     const analysis::Constant* c1 = constants[0];
     const analysis::Constant* c2 = constants[1];
     if (c1 == nullptr || c2 == nullptr) {
@@ -180,7 +180,7 @@
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants)
              -> const analysis::Constant* {
-    assert(inst->opcode() == SpvOpVectorTimesScalar);
+    assert(inst->opcode() == spv::Op::OpVectorTimesScalar);
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
     analysis::TypeManager* type_mgr = context->get_type_mgr();
 
@@ -255,7 +255,7 @@
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants)
              -> const analysis::Constant* {
-    assert(inst->opcode() == SpvOpVectorTimesMatrix);
+    assert(inst->opcode() == spv::Op::OpVectorTimesMatrix);
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
     analysis::TypeManager* type_mgr = context->get_type_mgr();
 
@@ -348,7 +348,7 @@
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants)
              -> const analysis::Constant* {
-    assert(inst->opcode() == SpvOpMatrixTimesVector);
+    assert(inst->opcode() == spv::Op::OpMatrixTimesVector);
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
     analysis::TypeManager* type_mgr = context->get_type_mgr();
 
@@ -458,9 +458,9 @@
       }
 
       uint32_t component_type_id = 0;
-      if (type_inst->opcode() == SpvOpTypeStruct) {
+      if (type_inst->opcode() == spv::Op::OpTypeStruct) {
         component_type_id = type_inst->GetSingleWordInOperand(i);
-      } else if (type_inst->opcode() == SpvOpTypeArray) {
+      } else if (type_inst->opcode() == spv::Op::OpTypeArray) {
         component_type_id = type_inst->GetSingleWordInOperand(0);
       }
 
@@ -509,7 +509,7 @@
     }
 
     const analysis::Constant* arg =
-        (inst->opcode() == SpvOpExtInst) ? constants[1] : constants[0];
+        (inst->opcode() == spv::Op::OpExtInst) ? constants[1] : constants[0];
 
     if (arg == nullptr) {
       return nullptr;
@@ -599,7 +599,7 @@
     if (!inst->IsFloatingPointFoldingAllowed()) {
       return nullptr;
     }
-    if (inst->opcode() == SpvOpExtInst) {
+    if (inst->opcode() == spv::Op::OpExtInst) {
       return FoldFPBinaryOp(scalar_rule, inst->type_id(),
                             {constants[1], constants[2]}, context);
     }
@@ -957,7 +957,7 @@
 
 ConstantFoldingRule FoldFNegate() { return FoldFPUnaryOp(FoldFNegateOp()); }
 
-ConstantFoldingRule FoldFClampFeedingCompare(uint32_t cmp_opcode) {
+ConstantFoldingRule FoldFClampFeedingCompare(spv::Op cmp_opcode) {
   return [cmp_opcode](IRContext* context, Instruction* inst,
                       const std::vector<const analysis::Constant*>& constants)
              -> const analysis::Constant* {
@@ -985,7 +985,7 @@
       return nullptr;
     }
 
-    if (operand_inst->opcode() != SpvOpExtInst) {
+    if (operand_inst->opcode() != spv::Op::OpExtInst) {
       return nullptr;
     }
 
@@ -1009,25 +1009,25 @@
     bool result = false;
 
     switch (cmp_opcode) {
-      case SpvOpFOrdLessThan:
-      case SpvOpFUnordLessThan:
-      case SpvOpFOrdGreaterThanEqual:
-      case SpvOpFUnordGreaterThanEqual:
+      case spv::Op::OpFOrdLessThan:
+      case spv::Op::OpFUnordLessThan:
+      case spv::Op::OpFOrdGreaterThanEqual:
+      case spv::Op::OpFUnordGreaterThanEqual:
         if (constants[0]) {
           if (min_const) {
             if (constants[0]->GetValueAsDouble() <
                 min_const->GetValueAsDouble()) {
               found_result = true;
-              result = (cmp_opcode == SpvOpFOrdLessThan ||
-                        cmp_opcode == SpvOpFUnordLessThan);
+              result = (cmp_opcode == spv::Op::OpFOrdLessThan ||
+                        cmp_opcode == spv::Op::OpFUnordLessThan);
             }
           }
           if (max_const) {
             if (constants[0]->GetValueAsDouble() >=
                 max_const->GetValueAsDouble()) {
               found_result = true;
-              result = !(cmp_opcode == SpvOpFOrdLessThan ||
-                         cmp_opcode == SpvOpFUnordLessThan);
+              result = !(cmp_opcode == spv::Op::OpFOrdLessThan ||
+                         cmp_opcode == spv::Op::OpFUnordLessThan);
             }
           }
         }
@@ -1037,8 +1037,8 @@
             if (max_const->GetValueAsDouble() <
                 constants[1]->GetValueAsDouble()) {
               found_result = true;
-              result = (cmp_opcode == SpvOpFOrdLessThan ||
-                        cmp_opcode == SpvOpFUnordLessThan);
+              result = (cmp_opcode == spv::Op::OpFOrdLessThan ||
+                        cmp_opcode == spv::Op::OpFUnordLessThan);
             }
           }
 
@@ -1046,31 +1046,31 @@
             if (min_const->GetValueAsDouble() >=
                 constants[1]->GetValueAsDouble()) {
               found_result = true;
-              result = !(cmp_opcode == SpvOpFOrdLessThan ||
-                         cmp_opcode == SpvOpFUnordLessThan);
+              result = !(cmp_opcode == spv::Op::OpFOrdLessThan ||
+                         cmp_opcode == spv::Op::OpFUnordLessThan);
             }
           }
         }
         break;
-      case SpvOpFOrdGreaterThan:
-      case SpvOpFUnordGreaterThan:
-      case SpvOpFOrdLessThanEqual:
-      case SpvOpFUnordLessThanEqual:
+      case spv::Op::OpFOrdGreaterThan:
+      case spv::Op::OpFUnordGreaterThan:
+      case spv::Op::OpFOrdLessThanEqual:
+      case spv::Op::OpFUnordLessThanEqual:
         if (constants[0]) {
           if (min_const) {
             if (constants[0]->GetValueAsDouble() <=
                 min_const->GetValueAsDouble()) {
               found_result = true;
-              result = (cmp_opcode == SpvOpFOrdLessThanEqual ||
-                        cmp_opcode == SpvOpFUnordLessThanEqual);
+              result = (cmp_opcode == spv::Op::OpFOrdLessThanEqual ||
+                        cmp_opcode == spv::Op::OpFUnordLessThanEqual);
             }
           }
           if (max_const) {
             if (constants[0]->GetValueAsDouble() >
                 max_const->GetValueAsDouble()) {
               found_result = true;
-              result = !(cmp_opcode == SpvOpFOrdLessThanEqual ||
-                         cmp_opcode == SpvOpFUnordLessThanEqual);
+              result = !(cmp_opcode == spv::Op::OpFOrdLessThanEqual ||
+                         cmp_opcode == spv::Op::OpFUnordLessThanEqual);
             }
           }
         }
@@ -1080,8 +1080,8 @@
             if (max_const->GetValueAsDouble() <=
                 constants[1]->GetValueAsDouble()) {
               found_result = true;
-              result = (cmp_opcode == SpvOpFOrdLessThanEqual ||
-                        cmp_opcode == SpvOpFUnordLessThanEqual);
+              result = (cmp_opcode == spv::Op::OpFOrdLessThanEqual ||
+                        cmp_opcode == spv::Op::OpFUnordLessThanEqual);
             }
           }
 
@@ -1089,8 +1089,8 @@
             if (min_const->GetValueAsDouble() >
                 constants[1]->GetValueAsDouble()) {
               found_result = true;
-              result = !(cmp_opcode == SpvOpFOrdLessThanEqual ||
-                         cmp_opcode == SpvOpFUnordLessThanEqual);
+              result = !(cmp_opcode == spv::Op::OpFOrdLessThanEqual ||
+                         cmp_opcode == spv::Op::OpFUnordLessThanEqual);
             }
           }
         }
@@ -1117,7 +1117,7 @@
             const std::vector<const analysis::Constant*>& constants)
              -> const analysis::Constant* {
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
-    assert(inst->opcode() == SpvOpExtInst &&
+    assert(inst->opcode() == spv::Op::OpExtInst &&
            "Expecting an extended instruction.");
     assert(inst->GetSingleWordInOperand(0) ==
                context->get_feature_mgr()->GetExtInstImportId_GLSLstd450() &&
@@ -1267,7 +1267,7 @@
 const analysis::Constant* FoldClamp1(
     IRContext* context, Instruction* inst,
     const std::vector<const analysis::Constant*>& constants) {
-  assert(inst->opcode() == SpvOpExtInst &&
+  assert(inst->opcode() == spv::Op::OpExtInst &&
          "Expecting an extended instruction.");
   assert(inst->GetSingleWordInOperand(0) ==
              context->get_feature_mgr()->GetExtInstImportId_GLSLstd450() &&
@@ -1293,7 +1293,7 @@
 const analysis::Constant* FoldClamp2(
     IRContext* context, Instruction* inst,
     const std::vector<const analysis::Constant*>& constants) {
-  assert(inst->opcode() == SpvOpExtInst &&
+  assert(inst->opcode() == spv::Op::OpExtInst &&
          "Expecting an extended instruction.");
   assert(inst->GetSingleWordInOperand(0) ==
              context->get_feature_mgr()->GetExtInstImportId_GLSLstd450() &&
@@ -1321,7 +1321,7 @@
 const analysis::Constant* FoldClamp3(
     IRContext* context, Instruction* inst,
     const std::vector<const analysis::Constant*>& constants) {
-  assert(inst->opcode() == SpvOpExtInst &&
+  assert(inst->opcode() == spv::Op::OpExtInst &&
          "Expecting an extended instruction.");
   assert(inst->GetSingleWordInOperand(0) ==
              context->get_feature_mgr()->GetExtInstImportId_GLSLstd450() &&
@@ -1407,68 +1407,69 @@
   // applies to the instruction, the rest of the rules will not be attempted.
   // Take that into consideration.
 
-  rules_[SpvOpCompositeConstruct].push_back(FoldCompositeWithConstants());
+  rules_[spv::Op::OpCompositeConstruct].push_back(FoldCompositeWithConstants());
 
-  rules_[SpvOpCompositeExtract].push_back(FoldExtractWithConstants());
+  rules_[spv::Op::OpCompositeExtract].push_back(FoldExtractWithConstants());
 
-  rules_[SpvOpConvertFToS].push_back(FoldFToI());
-  rules_[SpvOpConvertFToU].push_back(FoldFToI());
-  rules_[SpvOpConvertSToF].push_back(FoldIToF());
-  rules_[SpvOpConvertUToF].push_back(FoldIToF());
+  rules_[spv::Op::OpConvertFToS].push_back(FoldFToI());
+  rules_[spv::Op::OpConvertFToU].push_back(FoldFToI());
+  rules_[spv::Op::OpConvertSToF].push_back(FoldIToF());
+  rules_[spv::Op::OpConvertUToF].push_back(FoldIToF());
 
-  rules_[SpvOpDot].push_back(FoldOpDotWithConstants());
-  rules_[SpvOpFAdd].push_back(FoldFAdd());
-  rules_[SpvOpFDiv].push_back(FoldFDiv());
-  rules_[SpvOpFMul].push_back(FoldFMul());
-  rules_[SpvOpFSub].push_back(FoldFSub());
+  rules_[spv::Op::OpDot].push_back(FoldOpDotWithConstants());
+  rules_[spv::Op::OpFAdd].push_back(FoldFAdd());
+  rules_[spv::Op::OpFDiv].push_back(FoldFDiv());
+  rules_[spv::Op::OpFMul].push_back(FoldFMul());
+  rules_[spv::Op::OpFSub].push_back(FoldFSub());
 
-  rules_[SpvOpFOrdEqual].push_back(FoldFOrdEqual());
+  rules_[spv::Op::OpFOrdEqual].push_back(FoldFOrdEqual());
 
-  rules_[SpvOpFUnordEqual].push_back(FoldFUnordEqual());
+  rules_[spv::Op::OpFUnordEqual].push_back(FoldFUnordEqual());
 
-  rules_[SpvOpFOrdNotEqual].push_back(FoldFOrdNotEqual());
+  rules_[spv::Op::OpFOrdNotEqual].push_back(FoldFOrdNotEqual());
 
-  rules_[SpvOpFUnordNotEqual].push_back(FoldFUnordNotEqual());
+  rules_[spv::Op::OpFUnordNotEqual].push_back(FoldFUnordNotEqual());
 
-  rules_[SpvOpFOrdLessThan].push_back(FoldFOrdLessThan());
-  rules_[SpvOpFOrdLessThan].push_back(
-      FoldFClampFeedingCompare(SpvOpFOrdLessThan));
+  rules_[spv::Op::OpFOrdLessThan].push_back(FoldFOrdLessThan());
+  rules_[spv::Op::OpFOrdLessThan].push_back(
+      FoldFClampFeedingCompare(spv::Op::OpFOrdLessThan));
 
-  rules_[SpvOpFUnordLessThan].push_back(FoldFUnordLessThan());
-  rules_[SpvOpFUnordLessThan].push_back(
-      FoldFClampFeedingCompare(SpvOpFUnordLessThan));
+  rules_[spv::Op::OpFUnordLessThan].push_back(FoldFUnordLessThan());
+  rules_[spv::Op::OpFUnordLessThan].push_back(
+      FoldFClampFeedingCompare(spv::Op::OpFUnordLessThan));
 
-  rules_[SpvOpFOrdGreaterThan].push_back(FoldFOrdGreaterThan());
-  rules_[SpvOpFOrdGreaterThan].push_back(
-      FoldFClampFeedingCompare(SpvOpFOrdGreaterThan));
+  rules_[spv::Op::OpFOrdGreaterThan].push_back(FoldFOrdGreaterThan());
+  rules_[spv::Op::OpFOrdGreaterThan].push_back(
+      FoldFClampFeedingCompare(spv::Op::OpFOrdGreaterThan));
 
-  rules_[SpvOpFUnordGreaterThan].push_back(FoldFUnordGreaterThan());
-  rules_[SpvOpFUnordGreaterThan].push_back(
-      FoldFClampFeedingCompare(SpvOpFUnordGreaterThan));
+  rules_[spv::Op::OpFUnordGreaterThan].push_back(FoldFUnordGreaterThan());
+  rules_[spv::Op::OpFUnordGreaterThan].push_back(
+      FoldFClampFeedingCompare(spv::Op::OpFUnordGreaterThan));
 
-  rules_[SpvOpFOrdLessThanEqual].push_back(FoldFOrdLessThanEqual());
-  rules_[SpvOpFOrdLessThanEqual].push_back(
-      FoldFClampFeedingCompare(SpvOpFOrdLessThanEqual));
+  rules_[spv::Op::OpFOrdLessThanEqual].push_back(FoldFOrdLessThanEqual());
+  rules_[spv::Op::OpFOrdLessThanEqual].push_back(
+      FoldFClampFeedingCompare(spv::Op::OpFOrdLessThanEqual));
 
-  rules_[SpvOpFUnordLessThanEqual].push_back(FoldFUnordLessThanEqual());
-  rules_[SpvOpFUnordLessThanEqual].push_back(
-      FoldFClampFeedingCompare(SpvOpFUnordLessThanEqual));
+  rules_[spv::Op::OpFUnordLessThanEqual].push_back(FoldFUnordLessThanEqual());
+  rules_[spv::Op::OpFUnordLessThanEqual].push_back(
+      FoldFClampFeedingCompare(spv::Op::OpFUnordLessThanEqual));
 
-  rules_[SpvOpFOrdGreaterThanEqual].push_back(FoldFOrdGreaterThanEqual());
-  rules_[SpvOpFOrdGreaterThanEqual].push_back(
-      FoldFClampFeedingCompare(SpvOpFOrdGreaterThanEqual));
+  rules_[spv::Op::OpFOrdGreaterThanEqual].push_back(FoldFOrdGreaterThanEqual());
+  rules_[spv::Op::OpFOrdGreaterThanEqual].push_back(
+      FoldFClampFeedingCompare(spv::Op::OpFOrdGreaterThanEqual));
 
-  rules_[SpvOpFUnordGreaterThanEqual].push_back(FoldFUnordGreaterThanEqual());
-  rules_[SpvOpFUnordGreaterThanEqual].push_back(
-      FoldFClampFeedingCompare(SpvOpFUnordGreaterThanEqual));
+  rules_[spv::Op::OpFUnordGreaterThanEqual].push_back(
+      FoldFUnordGreaterThanEqual());
+  rules_[spv::Op::OpFUnordGreaterThanEqual].push_back(
+      FoldFClampFeedingCompare(spv::Op::OpFUnordGreaterThanEqual));
 
-  rules_[SpvOpVectorShuffle].push_back(FoldVectorShuffleWithConstants());
-  rules_[SpvOpVectorTimesScalar].push_back(FoldVectorTimesScalar());
-  rules_[SpvOpVectorTimesMatrix].push_back(FoldVectorTimesMatrix());
-  rules_[SpvOpMatrixTimesVector].push_back(FoldMatrixTimesVector());
+  rules_[spv::Op::OpVectorShuffle].push_back(FoldVectorShuffleWithConstants());
+  rules_[spv::Op::OpVectorTimesScalar].push_back(FoldVectorTimesScalar());
+  rules_[spv::Op::OpVectorTimesMatrix].push_back(FoldVectorTimesMatrix());
+  rules_[spv::Op::OpMatrixTimesVector].push_back(FoldMatrixTimesVector());
 
-  rules_[SpvOpFNegate].push_back(FoldFNegate());
-  rules_[SpvOpQuantizeToF16].push_back(FoldQuantizeToF16());
+  rules_[spv::Op::OpFNegate].push_back(FoldFNegate());
+  rules_[spv::Op::OpQuantizeToF16].push_back(FoldQuantizeToF16());
 
   // Add rules for GLSLstd450
   FeatureManager* feature_manager = context_->get_feature_mgr();
diff --git a/source/opt/const_folding_rules.h b/source/opt/const_folding_rules.h
index 41ee2aa..fa34532 100644
--- a/source/opt/const_folding_rules.h
+++ b/source/opt/const_folding_rules.h
@@ -88,7 +88,7 @@
   // Returns true if there is at least 1 folding rule for |inst|.
   const std::vector<ConstantFoldingRule>& GetRulesForInstruction(
       const Instruction* inst) const {
-    if (inst->opcode() != SpvOpExtInst) {
+    if (inst->opcode() != spv::Op::OpExtInst) {
       auto it = rules_.find(inst->opcode());
       if (it != rules_.end()) {
         return it->second.value;
@@ -108,9 +108,15 @@
   virtual void AddFoldingRules();
 
  protected:
+  struct hasher {
+    size_t operator()(const spv::Op& op) const noexcept {
+      return std::hash<uint32_t>()(uint32_t(op));
+    }
+  };
+
   // |rules[opcode]| is the set of rules that can be applied to instructions
   // with |opcode| as the opcode.
-  std::unordered_map<uint32_t, Value> rules_;
+  std::unordered_map<spv::Op, Value, hasher> rules_;
 
   // The folding rules for extended instructions.
   std::map<Key, Value> ext_rules_;
diff --git a/source/opt/constants.cpp b/source/opt/constants.cpp
index bcff08c..9930b44 100644
--- a/source/opt/constants.cpp
+++ b/source/opt/constants.cpp
@@ -306,16 +306,16 @@
   switch (inst->opcode()) {
     // OpConstant{True|False} have the value embedded in the opcode. So they
     // are not handled by the for-loop above. Here we add the value explicitly.
-    case SpvOp::SpvOpConstantTrue:
+    case spv::Op::OpConstantTrue:
       literal_words_or_ids.push_back(true);
       break;
-    case SpvOp::SpvOpConstantFalse:
+    case spv::Op::OpConstantFalse:
       literal_words_or_ids.push_back(false);
       break;
-    case SpvOp::SpvOpConstantNull:
-    case SpvOp::SpvOpConstant:
-    case SpvOp::SpvOpConstantComposite:
-    case SpvOp::SpvOpSpecConstantComposite:
+    case spv::Op::OpConstantNull:
+    case spv::Op::OpConstant:
+    case spv::Op::OpConstantComposite:
+    case spv::Op::OpSpecConstantComposite:
       break;
     default:
       return nullptr;
@@ -329,22 +329,22 @@
   uint32_t type =
       (type_id == 0) ? context()->get_type_mgr()->GetId(c->type()) : type_id;
   if (c->AsNullConstant()) {
-    return MakeUnique<Instruction>(context(), SpvOp::SpvOpConstantNull, type,
-                                   id, std::initializer_list<Operand>{});
+    return MakeUnique<Instruction>(context(), spv::Op::OpConstantNull, type, id,
+                                   std::initializer_list<Operand>{});
   } else if (const BoolConstant* bc = c->AsBoolConstant()) {
     return MakeUnique<Instruction>(
         context(),
-        bc->value() ? SpvOp::SpvOpConstantTrue : SpvOp::SpvOpConstantFalse,
-        type, id, std::initializer_list<Operand>{});
+        bc->value() ? spv::Op::OpConstantTrue : spv::Op::OpConstantFalse, type,
+        id, std::initializer_list<Operand>{});
   } else if (const IntConstant* ic = c->AsIntConstant()) {
     return MakeUnique<Instruction>(
-        context(), SpvOp::SpvOpConstant, type, id,
+        context(), spv::Op::OpConstant, type, id,
         std::initializer_list<Operand>{
             Operand(spv_operand_type_t::SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER,
                     ic->words())});
   } else if (const FloatConstant* fc = c->AsFloatConstant()) {
     return MakeUnique<Instruction>(
-        context(), SpvOp::SpvOpConstant, type, id,
+        context(), spv::Op::OpConstant, type, id,
         std::initializer_list<Operand>{
             Operand(spv_operand_type_t::SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER,
                     fc->words())});
@@ -362,9 +362,9 @@
   uint32_t component_index = 0;
   for (const Constant* component_const : cc->GetComponents()) {
     uint32_t component_type_id = 0;
-    if (type_inst && type_inst->opcode() == SpvOpTypeStruct) {
+    if (type_inst && type_inst->opcode() == spv::Op::OpTypeStruct) {
       component_type_id = type_inst->GetSingleWordInOperand(component_index);
-    } else if (type_inst && type_inst->opcode() == SpvOpTypeArray) {
+    } else if (type_inst && type_inst->opcode() == spv::Op::OpTypeArray) {
       component_type_id = type_inst->GetSingleWordInOperand(0);
     }
     uint32_t id = FindDeclaredConstant(component_const, component_type_id);
@@ -381,7 +381,7 @@
   }
   uint32_t type =
       (type_id == 0) ? context()->get_type_mgr()->GetId(cc->type()) : type_id;
-  return MakeUnique<Instruction>(context(), SpvOp::SpvOpConstantComposite, type,
+  return MakeUnique<Instruction>(context(), spv::Op::OpConstantComposite, type,
                                  result_id, std::move(operands));
 }
 
diff --git a/source/opt/control_dependence.cpp b/source/opt/control_dependence.cpp
index f4879e0..a153cab 100644
--- a/source/opt/control_dependence.cpp
+++ b/source/opt/control_dependence.cpp
@@ -24,7 +24,6 @@
 #include "source/opt/dominator_analysis.h"
 #include "source/opt/function.h"
 #include "source/opt/instruction.h"
-#include "spirv/unified1/spirv.h"
 
 // Computes the control dependence graph (CDG) using the algorithm in Cytron
 // 1991, "Efficiently Computing Static Single Assignment Form and the Control
@@ -49,8 +48,8 @@
   }
   const BasicBlock* source_bb = cfg.block(source_bb_id());
   const Instruction* branch = source_bb->terminator();
-  assert((branch->opcode() == SpvOpBranchConditional ||
-          branch->opcode() == SpvOpSwitch) &&
+  assert((branch->opcode() == spv::Op::OpBranchConditional ||
+          branch->opcode() == spv::Op::OpSwitch) &&
          "invalid control dependence; last instruction must be conditional "
          "branch or switch");
   return branch->GetSingleWordInOperand(0);
diff --git a/source/opt/convert_to_half_pass.cpp b/source/opt/convert_to_half_pass.cpp
index 4086e31..70a8d7d 100644
--- a/source/opt/convert_to_half_pass.cpp
+++ b/source/opt/convert_to_half_pass.cpp
@@ -30,7 +30,7 @@
 
 bool ConvertToHalfPass::IsArithmetic(Instruction* inst) {
   return target_ops_core_.count(inst->opcode()) != 0 ||
-         (inst->opcode() == SpvOpExtInst &&
+         (inst->opcode() == spv::Op::OpExtInst &&
           inst->GetSingleWordInOperand(0) ==
               context()->get_feature_mgr()->GetExtInstImportId_GLSLstd450() &&
           target_ops_450_.count(inst->GetSingleWordInOperand(1)) != 0);
@@ -45,9 +45,11 @@
 bool ConvertToHalfPass::IsDecoratedRelaxed(Instruction* inst) {
   uint32_t r_id = inst->result_id();
   for (auto r_inst : get_decoration_mgr()->GetDecorationsFor(r_id, false))
-    if (r_inst->opcode() == SpvOpDecorate &&
-        r_inst->GetSingleWordInOperand(1) == SpvDecorationRelaxedPrecision)
+    if (r_inst->opcode() == spv::Op::OpDecorate &&
+        spv::Decoration(r_inst->GetSingleWordInOperand(1)) ==
+            spv::Decoration::RelaxedPrecision) {
       return true;
+    }
   return false;
 }
 
@@ -82,12 +84,12 @@
 uint32_t ConvertToHalfPass::EquivFloatTypeId(uint32_t ty_id, uint32_t width) {
   analysis::Type* reg_equiv_ty;
   Instruction* ty_inst = get_def_use_mgr()->GetDef(ty_id);
-  if (ty_inst->opcode() == SpvOpTypeMatrix)
+  if (ty_inst->opcode() == spv::Op::OpTypeMatrix)
     reg_equiv_ty = FloatMatrixType(ty_inst->GetSingleWordInOperand(1),
                                    ty_inst->GetSingleWordInOperand(0), width);
-  else if (ty_inst->opcode() == SpvOpTypeVector)
+  else if (ty_inst->opcode() == spv::Op::OpTypeVector)
     reg_equiv_ty = FloatVectorType(ty_inst->GetSingleWordInOperand(1), width);
-  else  // SpvOpTypeFloat
+  else  // spv::Op::OpTypeFloat
     reg_equiv_ty = FloatScalarType(width);
   return context()->get_type_mgr()->GetTypeInstruction(reg_equiv_ty);
 }
@@ -102,18 +104,18 @@
   InstructionBuilder builder(
       context(), inst,
       IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
-  if (val_inst->opcode() == SpvOpUndef)
-    cvt_inst = builder.AddNullaryOp(nty_id, SpvOpUndef);
+  if (val_inst->opcode() == spv::Op::OpUndef)
+    cvt_inst = builder.AddNullaryOp(nty_id, spv::Op::OpUndef);
   else
-    cvt_inst = builder.AddUnaryOp(nty_id, SpvOpFConvert, *val_idp);
+    cvt_inst = builder.AddUnaryOp(nty_id, spv::Op::OpFConvert, *val_idp);
   *val_idp = cvt_inst->result_id();
 }
 
 bool ConvertToHalfPass::MatConvertCleanup(Instruction* inst) {
-  if (inst->opcode() != SpvOpFConvert) return false;
+  if (inst->opcode() != spv::Op::OpFConvert) return false;
   uint32_t mty_id = inst->type_id();
   Instruction* mty_inst = get_def_use_mgr()->GetDef(mty_id);
-  if (mty_inst->opcode() != SpvOpTypeMatrix) return false;
+  if (mty_inst->opcode() != spv::Op::OpTypeMatrix) return false;
   uint32_t vty_id = mty_inst->GetSingleWordInOperand(0);
   uint32_t v_cnt = mty_inst->GetSingleWordInOperand(1);
   Instruction* vty_inst = get_def_use_mgr()->GetDef(vty_id);
@@ -130,18 +132,18 @@
   std::vector<Operand> opnds = {};
   for (uint32_t vidx = 0; vidx < v_cnt; ++vidx) {
     Instruction* ext_inst = builder.AddIdLiteralOp(
-        orig_vty_id, SpvOpCompositeExtract, orig_mat_id, vidx);
+        orig_vty_id, spv::Op::OpCompositeExtract, orig_mat_id, vidx);
     Instruction* cvt_inst =
-        builder.AddUnaryOp(vty_id, SpvOpFConvert, ext_inst->result_id());
+        builder.AddUnaryOp(vty_id, spv::Op::OpFConvert, ext_inst->result_id());
     opnds.push_back({SPV_OPERAND_TYPE_ID, {cvt_inst->result_id()}});
   }
   uint32_t mat_id = TakeNextId();
   std::unique_ptr<Instruction> mat_inst(new Instruction(
-      context(), SpvOpCompositeConstruct, mty_id, mat_id, opnds));
+      context(), spv::Op::OpCompositeConstruct, mty_id, mat_id, opnds));
   (void)builder.AddInstruction(std::move(mat_inst));
   context()->ReplaceAllUsesWith(inst->result_id(), mat_id);
   // Turn original instruction into copy so it is valid.
-  inst->SetOpcode(SpvOpCopyObject);
+  inst->SetOpcode(spv::Op::OpCopyObject);
   inst->SetResultType(EquivFloatTypeId(mty_id, orig_width));
   get_def_use_mgr()->AnalyzeInstUse(inst);
   return true;
@@ -150,10 +152,11 @@
 bool ConvertToHalfPass::RemoveRelaxedDecoration(uint32_t id) {
   return context()->get_decoration_mgr()->RemoveDecorationsFrom(
       id, [](const Instruction& dec) {
-        if (dec.opcode() == SpvOpDecorate &&
-            dec.GetSingleWordInOperand(1u) == SpvDecorationRelaxedPrecision)
+        if (dec.opcode() == spv::Op::OpDecorate &&
+            spv::Decoration(dec.GetSingleWordInOperand(1u)) ==
+                spv::Decoration::RelaxedPrecision) {
           return true;
-        else
+        } else
           return false;
       });
 }
@@ -196,8 +199,8 @@
         auto insert_before = bp->tail();
         if (insert_before != bp->begin()) {
           --insert_before;
-          if (insert_before->opcode() != SpvOpSelectionMerge &&
-              insert_before->opcode() != SpvOpLoopMerge)
+          if (insert_before->opcode() != spv::Op::OpSelectionMerge &&
+              insert_before->opcode() != spv::Op::OpLoopMerge)
             ++insert_before;
         }
         GenConvert(prev_idp, to_width, &*insert_before);
@@ -229,7 +232,8 @@
   // changed to half.
   uint32_t val_id = inst->GetSingleWordInOperand(0);
   Instruction* val_inst = get_def_use_mgr()->GetDef(val_id);
-  if (inst->type_id() == val_inst->type_id()) inst->SetOpcode(SpvOpCopyObject);
+  if (inst->type_id() == val_inst->type_id())
+    inst->SetOpcode(spv::Op::OpCopyObject);
   return true;  // modified
 }
 
@@ -251,7 +255,7 @@
 bool ConvertToHalfPass::ProcessDefault(Instruction* inst) {
   // If non-relaxed instruction has changed operands, need to convert
   // them back to float32
-  if (inst->opcode() == SpvOpPhi) return ProcessPhi(inst, 16u, 32u);
+  if (inst->opcode() == spv::Op::OpPhi) return ProcessPhi(inst, 16u, 32u);
   bool modified = false;
   inst->ForEachInId([&inst, &modified, this](uint32_t* idp) {
     if (converted_ids_.count(*idp) == 0) return;
@@ -269,9 +273,9 @@
   bool inst_relaxed = IsRelaxed(inst->result_id());
   if (IsArithmetic(inst) && inst_relaxed)
     modified = GenHalfArith(inst);
-  else if (inst->opcode() == SpvOpPhi && inst_relaxed)
+  else if (inst->opcode() == spv::Op::OpPhi && inst_relaxed)
     modified = ProcessPhi(inst, 32u, 16u);
-  else if (inst->opcode() == SpvOpFConvert)
+  else if (inst->opcode() == spv::Op::OpFConvert)
     modified = ProcessConvert(inst);
   else if (image_ops_.count(inst->opcode()) != 0)
     modified = ProcessImageRef(inst);
@@ -350,7 +354,7 @@
   };
   bool modified = context()->ProcessReachableCallTree(pfn);
   // If modified, make sure module has Float16 capability
-  if (modified) context()->AddCapability(SpvCapabilityFloat16);
+  if (modified) context()->AddCapability(spv::Capability::Float16);
   // Remove all RelaxedPrecision decorations from instructions and globals
   for (auto c_id : relaxed_ids_set_) {
     modified |= RemoveRelaxedDecoration(c_id);
@@ -371,44 +375,44 @@
 
 void ConvertToHalfPass::Initialize() {
   target_ops_core_ = {
-      SpvOpVectorExtractDynamic,
-      SpvOpVectorInsertDynamic,
-      SpvOpVectorShuffle,
-      SpvOpCompositeConstruct,
-      SpvOpCompositeInsert,
-      SpvOpCompositeExtract,
-      SpvOpCopyObject,
-      SpvOpTranspose,
-      SpvOpConvertSToF,
-      SpvOpConvertUToF,
-      // SpvOpFConvert,
-      // SpvOpQuantizeToF16,
-      SpvOpFNegate,
-      SpvOpFAdd,
-      SpvOpFSub,
-      SpvOpFMul,
-      SpvOpFDiv,
-      SpvOpFMod,
-      SpvOpVectorTimesScalar,
-      SpvOpMatrixTimesScalar,
-      SpvOpVectorTimesMatrix,
-      SpvOpMatrixTimesVector,
-      SpvOpMatrixTimesMatrix,
-      SpvOpOuterProduct,
-      SpvOpDot,
-      SpvOpSelect,
-      SpvOpFOrdEqual,
-      SpvOpFUnordEqual,
-      SpvOpFOrdNotEqual,
-      SpvOpFUnordNotEqual,
-      SpvOpFOrdLessThan,
-      SpvOpFUnordLessThan,
-      SpvOpFOrdGreaterThan,
-      SpvOpFUnordGreaterThan,
-      SpvOpFOrdLessThanEqual,
-      SpvOpFUnordLessThanEqual,
-      SpvOpFOrdGreaterThanEqual,
-      SpvOpFUnordGreaterThanEqual,
+      spv::Op::OpVectorExtractDynamic,
+      spv::Op::OpVectorInsertDynamic,
+      spv::Op::OpVectorShuffle,
+      spv::Op::OpCompositeConstruct,
+      spv::Op::OpCompositeInsert,
+      spv::Op::OpCompositeExtract,
+      spv::Op::OpCopyObject,
+      spv::Op::OpTranspose,
+      spv::Op::OpConvertSToF,
+      spv::Op::OpConvertUToF,
+      // spv::Op::OpFConvert,
+      // spv::Op::OpQuantizeToF16,
+      spv::Op::OpFNegate,
+      spv::Op::OpFAdd,
+      spv::Op::OpFSub,
+      spv::Op::OpFMul,
+      spv::Op::OpFDiv,
+      spv::Op::OpFMod,
+      spv::Op::OpVectorTimesScalar,
+      spv::Op::OpMatrixTimesScalar,
+      spv::Op::OpVectorTimesMatrix,
+      spv::Op::OpMatrixTimesVector,
+      spv::Op::OpMatrixTimesMatrix,
+      spv::Op::OpOuterProduct,
+      spv::Op::OpDot,
+      spv::Op::OpSelect,
+      spv::Op::OpFOrdEqual,
+      spv::Op::OpFUnordEqual,
+      spv::Op::OpFOrdNotEqual,
+      spv::Op::OpFUnordNotEqual,
+      spv::Op::OpFOrdLessThan,
+      spv::Op::OpFUnordLessThan,
+      spv::Op::OpFOrdGreaterThan,
+      spv::Op::OpFUnordGreaterThan,
+      spv::Op::OpFOrdLessThanEqual,
+      spv::Op::OpFUnordLessThanEqual,
+      spv::Op::OpFOrdGreaterThanEqual,
+      spv::Op::OpFUnordGreaterThanEqual,
   };
   target_ops_450_ = {
       GLSLstd450Round, GLSLstd450RoundEven, GLSLstd450Trunc, GLSLstd450FAbs,
@@ -427,53 +431,53 @@
       GLSLstd450Ldexp, GLSLstd450Length, GLSLstd450Distance, GLSLstd450Cross,
       GLSLstd450Normalize, GLSLstd450FaceForward, GLSLstd450Reflect,
       GLSLstd450Refract, GLSLstd450NMin, GLSLstd450NMax, GLSLstd450NClamp};
-  image_ops_ = {SpvOpImageSampleImplicitLod,
-                SpvOpImageSampleExplicitLod,
-                SpvOpImageSampleDrefImplicitLod,
-                SpvOpImageSampleDrefExplicitLod,
-                SpvOpImageSampleProjImplicitLod,
-                SpvOpImageSampleProjExplicitLod,
-                SpvOpImageSampleProjDrefImplicitLod,
-                SpvOpImageSampleProjDrefExplicitLod,
-                SpvOpImageFetch,
-                SpvOpImageGather,
-                SpvOpImageDrefGather,
-                SpvOpImageRead,
-                SpvOpImageSparseSampleImplicitLod,
-                SpvOpImageSparseSampleExplicitLod,
-                SpvOpImageSparseSampleDrefImplicitLod,
-                SpvOpImageSparseSampleDrefExplicitLod,
-                SpvOpImageSparseSampleProjImplicitLod,
-                SpvOpImageSparseSampleProjExplicitLod,
-                SpvOpImageSparseSampleProjDrefImplicitLod,
-                SpvOpImageSparseSampleProjDrefExplicitLod,
-                SpvOpImageSparseFetch,
-                SpvOpImageSparseGather,
-                SpvOpImageSparseDrefGather,
-                SpvOpImageSparseTexelsResident,
-                SpvOpImageSparseRead};
+  image_ops_ = {spv::Op::OpImageSampleImplicitLod,
+                spv::Op::OpImageSampleExplicitLod,
+                spv::Op::OpImageSampleDrefImplicitLod,
+                spv::Op::OpImageSampleDrefExplicitLod,
+                spv::Op::OpImageSampleProjImplicitLod,
+                spv::Op::OpImageSampleProjExplicitLod,
+                spv::Op::OpImageSampleProjDrefImplicitLod,
+                spv::Op::OpImageSampleProjDrefExplicitLod,
+                spv::Op::OpImageFetch,
+                spv::Op::OpImageGather,
+                spv::Op::OpImageDrefGather,
+                spv::Op::OpImageRead,
+                spv::Op::OpImageSparseSampleImplicitLod,
+                spv::Op::OpImageSparseSampleExplicitLod,
+                spv::Op::OpImageSparseSampleDrefImplicitLod,
+                spv::Op::OpImageSparseSampleDrefExplicitLod,
+                spv::Op::OpImageSparseSampleProjImplicitLod,
+                spv::Op::OpImageSparseSampleProjExplicitLod,
+                spv::Op::OpImageSparseSampleProjDrefImplicitLod,
+                spv::Op::OpImageSparseSampleProjDrefExplicitLod,
+                spv::Op::OpImageSparseFetch,
+                spv::Op::OpImageSparseGather,
+                spv::Op::OpImageSparseDrefGather,
+                spv::Op::OpImageSparseTexelsResident,
+                spv::Op::OpImageSparseRead};
   dref_image_ops_ = {
-      SpvOpImageSampleDrefImplicitLod,
-      SpvOpImageSampleDrefExplicitLod,
-      SpvOpImageSampleProjDrefImplicitLod,
-      SpvOpImageSampleProjDrefExplicitLod,
-      SpvOpImageDrefGather,
-      SpvOpImageSparseSampleDrefImplicitLod,
-      SpvOpImageSparseSampleDrefExplicitLod,
-      SpvOpImageSparseSampleProjDrefImplicitLod,
-      SpvOpImageSparseSampleProjDrefExplicitLod,
-      SpvOpImageSparseDrefGather,
+      spv::Op::OpImageSampleDrefImplicitLod,
+      spv::Op::OpImageSampleDrefExplicitLod,
+      spv::Op::OpImageSampleProjDrefImplicitLod,
+      spv::Op::OpImageSampleProjDrefExplicitLod,
+      spv::Op::OpImageDrefGather,
+      spv::Op::OpImageSparseSampleDrefImplicitLod,
+      spv::Op::OpImageSparseSampleDrefExplicitLod,
+      spv::Op::OpImageSparseSampleProjDrefImplicitLod,
+      spv::Op::OpImageSparseSampleProjDrefExplicitLod,
+      spv::Op::OpImageSparseDrefGather,
   };
   closure_ops_ = {
-      SpvOpVectorExtractDynamic,
-      SpvOpVectorInsertDynamic,
-      SpvOpVectorShuffle,
-      SpvOpCompositeConstruct,
-      SpvOpCompositeInsert,
-      SpvOpCompositeExtract,
-      SpvOpCopyObject,
-      SpvOpTranspose,
-      SpvOpPhi,
+      spv::Op::OpVectorExtractDynamic,
+      spv::Op::OpVectorInsertDynamic,
+      spv::Op::OpVectorShuffle,
+      spv::Op::OpCompositeConstruct,
+      spv::Op::OpCompositeInsert,
+      spv::Op::OpCompositeExtract,
+      spv::Op::OpCopyObject,
+      spv::Op::OpTranspose,
+      spv::Op::OpPhi,
   };
   relaxed_ids_set_.clear();
   converted_ids_.clear();
diff --git a/source/opt/convert_to_half_pass.h b/source/opt/convert_to_half_pass.h
index c6e84d1..feabfba 100644
--- a/source/opt/convert_to_half_pass.h
+++ b/source/opt/convert_to_half_pass.h
@@ -120,20 +120,26 @@
   // Initialize state for converting to half
   void Initialize();
 
+  struct hasher {
+    size_t operator()(const spv::Op& op) const noexcept {
+      return std::hash<uint32_t>()(uint32_t(op));
+    }
+  };
+
   // Set of core operations to be processed
-  std::unordered_set<uint32_t> target_ops_core_;
+  std::unordered_set<spv::Op, hasher> target_ops_core_;
 
   // Set of 450 extension operations to be processed
   std::unordered_set<uint32_t> target_ops_450_;
 
   // Set of sample operations
-  std::unordered_set<uint32_t> image_ops_;
+  std::unordered_set<spv::Op, hasher> image_ops_;
 
   // Set of dref sample operations
-  std::unordered_set<uint32_t> dref_image_ops_;
+  std::unordered_set<spv::Op, hasher> dref_image_ops_;
 
   // Set of dref sample operations
-  std::unordered_set<uint32_t> closure_ops_;
+  std::unordered_set<spv::Op, hasher> closure_ops_;
 
   // Set of ids of all relaxed instructions
   std::unordered_set<uint32_t> relaxed_ids_set_;
diff --git a/source/opt/convert_to_sampled_image_pass.cpp b/source/opt/convert_to_sampled_image_pass.cpp
index e84d357..2effc3e 100644
--- a/source/opt/convert_to_sampled_image_pass.cpp
+++ b/source/opt/convert_to_sampled_image_pass.cpp
@@ -70,7 +70,7 @@
 Instruction* GetNonCopyObjectDef(analysis::DefUseManager* def_use_mgr,
                                  uint32_t inst_id) {
   Instruction* inst = def_use_mgr->GetDef(inst_id);
-  while (inst->opcode() == SpvOpCopyObject) {
+  while (inst->opcode() == spv::Op::OpCopyObject) {
     inst_id = inst->GetSingleWordInOperand(0u);
     inst = def_use_mgr->GetDef(inst_id);
   }
@@ -87,8 +87,9 @@
   bool found_binding_to_convert = false;
   for (auto decorate :
        decoration_manager->GetDecorationsFor(inst.result_id(), false)) {
-    uint32_t decoration = decorate->GetSingleWordInOperand(1u);
-    if (decoration == SpvDecorationDescriptorSet) {
+    spv::Decoration decoration =
+        spv::Decoration(decorate->GetSingleWordInOperand(1u));
+    if (decoration == spv::Decoration::DescriptorSet) {
       if (found_descriptor_set_to_convert) {
         assert(false && "A resource has two OpDecorate for the descriptor set");
         return false;
@@ -96,7 +97,7 @@
       descriptor_set_binding->descriptor_set =
           decorate->GetSingleWordInOperand(2u);
       found_descriptor_set_to_convert = true;
-    } else if (decoration == SpvDecorationBinding) {
+    } else if (decoration == spv::Decoration::Binding) {
       if (found_binding_to_convert) {
         assert(false && "A resource has two OpDecorate for the binding");
         return false;
@@ -116,7 +117,7 @@
 
 const analysis::Type* ConvertToSampledImagePass::GetVariableType(
     const Instruction& variable) const {
-  if (variable.opcode() != SpvOpVariable) return nullptr;
+  if (variable.opcode() != spv::Op::OpVariable) return nullptr;
   auto* type = context()->get_type_mgr()->GetType(variable.type_id());
   auto* pointer_type = type->AsPointer();
   if (!pointer_type) return nullptr;
@@ -124,12 +125,12 @@
   return pointer_type->pointee_type();
 }
 
-SpvStorageClass ConvertToSampledImagePass::GetStorageClass(
+spv::StorageClass ConvertToSampledImagePass::GetStorageClass(
     const Instruction& variable) const {
-  assert(variable.opcode() == SpvOpVariable);
+  assert(variable.opcode() == spv::Op::OpVariable);
   auto* type = context()->get_type_mgr()->GetType(variable.type_id());
   auto* pointer_type = type->AsPointer();
-  if (!pointer_type) return SpvStorageClassMax;
+  if (!pointer_type) return spv::StorageClass::Max;
 
   return pointer_type->storage_class();
 }
@@ -205,12 +206,12 @@
 
 void ConvertToSampledImagePass::FindUses(const Instruction* inst,
                                          std::vector<Instruction*>* uses,
-                                         uint32_t user_opcode) const {
+                                         spv::Op user_opcode) const {
   auto* def_use_mgr = context()->get_def_use_mgr();
   def_use_mgr->ForEachUser(inst, [uses, user_opcode, this](Instruction* user) {
     if (user->opcode() == user_opcode) {
       uses->push_back(user);
-    } else if (user->opcode() == SpvOpCopyObject) {
+    } else if (user->opcode() == spv::Op::OpCopyObject) {
       FindUses(user, uses, user_opcode);
     }
   });
@@ -221,21 +222,21 @@
   auto* def_use_mgr = context()->get_def_use_mgr();
   def_use_mgr->ForEachUser(image, [uses, this](Instruction* user) {
     switch (user->opcode()) {
-      case SpvOpImageFetch:
-      case SpvOpImageRead:
-      case SpvOpImageWrite:
-      case SpvOpImageQueryFormat:
-      case SpvOpImageQueryOrder:
-      case SpvOpImageQuerySizeLod:
-      case SpvOpImageQuerySize:
-      case SpvOpImageQueryLevels:
-      case SpvOpImageQuerySamples:
-      case SpvOpImageSparseFetch:
+      case spv::Op::OpImageFetch:
+      case spv::Op::OpImageRead:
+      case spv::Op::OpImageWrite:
+      case spv::Op::OpImageQueryFormat:
+      case spv::Op::OpImageQueryOrder:
+      case spv::Op::OpImageQuerySizeLod:
+      case spv::Op::OpImageQuerySize:
+      case spv::Op::OpImageQueryLevels:
+      case spv::Op::OpImageQuerySamples:
+      case spv::Op::OpImageSparseFetch:
         uses->push_back(user);
       default:
         break;
     }
-    if (user->opcode() == SpvOpCopyObject) {
+    if (user->opcode() == spv::Op::OpCopyObject) {
       FindUsesOfImage(user, uses);
     }
   });
@@ -248,7 +249,7 @@
       IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
   return builder.AddUnaryOp(
       GetImageTypeOfSampledImage(context()->get_type_mgr(), sampled_image),
-      SpvOpImage, sampled_image->result_id());
+      spv::Op::OpImage, sampled_image->result_id());
 }
 
 uint32_t ConvertToSampledImagePass::GetSampledImageTypeForImage(
@@ -284,7 +285,7 @@
   auto* def_use_mgr = context()->get_def_use_mgr();
   uint32_t sampler_id = sampled_image_inst->GetSingleWordInOperand(1u);
   auto* sampler_load = def_use_mgr->GetDef(sampler_id);
-  if (sampler_load->opcode() != SpvOpLoad) return false;
+  if (sampler_load->opcode() != spv::Op::OpLoad) return false;
   auto* sampler = def_use_mgr->GetDef(sampler_load->GetSingleWordInOperand(0u));
   DescriptorSetAndBinding sampler_descriptor_set_binding;
   return GetDescriptorSetBinding(*sampler, &sampler_descriptor_set_binding) &&
@@ -295,7 +296,7 @@
     Instruction* image_load, Instruction* image_extraction,
     const DescriptorSetAndBinding& image_descriptor_set_binding) {
   std::vector<Instruction*> sampled_image_users;
-  FindUses(image_load, &sampled_image_users, SpvOpSampledImage);
+  FindUses(image_load, &sampled_image_users, spv::Op::OpSampledImage);
 
   auto* def_use_mgr = context()->get_def_use_mgr();
   for (auto* sampled_image_inst : sampled_image_users) {
@@ -328,7 +329,7 @@
       context()->get_type_mgr()->GetType(sampled_image_type_id);
   if (sampled_image_type == nullptr) return false;
   auto storage_class = GetStorageClass(*image_variable);
-  if (storage_class == SpvStorageClassMax) return false;
+  if (storage_class == spv::StorageClass::Max) return false;
   analysis::Pointer sampled_image_pointer(sampled_image_type, storage_class);
 
   // Make sure |image_variable| is behind its type i.e., avoid the forward
@@ -343,7 +344,7 @@
     Instruction* image_variable,
     const DescriptorSetAndBinding& descriptor_set_binding) {
   std::vector<Instruction*> image_variable_loads;
-  FindUses(image_variable, &image_variable_loads, SpvOpLoad);
+  FindUses(image_variable, &image_variable_loads, spv::Op::OpLoad);
   if (image_variable_loads.empty()) return Status::SuccessWithoutChange;
 
   const uint32_t sampled_image_type_id =
@@ -364,14 +365,14 @@
 
 bool ConvertToSampledImagePass::DoesSampledImageReferenceImage(
     Instruction* sampled_image_inst, Instruction* image_variable) {
-  if (sampled_image_inst->opcode() != SpvOpSampledImage) return false;
+  if (sampled_image_inst->opcode() != spv::Op::OpSampledImage) return false;
   auto* def_use_mgr = context()->get_def_use_mgr();
   auto* image_load = GetNonCopyObjectDef(
       def_use_mgr, sampled_image_inst->GetSingleWordInOperand(0u));
-  if (image_load->opcode() != SpvOpLoad) return false;
+  if (image_load->opcode() != spv::Op::OpLoad) return false;
   auto* image =
       GetNonCopyObjectDef(def_use_mgr, image_load->GetSingleWordInOperand(0u));
-  return image->opcode() == SpvOpVariable &&
+  return image->opcode() == spv::Op::OpVariable &&
          image->result_id() == image_variable->result_id();
 }
 
@@ -381,10 +382,10 @@
   if (image_to_be_combined_with == nullptr) return Status::Failure;
 
   std::vector<Instruction*> sampler_variable_loads;
-  FindUses(sampler_variable, &sampler_variable_loads, SpvOpLoad);
+  FindUses(sampler_variable, &sampler_variable_loads, spv::Op::OpLoad);
   for (auto* load : sampler_variable_loads) {
     std::vector<Instruction*> sampled_image_users;
-    FindUses(load, &sampled_image_users, SpvOpSampledImage);
+    FindUses(load, &sampled_image_users, spv::Op::OpSampledImage);
     for (auto* sampled_image_inst : sampled_image_users) {
       if (!DoesSampledImageReferenceImage(sampled_image_inst,
                                           image_to_be_combined_with)) {
diff --git a/source/opt/convert_to_sampled_image_pass.h b/source/opt/convert_to_sampled_image_pass.h
index d3938af..a8b1501 100644
--- a/source/opt/convert_to_sampled_image_pass.h
+++ b/source/opt/convert_to_sampled_image_pass.h
@@ -120,13 +120,13 @@
   const analysis::Type* GetVariableType(const Instruction& variable) const;
 
   // Returns the storage class of |variable|.
-  SpvStorageClass GetStorageClass(const Instruction& variable) const;
+  spv::StorageClass GetStorageClass(const Instruction& variable) const;
 
   // Finds |inst|'s users whose opcode is |user_opcode| or users of OpCopyObject
   // instructions of |inst| whose opcode is |user_opcode| and puts them in
   // |uses|.
   void FindUses(const Instruction* inst, std::vector<Instruction*>* uses,
-                uint32_t user_opcode) const;
+                spv::Op user_opcode) const;
 
   // Finds OpImage* instructions using |image| or OpCopyObject instructions that
   // copy |image| and puts them in |uses|.
diff --git a/source/opt/copy_prop_arrays.cpp b/source/opt/copy_prop_arrays.cpp
index 0b23562..9afbb1a 100644
--- a/source/opt/copy_prop_arrays.cpp
+++ b/source/opt/copy_prop_arrays.cpp
@@ -46,8 +46,8 @@
 
     BasicBlock* entry_bb = &*function.begin();
 
-    for (auto var_inst = entry_bb->begin(); var_inst->opcode() == SpvOpVariable;
-         ++var_inst) {
+    for (auto var_inst = entry_bb->begin();
+         var_inst->opcode() == spv::Op::OpVariable; ++var_inst) {
       if (!IsPointerToArrayType(var_inst->type_id())) {
         continue;
       }
@@ -76,7 +76,7 @@
 std::unique_ptr<CopyPropagateArrays::MemoryObject>
 CopyPropagateArrays::FindSourceObjectIfPossible(Instruction* var_inst,
                                                 Instruction* store_inst) {
-  assert(var_inst->opcode() == SpvOpVariable && "Expecting a variable.");
+  assert(var_inst->opcode() == spv::Op::OpVariable && "Expecting a variable.");
 
   // Check that the variable is a composite object where |store_inst|
   // dominates all of its loads.
@@ -114,7 +114,7 @@
   Instruction* store_inst = nullptr;
   get_def_use_mgr()->WhileEachUser(
       var_inst, [&store_inst, var_inst](Instruction* use) {
-        if (use->opcode() == SpvOpStore &&
+        if (use->opcode() == spv::Op::OpStore &&
             use->GetSingleWordInOperand(kStorePointerInOperand) ==
                 var_inst->result_id()) {
           if (store_inst == nullptr) {
@@ -132,7 +132,7 @@
 void CopyPropagateArrays::PropagateObject(Instruction* var_inst,
                                           MemoryObject* source,
                                           Instruction* insertion_point) {
-  assert(var_inst->opcode() == SpvOpVariable &&
+  assert(var_inst->opcode() == spv::Op::OpVariable &&
          "This function propagates variables.");
 
   Instruction* new_access_chain = BuildNewAccessChain(insertion_point, source);
@@ -166,17 +166,17 @@
 
 bool CopyPropagateArrays::HasNoStores(Instruction* ptr_inst) {
   return get_def_use_mgr()->WhileEachUser(ptr_inst, [this](Instruction* use) {
-    if (use->opcode() == SpvOpLoad) {
+    if (use->opcode() == spv::Op::OpLoad) {
       return true;
-    } else if (use->opcode() == SpvOpAccessChain) {
+    } else if (use->opcode() == spv::Op::OpAccessChain) {
       return HasNoStores(use);
-    } else if (use->IsDecoration() || use->opcode() == SpvOpName) {
+    } else if (use->IsDecoration() || use->opcode() == spv::Op::OpName) {
       return true;
-    } else if (use->opcode() == SpvOpStore) {
+    } else if (use->opcode() == spv::Op::OpStore) {
       return false;
-    } else if (use->opcode() == SpvOpImageTexelPointer) {
+    } else if (use->opcode() == spv::Op::OpImageTexelPointer) {
       return true;
-    } else if (use->opcode() == SpvOpEntryPoint) {
+    } else if (use->opcode() == spv::Op::OpEntryPoint) {
       return true;
     }
     // Some other instruction.  Be conservative.
@@ -193,19 +193,19 @@
   return get_def_use_mgr()->WhileEachUser(
       ptr_inst,
       [this, store_inst, dominator_analysis, ptr_inst](Instruction* use) {
-        if (use->opcode() == SpvOpLoad ||
-            use->opcode() == SpvOpImageTexelPointer) {
+        if (use->opcode() == spv::Op::OpLoad ||
+            use->opcode() == spv::Op::OpImageTexelPointer) {
           // TODO: If there are many load in the same BB as |store_inst| the
           // time to do the multiple traverses can add up.  Consider collecting
           // those loads and doing a single traversal.
           return dominator_analysis->Dominates(store_inst, use);
-        } else if (use->opcode() == SpvOpAccessChain) {
+        } else if (use->opcode() == spv::Op::OpAccessChain) {
           return HasValidReferencesOnly(use, store_inst);
-        } else if (use->IsDecoration() || use->opcode() == SpvOpName) {
+        } else if (use->IsDecoration() || use->opcode() == spv::Op::OpName) {
           return true;
-        } else if (use->opcode() == SpvOpStore) {
+        } else if (use->opcode() == spv::Op::OpStore) {
           // If we are storing to part of the object it is not an candidate.
-          return ptr_inst->opcode() == SpvOpVariable &&
+          return ptr_inst->opcode() == spv::Op::OpVariable &&
                  store_inst->GetSingleWordInOperand(kStorePointerInOperand) ==
                      ptr_inst->result_id();
         } else if (IsDebugDeclareOrValue(use)) {
@@ -221,15 +221,15 @@
   Instruction* result_inst = context()->get_def_use_mgr()->GetDef(result);
 
   switch (result_inst->opcode()) {
-    case SpvOpLoad:
+    case spv::Op::OpLoad:
       return BuildMemoryObjectFromLoad(result_inst);
-    case SpvOpCompositeExtract:
+    case spv::Op::OpCompositeExtract:
       return BuildMemoryObjectFromExtract(result_inst);
-    case SpvOpCompositeConstruct:
+    case spv::Op::OpCompositeConstruct:
       return BuildMemoryObjectFromCompositeConstruct(result_inst);
-    case SpvOpCopyObject:
+    case spv::Op::OpCopyObject:
       return GetSourceObjectIfAny(result_inst->GetSingleWordInOperand(0));
-    case SpvOpCompositeInsert:
+    case spv::Op::OpCompositeInsert:
       return BuildMemoryObjectFromInsert(result_inst);
     default:
       return nullptr;
@@ -251,7 +251,7 @@
   //
   // It is built in reverse order because the different |OpAccessChain|
   // instructions are visited in reverse order from which they are applied.
-  while (current_inst->opcode() == SpvOpAccessChain) {
+  while (current_inst->opcode() == spv::Op::OpAccessChain) {
     for (uint32_t i = current_inst->NumInOperands() - 1; i >= 1; --i) {
       uint32_t element_index_id = current_inst->GetSingleWordInOperand(i);
       components_in_reverse.push_back(element_index_id);
@@ -263,7 +263,7 @@
   // instruction followed by a series of |OpAccessChain| instructions, then
   // return |nullptr| because we cannot identify the owner or access chain
   // exactly.
-  if (current_inst->opcode() != SpvOpVariable) {
+  if (current_inst->opcode() != spv::Op::OpVariable) {
     return nullptr;
   }
 
@@ -276,7 +276,7 @@
 
 std::unique_ptr<CopyPropagateArrays::MemoryObject>
 CopyPropagateArrays::BuildMemoryObjectFromExtract(Instruction* extract_inst) {
-  assert(extract_inst->opcode() == SpvOpCompositeExtract &&
+  assert(extract_inst->opcode() == spv::Op::OpCompositeExtract &&
          "Expecting an OpCompositeExtract instruction.");
   std::unique_ptr<MemoryObject> result = GetSourceObjectIfAny(
       extract_inst->GetSingleWordInOperand(kCompositeExtractObjectInOperand));
@@ -297,7 +297,7 @@
 std::unique_ptr<CopyPropagateArrays::MemoryObject>
 CopyPropagateArrays::BuildMemoryObjectFromCompositeConstruct(
     Instruction* conststruct_inst) {
-  assert(conststruct_inst->opcode() == SpvOpCompositeConstruct &&
+  assert(conststruct_inst->opcode() == spv::Op::OpCompositeConstruct &&
          "Expecting an OpCompositeConstruct instruction.");
 
   // If every operand in the instruction are part of the same memory object, and
@@ -352,7 +352,7 @@
 
 std::unique_ptr<CopyPropagateArrays::MemoryObject>
 CopyPropagateArrays::BuildMemoryObjectFromInsert(Instruction* insert_inst) {
-  assert(insert_inst->opcode() == SpvOpCompositeInsert &&
+  assert(insert_inst->opcode() == spv::Op::OpCompositeInsert &&
          "Expecting an OpCompositeInsert instruction.");
 
   analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
@@ -407,7 +407,7 @@
   Instruction* current_insert =
       def_use_mgr->GetDef(insert_inst->GetSingleWordInOperand(1));
   for (uint32_t i = number_of_elements - 1; i > 0; --i) {
-    if (current_insert->opcode() != SpvOpCompositeInsert) {
+    if (current_insert->opcode() != spv::Op::OpCompositeInsert) {
       return nullptr;
     }
 
@@ -500,7 +500,7 @@
     if (IsDebugDeclareOrValue(use)) return true;
 
     switch (use->opcode()) {
-      case SpvOpLoad: {
+      case spv::Op::OpLoad: {
         analysis::Pointer* pointer_type = type->AsPointer();
         uint32_t new_type_id = type_mgr->GetId(pointer_type->pointee_type());
 
@@ -509,7 +509,7 @@
         }
         return true;
       }
-      case SpvOpAccessChain: {
+      case spv::Op::OpAccessChain: {
         analysis::Pointer* pointer_type = type->AsPointer();
         const analysis::Type* pointee_type = pointer_type->pointee_type();
 
@@ -547,7 +547,7 @@
         }
         return true;
       }
-      case SpvOpCompositeExtract: {
+      case spv::Op::OpCompositeExtract: {
         std::vector<uint32_t> access_chain;
         for (uint32_t i = 1; i < use->NumInOperands(); ++i) {
           access_chain.push_back(use->GetSingleWordInOperand(i));
@@ -565,13 +565,13 @@
         }
         return true;
       }
-      case SpvOpStore:
+      case spv::Op::OpStore:
         // If needed, we can create an element-by-element copy to change the
         // type of the value being stored.  This way we can always handled
         // stores.
         return true;
-      case SpvOpImageTexelPointer:
-      case SpvOpName:
+      case spv::Op::OpImageTexelPointer:
+      case spv::Op::OpName:
         return true;
       default:
         return use->IsDecoration();
@@ -598,8 +598,8 @@
     if (use->IsCommonDebugInstr()) {
       switch (use->GetCommonDebugOpcode()) {
         case CommonDebugInfoDebugDeclare: {
-          if (new_ptr_inst->opcode() == SpvOpVariable ||
-              new_ptr_inst->opcode() == SpvOpFunctionParameter) {
+          if (new_ptr_inst->opcode() == spv::Op::OpVariable ||
+              new_ptr_inst->opcode() == spv::Op::OpFunctionParameter) {
             context()->ForgetUses(use);
             use->SetOperand(index, {new_ptr_inst->result_id()});
             context()->AnalyzeUses(use);
@@ -640,7 +640,7 @@
     }
 
     switch (use->opcode()) {
-      case SpvOpLoad: {
+      case spv::Op::OpLoad: {
         // Replace the actual use.
         context()->ForgetUses(use);
         use->SetOperand(index, {new_ptr_inst->result_id()});
@@ -658,7 +658,7 @@
           context()->AnalyzeUses(use);
         }
       } break;
-      case SpvOpAccessChain: {
+      case spv::Op::OpAccessChain: {
         // Update the actual use.
         context()->ForgetUses(use);
         use->SetOperand(index, {new_ptr_inst->result_id()});
@@ -685,7 +685,7 @@
             pointer_type_inst->GetSingleWordInOperand(kTypePointerPointeeInIdx),
             access_chain);
 
-        SpvStorageClass storage_class = static_cast<SpvStorageClass>(
+        spv::StorageClass storage_class = static_cast<spv::StorageClass>(
             pointer_type_inst->GetSingleWordInOperand(
                 kTypePointerStorageClassInIdx));
 
@@ -700,7 +700,7 @@
           context()->AnalyzeUses(use);
         }
       } break;
-      case SpvOpCompositeExtract: {
+      case spv::Op::OpCompositeExtract: {
         // Update the actual use.
         context()->ForgetUses(use);
         use->SetOperand(index, {new_ptr_inst->result_id()});
@@ -721,7 +721,7 @@
           context()->AnalyzeUses(use);
         }
       } break;
-      case SpvOpStore:
+      case spv::Op::OpStore:
         // If the use is the pointer, then it is the single store to that
         // variable.  We do not want to replace it.  Instead, it will become
         // dead after all of the loads are removed, and ADCE will get rid of it.
@@ -744,11 +744,11 @@
           context()->AnalyzeUses(use);
         }
         break;
-      case SpvOpDecorate:
+      case spv::Op::OpDecorate:
       // We treat an OpImageTexelPointer as a load.  The result type should
       // always have the Image storage class, and should not need to be
       // updated.
-      case SpvOpImageTexelPointer:
+      case spv::Op::OpImageTexelPointer:
         // Replace the actual use.
         context()->ForgetUses(use);
         use->SetOperand(index, {new_ptr_inst->result_id()});
@@ -766,13 +766,13 @@
   for (uint32_t element_index : access_chain) {
     Instruction* type_inst = get_def_use_mgr()->GetDef(id);
     switch (type_inst->opcode()) {
-      case SpvOpTypeArray:
-      case SpvOpTypeRuntimeArray:
-      case SpvOpTypeMatrix:
-      case SpvOpTypeVector:
+      case spv::Op::OpTypeArray:
+      case spv::Op::OpTypeRuntimeArray:
+      case spv::Op::OpTypeMatrix:
+      case spv::Op::OpTypeVector:
         id = type_inst->GetSingleWordInOperand(0);
         break;
-      case SpvOpTypeStruct:
+      case spv::Op::OpTypeStruct:
         id = type_inst->GetSingleWordInOperand(element_index);
         break;
       default:
diff --git a/source/opt/copy_prop_arrays.h b/source/opt/copy_prop_arrays.h
index 9e7641f..7486f80 100644
--- a/source/opt/copy_prop_arrays.h
+++ b/source/opt/copy_prop_arrays.h
@@ -134,13 +134,13 @@
           var_pointer_inst->GetSingleWordInOperand(1), GetAccessIds());
 
       uint32_t member_pointer_type_id = type_mgr->FindPointerToType(
-          member_type_id, static_cast<SpvStorageClass>(
+          member_type_id, static_cast<spv::StorageClass>(
                               var_pointer_inst->GetSingleWordInOperand(0)));
       return member_pointer_type_id;
     }
 
     // Returns the storage class of the memory object.
-    SpvStorageClass GetStorageClass() const {
+    spv::StorageClass GetStorageClass() const {
       analysis::TypeManager* type_mgr =
           GetVariable()->context()->get_type_mgr();
       const analysis::Pointer* pointer_type =
diff --git a/source/opt/dataflow.cpp b/source/opt/dataflow.cpp
index c91fad0..8d74e41 100644
--- a/source/opt/dataflow.cpp
+++ b/source/opt/dataflow.cpp
@@ -78,7 +78,7 @@
 }
 
 void ForwardDataFlowAnalysis::EnqueueBlockSuccessors(Instruction* inst) {
-  if (inst->opcode() != SpvOpLabel) return;
+  if (inst->opcode() != spv::Op::OpLabel) return;
   context()
       .cfg()
       ->block(inst->result_id())
diff --git a/source/opt/dead_branch_elim_pass.cpp b/source/opt/dead_branch_elim_pass.cpp
index d99b7f7..f5ba10e 100644
--- a/source/opt/dead_branch_elim_pass.cpp
+++ b/source/opt/dead_branch_elim_pass.cpp
@@ -41,16 +41,16 @@
   bool condIsConst;
   Instruction* cInst = get_def_use_mgr()->GetDef(condId);
   switch (cInst->opcode()) {
-    case SpvOpConstantNull:
-    case SpvOpConstantFalse: {
+    case spv::Op::OpConstantNull:
+    case spv::Op::OpConstantFalse: {
       *condVal = false;
       condIsConst = true;
     } break;
-    case SpvOpConstantTrue: {
+    case spv::Op::OpConstantTrue: {
       *condVal = true;
       condIsConst = true;
     } break;
-    case SpvOpLogicalNot: {
+    case spv::Op::OpLogicalNot: {
       bool negVal;
       condIsConst =
           GetConstCondition(cInst->GetSingleWordInOperand(0), &negVal);
@@ -65,13 +65,13 @@
   Instruction* sInst = get_def_use_mgr()->GetDef(selId);
   uint32_t typeId = sInst->type_id();
   Instruction* typeInst = get_def_use_mgr()->GetDef(typeId);
-  if (!typeInst || (typeInst->opcode() != SpvOpTypeInt)) return false;
+  if (!typeInst || (typeInst->opcode() != spv::Op::OpTypeInt)) return false;
   // TODO(greg-lunarg): Support non-32 bit ints
   if (typeInst->GetSingleWordInOperand(0) != 32) return false;
-  if (sInst->opcode() == SpvOpConstant) {
+  if (sInst->opcode() == spv::Op::OpConstant) {
     *selVal = sInst->GetSingleWordInOperand(0);
     return true;
-  } else if (sInst->opcode() == SpvOpConstantNull) {
+  } else if (sInst->opcode() == spv::Op::OpConstantNull) {
     *selVal = 0;
     return true;
   }
@@ -81,7 +81,7 @@
 void DeadBranchElimPass::AddBranch(uint32_t labelId, BasicBlock* bp) {
   assert(get_def_use_mgr()->GetDef(labelId) != nullptr);
   std::unique_ptr<Instruction> newBranch(
-      new Instruction(context(), SpvOpBranch, 0, 0,
+      new Instruction(context(), spv::Op::OpBranch, 0, 0,
                       {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {labelId}}}));
   context()->AnalyzeDefUse(&*newBranch);
   context()->set_instr_block(&*newBranch, bp);
@@ -115,13 +115,13 @@
     Instruction* terminator = block->terminator();
     uint32_t live_lab_id = 0;
     // Check if the terminator has a single valid successor.
-    if (terminator->opcode() == SpvOpBranchConditional) {
+    if (terminator->opcode() == spv::Op::OpBranchConditional) {
       bool condVal;
       if (GetConstCondition(terminator->GetSingleWordInOperand(0u), &condVal)) {
         live_lab_id = terminator->GetSingleWordInOperand(
             condVal ? kBranchCondTrueLabIdInIdx : kBranchCondFalseLabIdInIdx);
       }
-    } else if (terminator->opcode() == SpvOpSwitch) {
+    } else if (terminator->opcode() == spv::Op::OpSwitch) {
       uint32_t sel_val;
       if (GetConstInteger(terminator->GetSingleWordInOperand(0u), &sel_val)) {
         // Search switch operands for selector value, set live_lab_id to
@@ -194,8 +194,8 @@
                                         uint32_t live_lab_id) {
   Instruction* merge_inst = block->GetMergeInst();
   Instruction* terminator = block->terminator();
-  if (merge_inst && merge_inst->opcode() == SpvOpSelectionMerge) {
-    if (merge_inst->NextNode()->opcode() == SpvOpSwitch &&
+  if (merge_inst && merge_inst->opcode() == spv::Op::OpSelectionMerge) {
+    if (merge_inst->NextNode()->opcode() == spv::Op::OpSwitch &&
         SwitchHasNestedBreak(block->id())) {
       if (terminator->NumInOperands() == 2) {
         // We cannot remove the branch, and it already has a single case, so no
@@ -266,7 +266,7 @@
   for (auto& block : *func) {
     if (live_blocks.count(&block)) {
       for (auto iter = block.begin(); iter != block.end();) {
-        if (iter->opcode() != SpvOpPhi) {
+        if (iter->opcode() != spv::Op::OpPhi) {
           break;
         }
 
@@ -292,7 +292,7 @@
               cont_iter->second == &block && inst->NumInOperands() > 4) {
             if (get_def_use_mgr()
                     ->GetDef(inst->GetSingleWordInOperand(i - 1))
-                    ->opcode() == SpvOpUndef) {
+                    ->opcode() == spv::Op::OpUndef) {
               // Already undef incoming value, no change necessary.
               operands.push_back(inst->GetInOperand(i - 1));
               operands.push_back(inst->GetInOperand(i));
@@ -378,14 +378,14 @@
     if (unreachable_continues.count(&*ebi)) {
       uint32_t cont_id = unreachable_continues.find(&*ebi)->second->id();
       if (ebi->begin() != ebi->tail() ||
-          ebi->terminator()->opcode() != SpvOpBranch ||
+          ebi->terminator()->opcode() != spv::Op::OpBranch ||
           ebi->terminator()->GetSingleWordInOperand(0u) != cont_id) {
         // Make unreachable, but leave the label.
         KillAllInsts(&*ebi, false);
         // Add unconditional branch to header.
         assert(unreachable_continues.count(&*ebi));
         ebi->AddInstruction(MakeUnique<Instruction>(
-            context(), SpvOpBranch, 0, 0,
+            context(), spv::Op::OpBranch, 0, 0,
             std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {cont_id}}}));
         get_def_use_mgr()->AnalyzeInstUse(&*ebi->tail());
         context()->set_instr_block(&*ebi->tail(), &*ebi);
@@ -394,12 +394,12 @@
       ++ebi;
     } else if (unreachable_merges.count(&*ebi)) {
       if (ebi->begin() != ebi->tail() ||
-          ebi->terminator()->opcode() != SpvOpUnreachable) {
+          ebi->terminator()->opcode() != spv::Op::OpUnreachable) {
         // Make unreachable, but leave the label.
         KillAllInsts(&*ebi, false);
         // Add unreachable terminator.
         ebi->AddInstruction(
-            MakeUnique<Instruction>(context(), SpvOpUnreachable, 0, 0,
+            MakeUnique<Instruction>(context(), spv::Op::OpUnreachable, 0, 0,
                                     std::initializer_list<Operand>{}));
         context()->AnalyzeUses(ebi->terminator());
         context()->set_instr_block(ebi->terminator(), &*ebi);
@@ -465,7 +465,7 @@
   };
 
   // Structured order is more intuitive so use it where possible.
-  if (context()->get_feature_mgr()->HasCapability(SpvCapabilityShader)) {
+  if (context()->get_feature_mgr()->HasCapability(spv::Capability::Shader)) {
     context()->ProcessReachableCallTree(reorder_structured);
   } else {
     context()->ProcessReachableCallTree(reorder_dominators);
@@ -477,7 +477,8 @@
   // support required in KillNamesAndDecorates().
   // TODO(greg-lunarg): Add support for OpGroupDecorate
   for (auto& ai : get_module()->annotations())
-    if (ai.opcode() == SpvOpGroupDecorate) return Status::SuccessWithoutChange;
+    if (ai.opcode() == spv::Op::OpGroupDecorate)
+      return Status::SuccessWithoutChange;
   // Process all entry point functions
   ProcessFunction pfn = [this](Function* fp) {
     return EliminateDeadBranches(fp);
@@ -501,7 +502,7 @@
     Instruction* branch = start_block->terminator();
     uint32_t next_block_id = 0;
     switch (branch->opcode()) {
-      case SpvOpBranchConditional:
+      case spv::Op::OpBranchConditional:
         next_block_id = start_block->MergeBlockIdIfAny();
         if (next_block_id == 0) {
           // If a possible target is the |loop_merge_id| or |loop_continue_id|,
@@ -530,7 +531,7 @@
           }
         }
         break;
-      case SpvOpSwitch:
+      case spv::Op::OpSwitch:
         next_block_id = start_block->MergeBlockIdIfAny();
         if (next_block_id == 0) {
           // A switch with no merge instructions can have at most 5 targets:
@@ -578,7 +579,7 @@
           // The fall through is case 3.
         }
         break;
-      case SpvOpBranch:
+      case spv::Op::OpBranch:
         // Need to check if this is the header of a loop nested in the
         // selection construct.
         next_block_id = start_block->MergeBlockIdIfAny();
diff --git a/source/opt/dead_insert_elim_pass.cpp b/source/opt/dead_insert_elim_pass.cpp
index d877f0f..86b3020 100644
--- a/source/opt/dead_insert_elim_pass.cpp
+++ b/source/opt/dead_insert_elim_pass.cpp
@@ -38,17 +38,17 @@
 
 uint32_t DeadInsertElimPass::NumComponents(Instruction* typeInst) {
   switch (typeInst->opcode()) {
-    case SpvOpTypeVector: {
+    case spv::Op::OpTypeVector: {
       return typeInst->GetSingleWordInOperand(kTypeVectorCountInIdx);
     } break;
-    case SpvOpTypeMatrix: {
+    case spv::Op::OpTypeMatrix: {
       return typeInst->GetSingleWordInOperand(kTypeMatrixCountInIdx);
     } break;
-    case SpvOpTypeArray: {
+    case spv::Op::OpTypeArray: {
       uint32_t lenId =
           typeInst->GetSingleWordInOperand(kTypeArrayLengthIdInIdx);
       Instruction* lenInst = get_def_use_mgr()->GetDef(lenId);
-      if (lenInst->opcode() != SpvOpConstant) return 0;
+      if (lenInst->opcode() != spv::Op::OpConstant) return 0;
       uint32_t lenTypeId = lenInst->type_id();
       Instruction* lenTypeInst = get_def_use_mgr()->GetDef(lenTypeId);
       // TODO(greg-lunarg): Support non-32-bit array length
@@ -56,7 +56,7 @@
         return 0;
       return lenInst->GetSingleWordInOperand(kConstantValueInIdx);
     } break;
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       return typeInst->NumInOperands();
     } break;
     default: { return 0; } break;
@@ -68,10 +68,10 @@
     uint32_t extOffset, std::unordered_set<uint32_t>* visited_phis) {
   // Not currently optimizing array inserts.
   Instruction* typeInst = get_def_use_mgr()->GetDef(insertChain->type_id());
-  if (typeInst->opcode() == SpvOpTypeArray) return;
+  if (typeInst->opcode() == spv::Op::OpTypeArray) return;
   // Insert chains are only composed of inserts and phis
-  if (insertChain->opcode() != SpvOpCompositeInsert &&
-      insertChain->opcode() != SpvOpPhi)
+  if (insertChain->opcode() != spv::Op::OpCompositeInsert &&
+      insertChain->opcode() != spv::Op::OpPhi)
     return;
   // If extract indices are empty, mark all subcomponents if type
   // is constant length.
@@ -89,7 +89,7 @@
     }
   }
   Instruction* insInst = insertChain;
-  while (insInst->opcode() == SpvOpCompositeInsert) {
+  while (insInst->opcode() == spv::Op::OpCompositeInsert) {
     // If no extract indices, mark insert and inserted object (which might
     // also be an insert chain) and continue up the chain though the input
     // composite.
@@ -139,7 +139,7 @@
     insInst = get_def_use_mgr()->GetDef(compId);
   }
   // If insert chain ended with phi, do recursive call on each operand
-  if (insInst->opcode() != SpvOpPhi) return;
+  if (insInst->opcode() != spv::Op::OpPhi) return;
   // Mark phi visited to prevent potential infinite loop. If phi is already
   // visited, return to avoid infinite loop.
   if (visited_phis->count(insInst->result_id()) != 0) return;
@@ -179,17 +179,17 @@
   for (auto bi = func->begin(); bi != func->end(); ++bi) {
     for (auto ii = bi->begin(); ii != bi->end(); ++ii) {
       // Only process Inserts and composite Phis
-      SpvOp op = ii->opcode();
+      spv::Op op = ii->opcode();
       Instruction* typeInst = get_def_use_mgr()->GetDef(ii->type_id());
-      if (op != SpvOpCompositeInsert &&
-          (op != SpvOpPhi || !spvOpcodeIsComposite(typeInst->opcode())))
+      if (op != spv::Op::OpCompositeInsert &&
+          (op != spv::Op::OpPhi || !spvOpcodeIsComposite(typeInst->opcode())))
         continue;
       // The marking algorithm can be expensive for large arrays and the
       // efficacy of eliminating dead inserts into arrays is questionable.
       // Skip optimizing array inserts for now. Just mark them live.
       // TODO(greg-lunarg): Eliminate dead array inserts
-      if (op == SpvOpCompositeInsert) {
-        if (typeInst->opcode() == SpvOpTypeArray) {
+      if (op == spv::Op::OpCompositeInsert) {
+        if (typeInst->opcode() == spv::Op::OpTypeArray) {
           liveInserts_.insert(ii->result_id());
           continue;
         }
@@ -198,11 +198,11 @@
       get_def_use_mgr()->ForEachUser(id, [&ii, this](Instruction* user) {
         if (user->IsCommonDebugInstr()) return;
         switch (user->opcode()) {
-          case SpvOpCompositeInsert:
-          case SpvOpPhi:
+          case spv::Op::OpCompositeInsert:
+          case spv::Op::OpPhi:
             // Use by insert or phi does not initiate marking
             break;
-          case SpvOpCompositeExtract: {
+          case spv::Op::OpCompositeExtract: {
             // Capture extract indices
             std::vector<uint32_t> extIndices;
             uint32_t icnt = 0;
@@ -226,7 +226,7 @@
   std::vector<Instruction*> dead_instructions;
   for (auto bi = func->begin(); bi != func->end(); ++bi) {
     for (auto ii = bi->begin(); ii != bi->end(); ++ii) {
-      if (ii->opcode() != SpvOpCompositeInsert) continue;
+      if (ii->opcode() != spv::Op::OpCompositeInsert) continue;
       const uint32_t id = ii->result_id();
       if (liveInserts_.find(id) != liveInserts_.end()) continue;
       const uint32_t replId =
diff --git a/source/opt/dead_variable_elimination.cpp b/source/opt/dead_variable_elimination.cpp
index 2837106..e39132c 100644
--- a/source/opt/dead_variable_elimination.cpp
+++ b/source/opt/dead_variable_elimination.cpp
@@ -33,7 +33,7 @@
 
   // Get the reference count for all of the global OpVariable instructions.
   for (auto& inst : context()->types_values()) {
-    if (inst.opcode() != SpvOp::SpvOpVariable) {
+    if (inst.opcode() != spv::Op::OpVariable) {
       continue;
     }
 
@@ -43,11 +43,11 @@
     // Check the linkage.  If it is exported, it could be reference somewhere
     // else, so we must keep the variable around.
     get_decoration_mgr()->ForEachDecoration(
-        result_id, SpvDecorationLinkageAttributes,
+        result_id, uint32_t(spv::Decoration::LinkageAttributes),
         [&count](const Instruction& linkage_instruction) {
           uint32_t last_operand = linkage_instruction.NumOperands() - 1;
-          if (linkage_instruction.GetSingleWordOperand(last_operand) ==
-              SpvLinkageTypeExport) {
+          if (spv::LinkageType(linkage_instruction.GetSingleWordOperand(
+                  last_operand)) == spv::LinkageType::Export) {
             count = kMustKeep;
           }
         });
@@ -57,7 +57,8 @@
       // at the uses and count the number of real references.
       count = 0;
       get_def_use_mgr()->ForEachUser(result_id, [&count](Instruction* user) {
-        if (!IsAnnotationInst(user->opcode()) && user->opcode() != SpvOpName) {
+        if (!IsAnnotationInst(user->opcode()) &&
+            user->opcode() != spv::Op::OpName) {
           ++count;
         }
       });
@@ -81,7 +82,7 @@
 
 void DeadVariableElimination::DeleteVariable(uint32_t result_id) {
   Instruction* inst = get_def_use_mgr()->GetDef(result_id);
-  assert(inst->opcode() == SpvOpVariable &&
+  assert(inst->opcode() == spv::Op::OpVariable &&
          "Should not be trying to delete anything other than an OpVariable.");
 
   // Look for an initializer that references another variable.  We need to know
@@ -93,7 +94,7 @@
     // TODO: Handle OpSpecConstantOP which might be defined in terms of other
     // variables.  Will probably require a unified dead code pass that does all
     // instruction types.  (Issue 906)
-    if (initializer->opcode() == SpvOpVariable) {
+    if (initializer->opcode() == spv::Op::OpVariable) {
       uint32_t initializer_id = initializer->result_id();
       size_t& count = reference_count_[initializer_id];
       if (count != kMustKeep) {
diff --git a/source/opt/debug_info_manager.cpp b/source/opt/debug_info_manager.cpp
index 3585186..d985d6a 100644
--- a/source/opt/debug_info_manager.cpp
+++ b/source/opt/debug_info_manager.cpp
@@ -156,7 +156,8 @@
 uint32_t AddNewConstInGlobals(IRContext* context, uint32_t const_value) {
   uint32_t id = context->TakeNextId();
   std::unique_ptr<Instruction> new_const(new Instruction(
-      context, SpvOpConstant, context->get_type_mgr()->GetUIntTypeId(), id,
+      context, spv::Op::OpConstant, context->get_type_mgr()->GetUIntTypeId(),
+      id,
       {
           {spv_operand_type_t::SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER,
            {const_value}},
@@ -212,7 +213,7 @@
         break;
     }
   } else {
-    if (line->opcode() == SpvOpLine) {
+    if (line->opcode() == spv::Op::OpLine) {
       line_number = line->GetSingleWordOperand(kOpLineOperandLineIndex);
     } else if (line->GetShader100DebugOpcode() ==
                NonSemanticShaderDebugInfo100DebugLine) {
@@ -230,7 +231,7 @@
     // constants that may be generated here is likely not significant
     // and will likely be cleaned up in later passes.
     if (line_number_type == spv_operand_type_t::SPV_OPERAND_TYPE_ID &&
-        line->opcode() == SpvOpLine) {
+        line->opcode() == spv::Op::OpLine) {
       if (!context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse) ||
           !context()->AreAnalysesValid(IRContext::Analysis::kAnalysisConstants))
         line_number = AddNewConstInGlobals(context(), line_number);
@@ -241,7 +242,7 @@
 
   uint32_t result_id = context()->TakeNextId();
   std::unique_ptr<Instruction> inlined_at(new Instruction(
-      context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
+      context(), spv::Op::OpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
       result_id,
       {
           {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {setId}},
@@ -334,8 +335,8 @@
 
   if (context()->get_feature_mgr()->GetExtInstImportId_OpenCL100DebugInfo()) {
     deref_operation = std::unique_ptr<Instruction>(new Instruction(
-        context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
-        result_id,
+        context(), spv::Op::OpExtInst,
+        context()->get_type_mgr()->GetVoidTypeId(), result_id,
         {
             {SPV_OPERAND_TYPE_ID, {GetDbgSetImportId()}},
             {SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER,
@@ -348,7 +349,7 @@
         NonSemanticShaderDebugInfo100Deref);
 
     deref_operation = std::unique_ptr<Instruction>(
-        new Instruction(context(), SpvOpExtInst,
+        new Instruction(context(), spv::Op::OpExtInst,
                         context()->get_type_mgr()->GetVoidTypeId(), result_id,
                         {
                             {SPV_OPERAND_TYPE_ID, {GetDbgSetImportId()}},
@@ -390,7 +391,7 @@
 
   uint32_t result_id = context()->TakeNextId();
   std::unique_ptr<Instruction> dbg_info_none_inst(new Instruction(
-      context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
+      context(), spv::Op::OpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
       result_id,
       {
           {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {GetDbgSetImportId()}},
@@ -414,7 +415,7 @@
 
   uint32_t result_id = context()->TakeNextId();
   std::unique_ptr<Instruction> empty_debug_expr(new Instruction(
-      context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
+      context(), spv::Op::OpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
       result_id,
       {
           {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {GetDbgSetImportId()}},
@@ -527,7 +528,7 @@
   assert(scope != nullptr);
 
   std::vector<uint32_t> scope_ids;
-  if (scope->opcode() == SpvOpPhi) {
+  if (scope->opcode() == spv::Op::OpPhi) {
     scope_ids.push_back(scope->GetDebugScope().GetLexicalScope());
     for (uint32_t i = 0; i < scope->NumInOperands(); i += 2) {
       auto* value = context()->get_def_use_mgr()->GetDef(
@@ -571,8 +572,8 @@
     // Avoid inserting the new DebugValue between OpPhi or OpVariable
     // instructions.
     Instruction* insert_before = insert_pos->NextNode();
-    while (insert_before->opcode() == SpvOpPhi ||
-           insert_before->opcode() == SpvOpVariable) {
+    while (insert_before->opcode() == spv::Op::OpPhi ||
+           insert_before->opcode() == spv::Op::OpVariable) {
       insert_before = insert_before->NextNode();
     }
     modified |= AddDebugValueForDecl(dbg_decl_or_val, value_id, insert_before,
@@ -653,9 +654,10 @@
   }
 
   auto* var = context()->get_def_use_mgr()->GetDef(var_id);
-  if (var->opcode() == SpvOpVariable &&
-      SpvStorageClass(var->GetSingleWordOperand(
-          kOpVariableOperandStorageClassIndex)) == SpvStorageClassFunction) {
+  if (var->opcode() == spv::Op::OpVariable &&
+      spv::StorageClass(
+          var->GetSingleWordOperand(kOpVariableOperandStorageClassIndex)) ==
+          spv::StorageClass::Function) {
     return var_id;
   }
   return 0;
@@ -762,8 +764,8 @@
       CommonDebugInfoDebugGlobalVariable) {
     return;
   }
-  assert(local_var->opcode() == SpvOpVariable ||
-         local_var->opcode() == SpvOpFunctionParameter);
+  assert(local_var->opcode() == spv::Op::OpVariable ||
+         local_var->opcode() == spv::Op::OpFunctionParameter);
 
   // Convert |dbg_global_var| to DebugLocalVariable
   dbg_global_var->SetInOperand(kExtInstInstructionInIdx,
@@ -780,7 +782,7 @@
 
   // Create a DebugDeclare
   std::unique_ptr<Instruction> new_dbg_decl(new Instruction(
-      context(), SpvOpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
+      context(), spv::Op::OpExtInst, context()->get_type_mgr()->GetVoidTypeId(),
       context()->TakeNextId(),
       {
           {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {GetDbgSetImportId()}},
@@ -794,7 +796,7 @@
       }));
   // Must insert after all OpVariables in block
   Instruction* insert_before = local_var;
-  while (insert_before->opcode() == SpvOpVariable)
+  while (insert_before->opcode() == spv::Op::OpVariable)
     insert_before = insert_before->NextNode();
   auto* added_dbg_decl = insert_before->InsertBefore(std::move(new_dbg_decl));
   if (context()->AreAnalysesValid(IRContext::Analysis::kAnalysisDefUse))
diff --git a/source/opt/decoration_manager.cpp b/source/opt/decoration_manager.cpp
index 2146c35..11072e5 100644
--- a/source/opt/decoration_manager.cpp
+++ b/source/opt/decoration_manager.cpp
@@ -76,8 +76,8 @@
   // applying the group.
   std::unordered_set<const Instruction*> indirect_decorations_to_remove;
   for (Instruction* inst : decorations_info.indirect_decorations) {
-    assert(inst->opcode() == SpvOpGroupDecorate ||
-           inst->opcode() == SpvOpGroupMemberDecorate);
+    assert(inst->opcode() == spv::Op::OpGroupDecorate ||
+           inst->opcode() == spv::Op::OpGroupMemberDecorate);
 
     std::vector<Instruction*> group_decorations_to_keep;
     const uint32_t group_id = inst->GetSingleWordInOperand(0u);
@@ -99,7 +99,8 @@
     }
 
     // Otherwise, remove |id| from the targets of |group_id|
-    const uint32_t stride = inst->opcode() == SpvOpGroupDecorate ? 1u : 2u;
+    const uint32_t stride =
+        inst->opcode() == spv::Op::OpGroupDecorate ? 1u : 2u;
     for (uint32_t i = 1u; i < inst->NumInOperands();) {
       if (inst->GetSingleWordInOperand(i) != id) {
         i += stride;
@@ -212,16 +213,16 @@
           }
 
           switch (inst->opcode()) {
-            case SpvOpDecorate:
+            case spv::Op::OpDecorate:
               decorate_set->emplace(std::move(decoration_payload));
               break;
-            case SpvOpMemberDecorate:
+            case spv::Op::OpMemberDecorate:
               member_decorate_set->emplace(std::move(decoration_payload));
               break;
-            case SpvOpDecorateId:
+            case spv::Op::OpDecorateId:
               decorate_id_set->emplace(std::move(decoration_payload));
               break;
-            case SpvOpDecorateStringGOOGLE:
+            case spv::Op::OpDecorateStringGOOGLE:
               decorate_string_set->emplace(std::move(decoration_payload));
               break;
             default:
@@ -278,16 +279,16 @@
           }
 
           switch (inst->opcode()) {
-            case SpvOpDecorate:
+            case spv::Op::OpDecorate:
               decorate_set->emplace(std::move(decoration_payload));
               break;
-            case SpvOpMemberDecorate:
+            case spv::Op::OpMemberDecorate:
               member_decorate_set->emplace(std::move(decoration_payload));
               break;
-            case SpvOpDecorateId:
+            case spv::Op::OpDecorateId:
               decorate_id_set->emplace(std::move(decoration_payload));
               break;
-            case SpvOpDecorateStringGOOGLE:
+            case spv::Op::OpDecorateStringGOOGLE:
               decorate_string_set->emplace(std::move(decoration_payload));
               break;
             default:
@@ -328,10 +329,10 @@
                                               const Instruction* inst2,
                                               bool ignore_target) const {
   switch (inst1->opcode()) {
-    case SpvOpDecorate:
-    case SpvOpMemberDecorate:
-    case SpvOpDecorateId:
-    case SpvOpDecorateStringGOOGLE:
+    case spv::Op::OpDecorate:
+    case spv::Op::OpMemberDecorate:
+    case spv::Op::OpDecorateId:
+    case spv::Op::OpDecorateStringGOOGLE:
       break;
     default:
       return false;
@@ -358,17 +359,18 @@
 
 void DecorationManager::AddDecoration(Instruction* inst) {
   switch (inst->opcode()) {
-    case SpvOpDecorate:
-    case SpvOpDecorateId:
-    case SpvOpDecorateStringGOOGLE:
-    case SpvOpMemberDecorate: {
+    case spv::Op::OpDecorate:
+    case spv::Op::OpDecorateId:
+    case spv::Op::OpDecorateStringGOOGLE:
+    case spv::Op::OpMemberDecorate: {
       const auto target_id = inst->GetSingleWordInOperand(0u);
       id_to_decoration_insts_[target_id].direct_decorations.push_back(inst);
       break;
     }
-    case SpvOpGroupDecorate:
-    case SpvOpGroupMemberDecorate: {
-      const uint32_t start = inst->opcode() == SpvOpGroupDecorate ? 1u : 2u;
+    case spv::Op::OpGroupDecorate:
+    case spv::Op::OpGroupMemberDecorate: {
+      const uint32_t start =
+          inst->opcode() == spv::Op::OpGroupDecorate ? 1u : 2u;
       const uint32_t stride = start;
       for (uint32_t i = start; i < inst->NumInOperands(); i += stride) {
         const auto target_id = inst->GetSingleWordInOperand(i);
@@ -384,7 +386,7 @@
   }
 }
 
-void DecorationManager::AddDecoration(SpvOp opcode,
+void DecorationManager::AddDecoration(spv::Op opcode,
                                       std::vector<Operand> opnds) {
   IRContext* ctx = module_->context();
   std::unique_ptr<Instruction> newDecoOp(
@@ -394,7 +396,7 @@
 
 void DecorationManager::AddDecoration(uint32_t inst_id, uint32_t decoration) {
   AddDecoration(
-      SpvOpDecorate,
+      spv::Op::OpDecorate,
       {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {inst_id}},
        {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {decoration}}});
 }
@@ -402,7 +404,7 @@
 void DecorationManager::AddDecorationVal(uint32_t inst_id, uint32_t decoration,
                                          uint32_t decoration_value) {
   AddDecoration(
-      SpvOpDecorate,
+      spv::Op::OpDecorate,
       {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {inst_id}},
        {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {decoration}},
        {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
@@ -413,7 +415,7 @@
                                             uint32_t decoration,
                                             uint32_t decoration_value) {
   AddDecoration(
-      SpvOpMemberDecorate,
+      spv::Op::OpMemberDecorate,
       {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {inst_id}},
        {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {member}},
        {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {decoration}},
@@ -436,9 +438,10 @@
       [include_linkage,
        &decorations](const std::vector<Instruction*>& direct_decorations) {
         for (Instruction* inst : direct_decorations) {
-          const bool is_linkage = inst->opcode() == SpvOpDecorate &&
-                                  inst->GetSingleWordInOperand(1u) ==
-                                      SpvDecorationLinkageAttributes;
+          const bool is_linkage =
+              inst->opcode() == spv::Op::OpDecorate &&
+              spv::Decoration(inst->GetSingleWordInOperand(1u)) ==
+                  spv::Decoration::LinkageAttributes;
           if (include_linkage || !is_linkage) decorations.push_back(inst);
         }
       };
@@ -462,14 +465,14 @@
     std::function<bool(const Instruction&)> f) {
   for (const Instruction* inst : GetDecorationsFor(id, true)) {
     switch (inst->opcode()) {
-      case SpvOpMemberDecorate:
+      case spv::Op::OpMemberDecorate:
         if (inst->GetSingleWordInOperand(2) == decoration) {
           if (!f(*inst)) return false;
         }
         break;
-      case SpvOpDecorate:
-      case SpvOpDecorateId:
-      case SpvOpDecorateStringGOOGLE:
+      case spv::Op::OpDecorate:
+      case spv::Op::OpDecorateId:
+      case spv::Op::OpDecorateStringGOOGLE:
         if (inst->GetSingleWordInOperand(1) == decoration) {
           if (!f(*inst)) return false;
         }
@@ -523,14 +526,14 @@
       decoration_list->second.indirect_decorations;
   for (Instruction* inst : indirect_decorations) {
     switch (inst->opcode()) {
-      case SpvOpGroupDecorate:
+      case spv::Op::OpGroupDecorate:
         context->ForgetUses(inst);
         // add |to| to list of decorated id's
         inst->AddOperand(
             Operand(spv_operand_type_t::SPV_OPERAND_TYPE_ID, {to}));
         context->AnalyzeUses(inst);
         break;
-      case SpvOpGroupMemberDecorate: {
+      case spv::Op::OpGroupMemberDecorate: {
         context->ForgetUses(inst);
         // for each (id == from), add (to, literal) as operands
         const uint32_t num_operands = inst->NumOperands();
@@ -554,13 +557,13 @@
 
 void DecorationManager::CloneDecorations(
     uint32_t from, uint32_t to,
-    const std::vector<SpvDecoration>& decorations_to_copy) {
+    const std::vector<spv::Decoration>& decorations_to_copy) {
   const auto decoration_list = id_to_decoration_insts_.find(from);
   if (decoration_list == id_to_decoration_insts_.end()) return;
   auto context = module_->context();
   for (Instruction* inst : decoration_list->second.direct_decorations) {
     if (std::find(decorations_to_copy.begin(), decorations_to_copy.end(),
-                  inst->GetSingleWordInOperand(1)) ==
+                  spv::Decoration(inst->GetSingleWordInOperand(1))) ==
         decorations_to_copy.end()) {
       continue;
     }
@@ -579,11 +582,11 @@
       decoration_list->second.indirect_decorations;
   for (Instruction* inst : indirect_decorations) {
     switch (inst->opcode()) {
-      case SpvOpGroupDecorate:
+      case spv::Op::OpGroupDecorate:
         CloneDecorations(inst->GetSingleWordInOperand(0), to,
                          decorations_to_copy);
         break;
-      case SpvOpGroupMemberDecorate: {
+      case spv::Op::OpGroupMemberDecorate: {
         assert(false && "The source id is not suppose to be a type.");
         break;
       }
@@ -599,18 +602,19 @@
   };
 
   switch (inst->opcode()) {
-    case SpvOpDecorate:
-    case SpvOpDecorateId:
-    case SpvOpDecorateStringGOOGLE:
-    case SpvOpMemberDecorate: {
+    case spv::Op::OpDecorate:
+    case spv::Op::OpDecorateId:
+    case spv::Op::OpDecorateStringGOOGLE:
+    case spv::Op::OpMemberDecorate: {
       const auto target_id = inst->GetSingleWordInOperand(0u);
       auto const iter = id_to_decoration_insts_.find(target_id);
       if (iter == id_to_decoration_insts_.end()) return;
       remove_from_container(iter->second.direct_decorations);
     } break;
-    case SpvOpGroupDecorate:
-    case SpvOpGroupMemberDecorate: {
-      const uint32_t stride = inst->opcode() == SpvOpGroupDecorate ? 1u : 2u;
+    case spv::Op::OpGroupDecorate:
+    case spv::Op::OpGroupMemberDecorate: {
+      const uint32_t stride =
+          inst->opcode() == spv::Op::OpGroupDecorate ? 1u : 2u;
       for (uint32_t i = 1u; i < inst->NumInOperands(); i += stride) {
         const auto target_id = inst->GetSingleWordInOperand(i);
         auto const iter = id_to_decoration_insts_.find(target_id);
diff --git a/source/opt/decoration_manager.h b/source/opt/decoration_manager.h
index fe78f2c..1a0d1b1 100644
--- a/source/opt/decoration_manager.h
+++ b/source/opt/decoration_manager.h
@@ -71,14 +71,14 @@
                                               bool include_linkage);
   std::vector<const Instruction*> GetDecorationsFor(uint32_t id,
                                                     bool include_linkage) const;
-  // Returns whether two IDs have the same decorations. Two SpvOpGroupDecorate
-  // instructions that apply the same decorations but to different IDs, still
-  // count as being the same.
+  // Returns whether two IDs have the same decorations. Two
+  // spv::Op::OpGroupDecorate instructions that apply the same decorations but
+  // to different IDs, still count as being the same.
   bool HaveTheSameDecorations(uint32_t id1, uint32_t id2) const;
 
-  // Returns whether two IDs have the same decorations. Two SpvOpGroupDecorate
-  // instructions that apply the same decorations but to different IDs, still
-  // count as being the same.
+  // Returns whether two IDs have the same decorations. Two
+  // spv::Op::OpGroupDecorate instructions that apply the same decorations but
+  // to different IDs, still count as being the same.
   bool HaveSubsetOfDecorations(uint32_t id1, uint32_t id2) const;
 
   // Returns whether the two decorations instructions are the same and are
@@ -123,14 +123,15 @@
   // Same as above, but only clone the decoration if the decoration operand is
   // in |decorations_to_copy|.  This function has the extra restriction that
   // |from| and |to| must not be an object, not a type.
-  void CloneDecorations(uint32_t from, uint32_t to,
-                        const std::vector<SpvDecoration>& decorations_to_copy);
+  void CloneDecorations(
+      uint32_t from, uint32_t to,
+      const std::vector<spv::Decoration>& decorations_to_copy);
 
   // Informs the decoration manager of a new decoration that it needs to track.
   void AddDecoration(Instruction* inst);
 
   // Add decoration with |opcode| and operands |opnds|.
-  void AddDecoration(SpvOp opcode, const std::vector<Operand> opnds);
+  void AddDecoration(spv::Op opcode, const std::vector<Operand> opnds);
 
   // Add |decoration| of |inst_id| to module.
   void AddDecoration(uint32_t inst_id, uint32_t decoration);
@@ -195,9 +196,9 @@
 
   // Mapping from ids to the instructions applying a decoration to those ids.
   // In other words, for each id you get all decoration instructions
-  // referencing that id, be it directly (SpvOpDecorate, SpvOpMemberDecorate
-  // and SpvOpDecorateId), or indirectly (SpvOpGroupDecorate,
-  // SpvOpMemberGroupDecorate).
+  // referencing that id, be it directly (spv::Op::OpDecorate,
+  // spv::Op::OpMemberDecorate and spv::Op::OpDecorateId), or indirectly
+  // (spv::Op::OpGroupDecorate, spv::Op::OpMemberGroupDecorate).
   std::unordered_map<uint32_t, TargetData> id_to_decoration_insts_;
   // The enclosing module.
   Module* module_;
diff --git a/source/opt/desc_sroa.cpp b/source/opt/desc_sroa.cpp
index b130ca8..8da0c86 100644
--- a/source/opt/desc_sroa.cpp
+++ b/source/opt/desc_sroa.cpp
@@ -22,8 +22,9 @@
 namespace {
 
 bool IsDecorationBinding(Instruction* inst) {
-  if (inst->opcode() != SpvOpDecorate) return false;
-  return inst->GetSingleWordInOperand(1u) == SpvDecorationBinding;
+  if (inst->opcode() != spv::Op::OpDecorate) return false;
+  return spv::Decoration(inst->GetSingleWordInOperand(1u)) ==
+         spv::Decoration::Binding;
 }
 
 }  // namespace
@@ -56,7 +57,7 @@
   bool failed = !get_def_use_mgr()->WhileEachUser(
       var->result_id(),
       [this, &access_chain_work_list, &load_work_list](Instruction* use) {
-        if (use->opcode() == SpvOpName) {
+        if (use->opcode() == spv::Op::OpName) {
           return true;
         }
 
@@ -65,11 +66,11 @@
         }
 
         switch (use->opcode()) {
-          case SpvOpAccessChain:
-          case SpvOpInBoundsAccessChain:
+          case spv::Op::OpAccessChain:
+          case spv::Op::OpInBoundsAccessChain:
             access_chain_work_list.push_back(use);
             return true;
-          case SpvOpLoad:
+          case spv::Op::OpLoad:
             load_work_list.push_back(use);
             return true;
           default:
@@ -184,7 +185,7 @@
   // Handle OpMemberDecorate instructions.
   for (auto old_decoration : get_decoration_mgr()->GetDecorationsFor(
            old_var_type->result_id(), true)) {
-    assert(old_decoration->opcode() == SpvOpMemberDecorate);
+    assert(old_decoration->opcode() == spv::Op::OpMemberDecorate);
     if (old_decoration->GetSingleWordInOperand(1u) != index) continue;
     CreateNewDecorationForMemberDecorate(old_decoration, new_var_id);
   }
@@ -212,8 +213,8 @@
 
 void DescriptorScalarReplacement::CreateNewDecorationForNewVariable(
     Instruction* old_decoration, uint32_t new_var_id, uint32_t new_binding) {
-  assert(old_decoration->opcode() == SpvOpDecorate ||
-         old_decoration->opcode() == SpvOpDecorateString);
+  assert(old_decoration->opcode() == spv::Op::OpDecorate ||
+         old_decoration->opcode() == spv::Op::OpDecorateString);
   std::unique_ptr<Instruction> new_decoration(old_decoration->Clone(context()));
   new_decoration->SetInOperand(0, {new_var_id});
 
@@ -231,25 +232,25 @@
   auto new_decorate_operand_end = old_member_decoration->end();
   operands.insert(operands.end(), new_decorate_operand_begin,
                   new_decorate_operand_end);
-  get_decoration_mgr()->AddDecoration(SpvOpDecorate, std::move(operands));
+  get_decoration_mgr()->AddDecoration(spv::Op::OpDecorate, std::move(operands));
 }
 
 uint32_t DescriptorScalarReplacement::CreateReplacementVariable(
     Instruction* var, uint32_t idx) {
   // The storage class for the new variable is the same as the original.
-  SpvStorageClass storage_class =
-      static_cast<SpvStorageClass>(var->GetSingleWordInOperand(0));
+  spv::StorageClass storage_class =
+      static_cast<spv::StorageClass>(var->GetSingleWordInOperand(0));
 
   // The type for the new variable will be a pointer to type of the elements of
   // the array.
   uint32_t ptr_type_id = var->type_id();
   Instruction* ptr_type_inst = get_def_use_mgr()->GetDef(ptr_type_id);
-  assert(ptr_type_inst->opcode() == SpvOpTypePointer &&
+  assert(ptr_type_inst->opcode() == spv::Op::OpTypePointer &&
          "Variable should be a pointer to an array or structure.");
   uint32_t pointee_type_id = ptr_type_inst->GetSingleWordInOperand(1);
   Instruction* pointee_type_inst = get_def_use_mgr()->GetDef(pointee_type_id);
-  const bool is_array = pointee_type_inst->opcode() == SpvOpTypeArray;
-  const bool is_struct = pointee_type_inst->opcode() == SpvOpTypeStruct;
+  const bool is_array = pointee_type_inst->opcode() == spv::Op::OpTypeArray;
+  const bool is_struct = pointee_type_inst->opcode() == spv::Op::OpTypeStruct;
   assert((is_array || is_struct) &&
          "Variable should be a pointer to an array or structure.");
 
@@ -263,7 +264,7 @@
   // Create the variable.
   uint32_t id = TakeNextId();
   std::unique_ptr<Instruction> variable(
-      new Instruction(context(), SpvOpVariable, ptr_element_type_id, id,
+      new Instruction(context(), spv::Op::OpVariable, ptr_element_type_id, id,
                       std::initializer_list<Operand>{
                           {SPV_OPERAND_TYPE_STORAGE_CLASS,
                            {static_cast<uint32_t>(storage_class)}}}));
@@ -293,7 +294,7 @@
     }
 
     std::unique_ptr<Instruction> new_name(new Instruction(
-        context(), SpvOpName, 0, 0,
+        context(), spv::Op::OpName, 0, 0,
         std::initializer_list<Operand>{
             {SPV_OPERAND_TYPE_ID, {id}},
             {SPV_OPERAND_TYPE_LITERAL_STRING, utils::MakeVector(name_str)}}));
@@ -315,14 +316,14 @@
   Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
 
   // If it's a pointer, look at the underlying type.
-  if (type_inst->opcode() == SpvOpTypePointer) {
+  if (type_inst->opcode() == spv::Op::OpTypePointer) {
     type_id = type_inst->GetSingleWordInOperand(1);
     type_inst = get_def_use_mgr()->GetDef(type_id);
   }
 
   // Arrays consume N*M binding numbers where N is the array length, and M is
   // the number of bindings used by each array element.
-  if (type_inst->opcode() == SpvOpTypeArray) {
+  if (type_inst->opcode() == spv::Op::OpTypeArray) {
     uint32_t element_type_id = type_inst->GetSingleWordInOperand(0);
     uint32_t length_id = type_inst->GetSingleWordInOperand(1);
     const analysis::Constant* length_const =
@@ -335,7 +336,7 @@
 
   // The number of bindings consumed by a structure is the sum of the bindings
   // used by its members.
-  if (type_inst->opcode() == SpvOpTypeStruct &&
+  if (type_inst->opcode() == spv::Op::OpTypeStruct &&
       !descsroautil::IsTypeOfStructuredBuffer(context(), type_inst)) {
     uint32_t sum = 0;
     for (uint32_t i = 0; i < type_inst->NumInOperands(); i++)
@@ -353,12 +354,12 @@
   // |value| is the OpLoad instruction that has loaded |var|.
   // The function expects all users of |value| to be OpCompositeExtract
   // instructions. Otherwise the function returns false with an error message.
-  assert(value->opcode() == SpvOpLoad);
+  assert(value->opcode() == spv::Op::OpLoad);
   assert(value->GetSingleWordInOperand(0) == var->result_id());
   std::vector<Instruction*> work_list;
   bool failed = !get_def_use_mgr()->WhileEachUser(
       value->result_id(), [this, &work_list](Instruction* use) {
-        if (use->opcode() != SpvOpCompositeExtract) {
+        if (use->opcode() != spv::Op::OpCompositeExtract) {
           context()->EmitErrorMessage(
               "Variable cannot be replaced: invalid instruction", use);
           return false;
@@ -384,7 +385,7 @@
 
 bool DescriptorScalarReplacement::ReplaceCompositeExtract(
     Instruction* var, Instruction* extract) {
-  assert(extract->opcode() == SpvOpCompositeExtract);
+  assert(extract->opcode() == spv::Op::OpCompositeExtract);
   // We're currently only supporting extractions of one index at a time. If we
   // need to, we can handle cases with multiple indexes in the future.
   if (extract->NumInOperands() != 2) {
@@ -400,7 +401,7 @@
   // OpCompositeExtract.
   uint32_t load_id = TakeNextId();
   std::unique_ptr<Instruction> load(
-      new Instruction(context(), SpvOpLoad, extract->type_id(), load_id,
+      new Instruction(context(), spv::Op::OpLoad, extract->type_id(), load_id,
                       std::initializer_list<Operand>{
                           {SPV_OPERAND_TYPE_ID, {replacement_var}}}));
   Instruction* load_instr = load.get();
diff --git a/source/opt/desc_sroa_util.cpp b/source/opt/desc_sroa_util.cpp
index 1954e2c..41b8f19 100644
--- a/source/opt/desc_sroa_util.cpp
+++ b/source/opt/desc_sroa_util.cpp
@@ -22,7 +22,7 @@
 
 // Returns the length of array type |type|.
 uint32_t GetLengthOfArrayType(IRContext* context, Instruction* type) {
-  assert(type->opcode() == SpvOpTypeArray && "type must be array");
+  assert(type->opcode() == spv::Op::OpTypeArray && "type must be array");
   uint32_t length_id = type->GetSingleWordInOperand(1);
   const analysis::Constant* length_const =
       context->get_constant_mgr()->FindDeclaredConstant(length_id);
@@ -35,20 +35,20 @@
 namespace descsroautil {
 
 bool IsDescriptorArray(IRContext* context, Instruction* var) {
-  if (var->opcode() != SpvOpVariable) {
+  if (var->opcode() != spv::Op::OpVariable) {
     return false;
   }
 
   uint32_t ptr_type_id = var->type_id();
   Instruction* ptr_type_inst = context->get_def_use_mgr()->GetDef(ptr_type_id);
-  if (ptr_type_inst->opcode() != SpvOpTypePointer) {
+  if (ptr_type_inst->opcode() != spv::Op::OpTypePointer) {
     return false;
   }
 
   uint32_t var_type_id = ptr_type_inst->GetSingleWordInOperand(1);
   Instruction* var_type_inst = context->get_def_use_mgr()->GetDef(var_type_id);
-  if (var_type_inst->opcode() != SpvOpTypeArray &&
-      var_type_inst->opcode() != SpvOpTypeStruct) {
+  if (var_type_inst->opcode() != spv::Op::OpTypeArray &&
+      var_type_inst->opcode() != spv::Op::OpTypeStruct) {
     return false;
   }
 
@@ -59,23 +59,23 @@
   }
 
   if (!context->get_decoration_mgr()->HasDecoration(
-          var->result_id(), SpvDecorationDescriptorSet)) {
+          var->result_id(), uint32_t(spv::Decoration::DescriptorSet))) {
     return false;
   }
 
-  return context->get_decoration_mgr()->HasDecoration(var->result_id(),
-                                                      SpvDecorationBinding);
+  return context->get_decoration_mgr()->HasDecoration(
+      var->result_id(), uint32_t(spv::Decoration::Binding));
 }
 
 bool IsTypeOfStructuredBuffer(IRContext* context, const Instruction* type) {
-  if (type->opcode() != SpvOpTypeStruct) {
+  if (type->opcode() != spv::Op::OpTypeStruct) {
     return false;
   }
 
   // All buffers have offset decorations for members of their structure types.
   // This is how we distinguish it from a structure of descriptors.
-  return context->get_decoration_mgr()->HasDecoration(type->result_id(),
-                                                      SpvDecorationOffset);
+  return context->get_decoration_mgr()->HasDecoration(
+      type->result_id(), uint32_t(spv::Decoration::Offset));
 }
 
 const analysis::Constant* GetAccessChainIndexAsConst(
@@ -99,15 +99,15 @@
                                              Instruction* var) {
   uint32_t ptr_type_id = var->type_id();
   Instruction* ptr_type_inst = context->get_def_use_mgr()->GetDef(ptr_type_id);
-  assert(ptr_type_inst->opcode() == SpvOpTypePointer &&
+  assert(ptr_type_inst->opcode() == spv::Op::OpTypePointer &&
          "Variable should be a pointer to an array or structure.");
   uint32_t pointee_type_id = ptr_type_inst->GetSingleWordInOperand(1);
   Instruction* pointee_type_inst =
       context->get_def_use_mgr()->GetDef(pointee_type_id);
-  if (pointee_type_inst->opcode() == SpvOpTypeArray) {
+  if (pointee_type_inst->opcode() == spv::Op::OpTypeArray) {
     return GetLengthOfArrayType(context, pointee_type_inst);
   }
-  assert(pointee_type_inst->opcode() == SpvOpTypeStruct &&
+  assert(pointee_type_inst->opcode() == spv::Op::OpTypeStruct &&
          "Variable should be a pointer to an array or structure.");
   return pointee_type_inst->NumInOperands();
 }
diff --git a/source/opt/dominator_analysis.cpp b/source/opt/dominator_analysis.cpp
index b692d26..eb6dfc9 100644
--- a/source/opt/dominator_analysis.cpp
+++ b/source/opt/dominator_analysis.cpp
@@ -64,7 +64,7 @@
 
   // We handle OpLabel instructions explicitly since they are not stored in the
   // instruction list.
-  if (current->opcode() == SpvOpLabel) {
+  if (current->opcode() == spv::Op::OpLabel) {
     return true;
   }
 
diff --git a/source/opt/eliminate_dead_constant_pass.cpp b/source/opt/eliminate_dead_constant_pass.cpp
index d368bd1..d021515 100644
--- a/source/opt/eliminate_dead_constant_pass.cpp
+++ b/source/opt/eliminate_dead_constant_pass.cpp
@@ -40,7 +40,7 @@
     context()->get_def_use_mgr()->ForEachUse(
         const_id, [&count](Instruction* user, uint32_t index) {
           (void)index;
-          SpvOp op = user->opcode();
+          spv::Op op = user->opcode();
           if (!(IsAnnotationInst(op) || IsDebug1Inst(op) || IsDebug2Inst(op) ||
                 IsDebug3Inst(op))) {
             ++count;
@@ -59,9 +59,9 @@
     Instruction* inst = *working_list.begin();
     // Back propagate if the instruction contains IDs in its operands.
     switch (inst->opcode()) {
-      case SpvOp::SpvOpConstantComposite:
-      case SpvOp::SpvOpSpecConstantComposite:
-      case SpvOp::SpvOpSpecConstantOp:
+      case spv::Op::OpConstantComposite:
+      case spv::Op::OpSpecConstantComposite:
+      case spv::Op::OpSpecConstantOp:
         for (uint32_t i = 0; i < inst->NumInOperands(); i++) {
           // SpecConstantOp instruction contains 'opcode' as its operand. Need
           // to exclude such operands when decreasing uses.
diff --git a/source/opt/eliminate_dead_functions_util.cpp b/source/opt/eliminate_dead_functions_util.cpp
index 1379120..cf7f92f 100644
--- a/source/opt/eliminate_dead_functions_util.cpp
+++ b/source/opt/eliminate_dead_functions_util.cpp
@@ -28,12 +28,12 @@
       ->ForEachInst(
           [context, first_func, func_iter, &seen_func_end,
            &to_kill](Instruction* inst) {
-            if (inst->opcode() == SpvOpFunctionEnd) {
+            if (inst->opcode() == spv::Op::OpFunctionEnd) {
               seen_func_end = true;
             }
             // Move non-semantic instructions to the previous function or
             // global values if this is the first function.
-            if (seen_func_end && inst->opcode() == SpvOpExtInst) {
+            if (seen_func_end && inst->opcode() == spv::Op::OpExtInst) {
               assert(inst->IsNonSemanticInstruction());
               if (to_kill.find(inst) != to_kill.end()) return;
               std::unique_ptr<Instruction> clone(inst->Clone(context));
diff --git a/source/opt/eliminate_dead_input_components_pass.cpp b/source/opt/eliminate_dead_input_components_pass.cpp
index aa2776b..de75abd 100644
--- a/source/opt/eliminate_dead_input_components_pass.cpp
+++ b/source/opt/eliminate_dead_input_components_pass.cpp
@@ -37,14 +37,14 @@
 
 Pass::Status EliminateDeadInputComponentsPass::Process() {
   // Current functionality assumes shader capability
-  if (!context()->get_feature_mgr()->HasCapability(SpvCapabilityShader))
+  if (!context()->get_feature_mgr()->HasCapability(spv::Capability::Shader))
     return Status::SuccessWithoutChange;
   analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
   analysis::TypeManager* type_mgr = context()->get_type_mgr();
   bool modified = false;
   std::vector<std::pair<Instruction*, unsigned>> arrays_to_change;
   for (auto& var : context()->types_values()) {
-    if (var.opcode() != SpvOpVariable) {
+    if (var.opcode() != spv::Op::OpVariable) {
       continue;
     }
     analysis::Type* var_type = type_mgr->GetType(var.type_id());
@@ -52,14 +52,14 @@
     if (ptr_type == nullptr) {
       continue;
     }
-    if (ptr_type->storage_class() != SpvStorageClassInput) {
+    if (ptr_type->storage_class() != spv::StorageClass::Input) {
       continue;
     }
     const analysis::Array* arr_type = ptr_type->pointee_type()->AsArray();
     if (arr_type != nullptr) {
       unsigned arr_len_id = arr_type->LengthId();
       Instruction* arr_len_inst = def_use_mgr->GetDef(arr_len_id);
-      if (arr_len_inst->opcode() != SpvOpConstant) {
+      if (arr_len_inst->opcode() != spv::Op::OpConstant) {
         continue;
       }
       // SPIR-V requires array size is >= 1, so this works for signed or
@@ -91,18 +91,19 @@
                                                         unsigned original_max) {
   unsigned max = 0;
   bool seen_non_const_ac = false;
-  assert(var.opcode() == SpvOpVariable && "must be variable");
+  assert(var.opcode() == spv::Op::OpVariable && "must be variable");
   context()->get_def_use_mgr()->WhileEachUser(
       var.result_id(), [&max, &seen_non_const_ac, var, this](Instruction* use) {
         auto use_opcode = use->opcode();
-        if (use_opcode == SpvOpLoad || use_opcode == SpvOpCopyMemory ||
-            use_opcode == SpvOpCopyMemorySized ||
-            use_opcode == SpvOpCopyObject) {
+        if (use_opcode == spv::Op::OpLoad ||
+            use_opcode == spv::Op::OpCopyMemory ||
+            use_opcode == spv::Op::OpCopyMemorySized ||
+            use_opcode == spv::Op::OpCopyObject) {
           seen_non_const_ac = true;
           return false;
         }
-        if (use->opcode() != SpvOpAccessChain &&
-            use->opcode() != SpvOpInBoundsAccessChain) {
+        if (use->opcode() != spv::Op::OpAccessChain &&
+            use->opcode() != spv::Op::OpInBoundsAccessChain) {
           return true;
         }
         // OpAccessChain with no indices currently not optimized
@@ -114,7 +115,7 @@
         USE_ASSERT(base_id == var.result_id() && "unexpected base");
         unsigned idx_id = use->GetSingleWordInOperand(kAccessChainIndex0InIdx);
         Instruction* idx_inst = context()->get_def_use_mgr()->GetDef(idx_id);
-        if (idx_inst->opcode() != SpvOpConstant) {
+        if (idx_inst->opcode() != spv::Op::OpConstant) {
           seen_non_const_ac = true;
           return false;
         }
@@ -138,14 +139,14 @@
   analysis::Array new_arr_ty(arr_ty->element_type(),
                              arr_ty->GetConstantLengthInfo(length_id, length));
   analysis::Type* reg_new_arr_ty = type_mgr->GetRegisteredType(&new_arr_ty);
-  analysis::Pointer new_ptr_ty(reg_new_arr_ty, SpvStorageClassInput);
+  analysis::Pointer new_ptr_ty(reg_new_arr_ty, spv::StorageClass::Input);
   analysis::Type* reg_new_ptr_ty = type_mgr->GetRegisteredType(&new_ptr_ty);
   uint32_t new_ptr_ty_id = type_mgr->GetTypeInstruction(reg_new_ptr_ty);
   arr_var.SetResultType(new_ptr_ty_id);
   def_use_mgr->AnalyzeInstUse(&arr_var);
   // Move arr_var after its new type to preserve order
-  USE_ASSERT(arr_var.GetSingleWordInOperand(kVariableStorageClassInIdx) !=
-                 SpvStorageClassFunction &&
+  USE_ASSERT(spv::StorageClass(arr_var.GetSingleWordInOperand(
+                 kVariableStorageClassInIdx)) != spv::StorageClass::Function &&
              "cannot move Function variable");
   Instruction* new_ptr_ty_inst = def_use_mgr->GetDef(new_ptr_ty_id);
   arr_var.RemoveFromList();
@@ -170,15 +171,15 @@
   uint32_t old_struct_ty_id = type_mgr->GetTypeInstruction(struct_ty);
   analysis::DecorationManager* deco_mgr = context()->get_decoration_mgr();
   deco_mgr->CloneDecorations(old_struct_ty_id, new_struct_ty_id);
-  analysis::Pointer new_ptr_ty(reg_new_struct_ty, SpvStorageClassInput);
+  analysis::Pointer new_ptr_ty(reg_new_struct_ty, spv::StorageClass::Input);
   analysis::Type* reg_new_ptr_ty = type_mgr->GetRegisteredType(&new_ptr_ty);
   uint32_t new_ptr_ty_id = type_mgr->GetTypeInstruction(reg_new_ptr_ty);
   struct_var.SetResultType(new_ptr_ty_id);
   analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
   def_use_mgr->AnalyzeInstUse(&struct_var);
   // Move struct_var after its new type to preserve order
-  USE_ASSERT(struct_var.GetSingleWordInOperand(kVariableStorageClassInIdx) !=
-                 SpvStorageClassFunction &&
+  USE_ASSERT(spv::StorageClass(struct_var.GetSingleWordInOperand(
+                 kVariableStorageClassInIdx)) != spv::StorageClass::Function &&
              "cannot move Function variable");
   Instruction* new_ptr_ty_inst = def_use_mgr->GetDef(new_ptr_ty_id);
   struct_var.RemoveFromList();
diff --git a/source/opt/eliminate_dead_members_pass.cpp b/source/opt/eliminate_dead_members_pass.cpp
index 52aca52..9cf9f15 100644
--- a/source/opt/eliminate_dead_members_pass.cpp
+++ b/source/opt/eliminate_dead_members_pass.cpp
@@ -27,7 +27,7 @@
 namespace opt {
 
 Pass::Status EliminateDeadMembersPass::Process() {
-  if (!context()->get_feature_mgr()->HasCapability(SpvCapabilityShader))
+  if (!context()->get_feature_mgr()->HasCapability(spv::Capability::Shader))
     return Status::SuccessWithoutChange;
 
   FindLiveMembers();
@@ -41,27 +41,27 @@
   // Until we have implemented the rewriting of OpSpecConsantOp instructions,
   // we have to mark them as fully used just to be safe.
   for (auto& inst : get_module()->types_values()) {
-    if (inst.opcode() == SpvOpSpecConstantOp) {
-      switch (inst.GetSingleWordInOperand(kSpecConstOpOpcodeIdx)) {
-        case SpvOpCompositeExtract:
+    if (inst.opcode() == spv::Op::OpSpecConstantOp) {
+      switch (spv::Op(inst.GetSingleWordInOperand(kSpecConstOpOpcodeIdx))) {
+        case spv::Op::OpCompositeExtract:
           MarkMembersAsLiveForExtract(&inst);
           break;
-        case SpvOpCompositeInsert:
+        case spv::Op::OpCompositeInsert:
           // Nothing specific to do.
           break;
-        case SpvOpAccessChain:
-        case SpvOpInBoundsAccessChain:
-        case SpvOpPtrAccessChain:
-        case SpvOpInBoundsPtrAccessChain:
+        case spv::Op::OpAccessChain:
+        case spv::Op::OpInBoundsAccessChain:
+        case spv::Op::OpPtrAccessChain:
+        case spv::Op::OpInBoundsPtrAccessChain:
           assert(false && "Not implemented yet.");
           break;
         default:
           break;
       }
-    } else if (inst.opcode() == SpvOpVariable) {
-      switch (inst.GetSingleWordInOperand(0)) {
-        case SpvStorageClassInput:
-        case SpvStorageClassOutput:
+    } else if (inst.opcode() == spv::Op::OpVariable) {
+      switch (spv::StorageClass(inst.GetSingleWordInOperand(0))) {
+        case spv::StorageClass::Input:
+        case spv::StorageClass::Output:
           MarkPointeeTypeAsFullUsed(inst.type_id());
           break;
         default:
@@ -86,34 +86,34 @@
 
 void EliminateDeadMembersPass::FindLiveMembers(const Instruction* inst) {
   switch (inst->opcode()) {
-    case SpvOpStore:
+    case spv::Op::OpStore:
       MarkMembersAsLiveForStore(inst);
       break;
-    case SpvOpCopyMemory:
-    case SpvOpCopyMemorySized:
+    case spv::Op::OpCopyMemory:
+    case spv::Op::OpCopyMemorySized:
       MarkMembersAsLiveForCopyMemory(inst);
       break;
-    case SpvOpCompositeExtract:
+    case spv::Op::OpCompositeExtract:
       MarkMembersAsLiveForExtract(inst);
       break;
-    case SpvOpAccessChain:
-    case SpvOpInBoundsAccessChain:
-    case SpvOpPtrAccessChain:
-    case SpvOpInBoundsPtrAccessChain:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
+    case spv::Op::OpPtrAccessChain:
+    case spv::Op::OpInBoundsPtrAccessChain:
       MarkMembersAsLiveForAccessChain(inst);
       break;
-    case SpvOpReturnValue:
+    case spv::Op::OpReturnValue:
       // This should be an issue only if we are returning from the entry point.
       // However, for now I will keep it more conservative because functions are
       // often inlined leaving only the entry points.
       MarkOperandTypeAsFullyUsed(inst, 0);
       break;
-    case SpvOpArrayLength:
+    case spv::Op::OpArrayLength:
       MarkMembersAsLiveForArrayLength(inst);
       break;
-    case SpvOpLoad:
-    case SpvOpCompositeInsert:
-    case SpvOpCompositeConstruct:
+    case spv::Op::OpLoad:
+    case spv::Op::OpCompositeInsert:
+    case spv::Op::OpCompositeConstruct:
       break;
     default:
       // This path is here for safety.  All instructions that can reference
@@ -131,7 +131,7 @@
   // memory that is read outside of the shader.  Other passes can remove all
   // store to memory that is not visible outside of the shader, so we do not
   // complicate the code for now.
-  assert(inst->opcode() == SpvOpStore);
+  assert(inst->opcode() == spv::Op::OpStore);
   uint32_t object_id = inst->GetSingleWordInOperand(1);
   Instruction* object_inst = context()->get_def_use_mgr()->GetDef(object_id);
   uint32_t object_type_id = object_inst->type_id();
@@ -143,15 +143,15 @@
   assert(type_inst != nullptr);
 
   switch (type_inst->opcode()) {
-    case SpvOpTypeStruct:
+    case spv::Op::OpTypeStruct:
       // Mark every member and its type as fully used.
       for (uint32_t i = 0; i < type_inst->NumInOperands(); ++i) {
         used_members_[type_id].insert(i);
         MarkTypeAsFullyUsed(type_inst->GetSingleWordInOperand(i));
       }
       break;
-    case SpvOpTypeArray:
-    case SpvOpTypeRuntimeArray:
+    case spv::Op::OpTypeArray:
+    case spv::Op::OpTypeRuntimeArray:
       MarkTypeAsFullyUsed(
           type_inst->GetSingleWordInOperand(kArrayElementTypeIdx));
       break;
@@ -162,7 +162,7 @@
 
 void EliminateDeadMembersPass::MarkPointeeTypeAsFullUsed(uint32_t ptr_type_id) {
   Instruction* ptr_type_inst = get_def_use_mgr()->GetDef(ptr_type_id);
-  assert(ptr_type_inst->opcode() == SpvOpTypePointer);
+  assert(ptr_type_inst->opcode() == spv::Op::OpTypePointer);
   MarkTypeAsFullyUsed(ptr_type_inst->GetSingleWordInOperand(1));
 }
 
@@ -178,12 +178,13 @@
 
 void EliminateDeadMembersPass::MarkMembersAsLiveForExtract(
     const Instruction* inst) {
-  assert(inst->opcode() == SpvOpCompositeExtract ||
-         (inst->opcode() == SpvOpSpecConstantOp &&
-          inst->GetSingleWordInOperand(kSpecConstOpOpcodeIdx) ==
-              SpvOpCompositeExtract));
+  assert(inst->opcode() == spv::Op::OpCompositeExtract ||
+         (inst->opcode() == spv::Op::OpSpecConstantOp &&
+          spv::Op(inst->GetSingleWordInOperand(kSpecConstOpOpcodeIdx)) ==
+              spv::Op::OpCompositeExtract));
 
-  uint32_t first_operand = (inst->opcode() == SpvOpSpecConstantOp ? 1 : 0);
+  uint32_t first_operand =
+      (inst->opcode() == spv::Op::OpSpecConstantOp ? 1 : 0);
   uint32_t composite_id = inst->GetSingleWordInOperand(first_operand);
   Instruction* composite_inst = get_def_use_mgr()->GetDef(composite_id);
   uint32_t type_id = composite_inst->type_id();
@@ -192,14 +193,14 @@
     Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
     uint32_t member_idx = inst->GetSingleWordInOperand(i);
     switch (type_inst->opcode()) {
-      case SpvOpTypeStruct:
+      case spv::Op::OpTypeStruct:
         used_members_[type_id].insert(member_idx);
         type_id = type_inst->GetSingleWordInOperand(member_idx);
         break;
-      case SpvOpTypeArray:
-      case SpvOpTypeRuntimeArray:
-      case SpvOpTypeVector:
-      case SpvOpTypeMatrix:
+      case spv::Op::OpTypeArray:
+      case spv::Op::OpTypeRuntimeArray:
+      case spv::Op::OpTypeVector:
+      case spv::Op::OpTypeMatrix:
         type_id = type_inst->GetSingleWordInOperand(0);
         break;
       default:
@@ -210,10 +211,10 @@
 
 void EliminateDeadMembersPass::MarkMembersAsLiveForAccessChain(
     const Instruction* inst) {
-  assert(inst->opcode() == SpvOpAccessChain ||
-         inst->opcode() == SpvOpInBoundsAccessChain ||
-         inst->opcode() == SpvOpPtrAccessChain ||
-         inst->opcode() == SpvOpInBoundsPtrAccessChain);
+  assert(inst->opcode() == spv::Op::OpAccessChain ||
+         inst->opcode() == spv::Op::OpInBoundsAccessChain ||
+         inst->opcode() == spv::Op::OpPtrAccessChain ||
+         inst->opcode() == spv::Op::OpInBoundsPtrAccessChain);
 
   uint32_t pointer_id = inst->GetSingleWordInOperand(0);
   Instruction* pointer_inst = get_def_use_mgr()->GetDef(pointer_id);
@@ -225,14 +226,14 @@
 
   // For a pointer access chain, we need to skip the |element| index.  It is not
   // a reference to the member of a struct, and it does not change the type.
-  uint32_t i = (inst->opcode() == SpvOpAccessChain ||
-                        inst->opcode() == SpvOpInBoundsAccessChain
+  uint32_t i = (inst->opcode() == spv::Op::OpAccessChain ||
+                        inst->opcode() == spv::Op::OpInBoundsAccessChain
                     ? 1
                     : 2);
   for (; i < inst->NumInOperands(); ++i) {
     Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
     switch (type_inst->opcode()) {
-      case SpvOpTypeStruct: {
+      case spv::Op::OpTypeStruct: {
         const analysis::IntConstant* member_idx =
             const_mgr->FindDeclaredConstant(inst->GetSingleWordInOperand(i))
                 ->AsIntConstant();
@@ -242,10 +243,10 @@
         used_members_[type_id].insert(index);
         type_id = type_inst->GetSingleWordInOperand(index);
       } break;
-      case SpvOpTypeArray:
-      case SpvOpTypeRuntimeArray:
-      case SpvOpTypeVector:
-      case SpvOpTypeMatrix:
+      case spv::Op::OpTypeArray:
+      case spv::Op::OpTypeRuntimeArray:
+      case spv::Op::OpTypeVector:
+      case spv::Op::OpTypeMatrix:
         type_id = type_inst->GetSingleWordInOperand(0);
         break;
       default:
@@ -263,7 +264,7 @@
 
 void EliminateDeadMembersPass::MarkMembersAsLiveForArrayLength(
     const Instruction* inst) {
-  assert(inst->opcode() == SpvOpArrayLength);
+  assert(inst->opcode() == spv::Op::OpArrayLength);
   uint32_t object_id = inst->GetSingleWordInOperand(0);
   Instruction* object_inst = get_def_use_mgr()->GetDef(object_id);
   uint32_t pointer_type_id = object_inst->type_id();
@@ -278,7 +279,7 @@
   // First update all of the OpTypeStruct instructions.
   get_module()->ForEachInst([&modified, this](Instruction* inst) {
     switch (inst->opcode()) {
-      case SpvOpTypeStruct:
+      case spv::Op::OpTypeStruct:
         modified |= UpdateOpTypeStruct(inst);
         break;
       default:
@@ -289,47 +290,47 @@
   // Now update all of the instructions that reference the OpTypeStructs.
   get_module()->ForEachInst([&modified, this](Instruction* inst) {
     switch (inst->opcode()) {
-      case SpvOpMemberName:
+      case spv::Op::OpMemberName:
         modified |= UpdateOpMemberNameOrDecorate(inst);
         break;
-      case SpvOpMemberDecorate:
+      case spv::Op::OpMemberDecorate:
         modified |= UpdateOpMemberNameOrDecorate(inst);
         break;
-      case SpvOpGroupMemberDecorate:
+      case spv::Op::OpGroupMemberDecorate:
         modified |= UpdateOpGroupMemberDecorate(inst);
         break;
-      case SpvOpSpecConstantComposite:
-      case SpvOpConstantComposite:
-      case SpvOpCompositeConstruct:
+      case spv::Op::OpSpecConstantComposite:
+      case spv::Op::OpConstantComposite:
+      case spv::Op::OpCompositeConstruct:
         modified |= UpdateConstantComposite(inst);
         break;
-      case SpvOpAccessChain:
-      case SpvOpInBoundsAccessChain:
-      case SpvOpPtrAccessChain:
-      case SpvOpInBoundsPtrAccessChain:
+      case spv::Op::OpAccessChain:
+      case spv::Op::OpInBoundsAccessChain:
+      case spv::Op::OpPtrAccessChain:
+      case spv::Op::OpInBoundsPtrAccessChain:
         modified |= UpdateAccessChain(inst);
         break;
-      case SpvOpCompositeExtract:
+      case spv::Op::OpCompositeExtract:
         modified |= UpdateCompsiteExtract(inst);
         break;
-      case SpvOpCompositeInsert:
+      case spv::Op::OpCompositeInsert:
         modified |= UpdateCompositeInsert(inst);
         break;
-      case SpvOpArrayLength:
+      case spv::Op::OpArrayLength:
         modified |= UpdateOpArrayLength(inst);
         break;
-      case SpvOpSpecConstantOp:
-        switch (inst->GetSingleWordInOperand(kSpecConstOpOpcodeIdx)) {
-          case SpvOpCompositeExtract:
+      case spv::Op::OpSpecConstantOp:
+        switch (spv::Op(inst->GetSingleWordInOperand(kSpecConstOpOpcodeIdx))) {
+          case spv::Op::OpCompositeExtract:
             modified |= UpdateCompsiteExtract(inst);
             break;
-          case SpvOpCompositeInsert:
+          case spv::Op::OpCompositeInsert:
             modified |= UpdateCompositeInsert(inst);
             break;
-          case SpvOpAccessChain:
-          case SpvOpInBoundsAccessChain:
-          case SpvOpPtrAccessChain:
-          case SpvOpInBoundsPtrAccessChain:
+          case spv::Op::OpAccessChain:
+          case spv::Op::OpInBoundsAccessChain:
+          case spv::Op::OpPtrAccessChain:
+          case spv::Op::OpInBoundsPtrAccessChain:
             assert(false && "Not implemented yet.");
             break;
           default:
@@ -344,7 +345,7 @@
 }
 
 bool EliminateDeadMembersPass::UpdateOpTypeStruct(Instruction* inst) {
-  assert(inst->opcode() == SpvOpTypeStruct);
+  assert(inst->opcode() == spv::Op::OpTypeStruct);
 
   const auto& live_members = used_members_[inst->result_id()];
   if (live_members.size() == inst->NumInOperands()) {
@@ -362,8 +363,8 @@
 }
 
 bool EliminateDeadMembersPass::UpdateOpMemberNameOrDecorate(Instruction* inst) {
-  assert(inst->opcode() == SpvOpMemberName ||
-         inst->opcode() == SpvOpMemberDecorate);
+  assert(inst->opcode() == spv::Op::OpMemberName ||
+         inst->opcode() == spv::Op::OpMemberDecorate);
 
   uint32_t type_id = inst->GetSingleWordInOperand(0);
   auto live_members = used_members_.find(type_id);
@@ -388,7 +389,7 @@
 }
 
 bool EliminateDeadMembersPass::UpdateOpGroupMemberDecorate(Instruction* inst) {
-  assert(inst->opcode() == SpvOpGroupMemberDecorate);
+  assert(inst->opcode() == spv::Op::OpGroupMemberDecorate);
 
   bool modified = false;
 
@@ -429,9 +430,9 @@
 }
 
 bool EliminateDeadMembersPass::UpdateConstantComposite(Instruction* inst) {
-  assert(inst->opcode() == SpvOpSpecConstantComposite ||
-         inst->opcode() == SpvOpConstantComposite ||
-         inst->opcode() == SpvOpCompositeConstruct);
+  assert(inst->opcode() == spv::Op::OpSpecConstantComposite ||
+         inst->opcode() == spv::Op::OpConstantComposite ||
+         inst->opcode() == spv::Op::OpCompositeConstruct);
   uint32_t type_id = inst->type_id();
 
   bool modified = false;
@@ -450,10 +451,10 @@
 }
 
 bool EliminateDeadMembersPass::UpdateAccessChain(Instruction* inst) {
-  assert(inst->opcode() == SpvOpAccessChain ||
-         inst->opcode() == SpvOpInBoundsAccessChain ||
-         inst->opcode() == SpvOpPtrAccessChain ||
-         inst->opcode() == SpvOpInBoundsPtrAccessChain);
+  assert(inst->opcode() == spv::Op::OpAccessChain ||
+         inst->opcode() == spv::Op::OpInBoundsAccessChain ||
+         inst->opcode() == spv::Op::OpPtrAccessChain ||
+         inst->opcode() == spv::Op::OpInBoundsPtrAccessChain);
 
   uint32_t pointer_id = inst->GetSingleWordInOperand(0);
   Instruction* pointer_inst = get_def_use_mgr()->GetDef(pointer_id);
@@ -467,8 +468,8 @@
   new_operands.emplace_back(inst->GetInOperand(0));
 
   // For pointer access chains we want to copy the element operand.
-  if (inst->opcode() == SpvOpPtrAccessChain ||
-      inst->opcode() == SpvOpInBoundsPtrAccessChain) {
+  if (inst->opcode() == spv::Op::OpPtrAccessChain ||
+      inst->opcode() == spv::Op::OpInBoundsPtrAccessChain) {
     new_operands.emplace_back(inst->GetInOperand(1));
   }
 
@@ -476,7 +477,7 @@
        i < inst->NumInOperands(); ++i) {
     Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
     switch (type_inst->opcode()) {
-      case SpvOpTypeStruct: {
+      case spv::Op::OpTypeStruct: {
         const analysis::IntConstant* member_idx =
             const_mgr->FindDeclaredConstant(inst->GetSingleWordInOperand(i))
                 ->AsIntConstant();
@@ -501,10 +502,10 @@
         // index.
         type_id = type_inst->GetSingleWordInOperand(new_member_idx);
       } break;
-      case SpvOpTypeArray:
-      case SpvOpTypeRuntimeArray:
-      case SpvOpTypeVector:
-      case SpvOpTypeMatrix:
+      case spv::Op::OpTypeArray:
+      case spv::Op::OpTypeRuntimeArray:
+      case spv::Op::OpTypeVector:
+      case spv::Op::OpTypeMatrix:
         new_operands.emplace_back(inst->GetInOperand(i));
         type_id = type_inst->GetSingleWordInOperand(0);
         break;
@@ -539,13 +540,13 @@
 }
 
 bool EliminateDeadMembersPass::UpdateCompsiteExtract(Instruction* inst) {
-  assert(inst->opcode() == SpvOpCompositeExtract ||
-         (inst->opcode() == SpvOpSpecConstantOp &&
-          inst->GetSingleWordInOperand(kSpecConstOpOpcodeIdx) ==
-              SpvOpCompositeExtract));
+  assert(inst->opcode() == spv::Op::OpCompositeExtract ||
+         (inst->opcode() == spv::Op::OpSpecConstantOp &&
+          spv::Op(inst->GetSingleWordInOperand(kSpecConstOpOpcodeIdx)) ==
+              spv::Op::OpCompositeExtract));
 
   uint32_t first_operand = 0;
-  if (inst->opcode() == SpvOpSpecConstantOp) {
+  if (inst->opcode() == spv::Op::OpSpecConstantOp) {
     first_operand = 1;
   }
   uint32_t object_id = inst->GetSingleWordInOperand(first_operand);
@@ -569,15 +570,15 @@
 
     Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
     switch (type_inst->opcode()) {
-      case SpvOpTypeStruct:
+      case spv::Op::OpTypeStruct:
         // The type will have already been rewritten, so use the new member
         // index.
         type_id = type_inst->GetSingleWordInOperand(new_member_idx);
         break;
-      case SpvOpTypeArray:
-      case SpvOpTypeRuntimeArray:
-      case SpvOpTypeVector:
-      case SpvOpTypeMatrix:
+      case spv::Op::OpTypeArray:
+      case spv::Op::OpTypeRuntimeArray:
+      case spv::Op::OpTypeVector:
+      case spv::Op::OpTypeMatrix:
         type_id = type_inst->GetSingleWordInOperand(0);
         break;
       default:
@@ -594,13 +595,13 @@
 }
 
 bool EliminateDeadMembersPass::UpdateCompositeInsert(Instruction* inst) {
-  assert(inst->opcode() == SpvOpCompositeInsert ||
-         (inst->opcode() == SpvOpSpecConstantOp &&
-          inst->GetSingleWordInOperand(kSpecConstOpOpcodeIdx) ==
-              SpvOpCompositeInsert));
+  assert(inst->opcode() == spv::Op::OpCompositeInsert ||
+         (inst->opcode() == spv::Op::OpSpecConstantOp &&
+          spv::Op(inst->GetSingleWordInOperand(kSpecConstOpOpcodeIdx)) ==
+              spv::Op::OpCompositeInsert));
 
   uint32_t first_operand = 0;
-  if (inst->opcode() == SpvOpSpecConstantOp) {
+  if (inst->opcode() == spv::Op::OpSpecConstantOp) {
     first_operand = 1;
   }
 
@@ -630,15 +631,15 @@
 
     Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
     switch (type_inst->opcode()) {
-      case SpvOpTypeStruct:
+      case spv::Op::OpTypeStruct:
         // The type will have already been rewritten, so use the new member
         // index.
         type_id = type_inst->GetSingleWordInOperand(new_member_idx);
         break;
-      case SpvOpTypeArray:
-      case SpvOpTypeRuntimeArray:
-      case SpvOpTypeVector:
-      case SpvOpTypeMatrix:
+      case spv::Op::OpTypeArray:
+      case spv::Op::OpTypeRuntimeArray:
+      case spv::Op::OpTypeVector:
+      case spv::Op::OpTypeMatrix:
         type_id = type_inst->GetSingleWordInOperand(0);
         break;
       default:
diff --git a/source/opt/eliminate_dead_output_stores_pass.cpp b/source/opt/eliminate_dead_output_stores_pass.cpp
index 9378898..3237c5a 100644
--- a/source/opt/eliminate_dead_output_stores_pass.cpp
+++ b/source/opt/eliminate_dead_output_stores_pass.cpp
@@ -34,7 +34,7 @@
 
 Pass::Status EliminateDeadOutputStoresPass::Process() {
   // Current functionality assumes shader capability
-  if (!context()->get_feature_mgr()->HasCapability(SpvCapabilityShader))
+  if (!context()->get_feature_mgr()->HasCapability(spv::Capability::Shader))
     return Status::SuccessWithoutChange;
   Pass::Status status = DoDeadOutputStoreElimination();
   return status;
@@ -59,15 +59,15 @@
 
 void EliminateDeadOutputStoresPass::KillAllStoresOfRef(Instruction* ref) {
   analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
-  if (ref->opcode() == SpvOpStore) {
+  if (ref->opcode() == spv::Op::OpStore) {
     kill_list_.push_back(ref);
     return;
   }
-  assert((ref->opcode() == SpvOpAccessChain ||
-          ref->opcode() == SpvOpInBoundsAccessChain) &&
+  assert((ref->opcode() == spv::Op::OpAccessChain ||
+          ref->opcode() == spv::Op::OpInBoundsAccessChain) &&
          "unexpected use of output variable");
   def_use_mgr->ForEachUser(ref, [this](Instruction* user) {
-    if (user->opcode() == SpvOpStore) kill_list_.push_back(user);
+    if (user->opcode() == spv::Op::OpStore) kill_list_.push_back(user);
   });
 }
 
@@ -80,15 +80,16 @@
   uint32_t start_loc = 0;
   auto var_id = var->result_id();
   bool no_loc = deco_mgr->WhileEachDecoration(
-      var_id, SpvDecorationLocation, [&start_loc](const Instruction& deco) {
-        assert(deco.opcode() == SpvOpDecorate && "unexpected decoration");
+      var_id, uint32_t(spv::Decoration::Location),
+      [&start_loc](const Instruction& deco) {
+        assert(deco.opcode() == spv::Op::OpDecorate && "unexpected decoration");
         start_loc = deco.GetSingleWordInOperand(kDecorationLocationInIdx);
         return false;
       });
   // Find patch decoration if present
   bool is_patch = !deco_mgr->WhileEachDecoration(
-      var_id, SpvDecorationPatch, [](const Instruction& deco) {
-        if (deco.opcode() != SpvOpDecorate)
+      var_id, uint32_t(spv::Decoration::Patch), [](const Instruction& deco) {
+        if (deco.opcode() != spv::Op::OpDecorate)
           assert(false && "unexpected decoration");
         return false;
       });
@@ -99,10 +100,11 @@
   auto var_type = ptr_type->pointee_type();
   uint32_t ref_loc = start_loc;
   auto curr_type = var_type;
-  if (ref->opcode() == SpvOpAccessChain ||
-      ref->opcode() == SpvOpInBoundsAccessChain)
+  if (ref->opcode() == spv::Op::OpAccessChain ||
+      ref->opcode() == spv::Op::OpInBoundsAccessChain) {
     live_mgr->AnalyzeAccessChainLoc(ref, &curr_type, &ref_loc, &no_loc,
                                     is_patch, /* input */ false);
+  }
   if (no_loc || AnyLocsAreLive(ref_loc, live_mgr->GetLocSize(curr_type)))
     return;
   // Kill all stores based on this reference
@@ -116,23 +118,27 @@
   auto type_mgr = context()->get_type_mgr();
   auto live_mgr = context()->get_liveness_mgr();
   // Search for builtin decoration of base variable
-  uint32_t builtin = SpvBuiltInMax;
+  uint32_t builtin = uint32_t(spv::BuiltIn::Max);
   auto var_id = var->result_id();
   (void)deco_mgr->WhileEachDecoration(
-      var_id, SpvDecorationBuiltIn, [&builtin](const Instruction& deco) {
-        assert(deco.opcode() == SpvOpDecorate && "unexpected decoration");
+      var_id, uint32_t(spv::Decoration::BuiltIn),
+      [&builtin](const Instruction& deco) {
+        assert(deco.opcode() == spv::Op::OpDecorate && "unexpected decoration");
         builtin = deco.GetSingleWordInOperand(kOpDecorateBuiltInLiteralInIdx);
         return false;
       });
   // If analyzed builtin and not live, kill stores.
-  if (builtin != SpvBuiltInMax) {
+  if (builtin != uint32_t(spv::BuiltIn::Max)) {
     if (live_mgr->IsAnalyzedBuiltin(builtin) && !IsLiveBuiltin(builtin))
       KillAllStoresOfRef(ref);
     return;
   }
   // Search for builtin decoration on indexed member
   auto ref_op = ref->opcode();
-  if (ref_op != SpvOpAccessChain && ref_op != SpvOpInBoundsAccessChain) return;
+  if (ref_op != spv::Op::OpAccessChain &&
+      ref_op != spv::Op::OpInBoundsAccessChain) {
+    return;
+  }
   uint32_t in_idx = kOpAccessChainIdx0InIdx;
   analysis::Type* var_type = type_mgr->GetType(var->type_id());
   analysis::Pointer* ptr_type = var_type->AsPointer();
@@ -146,13 +152,14 @@
   auto str_type_id = type_mgr->GetId(str_type);
   auto member_idx_id = ref->GetSingleWordInOperand(in_idx);
   auto member_idx_inst = def_use_mgr->GetDef(member_idx_id);
-  assert(member_idx_inst->opcode() == SpvOpConstant &&
+  assert(member_idx_inst->opcode() == spv::Op::OpConstant &&
          "unexpected non-constant index");
   auto ac_idx = member_idx_inst->GetSingleWordInOperand(kOpConstantValueInIdx);
   (void)deco_mgr->WhileEachDecoration(
-      str_type_id, SpvDecorationBuiltIn,
+      str_type_id, uint32_t(spv::Decoration::BuiltIn),
       [ac_idx, &builtin](const Instruction& deco) {
-        assert(deco.opcode() == SpvOpMemberDecorate && "unexpected decoration");
+        assert(deco.opcode() == spv::Op::OpMemberDecorate &&
+               "unexpected decoration");
         auto deco_idx =
             deco.GetSingleWordInOperand(kOpDecorateMemberMemberInIdx);
         if (deco_idx == ac_idx) {
@@ -162,7 +169,7 @@
         }
         return true;
       });
-  assert(builtin != SpvBuiltInMax && "builtin not found");
+  assert(builtin != uint32_t(spv::BuiltIn::Max) && "builtin not found");
   // If analyzed builtin and not live, kill stores.
   if (live_mgr->IsAnalyzedBuiltin(builtin) && !IsLiveBuiltin(builtin))
     KillAllStoresOfRef(ref);
@@ -171,10 +178,10 @@
 Pass::Status EliminateDeadOutputStoresPass::DoDeadOutputStoreElimination() {
   // Current implementation only supports vert, tesc, tese, geom shaders
   auto stage = context()->GetStage();
-  if (stage != SpvExecutionModelVertex &&
-      stage != SpvExecutionModelTessellationControl &&
-      stage != SpvExecutionModelTessellationEvaluation &&
-      stage != SpvExecutionModelGeometry)
+  if (stage != spv::ExecutionModel::Vertex &&
+      stage != spv::ExecutionModel::TessellationControl &&
+      stage != spv::ExecutionModel::TessellationEvaluation &&
+      stage != spv::ExecutionModel::Geometry)
     return Status::Failure;
   InitializeElimination();
   analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
@@ -182,18 +189,18 @@
   analysis::DecorationManager* deco_mgr = context()->get_decoration_mgr();
   // Process all output variables
   for (auto& var : context()->types_values()) {
-    if (var.opcode() != SpvOpVariable) {
+    if (var.opcode() != spv::Op::OpVariable) {
       continue;
     }
     analysis::Type* var_type = type_mgr->GetType(var.type_id());
     analysis::Pointer* ptr_type = var_type->AsPointer();
-    if (ptr_type->storage_class() != SpvStorageClassOutput) {
+    if (ptr_type->storage_class() != spv::StorageClass::Output) {
       continue;
     }
     // If builtin decoration on variable, process as builtin.
     auto var_id = var.result_id();
     bool is_builtin = false;
-    if (deco_mgr->HasDecoration(var_id, SpvDecorationBuiltIn)) {
+    if (deco_mgr->HasDecoration(var_id, uint32_t(spv::Decoration::BuiltIn))) {
       is_builtin = true;
     } else {
       // If interface block with builtin members, process as builtin.
@@ -204,7 +211,8 @@
       auto str_type = curr_type->AsStruct();
       if (str_type) {
         auto str_type_id = type_mgr->GetId(str_type);
-        if (deco_mgr->HasDecoration(str_type_id, SpvDecorationBuiltIn))
+        if (deco_mgr->HasDecoration(str_type_id,
+                                    uint32_t(spv::Decoration::BuiltIn)))
           is_builtin = true;
       }
     }
@@ -213,7 +221,8 @@
     def_use_mgr->ForEachUser(
         var_id, [this, &var, is_builtin](Instruction* user) {
           auto op = user->opcode();
-          if (op == SpvOpEntryPoint || op == SpvOpName || op == SpvOpDecorate)
+          if (op == spv::Op::OpEntryPoint || op == spv::Op::OpName ||
+              op == spv::Op::OpDecorate)
             return;
           if (is_builtin)
             KillAllDeadStoresOfBuiltinRef(user, &var);
diff --git a/source/opt/feature_manager.cpp b/source/opt/feature_manager.cpp
index a590271..2a1c006 100644
--- a/source/opt/feature_manager.cpp
+++ b/source/opt/feature_manager.cpp
@@ -36,7 +36,7 @@
 }
 
 void FeatureManager::AddExtension(Instruction* ext) {
-  assert(ext->opcode() == SpvOpExtension &&
+  assert(ext->opcode() == spv::Op::OpExtension &&
          "Expecting an extension instruction.");
 
   const std::string name = ext->GetInOperand(0u).AsString();
@@ -51,27 +51,27 @@
   extensions_.Remove(ext);
 }
 
-void FeatureManager::AddCapability(SpvCapability cap) {
+void FeatureManager::AddCapability(spv::Capability cap) {
   if (capabilities_.Contains(cap)) return;
 
   capabilities_.Add(cap);
 
   spv_operand_desc desc = {};
-  if (SPV_SUCCESS ==
-      grammar_.lookupOperand(SPV_OPERAND_TYPE_CAPABILITY, cap, &desc)) {
+  if (SPV_SUCCESS == grammar_.lookupOperand(SPV_OPERAND_TYPE_CAPABILITY,
+                                            uint32_t(cap), &desc)) {
     CapabilitySet(desc->numCapabilities, desc->capabilities)
-        .ForEach([this](SpvCapability c) { AddCapability(c); });
+        .ForEach([this](spv::Capability c) { AddCapability(c); });
   }
 }
 
-void FeatureManager::RemoveCapability(SpvCapability cap) {
+void FeatureManager::RemoveCapability(spv::Capability cap) {
   if (!capabilities_.Contains(cap)) return;
   capabilities_.Remove(cap);
 }
 
 void FeatureManager::AddCapabilities(Module* module) {
   for (Instruction& inst : module->capabilities()) {
-    AddCapability(static_cast<SpvCapability>(inst.GetSingleWordInOperand(0)));
+    AddCapability(static_cast<spv::Capability>(inst.GetSingleWordInOperand(0)));
   }
 }
 
diff --git a/source/opt/feature_manager.h b/source/opt/feature_manager.h
index 68c8e9a..b96988d 100644
--- a/source/opt/feature_manager.h
+++ b/source/opt/feature_manager.h
@@ -34,12 +34,12 @@
   void RemoveExtension(Extension extension);
 
   // Returns true if |cap| is an enabled capability in the module.
-  bool HasCapability(SpvCapability cap) const {
+  bool HasCapability(spv::Capability cap) const {
     return capabilities_.Contains(cap);
   }
 
   // Removes the given |capability| from the current FeatureManager.
-  void RemoveCapability(SpvCapability capability);
+  void RemoveCapability(spv::Capability capability);
 
   // Analyzes |module| and records enabled extensions and capabilities.
   void Analyze(Module* module);
@@ -66,7 +66,7 @@
 
   // Adds the given |capability| and all implied capabilities into the current
   // FeatureManager.
-  void AddCapability(SpvCapability capability);
+  void AddCapability(spv::Capability capability);
 
   // Add the extension |ext| to the feature manager.
   void AddExtension(Instruction* ext);
diff --git a/source/opt/fix_func_call_arguments.cpp b/source/opt/fix_func_call_arguments.cpp
index d140fb4..f3486be 100644
--- a/source/opt/fix_func_call_arguments.cpp
+++ b/source/opt/fix_func_call_arguments.cpp
@@ -29,7 +29,7 @@
   if (ModuleHasASingleFunction()) return Status::SuccessWithoutChange;
   for (auto& func : *get_module()) {
     func.ForEachInst([this, &modified](Instruction* inst) {
-      if (inst->opcode() == SpvOpFunctionCall) {
+      if (inst->opcode() == spv::Op::OpFunctionCall) {
         modified |= FixFuncCallArguments(inst);
       }
     });
@@ -44,7 +44,7 @@
     Operand& op = func_call_inst->GetInOperand(i);
     if (op.type != SPV_OPERAND_TYPE_ID) continue;
     Instruction* operand_inst = get_def_use_mgr()->GetDef(op.AsId());
-    if (operand_inst->opcode() == SpvOpAccessChain) {
+    if (operand_inst->opcode() == spv::Op::OpAccessChain) {
       uint32_t var_id =
           ReplaceAccessChainFuncCallArguments(func_call_inst, operand_inst);
       func_call_inst->SetInOperand(i, {var_id});
@@ -71,10 +71,11 @@
   Instruction* op_type =
       get_def_use_mgr()->GetDef(op_ptr_type->GetSingleWordInOperand(1));
   uint32_t varType = context()->get_type_mgr()->FindPointerToType(
-      op_type->result_id(), SpvStorageClassFunction);
+      op_type->result_id(), spv::StorageClass::Function);
   // Create new variable
   builder.SetInsertPoint(variable_insertion_point);
-  Instruction* var = builder.AddVariable(varType, SpvStorageClassFunction);
+  Instruction* var =
+      builder.AddVariable(varType, uint32_t(spv::StorageClass::Function));
   // Load access chain to the new variable before function call
   builder.SetInsertPoint(func_call_inst);
 
diff --git a/source/opt/fix_storage_class.cpp b/source/opt/fix_storage_class.cpp
index 04eb132..5597e82 100644
--- a/source/opt/fix_storage_class.cpp
+++ b/source/opt/fix_storage_class.cpp
@@ -26,7 +26,7 @@
   bool modified = false;
 
   get_module()->ForEachInst([this, &modified](Instruction* inst) {
-    if (inst->opcode() == SpvOpVariable) {
+    if (inst->opcode() == spv::Op::OpVariable) {
       std::set<uint32_t> seen;
       std::vector<std::pair<Instruction*, uint32_t>> uses;
       get_def_use_mgr()->ForEachUse(inst,
@@ -37,7 +37,7 @@
       for (auto& use : uses) {
         modified |= PropagateStorageClass(
             use.first,
-            static_cast<SpvStorageClass>(inst->GetSingleWordInOperand(0)),
+            static_cast<spv::StorageClass>(inst->GetSingleWordInOperand(0)),
             &seen);
         assert(seen.empty() && "Seen was not properly reset.");
         modified |=
@@ -50,14 +50,14 @@
 }
 
 bool FixStorageClass::PropagateStorageClass(Instruction* inst,
-                                            SpvStorageClass storage_class,
+                                            spv::StorageClass storage_class,
                                             std::set<uint32_t>* seen) {
   if (!IsPointerResultType(inst)) {
     return false;
   }
 
   if (IsPointerToStorageClass(inst, storage_class)) {
-    if (inst->opcode() == SpvOpPhi) {
+    if (inst->opcode() == spv::Op::OpPhi) {
       if (!seen->insert(inst->result_id()).second) {
         return false;
       }
@@ -71,34 +71,34 @@
       modified |= PropagateStorageClass(use, storage_class, seen);
     }
 
-    if (inst->opcode() == SpvOpPhi) {
+    if (inst->opcode() == spv::Op::OpPhi) {
       seen->erase(inst->result_id());
     }
     return modified;
   }
 
   switch (inst->opcode()) {
-    case SpvOpAccessChain:
-    case SpvOpPtrAccessChain:
-    case SpvOpInBoundsAccessChain:
-    case SpvOpCopyObject:
-    case SpvOpPhi:
-    case SpvOpSelect:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpPtrAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
+    case spv::Op::OpCopyObject:
+    case spv::Op::OpPhi:
+    case spv::Op::OpSelect:
       FixInstructionStorageClass(inst, storage_class, seen);
       return true;
-    case SpvOpFunctionCall:
+    case spv::Op::OpFunctionCall:
       // We cannot be sure of the actual connection between the storage class
       // of the parameter and the storage class of the result, so we should not
       // do anything.  If the result type needs to be fixed, the function call
       // should be inlined.
       return false;
-    case SpvOpImageTexelPointer:
-    case SpvOpLoad:
-    case SpvOpStore:
-    case SpvOpCopyMemory:
-    case SpvOpCopyMemorySized:
-    case SpvOpVariable:
-    case SpvOpBitcast:
+    case spv::Op::OpImageTexelPointer:
+    case spv::Op::OpLoad:
+    case spv::Op::OpStore:
+    case spv::Op::OpCopyMemory:
+    case spv::Op::OpCopyMemorySized:
+    case spv::Op::OpVariable:
+    case spv::Op::OpBitcast:
       // Nothing to change for these opcode.  The result type is the same
       // regardless of the storage class of the operand.
       return false;
@@ -109,9 +109,9 @@
   }
 }
 
-void FixStorageClass::FixInstructionStorageClass(Instruction* inst,
-                                                 SpvStorageClass storage_class,
-                                                 std::set<uint32_t>* seen) {
+void FixStorageClass::FixInstructionStorageClass(
+    Instruction* inst, spv::StorageClass storage_class,
+    std::set<uint32_t>* seen) {
   assert(IsPointerResultType(inst) &&
          "The result type of the instruction must be a pointer.");
 
@@ -126,10 +126,10 @@
 }
 
 void FixStorageClass::ChangeResultStorageClass(
-    Instruction* inst, SpvStorageClass storage_class) const {
+    Instruction* inst, spv::StorageClass storage_class) const {
   analysis::TypeManager* type_mgr = context()->get_type_mgr();
   Instruction* result_type_inst = get_def_use_mgr()->GetDef(inst->type_id());
-  assert(result_type_inst->opcode() == SpvOpTypePointer);
+  assert(result_type_inst->opcode() == spv::Op::OpTypePointer);
   uint32_t pointee_type_id = result_type_inst->GetSingleWordInOperand(1);
   uint32_t new_result_type_id =
       type_mgr->FindPointerToType(pointee_type_id, storage_class);
@@ -147,7 +147,7 @@
 }
 
 bool FixStorageClass::IsPointerToStorageClass(Instruction* inst,
-                                              SpvStorageClass storage_class) {
+                                              spv::StorageClass storage_class) {
   analysis::TypeManager* type_mgr = context()->get_type_mgr();
   analysis::Type* pType = type_mgr->GetType(inst->type_id());
   const analysis::Pointer* result_type = pType->AsPointer();
@@ -180,39 +180,39 @@
   // particular type, then we want find that type.
   uint32_t new_type_id = 0;
   switch (inst->opcode()) {
-    case SpvOpAccessChain:
-    case SpvOpPtrAccessChain:
-    case SpvOpInBoundsAccessChain:
-    case SpvOpInBoundsPtrAccessChain:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpPtrAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
+    case spv::Op::OpInBoundsPtrAccessChain:
       if (op_idx == 2) {
         new_type_id = WalkAccessChainType(inst, type_id);
       }
       break;
-    case SpvOpCopyObject:
+    case spv::Op::OpCopyObject:
       new_type_id = type_id;
       break;
-    case SpvOpPhi:
+    case spv::Op::OpPhi:
       if (seen->insert(inst->result_id()).second) {
         new_type_id = type_id;
       }
       break;
-    case SpvOpSelect:
+    case spv::Op::OpSelect:
       if (op_idx > 2) {
         new_type_id = type_id;
       }
       break;
-    case SpvOpFunctionCall:
+    case spv::Op::OpFunctionCall:
       // We cannot be sure of the actual connection between the type
       // of the parameter and the type of the result, so we should not
       // do anything.  If the result type needs to be fixed, the function call
       // should be inlined.
       return false;
-    case SpvOpLoad: {
+    case spv::Op::OpLoad: {
       Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
       new_type_id = type_inst->GetSingleWordInOperand(1);
       break;
     }
-    case SpvOpStore: {
+    case spv::Op::OpStore: {
       uint32_t obj_id = inst->GetSingleWordInOperand(1);
       Instruction* obj_inst = get_def_use_mgr()->GetDef(obj_id);
       uint32_t obj_type_id = obj_inst->type_id();
@@ -237,18 +237,18 @@
         context()->UpdateDefUse(inst);
       }
     } break;
-    case SpvOpCopyMemory:
-    case SpvOpCopyMemorySized:
+    case spv::Op::OpCopyMemory:
+    case spv::Op::OpCopyMemorySized:
       // TODO: May need to expand the copy as we do with the stores.
       break;
-    case SpvOpCompositeConstruct:
-    case SpvOpCompositeExtract:
-    case SpvOpCompositeInsert:
+    case spv::Op::OpCompositeConstruct:
+    case spv::Op::OpCompositeExtract:
+    case spv::Op::OpCompositeInsert:
       // TODO: DXC does not seem to generate code that will require changes to
       // these opcode.  The can be implemented when they come up.
       break;
-    case SpvOpImageTexelPointer:
-    case SpvOpBitcast:
+    case spv::Op::OpImageTexelPointer:
+    case spv::Op::OpBitcast:
       // Nothing to change for these opcode.  The result type is the same
       // regardless of the type of the operand.
       return false;
@@ -278,7 +278,7 @@
       PropagateType(use.first, new_type_id, use.second, seen);
     }
 
-    if (inst->opcode() == SpvOpPhi) {
+    if (inst->opcode() == spv::Op::OpPhi) {
       seen->erase(inst->result_id());
     }
   }
@@ -288,12 +288,12 @@
 uint32_t FixStorageClass::WalkAccessChainType(Instruction* inst, uint32_t id) {
   uint32_t start_idx = 0;
   switch (inst->opcode()) {
-    case SpvOpAccessChain:
-    case SpvOpInBoundsAccessChain:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
       start_idx = 1;
       break;
-    case SpvOpPtrAccessChain:
-    case SpvOpInBoundsPtrAccessChain:
+    case spv::Op::OpPtrAccessChain:
+    case spv::Op::OpInBoundsPtrAccessChain:
       start_idx = 2;
       break;
     default:
@@ -302,19 +302,19 @@
   }
 
   Instruction* orig_type_inst = get_def_use_mgr()->GetDef(id);
-  assert(orig_type_inst->opcode() == SpvOpTypePointer);
+  assert(orig_type_inst->opcode() == spv::Op::OpTypePointer);
   id = orig_type_inst->GetSingleWordInOperand(1);
 
   for (uint32_t i = start_idx; i < inst->NumInOperands(); ++i) {
     Instruction* type_inst = get_def_use_mgr()->GetDef(id);
     switch (type_inst->opcode()) {
-      case SpvOpTypeArray:
-      case SpvOpTypeRuntimeArray:
-      case SpvOpTypeMatrix:
-      case SpvOpTypeVector:
+      case spv::Op::OpTypeArray:
+      case spv::Op::OpTypeRuntimeArray:
+      case spv::Op::OpTypeMatrix:
+      case spv::Op::OpTypeVector:
         id = type_inst->GetSingleWordInOperand(0);
         break;
-      case SpvOpTypeStruct: {
+      case spv::Op::OpTypeStruct: {
         const analysis::Constant* index_const =
             context()->get_constant_mgr()->FindDeclaredConstant(
                 inst->GetSingleWordInOperand(i));
@@ -330,8 +330,8 @@
   }
 
   return context()->get_type_mgr()->FindPointerToType(
-      id,
-      static_cast<SpvStorageClass>(orig_type_inst->GetSingleWordInOperand(0)));
+      id, static_cast<spv::StorageClass>(
+              orig_type_inst->GetSingleWordInOperand(0)));
 }
 
 // namespace opt
diff --git a/source/opt/fix_storage_class.h b/source/opt/fix_storage_class.h
index e72e864..6c67acd 100644
--- a/source/opt/fix_storage_class.h
+++ b/source/opt/fix_storage_class.h
@@ -48,7 +48,7 @@
   // appropriate, and propagates the change to the users of |inst| as well.
   // Returns true of any changes were made.
   // |seen| is used to track OpPhi instructions that should not be processed.
-  bool PropagateStorageClass(Instruction* inst, SpvStorageClass storage_class,
+  bool PropagateStorageClass(Instruction* inst, spv::StorageClass storage_class,
                              std::set<uint32_t>* seen);
 
   // Changes the storage class of the result of |inst| to |storage_class|.
@@ -58,13 +58,13 @@
   // |seen| is used to track OpPhi instructions that should not be processed by
   // |PropagateStorageClass|
   void FixInstructionStorageClass(Instruction* inst,
-                                  SpvStorageClass storage_class,
+                                  spv::StorageClass storage_class,
                                   std::set<uint32_t>* seen);
 
   // Changes the storage class of the result of |inst| to |storage_class|.  The
   // result type of |inst| must be a pointer.
   void ChangeResultStorageClass(Instruction* inst,
-                                SpvStorageClass storage_class) const;
+                                spv::StorageClass storage_class) const;
 
   // Returns true if the result type of |inst| is a pointer.
   bool IsPointerResultType(Instruction* inst);
@@ -72,7 +72,7 @@
   // Returns true if the result of |inst| is a pointer to storage class
   // |storage_class|.
   bool IsPointerToStorageClass(Instruction* inst,
-                               SpvStorageClass storage_class);
+                               spv::StorageClass storage_class);
 
   // Change |inst| to match that operand |op_idx| now has type |type_id|, and
   // adjust any uses of |inst| accordingly. Returns true if the code changed.
diff --git a/source/opt/flatten_decoration_pass.cpp b/source/opt/flatten_decoration_pass.cpp
index f4de911..c878c09 100644
--- a/source/opt/flatten_decoration_pass.cpp
+++ b/source/opt/flatten_decoration_pass.cpp
@@ -49,16 +49,16 @@
   // Rely on unordered_map::operator[] to create its entries on first access.
   for (const auto& inst : annotations) {
     switch (inst.opcode()) {
-      case SpvOp::SpvOpDecorationGroup:
+      case spv::Op::OpDecorationGroup:
         group_ids.insert(inst.result_id());
         break;
-      case SpvOp::SpvOpGroupDecorate: {
+      case spv::Op::OpGroupDecorate: {
         Words& words = normal_uses[inst.GetSingleWordInOperand(0)];
         for (uint32_t i = 1; i < inst.NumInOperandWords(); i++) {
           words.push_back(inst.GetSingleWordInOperand(i));
         }
       } break;
-      case SpvOp::SpvOpGroupMemberDecorate: {
+      case spv::Op::OpGroupMemberDecorate: {
         Words& words = member_uses[inst.GetSingleWordInOperand(0)];
         for (uint32_t i = 1; i < inst.NumInOperandWords(); i++) {
           words.push_back(inst.GetSingleWordInOperand(i));
@@ -77,12 +77,12 @@
     // Should we replace this instruction?
     bool replace = false;
     switch (inst_iter->opcode()) {
-      case SpvOp::SpvOpDecorationGroup:
-      case SpvOp::SpvOpGroupDecorate:
-      case SpvOp::SpvOpGroupMemberDecorate:
+      case spv::Op::OpDecorationGroup:
+      case spv::Op::OpGroupDecorate:
+      case spv::Op::OpGroupMemberDecorate:
         replace = true;
         break;
-      case SpvOp::SpvOpDecorate: {
+      case spv::Op::OpDecorate: {
         // If this decoration targets a group, then replace it
         // by sets of normal and member decorations.
         const uint32_t group = inst_iter->GetSingleWordOperand(0);
@@ -115,7 +115,7 @@
             operands.insert(operands.end(), decoration_operands_iter,
                             inst_iter->end());
             std::unique_ptr<Instruction> new_inst(new Instruction(
-                context(), SpvOp::SpvOpMemberDecorate, 0, 0, operands));
+                context(), spv::Op::OpMemberDecorate, 0, 0, operands));
             inst_iter = inst_iter.InsertBefore(std::move(new_inst));
             ++inst_iter;
             replace = true;
@@ -146,7 +146,7 @@
   if (!group_ids.empty()) {
     for (auto debug_inst_iter = context()->debug2_begin();
          debug_inst_iter != context()->debug2_end();) {
-      if (debug_inst_iter->opcode() == SpvOp::SpvOpName) {
+      if (debug_inst_iter->opcode() == spv::Op::OpName) {
         const uint32_t target = debug_inst_iter->GetSingleWordOperand(0);
         if (group_ids.count(target)) {
           debug_inst_iter = debug_inst_iter.Erase();
diff --git a/source/opt/fold.cpp b/source/opt/fold.cpp
index 315741a..3c234c4 100644
--- a/source/opt/fold.cpp
+++ b/source/opt/fold.cpp
@@ -42,23 +42,24 @@
 
 }  // namespace
 
-uint32_t InstructionFolder::UnaryOperate(SpvOp opcode, uint32_t operand) const {
+uint32_t InstructionFolder::UnaryOperate(spv::Op opcode,
+                                         uint32_t operand) const {
   switch (opcode) {
     // Arthimetics
-    case SpvOp::SpvOpSNegate: {
+    case spv::Op::OpSNegate: {
       int32_t s_operand = static_cast<int32_t>(operand);
       if (s_operand == std::numeric_limits<int32_t>::min()) {
         return s_operand;
       }
       return -s_operand;
     }
-    case SpvOp::SpvOpNot:
+    case spv::Op::OpNot:
       return ~operand;
-    case SpvOp::SpvOpLogicalNot:
+    case spv::Op::OpLogicalNot:
       return !static_cast<bool>(operand);
-    case SpvOp::SpvOpUConvert:
+    case spv::Op::OpUConvert:
       return operand;
-    case SpvOp::SpvOpSConvert:
+    case spv::Op::OpSConvert:
       return operand;
     default:
       assert(false &&
@@ -67,31 +68,31 @@
   }
 }
 
-uint32_t InstructionFolder::BinaryOperate(SpvOp opcode, uint32_t a,
+uint32_t InstructionFolder::BinaryOperate(spv::Op opcode, uint32_t a,
                                           uint32_t b) const {
   switch (opcode) {
     // Arthimetics
-    case SpvOp::SpvOpIAdd:
+    case spv::Op::OpIAdd:
       return a + b;
-    case SpvOp::SpvOpISub:
+    case spv::Op::OpISub:
       return a - b;
-    case SpvOp::SpvOpIMul:
+    case spv::Op::OpIMul:
       return a * b;
-    case SpvOp::SpvOpUDiv:
+    case spv::Op::OpUDiv:
       if (b != 0) {
         return a / b;
       } else {
         // Dividing by 0 is undefined, so we will just pick 0.
         return 0;
       }
-    case SpvOp::SpvOpSDiv:
+    case spv::Op::OpSDiv:
       if (b != 0u) {
         return (static_cast<int32_t>(a)) / (static_cast<int32_t>(b));
       } else {
         // Dividing by 0 is undefined, so we will just pick 0.
         return 0;
       }
-    case SpvOp::SpvOpSRem: {
+    case spv::Op::OpSRem: {
       // The sign of non-zero result comes from the first operand: a. This is
       // guaranteed by C++11 rules for integer division operator. The division
       // result is rounded toward zero, so the result of '%' has the sign of
@@ -103,10 +104,10 @@
         return 0;
       }
     }
-    case SpvOp::SpvOpSMod: {
+    case spv::Op::OpSMod: {
       // The sign of non-zero result comes from the second operand: b
       if (b != 0u) {
-        int32_t rem = BinaryOperate(SpvOp::SpvOpSRem, a, b);
+        int32_t rem = BinaryOperate(spv::Op::OpSRem, a, b);
         int32_t b_prim = static_cast<int32_t>(b);
         return (rem + b_prim) % b_prim;
       } else {
@@ -114,7 +115,7 @@
         return 0;
       }
     }
-    case SpvOp::SpvOpUMod:
+    case spv::Op::OpUMod:
       if (b != 0u) {
         return (a % b);
       } else {
@@ -123,7 +124,7 @@
       }
 
     // Shifting
-    case SpvOp::SpvOpShiftRightLogical:
+    case spv::Op::OpShiftRightLogical:
       if (b >= 32) {
         // This is undefined behaviour when |b| > 32.  Choose 0 for consistency.
         // When |b| == 32, doing the shift in C++ in undefined, but the result
@@ -131,7 +132,7 @@
         return 0;
       }
       return a >> b;
-    case SpvOp::SpvOpShiftRightArithmetic:
+    case spv::Op::OpShiftRightArithmetic:
       if (b > 32) {
         // This is undefined behaviour.  Choose 0 for consistency.
         return 0;
@@ -146,7 +147,7 @@
         }
       }
       return (static_cast<int32_t>(a)) >> b;
-    case SpvOp::SpvOpShiftLeftLogical:
+    case spv::Op::OpShiftLeftLogical:
       if (b >= 32) {
         // This is undefined behaviour when |b| > 32.  Choose 0 for consistency.
         // When |b| == 32, doing the shift in C++ in undefined, but the result
@@ -156,43 +157,43 @@
       return a << b;
 
     // Bitwise operations
-    case SpvOp::SpvOpBitwiseOr:
+    case spv::Op::OpBitwiseOr:
       return a | b;
-    case SpvOp::SpvOpBitwiseAnd:
+    case spv::Op::OpBitwiseAnd:
       return a & b;
-    case SpvOp::SpvOpBitwiseXor:
+    case spv::Op::OpBitwiseXor:
       return a ^ b;
 
     // Logical
-    case SpvOp::SpvOpLogicalEqual:
+    case spv::Op::OpLogicalEqual:
       return (static_cast<bool>(a)) == (static_cast<bool>(b));
-    case SpvOp::SpvOpLogicalNotEqual:
+    case spv::Op::OpLogicalNotEqual:
       return (static_cast<bool>(a)) != (static_cast<bool>(b));
-    case SpvOp::SpvOpLogicalOr:
+    case spv::Op::OpLogicalOr:
       return (static_cast<bool>(a)) || (static_cast<bool>(b));
-    case SpvOp::SpvOpLogicalAnd:
+    case spv::Op::OpLogicalAnd:
       return (static_cast<bool>(a)) && (static_cast<bool>(b));
 
     // Comparison
-    case SpvOp::SpvOpIEqual:
+    case spv::Op::OpIEqual:
       return a == b;
-    case SpvOp::SpvOpINotEqual:
+    case spv::Op::OpINotEqual:
       return a != b;
-    case SpvOp::SpvOpULessThan:
+    case spv::Op::OpULessThan:
       return a < b;
-    case SpvOp::SpvOpSLessThan:
+    case spv::Op::OpSLessThan:
       return (static_cast<int32_t>(a)) < (static_cast<int32_t>(b));
-    case SpvOp::SpvOpUGreaterThan:
+    case spv::Op::OpUGreaterThan:
       return a > b;
-    case SpvOp::SpvOpSGreaterThan:
+    case spv::Op::OpSGreaterThan:
       return (static_cast<int32_t>(a)) > (static_cast<int32_t>(b));
-    case SpvOp::SpvOpULessThanEqual:
+    case spv::Op::OpULessThanEqual:
       return a <= b;
-    case SpvOp::SpvOpSLessThanEqual:
+    case spv::Op::OpSLessThanEqual:
       return (static_cast<int32_t>(a)) <= (static_cast<int32_t>(b));
-    case SpvOp::SpvOpUGreaterThanEqual:
+    case spv::Op::OpUGreaterThanEqual:
       return a >= b;
-    case SpvOp::SpvOpSGreaterThanEqual:
+    case spv::Op::OpSGreaterThanEqual:
       return (static_cast<int32_t>(a)) >= (static_cast<int32_t>(b));
     default:
       assert(false &&
@@ -201,10 +202,10 @@
   }
 }
 
-uint32_t InstructionFolder::TernaryOperate(SpvOp opcode, uint32_t a, uint32_t b,
-                                           uint32_t c) const {
+uint32_t InstructionFolder::TernaryOperate(spv::Op opcode, uint32_t a,
+                                           uint32_t b, uint32_t c) const {
   switch (opcode) {
-    case SpvOp::SpvOpSelect:
+    case spv::Op::OpSelect:
       return (static_cast<bool>(a)) ? b : c;
     default:
       assert(false &&
@@ -214,7 +215,7 @@
 }
 
 uint32_t InstructionFolder::OperateWords(
-    SpvOp opcode, const std::vector<uint32_t>& operand_words) const {
+    spv::Op opcode, const std::vector<uint32_t>& operand_words) const {
   switch (operand_words.size()) {
     case 1:
       return UnaryOperate(opcode, operand_words.front());
@@ -233,7 +234,7 @@
   auto identity_map = [](uint32_t id) { return id; };
   Instruction* folded_inst = FoldInstructionToConstant(inst, identity_map);
   if (folded_inst != nullptr) {
-    inst->SetOpcode(SpvOpCopyObject);
+    inst->SetOpcode(spv::Op::OpCopyObject);
     inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {folded_inst->result_id()}}});
     return true;
   }
@@ -256,7 +257,7 @@
 // result in 32 bit word. Scalar constants with longer than 32-bit width are
 // not accepted in this function.
 uint32_t InstructionFolder::FoldScalars(
-    SpvOp opcode,
+    spv::Op opcode,
     const std::vector<const analysis::Constant*>& operands) const {
   assert(IsFoldableOpcode(opcode) &&
          "Unhandled instruction opcode in FoldScalars");
@@ -282,7 +283,7 @@
 bool InstructionFolder::FoldBinaryIntegerOpToConstant(
     Instruction* inst, const std::function<uint32_t(uint32_t)>& id_map,
     uint32_t* result) const {
-  SpvOp opcode = inst->opcode();
+  spv::Op opcode = inst->opcode();
   analysis::ConstantManager* const_manger = context_->get_constant_mgr();
 
   uint32_t ids[2];
@@ -300,7 +301,7 @@
 
   switch (opcode) {
     // Arthimetics
-    case SpvOp::SpvOpIMul:
+    case spv::Op::OpIMul:
       for (uint32_t i = 0; i < 2; i++) {
         if (constants[i] != nullptr && constants[i]->IsZero()) {
           *result = 0;
@@ -308,11 +309,11 @@
         }
       }
       break;
-    case SpvOp::SpvOpUDiv:
-    case SpvOp::SpvOpSDiv:
-    case SpvOp::SpvOpSRem:
-    case SpvOp::SpvOpSMod:
-    case SpvOp::SpvOpUMod:
+    case spv::Op::OpUDiv:
+    case spv::Op::OpSDiv:
+    case spv::Op::OpSRem:
+    case spv::Op::OpSMod:
+    case spv::Op::OpUMod:
       // This changes undefined behaviour (ie divide by 0) into a 0.
       for (uint32_t i = 0; i < 2; i++) {
         if (constants[i] != nullptr && constants[i]->IsZero()) {
@@ -323,8 +324,8 @@
       break;
 
     // Shifting
-    case SpvOp::SpvOpShiftRightLogical:
-    case SpvOp::SpvOpShiftLeftLogical:
+    case spv::Op::OpShiftRightLogical:
+    case spv::Op::OpShiftLeftLogical:
       if (constants[1] != nullptr) {
         // When shifting by a value larger than the size of the result, the
         // result is undefined.  We are setting the undefined behaviour to a
@@ -339,7 +340,7 @@
       break;
 
     // Bitwise operations
-    case SpvOp::SpvOpBitwiseOr:
+    case spv::Op::OpBitwiseOr:
       for (uint32_t i = 0; i < 2; i++) {
         if (constants[i] != nullptr) {
           // TODO: Change the mask against a value based on the bit width of the
@@ -353,7 +354,7 @@
         }
       }
       break;
-    case SpvOp::SpvOpBitwiseAnd:
+    case spv::Op::OpBitwiseAnd:
       for (uint32_t i = 0; i < 2; i++) {
         if (constants[i] != nullptr) {
           if (constants[i]->IsZero()) {
@@ -365,7 +366,7 @@
       break;
 
     // Comparison
-    case SpvOp::SpvOpULessThan:
+    case spv::Op::OpULessThan:
       if (constants[0] != nullptr &&
           constants[0]->GetU32BitValue() == UINT32_MAX) {
         *result = false;
@@ -376,7 +377,7 @@
         return true;
       }
       break;
-    case SpvOp::SpvOpSLessThan:
+    case spv::Op::OpSLessThan:
       if (constants[0] != nullptr &&
           constants[0]->GetS32BitValue() == INT32_MAX) {
         *result = false;
@@ -388,7 +389,7 @@
         return true;
       }
       break;
-    case SpvOp::SpvOpUGreaterThan:
+    case spv::Op::OpUGreaterThan:
       if (constants[0] != nullptr && constants[0]->IsZero()) {
         *result = false;
         return true;
@@ -399,7 +400,7 @@
         return true;
       }
       break;
-    case SpvOp::SpvOpSGreaterThan:
+    case spv::Op::OpSGreaterThan:
       if (constants[0] != nullptr &&
           constants[0]->GetS32BitValue() == INT32_MIN) {
         *result = false;
@@ -411,7 +412,7 @@
         return true;
       }
       break;
-    case SpvOp::SpvOpULessThanEqual:
+    case spv::Op::OpULessThanEqual:
       if (constants[0] != nullptr && constants[0]->IsZero()) {
         *result = true;
         return true;
@@ -422,7 +423,7 @@
         return true;
       }
       break;
-    case SpvOp::SpvOpSLessThanEqual:
+    case spv::Op::OpSLessThanEqual:
       if (constants[0] != nullptr &&
           constants[0]->GetS32BitValue() == INT32_MIN) {
         *result = true;
@@ -434,7 +435,7 @@
         return true;
       }
       break;
-    case SpvOp::SpvOpUGreaterThanEqual:
+    case spv::Op::OpUGreaterThanEqual:
       if (constants[0] != nullptr &&
           constants[0]->GetU32BitValue() == UINT32_MAX) {
         *result = true;
@@ -445,7 +446,7 @@
         return true;
       }
       break;
-    case SpvOp::SpvOpSGreaterThanEqual:
+    case spv::Op::OpSGreaterThanEqual:
       if (constants[0] != nullptr &&
           constants[0]->GetS32BitValue() == INT32_MAX) {
         *result = true;
@@ -466,7 +467,7 @@
 bool InstructionFolder::FoldBinaryBooleanOpToConstant(
     Instruction* inst, const std::function<uint32_t(uint32_t)>& id_map,
     uint32_t* result) const {
-  SpvOp opcode = inst->opcode();
+  spv::Op opcode = inst->opcode();
   analysis::ConstantManager* const_manger = context_->get_constant_mgr();
 
   uint32_t ids[2];
@@ -484,7 +485,7 @@
 
   switch (opcode) {
     // Logical
-    case SpvOp::SpvOpLogicalOr:
+    case spv::Op::OpLogicalOr:
       for (uint32_t i = 0; i < 2; i++) {
         if (constants[i] != nullptr) {
           if (constants[i]->value()) {
@@ -494,7 +495,7 @@
         }
       }
       break;
-    case SpvOp::SpvOpLogicalAnd:
+    case spv::Op::OpLogicalAnd:
       for (uint32_t i = 0; i < 2; i++) {
         if (constants[i] != nullptr) {
           if (!constants[i]->value()) {
@@ -526,7 +527,7 @@
 }
 
 std::vector<uint32_t> InstructionFolder::FoldVectors(
-    SpvOp opcode, uint32_t num_dims,
+    spv::Op opcode, uint32_t num_dims,
     const std::vector<const analysis::Constant*>& operands) const {
   assert(IsFoldableOpcode(opcode) &&
          "Unhandled instruction opcode in FoldVectors");
@@ -570,44 +571,44 @@
   return result;
 }
 
-bool InstructionFolder::IsFoldableOpcode(SpvOp opcode) const {
+bool InstructionFolder::IsFoldableOpcode(spv::Op opcode) const {
   // NOTE: Extend to more opcodes as new cases are handled in the folder
   // functions.
   switch (opcode) {
-    case SpvOp::SpvOpBitwiseAnd:
-    case SpvOp::SpvOpBitwiseOr:
-    case SpvOp::SpvOpBitwiseXor:
-    case SpvOp::SpvOpIAdd:
-    case SpvOp::SpvOpIEqual:
-    case SpvOp::SpvOpIMul:
-    case SpvOp::SpvOpINotEqual:
-    case SpvOp::SpvOpISub:
-    case SpvOp::SpvOpLogicalAnd:
-    case SpvOp::SpvOpLogicalEqual:
-    case SpvOp::SpvOpLogicalNot:
-    case SpvOp::SpvOpLogicalNotEqual:
-    case SpvOp::SpvOpLogicalOr:
-    case SpvOp::SpvOpNot:
-    case SpvOp::SpvOpSDiv:
-    case SpvOp::SpvOpSelect:
-    case SpvOp::SpvOpSGreaterThan:
-    case SpvOp::SpvOpSGreaterThanEqual:
-    case SpvOp::SpvOpShiftLeftLogical:
-    case SpvOp::SpvOpShiftRightArithmetic:
-    case SpvOp::SpvOpShiftRightLogical:
-    case SpvOp::SpvOpSLessThan:
-    case SpvOp::SpvOpSLessThanEqual:
-    case SpvOp::SpvOpSMod:
-    case SpvOp::SpvOpSNegate:
-    case SpvOp::SpvOpSRem:
-    case SpvOp::SpvOpSConvert:
-    case SpvOp::SpvOpUConvert:
-    case SpvOp::SpvOpUDiv:
-    case SpvOp::SpvOpUGreaterThan:
-    case SpvOp::SpvOpUGreaterThanEqual:
-    case SpvOp::SpvOpULessThan:
-    case SpvOp::SpvOpULessThanEqual:
-    case SpvOp::SpvOpUMod:
+    case spv::Op::OpBitwiseAnd:
+    case spv::Op::OpBitwiseOr:
+    case spv::Op::OpBitwiseXor:
+    case spv::Op::OpIAdd:
+    case spv::Op::OpIEqual:
+    case spv::Op::OpIMul:
+    case spv::Op::OpINotEqual:
+    case spv::Op::OpISub:
+    case spv::Op::OpLogicalAnd:
+    case spv::Op::OpLogicalEqual:
+    case spv::Op::OpLogicalNot:
+    case spv::Op::OpLogicalNotEqual:
+    case spv::Op::OpLogicalOr:
+    case spv::Op::OpNot:
+    case spv::Op::OpSDiv:
+    case spv::Op::OpSelect:
+    case spv::Op::OpSGreaterThan:
+    case spv::Op::OpSGreaterThanEqual:
+    case spv::Op::OpShiftLeftLogical:
+    case spv::Op::OpShiftRightArithmetic:
+    case spv::Op::OpShiftRightLogical:
+    case spv::Op::OpSLessThan:
+    case spv::Op::OpSLessThanEqual:
+    case spv::Op::OpSMod:
+    case spv::Op::OpSNegate:
+    case spv::Op::OpSRem:
+    case spv::Op::OpSConvert:
+    case spv::Op::OpUConvert:
+    case spv::Op::OpUDiv:
+    case spv::Op::OpUGreaterThan:
+    case spv::Op::OpUGreaterThanEqual:
+    case spv::Op::OpULessThan:
+    case spv::Op::OpULessThanEqual:
+    case spv::Op::OpUMod:
       return true;
     default:
       return false;
@@ -685,11 +686,11 @@
 
 bool InstructionFolder::IsFoldableType(Instruction* type_inst) const {
   // Support 32-bit integers.
-  if (type_inst->opcode() == SpvOpTypeInt) {
+  if (type_inst->opcode() == spv::Op::OpTypeInt) {
     return type_inst->GetSingleWordInOperand(0) == 32;
   }
   // Support booleans.
-  if (type_inst->opcode() == SpvOpTypeBool) {
+  if (type_inst->opcode() == spv::Op::OpTypeBool) {
     return true;
   }
   // Nothing else yet.
@@ -699,7 +700,7 @@
 bool InstructionFolder::FoldInstruction(Instruction* inst) const {
   bool modified = false;
   Instruction* folded_inst(inst);
-  while (folded_inst->opcode() != SpvOpCopyObject &&
+  while (folded_inst->opcode() != spv::Op::OpCopyObject &&
          FoldInstructionInternal(&*folded_inst)) {
     modified = true;
   }
diff --git a/source/opt/fold.h b/source/opt/fold.h
index 9e7c470..9a131d0 100644
--- a/source/opt/fold.h
+++ b/source/opt/fold.h
@@ -55,7 +55,7 @@
   // IsFoldableOpcode test. If any error occurs during folding, the folder will
   // fail with a call to assert.
   uint32_t FoldScalars(
-      SpvOp opcode,
+      spv::Op opcode,
       const std::vector<const analysis::Constant*>& operands) const;
 
   // Returns the result of performing an operation with the given |opcode| over
@@ -72,12 +72,12 @@
   // IsFoldableOpcode test. If any error occurs during folding, the folder will
   // fail with a call to assert.
   std::vector<uint32_t> FoldVectors(
-      SpvOp opcode, uint32_t num_dims,
+      spv::Op opcode, uint32_t num_dims,
       const std::vector<const analysis::Constant*>& operands) const;
 
   // Returns true if |opcode| represents an operation handled by FoldScalars or
   // FoldVectors.
-  bool IsFoldableOpcode(SpvOp opcode) const;
+  bool IsFoldableOpcode(spv::Op opcode) const;
 
   // Returns true if |cst| is supported by FoldScalars and FoldVectors.
   bool IsFoldableConstant(const analysis::Constant* cst) const;
@@ -126,22 +126,22 @@
 
   // Returns the single-word result from performing the given unary operation on
   // the operand value which is passed in as a 32-bit word.
-  uint32_t UnaryOperate(SpvOp opcode, uint32_t operand) const;
+  uint32_t UnaryOperate(spv::Op opcode, uint32_t operand) const;
 
   // Returns the single-word result from performing the given binary operation
   // on the operand values which are passed in as two 32-bit word.
-  uint32_t BinaryOperate(SpvOp opcode, uint32_t a, uint32_t b) const;
+  uint32_t BinaryOperate(spv::Op opcode, uint32_t a, uint32_t b) const;
 
   // Returns the single-word result from performing the given ternary operation
   // on the operand values which are passed in as three 32-bit word.
-  uint32_t TernaryOperate(SpvOp opcode, uint32_t a, uint32_t b,
+  uint32_t TernaryOperate(spv::Op opcode, uint32_t a, uint32_t b,
                           uint32_t c) const;
 
   // Returns the single-word result from performing the given operation on the
   // operand words. This only works with 32-bit operations and uses boolean
   // convention that 0u is false, and anything else is boolean true.
   // TODO(qining): Support operands other than 32-bit wide.
-  uint32_t OperateWords(SpvOp opcode,
+  uint32_t OperateWords(spv::Op opcode,
                         const std::vector<uint32_t>& operand_words) const;
 
   bool FoldInstructionInternal(Instruction* inst) const;
diff --git a/source/opt/fold_spec_constant_op_and_composite_pass.cpp b/source/opt/fold_spec_constant_op_and_composite_pass.cpp
index 7a51870..132be0c 100644
--- a/source/opt/fold_spec_constant_op_and_composite_pass.cpp
+++ b/source/opt/fold_spec_constant_op_and_composite_pass.cpp
@@ -66,14 +66,14 @@
     if (const_mgr->GetType(inst) &&
         !const_mgr->GetType(inst)->decoration_empty())
       continue;
-    switch (SpvOp opcode = inst->opcode()) {
+    switch (spv::Op opcode = inst->opcode()) {
       // Records the values of Normal Constants.
-      case SpvOp::SpvOpConstantTrue:
-      case SpvOp::SpvOpConstantFalse:
-      case SpvOp::SpvOpConstant:
-      case SpvOp::SpvOpConstantNull:
-      case SpvOp::SpvOpConstantComposite:
-      case SpvOp::SpvOpSpecConstantComposite: {
+      case spv::Op::OpConstantTrue:
+      case spv::Op::OpConstantFalse:
+      case spv::Op::OpConstant:
+      case spv::Op::OpConstantNull:
+      case spv::Op::OpConstantComposite:
+      case spv::Op::OpSpecConstantComposite: {
         // A Constant instance will be created if the given instruction is a
         // Normal Constant whose value(s) are fixed. Note that for a composite
         // Spec Constant defined with OpSpecConstantComposite instruction, if
@@ -84,8 +84,8 @@
         if (auto const_value = const_mgr->GetConstantFromInst(inst)) {
           // Need to replace the OpSpecConstantComposite instruction with a
           // corresponding OpConstantComposite instruction.
-          if (opcode == SpvOp::SpvOpSpecConstantComposite) {
-            inst->SetOpcode(SpvOp::SpvOpConstantComposite);
+          if (opcode == spv::Op::OpSpecConstantComposite) {
+            inst->SetOpcode(spv::Op::OpConstantComposite);
             modified = true;
           }
           const_mgr->MapConstantToInst(const_value, inst);
@@ -99,7 +99,7 @@
       // Constants will be added to id_to_const_val_ and const_val_to_id_ so
       // that we can use the new Normal Constants when folding following Spec
       // Constants.
-      case SpvOp::SpvOpSpecConstantOp:
+      case spv::Op::OpSpecConstantOp:
         modified |= ProcessOpSpecConstantOp(&inst_iter);
         break;
       default:
@@ -118,11 +118,11 @@
          "The first in-operand of OpSpecConstantOp instruction must be of "
          "SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER type");
 
-  switch (static_cast<SpvOp>(inst->GetSingleWordInOperand(0))) {
-    case SpvOp::SpvOpCompositeExtract:
-    case SpvOp::SpvOpVectorShuffle:
-    case SpvOp::SpvOpCompositeInsert:
-    case SpvOp::SpvOpQuantizeToF16:
+  switch (static_cast<spv::Op>(inst->GetSingleWordInOperand(0))) {
+    case spv::Op::OpCompositeExtract:
+    case spv::Op::OpVectorShuffle:
+    case spv::Op::OpCompositeInsert:
+    case spv::Op::OpQuantizeToF16:
       folded_inst = FoldWithInstructionFolder(pos);
       break;
     default:
@@ -165,7 +165,7 @@
   // instruction and pass it to the instruction folder.
   std::unique_ptr<Instruction> inst((*inst_iter_ptr)->Clone(context()));
   inst->SetOpcode(
-      static_cast<SpvOp>((*inst_iter_ptr)->GetSingleWordInOperand(0)));
+      static_cast<spv::Op>((*inst_iter_ptr)->GetSingleWordInOperand(0)));
   inst->RemoveOperand(2);
 
   // We want the current instruction to be replaced by an |OpConstant*|
@@ -289,7 +289,7 @@
   const Instruction* inst = &**pos;
   analysis::ConstantManager* const_mgr = context()->get_constant_mgr();
   const analysis::Type* result_type = const_mgr->GetType(inst);
-  SpvOp spec_opcode = static_cast<SpvOp>(inst->GetSingleWordInOperand(0));
+  spv::Op spec_opcode = static_cast<spv::Op>(inst->GetSingleWordInOperand(0));
   // Check and collect operands.
   std::vector<const analysis::Constant*> operands;
 
diff --git a/source/opt/folding_rules.cpp b/source/opt/folding_rules.cpp
index 3d803ad..1a4fdcc 100644
--- a/source/opt/folding_rules.cpp
+++ b/source/opt/folding_rules.cpp
@@ -43,33 +43,33 @@
 int32_t ImageOperandsMaskInOperandIndex(Instruction* inst) {
   const auto opcode = inst->opcode();
   switch (opcode) {
-    case SpvOpImageSampleImplicitLod:
-    case SpvOpImageSampleExplicitLod:
-    case SpvOpImageSampleProjImplicitLod:
-    case SpvOpImageSampleProjExplicitLod:
-    case SpvOpImageFetch:
-    case SpvOpImageRead:
-    case SpvOpImageSparseSampleImplicitLod:
-    case SpvOpImageSparseSampleExplicitLod:
-    case SpvOpImageSparseSampleProjImplicitLod:
-    case SpvOpImageSparseSampleProjExplicitLod:
-    case SpvOpImageSparseFetch:
-    case SpvOpImageSparseRead:
+    case spv::Op::OpImageSampleImplicitLod:
+    case spv::Op::OpImageSampleExplicitLod:
+    case spv::Op::OpImageSampleProjImplicitLod:
+    case spv::Op::OpImageSampleProjExplicitLod:
+    case spv::Op::OpImageFetch:
+    case spv::Op::OpImageRead:
+    case spv::Op::OpImageSparseSampleImplicitLod:
+    case spv::Op::OpImageSparseSampleExplicitLod:
+    case spv::Op::OpImageSparseSampleProjImplicitLod:
+    case spv::Op::OpImageSparseSampleProjExplicitLod:
+    case spv::Op::OpImageSparseFetch:
+    case spv::Op::OpImageSparseRead:
       return inst->NumOperands() > 4 ? 2 : -1;
-    case SpvOpImageSampleDrefImplicitLod:
-    case SpvOpImageSampleDrefExplicitLod:
-    case SpvOpImageSampleProjDrefImplicitLod:
-    case SpvOpImageSampleProjDrefExplicitLod:
-    case SpvOpImageGather:
-    case SpvOpImageDrefGather:
-    case SpvOpImageSparseSampleDrefImplicitLod:
-    case SpvOpImageSparseSampleDrefExplicitLod:
-    case SpvOpImageSparseSampleProjDrefImplicitLod:
-    case SpvOpImageSparseSampleProjDrefExplicitLod:
-    case SpvOpImageSparseGather:
-    case SpvOpImageSparseDrefGather:
+    case spv::Op::OpImageSampleDrefImplicitLod:
+    case spv::Op::OpImageSampleDrefExplicitLod:
+    case spv::Op::OpImageSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSampleProjDrefExplicitLod:
+    case spv::Op::OpImageGather:
+    case spv::Op::OpImageDrefGather:
+    case spv::Op::OpImageSparseSampleDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleDrefExplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefExplicitLod:
+    case spv::Op::OpImageSparseGather:
+    case spv::Op::OpImageSparseDrefGather:
       return inst->NumOperands() > 5 ? 3 : -1;
-    case SpvOpImageWrite:
+    case spv::Op::OpImageWrite:
       return inst->NumOperands() > 3 ? 3 : -1;
     default:
       return -1;
@@ -304,7 +304,7 @@
 FoldingRule ReciprocalFDiv() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFDiv);
+    assert(inst->opcode() == spv::Op::OpFDiv);
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
     const analysis::Type* type =
         context->get_type_mgr()->GetType(inst->type_id());
@@ -333,7 +333,7 @@
         // Don't fold a null constant.
         return false;
       }
-      inst->SetOpcode(SpvOpFMul);
+      inst->SetOpcode(spv::Op::OpFMul);
       inst->SetInOperands(
           {{SPV_OPERAND_TYPE_ID, {inst->GetSingleWordInOperand(0u)}},
            {SPV_OPERAND_TYPE_ID, {id}}});
@@ -348,7 +348,8 @@
 FoldingRule MergeNegateArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFNegate || inst->opcode() == SpvOpSNegate);
+    assert(inst->opcode() == spv::Op::OpFNegate ||
+           inst->opcode() == spv::Op::OpSNegate);
     (void)constants;
     const analysis::Type* type =
         context->get_type_mgr()->GetType(inst->type_id());
@@ -362,7 +363,7 @@
 
     if (op_inst->opcode() == inst->opcode()) {
       // Elide negates.
-      inst->SetOpcode(SpvOpCopyObject);
+      inst->SetOpcode(spv::Op::OpCopyObject);
       inst->SetInOperands(
           {{SPV_OPERAND_TYPE_ID, {op_inst->GetSingleWordInOperand(0u)}}});
       return true;
@@ -382,7 +383,8 @@
 FoldingRule MergeNegateMulDivArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFNegate || inst->opcode() == SpvOpSNegate);
+    assert(inst->opcode() == spv::Op::OpFNegate ||
+           inst->opcode() == spv::Op::OpSNegate);
     (void)constants;
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
     const analysis::Type* type =
@@ -398,9 +400,10 @@
     uint32_t width = ElementWidth(type);
     if (width != 32 && width != 64) return false;
 
-    SpvOp opcode = op_inst->opcode();
-    if (opcode == SpvOpFMul || opcode == SpvOpFDiv || opcode == SpvOpIMul ||
-        opcode == SpvOpSDiv || opcode == SpvOpUDiv) {
+    spv::Op opcode = op_inst->opcode();
+    if (opcode == spv::Op::OpFMul || opcode == spv::Op::OpFDiv ||
+        opcode == spv::Op::OpIMul || opcode == spv::Op::OpSDiv ||
+        opcode == spv::Op::OpUDiv) {
       std::vector<const analysis::Constant*> op_constants =
           const_mgr->GetOperandConstants(op_inst);
       // Merge negate into mul or div if one operand is constant.
@@ -413,7 +416,8 @@
                                     : op_inst->GetSingleWordInOperand(1u);
         // Change this instruction to a mul/div.
         inst->SetOpcode(op_inst->opcode());
-        if (opcode == SpvOpFDiv || opcode == SpvOpUDiv || opcode == SpvOpSDiv) {
+        if (opcode == spv::Op::OpFDiv || opcode == spv::Op::OpUDiv ||
+            opcode == spv::Op::OpSDiv) {
           uint32_t op0 = zero_is_variable ? non_const_id : neg_id;
           uint32_t op1 = zero_is_variable ? neg_id : non_const_id;
           inst->SetInOperands(
@@ -440,7 +444,8 @@
 FoldingRule MergeNegateAddSubArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFNegate || inst->opcode() == SpvOpSNegate);
+    assert(inst->opcode() == spv::Op::OpFNegate ||
+           inst->opcode() == spv::Op::OpSNegate);
     (void)constants;
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
     const analysis::Type* type =
@@ -456,14 +461,16 @@
     uint32_t width = ElementWidth(type);
     if (width != 32 && width != 64) return false;
 
-    if (op_inst->opcode() == SpvOpFAdd || op_inst->opcode() == SpvOpFSub ||
-        op_inst->opcode() == SpvOpIAdd || op_inst->opcode() == SpvOpISub) {
+    if (op_inst->opcode() == spv::Op::OpFAdd ||
+        op_inst->opcode() == spv::Op::OpFSub ||
+        op_inst->opcode() == spv::Op::OpIAdd ||
+        op_inst->opcode() == spv::Op::OpISub) {
       std::vector<const analysis::Constant*> op_constants =
           const_mgr->GetOperandConstants(op_inst);
       if (op_constants[0] || op_constants[1]) {
         bool zero_is_variable = op_constants[0] == nullptr;
-        bool is_add = (op_inst->opcode() == SpvOpFAdd) ||
-                      (op_inst->opcode() == SpvOpIAdd);
+        bool is_add = (op_inst->opcode() == spv::Op::OpFAdd) ||
+                      (op_inst->opcode() == spv::Op::OpIAdd);
         bool swap_operands = !is_add || zero_is_variable;
         bool negate_const = is_add;
         const analysis::Constant* c = ConstInput(op_constants);
@@ -481,7 +488,8 @@
         uint32_t op1 =
             zero_is_variable ? const_id : op_inst->GetSingleWordInOperand(1u);
         if (swap_operands) std::swap(op0, op1);
-        inst->SetOpcode(HasFloatingPoint(type) ? SpvOpFSub : SpvOpISub);
+        inst->SetOpcode(HasFloatingPoint(type) ? spv::Op::OpFSub
+                                               : spv::Op::OpISub);
         inst->SetInOperands(
             {{SPV_OPERAND_TYPE_ID, {op0}}, {SPV_OPERAND_TYPE_ID, {op1}}});
         return true;
@@ -512,7 +520,7 @@
 // id. Returns 0 if the result is not a valid value. The input types must be
 // Float.
 uint32_t PerformFloatingPointOperation(analysis::ConstantManager* const_mgr,
-                                       SpvOp opcode,
+                                       spv::Op opcode,
                                        const analysis::Constant* input1,
                                        const analysis::Constant* input2) {
   const analysis::Type* type = input1->type();
@@ -535,17 +543,17 @@
   }                                                                          \
   static_assert(true, "require extra semicolon")
   switch (opcode) {
-    case SpvOpFMul:
+    case spv::Op::OpFMul:
       FOLD_OP(*);
       break;
-    case SpvOpFDiv:
+    case spv::Op::OpFDiv:
       if (HasZero(input2)) return 0;
       FOLD_OP(/);
       break;
-    case SpvOpFAdd:
+    case spv::Op::OpFAdd:
       FOLD_OP(+);
       break;
-    case SpvOpFSub:
+    case spv::Op::OpFSub:
       FOLD_OP(-);
       break;
     default:
@@ -561,7 +569,8 @@
 // id. Returns 0 if the result is not a valid value. The input types must be
 // Integers.
 uint32_t PerformIntegerOperation(analysis::ConstantManager* const_mgr,
-                                 SpvOp opcode, const analysis::Constant* input1,
+                                 spv::Op opcode,
+                                 const analysis::Constant* input1,
                                  const analysis::Constant* input2) {
   assert(input1->type()->AsInteger());
   const analysis::Integer* type = input1->type()->AsInteger();
@@ -582,17 +591,17 @@
   }                                                      \
   static_assert(true, "require extra semicolon")
   switch (opcode) {
-    case SpvOpIMul:
+    case spv::Op::OpIMul:
       FOLD_OP(*);
       break;
-    case SpvOpSDiv:
-    case SpvOpUDiv:
+    case spv::Op::OpSDiv:
+    case spv::Op::OpUDiv:
       assert(false && "Should not merge integer division");
       break;
-    case SpvOpIAdd:
+    case spv::Op::OpIAdd:
       FOLD_OP(+);
       break;
-    case SpvOpISub:
+    case spv::Op::OpISub:
       FOLD_OP(-);
       break;
     default:
@@ -607,7 +616,7 @@
 // Performs |input1| |opcode| |input2| and returns the merged constant result
 // id. Returns 0 if the result is not a valid value. The input types must be
 // Integers, Floats or Vectors of such.
-uint32_t PerformOperation(analysis::ConstantManager* const_mgr, SpvOp opcode,
+uint32_t PerformOperation(analysis::ConstantManager* const_mgr, spv::Op opcode,
                           const analysis::Constant* input1,
                           const analysis::Constant* input2) {
   assert(input1 && input2);
@@ -667,7 +676,8 @@
 FoldingRule MergeMulMulArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFMul || inst->opcode() == SpvOpIMul);
+    assert(inst->opcode() == spv::Op::OpFMul ||
+           inst->opcode() == spv::Op::OpIMul);
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
     const analysis::Type* type =
         context->get_type_mgr()->GetType(inst->type_id());
@@ -719,7 +729,7 @@
 FoldingRule MergeMulDivArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFMul);
+    assert(inst->opcode() == spv::Op::OpFMul);
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
     analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
 
@@ -733,10 +743,10 @@
     for (uint32_t i = 0; i < 2; i++) {
       uint32_t op_id = inst->GetSingleWordInOperand(i);
       Instruction* op_inst = def_use_mgr->GetDef(op_id);
-      if (op_inst->opcode() == SpvOpFDiv) {
+      if (op_inst->opcode() == spv::Op::OpFDiv) {
         if (op_inst->GetSingleWordInOperand(1) ==
             inst->GetSingleWordInOperand(1 - i)) {
-          inst->SetOpcode(SpvOpCopyObject);
+          inst->SetOpcode(spv::Op::OpCopyObject);
           inst->SetInOperands(
               {{SPV_OPERAND_TYPE_ID, {op_inst->GetSingleWordInOperand(0)}}});
           return true;
@@ -749,7 +759,7 @@
     Instruction* other_inst = NonConstInput(context, constants[0], inst);
     if (!other_inst->IsFloatingPointFoldingAllowed()) return false;
 
-    if (other_inst->opcode() == SpvOpFDiv) {
+    if (other_inst->opcode() == spv::Op::OpFDiv) {
       std::vector<const analysis::Constant*> other_constants =
           const_mgr->GetOperandConstants(other_inst);
       const analysis::Constant* const_input2 = ConstInput(other_constants);
@@ -793,7 +803,8 @@
 FoldingRule MergeMulNegateArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFMul || inst->opcode() == SpvOpIMul);
+    assert(inst->opcode() == spv::Op::OpFMul ||
+           inst->opcode() == spv::Op::OpIMul);
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
     const analysis::Type* type =
         context->get_type_mgr()->GetType(inst->type_id());
@@ -809,8 +820,8 @@
     if (uses_float && !other_inst->IsFloatingPointFoldingAllowed())
       return false;
 
-    if (other_inst->opcode() == SpvOpFNegate ||
-        other_inst->opcode() == SpvOpSNegate) {
+    if (other_inst->opcode() == spv::Op::OpFNegate ||
+        other_inst->opcode() == spv::Op::OpSNegate) {
       uint32_t neg_id = NegateConstant(const_mgr, const_input1);
 
       inst->SetInOperands(
@@ -833,7 +844,7 @@
 FoldingRule MergeDivDivArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFDiv);
+    assert(inst->opcode() == spv::Op::OpFDiv);
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
     const analysis::Type* type =
         context->get_type_mgr()->GetType(inst->type_id());
@@ -856,10 +867,10 @@
 
       bool other_first_is_variable = other_constants[0] == nullptr;
 
-      SpvOp merge_op = inst->opcode();
+      spv::Op merge_op = inst->opcode();
       if (other_first_is_variable) {
         // Constants magnify.
-        merge_op = SpvOpFMul;
+        merge_op = spv::Op::OpFMul;
       }
 
       // This is an x / (*) case. Swap the inputs. Doesn't harm multiply
@@ -873,10 +884,10 @@
                                   ? other_inst->GetSingleWordInOperand(0u)
                                   : other_inst->GetSingleWordInOperand(1u);
 
-      SpvOp op = inst->opcode();
+      spv::Op op = inst->opcode();
       if (!first_is_variable && !other_first_is_variable) {
         // Effectively div of 1/x, so change to multiply.
-        op = SpvOpFMul;
+        op = spv::Op::OpFMul;
       }
 
       uint32_t op1 = merged_id;
@@ -904,7 +915,7 @@
 FoldingRule MergeDivMulArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFDiv);
+    assert(inst->opcode() == spv::Op::OpFDiv);
     analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
 
@@ -918,11 +929,11 @@
     uint32_t op_id = inst->GetSingleWordInOperand(0);
     Instruction* op_inst = def_use_mgr->GetDef(op_id);
 
-    if (op_inst->opcode() == SpvOpFMul) {
+    if (op_inst->opcode() == spv::Op::OpFMul) {
       for (uint32_t i = 0; i < 2; i++) {
         if (op_inst->GetSingleWordInOperand(i) ==
             inst->GetSingleWordInOperand(1)) {
-          inst->SetOpcode(SpvOpCopyObject);
+          inst->SetOpcode(spv::Op::OpCopyObject);
           inst->SetInOperands({{SPV_OPERAND_TYPE_ID,
                                 {op_inst->GetSingleWordInOperand(1 - i)}}});
           return true;
@@ -936,7 +947,7 @@
     if (!other_inst->IsFloatingPointFoldingAllowed()) return false;
 
     bool first_is_variable = constants[0] == nullptr;
-    if (other_inst->opcode() == SpvOpFMul) {
+    if (other_inst->opcode() == spv::Op::OpFMul) {
       std::vector<const analysis::Constant*> other_constants =
           const_mgr->GetOperandConstants(other_inst);
       const analysis::Constant* const_input2 = ConstInput(other_constants);
@@ -976,7 +987,7 @@
 FoldingRule MergeDivNegateArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFDiv);
+    assert(inst->opcode() == spv::Op::OpFDiv);
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
     if (!inst->IsFloatingPointFoldingAllowed()) return false;
 
@@ -986,7 +997,7 @@
     if (!other_inst->IsFloatingPointFoldingAllowed()) return false;
 
     bool first_is_variable = constants[0] == nullptr;
-    if (other_inst->opcode() == SpvOpFNegate) {
+    if (other_inst->opcode() == spv::Op::OpFNegate) {
       uint32_t neg_id = NegateConstant(const_mgr, const_input1);
 
       if (first_is_variable) {
@@ -1012,7 +1023,8 @@
 FoldingRule MergeAddNegateArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFAdd || inst->opcode() == SpvOpIAdd);
+    assert(inst->opcode() == spv::Op::OpFAdd ||
+           inst->opcode() == spv::Op::OpIAdd);
     const analysis::Type* type =
         context->get_type_mgr()->GetType(inst->type_id());
     bool uses_float = HasFloatingPoint(type);
@@ -1024,9 +1036,10 @@
     if (uses_float && !other_inst->IsFloatingPointFoldingAllowed())
       return false;
 
-    if (other_inst->opcode() == SpvOpSNegate ||
-        other_inst->opcode() == SpvOpFNegate) {
-      inst->SetOpcode(HasFloatingPoint(type) ? SpvOpFSub : SpvOpISub);
+    if (other_inst->opcode() == spv::Op::OpSNegate ||
+        other_inst->opcode() == spv::Op::OpFNegate) {
+      inst->SetOpcode(HasFloatingPoint(type) ? spv::Op::OpFSub
+                                             : spv::Op::OpISub);
       uint32_t const_id = constants[0] ? inst->GetSingleWordInOperand(0u)
                                        : inst->GetSingleWordInOperand(1u);
       inst->SetInOperands(
@@ -1045,7 +1058,8 @@
 FoldingRule MergeSubNegateArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFSub || inst->opcode() == SpvOpISub);
+    assert(inst->opcode() == spv::Op::OpFSub ||
+           inst->opcode() == spv::Op::OpISub);
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
     const analysis::Type* type =
         context->get_type_mgr()->GetType(inst->type_id());
@@ -1061,15 +1075,15 @@
     if (uses_float && !other_inst->IsFloatingPointFoldingAllowed())
       return false;
 
-    if (other_inst->opcode() == SpvOpSNegate ||
-        other_inst->opcode() == SpvOpFNegate) {
+    if (other_inst->opcode() == spv::Op::OpSNegate ||
+        other_inst->opcode() == spv::Op::OpFNegate) {
       uint32_t op1 = 0;
       uint32_t op2 = 0;
-      SpvOp opcode = inst->opcode();
+      spv::Op opcode = inst->opcode();
       if (constants[0] != nullptr) {
         op1 = other_inst->GetSingleWordInOperand(0u);
         op2 = inst->GetSingleWordInOperand(0u);
-        opcode = HasFloatingPoint(type) ? SpvOpFAdd : SpvOpIAdd;
+        opcode = HasFloatingPoint(type) ? spv::Op::OpFAdd : spv::Op::OpIAdd;
       } else {
         op1 = NegateConstant(const_mgr, const_input1);
         op2 = other_inst->GetSingleWordInOperand(0u);
@@ -1093,7 +1107,8 @@
 FoldingRule MergeAddAddArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFAdd || inst->opcode() == SpvOpIAdd);
+    assert(inst->opcode() == spv::Op::OpFAdd ||
+           inst->opcode() == spv::Op::OpIAdd);
     const analysis::Type* type =
         context->get_type_mgr()->GetType(inst->type_id());
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
@@ -1109,8 +1124,8 @@
     if (uses_float && !other_inst->IsFloatingPointFoldingAllowed())
       return false;
 
-    if (other_inst->opcode() == SpvOpFAdd ||
-        other_inst->opcode() == SpvOpIAdd) {
+    if (other_inst->opcode() == spv::Op::OpFAdd ||
+        other_inst->opcode() == spv::Op::OpIAdd) {
       std::vector<const analysis::Constant*> other_constants =
           const_mgr->GetOperandConstants(other_inst);
       const analysis::Constant* const_input2 = ConstInput(other_constants);
@@ -1140,7 +1155,8 @@
 FoldingRule MergeAddSubArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFAdd || inst->opcode() == SpvOpIAdd);
+    assert(inst->opcode() == spv::Op::OpFAdd ||
+           inst->opcode() == spv::Op::OpIAdd);
     const analysis::Type* type =
         context->get_type_mgr()->GetType(inst->type_id());
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
@@ -1156,15 +1172,15 @@
     if (uses_float && !other_inst->IsFloatingPointFoldingAllowed())
       return false;
 
-    if (other_inst->opcode() == SpvOpFSub ||
-        other_inst->opcode() == SpvOpISub) {
+    if (other_inst->opcode() == spv::Op::OpFSub ||
+        other_inst->opcode() == spv::Op::OpISub) {
       std::vector<const analysis::Constant*> other_constants =
           const_mgr->GetOperandConstants(other_inst);
       const analysis::Constant* const_input2 = ConstInput(other_constants);
       if (!const_input2) return false;
 
       bool first_is_variable = other_constants[0] == nullptr;
-      SpvOp op = inst->opcode();
+      spv::Op op = inst->opcode();
       uint32_t op1 = 0;
       uint32_t op2 = 0;
       if (first_is_variable) {
@@ -1199,7 +1215,8 @@
 FoldingRule MergeSubAddArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFSub || inst->opcode() == SpvOpISub);
+    assert(inst->opcode() == spv::Op::OpFSub ||
+           inst->opcode() == spv::Op::OpISub);
     const analysis::Type* type =
         context->get_type_mgr()->GetType(inst->type_id());
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
@@ -1215,8 +1232,8 @@
     if (uses_float && !other_inst->IsFloatingPointFoldingAllowed())
       return false;
 
-    if (other_inst->opcode() == SpvOpFAdd ||
-        other_inst->opcode() == SpvOpIAdd) {
+    if (other_inst->opcode() == spv::Op::OpFAdd ||
+        other_inst->opcode() == spv::Op::OpIAdd) {
       std::vector<const analysis::Constant*> other_constants =
           const_mgr->GetOperandConstants(other_inst);
       const analysis::Constant* const_input2 = ConstInput(other_constants);
@@ -1231,7 +1248,7 @@
       // Subtract the constants.
       uint32_t merged_id = PerformOperation(const_mgr, inst->opcode(),
                                             const_input1, const_input2);
-      SpvOp op = inst->opcode();
+      spv::Op op = inst->opcode();
       uint32_t op1 = 0;
       uint32_t op2 = 0;
       if (constants[0] == nullptr) {
@@ -1264,7 +1281,8 @@
 FoldingRule MergeSubSubArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFSub || inst->opcode() == SpvOpISub);
+    assert(inst->opcode() == spv::Op::OpFSub ||
+           inst->opcode() == spv::Op::OpISub);
     const analysis::Type* type =
         context->get_type_mgr()->GetType(inst->type_id());
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
@@ -1280,8 +1298,8 @@
     if (uses_float && !other_inst->IsFloatingPointFoldingAllowed())
       return false;
 
-    if (other_inst->opcode() == SpvOpFSub ||
-        other_inst->opcode() == SpvOpISub) {
+    if (other_inst->opcode() == spv::Op::OpFSub ||
+        other_inst->opcode() == spv::Op::OpISub) {
       std::vector<const analysis::Constant*> other_constants =
           const_mgr->GetOperandConstants(other_inst);
       const analysis::Constant* const_input2 = ConstInput(other_constants);
@@ -1292,9 +1310,9 @@
 
       // Merge the constants.
       uint32_t merged_id = 0;
-      SpvOp merge_op = inst->opcode();
+      spv::Op merge_op = inst->opcode();
       if (other_constants[0] == nullptr) {
-        merge_op = uses_float ? SpvOpFAdd : SpvOpIAdd;
+        merge_op = uses_float ? spv::Op::OpFAdd : spv::Op::OpIAdd;
       } else if (constants[0] == nullptr) {
         std::swap(const_input1, const_input2);
       }
@@ -1302,10 +1320,10 @@
           PerformOperation(const_mgr, merge_op, const_input1, const_input2);
       if (merged_id == 0) return false;
 
-      SpvOp op = inst->opcode();
+      spv::Op op = inst->opcode();
       if (constants[0] != nullptr && other_constants[0] != nullptr) {
         // Change the operation.
-        op = uses_float ? SpvOpFAdd : SpvOpIAdd;
+        op = uses_float ? spv::Op::OpFAdd : spv::Op::OpIAdd;
       }
 
       uint32_t op1 = 0;
@@ -1333,13 +1351,14 @@
   IRContext* context = inst->context();
   analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
   Instruction* sub_inst = def_use_mgr->GetDef(sub);
-  if (sub_inst->opcode() != SpvOpFSub && sub_inst->opcode() != SpvOpISub)
+  if (sub_inst->opcode() != spv::Op::OpFSub &&
+      sub_inst->opcode() != spv::Op::OpISub)
     return false;
-  if (sub_inst->opcode() == SpvOpFSub &&
+  if (sub_inst->opcode() == spv::Op::OpFSub &&
       !sub_inst->IsFloatingPointFoldingAllowed())
     return false;
   if (addend != sub_inst->GetSingleWordInOperand(1)) return false;
-  inst->SetOpcode(SpvOpCopyObject);
+  inst->SetOpcode(spv::Op::OpCopyObject);
   inst->SetInOperands(
       {{SPV_OPERAND_TYPE_ID, {sub_inst->GetSingleWordInOperand(0)}}});
   context->UpdateDefUse(inst);
@@ -1355,7 +1374,8 @@
 FoldingRule MergeGenericAddSubArithmetic() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>&) {
-    assert(inst->opcode() == SpvOpFAdd || inst->opcode() == SpvOpIAdd);
+    assert(inst->opcode() == spv::Op::OpFAdd ||
+           inst->opcode() == spv::Op::OpIAdd);
     const analysis::Type* type =
         context->get_type_mgr()->GetType(inst->type_id());
     bool uses_float = HasFloatingPoint(type);
@@ -1383,7 +1403,8 @@
       IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
   Instruction* new_add_inst = ir_builder.AddBinaryOp(
       inst->type_id(), inst->opcode(), factor0_1, factor1_1);
-  inst->SetOpcode(inst->opcode() == SpvOpFAdd ? SpvOpFMul : SpvOpIMul);
+  inst->SetOpcode(inst->opcode() == spv::Op::OpFAdd ? spv::Op::OpFMul
+                                                    : spv::Op::OpIMul);
   inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {factor0_0}},
                        {SPV_OPERAND_TYPE_ID, {new_add_inst->result_id()}}});
   context->UpdateDefUse(inst);
@@ -1395,7 +1416,8 @@
 FoldingRule FactorAddMuls() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>&) {
-    assert(inst->opcode() == SpvOpFAdd || inst->opcode() == SpvOpIAdd);
+    assert(inst->opcode() == spv::Op::OpFAdd ||
+           inst->opcode() == spv::Op::OpIAdd);
     const analysis::Type* type =
         context->get_type_mgr()->GetType(inst->type_id());
     bool uses_float = HasFloatingPoint(type);
@@ -1404,13 +1426,13 @@
     analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
     uint32_t add_op0 = inst->GetSingleWordInOperand(0);
     Instruction* add_op0_inst = def_use_mgr->GetDef(add_op0);
-    if (add_op0_inst->opcode() != SpvOpFMul &&
-        add_op0_inst->opcode() != SpvOpIMul)
+    if (add_op0_inst->opcode() != spv::Op::OpFMul &&
+        add_op0_inst->opcode() != spv::Op::OpIMul)
       return false;
     uint32_t add_op1 = inst->GetSingleWordInOperand(1);
     Instruction* add_op1_inst = def_use_mgr->GetDef(add_op1);
-    if (add_op1_inst->opcode() != SpvOpFMul &&
-        add_op1_inst->opcode() != SpvOpIMul)
+    if (add_op1_inst->opcode() != spv::Op::OpFMul &&
+        add_op1_inst->opcode() != spv::Op::OpIMul)
       return false;
 
     // Only perform this optimization if both of the muls only have one use.
@@ -1418,7 +1440,7 @@
     if (def_use_mgr->NumUses(add_op0_inst) > 1) return false;
     if (def_use_mgr->NumUses(add_op1_inst) > 1) return false;
 
-    if (add_op0_inst->opcode() == SpvOpFMul &&
+    if (add_op0_inst->opcode() == spv::Op::OpFMul &&
         (!add_op0_inst->IsFloatingPointFoldingAllowed() ||
          !add_op1_inst->IsFloatingPointFoldingAllowed()))
       return false;
@@ -1457,7 +1479,7 @@
   operands.push_back({SPV_OPERAND_TYPE_ID, {y}});
   operands.push_back({SPV_OPERAND_TYPE_ID, {a}});
 
-  inst->SetOpcode(SpvOpExtInst);
+  inst->SetOpcode(spv::Op::OpExtInst);
   inst->SetInOperands(std::move(operands));
 }
 
@@ -1468,7 +1490,7 @@
 // a + (x * y) = Fma x y a
 bool MergeMulAddArithmetic(IRContext* context, Instruction* inst,
                            const std::vector<const analysis::Constant*>&) {
-  assert(inst->opcode() == SpvOpFAdd);
+  assert(inst->opcode() == spv::Op::OpFAdd);
 
   if (!inst->IsFloatingPointFoldingAllowed()) {
     return false;
@@ -1479,7 +1501,7 @@
     uint32_t op_id = inst->GetSingleWordInOperand(i);
     Instruction* op_inst = def_use_mgr->GetDef(op_id);
 
-    if (op_inst->opcode() != SpvOpFMul) {
+    if (op_inst->opcode() != spv::Op::OpFMul) {
       continue;
     }
 
@@ -1514,7 +1536,7 @@
       sub->context(), sub,
       IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
 
-  Instruction* neg = ir_builder.AddUnaryOp(sub->type_id(), SpvOpFNegate,
+  Instruction* neg = ir_builder.AddUnaryOp(sub->type_id(), spv::Op::OpFNegate,
                                            negate_addition ? a : x);
   uint32_t neg_op = neg->result_id();  // -a : -x
 
@@ -1525,7 +1547,7 @@
   operands.push_back({SPV_OPERAND_TYPE_ID, {y}});
   operands.push_back({SPV_OPERAND_TYPE_ID, {negate_addition ? neg_op : a}});
 
-  sub->SetOpcode(SpvOpExtInst);
+  sub->SetOpcode(spv::Op::OpExtInst);
   sub->SetInOperands(std::move(operands));
 }
 
@@ -1536,7 +1558,7 @@
 // a - (x * y) = Fma -x y a
 bool MergeMulSubArithmetic(IRContext* context, Instruction* sub,
                            const std::vector<const analysis::Constant*>&) {
-  assert(sub->opcode() == SpvOpFSub);
+  assert(sub->opcode() == spv::Op::OpFSub);
 
   if (!sub->IsFloatingPointFoldingAllowed()) {
     return false;
@@ -1547,7 +1569,7 @@
     uint32_t op_id = sub->GetSingleWordInOperand(i);
     Instruction* mul = def_use_mgr->GetDef(op_id);
 
-    if (mul->opcode() != SpvOpFMul) {
+    if (mul->opcode() != spv::Op::OpFMul) {
       continue;
     }
 
@@ -1567,7 +1589,8 @@
 FoldingRule IntMultipleBy1() {
   return [](IRContext*, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpIMul && "Wrong opcode.  Should be OpIMul.");
+    assert(inst->opcode() == spv::Op::OpIMul &&
+           "Wrong opcode.  Should be OpIMul.");
     for (uint32_t i = 0; i < 2; i++) {
       if (constants[i] == nullptr) {
         continue;
@@ -1579,7 +1602,7 @@
         bool is_one = (width == 32) ? int_constant->GetU32BitValue() == 1u
                                     : int_constant->GetU64BitValue() == 1ull;
         if (is_one) {
-          inst->SetOpcode(SpvOpCopyObject);
+          inst->SetOpcode(spv::Op::OpCopyObject);
           inst->SetInOperands(
               {{SPV_OPERAND_TYPE_ID, {inst->GetSingleWordInOperand(1 - i)}}});
           return true;
@@ -1596,7 +1619,7 @@
 uint32_t GetNumOfElementsContributedByOperand(IRContext* context,
                                               const Instruction* inst,
                                               uint32_t index) {
-  assert(inst->opcode() == SpvOpCompositeConstruct);
+  assert(inst->opcode() == spv::Op::OpCompositeConstruct);
   analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
   analysis::TypeManager* type_mgr = context->get_type_mgr();
 
@@ -1627,7 +1650,7 @@
 // out-of-bounds. |inst| must be an |OpCompositeConstruct| instruction.
 std::vector<Operand> GetExtractOperandsForElementOfCompositeConstruct(
     IRContext* context, const Instruction* inst, uint32_t result_index) {
-  assert(inst->opcode() == SpvOpCompositeConstruct);
+  assert(inst->opcode() == spv::Op::OpCompositeConstruct);
   analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
   analysis::TypeManager* type_mgr = context->get_type_mgr();
 
@@ -1666,7 +1689,7 @@
     const std::vector<const analysis::Constant*>&) {
   // If the input to an OpCompositeExtract is an OpCompositeConstruct,
   // then we can simply use the appropriate element in the construction.
-  assert(inst->opcode() == SpvOpCompositeExtract &&
+  assert(inst->opcode() == spv::Op::OpCompositeExtract &&
          "Wrong opcode.  Should be OpCompositeExtract.");
   analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
 
@@ -1678,7 +1701,7 @@
   uint32_t cid = inst->GetSingleWordInOperand(kExtractCompositeIdInIdx);
   Instruction* cinst = def_use_mgr->GetDef(cid);
 
-  if (cinst->opcode() != SpvOpCompositeConstruct) {
+  if (cinst->opcode() != spv::Op::OpCompositeConstruct) {
     return false;
   }
 
@@ -1700,7 +1723,7 @@
   if (operands.size() == 1) {
     // If there were no extra indices, then we have the final object.  No need
     // to extract any more.
-    inst->SetOpcode(SpvOpCopyObject);
+    inst->SetOpcode(spv::Op::OpCopyObject);
   }
 
   inst->SetInOperands(std::move(operands));
@@ -1738,8 +1761,8 @@
 bool HaveSameIndexesExceptForLast(Instruction* inst_1, Instruction* inst_2) {
   assert(inst_1->opcode() == inst_2->opcode() &&
          "Expecting the opcodes to be the same.");
-  assert((inst_1->opcode() == SpvOpCompositeInsert ||
-          inst_1->opcode() == SpvOpCompositeExtract) &&
+  assert((inst_1->opcode() == spv::Op::OpCompositeInsert ||
+          inst_1->opcode() == spv::Op::OpCompositeExtract) &&
          "Instructions must be OpCompositeInsert or OpCompositeExtract.");
 
   if (inst_1->NumInOperands() != inst_2->NumInOperands()) {
@@ -1747,7 +1770,7 @@
   }
 
   uint32_t first_index_position =
-      (inst_1->opcode() == SpvOpCompositeInsert ? 2 : 1);
+      (inst_1->opcode() == spv::Op::OpCompositeInsert ? 2 : 1);
   for (uint32_t i = first_index_position; i < inst_1->NumInOperands() - 1;
        i++) {
     if (inst_1->GetSingleWordInOperand(i) !=
@@ -1766,7 +1789,7 @@
 bool CompositeExtractFeedingConstruct(
     IRContext* context, Instruction* inst,
     const std::vector<const analysis::Constant*>&) {
-  assert(inst->opcode() == SpvOpCompositeConstruct &&
+  assert(inst->opcode() == spv::Op::OpCompositeConstruct &&
          "Wrong opcode.  Should be OpCompositeConstruct.");
   analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
   uint32_t original_id = 0;
@@ -1788,7 +1811,7 @@
       first_element_inst = element_inst;
     }
 
-    if (element_inst->opcode() != SpvOpCompositeExtract) {
+    if (element_inst->opcode() != spv::Op::OpCompositeExtract) {
       return false;
     }
 
@@ -1828,14 +1851,14 @@
 
   if (first_element_inst->NumInOperands() == 2) {
     // Simplify by using the original object.
-    inst->SetOpcode(SpvOpCopyObject);
+    inst->SetOpcode(spv::Op::OpCopyObject);
     inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {original_id}}});
     return true;
   }
 
   // Copies the original id and all indexes except for the last to the new
   // extract instruction.
-  inst->SetOpcode(SpvOpCompositeExtract);
+  inst->SetOpcode(spv::Op::OpCompositeExtract);
   inst->SetInOperands(std::vector<Operand>(first_element_inst->begin() + 2,
                                            first_element_inst->end() - 1));
   return true;
@@ -1844,13 +1867,13 @@
 FoldingRule InsertFeedingExtract() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>&) {
-    assert(inst->opcode() == SpvOpCompositeExtract &&
+    assert(inst->opcode() == spv::Op::OpCompositeExtract &&
            "Wrong opcode.  Should be OpCompositeExtract.");
     analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
     uint32_t cid = inst->GetSingleWordInOperand(kExtractCompositeIdInIdx);
     Instruction* cinst = def_use_mgr->GetDef(cid);
 
-    if (cinst->opcode() != SpvOpCompositeInsert) {
+    if (cinst->opcode() != spv::Op::OpCompositeInsert) {
       return false;
     }
 
@@ -1870,7 +1893,7 @@
 
     // We are extracting the element that was inserted.
     if (i == inst->NumInOperands() && i + 1 == cinst->NumInOperands()) {
-      inst->SetOpcode(SpvOpCopyObject);
+      inst->SetOpcode(spv::Op::OpCopyObject);
       inst->SetInOperands(
           {{SPV_OPERAND_TYPE_ID,
             {cinst->GetSingleWordInOperand(kInsertObjectIdInIdx)}}});
@@ -1919,14 +1942,14 @@
 FoldingRule VectorShuffleFeedingExtract() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>&) {
-    assert(inst->opcode() == SpvOpCompositeExtract &&
+    assert(inst->opcode() == spv::Op::OpCompositeExtract &&
            "Wrong opcode.  Should be OpCompositeExtract.");
     analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
     analysis::TypeManager* type_mgr = context->get_type_mgr();
     uint32_t cid = inst->GetSingleWordInOperand(kExtractCompositeIdInIdx);
     Instruction* cinst = def_use_mgr->GetDef(cid);
 
-    if (cinst->opcode() != SpvOpVectorShuffle) {
+    if (cinst->opcode() != spv::Op::OpVectorShuffle) {
       return false;
     }
 
@@ -1947,7 +1970,7 @@
     // Extracting an undefined value so fold this extract into an undef.
     const uint32_t undef_literal_value = 0xffffffff;
     if (new_index == undef_literal_value) {
-      inst->SetOpcode(SpvOpUndef);
+      inst->SetOpcode(spv::Op::OpUndef);
       inst->SetInOperands({});
       return true;
     }
@@ -1975,7 +1998,7 @@
 FoldingRule FMixFeedingExtract() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>&) {
-    assert(inst->opcode() == SpvOpCompositeExtract &&
+    assert(inst->opcode() == spv::Op::OpCompositeExtract &&
            "Wrong opcode.  Should be OpCompositeExtract.");
     analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
@@ -1984,7 +2007,7 @@
         inst->GetSingleWordInOperand(kExtractCompositeIdInIdx);
     Instruction* composite_inst = def_use_mgr->GetDef(composite_id);
 
-    if (composite_inst->opcode() != SpvOpExtInst) {
+    if (composite_inst->opcode() != spv::Op::OpExtInst) {
       return false;
     }
 
@@ -2004,7 +2027,7 @@
     a->SetInOperand(kExtractCompositeIdInIdx, {a_id});
     context->get_instruction_folder().FoldInstruction(a.get());
 
-    if (a->opcode() != SpvOpCopyObject) {
+    if (a->opcode() != spv::Op::OpCopyObject) {
       return false;
     }
 
@@ -2066,7 +2089,7 @@
   analysis::DefUseManager* def_use_mgr = inst->context()->get_def_use_mgr();
   std::map<uint32_t, uint32_t> values_inserted;
   Instruction* current_inst = inst;
-  while (current_inst->opcode() == SpvOpCompositeInsert) {
+  while (current_inst->opcode() == spv::Op::OpCompositeInsert) {
     if (current_inst->NumInOperands() > inst->NumInOperands()) {
       // This is the catch the case
       //   %2 = OpCompositeInsert %m2x2int %v2int_1_0 %m2x2int_undef 0
@@ -2108,7 +2131,7 @@
 // Returns the type of the element that immediately contains the element being
 // inserted by the OpCompositeInsert instruction |inst|.
 const analysis::Type* GetContainerType(Instruction* inst) {
-  assert(inst->opcode() == SpvOpCompositeInsert);
+  assert(inst->opcode() == spv::Op::OpCompositeInsert);
   analysis::TypeManager* type_mgr = inst->context()->get_type_mgr();
   return GetElementType(inst->type_id(), inst->begin() + 4, inst->end() - 1,
                         type_mgr);
@@ -2140,7 +2163,7 @@
 // instruction is replaced with an OpCopyObject instead.
 void InsertConstructedObject(Instruction* inst, const Instruction* construct) {
   if (inst->NumInOperands() == 3) {
-    inst->SetOpcode(SpvOpCopyObject);
+    inst->SetOpcode(spv::Op::OpCopyObject);
     inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {construct->result_id()}}});
   } else {
     inst->SetInOperand(kInsertObjectIdInIdx, {construct->result_id()});
@@ -2153,7 +2176,7 @@
 bool CompositeInsertToCompositeConstruct(
     IRContext* context, Instruction* inst,
     const std::vector<const analysis::Constant*>&) {
-  assert(inst->opcode() == SpvOpCompositeInsert &&
+  assert(inst->opcode() == spv::Op::OpCompositeInsert &&
          "Wrong opcode.  Should be OpCompositeInsert.");
   if (inst->NumInOperands() < 3) return false;
 
@@ -2179,7 +2202,8 @@
   // itself, can be replaced by the value itself.
   return [](IRContext*, Instruction* inst,
             const std::vector<const analysis::Constant*>&) {
-    assert(inst->opcode() == SpvOpPhi && "Wrong opcode.  Should be OpPhi.");
+    assert(inst->opcode() == spv::Op::OpPhi &&
+           "Wrong opcode.  Should be OpPhi.");
 
     uint32_t incoming_value = 0;
 
@@ -2203,7 +2227,7 @@
     }
 
     // We have a single incoming value.  Simplify using that value.
-    inst->SetOpcode(SpvOpCopyObject);
+    inst->SetOpcode(spv::Op::OpCopyObject);
     inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {incoming_value}}});
     return true;
   };
@@ -2212,7 +2236,7 @@
 FoldingRule BitCastScalarOrVector() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpBitcast && constants.size() == 1);
+    assert(inst->opcode() == spv::Op::OpBitcast && constants.size() == 1);
     if (constants[0] == nullptr) return false;
 
     const analysis::Type* type =
@@ -2232,7 +2256,7 @@
     auto new_feeder_id =
         const_mgr->GetDefiningInstruction(bitcasted_constant, inst->type_id())
             ->result_id();
-    inst->SetOpcode(SpvOpCopyObject);
+    inst->SetOpcode(spv::Op::OpCopyObject);
     inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {new_feeder_id}}});
     return true;
   };
@@ -2243,7 +2267,7 @@
   // constant can be replaced by one of the values
   return [](IRContext*, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpSelect &&
+    assert(inst->opcode() == spv::Op::OpSelect &&
            "Wrong opcode.  Should be OpSelect.");
     assert(inst->NumInOperands() == 3);
     assert(constants.size() == 3);
@@ -2253,14 +2277,14 @@
 
     if (true_id == false_id) {
       // Both results are the same, condition doesn't matter
-      inst->SetOpcode(SpvOpCopyObject);
+      inst->SetOpcode(spv::Op::OpCopyObject);
       inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {true_id}}});
       return true;
     } else if (constants[0]) {
       const analysis::Type* type = constants[0]->type();
       if (type->AsBool()) {
         // Scalar constant value, select the corresponding value.
-        inst->SetOpcode(SpvOpCopyObject);
+        inst->SetOpcode(spv::Op::OpCopyObject);
         if (constants[0]->AsNullConstant() ||
             !constants[0]->AsBoolConstant()->value()) {
           inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {false_id}}});
@@ -2272,7 +2296,7 @@
         assert(type->AsVector());
         if (constants[0]->AsNullConstant()) {
           // All values come from false id.
-          inst->SetOpcode(SpvOpCopyObject);
+          inst->SetOpcode(spv::Op::OpCopyObject);
           inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {false_id}}});
           return true;
         } else {
@@ -2299,7 +2323,7 @@
             }
           }
 
-          inst->SetOpcode(SpvOpVectorShuffle);
+          inst->SetOpcode(spv::Op::OpVectorShuffle);
           inst->SetInOperands(std::move(ops));
           return true;
         }
@@ -2359,7 +2383,8 @@
 FoldingRule RedundantFAdd() {
   return [](IRContext*, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFAdd && "Wrong opcode.  Should be OpFAdd.");
+    assert(inst->opcode() == spv::Op::OpFAdd &&
+           "Wrong opcode.  Should be OpFAdd.");
     assert(constants.size() == 2);
 
     if (!inst->IsFloatingPointFoldingAllowed()) {
@@ -2370,7 +2395,7 @@
     FloatConstantKind kind1 = getFloatConstantKind(constants[1]);
 
     if (kind0 == FloatConstantKind::Zero || kind1 == FloatConstantKind::Zero) {
-      inst->SetOpcode(SpvOpCopyObject);
+      inst->SetOpcode(spv::Op::OpCopyObject);
       inst->SetInOperands({{SPV_OPERAND_TYPE_ID,
                             {inst->GetSingleWordInOperand(
                                 kind0 == FloatConstantKind::Zero ? 1 : 0)}}});
@@ -2384,7 +2409,8 @@
 FoldingRule RedundantFSub() {
   return [](IRContext*, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFSub && "Wrong opcode.  Should be OpFSub.");
+    assert(inst->opcode() == spv::Op::OpFSub &&
+           "Wrong opcode.  Should be OpFSub.");
     assert(constants.size() == 2);
 
     if (!inst->IsFloatingPointFoldingAllowed()) {
@@ -2395,14 +2421,14 @@
     FloatConstantKind kind1 = getFloatConstantKind(constants[1]);
 
     if (kind0 == FloatConstantKind::Zero) {
-      inst->SetOpcode(SpvOpFNegate);
+      inst->SetOpcode(spv::Op::OpFNegate);
       inst->SetInOperands(
           {{SPV_OPERAND_TYPE_ID, {inst->GetSingleWordInOperand(1)}}});
       return true;
     }
 
     if (kind1 == FloatConstantKind::Zero) {
-      inst->SetOpcode(SpvOpCopyObject);
+      inst->SetOpcode(spv::Op::OpCopyObject);
       inst->SetInOperands(
           {{SPV_OPERAND_TYPE_ID, {inst->GetSingleWordInOperand(0)}}});
       return true;
@@ -2415,7 +2441,8 @@
 FoldingRule RedundantFMul() {
   return [](IRContext*, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFMul && "Wrong opcode.  Should be OpFMul.");
+    assert(inst->opcode() == spv::Op::OpFMul &&
+           "Wrong opcode.  Should be OpFMul.");
     assert(constants.size() == 2);
 
     if (!inst->IsFloatingPointFoldingAllowed()) {
@@ -2426,7 +2453,7 @@
     FloatConstantKind kind1 = getFloatConstantKind(constants[1]);
 
     if (kind0 == FloatConstantKind::Zero || kind1 == FloatConstantKind::Zero) {
-      inst->SetOpcode(SpvOpCopyObject);
+      inst->SetOpcode(spv::Op::OpCopyObject);
       inst->SetInOperands({{SPV_OPERAND_TYPE_ID,
                             {inst->GetSingleWordInOperand(
                                 kind0 == FloatConstantKind::Zero ? 0 : 1)}}});
@@ -2434,7 +2461,7 @@
     }
 
     if (kind0 == FloatConstantKind::One || kind1 == FloatConstantKind::One) {
-      inst->SetOpcode(SpvOpCopyObject);
+      inst->SetOpcode(spv::Op::OpCopyObject);
       inst->SetInOperands({{SPV_OPERAND_TYPE_ID,
                             {inst->GetSingleWordInOperand(
                                 kind0 == FloatConstantKind::One ? 1 : 0)}}});
@@ -2448,7 +2475,8 @@
 FoldingRule RedundantFDiv() {
   return [](IRContext*, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpFDiv && "Wrong opcode.  Should be OpFDiv.");
+    assert(inst->opcode() == spv::Op::OpFDiv &&
+           "Wrong opcode.  Should be OpFDiv.");
     assert(constants.size() == 2);
 
     if (!inst->IsFloatingPointFoldingAllowed()) {
@@ -2459,14 +2487,14 @@
     FloatConstantKind kind1 = getFloatConstantKind(constants[1]);
 
     if (kind0 == FloatConstantKind::Zero) {
-      inst->SetOpcode(SpvOpCopyObject);
+      inst->SetOpcode(spv::Op::OpCopyObject);
       inst->SetInOperands(
           {{SPV_OPERAND_TYPE_ID, {inst->GetSingleWordInOperand(0)}}});
       return true;
     }
 
     if (kind1 == FloatConstantKind::One) {
-      inst->SetOpcode(SpvOpCopyObject);
+      inst->SetOpcode(spv::Op::OpCopyObject);
       inst->SetInOperands(
           {{SPV_OPERAND_TYPE_ID, {inst->GetSingleWordInOperand(0)}}});
       return true;
@@ -2479,7 +2507,7 @@
 FoldingRule RedundantFMix() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpExtInst &&
+    assert(inst->opcode() == spv::Op::OpExtInst &&
            "Wrong opcode.  Should be OpExtInst.");
 
     if (!inst->IsFloatingPointFoldingAllowed()) {
@@ -2497,7 +2525,7 @@
       FloatConstantKind kind4 = getFloatConstantKind(constants[4]);
 
       if (kind4 == FloatConstantKind::Zero || kind4 == FloatConstantKind::One) {
-        inst->SetOpcode(SpvOpCopyObject);
+        inst->SetOpcode(spv::Op::OpCopyObject);
         inst->SetInOperands(
             {{SPV_OPERAND_TYPE_ID,
               {inst->GetSingleWordInOperand(kind4 == FloatConstantKind::Zero
@@ -2515,7 +2543,8 @@
 FoldingRule RedundantIAdd() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpIAdd && "Wrong opcode. Should be OpIAdd.");
+    assert(inst->opcode() == spv::Op::OpIAdd &&
+           "Wrong opcode. Should be OpIAdd.");
 
     uint32_t operand = std::numeric_limits<uint32_t>::max();
     const analysis::Type* operand_type = nullptr;
@@ -2531,9 +2560,9 @@
       const analysis::Type* inst_type =
           context->get_type_mgr()->GetType(inst->type_id());
       if (inst_type->IsSame(operand_type)) {
-        inst->SetOpcode(SpvOpCopyObject);
+        inst->SetOpcode(spv::Op::OpCopyObject);
       } else {
-        inst->SetOpcode(SpvOpBitcast);
+        inst->SetOpcode(spv::Op::OpBitcast);
       }
       inst->SetInOperands({{SPV_OPERAND_TYPE_ID, {operand}}});
       return true;
@@ -2547,7 +2576,8 @@
 FoldingRule DotProductDoingExtract() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>& constants) {
-    assert(inst->opcode() == SpvOpDot && "Wrong opcode.  Should be OpDot.");
+    assert(inst->opcode() == spv::Op::OpDot &&
+           "Wrong opcode.  Should be OpDot.");
 
     analysis::ConstantManager* const_mgr = context->get_constant_mgr();
 
@@ -2606,7 +2636,7 @@
       operands.push_back(
           {SPV_OPERAND_TYPE_LITERAL_INTEGER, {component_with_one}});
 
-      inst->SetOpcode(SpvOpCompositeExtract);
+      inst->SetOpcode(spv::Op::OpCompositeExtract);
       inst->SetInOperands(std::move(operands));
       return true;
     }
@@ -2621,20 +2651,22 @@
 FoldingRule StoringUndef() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>&) {
-    assert(inst->opcode() == SpvOpStore && "Wrong opcode.  Should be OpStore.");
+    assert(inst->opcode() == spv::Op::OpStore &&
+           "Wrong opcode.  Should be OpStore.");
 
     analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
 
     // If this is a volatile store, the store cannot be removed.
     if (inst->NumInOperands() == 3) {
-      if (inst->GetSingleWordInOperand(2) & SpvMemoryAccessVolatileMask) {
+      if (inst->GetSingleWordInOperand(2) &
+          uint32_t(spv::MemoryAccessMask::Volatile)) {
         return false;
       }
     }
 
     uint32_t object_id = inst->GetSingleWordInOperand(kStoreObjectInIdx);
     Instruction* object_inst = def_use_mgr->GetDef(object_id);
-    if (object_inst->opcode() == SpvOpUndef) {
+    if (object_inst->opcode() == spv::Op::OpUndef) {
       inst->ToNop();
       return true;
     }
@@ -2645,7 +2677,7 @@
 FoldingRule VectorShuffleFeedingShuffle() {
   return [](IRContext* context, Instruction* inst,
             const std::vector<const analysis::Constant*>&) {
-    assert(inst->opcode() == SpvOpVectorShuffle &&
+    assert(inst->opcode() == spv::Op::OpVectorShuffle &&
            "Wrong opcode.  Should be OpVectorShuffle.");
 
     analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
@@ -2658,13 +2690,13 @@
     uint32_t op0_length = op0_type->element_count();
 
     bool feeder_is_op0 = true;
-    if (feeding_shuffle_inst->opcode() != SpvOpVectorShuffle) {
+    if (feeding_shuffle_inst->opcode() != spv::Op::OpVectorShuffle) {
       feeding_shuffle_inst =
           def_use_mgr->GetDef(inst->GetSingleWordInOperand(1));
       feeder_is_op0 = false;
     }
 
-    if (feeding_shuffle_inst->opcode() != SpvOpVectorShuffle) {
+    if (feeding_shuffle_inst->opcode() != spv::Op::OpVectorShuffle) {
       return false;
     }
 
@@ -2775,7 +2807,7 @@
 FoldingRule RemoveRedundantOperands() {
   return [](IRContext*, Instruction* inst,
             const std::vector<const analysis::Constant*>&) {
-    assert(inst->opcode() == SpvOpEntryPoint &&
+    assert(inst->opcode() == spv::Op::OpEntryPoint &&
            "Wrong opcode.  Should be OpEntryPoint.");
     bool has_redundant_operand = false;
     std::unordered_set<uint32_t> seen_operands;
@@ -2808,46 +2840,52 @@
             const std::vector<const analysis::Constant*>& constants) {
     const auto opcode = inst->opcode();
     (void)opcode;
-    assert((opcode == SpvOpImageSampleImplicitLod ||
-            opcode == SpvOpImageSampleExplicitLod ||
-            opcode == SpvOpImageSampleDrefImplicitLod ||
-            opcode == SpvOpImageSampleDrefExplicitLod ||
-            opcode == SpvOpImageSampleProjImplicitLod ||
-            opcode == SpvOpImageSampleProjExplicitLod ||
-            opcode == SpvOpImageSampleProjDrefImplicitLod ||
-            opcode == SpvOpImageSampleProjDrefExplicitLod ||
-            opcode == SpvOpImageFetch || opcode == SpvOpImageGather ||
-            opcode == SpvOpImageDrefGather || opcode == SpvOpImageRead ||
-            opcode == SpvOpImageWrite ||
-            opcode == SpvOpImageSparseSampleImplicitLod ||
-            opcode == SpvOpImageSparseSampleExplicitLod ||
-            opcode == SpvOpImageSparseSampleDrefImplicitLod ||
-            opcode == SpvOpImageSparseSampleDrefExplicitLod ||
-            opcode == SpvOpImageSparseSampleProjImplicitLod ||
-            opcode == SpvOpImageSparseSampleProjExplicitLod ||
-            opcode == SpvOpImageSparseSampleProjDrefImplicitLod ||
-            opcode == SpvOpImageSparseSampleProjDrefExplicitLod ||
-            opcode == SpvOpImageSparseFetch ||
-            opcode == SpvOpImageSparseGather ||
-            opcode == SpvOpImageSparseDrefGather ||
-            opcode == SpvOpImageSparseRead) &&
+    assert((opcode == spv::Op::OpImageSampleImplicitLod ||
+            opcode == spv::Op::OpImageSampleExplicitLod ||
+            opcode == spv::Op::OpImageSampleDrefImplicitLod ||
+            opcode == spv::Op::OpImageSampleDrefExplicitLod ||
+            opcode == spv::Op::OpImageSampleProjImplicitLod ||
+            opcode == spv::Op::OpImageSampleProjExplicitLod ||
+            opcode == spv::Op::OpImageSampleProjDrefImplicitLod ||
+            opcode == spv::Op::OpImageSampleProjDrefExplicitLod ||
+            opcode == spv::Op::OpImageFetch ||
+            opcode == spv::Op::OpImageGather ||
+            opcode == spv::Op::OpImageDrefGather ||
+            opcode == spv::Op::OpImageRead || opcode == spv::Op::OpImageWrite ||
+            opcode == spv::Op::OpImageSparseSampleImplicitLod ||
+            opcode == spv::Op::OpImageSparseSampleExplicitLod ||
+            opcode == spv::Op::OpImageSparseSampleDrefImplicitLod ||
+            opcode == spv::Op::OpImageSparseSampleDrefExplicitLod ||
+            opcode == spv::Op::OpImageSparseSampleProjImplicitLod ||
+            opcode == spv::Op::OpImageSparseSampleProjExplicitLod ||
+            opcode == spv::Op::OpImageSparseSampleProjDrefImplicitLod ||
+            opcode == spv::Op::OpImageSparseSampleProjDrefExplicitLod ||
+            opcode == spv::Op::OpImageSparseFetch ||
+            opcode == spv::Op::OpImageSparseGather ||
+            opcode == spv::Op::OpImageSparseDrefGather ||
+            opcode == spv::Op::OpImageSparseRead) &&
            "Wrong opcode.  Should be an image instruction.");
 
     int32_t operand_index = ImageOperandsMaskInOperandIndex(inst);
     if (operand_index >= 0) {
       auto image_operands = inst->GetSingleWordInOperand(operand_index);
-      if (image_operands & SpvImageOperandsOffsetMask) {
+      if (image_operands & uint32_t(spv::ImageOperandsMask::Offset)) {
         uint32_t offset_operand_index = operand_index + 1;
-        if (image_operands & SpvImageOperandsBiasMask) offset_operand_index++;
-        if (image_operands & SpvImageOperandsLodMask) offset_operand_index++;
-        if (image_operands & SpvImageOperandsGradMask)
+        if (image_operands & uint32_t(spv::ImageOperandsMask::Bias))
+          offset_operand_index++;
+        if (image_operands & uint32_t(spv::ImageOperandsMask::Lod))
+          offset_operand_index++;
+        if (image_operands & uint32_t(spv::ImageOperandsMask::Grad))
           offset_operand_index += 2;
-        assert(((image_operands & SpvImageOperandsConstOffsetMask) == 0) &&
+        assert(((image_operands &
+                 uint32_t(spv::ImageOperandsMask::ConstOffset)) == 0) &&
                "Offset and ConstOffset may not be used together");
         if (offset_operand_index < inst->NumOperands()) {
           if (constants[offset_operand_index]) {
-            image_operands = image_operands | SpvImageOperandsConstOffsetMask;
-            image_operands = image_operands & ~SpvImageOperandsOffsetMask;
+            image_operands =
+                image_operands | uint32_t(spv::ImageOperandsMask::ConstOffset);
+            image_operands =
+                image_operands & ~uint32_t(spv::ImageOperandsMask::Offset);
             inst->SetInOperand(operand_index, {image_operands});
             return true;
           }
@@ -2866,108 +2904,119 @@
   // Note that the order in which rules are added to the list matters. If a rule
   // applies to the instruction, the rest of the rules will not be attempted.
   // Take that into consideration.
-  rules_[SpvOpBitcast].push_back(BitCastScalarOrVector());
+  rules_[spv::Op::OpBitcast].push_back(BitCastScalarOrVector());
 
-  rules_[SpvOpCompositeConstruct].push_back(CompositeExtractFeedingConstruct);
+  rules_[spv::Op::OpCompositeConstruct].push_back(
+      CompositeExtractFeedingConstruct);
 
-  rules_[SpvOpCompositeExtract].push_back(InsertFeedingExtract());
-  rules_[SpvOpCompositeExtract].push_back(CompositeConstructFeedingExtract);
-  rules_[SpvOpCompositeExtract].push_back(VectorShuffleFeedingExtract());
-  rules_[SpvOpCompositeExtract].push_back(FMixFeedingExtract());
+  rules_[spv::Op::OpCompositeExtract].push_back(InsertFeedingExtract());
+  rules_[spv::Op::OpCompositeExtract].push_back(
+      CompositeConstructFeedingExtract);
+  rules_[spv::Op::OpCompositeExtract].push_back(VectorShuffleFeedingExtract());
+  rules_[spv::Op::OpCompositeExtract].push_back(FMixFeedingExtract());
 
-  rules_[SpvOpCompositeInsert].push_back(CompositeInsertToCompositeConstruct);
+  rules_[spv::Op::OpCompositeInsert].push_back(
+      CompositeInsertToCompositeConstruct);
 
-  rules_[SpvOpDot].push_back(DotProductDoingExtract());
+  rules_[spv::Op::OpDot].push_back(DotProductDoingExtract());
 
-  rules_[SpvOpEntryPoint].push_back(RemoveRedundantOperands());
+  rules_[spv::Op::OpEntryPoint].push_back(RemoveRedundantOperands());
 
-  rules_[SpvOpFAdd].push_back(RedundantFAdd());
-  rules_[SpvOpFAdd].push_back(MergeAddNegateArithmetic());
-  rules_[SpvOpFAdd].push_back(MergeAddAddArithmetic());
-  rules_[SpvOpFAdd].push_back(MergeAddSubArithmetic());
-  rules_[SpvOpFAdd].push_back(MergeGenericAddSubArithmetic());
-  rules_[SpvOpFAdd].push_back(FactorAddMuls());
-  rules_[SpvOpFAdd].push_back(MergeMulAddArithmetic);
+  rules_[spv::Op::OpFAdd].push_back(RedundantFAdd());
+  rules_[spv::Op::OpFAdd].push_back(MergeAddNegateArithmetic());
+  rules_[spv::Op::OpFAdd].push_back(MergeAddAddArithmetic());
+  rules_[spv::Op::OpFAdd].push_back(MergeAddSubArithmetic());
+  rules_[spv::Op::OpFAdd].push_back(MergeGenericAddSubArithmetic());
+  rules_[spv::Op::OpFAdd].push_back(FactorAddMuls());
+  rules_[spv::Op::OpFAdd].push_back(MergeMulAddArithmetic);
 
-  rules_[SpvOpFDiv].push_back(RedundantFDiv());
-  rules_[SpvOpFDiv].push_back(ReciprocalFDiv());
-  rules_[SpvOpFDiv].push_back(MergeDivDivArithmetic());
-  rules_[SpvOpFDiv].push_back(MergeDivMulArithmetic());
-  rules_[SpvOpFDiv].push_back(MergeDivNegateArithmetic());
+  rules_[spv::Op::OpFDiv].push_back(RedundantFDiv());
+  rules_[spv::Op::OpFDiv].push_back(ReciprocalFDiv());
+  rules_[spv::Op::OpFDiv].push_back(MergeDivDivArithmetic());
+  rules_[spv::Op::OpFDiv].push_back(MergeDivMulArithmetic());
+  rules_[spv::Op::OpFDiv].push_back(MergeDivNegateArithmetic());
 
-  rules_[SpvOpFMul].push_back(RedundantFMul());
-  rules_[SpvOpFMul].push_back(MergeMulMulArithmetic());
-  rules_[SpvOpFMul].push_back(MergeMulDivArithmetic());
-  rules_[SpvOpFMul].push_back(MergeMulNegateArithmetic());
+  rules_[spv::Op::OpFMul].push_back(RedundantFMul());
+  rules_[spv::Op::OpFMul].push_back(MergeMulMulArithmetic());
+  rules_[spv::Op::OpFMul].push_back(MergeMulDivArithmetic());
+  rules_[spv::Op::OpFMul].push_back(MergeMulNegateArithmetic());
 
-  rules_[SpvOpFNegate].push_back(MergeNegateArithmetic());
-  rules_[SpvOpFNegate].push_back(MergeNegateAddSubArithmetic());
-  rules_[SpvOpFNegate].push_back(MergeNegateMulDivArithmetic());
+  rules_[spv::Op::OpFNegate].push_back(MergeNegateArithmetic());
+  rules_[spv::Op::OpFNegate].push_back(MergeNegateAddSubArithmetic());
+  rules_[spv::Op::OpFNegate].push_back(MergeNegateMulDivArithmetic());
 
-  rules_[SpvOpFSub].push_back(RedundantFSub());
-  rules_[SpvOpFSub].push_back(MergeSubNegateArithmetic());
-  rules_[SpvOpFSub].push_back(MergeSubAddArithmetic());
-  rules_[SpvOpFSub].push_back(MergeSubSubArithmetic());
-  rules_[SpvOpFSub].push_back(MergeMulSubArithmetic);
+  rules_[spv::Op::OpFSub].push_back(RedundantFSub());
+  rules_[spv::Op::OpFSub].push_back(MergeSubNegateArithmetic());
+  rules_[spv::Op::OpFSub].push_back(MergeSubAddArithmetic());
+  rules_[spv::Op::OpFSub].push_back(MergeSubSubArithmetic());
+  rules_[spv::Op::OpFSub].push_back(MergeMulSubArithmetic);
 
-  rules_[SpvOpIAdd].push_back(RedundantIAdd());
-  rules_[SpvOpIAdd].push_back(MergeAddNegateArithmetic());
-  rules_[SpvOpIAdd].push_back(MergeAddAddArithmetic());
-  rules_[SpvOpIAdd].push_back(MergeAddSubArithmetic());
-  rules_[SpvOpIAdd].push_back(MergeGenericAddSubArithmetic());
-  rules_[SpvOpIAdd].push_back(FactorAddMuls());
+  rules_[spv::Op::OpIAdd].push_back(RedundantIAdd());
+  rules_[spv::Op::OpIAdd].push_back(MergeAddNegateArithmetic());
+  rules_[spv::Op::OpIAdd].push_back(MergeAddAddArithmetic());
+  rules_[spv::Op::OpIAdd].push_back(MergeAddSubArithmetic());
+  rules_[spv::Op::OpIAdd].push_back(MergeGenericAddSubArithmetic());
+  rules_[spv::Op::OpIAdd].push_back(FactorAddMuls());
 
-  rules_[SpvOpIMul].push_back(IntMultipleBy1());
-  rules_[SpvOpIMul].push_back(MergeMulMulArithmetic());
-  rules_[SpvOpIMul].push_back(MergeMulNegateArithmetic());
+  rules_[spv::Op::OpIMul].push_back(IntMultipleBy1());
+  rules_[spv::Op::OpIMul].push_back(MergeMulMulArithmetic());
+  rules_[spv::Op::OpIMul].push_back(MergeMulNegateArithmetic());
 
-  rules_[SpvOpISub].push_back(MergeSubNegateArithmetic());
-  rules_[SpvOpISub].push_back(MergeSubAddArithmetic());
-  rules_[SpvOpISub].push_back(MergeSubSubArithmetic());
+  rules_[spv::Op::OpISub].push_back(MergeSubNegateArithmetic());
+  rules_[spv::Op::OpISub].push_back(MergeSubAddArithmetic());
+  rules_[spv::Op::OpISub].push_back(MergeSubSubArithmetic());
 
-  rules_[SpvOpPhi].push_back(RedundantPhi());
+  rules_[spv::Op::OpPhi].push_back(RedundantPhi());
 
-  rules_[SpvOpSNegate].push_back(MergeNegateArithmetic());
-  rules_[SpvOpSNegate].push_back(MergeNegateMulDivArithmetic());
-  rules_[SpvOpSNegate].push_back(MergeNegateAddSubArithmetic());
+  rules_[spv::Op::OpSNegate].push_back(MergeNegateArithmetic());
+  rules_[spv::Op::OpSNegate].push_back(MergeNegateMulDivArithmetic());
+  rules_[spv::Op::OpSNegate].push_back(MergeNegateAddSubArithmetic());
 
-  rules_[SpvOpSelect].push_back(RedundantSelect());
+  rules_[spv::Op::OpSelect].push_back(RedundantSelect());
 
-  rules_[SpvOpStore].push_back(StoringUndef());
+  rules_[spv::Op::OpStore].push_back(StoringUndef());
 
-  rules_[SpvOpVectorShuffle].push_back(VectorShuffleFeedingShuffle());
+  rules_[spv::Op::OpVectorShuffle].push_back(VectorShuffleFeedingShuffle());
 
-  rules_[SpvOpImageSampleImplicitLod].push_back(UpdateImageOperands());
-  rules_[SpvOpImageSampleExplicitLod].push_back(UpdateImageOperands());
-  rules_[SpvOpImageSampleDrefImplicitLod].push_back(UpdateImageOperands());
-  rules_[SpvOpImageSampleDrefExplicitLod].push_back(UpdateImageOperands());
-  rules_[SpvOpImageSampleProjImplicitLod].push_back(UpdateImageOperands());
-  rules_[SpvOpImageSampleProjExplicitLod].push_back(UpdateImageOperands());
-  rules_[SpvOpImageSampleProjDrefImplicitLod].push_back(UpdateImageOperands());
-  rules_[SpvOpImageSampleProjDrefExplicitLod].push_back(UpdateImageOperands());
-  rules_[SpvOpImageFetch].push_back(UpdateImageOperands());
-  rules_[SpvOpImageGather].push_back(UpdateImageOperands());
-  rules_[SpvOpImageDrefGather].push_back(UpdateImageOperands());
-  rules_[SpvOpImageRead].push_back(UpdateImageOperands());
-  rules_[SpvOpImageWrite].push_back(UpdateImageOperands());
-  rules_[SpvOpImageSparseSampleImplicitLod].push_back(UpdateImageOperands());
-  rules_[SpvOpImageSparseSampleExplicitLod].push_back(UpdateImageOperands());
-  rules_[SpvOpImageSparseSampleDrefImplicitLod].push_back(
+  rules_[spv::Op::OpImageSampleImplicitLod].push_back(UpdateImageOperands());
+  rules_[spv::Op::OpImageSampleExplicitLod].push_back(UpdateImageOperands());
+  rules_[spv::Op::OpImageSampleDrefImplicitLod].push_back(
       UpdateImageOperands());
-  rules_[SpvOpImageSparseSampleDrefExplicitLod].push_back(
+  rules_[spv::Op::OpImageSampleDrefExplicitLod].push_back(
       UpdateImageOperands());
-  rules_[SpvOpImageSparseSampleProjImplicitLod].push_back(
+  rules_[spv::Op::OpImageSampleProjImplicitLod].push_back(
       UpdateImageOperands());
-  rules_[SpvOpImageSparseSampleProjExplicitLod].push_back(
+  rules_[spv::Op::OpImageSampleProjExplicitLod].push_back(
       UpdateImageOperands());
-  rules_[SpvOpImageSparseSampleProjDrefImplicitLod].push_back(
+  rules_[spv::Op::OpImageSampleProjDrefImplicitLod].push_back(
       UpdateImageOperands());
-  rules_[SpvOpImageSparseSampleProjDrefExplicitLod].push_back(
+  rules_[spv::Op::OpImageSampleProjDrefExplicitLod].push_back(
       UpdateImageOperands());
-  rules_[SpvOpImageSparseFetch].push_back(UpdateImageOperands());
-  rules_[SpvOpImageSparseGather].push_back(UpdateImageOperands());
-  rules_[SpvOpImageSparseDrefGather].push_back(UpdateImageOperands());
-  rules_[SpvOpImageSparseRead].push_back(UpdateImageOperands());
+  rules_[spv::Op::OpImageFetch].push_back(UpdateImageOperands());
+  rules_[spv::Op::OpImageGather].push_back(UpdateImageOperands());
+  rules_[spv::Op::OpImageDrefGather].push_back(UpdateImageOperands());
+  rules_[spv::Op::OpImageRead].push_back(UpdateImageOperands());
+  rules_[spv::Op::OpImageWrite].push_back(UpdateImageOperands());
+  rules_[spv::Op::OpImageSparseSampleImplicitLod].push_back(
+      UpdateImageOperands());
+  rules_[spv::Op::OpImageSparseSampleExplicitLod].push_back(
+      UpdateImageOperands());
+  rules_[spv::Op::OpImageSparseSampleDrefImplicitLod].push_back(
+      UpdateImageOperands());
+  rules_[spv::Op::OpImageSparseSampleDrefExplicitLod].push_back(
+      UpdateImageOperands());
+  rules_[spv::Op::OpImageSparseSampleProjImplicitLod].push_back(
+      UpdateImageOperands());
+  rules_[spv::Op::OpImageSparseSampleProjExplicitLod].push_back(
+      UpdateImageOperands());
+  rules_[spv::Op::OpImageSparseSampleProjDrefImplicitLod].push_back(
+      UpdateImageOperands());
+  rules_[spv::Op::OpImageSparseSampleProjDrefExplicitLod].push_back(
+      UpdateImageOperands());
+  rules_[spv::Op::OpImageSparseFetch].push_back(UpdateImageOperands());
+  rules_[spv::Op::OpImageSparseGather].push_back(UpdateImageOperands());
+  rules_[spv::Op::OpImageSparseDrefGather].push_back(UpdateImageOperands());
+  rules_[spv::Op::OpImageSparseRead].push_back(UpdateImageOperands());
 
   FeatureManager* feature_manager = context_->get_feature_mgr();
   // Add rules for GLSLstd450
diff --git a/source/opt/folding_rules.h b/source/opt/folding_rules.h
index f1a8639..b51e0ce 100644
--- a/source/opt/folding_rules.h
+++ b/source/opt/folding_rules.h
@@ -64,7 +64,7 @@
   virtual ~FoldingRules() = default;
 
   const FoldingRuleSet& GetRulesForInstruction(Instruction* inst) const {
-    if (inst->opcode() != SpvOpExtInst) {
+    if (inst->opcode() != spv::Op::OpExtInst) {
       auto it = rules_.find(inst->opcode());
       if (it != rules_.end()) {
         return it->second;
@@ -86,8 +86,14 @@
   virtual void AddFoldingRules();
 
  protected:
+  struct hasher {
+    size_t operator()(const spv::Op& op) const noexcept {
+      return std::hash<uint32_t>()(uint32_t(op));
+    }
+  };
+
   // The folding rules for core instructions.
-  std::unordered_map<uint32_t, FoldingRuleSet> rules_;
+  std::unordered_map<spv::Op, FoldingRuleSet, hasher> rules_;
 
   // The folding rules for extended instructions.
   struct Key {
diff --git a/source/opt/freeze_spec_constant_value_pass.cpp b/source/opt/freeze_spec_constant_value_pass.cpp
index 10e98fd..3f89e56 100644
--- a/source/opt/freeze_spec_constant_value_pass.cpp
+++ b/source/opt/freeze_spec_constant_value_pass.cpp
@@ -23,21 +23,21 @@
   auto ctx = context();
   ctx->module()->ForEachInst([&modified, ctx](Instruction* inst) {
     switch (inst->opcode()) {
-      case SpvOp::SpvOpSpecConstant:
-        inst->SetOpcode(SpvOp::SpvOpConstant);
+      case spv::Op::OpSpecConstant:
+        inst->SetOpcode(spv::Op::OpConstant);
         modified = true;
         break;
-      case SpvOp::SpvOpSpecConstantTrue:
-        inst->SetOpcode(SpvOp::SpvOpConstantTrue);
+      case spv::Op::OpSpecConstantTrue:
+        inst->SetOpcode(spv::Op::OpConstantTrue);
         modified = true;
         break;
-      case SpvOp::SpvOpSpecConstantFalse:
-        inst->SetOpcode(SpvOp::SpvOpConstantFalse);
+      case spv::Op::OpSpecConstantFalse:
+        inst->SetOpcode(spv::Op::OpConstantFalse);
         modified = true;
         break;
-      case SpvOp::SpvOpDecorate:
-        if (inst->GetSingleWordInOperand(1) ==
-            SpvDecoration::SpvDecorationSpecId) {
+      case spv::Op::OpDecorate:
+        if (spv::Decoration(inst->GetSingleWordInOperand(1)) ==
+            spv::Decoration::SpecId) {
           ctx->KillInst(inst);
           modified = true;
         }
diff --git a/source/opt/function.cpp b/source/opt/function.cpp
index bb51df3..6c7c949 100644
--- a/source/opt/function.cpp
+++ b/source/opt/function.cpp
@@ -264,7 +264,7 @@
   std::ostringstream str;
   ForEachInst([&str, options](const Instruction* inst) {
     str << inst->PrettyPrint(options);
-    if (inst->opcode() != SpvOpFunctionEnd) {
+    if (inst->opcode() != spv::Op::OpFunctionEnd) {
       str << std::endl;
     }
   });
diff --git a/source/opt/function.h b/source/opt/function.h
index 146cbe3..8c0472c 100644
--- a/source/opt/function.h
+++ b/source/opt/function.h
@@ -253,7 +253,7 @@
   auto first_empty =
       std::remove_if(std::begin(blocks_), std::end(blocks_),
                      [](const std::unique_ptr<BasicBlock>& bb) -> bool {
-                       return bb->GetLabelInst()->opcode() == SpvOpNop;
+                       return bb->GetLabelInst()->opcode() == spv::Op::OpNop;
                      });
   blocks_.erase(first_empty, std::end(blocks_));
 }
diff --git a/source/opt/graphics_robust_access_pass.cpp b/source/opt/graphics_robust_access_pass.cpp
index 4652d72..da2764f 100644
--- a/source/opt/graphics_robust_access_pass.cpp
+++ b/source/opt/graphics_robust_access_pass.cpp
@@ -158,7 +158,6 @@
 #include "source/util/make_unique.h"
 #include "spirv-tools/libspirv.h"
 #include "spirv/unified1/GLSL.std.450.h"
-#include "spirv/unified1/spirv.h"
 #include "type_manager.h"
 #include "types.h"
 
@@ -194,14 +193,15 @@
 
 spv_result_t GraphicsRobustAccessPass::IsCompatibleModule() {
   auto* feature_mgr = context()->get_feature_mgr();
-  if (!feature_mgr->HasCapability(SpvCapabilityShader))
+  if (!feature_mgr->HasCapability(spv::Capability::Shader))
     return Fail() << "Can only process Shader modules";
-  if (feature_mgr->HasCapability(SpvCapabilityVariablePointers))
+  if (feature_mgr->HasCapability(spv::Capability::VariablePointers))
     return Fail() << "Can't process modules with VariablePointers capability";
-  if (feature_mgr->HasCapability(SpvCapabilityVariablePointersStorageBuffer))
+  if (feature_mgr->HasCapability(
+          spv::Capability::VariablePointersStorageBuffer))
     return Fail() << "Can't process modules with VariablePointersStorageBuffer "
                      "capability";
-  if (feature_mgr->HasCapability(SpvCapabilityRuntimeDescriptorArrayEXT)) {
+  if (feature_mgr->HasCapability(spv::Capability::RuntimeDescriptorArrayEXT)) {
     // These have a RuntimeArray outside of Block-decorated struct.  There
     // is no way to compute the array length from within SPIR-V.
     return Fail() << "Can't process modules with RuntimeDescriptorArrayEXT "
@@ -210,8 +210,9 @@
 
   {
     auto* inst = context()->module()->GetMemoryModel();
-    const auto addressing_model = inst->GetSingleWordOperand(0);
-    if (addressing_model != SpvAddressingModelLogical)
+    const auto addressing_model =
+        spv::AddressingModel(inst->GetSingleWordOperand(0));
+    if (addressing_model != spv::AddressingModel::Logical)
       return Fail() << "Addressing model must be Logical.  Found "
                     << inst->PrettyPrint();
   }
@@ -237,11 +238,11 @@
   for (auto& block : *function) {
     for (auto& inst : block) {
       switch (inst.opcode()) {
-        case SpvOpAccessChain:
-        case SpvOpInBoundsAccessChain:
+        case spv::Op::OpAccessChain:
+        case spv::Op::OpInBoundsAccessChain:
           access_chains.push_back(&inst);
           break;
-        case SpvOpImageTexelPointer:
+        case spv::Op::OpImageTexelPointer:
           image_texel_pointers.push_back(&inst);
           break;
         default:
@@ -268,7 +269,7 @@
   auto* def_use_mgr = context()->get_def_use_mgr();
   auto* type_mgr = context()->get_type_mgr();
   const bool have_int64_cap =
-      context()->get_feature_mgr()->HasCapability(SpvCapabilityInt64);
+      context()->get_feature_mgr()->HasCapability(spv::Capability::Int64);
 
   // Replaces one of the OpAccessChain index operands with a new value.
   // Updates def-use analysis.
@@ -451,7 +452,7 @@
       // It doesn't matter if 1 is signed or unsigned.
       auto* one = GetValueForType(1, wider_type);
       auto* count_minus_1 = InsertInst(
-          &inst, SpvOpISub, type_mgr->GetId(wider_type), TakeNextId(),
+          &inst, spv::Op::OpISub, type_mgr->GetId(wider_type), TakeNextId(),
           {{SPV_OPERAND_TYPE_ID, {count_inst->result_id()}},
            {SPV_OPERAND_TYPE_ID, {one->result_id()}}});
       auto* zero = GetValueForType(0, wider_type);
@@ -486,15 +487,15 @@
     Instruction* index_inst = GetDef(index_id);
 
     switch (pointee_type->opcode()) {
-      case SpvOpTypeMatrix:  // Use column count
-      case SpvOpTypeVector:  // Use component count
+      case spv::Op::OpTypeMatrix:  // Use column count
+      case spv::Op::OpTypeVector:  // Use component count
       {
         const uint32_t count = pointee_type->GetSingleWordOperand(2);
         clamp_to_literal_count(idx, count);
         pointee_type = GetDef(pointee_type->GetSingleWordOperand(1));
       } break;
 
-      case SpvOpTypeArray: {
+      case spv::Op::OpTypeArray: {
         // The array length can be a spec constant, so go through the general
         // case.
         Instruction* array_len = GetDef(pointee_type->GetSingleWordOperand(2));
@@ -502,11 +503,11 @@
         pointee_type = GetDef(pointee_type->GetSingleWordOperand(1));
       } break;
 
-      case SpvOpTypeStruct: {
+      case spv::Op::OpTypeStruct: {
         // SPIR-V requires the index to be an OpConstant.
         // We need to know the index literal value so we can compute the next
         // pointee type.
-        if (index_inst->opcode() != SpvOpConstant ||
+        if (index_inst->opcode() != spv::Op::OpConstant ||
             !constant_mgr->GetConstantFromInst(index_inst)
                  ->type()
                  ->AsInteger()) {
@@ -537,7 +538,7 @@
         // No need to clamp this index.  We just checked that it's valid.
       } break;
 
-      case SpvOpTypeRuntimeArray: {
+      case spv::Op::OpTypeRuntimeArray: {
         auto* array_len = MakeRuntimeArrayLengthInst(&inst, idx);
         if (!array_len) {  // We've already signaled an error.
           return;
@@ -571,7 +572,7 @@
       module_status_.glsl_insts_id = TakeNextId();
       std::vector<uint32_t> words = spvtools::utils::MakeVector(glsl);
       auto import_inst = MakeUnique<Instruction>(
-          context(), SpvOpExtInstImport, 0, module_status_.glsl_insts_id,
+          context(), spv::Op::OpExtInstImport, 0, module_status_.glsl_insts_id,
           std::initializer_list<Operand>{
               Operand{SPV_OPERAND_TYPE_LITERAL_STRING, std::move(words)}});
       Instruction* inst = import_inst.get();
@@ -609,8 +610,8 @@
   auto type_id = context()->get_type_mgr()->GetId(unsigned_type);
   auto conversion_id = TakeNextId();
   auto* conversion = InsertInst(
-      before_inst, (sign_extend ? SpvOpSConvert : SpvOpUConvert), type_id,
-      conversion_id, {{SPV_OPERAND_TYPE_ID, {value->result_id()}}});
+      before_inst, (sign_extend ? spv::Op::OpSConvert : spv::Op::OpUConvert),
+      type_id, conversion_id, {{SPV_OPERAND_TYPE_ID, {value->result_id()}}});
   return conversion;
 }
 
@@ -628,7 +629,7 @@
   (void)xwidth;
   (void)ywidth;
   auto* smin_inst = InsertInst(
-      where, SpvOpExtInst, x->type_id(), smin_id,
+      where, spv::Op::OpExtInst, x->type_id(), smin_id,
       {
           {SPV_OPERAND_TYPE_ID, {glsl_insts_id}},
           {SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER, {GLSLstd450UMin}},
@@ -655,7 +656,7 @@
   (void)minwidth;
   (void)maxwidth;
   auto* clamp_inst = InsertInst(
-      where, SpvOpExtInst, x->type_id(), clamp_id,
+      where, spv::Op::OpExtInst, x->type_id(), clamp_id,
       {
           {SPV_OPERAND_TYPE_ID, {glsl_insts_id}},
           {SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER, {GLSLstd450SClamp}},
@@ -689,13 +690,13 @@
   Instruction* pointer_to_containing_struct = nullptr;
   while (steps_remaining > 0) {
     switch (current_access_chain->opcode()) {
-      case SpvOpCopyObject:
+      case spv::Op::OpCopyObject:
         // Whoops. Walk right through this one.
         current_access_chain =
             GetDef(current_access_chain->GetSingleWordInOperand(0));
         break;
-      case SpvOpAccessChain:
-      case SpvOpInBoundsAccessChain: {
+      case spv::Op::OpAccessChain:
+      case spv::Op::OpInBoundsAccessChain: {
         const int first_index_operand = 3;
         // How many indices in this access chain contribute to getting us
         // to an element in the runtime array?
@@ -793,7 +794,8 @@
   analysis::Integer uint_type_for_query(32, false);
   auto* uint_type = type_mgr->GetRegisteredType(&uint_type_for_query);
   auto* array_len = InsertInst(
-      access_chain, SpvOpArrayLength, type_mgr->GetId(uint_type), array_len_id,
+      access_chain, spv::Op::OpArrayLength, type_mgr->GetId(uint_type),
+      array_len_id,
       {{SPV_OPERAND_TYPE_ID, {pointer_to_containing_struct->result_id()}},
        {SPV_OPERAND_TYPE_LITERAL_INTEGER, {member_index_of_runtime_array}}});
   return array_len;
@@ -839,11 +841,11 @@
 
   // Declare the ImageQuery capability if the module doesn't already have it.
   auto* feature_mgr = context()->get_feature_mgr();
-  if (!feature_mgr->HasCapability(SpvCapabilityImageQuery)) {
+  if (!feature_mgr->HasCapability(spv::Capability::ImageQuery)) {
     auto cap = MakeUnique<Instruction>(
-        context(), SpvOpCapability, 0, 0,
+        context(), spv::Op::OpCapability, 0, 0,
         std::initializer_list<Operand>{
-            {SPV_OPERAND_TYPE_CAPABILITY, {SpvCapabilityImageQuery}}});
+            {SPV_OPERAND_TYPE_CAPABILITY, {spv::Capability::ImageQuery}}});
     def_use_mgr->AnalyzeInstDefUse(cap.get());
     context()->AddCapability(std::move(cap));
     feature_mgr->Analyze(context()->module());
@@ -890,21 +892,21 @@
     const int arrayness_bonus = arrayed ? 1 : 0;
     int num_coords = 0;
     switch (dim) {
-      case SpvDimBuffer:
+      case spv::Dim::Buffer:
       case SpvDim1D:
         num_coords = 1;
         break;
-      case SpvDimCube:
+      case spv::Dim::Cube:
         // For cube, we need bounds for x, y, but not face.
-      case SpvDimRect:
+      case spv::Dim::Rect:
       case SpvDim2D:
         num_coords = 2;
         break;
       case SpvDim3D:
         num_coords = 3;
         break;
-      case SpvDimSubpassData:
-      case SpvDimMax:
+      case spv::Dim::SubpassData:
+      case spv::Dim::Max:
         return Fail() << "Invalid image dimension for OpImageTexelPointer: "
                       << int(dim);
         break;
@@ -941,12 +943,12 @@
 
   const uint32_t image_id = TakeNextId();
   auto* image =
-      InsertInst(image_texel_pointer, SpvOpLoad, image_type_id, image_id,
+      InsertInst(image_texel_pointer, spv::Op::OpLoad, image_type_id, image_id,
                  {{SPV_OPERAND_TYPE_ID, {image_ptr->result_id()}}});
 
   const uint32_t query_size_id = TakeNextId();
   auto* query_size =
-      InsertInst(image_texel_pointer, SpvOpImageQuerySize,
+      InsertInst(image_texel_pointer, spv::Op::OpImageQuerySize,
                  type_mgr->GetTypeInstruction(query_size_type), query_size_id,
                  {{SPV_OPERAND_TYPE_ID, {image->result_id()}}});
 
@@ -962,7 +964,7 @@
   // in the face index ranging from 0 through 5. The inclusive upper bound
   // on the third coordinate therefore is multiplied by 6.
   auto* query_size_including_faces = query_size;
-  if (arrayed && (dim == SpvDimCube)) {
+  if (arrayed && (dim == spv::Dim::Cube)) {
     // Multiply the last coordinate by 6.
     auto* component_6 = constant_mgr->GetConstant(coord_component_type, {6});
     const uint32_t component_6_id =
@@ -974,7 +976,7 @@
         constant_mgr->GetDefiningInstruction(multiplicand);
     const auto query_size_including_faces_id = TakeNextId();
     query_size_including_faces = InsertInst(
-        image_texel_pointer, SpvOpIMul,
+        image_texel_pointer, spv::Op::OpIMul,
         type_mgr->GetTypeInstruction(query_size_type),
         query_size_including_faces_id,
         {{SPV_OPERAND_TYPE_ID, {query_size_including_faces->result_id()}},
@@ -998,7 +1000,7 @@
 
   const uint32_t query_max_including_faces_id = TakeNextId();
   auto* query_max_including_faces = InsertInst(
-      image_texel_pointer, SpvOpISub,
+      image_texel_pointer, spv::Op::OpISub,
       type_mgr->GetTypeInstruction(query_size_type),
       query_max_including_faces_id,
       {{SPV_OPERAND_TYPE_ID, {query_size_including_faces->result_id()}},
@@ -1016,12 +1018,12 @@
     // Get the sample count via OpImageQuerySamples
     const auto query_samples_id = TakeNextId();
     auto* query_samples = InsertInst(
-        image_texel_pointer, SpvOpImageQuerySamples,
+        image_texel_pointer, spv::Op::OpImageQuerySamples,
         constant_mgr->GetDefiningInstruction(component_0)->type_id(),
         query_samples_id, {{SPV_OPERAND_TYPE_ID, {image->result_id()}}});
 
     const auto max_samples_id = TakeNextId();
-    auto* max_samples = InsertInst(image_texel_pointer, SpvOpImageQuerySamples,
+    auto* max_samples = InsertInst(image_texel_pointer, spv::Op::OpImageQuerySamples,
                                    query_samples->type_id(), max_samples_id,
                                    {{SPV_OPERAND_TYPE_ID, {query_samples_id}},
                                     {SPV_OPERAND_TYPE_ID, {component_1_id}}});
@@ -1043,7 +1045,7 @@
 }
 
 opt::Instruction* GraphicsRobustAccessPass::InsertInst(
-    opt::Instruction* where_inst, SpvOp opcode, uint32_t type_id,
+    opt::Instruction* where_inst, spv::Op opcode, uint32_t type_id,
     uint32_t result_id, const Instruction::OperandList& operands) {
   module_status_.modified = true;
   auto* result = where_inst->InsertBefore(
diff --git a/source/opt/graphics_robust_access_pass.h b/source/opt/graphics_robust_access_pass.h
index 8f4c9dc..a7ffe11 100644
--- a/source/opt/graphics_robust_access_pass.h
+++ b/source/opt/graphics_robust_access_pass.h
@@ -133,7 +133,7 @@
   // Returns a new instruction inserted before |where_inst|, and created from
   // the remaining arguments. Registers the definitions and uses of the new
   // instruction and also records its block.
-  opt::Instruction* InsertInst(opt::Instruction* where_inst, SpvOp opcode,
+  opt::Instruction* InsertInst(opt::Instruction* where_inst, spv::Op opcode,
                                uint32_t type_id, uint32_t result_id,
                                const Instruction::OperandList& operands);
 
diff --git a/source/opt/if_conversion.cpp b/source/opt/if_conversion.cpp
index 1232796..5912cf1 100644
--- a/source/opt/if_conversion.cpp
+++ b/source/opt/if_conversion.cpp
@@ -23,7 +23,7 @@
 namespace opt {
 
 Pass::Status IfConversion::Process() {
-  if (!context()->get_feature_mgr()->HasCapability(SpvCapabilityShader)) {
+  if (!context()->get_feature_mgr()->HasCapability(spv::Capability::Shader)) {
     return Status::SuccessWithoutChange;
   }
 
@@ -40,7 +40,7 @@
 
       // Get an insertion point.
       auto iter = block.begin();
-      while (iter != block.end() && iter->opcode() == SpvOpPhi) {
+      while (iter != block.end() && iter->opcode() == spv::Op::OpPhi) {
         ++iter;
       }
 
@@ -171,23 +171,26 @@
   *common = dominators->CommonDominator(inc0, inc1);
   if (!*common || cfg()->IsPseudoEntryBlock(*common)) return false;
   Instruction* branch = (*common)->terminator();
-  if (branch->opcode() != SpvOpBranchConditional) return false;
+  if (branch->opcode() != spv::Op::OpBranchConditional) return false;
   auto merge = (*common)->GetMergeInst();
-  if (!merge || merge->opcode() != SpvOpSelectionMerge) return false;
-  if (merge->GetSingleWordInOperand(1) == SpvSelectionControlDontFlattenMask)
+  if (!merge || merge->opcode() != spv::Op::OpSelectionMerge) return false;
+  if (spv::SelectionControlMask(merge->GetSingleWordInOperand(1)) ==
+      spv::SelectionControlMask::DontFlatten) {
     return false;
+  }
   if ((*common)->MergeBlockIdIfAny() != block->id()) return false;
 
   return true;
 }
 
 bool IfConversion::CheckPhiUsers(Instruction* phi, BasicBlock* block) {
-  return get_def_use_mgr()->WhileEachUser(phi, [block,
-                                                this](Instruction* user) {
-    if (user->opcode() == SpvOpPhi && context()->get_instr_block(user) == block)
-      return false;
-    return true;
-  });
+  return get_def_use_mgr()->WhileEachUser(
+      phi, [block, this](Instruction* user) {
+        if (user->opcode() == spv::Op::OpPhi &&
+            context()->get_instr_block(user) == block)
+          return false;
+        return true;
+      });
 }
 
 uint32_t IfConversion::SplatCondition(analysis::Vector* vec_data_ty,
@@ -207,9 +210,9 @@
 
 bool IfConversion::CheckType(uint32_t id) {
   Instruction* type = get_def_use_mgr()->GetDef(id);
-  SpvOp op = type->opcode();
-  if (spvOpcodeIsScalarType(op) || op == SpvOpTypePointer ||
-      op == SpvOpTypeVector)
+  spv::Op op = type->opcode();
+  if (spvOpcodeIsScalarType(op) || op == spv::Op::OpTypePointer ||
+      op == spv::Op::OpTypeVector)
     return true;
   return false;
 }
@@ -255,7 +258,7 @@
       });
 
   Instruction* insertion_pos = target_block->terminator();
-  if ((insertion_pos)->PreviousNode()->opcode() == SpvOpSelectionMerge) {
+  if ((insertion_pos)->PreviousNode()->opcode() == spv::Op::OpSelectionMerge) {
     insertion_pos = insertion_pos->PreviousNode();
   }
   inst->RemoveFromList();
diff --git a/source/opt/inline_opaque_pass.cpp b/source/opt/inline_opaque_pass.cpp
index fe9c679..c88513f 100644
--- a/source/opt/inline_opaque_pass.cpp
+++ b/source/opt/inline_opaque_pass.cpp
@@ -29,18 +29,18 @@
 bool InlineOpaquePass::IsOpaqueType(uint32_t typeId) {
   const Instruction* typeInst = get_def_use_mgr()->GetDef(typeId);
   switch (typeInst->opcode()) {
-    case SpvOpTypeSampler:
-    case SpvOpTypeImage:
-    case SpvOpTypeSampledImage:
+    case spv::Op::OpTypeSampler:
+    case spv::Op::OpTypeImage:
+    case spv::Op::OpTypeSampledImage:
       return true;
-    case SpvOpTypePointer:
+    case spv::Op::OpTypePointer:
       return IsOpaqueType(
           typeInst->GetSingleWordInOperand(kTypePointerTypeIdInIdx));
     default:
       break;
   }
   // TODO(greg-lunarg): Handle arrays containing opaque type
-  if (typeInst->opcode() != SpvOpTypeStruct) return false;
+  if (typeInst->opcode() != spv::Op::OpTypeStruct) return false;
   // Return true if any member is opaque
   return !typeInst->WhileEachInId([this](const uint32_t* tid) {
     if (IsOpaqueType(*tid)) return false;
diff --git a/source/opt/inline_pass.cpp b/source/opt/inline_pass.cpp
index e14516f..f8e67df 100644
--- a/source/opt/inline_pass.cpp
+++ b/source/opt/inline_pass.cpp
@@ -33,14 +33,14 @@
 namespace opt {
 
 uint32_t InlinePass::AddPointerToType(uint32_t type_id,
-                                      SpvStorageClass storage_class) {
+                                      spv::StorageClass storage_class) {
   uint32_t resultId = context()->TakeNextId();
   if (resultId == 0) {
     return resultId;
   }
 
   std::unique_ptr<Instruction> type_inst(
-      new Instruction(context(), SpvOpTypePointer, 0, resultId,
+      new Instruction(context(), spv::Op::OpTypePointer, 0, resultId,
                       {{spv_operand_type_t::SPV_OPERAND_TYPE_STORAGE_CLASS,
                         {uint32_t(storage_class)}},
                        {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {type_id}}}));
@@ -48,8 +48,8 @@
   analysis::Type* pointeeTy;
   std::unique_ptr<analysis::Pointer> pointerTy;
   std::tie(pointeeTy, pointerTy) =
-      context()->get_type_mgr()->GetTypeAndPointerType(type_id,
-                                                       SpvStorageClassFunction);
+      context()->get_type_mgr()->GetTypeAndPointerType(
+          type_id, spv::StorageClass::Function);
   context()->get_type_mgr()->RegisterType(resultId, *pointerTy);
   return resultId;
 }
@@ -57,7 +57,7 @@
 void InlinePass::AddBranch(uint32_t label_id,
                            std::unique_ptr<BasicBlock>* block_ptr) {
   std::unique_ptr<Instruction> newBranch(
-      new Instruction(context(), SpvOpBranch, 0, 0,
+      new Instruction(context(), spv::Op::OpBranch, 0, 0,
                       {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {label_id}}}));
   (*block_ptr)->AddInstruction(std::move(newBranch));
 }
@@ -66,7 +66,7 @@
                                uint32_t false_id,
                                std::unique_ptr<BasicBlock>* block_ptr) {
   std::unique_ptr<Instruction> newBranch(
-      new Instruction(context(), SpvOpBranchConditional, 0, 0,
+      new Instruction(context(), spv::Op::OpBranchConditional, 0, 0,
                       {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {cond_id}},
                        {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {true_id}},
                        {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {false_id}}}));
@@ -76,7 +76,7 @@
 void InlinePass::AddLoopMerge(uint32_t merge_id, uint32_t continue_id,
                               std::unique_ptr<BasicBlock>* block_ptr) {
   std::unique_ptr<Instruction> newLoopMerge(new Instruction(
-      context(), SpvOpLoopMerge, 0, 0,
+      context(), spv::Op::OpLoopMerge, 0, 0,
       {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {merge_id}},
        {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {continue_id}},
        {spv_operand_type_t::SPV_OPERAND_TYPE_LOOP_CONTROL, {0}}}));
@@ -88,7 +88,7 @@
                           const Instruction* line_inst,
                           const DebugScope& dbg_scope) {
   std::unique_ptr<Instruction> newStore(
-      new Instruction(context(), SpvOpStore, 0, 0,
+      new Instruction(context(), spv::Op::OpStore, 0, 0,
                       {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {ptr_id}},
                        {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {val_id}}}));
   if (line_inst != nullptr) {
@@ -103,7 +103,7 @@
                          const Instruction* line_inst,
                          const DebugScope& dbg_scope) {
   std::unique_ptr<Instruction> newLoad(
-      new Instruction(context(), SpvOpLoad, type_id, resultId,
+      new Instruction(context(), spv::Op::OpLoad, type_id, resultId,
                       {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {ptr_id}}}));
   if (line_inst != nullptr) {
     newLoad->AddDebugLine(line_inst);
@@ -114,27 +114,27 @@
 
 std::unique_ptr<Instruction> InlinePass::NewLabel(uint32_t label_id) {
   std::unique_ptr<Instruction> newLabel(
-      new Instruction(context(), SpvOpLabel, 0, label_id, {}));
+      new Instruction(context(), spv::Op::OpLabel, 0, label_id, {}));
   return newLabel;
 }
 
 uint32_t InlinePass::GetFalseId() {
   if (false_id_ != 0) return false_id_;
-  false_id_ = get_module()->GetGlobalValue(SpvOpConstantFalse);
+  false_id_ = get_module()->GetGlobalValue(spv::Op::OpConstantFalse);
   if (false_id_ != 0) return false_id_;
-  uint32_t boolId = get_module()->GetGlobalValue(SpvOpTypeBool);
+  uint32_t boolId = get_module()->GetGlobalValue(spv::Op::OpTypeBool);
   if (boolId == 0) {
     boolId = context()->TakeNextId();
     if (boolId == 0) {
       return 0;
     }
-    get_module()->AddGlobalValue(SpvOpTypeBool, boolId, 0);
+    get_module()->AddGlobalValue(spv::Op::OpTypeBool, boolId, 0);
   }
   false_id_ = context()->TakeNextId();
   if (false_id_ == 0) {
     return 0;
   }
-  get_module()->AddGlobalValue(SpvOpConstantFalse, false_id_, boolId);
+  get_module()->AddGlobalValue(spv::Op::OpConstantFalse, false_id_, boolId);
   return false_id_;
 }
 
@@ -157,10 +157,10 @@
     analysis::DebugInlinedAtContext* inlined_at_ctx) {
   auto callee_block_itr = calleeFn->begin();
   auto callee_var_itr = callee_block_itr->begin();
-  while (callee_var_itr->opcode() == SpvOp::SpvOpVariable ||
+  while (callee_var_itr->opcode() == spv::Op::OpVariable ||
          callee_var_itr->GetCommonDebugOpcode() ==
              CommonDebugInfoDebugDeclare) {
-    if (callee_var_itr->opcode() != SpvOp::SpvOpVariable) {
+    if (callee_var_itr->opcode() != spv::Op::OpVariable) {
       ++callee_var_itr;
       continue;
     }
@@ -191,10 +191,11 @@
          "Cannot create a return variable of type void.");
   // Find or create ptr to callee return type.
   uint32_t returnVarTypeId =
-      type_mgr->FindPointerToType(calleeTypeId, SpvStorageClassFunction);
+      type_mgr->FindPointerToType(calleeTypeId, spv::StorageClass::Function);
 
   if (returnVarTypeId == 0) {
-    returnVarTypeId = AddPointerToType(calleeTypeId, SpvStorageClassFunction);
+    returnVarTypeId =
+        AddPointerToType(calleeTypeId, spv::StorageClass::Function);
     if (returnVarTypeId == 0) {
       return 0;
     }
@@ -206,17 +207,18 @@
     return 0;
   }
 
-  std::unique_ptr<Instruction> var_inst(
-      new Instruction(context(), SpvOpVariable, returnVarTypeId, returnVarId,
-                      {{spv_operand_type_t::SPV_OPERAND_TYPE_STORAGE_CLASS,
-                        {SpvStorageClassFunction}}}));
+  std::unique_ptr<Instruction> var_inst(new Instruction(
+      context(), spv::Op::OpVariable, returnVarTypeId, returnVarId,
+      {{spv_operand_type_t::SPV_OPERAND_TYPE_STORAGE_CLASS,
+        {(uint32_t)spv::StorageClass::Function}}}));
   new_vars->push_back(std::move(var_inst));
   get_decoration_mgr()->CloneDecorations(calleeFn->result_id(), returnVarId);
   return returnVarId;
 }
 
 bool InlinePass::IsSameBlockOp(const Instruction* inst) const {
-  return inst->opcode() == SpvOpSampledImage || inst->opcode() == SpvOpImage;
+  return inst->opcode() == spv::Op::OpSampledImage ||
+         inst->opcode() == spv::Op::OpImage;
 }
 
 bool InlinePass::CloneSameBlockOps(
@@ -299,9 +301,9 @@
     std::unique_ptr<BasicBlock>* new_blk_ptr,
     UptrVectorIterator<BasicBlock> callee_first_block_itr) {
   auto callee_itr = callee_first_block_itr->begin();
-  while (callee_itr->opcode() == SpvOp::SpvOpVariable ||
+  while (callee_itr->opcode() == spv::Op::OpVariable ||
          callee_itr->GetCommonDebugOpcode() == CommonDebugInfoDebugDeclare) {
-    if (callee_itr->opcode() == SpvOp::SpvOpVariable &&
+    if (callee_itr->opcode() == spv::Op::OpVariable &&
         callee_itr->NumInOperands() == 2) {
       assert(callee2caller.count(callee_itr->result_id()) &&
              "Expected the variable to have already been mapped.");
@@ -330,7 +332,8 @@
     BasicBlock* new_blk_ptr, const Instruction* inst, uint32_t dbg_inlined_at) {
   // If we have return, it must be at the end of the callee. We will handle
   // it at the end.
-  if (inst->opcode() == SpvOpReturnValue || inst->opcode() == SpvOpReturn)
+  if (inst->opcode() == spv::Op::OpReturnValue ||
+      inst->opcode() == spv::Op::OpReturn)
     return true;
 
   // Copy callee instruction and remap all input Ids.
@@ -366,7 +369,7 @@
     analysis::DebugInlinedAtContext* inlined_at_ctx, Function* calleeFn,
     const Instruction* inst, uint32_t returnVarId) {
   // Store return value to return variable.
-  if (inst->opcode() == SpvOpReturnValue) {
+  if (inst->opcode() == spv::Op::OpReturnValue) {
     assert(returnVarId != 0);
     uint32_t valId = inst->GetInOperand(kSpvReturnValueId).words[0];
     const auto mapItr = callee2caller.find(valId);
@@ -388,7 +391,8 @@
   }
   if (returnLabelId == 0) return new_blk_ptr;
 
-  if (inst->opcode() == SpvOpReturn || inst->opcode() == SpvOpReturnValue)
+  if (inst->opcode() == spv::Op::OpReturn ||
+      inst->opcode() == spv::Op::OpReturnValue)
     AddBranch(returnLabelId, &new_blk_ptr);
   new_blocks->push_back(std::move(new_blk_ptr));
   return MakeUnique<BasicBlock>(NewLabel(returnLabelId));
@@ -499,7 +503,7 @@
   // Insert a modified copy of the loop merge into the first block.
   auto loop_merge_itr = last->tail();
   --loop_merge_itr;
-  assert(loop_merge_itr->opcode() == SpvOpLoopMerge);
+  assert(loop_merge_itr->opcode() == spv::Op::OpLoopMerge);
   std::unique_ptr<Instruction> cp_inst(loop_merge_itr->Clone(context()));
   first->tail().InsertBefore(std::move(cp_inst));
 
@@ -696,7 +700,7 @@
 }
 
 bool InlinePass::IsInlinableFunctionCall(const Instruction* inst) {
-  if (inst->opcode() != SpvOp::SpvOpFunctionCall) return false;
+  if (inst->opcode() != spv::Op::OpFunctionCall) return false;
   const uint32_t calleeFnId =
       inst->GetSingleWordOperand(kSpvFunctionCallFunctionId);
   const auto ci = inlinable_.find(calleeFnId);
@@ -738,7 +742,7 @@
 bool InlinePass::HasNoReturnInLoop(Function* func) {
   // If control not structured, do not do loop/return analysis
   // TODO: Analyze returns in non-structured control flow
-  if (!context()->get_feature_mgr()->HasCapability(SpvCapabilityShader))
+  if (!context()->get_feature_mgr()->HasCapability(spv::Capability::Shader))
     return false;
   const auto structured_analysis = context()->GetStructuredCFGAnalysis();
   // Search for returns in structured construct.
@@ -776,7 +780,7 @@
   if (func->cbegin() == func->cend()) return false;
 
   // Do not inline functions with DontInline flag.
-  if (func->control_mask() & SpvFunctionControlDontInlineMask) {
+  if (func->control_mask() & uint32_t(spv::FunctionControlMask::DontInline)) {
     return false;
   }
 
@@ -811,7 +815,7 @@
 
 bool InlinePass::ContainsAbortOtherThanUnreachable(Function* func) const {
   return !func->WhileEachInst([](Instruction* inst) {
-    return inst->opcode() == SpvOpUnreachable ||
+    return inst->opcode() == spv::Op::OpUnreachable ||
            !spvOpcodeIsAbort(inst->opcode());
   });
 }
diff --git a/source/opt/inline_pass.h b/source/opt/inline_pass.h
index d29c1e0..1c9d60e 100644
--- a/source/opt/inline_pass.h
+++ b/source/opt/inline_pass.h
@@ -44,7 +44,7 @@
 
   // Add pointer to type to module and return resultId.  Returns 0 if the type
   // could not be created.
-  uint32_t AddPointerToType(uint32_t type_id, SpvStorageClass storage_class);
+  uint32_t AddPointerToType(uint32_t type_id, spv::StorageClass storage_class);
 
   // Add unconditional branch to labelId to end of block block_ptr.
   void AddBranch(uint32_t labelId, std::unique_ptr<BasicBlock>* block_ptr);
diff --git a/source/opt/inst_bindless_check_pass.cpp b/source/opt/inst_bindless_check_pass.cpp
index c2c5d6c..336b929 100644
--- a/source/opt/inst_bindless_check_pass.cpp
+++ b/source/opt/inst_bindless_check_pass.cpp
@@ -79,25 +79,25 @@
     uint32_t old_image_id, InstructionBuilder* builder) {
   Instruction* new_image_inst;
   Instruction* old_image_inst = get_def_use_mgr()->GetDef(old_image_id);
-  if (old_image_inst->opcode() == SpvOpLoad) {
+  if (old_image_inst->opcode() == spv::Op::OpLoad) {
     new_image_inst = builder->AddLoad(
         old_image_inst->type_id(),
         old_image_inst->GetSingleWordInOperand(kSpvLoadPtrIdInIdx));
-  } else if (old_image_inst->opcode() == SpvOp::SpvOpSampledImage) {
+  } else if (old_image_inst->opcode() == spv::Op::OpSampledImage) {
     uint32_t clone_id = CloneOriginalImage(
         old_image_inst->GetSingleWordInOperand(kSpvSampledImageImageIdInIdx),
         builder);
     new_image_inst = builder->AddBinaryOp(
-        old_image_inst->type_id(), SpvOpSampledImage, clone_id,
+        old_image_inst->type_id(), spv::Op::OpSampledImage, clone_id,
         old_image_inst->GetSingleWordInOperand(kSpvSampledImageSamplerIdInIdx));
-  } else if (old_image_inst->opcode() == SpvOp::SpvOpImage) {
+  } else if (old_image_inst->opcode() == spv::Op::OpImage) {
     uint32_t clone_id = CloneOriginalImage(
         old_image_inst->GetSingleWordInOperand(kSpvImageSampledImageIdInIdx),
         builder);
-    new_image_inst =
-        builder->AddUnaryOp(old_image_inst->type_id(), SpvOpImage, clone_id);
+    new_image_inst = builder->AddUnaryOp(old_image_inst->type_id(),
+                                         spv::Op::OpImage, clone_id);
   } else {
-    assert(old_image_inst->opcode() == SpvOp::SpvOpCopyObject &&
+    assert(old_image_inst->opcode() == spv::Op::OpCopyObject &&
            "expecting OpCopyObject");
     uint32_t clone_id = CloneOriginalImage(
         old_image_inst->GetSingleWordInOperand(kSpvCopyObjectOperandIdInIdx),
@@ -143,38 +143,38 @@
 
 uint32_t InstBindlessCheckPass::GetImageId(Instruction* inst) {
   switch (inst->opcode()) {
-    case SpvOp::SpvOpImageSampleImplicitLod:
-    case SpvOp::SpvOpImageSampleExplicitLod:
-    case SpvOp::SpvOpImageSampleDrefImplicitLod:
-    case SpvOp::SpvOpImageSampleDrefExplicitLod:
-    case SpvOp::SpvOpImageSampleProjImplicitLod:
-    case SpvOp::SpvOpImageSampleProjExplicitLod:
-    case SpvOp::SpvOpImageSampleProjDrefImplicitLod:
-    case SpvOp::SpvOpImageSampleProjDrefExplicitLod:
-    case SpvOp::SpvOpImageGather:
-    case SpvOp::SpvOpImageDrefGather:
-    case SpvOp::SpvOpImageQueryLod:
-    case SpvOp::SpvOpImageSparseSampleImplicitLod:
-    case SpvOp::SpvOpImageSparseSampleExplicitLod:
-    case SpvOp::SpvOpImageSparseSampleDrefImplicitLod:
-    case SpvOp::SpvOpImageSparseSampleDrefExplicitLod:
-    case SpvOp::SpvOpImageSparseSampleProjImplicitLod:
-    case SpvOp::SpvOpImageSparseSampleProjExplicitLod:
-    case SpvOp::SpvOpImageSparseSampleProjDrefImplicitLod:
-    case SpvOp::SpvOpImageSparseSampleProjDrefExplicitLod:
-    case SpvOp::SpvOpImageSparseGather:
-    case SpvOp::SpvOpImageSparseDrefGather:
-    case SpvOp::SpvOpImageFetch:
-    case SpvOp::SpvOpImageRead:
-    case SpvOp::SpvOpImageQueryFormat:
-    case SpvOp::SpvOpImageQueryOrder:
-    case SpvOp::SpvOpImageQuerySizeLod:
-    case SpvOp::SpvOpImageQuerySize:
-    case SpvOp::SpvOpImageQueryLevels:
-    case SpvOp::SpvOpImageQuerySamples:
-    case SpvOp::SpvOpImageSparseFetch:
-    case SpvOp::SpvOpImageSparseRead:
-    case SpvOp::SpvOpImageWrite:
+    case spv::Op::OpImageSampleImplicitLod:
+    case spv::Op::OpImageSampleExplicitLod:
+    case spv::Op::OpImageSampleDrefImplicitLod:
+    case spv::Op::OpImageSampleDrefExplicitLod:
+    case spv::Op::OpImageSampleProjImplicitLod:
+    case spv::Op::OpImageSampleProjExplicitLod:
+    case spv::Op::OpImageSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSampleProjDrefExplicitLod:
+    case spv::Op::OpImageGather:
+    case spv::Op::OpImageDrefGather:
+    case spv::Op::OpImageQueryLod:
+    case spv::Op::OpImageSparseSampleImplicitLod:
+    case spv::Op::OpImageSparseSampleExplicitLod:
+    case spv::Op::OpImageSparseSampleDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleDrefExplicitLod:
+    case spv::Op::OpImageSparseSampleProjImplicitLod:
+    case spv::Op::OpImageSparseSampleProjExplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefExplicitLod:
+    case spv::Op::OpImageSparseGather:
+    case spv::Op::OpImageSparseDrefGather:
+    case spv::Op::OpImageFetch:
+    case spv::Op::OpImageRead:
+    case spv::Op::OpImageQueryFormat:
+    case spv::Op::OpImageQueryOrder:
+    case spv::Op::OpImageQuerySizeLod:
+    case spv::Op::OpImageQuerySize:
+    case spv::Op::OpImageQueryLevels:
+    case spv::Op::OpImageQuerySamples:
+    case spv::Op::OpImageSparseFetch:
+    case spv::Op::OpImageSparseRead:
+    case spv::Op::OpImageWrite:
       return inst->GetSingleWordInOperand(kSpvImageSampleImageIdInIdx);
     default:
       break;
@@ -190,56 +190,58 @@
 bool InstBindlessCheckPass::AnalyzeDescriptorReference(Instruction* ref_inst,
                                                        RefAnalysis* ref) {
   ref->ref_inst = ref_inst;
-  if (ref_inst->opcode() == SpvOpLoad || ref_inst->opcode() == SpvOpStore) {
+  if (ref_inst->opcode() == spv::Op::OpLoad ||
+      ref_inst->opcode() == spv::Op::OpStore) {
     ref->desc_load_id = 0;
     ref->ptr_id = ref_inst->GetSingleWordInOperand(kSpvLoadPtrIdInIdx);
     Instruction* ptr_inst = get_def_use_mgr()->GetDef(ref->ptr_id);
-    if (ptr_inst->opcode() != SpvOp::SpvOpAccessChain) return false;
+    if (ptr_inst->opcode() != spv::Op::OpAccessChain) return false;
     ref->var_id = ptr_inst->GetSingleWordInOperand(kSpvAccessChainBaseIdInIdx);
     Instruction* var_inst = get_def_use_mgr()->GetDef(ref->var_id);
-    if (var_inst->opcode() != SpvOp::SpvOpVariable) return false;
-    uint32_t storage_class =
-        var_inst->GetSingleWordInOperand(kSpvVariableStorageClassInIdx);
+    if (var_inst->opcode() != spv::Op::OpVariable) return false;
+    spv::StorageClass storage_class = spv::StorageClass(
+        var_inst->GetSingleWordInOperand(kSpvVariableStorageClassInIdx));
     switch (storage_class) {
-      case SpvStorageClassUniform:
-      case SpvStorageClassStorageBuffer:
+      case spv::StorageClass::Uniform:
+      case spv::StorageClass::StorageBuffer:
         break;
       default:
         return false;
         break;
     }
     // Check for deprecated storage block form
-    if (storage_class == SpvStorageClassUniform) {
+    if (storage_class == spv::StorageClass::Uniform) {
       uint32_t var_ty_id = var_inst->type_id();
       Instruction* var_ty_inst = get_def_use_mgr()->GetDef(var_ty_id);
       uint32_t ptr_ty_id =
           var_ty_inst->GetSingleWordInOperand(kSpvTypePtrTypeIdInIdx);
       Instruction* ptr_ty_inst = get_def_use_mgr()->GetDef(ptr_ty_id);
-      SpvOp ptr_ty_op = ptr_ty_inst->opcode();
+      spv::Op ptr_ty_op = ptr_ty_inst->opcode();
       uint32_t block_ty_id =
-          (ptr_ty_op == SpvOpTypeArray || ptr_ty_op == SpvOpTypeRuntimeArray)
+          (ptr_ty_op == spv::Op::OpTypeArray ||
+           ptr_ty_op == spv::Op::OpTypeRuntimeArray)
               ? ptr_ty_inst->GetSingleWordInOperand(kSpvTypeArrayTypeIdInIdx)
               : ptr_ty_id;
       assert(get_def_use_mgr()->GetDef(block_ty_id)->opcode() ==
-                 SpvOpTypeStruct &&
+                 spv::Op::OpTypeStruct &&
              "unexpected block type");
       bool block_found = get_decoration_mgr()->FindDecoration(
-          block_ty_id, SpvDecorationBlock,
+          block_ty_id, uint32_t(spv::Decoration::Block),
           [](const Instruction&) { return true; });
       if (!block_found) {
         // If block decoration not found, verify deprecated form of SSBO
         bool buffer_block_found = get_decoration_mgr()->FindDecoration(
-            block_ty_id, SpvDecorationBufferBlock,
+            block_ty_id, uint32_t(spv::Decoration::BufferBlock),
             [](const Instruction&) { return true; });
         USE_ASSERT(buffer_block_found && "block decoration not found");
-        storage_class = SpvStorageClassStorageBuffer;
+        storage_class = spv::StorageClass::StorageBuffer;
       }
     }
-    ref->strg_class = storage_class;
+    ref->strg_class = uint32_t(storage_class);
     Instruction* desc_type_inst = GetPointeeTypeInst(var_inst);
     switch (desc_type_inst->opcode()) {
-      case SpvOpTypeArray:
-      case SpvOpTypeRuntimeArray:
+      case spv::Op::OpTypeArray:
+      case spv::Op::OpTypeRuntimeArray:
         // A load through a descriptor array will have at least 3 operands. We
         // do not want to instrument loads of descriptors here which are part of
         // an image-based reference.
@@ -261,29 +263,29 @@
   Instruction* desc_load_inst;
   for (;;) {
     desc_load_inst = get_def_use_mgr()->GetDef(desc_load_id);
-    if (desc_load_inst->opcode() == SpvOp::SpvOpSampledImage)
+    if (desc_load_inst->opcode() == spv::Op::OpSampledImage)
       desc_load_id =
           desc_load_inst->GetSingleWordInOperand(kSpvSampledImageImageIdInIdx);
-    else if (desc_load_inst->opcode() == SpvOp::SpvOpImage)
+    else if (desc_load_inst->opcode() == spv::Op::OpImage)
       desc_load_id =
           desc_load_inst->GetSingleWordInOperand(kSpvImageSampledImageIdInIdx);
-    else if (desc_load_inst->opcode() == SpvOp::SpvOpCopyObject)
+    else if (desc_load_inst->opcode() == spv::Op::OpCopyObject)
       desc_load_id =
           desc_load_inst->GetSingleWordInOperand(kSpvCopyObjectOperandIdInIdx);
     else
       break;
   }
-  if (desc_load_inst->opcode() != SpvOp::SpvOpLoad) {
+  if (desc_load_inst->opcode() != spv::Op::OpLoad) {
     // TODO(greg-lunarg): Handle additional possibilities?
     return false;
   }
   ref->desc_load_id = desc_load_id;
   ref->ptr_id = desc_load_inst->GetSingleWordInOperand(kSpvLoadPtrIdInIdx);
   Instruction* ptr_inst = get_def_use_mgr()->GetDef(ref->ptr_id);
-  if (ptr_inst->opcode() == SpvOp::SpvOpVariable) {
+  if (ptr_inst->opcode() == spv::Op::OpVariable) {
     ref->desc_idx_id = 0;
     ref->var_id = ref->ptr_id;
-  } else if (ptr_inst->opcode() == SpvOp::SpvOpAccessChain) {
+  } else if (ptr_inst->opcode() == spv::Op::OpAccessChain) {
     if (ptr_inst->NumInOperands() != 2) {
       assert(false && "unexpected bindless index number");
       return false;
@@ -292,7 +294,7 @@
         ptr_inst->GetSingleWordInOperand(kSpvAccessChainIndex0IdInIdx);
     ref->var_id = ptr_inst->GetSingleWordInOperand(kSpvAccessChainBaseIdInIdx);
     Instruction* var_inst = get_def_use_mgr()->GetDef(ref->var_id);
-    if (var_inst->opcode() != SpvOpVariable) {
+    if (var_inst->opcode() != spv::Op::OpVariable) {
       assert(false && "unexpected bindless base");
       return false;
     }
@@ -369,13 +371,13 @@
   uint32_t buff_ty_id;
   uint32_t ac_in_idx = 1;
   switch (desc_ty_inst->opcode()) {
-    case SpvOpTypeArray:
-    case SpvOpTypeRuntimeArray:
+    case spv::Op::OpTypeArray:
+    case spv::Op::OpTypeRuntimeArray:
       buff_ty_id = desc_ty_inst->GetSingleWordInOperand(0);
       ++ac_in_idx;
       break;
     default:
-      assert(desc_ty_inst->opcode() == SpvOpTypeStruct &&
+      assert(desc_ty_inst->opcode() == spv::Op::OpTypeStruct &&
              "unexpected descriptor type");
       buff_ty_id = desc_ty_inst->result_id();
       break;
@@ -393,19 +395,20 @@
     Instruction* curr_ty_inst = get_def_use_mgr()->GetDef(curr_ty_id);
     uint32_t curr_offset_id = 0;
     switch (curr_ty_inst->opcode()) {
-      case SpvOpTypeArray:
-      case SpvOpTypeRuntimeArray: {
+      case spv::Op::OpTypeArray:
+      case spv::Op::OpTypeRuntimeArray: {
         // Get array stride and multiply by current index
-        uint32_t arr_stride = FindStride(curr_ty_id, SpvDecorationArrayStride);
+        uint32_t arr_stride =
+            FindStride(curr_ty_id, uint32_t(spv::Decoration::ArrayStride));
         uint32_t arr_stride_id = builder->GetUintConstantId(arr_stride);
         uint32_t curr_idx_32b_id = Gen32BitCvtCode(curr_idx_id, builder);
         Instruction* curr_offset_inst = builder->AddBinaryOp(
-            GetUintId(), SpvOpIMul, arr_stride_id, curr_idx_32b_id);
+            GetUintId(), spv::Op::OpIMul, arr_stride_id, curr_idx_32b_id);
         curr_offset_id = curr_offset_inst->result_id();
         // Get element type for next step
         curr_ty_id = curr_ty_inst->GetSingleWordInOperand(0);
       } break;
-      case SpvOpTypeMatrix: {
+      case spv::Op::OpTypeMatrix: {
         assert(matrix_stride != 0 && "missing matrix stride");
         matrix_stride_id = builder->GetUintConstantId(matrix_stride);
         uint32_t vec_ty_id = curr_ty_inst->GetSingleWordInOperand(0);
@@ -423,40 +426,40 @@
         }
         uint32_t curr_idx_32b_id = Gen32BitCvtCode(curr_idx_id, builder);
         Instruction* curr_offset_inst = builder->AddBinaryOp(
-            GetUintId(), SpvOpIMul, col_stride_id, curr_idx_32b_id);
+            GetUintId(), spv::Op::OpIMul, col_stride_id, curr_idx_32b_id);
         curr_offset_id = curr_offset_inst->result_id();
         // Get element type for next step
         curr_ty_id = vec_ty_id;
         in_matrix = true;
       } break;
-      case SpvOpTypeVector: {
+      case spv::Op::OpTypeVector: {
         // If inside a row major matrix type, multiply index by matrix stride,
         // else multiply by component size
         uint32_t comp_ty_id = curr_ty_inst->GetSingleWordInOperand(0u);
         uint32_t curr_idx_32b_id = Gen32BitCvtCode(curr_idx_id, builder);
         if (in_matrix && !col_major) {
           Instruction* curr_offset_inst = builder->AddBinaryOp(
-              GetUintId(), SpvOpIMul, matrix_stride_id, curr_idx_32b_id);
+              GetUintId(), spv::Op::OpIMul, matrix_stride_id, curr_idx_32b_id);
           curr_offset_id = curr_offset_inst->result_id();
         } else {
           uint32_t comp_ty_sz = ByteSize(comp_ty_id, 0u, false, false);
           uint32_t comp_ty_sz_id = builder->GetUintConstantId(comp_ty_sz);
           Instruction* curr_offset_inst = builder->AddBinaryOp(
-              GetUintId(), SpvOpIMul, comp_ty_sz_id, curr_idx_32b_id);
+              GetUintId(), spv::Op::OpIMul, comp_ty_sz_id, curr_idx_32b_id);
           curr_offset_id = curr_offset_inst->result_id();
         }
         // Get element type for next step
         curr_ty_id = comp_ty_id;
       } break;
-      case SpvOpTypeStruct: {
+      case spv::Op::OpTypeStruct: {
         // Get buffer byte offset for the referenced member
         Instruction* curr_idx_inst = get_def_use_mgr()->GetDef(curr_idx_id);
-        assert(curr_idx_inst->opcode() == SpvOpConstant &&
+        assert(curr_idx_inst->opcode() == spv::Op::OpConstant &&
                "unexpected struct index");
         uint32_t member_idx = curr_idx_inst->GetSingleWordInOperand(0);
         uint32_t member_offset = 0xdeadbeef;
         bool found = get_decoration_mgr()->FindDecoration(
-            curr_ty_id, SpvDecorationOffset,
+            curr_ty_id, uint32_t(spv::Decoration::Offset),
             [&member_idx, &member_offset](const Instruction& deco_inst) {
               if (deco_inst.GetSingleWordInOperand(1u) != member_idx)
                 return false;
@@ -470,7 +473,7 @@
         // enclosing struct type at the member index. If none found, reset
         // stride to 0.
         found = get_decoration_mgr()->FindDecoration(
-            curr_ty_id, SpvDecorationMatrixStride,
+            curr_ty_id, uint32_t(spv::Decoration::MatrixStride),
             [&member_idx, &matrix_stride](const Instruction& deco_inst) {
               if (deco_inst.GetSingleWordInOperand(1u) != member_idx)
                 return false;
@@ -480,7 +483,7 @@
         if (!found) matrix_stride = 0;
         // Look for column major decoration
         found = get_decoration_mgr()->FindDecoration(
-            curr_ty_id, SpvDecorationColMajor,
+            curr_ty_id, uint32_t(spv::Decoration::ColMajor),
             [&member_idx, &col_major](const Instruction& deco_inst) {
               if (deco_inst.GetSingleWordInOperand(1u) != member_idx)
                 return false;
@@ -496,8 +499,8 @@
     if (sum_id == 0)
       sum_id = curr_offset_id;
     else {
-      Instruction* sum_inst =
-          builder->AddBinaryOp(GetUintId(), SpvOpIAdd, sum_id, curr_offset_id);
+      Instruction* sum_inst = builder->AddBinaryOp(GetUintId(), spv::Op::OpIAdd,
+                                                   sum_id, curr_offset_id);
       sum_id = sum_inst->result_id();
     }
     ++ac_in_idx;
@@ -507,7 +510,7 @@
   uint32_t last = bsize - 1;
   uint32_t last_id = builder->GetUintConstantId(last);
   Instruction* sum_inst =
-      builder->AddBinaryOp(GetUintId(), SpvOpIAdd, sum_id, last_id);
+      builder->AddBinaryOp(GetUintId(), spv::Op::OpIAdd, sum_id, last_id);
   return sum_inst->result_id();
 }
 
@@ -527,8 +530,9 @@
   std::unique_ptr<Instruction> merge_label(NewLabel(merge_blk_id));
   std::unique_ptr<Instruction> valid_label(NewLabel(valid_blk_id));
   std::unique_ptr<Instruction> invalid_label(NewLabel(invalid_blk_id));
-  (void)builder.AddConditionalBranch(check_id, valid_blk_id, invalid_blk_id,
-                                     merge_blk_id, SpvSelectionControlMaskNone);
+  (void)builder.AddConditionalBranch(
+      check_id, valid_blk_id, invalid_blk_id, merge_blk_id,
+      uint32_t(spv::SelectionControlMask::MaskNone));
   // Gen valid bounds branch
   std::unique_ptr<BasicBlock> new_blk_ptr(
       new BasicBlock(std::move(valid_label)));
@@ -593,24 +597,24 @@
   RefAnalysis ref;
   if (!AnalyzeDescriptorReference(&*ref_inst_itr, &ref)) return;
   Instruction* ptr_inst = get_def_use_mgr()->GetDef(ref.ptr_id);
-  if (ptr_inst->opcode() != SpvOp::SpvOpAccessChain) return;
+  if (ptr_inst->opcode() != spv::Op::OpAccessChain) return;
   // If index and bound both compile-time constants and index < bound,
   // return without changing
   Instruction* var_inst = get_def_use_mgr()->GetDef(ref.var_id);
   Instruction* desc_type_inst = GetPointeeTypeInst(var_inst);
   uint32_t length_id = 0;
-  if (desc_type_inst->opcode() == SpvOpTypeArray) {
+  if (desc_type_inst->opcode() == spv::Op::OpTypeArray) {
     length_id =
         desc_type_inst->GetSingleWordInOperand(kSpvTypeArrayLengthIdInIdx);
     Instruction* index_inst = get_def_use_mgr()->GetDef(ref.desc_idx_id);
     Instruction* length_inst = get_def_use_mgr()->GetDef(length_id);
-    if (index_inst->opcode() == SpvOpConstant &&
-        length_inst->opcode() == SpvOpConstant &&
+    if (index_inst->opcode() == spv::Op::OpConstant &&
+        length_inst->opcode() == spv::Op::OpConstant &&
         index_inst->GetSingleWordInOperand(kSpvConstantValueInIdx) <
             length_inst->GetSingleWordInOperand(kSpvConstantValueInIdx))
       return;
   } else if (!desc_idx_enabled_ ||
-             desc_type_inst->opcode() != SpvOpTypeRuntimeArray) {
+             desc_type_inst->opcode() != spv::Op::OpTypeRuntimeArray) {
     return;
   }
   // Move original block's preceding instructions into first new block
@@ -624,7 +628,7 @@
   // If length id not yet set, descriptor array is runtime size so
   // generate load of length from stage's debug input buffer.
   if (length_id == 0) {
-    assert(desc_type_inst->opcode() == SpvOpTypeRuntimeArray &&
+    assert(desc_type_inst->opcode() == spv::Op::OpTypeRuntimeArray &&
            "unexpected bindless type");
     length_id = GenDebugReadLength(ref.var_id, &builder);
   }
@@ -633,7 +637,7 @@
   // for the referenced value.
   uint32_t desc_idx_32b_id = Gen32BitCvtCode(ref.desc_idx_id, &builder);
   uint32_t length_32b_id = Gen32BitCvtCode(length_id, &builder);
-  Instruction* ult_inst = builder.AddBinaryOp(GetBoolId(), SpvOpULessThan,
+  Instruction* ult_inst = builder.AddBinaryOp(GetBoolId(), spv::Op::OpULessThan,
                                               desc_idx_32b_id, length_32b_id);
   ref.desc_idx_id = desc_idx_32b_id;
   GenCheckCode(ult_inst->result_id(), error_id, 0u, length_id, stage_idx, &ref,
@@ -661,9 +665,10 @@
     // TODO(greg-lunarg): Do bounds check for aggregate loads and stores
     Instruction* ref_ptr_inst = get_def_use_mgr()->GetDef(ref.ptr_id);
     Instruction* pte_type_inst = GetPointeeTypeInst(ref_ptr_inst);
-    uint32_t pte_type_op = pte_type_inst->opcode();
-    if (pte_type_op == SpvOpTypeArray || pte_type_op == SpvOpTypeRuntimeArray ||
-        pte_type_op == SpvOpTypeStruct)
+    spv::Op pte_type_op = pte_type_inst->opcode();
+    if (pte_type_op == spv::Op::OpTypeArray ||
+        pte_type_op == spv::Op::OpTypeRuntimeArray ||
+        pte_type_op == spv::Op::OpTypeStruct)
       init_check = true;
   }
   // If initialization check and not enabled, return
@@ -687,11 +692,13 @@
   // being full reference and false branch being debug output and zero
   // for the referenced value.
   Instruction* ult_inst =
-      builder.AddBinaryOp(GetBoolId(), SpvOpULessThan, ref_id, init_id);
-  uint32_t error = init_check ? kInstErrorBindlessUninit
-                              : (ref.strg_class == SpvStorageClassUniform
-                                     ? kInstErrorBuffOOBUniform
-                                     : kInstErrorBuffOOBStorage);
+      builder.AddBinaryOp(GetBoolId(), spv::Op::OpULessThan, ref_id, init_id);
+  uint32_t error =
+      init_check
+          ? kInstErrorBindlessUninit
+          : (spv::StorageClass(ref.strg_class) == spv::StorageClass::Uniform
+                 ? kInstErrorBuffOOBUniform
+                 : kInstErrorBuffOOBStorage);
   uint32_t error_id = builder.GetUintConstantId(error);
   GenCheckCode(ult_inst->result_id(), error_id, init_check ? 0 : ref_id,
                init_check ? builder.GetUintConstantId(0u) : init_id, stage_idx,
@@ -708,11 +715,11 @@
     std::vector<std::unique_ptr<BasicBlock>>* new_blocks) {
   // Only process OpImageRead and OpImageWrite with no optional operands
   Instruction* ref_inst = &*ref_inst_itr;
-  SpvOp op = ref_inst->opcode();
+  spv::Op op = ref_inst->opcode();
   uint32_t num_in_oprnds = ref_inst->NumInOperands();
-  if (!((op == SpvOpImageRead && num_in_oprnds == 2) ||
-        (op == SpvOpImageFetch && num_in_oprnds == 2) ||
-        (op == SpvOpImageWrite && num_in_oprnds == 3)))
+  if (!((op == spv::Op::OpImageRead && num_in_oprnds == 2) ||
+        (op == spv::Op::OpImageFetch && num_in_oprnds == 2) ||
+        (op == spv::Op::OpImageWrite && num_in_oprnds == 3)))
     return;
   // Pull components from descriptor reference
   RefAnalysis ref;
@@ -721,17 +728,20 @@
   Instruction* image_inst = get_def_use_mgr()->GetDef(ref.image_id);
   uint32_t image_ty_id = image_inst->type_id();
   Instruction* image_ty_inst = get_def_use_mgr()->GetDef(image_ty_id);
-  if (image_ty_inst->GetSingleWordInOperand(kSpvTypeImageDim) != SpvDimBuffer)
+  if (spv::Dim(image_ty_inst->GetSingleWordInOperand(kSpvTypeImageDim)) !=
+      spv::Dim::Buffer) {
     return;
+  }
   if (image_ty_inst->GetSingleWordInOperand(kSpvTypeImageDepth) != 0) return;
   if (image_ty_inst->GetSingleWordInOperand(kSpvTypeImageArrayed) != 0) return;
   if (image_ty_inst->GetSingleWordInOperand(kSpvTypeImageMS) != 0) return;
   // Enable ImageQuery Capability if not yet enabled
-  if (!get_feature_mgr()->HasCapability(SpvCapabilityImageQuery)) {
-    std::unique_ptr<Instruction> cap_image_query_inst(new Instruction(
-        context(), SpvOpCapability, 0, 0,
-        std::initializer_list<Operand>{
-            {SPV_OPERAND_TYPE_CAPABILITY, {SpvCapabilityImageQuery}}}));
+  if (!get_feature_mgr()->HasCapability(spv::Capability::ImageQuery)) {
+    std::unique_ptr<Instruction> cap_image_query_inst(
+        new Instruction(context(), spv::Op::OpCapability, 0, 0,
+                        std::initializer_list<Operand>{
+                            {SPV_OPERAND_TYPE_CAPABILITY,
+                             {uint32_t(spv::Capability::ImageQuery)}}}));
     get_def_use_mgr()->AnalyzeInstDefUse(&*cap_image_query_inst);
     context()->AddCapability(std::move(cap_image_query_inst));
   }
@@ -750,13 +760,13 @@
   if (ref.desc_idx_id == 0) ref.desc_idx_id = builder.GetUintConstantId(0u);
   // Get texel buffer size.
   Instruction* size_inst =
-      builder.AddUnaryOp(GetUintId(), SpvOpImageQuerySize, ref.image_id);
+      builder.AddUnaryOp(GetUintId(), spv::Op::OpImageQuerySize, ref.image_id);
   uint32_t size_id = size_inst->result_id();
   // Generate runtime initialization/bounds test code with true branch
   // being full reference and false branch being debug output and zero
   // for the referenced value.
   Instruction* ult_inst =
-      builder.AddBinaryOp(GetBoolId(), SpvOpULessThan, coord_id, size_id);
+      builder.AddBinaryOp(GetBoolId(), spv::Op::OpULessThan, coord_id, size_id);
   uint32_t error =
       (image_ty_inst->GetSingleWordInOperand(kSpvTypeImageSampled) == 2)
           ? kInstErrorBuffOOBStorageTexel
@@ -778,13 +788,16 @@
   // init check is enabled.
   if (desc_idx_enabled_ || buffer_bounds_enabled_ || texel_buffer_enabled_)
     for (auto& anno : get_module()->annotations())
-      if (anno.opcode() == SpvOpDecorate) {
-        if (anno.GetSingleWordInOperand(1u) == SpvDecorationDescriptorSet)
+      if (anno.opcode() == spv::Op::OpDecorate) {
+        if (spv::Decoration(anno.GetSingleWordInOperand(1u)) ==
+            spv::Decoration::DescriptorSet) {
           var2desc_set_[anno.GetSingleWordInOperand(0u)] =
               anno.GetSingleWordInOperand(2u);
-        else if (anno.GetSingleWordInOperand(1u) == SpvDecorationBinding)
+        } else if (spv::Decoration(anno.GetSingleWordInOperand(1u)) ==
+                   spv::Decoration::Binding) {
           var2binding_[anno.GetSingleWordInOperand(0u)] =
               anno.GetSingleWordInOperand(2u);
+        }
       }
 }
 
diff --git a/source/opt/inst_buff_addr_check_pass.cpp b/source/opt/inst_buff_addr_check_pass.cpp
index 3318f88..be361e6 100644
--- a/source/opt/inst_buff_addr_check_pass.cpp
+++ b/source/opt/inst_buff_addr_check_pass.cpp
@@ -22,9 +22,9 @@
 uint32_t InstBuffAddrCheckPass::CloneOriginalReference(
     Instruction* ref_inst, InstructionBuilder* builder) {
   // Clone original ref with new result id (if load)
-  assert(
-      (ref_inst->opcode() == SpvOpLoad || ref_inst->opcode() == SpvOpStore) &&
-      "unexpected ref");
+  assert((ref_inst->opcode() == spv::Op::OpLoad ||
+          ref_inst->opcode() == spv::Op::OpStore) &&
+         "unexpected ref");
   std::unique_ptr<Instruction> new_ref_inst(ref_inst->Clone(context()));
   uint32_t ref_result_id = ref_inst->result_id();
   uint32_t new_ref_id = 0;
@@ -41,16 +41,17 @@
 }
 
 bool InstBuffAddrCheckPass::IsPhysicalBuffAddrReference(Instruction* ref_inst) {
-  if (ref_inst->opcode() != SpvOpLoad && ref_inst->opcode() != SpvOpStore)
+  if (ref_inst->opcode() != spv::Op::OpLoad &&
+      ref_inst->opcode() != spv::Op::OpStore)
     return false;
   uint32_t ptr_id = ref_inst->GetSingleWordInOperand(0);
   analysis::DefUseManager* du_mgr = get_def_use_mgr();
   Instruction* ptr_inst = du_mgr->GetDef(ptr_id);
-  if (ptr_inst->opcode() != SpvOpAccessChain) return false;
+  if (ptr_inst->opcode() != spv::Op::OpAccessChain) return false;
   uint32_t ptr_ty_id = ptr_inst->type_id();
   Instruction* ptr_ty_inst = du_mgr->GetDef(ptr_ty_id);
-  if (ptr_ty_inst->GetSingleWordInOperand(0) !=
-      SpvStorageClassPhysicalStorageBufferEXT)
+  if (spv::StorageClass(ptr_ty_inst->GetSingleWordInOperand(0)) !=
+      spv::StorageClass::PhysicalStorageBufferEXT)
     return false;
   return true;
 }
@@ -72,8 +73,9 @@
   std::unique_ptr<Instruction> merge_label(NewLabel(merge_blk_id));
   std::unique_ptr<Instruction> valid_label(NewLabel(valid_blk_id));
   std::unique_ptr<Instruction> invalid_label(NewLabel(invalid_blk_id));
-  (void)builder.AddConditionalBranch(check_id, valid_blk_id, invalid_blk_id,
-                                     merge_blk_id, SpvSelectionControlMaskNone);
+  (void)builder.AddConditionalBranch(
+      check_id, valid_blk_id, invalid_blk_id, merge_blk_id,
+      uint32_t(spv::SelectionControlMask::MaskNone));
   // Gen valid branch
   std::unique_ptr<BasicBlock> new_blk_ptr(
       new BasicBlock(std::move(valid_label)));
@@ -86,12 +88,12 @@
   builder.SetInsertPoint(&*new_blk_ptr);
   // Convert uptr from uint64 to 2 uint32
   Instruction* lo_uptr_inst =
-      builder.AddUnaryOp(GetUintId(), SpvOpUConvert, ref_uptr_id);
+      builder.AddUnaryOp(GetUintId(), spv::Op::OpUConvert, ref_uptr_id);
   Instruction* rshift_uptr_inst =
-      builder.AddBinaryOp(GetUint64Id(), SpvOpShiftRightLogical, ref_uptr_id,
-                          builder.GetUintConstantId(32));
-  Instruction* hi_uptr_inst = builder.AddUnaryOp(GetUintId(), SpvOpUConvert,
-                                                 rshift_uptr_inst->result_id());
+      builder.AddBinaryOp(GetUint64Id(), spv::Op::OpShiftRightLogical,
+                          ref_uptr_id, builder.GetUintConstantId(32));
+  Instruction* hi_uptr_inst = builder.AddUnaryOp(
+      GetUintId(), spv::Op::OpUConvert, rshift_uptr_inst->result_id());
   GenDebugStreamWrite(
       uid2offset_[ref_inst->unique_id()], stage_idx,
       {error_id, lo_uptr_inst->result_id(), hi_uptr_inst->result_id()},
@@ -105,8 +107,8 @@
     analysis::Type* ref_type = type_mgr->GetType(ref_type_id);
     if (ref_type->AsPointer() != nullptr) {
       uint32_t null_u64_id = GetNullId(GetUint64Id());
-      Instruction* null_ptr_inst =
-          builder.AddUnaryOp(ref_type_id, SpvOpConvertUToPtr, null_u64_id);
+      Instruction* null_ptr_inst = builder.AddUnaryOp(
+          ref_type_id, spv::Op::OpConvertUToPtr, null_u64_id);
       null_id = null_ptr_inst->result_id();
     } else {
       null_id = GetNullId(ref_type_id);
@@ -133,16 +135,16 @@
 uint32_t InstBuffAddrCheckPass::GetTypeAlignment(uint32_t type_id) {
   Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
   switch (type_inst->opcode()) {
-    case SpvOpTypeFloat:
-    case SpvOpTypeInt:
-    case SpvOpTypeVector:
+    case spv::Op::OpTypeFloat:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeVector:
       return GetTypeLength(type_id);
-    case SpvOpTypeMatrix:
+    case spv::Op::OpTypeMatrix:
       return GetTypeAlignment(type_inst->GetSingleWordInOperand(0));
-    case SpvOpTypeArray:
-    case SpvOpTypeRuntimeArray:
+    case spv::Op::OpTypeArray:
+    case spv::Op::OpTypeRuntimeArray:
       return GetTypeAlignment(type_inst->GetSingleWordInOperand(0));
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       uint32_t max = 0;
       type_inst->ForEachInId([&max, this](const uint32_t* iid) {
         uint32_t alignment = GetTypeAlignment(*iid);
@@ -150,9 +152,9 @@
       });
       return max;
     }
-    case SpvOpTypePointer:
-      assert(type_inst->GetSingleWordInOperand(0) ==
-                 SpvStorageClassPhysicalStorageBufferEXT &&
+    case spv::Op::OpTypePointer:
+      assert(spv::StorageClass(type_inst->GetSingleWordInOperand(0)) ==
+                 spv::StorageClass::PhysicalStorageBufferEXT &&
              "unexpected pointer type");
       return 8u;
     default:
@@ -164,29 +166,29 @@
 uint32_t InstBuffAddrCheckPass::GetTypeLength(uint32_t type_id) {
   Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
   switch (type_inst->opcode()) {
-    case SpvOpTypeFloat:
-    case SpvOpTypeInt:
+    case spv::Op::OpTypeFloat:
+    case spv::Op::OpTypeInt:
       return type_inst->GetSingleWordInOperand(0) / 8u;
-    case SpvOpTypeVector: {
+    case spv::Op::OpTypeVector: {
       uint32_t raw_cnt = type_inst->GetSingleWordInOperand(1);
       uint32_t adj_cnt = (raw_cnt == 3u) ? 4u : raw_cnt;
       return adj_cnt * GetTypeLength(type_inst->GetSingleWordInOperand(0));
     }
-    case SpvOpTypeMatrix:
+    case spv::Op::OpTypeMatrix:
       return type_inst->GetSingleWordInOperand(1) *
              GetTypeLength(type_inst->GetSingleWordInOperand(0));
-    case SpvOpTypePointer:
-      assert(type_inst->GetSingleWordInOperand(0) ==
-                 SpvStorageClassPhysicalStorageBufferEXT &&
+    case spv::Op::OpTypePointer:
+      assert(spv::StorageClass(type_inst->GetSingleWordInOperand(0)) ==
+                 spv::StorageClass::PhysicalStorageBufferEXT &&
              "unexpected pointer type");
       return 8u;
-    case SpvOpTypeArray: {
+    case spv::Op::OpTypeArray: {
       uint32_t const_id = type_inst->GetSingleWordInOperand(1);
       Instruction* const_inst = get_def_use_mgr()->GetDef(const_id);
       uint32_t cnt = const_inst->GetSingleWordInOperand(0);
       return cnt * GetTypeLength(type_inst->GetSingleWordInOperand(0));
     }
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       uint32_t len = 0;
       type_inst->ForEachInId([&len, this](const uint32_t* iid) {
         // Align struct length
@@ -200,7 +202,7 @@
       });
       return len;
     }
-    case SpvOpTypeRuntimeArray:
+    case spv::Op::OpTypeRuntimeArray:
     default:
       assert(false && "unexpected type");
       return 0;
@@ -213,7 +215,7 @@
   uint32_t pid = TakeNextId();
   param_vec->push_back(pid);
   std::unique_ptr<Instruction> param_inst(new Instruction(
-      get_module()->context(), SpvOpFunctionParameter, type_id, pid, {}));
+      get_module()->context(), spv::Op::OpFunctionParameter, type_id, pid, {}));
   get_def_use_mgr()->AnalyzeInstDefUse(&*param_inst);
   (*input_func)->AddParameter(std::move(param_inst));
 }
@@ -231,10 +233,10 @@
     analysis::Function func_ty(type_mgr->GetType(GetBoolId()), param_types);
     analysis::Type* reg_func_ty = type_mgr->GetRegisteredType(&func_ty);
     std::unique_ptr<Instruction> func_inst(
-        new Instruction(get_module()->context(), SpvOpFunction, GetBoolId(),
-                        search_test_func_id_,
+        new Instruction(get_module()->context(), spv::Op::OpFunction,
+                        GetBoolId(), search_test_func_id_,
                         {{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
-                          {SpvFunctionControlMaskNone}},
+                          {uint32_t(spv::FunctionControlMask::MaskNone)}},
                          {spv_operand_type_t::SPV_OPERAND_TYPE_ID,
                           {type_mgr->GetTypeInstruction(reg_func_ty)}}}));
     get_def_use_mgr()->AnalyzeInstDefUse(&*func_inst);
@@ -256,7 +258,7 @@
     // Branch to search loop header
     std::unique_ptr<Instruction> hdr_blk_label(NewLabel(hdr_blk_id));
     (void)builder.AddInstruction(MakeUnique<Instruction>(
-        context(), SpvOpBranch, 0, 0,
+        context(), spv::Op::OpBranch, 0, 0,
         std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {hdr_blk_id}}}));
     input_func->AddBasicBlock(std::move(first_blk_ptr));
     // Linear search loop header block
@@ -273,12 +275,12 @@
     uint32_t idx_phi_id = TakeNextId();
     uint32_t idx_inc_id = TakeNextId();
     std::unique_ptr<Instruction> idx_inc_inst(new Instruction(
-        context(), SpvOpIAdd, GetUintId(), idx_inc_id,
+        context(), spv::Op::OpIAdd, GetUintId(), idx_inc_id,
         {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {idx_phi_id}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_ID,
           {builder.GetUintConstantId(1u)}}}));
     std::unique_ptr<Instruction> idx_phi_inst(new Instruction(
-        context(), SpvOpPhi, GetUintId(), idx_phi_id,
+        context(), spv::Op::OpPhi, GetUintId(), idx_phi_id,
         {{spv_operand_type_t::SPV_OPERAND_TYPE_ID,
           {builder.GetUintConstantId(1u)}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {first_blk_id}},
@@ -292,14 +294,15 @@
     std::unique_ptr<Instruction> bound_test_blk_label(
         NewLabel(bound_test_blk_id));
     (void)builder.AddInstruction(MakeUnique<Instruction>(
-        context(), SpvOpLoopMerge, 0, 0,
+        context(), spv::Op::OpLoopMerge, 0, 0,
         std::initializer_list<Operand>{
             {SPV_OPERAND_TYPE_ID, {bound_test_blk_id}},
             {SPV_OPERAND_TYPE_ID, {cont_blk_id}},
-            {SPV_OPERAND_TYPE_LITERAL_INTEGER, {SpvLoopControlMaskNone}}}));
+            {SPV_OPERAND_TYPE_LITERAL_INTEGER,
+             {uint32_t(spv::LoopControlMask::MaskNone)}}}));
     // Branch to continue/work block
     (void)builder.AddInstruction(MakeUnique<Instruction>(
-        context(), SpvOpBranch, 0, 0,
+        context(), spv::Op::OpBranch, 0, 0,
         std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {cont_blk_id}}}));
     input_func->AddBasicBlock(std::move(hdr_blk_ptr));
     // Continue/Work Block. Read next buffer pointer and break if greater
@@ -313,19 +316,19 @@
     uint32_t ibuf_id = GetInputBufferId();
     uint32_t ibuf_ptr_id = GetInputBufferPtrId();
     Instruction* uptr_ac_inst = builder.AddTernaryOp(
-        ibuf_ptr_id, SpvOpAccessChain, ibuf_id,
+        ibuf_ptr_id, spv::Op::OpAccessChain, ibuf_id,
         builder.GetUintConstantId(kDebugInputDataOffset), idx_inc_id);
     uint32_t ibuf_type_id = GetInputBufferTypeId();
-    Instruction* uptr_load_inst =
-        builder.AddUnaryOp(ibuf_type_id, SpvOpLoad, uptr_ac_inst->result_id());
+    Instruction* uptr_load_inst = builder.AddUnaryOp(
+        ibuf_type_id, spv::Op::OpLoad, uptr_ac_inst->result_id());
     // If loaded address greater than ref_ptr arg, break, else branch back to
     // loop header
     Instruction* uptr_test_inst =
-        builder.AddBinaryOp(GetBoolId(), SpvOpUGreaterThan,
+        builder.AddBinaryOp(GetBoolId(), spv::Op::OpUGreaterThan,
                             uptr_load_inst->result_id(), param_vec[0]);
-    (void)builder.AddConditionalBranch(uptr_test_inst->result_id(),
-                                       bound_test_blk_id, hdr_blk_id,
-                                       kInvalidId, SpvSelectionControlMaskNone);
+    (void)builder.AddConditionalBranch(
+        uptr_test_inst->result_id(), bound_test_blk_id, hdr_blk_id, kInvalidId,
+        uint32_t(spv::SelectionControlMask::MaskNone));
     input_func->AddBasicBlock(std::move(cont_blk_ptr));
     // Bounds test block. Read length of selected buffer and test that
     // all len arg bytes are in buffer.
@@ -333,63 +336,65 @@
         MakeUnique<BasicBlock>(std::move(bound_test_blk_label));
     builder.SetInsertPoint(&*bound_test_blk_ptr);
     // Decrement index to point to previous/candidate buffer address
-    Instruction* cand_idx_inst = builder.AddBinaryOp(
-        GetUintId(), SpvOpISub, idx_inc_id, builder.GetUintConstantId(1u));
+    Instruction* cand_idx_inst =
+        builder.AddBinaryOp(GetUintId(), spv::Op::OpISub, idx_inc_id,
+                            builder.GetUintConstantId(1u));
     // Load candidate buffer address
     Instruction* cand_ac_inst =
-        builder.AddTernaryOp(ibuf_ptr_id, SpvOpAccessChain, ibuf_id,
+        builder.AddTernaryOp(ibuf_ptr_id, spv::Op::OpAccessChain, ibuf_id,
                              builder.GetUintConstantId(kDebugInputDataOffset),
                              cand_idx_inst->result_id());
-    Instruction* cand_load_inst =
-        builder.AddUnaryOp(ibuf_type_id, SpvOpLoad, cand_ac_inst->result_id());
+    Instruction* cand_load_inst = builder.AddUnaryOp(
+        ibuf_type_id, spv::Op::OpLoad, cand_ac_inst->result_id());
     // Compute offset of ref_ptr from candidate buffer address
-    Instruction* offset_inst = builder.AddBinaryOp(
-        ibuf_type_id, SpvOpISub, param_vec[0], cand_load_inst->result_id());
+    Instruction* offset_inst =
+        builder.AddBinaryOp(ibuf_type_id, spv::Op::OpISub, param_vec[0],
+                            cand_load_inst->result_id());
     // Convert ref length to uint64
     Instruction* ref_len_64_inst =
-        builder.AddUnaryOp(ibuf_type_id, SpvOpUConvert, param_vec[1]);
+        builder.AddUnaryOp(ibuf_type_id, spv::Op::OpUConvert, param_vec[1]);
     // Add ref length to ref offset to compute end of reference
-    Instruction* ref_end_inst =
-        builder.AddBinaryOp(ibuf_type_id, SpvOpIAdd, offset_inst->result_id(),
-                            ref_len_64_inst->result_id());
+    Instruction* ref_end_inst = builder.AddBinaryOp(
+        ibuf_type_id, spv::Op::OpIAdd, offset_inst->result_id(),
+        ref_len_64_inst->result_id());
     // Load starting index of lengths in input buffer and convert to uint32
     Instruction* len_start_ac_inst =
-        builder.AddTernaryOp(ibuf_ptr_id, SpvOpAccessChain, ibuf_id,
+        builder.AddTernaryOp(ibuf_ptr_id, spv::Op::OpAccessChain, ibuf_id,
                              builder.GetUintConstantId(kDebugInputDataOffset),
                              builder.GetUintConstantId(0u));
     Instruction* len_start_load_inst = builder.AddUnaryOp(
-        ibuf_type_id, SpvOpLoad, len_start_ac_inst->result_id());
+        ibuf_type_id, spv::Op::OpLoad, len_start_ac_inst->result_id());
     Instruction* len_start_32_inst = builder.AddUnaryOp(
-        GetUintId(), SpvOpUConvert, len_start_load_inst->result_id());
+        GetUintId(), spv::Op::OpUConvert, len_start_load_inst->result_id());
     // Decrement search index to get candidate buffer length index
-    Instruction* cand_len_idx_inst =
-        builder.AddBinaryOp(GetUintId(), SpvOpISub, cand_idx_inst->result_id(),
-                            builder.GetUintConstantId(1u));
+    Instruction* cand_len_idx_inst = builder.AddBinaryOp(
+        GetUintId(), spv::Op::OpISub, cand_idx_inst->result_id(),
+        builder.GetUintConstantId(1u));
     // Add candidate length index to start index
     Instruction* len_idx_inst = builder.AddBinaryOp(
-        GetUintId(), SpvOpIAdd, cand_len_idx_inst->result_id(),
+        GetUintId(), spv::Op::OpIAdd, cand_len_idx_inst->result_id(),
         len_start_32_inst->result_id());
     // Load candidate buffer length
     Instruction* len_ac_inst =
-        builder.AddTernaryOp(ibuf_ptr_id, SpvOpAccessChain, ibuf_id,
+        builder.AddTernaryOp(ibuf_ptr_id, spv::Op::OpAccessChain, ibuf_id,
                              builder.GetUintConstantId(kDebugInputDataOffset),
                              len_idx_inst->result_id());
-    Instruction* len_load_inst =
-        builder.AddUnaryOp(ibuf_type_id, SpvOpLoad, len_ac_inst->result_id());
+    Instruction* len_load_inst = builder.AddUnaryOp(
+        ibuf_type_id, spv::Op::OpLoad, len_ac_inst->result_id());
     // Test if reference end within candidate buffer length
     Instruction* len_test_inst = builder.AddBinaryOp(
-        GetBoolId(), SpvOpULessThanEqual, ref_end_inst->result_id(),
+        GetBoolId(), spv::Op::OpULessThanEqual, ref_end_inst->result_id(),
         len_load_inst->result_id());
     // Return test result
     (void)builder.AddInstruction(MakeUnique<Instruction>(
-        context(), SpvOpReturnValue, 0, 0,
+        context(), spv::Op::OpReturnValue, 0, 0,
         std::initializer_list<Operand>{
             {SPV_OPERAND_TYPE_ID, {len_test_inst->result_id()}}}));
     // Close block
     input_func->AddBasicBlock(std::move(bound_test_blk_ptr));
     // Close function and add function to module
-    std::unique_ptr<Instruction> func_end_inst(
-        new Instruction(get_module()->context(), SpvOpFunctionEnd, 0, 0, {}));
+    std::unique_ptr<Instruction> func_end_inst(new Instruction(
+        get_module()->context(), spv::Op::OpFunctionEnd, 0, 0, {}));
     get_def_use_mgr()->AnalyzeInstDefUse(&*func_end_inst);
     input_func->SetFunctionEnd(std::move(func_end_inst));
     context()->AddFunction(std::move(input_func));
@@ -403,18 +408,18 @@
                                                  InstructionBuilder* builder,
                                                  uint32_t* ref_uptr_id) {
   // Enable Int64 if necessary
-  if (!get_feature_mgr()->HasCapability(SpvCapabilityInt64)) {
+  if (!get_feature_mgr()->HasCapability(spv::Capability::Int64)) {
     std::unique_ptr<Instruction> cap_int64_inst(new Instruction(
-        context(), SpvOpCapability, 0, 0,
-        std::initializer_list<Operand>{
-            {SPV_OPERAND_TYPE_CAPABILITY, {SpvCapabilityInt64}}}));
+        context(), spv::Op::OpCapability, 0, 0,
+        std::initializer_list<Operand>{{SPV_OPERAND_TYPE_CAPABILITY,
+                                        {uint32_t(spv::Capability::Int64)}}}));
     get_def_use_mgr()->AnalyzeInstDefUse(&*cap_int64_inst);
     context()->AddCapability(std::move(cap_int64_inst));
   }
   // Convert reference pointer to uint64
   uint32_t ref_ptr_id = ref_inst->GetSingleWordInOperand(0);
   Instruction* ref_uptr_inst =
-      builder->AddUnaryOp(GetUint64Id(), SpvOpConvertPtrToU, ref_ptr_id);
+      builder->AddUnaryOp(GetUint64Id(), spv::Op::OpConvertPtrToU, ref_ptr_id);
   *ref_uptr_id = ref_uptr_inst->result_id();
   // Compute reference length in bytes
   analysis::DefUseManager* du_mgr = get_def_use_mgr();
@@ -427,7 +432,7 @@
   const std::vector<uint32_t> args = {GetSearchAndTestFuncId(), *ref_uptr_id,
                                       ref_len_id};
   Instruction* call_inst =
-      builder->AddNaryOp(GetBoolId(), SpvOpFunctionCall, args);
+      builder->AddNaryOp(GetBoolId(), spv::Op::OpFunctionCall, args);
   uint32_t retval = call_inst->result_id();
   return retval;
 }
@@ -485,7 +490,7 @@
 
 Pass::Status InstBuffAddrCheckPass::Process() {
   if (!get_feature_mgr()->HasCapability(
-          SpvCapabilityPhysicalStorageBufferAddressesEXT))
+          spv::Capability::PhysicalStorageBufferAddressesEXT))
     return Status::SuccessWithoutChange;
   InitInstBuffAddrCheck();
   return ProcessImpl();
diff --git a/source/opt/inst_debug_printf_pass.cpp b/source/opt/inst_debug_printf_pass.cpp
index 4218138..151b94c 100644
--- a/source/opt/inst_debug_printf_pass.cpp
+++ b/source/opt/inst_debug_printf_pass.cpp
@@ -35,7 +35,7 @@
       uint32_t c_ty_id = type_mgr->GetId(c_ty);
       for (uint32_t c = 0; c < v_ty->element_count(); ++c) {
         Instruction* c_inst = builder->AddIdLiteralOp(
-            c_ty_id, SpvOpCompositeExtract, val_inst->result_id(), c);
+            c_ty_id, spv::Op::OpCompositeExtract, val_inst->result_id(), c);
         GenOutputValues(c_inst, val_ids, builder);
       }
       return;
@@ -44,8 +44,9 @@
       // Select between uint32 zero or one
       uint32_t zero_id = builder->GetUintConstantId(0);
       uint32_t one_id = builder->GetUintConstantId(1);
-      Instruction* sel_inst = builder->AddTernaryOp(
-          GetUintId(), SpvOpSelect, val_inst->result_id(), one_id, zero_id);
+      Instruction* sel_inst =
+          builder->AddTernaryOp(GetUintId(), spv::Op::OpSelect,
+                                val_inst->result_id(), one_id, zero_id);
       val_ids->push_back(sel_inst->result_id());
       return;
     }
@@ -55,21 +56,21 @@
         case 16: {
           // Convert float16 to float32 and recurse
           Instruction* f32_inst = builder->AddUnaryOp(
-              GetFloatId(), SpvOpFConvert, val_inst->result_id());
+              GetFloatId(), spv::Op::OpFConvert, val_inst->result_id());
           GenOutputValues(f32_inst, val_ids, builder);
           return;
         }
         case 64: {
           // Bitcast float64 to uint64 and recurse
           Instruction* ui64_inst = builder->AddUnaryOp(
-              GetUint64Id(), SpvOpBitcast, val_inst->result_id());
+              GetUint64Id(), spv::Op::OpBitcast, val_inst->result_id());
           GenOutputValues(ui64_inst, val_ids, builder);
           return;
         }
         case 32: {
           // Bitcase float32 to uint32
-          Instruction* bc_inst = builder->AddUnaryOp(GetUintId(), SpvOpBitcast,
-                                                     val_inst->result_id());
+          Instruction* bc_inst = builder->AddUnaryOp(
+              GetUintId(), spv::Op::OpBitcast, val_inst->result_id());
           val_ids->push_back(bc_inst->result_id());
           return;
         }
@@ -85,17 +86,17 @@
           Instruction* ui64_inst = val_inst;
           if (i_ty->IsSigned()) {
             // Bitcast sint64 to uint64
-            ui64_inst = builder->AddUnaryOp(GetUint64Id(), SpvOpBitcast,
+            ui64_inst = builder->AddUnaryOp(GetUint64Id(), spv::Op::OpBitcast,
                                             val_inst->result_id());
           }
           // Break uint64 into 2x uint32
           Instruction* lo_ui64_inst = builder->AddUnaryOp(
-              GetUintId(), SpvOpUConvert, ui64_inst->result_id());
+              GetUintId(), spv::Op::OpUConvert, ui64_inst->result_id());
           Instruction* rshift_ui64_inst = builder->AddBinaryOp(
-              GetUint64Id(), SpvOpShiftRightLogical, ui64_inst->result_id(),
-              builder->GetUintConstantId(32));
+              GetUint64Id(), spv::Op::OpShiftRightLogical,
+              ui64_inst->result_id(), builder->GetUintConstantId(32));
           Instruction* hi_ui64_inst = builder->AddUnaryOp(
-              GetUintId(), SpvOpUConvert, rshift_ui64_inst->result_id());
+              GetUintId(), spv::Op::OpUConvert, rshift_ui64_inst->result_id());
           val_ids->push_back(lo_ui64_inst->result_id());
           val_ids->push_back(hi_ui64_inst->result_id());
           return;
@@ -104,12 +105,12 @@
           Instruction* ui8_inst = val_inst;
           if (i_ty->IsSigned()) {
             // Bitcast sint8 to uint8
-            ui8_inst = builder->AddUnaryOp(GetUint8Id(), SpvOpBitcast,
+            ui8_inst = builder->AddUnaryOp(GetUint8Id(), spv::Op::OpBitcast,
                                            val_inst->result_id());
           }
           // Convert uint8 to uint32
           Instruction* ui32_inst = builder->AddUnaryOp(
-              GetUintId(), SpvOpUConvert, ui8_inst->result_id());
+              GetUintId(), spv::Op::OpUConvert, ui8_inst->result_id());
           val_ids->push_back(ui32_inst->result_id());
           return;
         }
@@ -117,7 +118,7 @@
           Instruction* ui32_inst = val_inst;
           if (i_ty->IsSigned()) {
             // Bitcast sint32 to uint32
-            ui32_inst = builder->AddUnaryOp(GetUintId(), SpvOpBitcast,
+            ui32_inst = builder->AddUnaryOp(GetUintId(), spv::Op::OpBitcast,
                                             val_inst->result_id());
           }
           // uint32 needs no further processing
@@ -158,7 +159,7 @@
           return;
         }
         Instruction* opnd_inst = get_def_use_mgr()->GetDef(*iid);
-        if (opnd_inst->opcode() == SpvOpString) {
+        if (opnd_inst->opcode() == spv::Op::OpString) {
           uint32_t string_id_id = builder.GetUintConstantId(*iid);
           val_ids.push_back(string_id_id);
         } else {
@@ -176,7 +177,7 @@
     std::vector<std::unique_ptr<BasicBlock>>* new_blocks) {
   // If not DebugPrintf OpExtInst, return.
   Instruction* printf_inst = &*ref_inst_itr;
-  if (printf_inst->opcode() != SpvOpExtInst) return;
+  if (printf_inst->opcode() != spv::Op::OpExtInst) return;
   if (printf_inst->GetSingleWordInOperand(0) != ext_inst_printf_id_) return;
   if (printf_inst->GetSingleWordInOperand(1) !=
       NonSemanticDebugPrintfDebugPrintf)
diff --git a/source/opt/instruction.cpp b/source/opt/instruction.cpp
index e775a99..0338e5a 100644
--- a/source/opt/instruction.cpp
+++ b/source/opt/instruction.cpp
@@ -49,13 +49,13 @@
 Instruction::Instruction(IRContext* c)
     : utils::IntrusiveNodeBase<Instruction>(),
       context_(c),
-      opcode_(SpvOpNop),
+      opcode_(spv::Op::OpNop),
       has_type_id_(false),
       has_result_id_(false),
       unique_id_(c->TakeNextUniqueId()),
       dbg_scope_(kNoDebugScope, kNoInlinedAt) {}
 
-Instruction::Instruction(IRContext* c, SpvOp op)
+Instruction::Instruction(IRContext* c, spv::Op op)
     : utils::IntrusiveNodeBase<Instruction>(),
       context_(c),
       opcode_(op),
@@ -68,7 +68,7 @@
                          std::vector<Instruction>&& dbg_line)
     : utils::IntrusiveNodeBase<Instruction>(),
       context_(c),
-      opcode_(static_cast<SpvOp>(inst.opcode)),
+      opcode_(static_cast<spv::Op>(inst.opcode)),
       has_type_id_(inst.type_id != 0),
       has_result_id_(inst.result_id != 0),
       unique_id_(c->TakeNextUniqueId()),
@@ -88,7 +88,7 @@
                          const DebugScope& dbg_scope)
     : utils::IntrusiveNodeBase<Instruction>(),
       context_(c),
-      opcode_(static_cast<SpvOp>(inst.opcode)),
+      opcode_(static_cast<spv::Op>(inst.opcode)),
       has_type_id_(inst.type_id != 0),
       has_result_id_(inst.result_id != 0),
       unique_id_(c->TakeNextUniqueId()),
@@ -101,7 +101,7 @@
   }
 }
 
-Instruction::Instruction(IRContext* c, SpvOp op, uint32_t ty_id,
+Instruction::Instruction(IRContext* c, spv::Op op, uint32_t ty_id,
                          uint32_t res_id, const OperandList& in_operands)
     : utils::IntrusiveNodeBase<Instruction>(),
       context_(c),
@@ -179,7 +179,7 @@
 }
 
 bool Instruction::HasBranchWeights() const {
-  if (opcode_ == SpvOpBranchConditional &&
+  if (opcode_ == spv::Op::OpBranchConditional &&
       NumOperands() == kOpBranchConditionalWithWeightsNumOperands) {
     return true;
   }
@@ -208,13 +208,13 @@
       return false;
     }
 
-    if (address_def->opcode() == SpvOpVariable) {
+    if (address_def->opcode() == spv::Op::OpVariable) {
       if (address_def->IsReadOnlyPointer()) {
         return true;
       }
     }
 
-    if (address_def->opcode() == SpvOpLoad) {
+    if (address_def->opcode() == spv::Op::OpLoad) {
       const analysis::Type* address_type =
           context()->get_type_mgr()->GetType(address_def->type_id());
       if (address_type->AsSampledImage() != nullptr) {
@@ -235,12 +235,12 @@
   bool done = false;
   while (!done) {
     switch (base_inst->opcode()) {
-      case SpvOpAccessChain:
-      case SpvOpInBoundsAccessChain:
-      case SpvOpPtrAccessChain:
-      case SpvOpInBoundsPtrAccessChain:
-      case SpvOpImageTexelPointer:
-      case SpvOpCopyObject:
+      case spv::Op::OpAccessChain:
+      case spv::Op::OpInBoundsAccessChain:
+      case spv::Op::OpPtrAccessChain:
+      case spv::Op::OpInBoundsPtrAccessChain:
+      case spv::Op::OpImageTexelPointer:
+      case spv::Op::OpCopyObject:
         // All of these instructions have the base pointer use a base pointer
         // in in-operand 0.
         base = base_inst->GetSingleWordInOperand(0);
@@ -255,20 +255,20 @@
 }
 
 bool Instruction::IsReadOnlyPointer() const {
-  if (context()->get_feature_mgr()->HasCapability(SpvCapabilityShader))
+  if (context()->get_feature_mgr()->HasCapability(spv::Capability::Shader))
     return IsReadOnlyPointerShaders();
   else
     return IsReadOnlyPointerKernel();
 }
 
 bool Instruction::IsVulkanStorageImage() const {
-  if (opcode() != SpvOpTypePointer) {
+  if (opcode() != spv::Op::OpTypePointer) {
     return false;
   }
 
-  uint32_t storage_class =
-      GetSingleWordInOperand(kPointerTypeStorageClassIndex);
-  if (storage_class != SpvStorageClassUniformConstant) {
+  spv::StorageClass storage_class =
+      spv::StorageClass(GetSingleWordInOperand(kPointerTypeStorageClassIndex));
+  if (storage_class != spv::StorageClass::UniformConstant) {
     return false;
   }
 
@@ -276,17 +276,18 @@
       context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
 
   // Unpack the optional layer of arraying.
-  if (base_type->opcode() == SpvOpTypeArray ||
-      base_type->opcode() == SpvOpTypeRuntimeArray) {
+  if (base_type->opcode() == spv::Op::OpTypeArray ||
+      base_type->opcode() == spv::Op::OpTypeRuntimeArray) {
     base_type = context()->get_def_use_mgr()->GetDef(
         base_type->GetSingleWordInOperand(0));
   }
 
-  if (base_type->opcode() != SpvOpTypeImage) {
+  if (base_type->opcode() != spv::Op::OpTypeImage) {
     return false;
   }
 
-  if (base_type->GetSingleWordInOperand(kTypeImageDimIndex) == SpvDimBuffer) {
+  if (spv::Dim(base_type->GetSingleWordInOperand(kTypeImageDimIndex)) ==
+      spv::Dim::Buffer) {
     return false;
   }
 
@@ -296,13 +297,13 @@
 }
 
 bool Instruction::IsVulkanSampledImage() const {
-  if (opcode() != SpvOpTypePointer) {
+  if (opcode() != spv::Op::OpTypePointer) {
     return false;
   }
 
-  uint32_t storage_class =
-      GetSingleWordInOperand(kPointerTypeStorageClassIndex);
-  if (storage_class != SpvStorageClassUniformConstant) {
+  spv::StorageClass storage_class =
+      spv::StorageClass(GetSingleWordInOperand(kPointerTypeStorageClassIndex));
+  if (storage_class != spv::StorageClass::UniformConstant) {
     return false;
   }
 
@@ -310,17 +311,18 @@
       context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
 
   // Unpack the optional layer of arraying.
-  if (base_type->opcode() == SpvOpTypeArray ||
-      base_type->opcode() == SpvOpTypeRuntimeArray) {
+  if (base_type->opcode() == spv::Op::OpTypeArray ||
+      base_type->opcode() == spv::Op::OpTypeRuntimeArray) {
     base_type = context()->get_def_use_mgr()->GetDef(
         base_type->GetSingleWordInOperand(0));
   }
 
-  if (base_type->opcode() != SpvOpTypeImage) {
+  if (base_type->opcode() != spv::Op::OpTypeImage) {
     return false;
   }
 
-  if (base_type->GetSingleWordInOperand(kTypeImageDimIndex) == SpvDimBuffer) {
+  if (spv::Dim(base_type->GetSingleWordInOperand(kTypeImageDimIndex)) ==
+      spv::Dim::Buffer) {
     return false;
   }
 
@@ -330,13 +332,13 @@
 }
 
 bool Instruction::IsVulkanStorageTexelBuffer() const {
-  if (opcode() != SpvOpTypePointer) {
+  if (opcode() != spv::Op::OpTypePointer) {
     return false;
   }
 
-  uint32_t storage_class =
-      GetSingleWordInOperand(kPointerTypeStorageClassIndex);
-  if (storage_class != SpvStorageClassUniformConstant) {
+  spv::StorageClass storage_class =
+      spv::StorageClass(GetSingleWordInOperand(kPointerTypeStorageClassIndex));
+  if (storage_class != spv::StorageClass::UniformConstant) {
     return false;
   }
 
@@ -344,17 +346,18 @@
       context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
 
   // Unpack the optional layer of arraying.
-  if (base_type->opcode() == SpvOpTypeArray ||
-      base_type->opcode() == SpvOpTypeRuntimeArray) {
+  if (base_type->opcode() == spv::Op::OpTypeArray ||
+      base_type->opcode() == spv::Op::OpTypeRuntimeArray) {
     base_type = context()->get_def_use_mgr()->GetDef(
         base_type->GetSingleWordInOperand(0));
   }
 
-  if (base_type->opcode() != SpvOpTypeImage) {
+  if (base_type->opcode() != spv::Op::OpTypeImage) {
     return false;
   }
 
-  if (base_type->GetSingleWordInOperand(kTypeImageDimIndex) != SpvDimBuffer) {
+  if (spv::Dim(base_type->GetSingleWordInOperand(kTypeImageDimIndex)) !=
+      spv::Dim::Buffer) {
     return false;
   }
 
@@ -366,7 +369,7 @@
 bool Instruction::IsVulkanStorageBuffer() const {
   // Is there a difference between a "Storage buffer" and a "dynamic storage
   // buffer" in SPIR-V and do we care about the difference?
-  if (opcode() != SpvOpTypePointer) {
+  if (opcode() != spv::Op::OpTypePointer) {
     return false;
   }
 
@@ -374,28 +377,28 @@
       context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
 
   // Unpack the optional layer of arraying.
-  if (base_type->opcode() == SpvOpTypeArray ||
-      base_type->opcode() == SpvOpTypeRuntimeArray) {
+  if (base_type->opcode() == spv::Op::OpTypeArray ||
+      base_type->opcode() == spv::Op::OpTypeRuntimeArray) {
     base_type = context()->get_def_use_mgr()->GetDef(
         base_type->GetSingleWordInOperand(0));
   }
 
-  if (base_type->opcode() != SpvOpTypeStruct) {
+  if (base_type->opcode() != spv::Op::OpTypeStruct) {
     return false;
   }
 
-  uint32_t storage_class =
-      GetSingleWordInOperand(kPointerTypeStorageClassIndex);
-  if (storage_class == SpvStorageClassUniform) {
+  spv::StorageClass storage_class =
+      spv::StorageClass(GetSingleWordInOperand(kPointerTypeStorageClassIndex));
+  if (storage_class == spv::StorageClass::Uniform) {
     bool is_buffer_block = false;
     context()->get_decoration_mgr()->ForEachDecoration(
-        base_type->result_id(), SpvDecorationBufferBlock,
+        base_type->result_id(), uint32_t(spv::Decoration::BufferBlock),
         [&is_buffer_block](const Instruction&) { is_buffer_block = true; });
     return is_buffer_block;
-  } else if (storage_class == SpvStorageClassStorageBuffer) {
+  } else if (storage_class == spv::StorageClass::StorageBuffer) {
     bool is_block = false;
     context()->get_decoration_mgr()->ForEachDecoration(
-        base_type->result_id(), SpvDecorationBlock,
+        base_type->result_id(), uint32_t(spv::Decoration::Block),
         [&is_block](const Instruction&) { is_block = true; });
     return is_block;
   }
@@ -403,13 +406,14 @@
 }
 
 bool Instruction::IsVulkanStorageBufferVariable() const {
-  if (opcode() != SpvOpVariable) {
+  if (opcode() != spv::Op::OpVariable) {
     return false;
   }
 
-  uint32_t storage_class = GetSingleWordInOperand(kVariableStorageClassIndex);
-  if (storage_class == SpvStorageClassStorageBuffer ||
-      storage_class == SpvStorageClassUniform) {
+  spv::StorageClass storage_class =
+      spv::StorageClass(GetSingleWordInOperand(kVariableStorageClassIndex));
+  if (storage_class == spv::StorageClass::StorageBuffer ||
+      storage_class == spv::StorageClass::Uniform) {
     Instruction* var_type = context()->get_def_use_mgr()->GetDef(type_id());
     return var_type != nullptr && var_type->IsVulkanStorageBuffer();
   }
@@ -418,13 +422,13 @@
 }
 
 bool Instruction::IsVulkanUniformBuffer() const {
-  if (opcode() != SpvOpTypePointer) {
+  if (opcode() != spv::Op::OpTypePointer) {
     return false;
   }
 
-  uint32_t storage_class =
-      GetSingleWordInOperand(kPointerTypeStorageClassIndex);
-  if (storage_class != SpvStorageClassUniform) {
+  spv::StorageClass storage_class =
+      spv::StorageClass(GetSingleWordInOperand(kPointerTypeStorageClassIndex));
+  if (storage_class != spv::StorageClass::Uniform) {
     return false;
   }
 
@@ -432,19 +436,19 @@
       context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
 
   // Unpack the optional layer of arraying.
-  if (base_type->opcode() == SpvOpTypeArray ||
-      base_type->opcode() == SpvOpTypeRuntimeArray) {
+  if (base_type->opcode() == spv::Op::OpTypeArray ||
+      base_type->opcode() == spv::Op::OpTypeRuntimeArray) {
     base_type = context()->get_def_use_mgr()->GetDef(
         base_type->GetSingleWordInOperand(0));
   }
 
-  if (base_type->opcode() != SpvOpTypeStruct) {
+  if (base_type->opcode() != spv::Op::OpTypeStruct) {
     return false;
   }
 
   bool is_block = false;
   context()->get_decoration_mgr()->ForEachDecoration(
-      base_type->result_id(), SpvDecorationBlock,
+      base_type->result_id(), uint32_t(spv::Decoration::Block),
       [&is_block](const Instruction&) { is_block = true; });
   return is_block;
 }
@@ -455,27 +459,27 @@
   }
 
   Instruction* type_def = context()->get_def_use_mgr()->GetDef(type_id());
-  if (type_def->opcode() != SpvOpTypePointer) {
+  if (type_def->opcode() != spv::Op::OpTypePointer) {
     return false;
   }
 
-  uint32_t storage_class =
-      type_def->GetSingleWordInOperand(kPointerTypeStorageClassIndex);
+  spv::StorageClass storage_class = spv::StorageClass(
+      type_def->GetSingleWordInOperand(kPointerTypeStorageClassIndex));
 
   switch (storage_class) {
-    case SpvStorageClassUniformConstant:
+    case spv::StorageClass::UniformConstant:
       if (!type_def->IsVulkanStorageImage() &&
           !type_def->IsVulkanStorageTexelBuffer()) {
         return true;
       }
       break;
-    case SpvStorageClassUniform:
+    case spv::StorageClass::Uniform:
       if (!type_def->IsVulkanStorageBuffer()) {
         return true;
       }
       break;
-    case SpvStorageClassPushConstant:
-    case SpvStorageClassInput:
+    case spv::StorageClass::PushConstant:
+    case spv::StorageClass::Input:
       return true;
     default:
       break;
@@ -483,7 +487,7 @@
 
   bool is_nonwritable = false;
   context()->get_decoration_mgr()->ForEachDecoration(
-      result_id(), SpvDecorationNonWritable,
+      result_id(), uint32_t(spv::Decoration::NonWritable),
       [&is_nonwritable](const Instruction&) { is_nonwritable = true; });
   return is_nonwritable;
 }
@@ -494,14 +498,14 @@
   }
 
   Instruction* type_def = context()->get_def_use_mgr()->GetDef(type_id());
-  if (type_def->opcode() != SpvOpTypePointer) {
+  if (type_def->opcode() != spv::Op::OpTypePointer) {
     return false;
   }
 
-  uint32_t storage_class =
-      type_def->GetSingleWordInOperand(kPointerTypeStorageClassIndex);
+  spv::StorageClass storage_class = spv::StorageClass(
+      type_def->GetSingleWordInOperand(kPointerTypeStorageClassIndex));
 
-  return storage_class == SpvStorageClassUniformConstant;
+  return storage_class == spv::StorageClass::UniformConstant;
 }
 
 void Instruction::UpdateLexicalScope(uint32_t scope) {
@@ -564,13 +568,13 @@
 bool Instruction::IsLineInst() const { return IsLine() || IsNoLine(); }
 
 bool Instruction::IsLine() const {
-  if (opcode() == SpvOpLine) return true;
+  if (opcode() == spv::Op::OpLine) return true;
   NonSemanticShaderDebugInfo100Instructions ext_opt = GetShader100DebugOpcode();
   return ext_opt == NonSemanticShaderDebugInfo100DebugLine;
 }
 
 bool Instruction::IsNoLine() const {
-  if (opcode() == SpvOpNoLine) return true;
+  if (opcode() == spv::Op::OpNoLine) return true;
   NonSemanticShaderDebugInfo100Instructions ext_opt = GetShader100DebugOpcode();
   return ext_opt == NonSemanticShaderDebugInfo100DebugNoLine;
 }
@@ -597,33 +601,35 @@
   }
 
   Instruction* type = context()->get_def_use_mgr()->GetDef(tid);
-  if (type->opcode() != SpvOpTypePointer) {
+  if (type->opcode() != spv::Op::OpTypePointer) {
     return false;
   }
 
   auto feature_mgr = context()->get_feature_mgr();
-  if (feature_mgr->HasCapability(SpvCapabilityAddresses)) {
+  if (feature_mgr->HasCapability(spv::Capability::Addresses)) {
     // TODO: The rules here could be more restrictive.
     return true;
   }
 
-  if (opcode() == SpvOpVariable || opcode() == SpvOpFunctionParameter) {
+  if (opcode() == spv::Op::OpVariable ||
+      opcode() == spv::Op::OpFunctionParameter) {
     return true;
   }
 
   // With variable pointers, there are more valid base pointer objects.
   // Variable pointers implicitly declares Variable pointers storage buffer.
-  SpvStorageClass storage_class =
-      static_cast<SpvStorageClass>(type->GetSingleWordInOperand(0));
-  if ((feature_mgr->HasCapability(SpvCapabilityVariablePointersStorageBuffer) &&
-       storage_class == SpvStorageClassStorageBuffer) ||
-      (feature_mgr->HasCapability(SpvCapabilityVariablePointers) &&
-       storage_class == SpvStorageClassWorkgroup)) {
+  spv::StorageClass storage_class =
+      static_cast<spv::StorageClass>(type->GetSingleWordInOperand(0));
+  if ((feature_mgr->HasCapability(
+           spv::Capability::VariablePointersStorageBuffer) &&
+       storage_class == spv::StorageClass::StorageBuffer) ||
+      (feature_mgr->HasCapability(spv::Capability::VariablePointers) &&
+       storage_class == spv::StorageClass::Workgroup)) {
     switch (opcode()) {
-      case SpvOpPhi:
-      case SpvOpSelect:
-      case SpvOpFunctionCall:
-      case SpvOpConstantNull:
+      case spv::Op::OpPhi:
+      case spv::Op::OpSelect:
+      case spv::Op::OpFunctionCall:
+      case spv::Op::OpConstantNull:
         return true;
       default:
         break;
@@ -641,7 +647,7 @@
 }
 
 OpenCLDebugInfo100Instructions Instruction::GetOpenCL100DebugOpcode() const {
-  if (opcode() != SpvOpExtInst) {
+  if (opcode() != spv::Op::OpExtInst) {
     return OpenCLDebugInfo100InstructionsMax;
   }
 
@@ -660,7 +666,7 @@
 
 NonSemanticShaderDebugInfo100Instructions Instruction::GetShader100DebugOpcode()
     const {
-  if (opcode() != SpvOpExtInst) {
+  if (opcode() != spv::Op::OpExtInst) {
     return NonSemanticShaderDebugInfo100InstructionsMax;
   }
 
@@ -682,7 +688,7 @@
 }
 
 CommonDebugInfoInstructions Instruction::GetCommonDebugOpcode() const {
-  if (opcode() != SpvOpExtInst) {
+  if (opcode() != spv::Op::OpExtInst) {
     return CommonDebugInfoInstructionsMax;
   }
 
@@ -712,25 +718,25 @@
   }
 
   Instruction* type = context()->get_def_use_mgr()->GetDef(tid);
-  return (type->opcode() == SpvOpTypeImage ||
-          type->opcode() == SpvOpTypeSampledImage);
+  return (type->opcode() == spv::Op::OpTypeImage ||
+          type->opcode() == spv::Op::OpTypeSampledImage);
 }
 
 bool Instruction::IsOpaqueType() const {
-  if (opcode() == SpvOpTypeStruct) {
+  if (opcode() == spv::Op::OpTypeStruct) {
     bool is_opaque = false;
     ForEachInOperand([&is_opaque, this](const uint32_t* op_id) {
       Instruction* type_inst = context()->get_def_use_mgr()->GetDef(*op_id);
       is_opaque |= type_inst->IsOpaqueType();
     });
     return is_opaque;
-  } else if (opcode() == SpvOpTypeArray) {
+  } else if (opcode() == spv::Op::OpTypeArray) {
     uint32_t sub_type_id = GetSingleWordInOperand(0);
     Instruction* sub_type_inst =
         context()->get_def_use_mgr()->GetDef(sub_type_id);
     return sub_type_inst->IsOpaqueType();
   } else {
-    return opcode() == SpvOpTypeRuntimeArray ||
+    return opcode() == spv::Op::OpTypeRuntimeArray ||
            spvOpcodeIsBaseOpaqueType(opcode());
   }
 }
@@ -765,22 +771,23 @@
 bool Instruction::IsFloatingPointFoldingAllowed() const {
   // TODO: Add the rules for kernels.  For now it will be pessimistic.
   // For now, do not support capabilities introduced by SPV_KHR_float_controls.
-  if (!context_->get_feature_mgr()->HasCapability(SpvCapabilityShader) ||
-      context_->get_feature_mgr()->HasCapability(SpvCapabilityDenormPreserve) ||
+  if (!context_->get_feature_mgr()->HasCapability(spv::Capability::Shader) ||
       context_->get_feature_mgr()->HasCapability(
-          SpvCapabilityDenormFlushToZero) ||
+          spv::Capability::DenormPreserve) ||
       context_->get_feature_mgr()->HasCapability(
-          SpvCapabilitySignedZeroInfNanPreserve) ||
+          spv::Capability::DenormFlushToZero) ||
       context_->get_feature_mgr()->HasCapability(
-          SpvCapabilityRoundingModeRTZ) ||
+          spv::Capability::SignedZeroInfNanPreserve) ||
       context_->get_feature_mgr()->HasCapability(
-          SpvCapabilityRoundingModeRTE)) {
+          spv::Capability::RoundingModeRTZ) ||
+      context_->get_feature_mgr()->HasCapability(
+          spv::Capability::RoundingModeRTE)) {
     return false;
   }
 
   bool is_nocontract = false;
   context_->get_decoration_mgr()->WhileEachDecoration(
-      result_id(), SpvDecorationNoContraction,
+      result_id(), uint32_t(spv::Decoration::NoContraction),
       [&is_nocontract](const Instruction&) {
         is_nocontract = true;
         return false;
@@ -816,101 +823,101 @@
 
 bool Instruction::IsOpcodeCodeMotionSafe() const {
   switch (opcode_) {
-    case SpvOpNop:
-    case SpvOpUndef:
-    case SpvOpLoad:
-    case SpvOpAccessChain:
-    case SpvOpInBoundsAccessChain:
-    case SpvOpArrayLength:
-    case SpvOpVectorExtractDynamic:
-    case SpvOpVectorInsertDynamic:
-    case SpvOpVectorShuffle:
-    case SpvOpCompositeConstruct:
-    case SpvOpCompositeExtract:
-    case SpvOpCompositeInsert:
-    case SpvOpCopyObject:
-    case SpvOpTranspose:
-    case SpvOpConvertFToU:
-    case SpvOpConvertFToS:
-    case SpvOpConvertSToF:
-    case SpvOpConvertUToF:
-    case SpvOpUConvert:
-    case SpvOpSConvert:
-    case SpvOpFConvert:
-    case SpvOpQuantizeToF16:
-    case SpvOpBitcast:
-    case SpvOpSNegate:
-    case SpvOpFNegate:
-    case SpvOpIAdd:
-    case SpvOpFAdd:
-    case SpvOpISub:
-    case SpvOpFSub:
-    case SpvOpIMul:
-    case SpvOpFMul:
-    case SpvOpUDiv:
-    case SpvOpSDiv:
-    case SpvOpFDiv:
-    case SpvOpUMod:
-    case SpvOpSRem:
-    case SpvOpSMod:
-    case SpvOpFRem:
-    case SpvOpFMod:
-    case SpvOpVectorTimesScalar:
-    case SpvOpMatrixTimesScalar:
-    case SpvOpVectorTimesMatrix:
-    case SpvOpMatrixTimesVector:
-    case SpvOpMatrixTimesMatrix:
-    case SpvOpOuterProduct:
-    case SpvOpDot:
-    case SpvOpIAddCarry:
-    case SpvOpISubBorrow:
-    case SpvOpUMulExtended:
-    case SpvOpSMulExtended:
-    case SpvOpAny:
-    case SpvOpAll:
-    case SpvOpIsNan:
-    case SpvOpIsInf:
-    case SpvOpLogicalEqual:
-    case SpvOpLogicalNotEqual:
-    case SpvOpLogicalOr:
-    case SpvOpLogicalAnd:
-    case SpvOpLogicalNot:
-    case SpvOpSelect:
-    case SpvOpIEqual:
-    case SpvOpINotEqual:
-    case SpvOpUGreaterThan:
-    case SpvOpSGreaterThan:
-    case SpvOpUGreaterThanEqual:
-    case SpvOpSGreaterThanEqual:
-    case SpvOpULessThan:
-    case SpvOpSLessThan:
-    case SpvOpULessThanEqual:
-    case SpvOpSLessThanEqual:
-    case SpvOpFOrdEqual:
-    case SpvOpFUnordEqual:
-    case SpvOpFOrdNotEqual:
-    case SpvOpFUnordNotEqual:
-    case SpvOpFOrdLessThan:
-    case SpvOpFUnordLessThan:
-    case SpvOpFOrdGreaterThan:
-    case SpvOpFUnordGreaterThan:
-    case SpvOpFOrdLessThanEqual:
-    case SpvOpFUnordLessThanEqual:
-    case SpvOpFOrdGreaterThanEqual:
-    case SpvOpFUnordGreaterThanEqual:
-    case SpvOpShiftRightLogical:
-    case SpvOpShiftRightArithmetic:
-    case SpvOpShiftLeftLogical:
-    case SpvOpBitwiseOr:
-    case SpvOpBitwiseXor:
-    case SpvOpBitwiseAnd:
-    case SpvOpNot:
-    case SpvOpBitFieldInsert:
-    case SpvOpBitFieldSExtract:
-    case SpvOpBitFieldUExtract:
-    case SpvOpBitReverse:
-    case SpvOpBitCount:
-    case SpvOpSizeOf:
+    case spv::Op::OpNop:
+    case spv::Op::OpUndef:
+    case spv::Op::OpLoad:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
+    case spv::Op::OpArrayLength:
+    case spv::Op::OpVectorExtractDynamic:
+    case spv::Op::OpVectorInsertDynamic:
+    case spv::Op::OpVectorShuffle:
+    case spv::Op::OpCompositeConstruct:
+    case spv::Op::OpCompositeExtract:
+    case spv::Op::OpCompositeInsert:
+    case spv::Op::OpCopyObject:
+    case spv::Op::OpTranspose:
+    case spv::Op::OpConvertFToU:
+    case spv::Op::OpConvertFToS:
+    case spv::Op::OpConvertSToF:
+    case spv::Op::OpConvertUToF:
+    case spv::Op::OpUConvert:
+    case spv::Op::OpSConvert:
+    case spv::Op::OpFConvert:
+    case spv::Op::OpQuantizeToF16:
+    case spv::Op::OpBitcast:
+    case spv::Op::OpSNegate:
+    case spv::Op::OpFNegate:
+    case spv::Op::OpIAdd:
+    case spv::Op::OpFAdd:
+    case spv::Op::OpISub:
+    case spv::Op::OpFSub:
+    case spv::Op::OpIMul:
+    case spv::Op::OpFMul:
+    case spv::Op::OpUDiv:
+    case spv::Op::OpSDiv:
+    case spv::Op::OpFDiv:
+    case spv::Op::OpUMod:
+    case spv::Op::OpSRem:
+    case spv::Op::OpSMod:
+    case spv::Op::OpFRem:
+    case spv::Op::OpFMod:
+    case spv::Op::OpVectorTimesScalar:
+    case spv::Op::OpMatrixTimesScalar:
+    case spv::Op::OpVectorTimesMatrix:
+    case spv::Op::OpMatrixTimesVector:
+    case spv::Op::OpMatrixTimesMatrix:
+    case spv::Op::OpOuterProduct:
+    case spv::Op::OpDot:
+    case spv::Op::OpIAddCarry:
+    case spv::Op::OpISubBorrow:
+    case spv::Op::OpUMulExtended:
+    case spv::Op::OpSMulExtended:
+    case spv::Op::OpAny:
+    case spv::Op::OpAll:
+    case spv::Op::OpIsNan:
+    case spv::Op::OpIsInf:
+    case spv::Op::OpLogicalEqual:
+    case spv::Op::OpLogicalNotEqual:
+    case spv::Op::OpLogicalOr:
+    case spv::Op::OpLogicalAnd:
+    case spv::Op::OpLogicalNot:
+    case spv::Op::OpSelect:
+    case spv::Op::OpIEqual:
+    case spv::Op::OpINotEqual:
+    case spv::Op::OpUGreaterThan:
+    case spv::Op::OpSGreaterThan:
+    case spv::Op::OpUGreaterThanEqual:
+    case spv::Op::OpSGreaterThanEqual:
+    case spv::Op::OpULessThan:
+    case spv::Op::OpSLessThan:
+    case spv::Op::OpULessThanEqual:
+    case spv::Op::OpSLessThanEqual:
+    case spv::Op::OpFOrdEqual:
+    case spv::Op::OpFUnordEqual:
+    case spv::Op::OpFOrdNotEqual:
+    case spv::Op::OpFUnordNotEqual:
+    case spv::Op::OpFOrdLessThan:
+    case spv::Op::OpFUnordLessThan:
+    case spv::Op::OpFOrdGreaterThan:
+    case spv::Op::OpFUnordGreaterThan:
+    case spv::Op::OpFOrdLessThanEqual:
+    case spv::Op::OpFUnordLessThanEqual:
+    case spv::Op::OpFOrdGreaterThanEqual:
+    case spv::Op::OpFUnordGreaterThanEqual:
+    case spv::Op::OpShiftRightLogical:
+    case spv::Op::OpShiftRightArithmetic:
+    case spv::Op::OpShiftLeftLogical:
+    case spv::Op::OpBitwiseOr:
+    case spv::Op::OpBitwiseXor:
+    case spv::Op::OpBitwiseAnd:
+    case spv::Op::OpNot:
+    case spv::Op::OpBitFieldInsert:
+    case spv::Op::OpBitFieldSExtract:
+    case spv::Op::OpBitFieldUExtract:
+    case spv::Op::OpBitReverse:
+    case spv::Op::OpBitCount:
+    case spv::Op::OpSizeOf:
       return true;
     default:
       return false;
@@ -922,7 +929,7 @@
     return true;
   }
 
-  if (opcode() == SpvOpExtInst) {
+  if (opcode() == spv::Op::OpExtInst) {
     uint32_t instSetId =
         context()->get_feature_mgr()->GetExtInstImportId_GLSLstd450();
 
@@ -997,16 +1004,16 @@
   }
 
   switch (opcode()) {
-    case SpvOpDPdx:
-    case SpvOpDPdy:
-    case SpvOpFwidth:
-    case SpvOpDPdxFine:
-    case SpvOpDPdyFine:
-    case SpvOpFwidthFine:
-    case SpvOpDPdxCoarse:
-    case SpvOpDPdyCoarse:
-    case SpvOpFwidthCoarse:
-    case SpvOpImageQueryLod:
+    case spv::Op::OpDPdx:
+    case spv::Op::OpDPdy:
+    case spv::Op::OpFwidth:
+    case spv::Op::OpDPdxFine:
+    case spv::Op::OpDPdyFine:
+    case spv::Op::OpFwidthFine:
+    case spv::Op::OpDPdxCoarse:
+    case spv::Op::OpDPdyCoarse:
+    case spv::Op::OpFwidthCoarse:
+    case spv::Op::OpImageQueryLod:
       return true;
     default:
       return false;
@@ -1015,7 +1022,7 @@
 
 bool Instruction::IsNonSemanticInstruction() const {
   if (!HasResultId()) return false;
-  if (opcode() != SpvOpExtInst) return false;
+  if (opcode() != spv::Op::OpExtInst) return false;
 
   auto import_inst =
       context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(0));
@@ -1035,7 +1042,7 @@
     num_words = kDebugScopeNumWordsWithoutInlinedAt;
   }
   std::vector<uint32_t> operands = {
-      (num_words << 16) | static_cast<uint16_t>(SpvOpExtInst),
+      (num_words << 16) | static_cast<uint16_t>(spv::Op::OpExtInst),
       type_id,
       result_id,
       ext_set,
diff --git a/source/opt/instruction.h b/source/opt/instruction.h
index e79c628..07c6aee 100644
--- a/source/opt/instruction.h
+++ b/source/opt/instruction.h
@@ -190,7 +190,7 @@
   Instruction()
       : utils::IntrusiveNodeBase<Instruction>(),
         context_(nullptr),
-        opcode_(SpvOpNop),
+        opcode_(spv::Op::OpNop),
         has_type_id_(false),
         has_result_id_(false),
         unique_id_(0),
@@ -200,7 +200,7 @@
   Instruction(IRContext*);
   // Creates an instruction with the given opcode |op| and no additional logical
   // operands.
-  Instruction(IRContext*, SpvOp);
+  Instruction(IRContext*, spv::Op);
   // Creates an instruction using the given spv_parsed_instruction_t |inst|. All
   // the data inside |inst| will be copied and owned in this instance. And keep
   // record of line-related debug instructions |dbg_line| ahead of this
@@ -213,7 +213,7 @@
 
   // Creates an instruction with the given opcode |op|, type id: |ty_id|,
   // result id: |res_id| and input operands: |in_operands|.
-  Instruction(IRContext* c, SpvOp op, uint32_t ty_id, uint32_t res_id,
+  Instruction(IRContext* c, spv::Op op, uint32_t ty_id, uint32_t res_id,
               const OperandList& in_operands);
 
   // TODO: I will want to remove these, but will first have to remove the use of
@@ -235,12 +235,12 @@
 
   IRContext* context() const { return context_; }
 
-  SpvOp opcode() const { return opcode_; }
+  spv::Op opcode() const { return opcode_; }
   // Sets the opcode of this instruction to a specific opcode. Note this may
   // invalidate the instruction.
   // TODO(qining): Remove this function when instruction building and insertion
   // is well implemented.
-  void SetOpcode(SpvOp op) { opcode_ = op; }
+  void SetOpcode(spv::Op op) { opcode_ = op; }
   uint32_t type_id() const {
     return has_type_id_ ? GetSingleWordOperand(0) : 0;
   }
@@ -625,7 +625,7 @@
   bool IsValidBaseImage() const;
 
   IRContext* context_;  // IR Context
-  SpvOp opcode_;        // Opcode
+  spv::Op opcode_;      // Opcode
   bool has_type_id_;    // True if the instruction has a type id
   bool has_result_id_;  // True if the instruction has a result id
   uint32_t unique_id_;  // Unique instruction id
@@ -732,12 +732,12 @@
 }
 
 inline bool Instruction::IsNop() const {
-  return opcode_ == SpvOpNop && !has_type_id_ && !has_result_id_ &&
+  return opcode_ == spv::Op::OpNop && !has_type_id_ && !has_result_id_ &&
          operands_.empty();
 }
 
 inline void Instruction::ToNop() {
-  opcode_ = SpvOpNop;
+  opcode_ = spv::Op::OpNop;
   has_type_id_ = false;
   has_result_id_ = false;
   operands_.clear();
@@ -879,12 +879,12 @@
 
 inline bool Instruction::HasLabels() const {
   switch (opcode_) {
-    case SpvOpSelectionMerge:
-    case SpvOpBranch:
-    case SpvOpLoopMerge:
-    case SpvOpBranchConditional:
-    case SpvOpSwitch:
-    case SpvOpPhi:
+    case spv::Op::OpSelectionMerge:
+    case spv::Op::OpBranch:
+    case spv::Op::OpLoopMerge:
+    case spv::Op::OpBranchConditional:
+    case spv::Op::OpSwitch:
+    case spv::Op::OpPhi:
       return true;
       break;
     default:
diff --git a/source/opt/instrument_pass.cpp b/source/opt/instrument_pass.cpp
index d143d59..cf3f629 100644
--- a/source/opt/instrument_pass.cpp
+++ b/source/opt/instrument_pass.cpp
@@ -83,7 +83,7 @@
 
 std::unique_ptr<Instruction> InstrumentPass::NewLabel(uint32_t label_id) {
   std::unique_ptr<Instruction> newLabel(
-      new Instruction(context(), SpvOpLabel, 0, label_id, {}));
+      new Instruction(context(), spv::Op::OpLabel, 0, label_id, {}));
   get_def_use_mgr()->AnalyzeInstDefUse(&*newLabel);
   return newLabel;
 }
@@ -91,7 +91,7 @@
 std::unique_ptr<Instruction> InstrumentPass::NewName(
     uint32_t id, const std::string& name_str) {
   std::unique_ptr<Instruction> new_name(new Instruction(
-      context(), SpvOpName, 0, 0,
+      context(), spv::Op::OpName, 0, 0,
       std::initializer_list<Operand>{
           {SPV_OPERAND_TYPE_ID, {id}},
           {SPV_OPERAND_TYPE_LITERAL_STRING, utils::MakeVector(name_str)}}));
@@ -124,7 +124,7 @@
 std::unique_ptr<Instruction> InstrumentPass::NewMemberName(
     uint32_t id, uint32_t member_index, const std::string& name_str) {
   std::unique_ptr<Instruction> new_name(new Instruction(
-      context(), SpvOpMemberName, 0, 0,
+      context(), spv::Op::OpMemberName, 0, 0,
       std::initializer_list<Operand>{
           {SPV_OPERAND_TYPE_ID, {id}},
           {SPV_OPERAND_TYPE_LITERAL_INTEGER, {member_index}},
@@ -145,10 +145,10 @@
   analysis::Type* val_32b_reg_ty = type_mgr->GetRegisteredType(&val_32b_ty);
   uint32_t val_32b_reg_ty_id = type_mgr->GetId(val_32b_reg_ty);
   if (is_signed)
-    return builder->AddUnaryOp(val_32b_reg_ty_id, SpvOpSConvert, val_id)
+    return builder->AddUnaryOp(val_32b_reg_ty_id, spv::Op::OpSConvert, val_id)
         ->result_id();
   else
-    return builder->AddUnaryOp(val_32b_reg_ty_id, SpvOpUConvert, val_id)
+    return builder->AddUnaryOp(val_32b_reg_ty_id, spv::Op::OpUConvert, val_id)
         ->result_id();
 }
 
@@ -161,7 +161,7 @@
   uint32_t val_ty_id = get_def_use_mgr()->GetDef(val_32b_id)->type_id();
   analysis::Integer* val_ty = type_mgr->GetType(val_ty_id)->AsInteger();
   if (!val_ty->IsSigned()) return val_32b_id;
-  return builder->AddUnaryOp(GetUintId(), SpvOpBitcast, val_32b_id)
+  return builder->AddUnaryOp(GetUintId(), spv::Op::OpBitcast, val_32b_id)
       ->result_id();
 }
 
@@ -173,15 +173,16 @@
   uint32_t val_id = GenUintCastCode(field_value_id, builder);
   // Store value
   Instruction* data_idx_inst =
-      builder->AddBinaryOp(GetUintId(), SpvOpIAdd, base_offset_id,
+      builder->AddBinaryOp(GetUintId(), spv::Op::OpIAdd, base_offset_id,
                            builder->GetUintConstantId(field_offset));
   uint32_t buf_id = GetOutputBufferId();
   uint32_t buf_uint_ptr_id = GetOutputBufferPtrId();
   Instruction* achain_inst =
-      builder->AddTernaryOp(buf_uint_ptr_id, SpvOpAccessChain, buf_id,
+      builder->AddTernaryOp(buf_uint_ptr_id, spv::Op::OpAccessChain, buf_id,
                             builder->GetUintConstantId(kDebugOutputDataOffset),
                             data_idx_inst->result_id());
-  (void)builder->AddBinaryOp(0, SpvOpStore, achain_inst->result_id(), val_id);
+  (void)builder->AddBinaryOp(0, spv::Op::OpStore, achain_inst->result_id(),
+                             val_id);
 }
 
 void InstrumentPass::GenCommonStreamWriteCode(uint32_t record_sz,
@@ -207,7 +208,7 @@
     uint32_t base_offset_id, uint32_t uint_frag_coord_id, uint32_t element,
     InstructionBuilder* builder) {
   Instruction* element_val_inst = builder->AddIdLiteralOp(
-      GetUintId(), SpvOpCompositeExtract, uint_frag_coord_id, element);
+      GetUintId(), spv::Op::OpCompositeExtract, uint_frag_coord_id, element);
   GenDebugOutputFieldCode(base_offset_id, kInstFragOutFragCoordX + element,
                           element_val_inst->result_id(), builder);
 }
@@ -216,7 +217,8 @@
                                     InstructionBuilder* builder) {
   Instruction* var_inst = get_def_use_mgr()->GetDef(var_id);
   uint32_t type_id = GetPointeeTypeId(var_inst);
-  Instruction* load_inst = builder->AddUnaryOp(type_id, SpvOpLoad, var_id);
+  Instruction* load_inst =
+      builder->AddUnaryOp(type_id, spv::Op::OpLoad, var_id);
   return load_inst->result_id();
 }
 
@@ -233,31 +235,31 @@
                                              uint32_t base_offset_id,
                                              InstructionBuilder* builder) {
   // TODO(greg-lunarg): Add support for all stages
-  switch (stage_idx) {
-    case SpvExecutionModelVertex: {
+  switch (spv::ExecutionModel(stage_idx)) {
+    case spv::ExecutionModel::Vertex: {
       // Load and store VertexId and InstanceId
       GenBuiltinOutputCode(
-          context()->GetBuiltinInputVarId(SpvBuiltInVertexIndex),
+          context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::VertexIndex)),
           kInstVertOutVertexIndex, base_offset_id, builder);
-      GenBuiltinOutputCode(
-          context()->GetBuiltinInputVarId(SpvBuiltInInstanceIndex),
-          kInstVertOutInstanceIndex, base_offset_id, builder);
+      GenBuiltinOutputCode(context()->GetBuiltinInputVarId(
+                               uint32_t(spv::BuiltIn::InstanceIndex)),
+                           kInstVertOutInstanceIndex, base_offset_id, builder);
     } break;
-    case SpvExecutionModelGLCompute:
-    case SpvExecutionModelTaskNV:
-    case SpvExecutionModelMeshNV:
-    case SpvExecutionModelTaskEXT:
-    case SpvExecutionModelMeshEXT: {
+    case spv::ExecutionModel::GLCompute:
+    case spv::ExecutionModel::TaskNV:
+    case spv::ExecutionModel::MeshNV:
+    case spv::ExecutionModel::TaskEXT:
+    case spv::ExecutionModel::MeshEXT: {
       // Load and store GlobalInvocationId.
-      uint32_t load_id = GenVarLoad(
-          context()->GetBuiltinInputVarId(SpvBuiltInGlobalInvocationId),
-          builder);
+      uint32_t load_id = GenVarLoad(context()->GetBuiltinInputVarId(uint32_t(
+                                        spv::BuiltIn::GlobalInvocationId)),
+                                    builder);
       Instruction* x_inst = builder->AddIdLiteralOp(
-          GetUintId(), SpvOpCompositeExtract, load_id, 0);
+          GetUintId(), spv::Op::OpCompositeExtract, load_id, 0);
       Instruction* y_inst = builder->AddIdLiteralOp(
-          GetUintId(), SpvOpCompositeExtract, load_id, 1);
+          GetUintId(), spv::Op::OpCompositeExtract, load_id, 1);
       Instruction* z_inst = builder->AddIdLiteralOp(
-          GetUintId(), SpvOpCompositeExtract, load_id, 2);
+          GetUintId(), spv::Op::OpCompositeExtract, load_id, 2);
       GenDebugOutputFieldCode(base_offset_id, kInstCompOutGlobalInvocationIdX,
                               x_inst->result_id(), builder);
       GenDebugOutputFieldCode(base_offset_id, kInstCompOutGlobalInvocationIdY,
@@ -265,69 +267,71 @@
       GenDebugOutputFieldCode(base_offset_id, kInstCompOutGlobalInvocationIdZ,
                               z_inst->result_id(), builder);
     } break;
-    case SpvExecutionModelGeometry: {
+    case spv::ExecutionModel::Geometry: {
       // Load and store PrimitiveId and InvocationId.
       GenBuiltinOutputCode(
-          context()->GetBuiltinInputVarId(SpvBuiltInPrimitiveId),
+          context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::PrimitiveId)),
           kInstGeomOutPrimitiveId, base_offset_id, builder);
       GenBuiltinOutputCode(
-          context()->GetBuiltinInputVarId(SpvBuiltInInvocationId),
+          context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::InvocationId)),
           kInstGeomOutInvocationId, base_offset_id, builder);
     } break;
-    case SpvExecutionModelTessellationControl: {
+    case spv::ExecutionModel::TessellationControl: {
       // Load and store InvocationId and PrimitiveId
       GenBuiltinOutputCode(
-          context()->GetBuiltinInputVarId(SpvBuiltInInvocationId),
+          context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::InvocationId)),
           kInstTessCtlOutInvocationId, base_offset_id, builder);
       GenBuiltinOutputCode(
-          context()->GetBuiltinInputVarId(SpvBuiltInPrimitiveId),
+          context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::PrimitiveId)),
           kInstTessCtlOutPrimitiveId, base_offset_id, builder);
     } break;
-    case SpvExecutionModelTessellationEvaluation: {
+    case spv::ExecutionModel::TessellationEvaluation: {
       // Load and store PrimitiveId and TessCoord.uv
       GenBuiltinOutputCode(
-          context()->GetBuiltinInputVarId(SpvBuiltInPrimitiveId),
+          context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::PrimitiveId)),
           kInstTessEvalOutPrimitiveId, base_offset_id, builder);
       uint32_t load_id = GenVarLoad(
-          context()->GetBuiltinInputVarId(SpvBuiltInTessCoord), builder);
+          context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::TessCoord)),
+          builder);
       Instruction* uvec3_cast_inst =
-          builder->AddUnaryOp(GetVec3UintId(), SpvOpBitcast, load_id);
+          builder->AddUnaryOp(GetVec3UintId(), spv::Op::OpBitcast, load_id);
       uint32_t uvec3_cast_id = uvec3_cast_inst->result_id();
       Instruction* u_inst = builder->AddIdLiteralOp(
-          GetUintId(), SpvOpCompositeExtract, uvec3_cast_id, 0);
+          GetUintId(), spv::Op::OpCompositeExtract, uvec3_cast_id, 0);
       Instruction* v_inst = builder->AddIdLiteralOp(
-          GetUintId(), SpvOpCompositeExtract, uvec3_cast_id, 1);
+          GetUintId(), spv::Op::OpCompositeExtract, uvec3_cast_id, 1);
       GenDebugOutputFieldCode(base_offset_id, kInstTessEvalOutTessCoordU,
                               u_inst->result_id(), builder);
       GenDebugOutputFieldCode(base_offset_id, kInstTessEvalOutTessCoordV,
                               v_inst->result_id(), builder);
     } break;
-    case SpvExecutionModelFragment: {
+    case spv::ExecutionModel::Fragment: {
       // Load FragCoord and convert to Uint
       Instruction* frag_coord_inst = builder->AddUnaryOp(
-          GetVec4FloatId(), SpvOpLoad,
-          context()->GetBuiltinInputVarId(SpvBuiltInFragCoord));
+          GetVec4FloatId(), spv::Op::OpLoad,
+          context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::FragCoord)));
       Instruction* uint_frag_coord_inst = builder->AddUnaryOp(
-          GetVec4UintId(), SpvOpBitcast, frag_coord_inst->result_id());
+          GetVec4UintId(), spv::Op::OpBitcast, frag_coord_inst->result_id());
       for (uint32_t u = 0; u < 2u; ++u)
         GenFragCoordEltDebugOutputCode(
             base_offset_id, uint_frag_coord_inst->result_id(), u, builder);
     } break;
-    case SpvExecutionModelRayGenerationNV:
-    case SpvExecutionModelIntersectionNV:
-    case SpvExecutionModelAnyHitNV:
-    case SpvExecutionModelClosestHitNV:
-    case SpvExecutionModelMissNV:
-    case SpvExecutionModelCallableNV: {
+    case spv::ExecutionModel::RayGenerationNV:
+    case spv::ExecutionModel::IntersectionNV:
+    case spv::ExecutionModel::AnyHitNV:
+    case spv::ExecutionModel::ClosestHitNV:
+    case spv::ExecutionModel::MissNV:
+    case spv::ExecutionModel::CallableNV: {
       // Load and store LaunchIdNV.
       uint32_t launch_id = GenVarLoad(
-          context()->GetBuiltinInputVarId(SpvBuiltInLaunchIdNV), builder);
+          context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::LaunchIdNV)),
+          builder);
       Instruction* x_launch_inst = builder->AddIdLiteralOp(
-          GetUintId(), SpvOpCompositeExtract, launch_id, 0);
+          GetUintId(), spv::Op::OpCompositeExtract, launch_id, 0);
       Instruction* y_launch_inst = builder->AddIdLiteralOp(
-          GetUintId(), SpvOpCompositeExtract, launch_id, 1);
+          GetUintId(), spv::Op::OpCompositeExtract, launch_id, 1);
       Instruction* z_launch_inst = builder->AddIdLiteralOp(
-          GetUintId(), SpvOpCompositeExtract, launch_id, 2);
+          GetUintId(), spv::Op::OpCompositeExtract, launch_id, 2);
       GenDebugOutputFieldCode(base_offset_id, kInstRayTracingOutLaunchIdX,
                               x_launch_inst->result_id(), builder);
       GenDebugOutputFieldCode(base_offset_id, kInstRayTracingOutLaunchIdY,
@@ -349,7 +353,7 @@
   std::vector<uint32_t> args = {output_func_id,
                                 builder->GetUintConstantId(instruction_idx)};
   (void)args.insert(args.end(), validation_ids.begin(), validation_ids.end());
-  (void)builder->AddNaryOp(GetVoidId(), SpvOpFunctionCall, args);
+  (void)builder->AddNaryOp(GetVoidId(), spv::Op::OpFunctionCall, args);
 }
 
 bool InstrumentPass::AllConstant(const std::vector<uint32_t>& ids) {
@@ -385,13 +389,15 @@
     builder.SetInsertPoint(insert_before);
   }
   uint32_t res_id =
-      builder.AddNaryOp(GetUintId(), SpvOpFunctionCall, args)->result_id();
+      builder.AddNaryOp(GetUintId(), spv::Op::OpFunctionCall, args)
+          ->result_id();
   if (insert_in_first_block) call2id_[args] = res_id;
   return res_id;
 }
 
 bool InstrumentPass::IsSameBlockOp(const Instruction* inst) const {
-  return inst->opcode() == SpvOpSampledImage || inst->opcode() == SpvOpImage;
+  return inst->opcode() == spv::Op::OpSampledImage ||
+         inst->opcode() == spv::Op::OpImage;
 }
 
 void InstrumentPass::CloneSameBlockOps(
@@ -457,7 +463,7 @@
 uint32_t InstrumentPass::GetOutputBufferPtrId() {
   if (output_buffer_ptr_id_ == 0) {
     output_buffer_ptr_id_ = context()->get_type_mgr()->FindPointerToType(
-        GetUintId(), SpvStorageClassStorageBuffer);
+        GetUintId(), spv::StorageClass::StorageBuffer);
   }
   return output_buffer_ptr_id_;
 }
@@ -470,7 +476,7 @@
 uint32_t InstrumentPass::GetInputBufferPtrId() {
   if (input_buffer_ptr_id_ == 0) {
     input_buffer_ptr_id_ = context()->get_type_mgr()->FindPointerToType(
-        GetInputBufferTypeId(), SpvStorageClassStorageBuffer);
+        GetInputBufferTypeId(), spv::StorageClass::StorageBuffer);
   }
   return input_buffer_ptr_id_;
 }
@@ -519,8 +525,8 @@
     // invalidated after this pass.
     assert(context()->get_def_use_mgr()->NumUses(uint_arr_ty_id) == 0 &&
            "used RuntimeArray type returned");
-    deco_mgr->AddDecorationVal(uint_arr_ty_id, SpvDecorationArrayStride,
-                               width / 8u);
+    deco_mgr->AddDecorationVal(
+        uint_arr_ty_id, uint32_t(spv::Decoration::ArrayStride), width / 8u);
   }
   return *rarr_ty;
 }
@@ -559,26 +565,27 @@
     // invalidated after this pass.
     assert(context()->get_def_use_mgr()->NumUses(obufTyId) == 0 &&
            "used struct type returned");
-    deco_mgr->AddDecoration(obufTyId, SpvDecorationBlock);
+    deco_mgr->AddDecoration(obufTyId, uint32_t(spv::Decoration::Block));
     deco_mgr->AddMemberDecoration(obufTyId, kDebugOutputSizeOffset,
-                                  SpvDecorationOffset, 0);
+                                  uint32_t(spv::Decoration::Offset), 0);
     deco_mgr->AddMemberDecoration(obufTyId, kDebugOutputDataOffset,
-                                  SpvDecorationOffset, 4);
+                                  uint32_t(spv::Decoration::Offset), 4);
     uint32_t obufTyPtrId_ =
-        type_mgr->FindPointerToType(obufTyId, SpvStorageClassStorageBuffer);
+        type_mgr->FindPointerToType(obufTyId, spv::StorageClass::StorageBuffer);
     output_buffer_id_ = TakeNextId();
     std::unique_ptr<Instruction> newVarOp(new Instruction(
-        context(), SpvOpVariable, obufTyPtrId_, output_buffer_id_,
+        context(), spv::Op::OpVariable, obufTyPtrId_, output_buffer_id_,
         {{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
-          {SpvStorageClassStorageBuffer}}}));
+          {uint32_t(spv::StorageClass::StorageBuffer)}}}));
     context()->AddGlobalValue(std::move(newVarOp));
     context()->AddDebug2Inst(NewGlobalName(obufTyId, "OutputBuffer"));
     context()->AddDebug2Inst(NewMemberName(obufTyId, 0, "written_count"));
     context()->AddDebug2Inst(NewMemberName(obufTyId, 1, "data"));
     context()->AddDebug2Inst(NewGlobalName(output_buffer_id_, "output_buffer"));
-    deco_mgr->AddDecorationVal(output_buffer_id_, SpvDecorationDescriptorSet,
-                               desc_set_);
-    deco_mgr->AddDecorationVal(output_buffer_id_, SpvDecorationBinding,
+    deco_mgr->AddDecorationVal(
+        output_buffer_id_, uint32_t(spv::Decoration::DescriptorSet), desc_set_);
+    deco_mgr->AddDecorationVal(output_buffer_id_,
+                               uint32_t(spv::Decoration::Binding),
                                GetOutputBufferBinding());
     AddStorageBufferExt();
     if (get_module()->version() >= SPV_SPIRV_VERSION_WORD(1, 4)) {
@@ -610,22 +617,24 @@
     // invalidated after this pass.
     assert(context()->get_def_use_mgr()->NumUses(ibufTyId) == 0 &&
            "used struct type returned");
-    deco_mgr->AddDecoration(ibufTyId, SpvDecorationBlock);
-    deco_mgr->AddMemberDecoration(ibufTyId, 0, SpvDecorationOffset, 0);
+    deco_mgr->AddDecoration(ibufTyId, uint32_t(spv::Decoration::Block));
+    deco_mgr->AddMemberDecoration(ibufTyId, 0,
+                                  uint32_t(spv::Decoration::Offset), 0);
     uint32_t ibufTyPtrId_ =
-        type_mgr->FindPointerToType(ibufTyId, SpvStorageClassStorageBuffer);
+        type_mgr->FindPointerToType(ibufTyId, spv::StorageClass::StorageBuffer);
     input_buffer_id_ = TakeNextId();
     std::unique_ptr<Instruction> newVarOp(new Instruction(
-        context(), SpvOpVariable, ibufTyPtrId_, input_buffer_id_,
+        context(), spv::Op::OpVariable, ibufTyPtrId_, input_buffer_id_,
         {{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
-          {SpvStorageClassStorageBuffer}}}));
+          {uint32_t(spv::StorageClass::StorageBuffer)}}}));
     context()->AddGlobalValue(std::move(newVarOp));
     context()->AddDebug2Inst(NewGlobalName(ibufTyId, "InputBuffer"));
     context()->AddDebug2Inst(NewMemberName(ibufTyId, 0, "data"));
     context()->AddDebug2Inst(NewGlobalName(input_buffer_id_, "input_buffer"));
-    deco_mgr->AddDecorationVal(input_buffer_id_, SpvDecorationDescriptorSet,
-                               desc_set_);
-    deco_mgr->AddDecorationVal(input_buffer_id_, SpvDecorationBinding,
+    deco_mgr->AddDecorationVal(
+        input_buffer_id_, uint32_t(spv::Decoration::DescriptorSet), desc_set_);
+    deco_mgr->AddDecorationVal(input_buffer_id_,
+                               uint32_t(spv::Decoration::Binding),
                                GetInputBufferBinding());
     AddStorageBufferExt();
     if (get_module()->version() >= SPV_SPIRV_VERSION_WORD(1, 4)) {
@@ -746,10 +755,10 @@
     analysis::Function func_ty(type_mgr->GetType(GetVoidId()), param_types);
     analysis::Type* reg_func_ty = type_mgr->GetRegisteredType(&func_ty);
     std::unique_ptr<Instruction> func_inst(
-        new Instruction(get_module()->context(), SpvOpFunction, GetVoidId(),
-                        param2output_func_id_[param_cnt],
+        new Instruction(get_module()->context(), spv::Op::OpFunction,
+                        GetVoidId(), param2output_func_id_[param_cnt],
                         {{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
-                          {SpvFunctionControlMaskNone}},
+                          {uint32_t(spv::FunctionControlMask::MaskNone)}},
                          {spv_operand_type_t::SPV_OPERAND_TYPE_ID,
                           {type_mgr->GetTypeInstruction(reg_func_ty)}}}));
     get_def_use_mgr()->AnalyzeInstDefUse(&*func_inst);
@@ -761,7 +770,7 @@
       uint32_t pid = TakeNextId();
       param_vec.push_back(pid);
       std::unique_ptr<Instruction> param_inst(
-          new Instruction(get_module()->context(), SpvOpFunctionParameter,
+          new Instruction(get_module()->context(), spv::Op::OpFunctionParameter,
                           GetUintId(), pid, {}));
       get_def_use_mgr()->AnalyzeInstDefUse(&*param_inst);
       output_func->AddParameter(std::move(param_inst));
@@ -780,37 +789,39 @@
     uint32_t buf_id = GetOutputBufferId();
     uint32_t buf_uint_ptr_id = GetOutputBufferPtrId();
     Instruction* obuf_curr_sz_ac_inst =
-        builder.AddBinaryOp(buf_uint_ptr_id, SpvOpAccessChain, buf_id,
+        builder.AddBinaryOp(buf_uint_ptr_id, spv::Op::OpAccessChain, buf_id,
                             builder.GetUintConstantId(kDebugOutputSizeOffset));
     // Fetch the current debug buffer written size atomically, adding the
     // size of the record to be written.
     uint32_t obuf_record_sz_id = builder.GetUintConstantId(obuf_record_sz);
-    uint32_t mask_none_id = builder.GetUintConstantId(SpvMemoryAccessMaskNone);
-    uint32_t scope_invok_id = builder.GetUintConstantId(SpvScopeInvocation);
+    uint32_t mask_none_id =
+        builder.GetUintConstantId(uint32_t(spv::MemoryAccessMask::MaskNone));
+    uint32_t scope_invok_id =
+        builder.GetUintConstantId(uint32_t(spv::Scope::Invocation));
     Instruction* obuf_curr_sz_inst = builder.AddQuadOp(
-        GetUintId(), SpvOpAtomicIAdd, obuf_curr_sz_ac_inst->result_id(),
+        GetUintId(), spv::Op::OpAtomicIAdd, obuf_curr_sz_ac_inst->result_id(),
         scope_invok_id, mask_none_id, obuf_record_sz_id);
     uint32_t obuf_curr_sz_id = obuf_curr_sz_inst->result_id();
     // Compute new written size
     Instruction* obuf_new_sz_inst =
-        builder.AddBinaryOp(GetUintId(), SpvOpIAdd, obuf_curr_sz_id,
+        builder.AddBinaryOp(GetUintId(), spv::Op::OpIAdd, obuf_curr_sz_id,
                             builder.GetUintConstantId(obuf_record_sz));
     // Fetch the data bound
     Instruction* obuf_bnd_inst =
-        builder.AddIdLiteralOp(GetUintId(), SpvOpArrayLength,
+        builder.AddIdLiteralOp(GetUintId(), spv::Op::OpArrayLength,
                                GetOutputBufferId(), kDebugOutputDataOffset);
     // Test that new written size is less than or equal to debug output
     // data bound
     Instruction* obuf_safe_inst = builder.AddBinaryOp(
-        GetBoolId(), SpvOpULessThanEqual, obuf_new_sz_inst->result_id(),
+        GetBoolId(), spv::Op::OpULessThanEqual, obuf_new_sz_inst->result_id(),
         obuf_bnd_inst->result_id());
     uint32_t merge_blk_id = TakeNextId();
     uint32_t write_blk_id = TakeNextId();
     std::unique_ptr<Instruction> merge_label(NewLabel(merge_blk_id));
     std::unique_ptr<Instruction> write_label(NewLabel(write_blk_id));
-    (void)builder.AddConditionalBranch(obuf_safe_inst->result_id(),
-                                       write_blk_id, merge_blk_id, merge_blk_id,
-                                       SpvSelectionControlMaskNone);
+    (void)builder.AddConditionalBranch(
+        obuf_safe_inst->result_id(), write_blk_id, merge_blk_id, merge_blk_id,
+        uint32_t(spv::SelectionControlMask::MaskNone));
     // Close safety test block and gen write block
     output_func->AddBasicBlock(std::move(new_blk_ptr));
     new_blk_ptr = MakeUnique<BasicBlock>(std::move(write_label));
@@ -830,10 +841,10 @@
     new_blk_ptr = MakeUnique<BasicBlock>(std::move(merge_label));
     builder.SetInsertPoint(&*new_blk_ptr);
     // Close merge block and function and add function to module
-    (void)builder.AddNullaryOp(0, SpvOpReturn);
+    (void)builder.AddNullaryOp(0, spv::Op::OpReturn);
     output_func->AddBasicBlock(std::move(new_blk_ptr));
-    std::unique_ptr<Instruction> func_end_inst(
-        new Instruction(get_module()->context(), SpvOpFunctionEnd, 0, 0, {}));
+    std::unique_ptr<Instruction> func_end_inst(new Instruction(
+        get_module()->context(), spv::Op::OpFunctionEnd, 0, 0, {}));
     get_def_use_mgr()->AnalyzeInstDefUse(&*func_end_inst);
     output_func->SetFunctionEnd(std::move(func_end_inst));
     context()->AddFunction(std::move(output_func));
@@ -860,9 +871,9 @@
   analysis::Function func_ty(type_mgr->GetType(ibuf_type_id), param_types);
   analysis::Type* reg_func_ty = type_mgr->GetRegisteredType(&func_ty);
   std::unique_ptr<Instruction> func_inst(new Instruction(
-      get_module()->context(), SpvOpFunction, ibuf_type_id, func_id,
+      get_module()->context(), spv::Op::OpFunction, ibuf_type_id, func_id,
       {{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
-        {SpvFunctionControlMaskNone}},
+        {uint32_t(spv::FunctionControlMask::MaskNone)}},
        {spv_operand_type_t::SPV_OPERAND_TYPE_ID,
         {type_mgr->GetTypeInstruction(reg_func_ty)}}}));
   get_def_use_mgr()->AnalyzeInstDefUse(&*func_inst);
@@ -873,8 +884,9 @@
   for (uint32_t c = 0; c < param_cnt; ++c) {
     uint32_t pid = TakeNextId();
     param_vec.push_back(pid);
-    std::unique_ptr<Instruction> param_inst(new Instruction(
-        get_module()->context(), SpvOpFunctionParameter, GetUintId(), pid, {}));
+    std::unique_ptr<Instruction> param_inst(
+        new Instruction(get_module()->context(), spv::Op::OpFunctionParameter,
+                        GetUintId(), pid, {}));
     get_def_use_mgr()->AnalyzeInstDefUse(&*param_inst);
     input_func->AddParameter(std::move(param_inst));
   }
@@ -899,27 +911,27 @@
     } else {
       if (ibuf_type_id != GetUintId()) {
         Instruction* ucvt_inst =
-            builder.AddUnaryOp(GetUintId(), SpvOpUConvert, last_value_id);
+            builder.AddUnaryOp(GetUintId(), spv::Op::OpUConvert, last_value_id);
         last_value_id = ucvt_inst->result_id();
       }
       Instruction* offset_inst = builder.AddBinaryOp(
-          GetUintId(), SpvOpIAdd, last_value_id, param_vec[p]);
+          GetUintId(), spv::Op::OpIAdd, last_value_id, param_vec[p]);
       offset_id = offset_inst->result_id();
     }
     Instruction* ac_inst = builder.AddTernaryOp(
-        buf_ptr_id, SpvOpAccessChain, buf_id,
+        buf_ptr_id, spv::Op::OpAccessChain, buf_id,
         builder.GetUintConstantId(kDebugInputDataOffset), offset_id);
     Instruction* load_inst =
-        builder.AddUnaryOp(ibuf_type_id, SpvOpLoad, ac_inst->result_id());
+        builder.AddUnaryOp(ibuf_type_id, spv::Op::OpLoad, ac_inst->result_id());
     last_value_id = load_inst->result_id();
   }
   (void)builder.AddInstruction(MakeUnique<Instruction>(
-      context(), SpvOpReturnValue, 0, 0,
+      context(), spv::Op::OpReturnValue, 0, 0,
       std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {last_value_id}}}));
   // Close block and function and add function to module
   input_func->AddBasicBlock(std::move(new_blk_ptr));
-  std::unique_ptr<Instruction> func_end_inst(
-      new Instruction(get_module()->context(), SpvOpFunctionEnd, 0, 0, {}));
+  std::unique_ptr<Instruction> func_end_inst(new Instruction(
+      get_module()->context(), spv::Op::OpFunctionEnd, 0, 0, {}));
   get_def_use_mgr()->AnalyzeInstDefUse(&*func_end_inst);
   input_func->SetFunctionEnd(std::move(func_end_inst));
   context()->AddFunction(std::move(input_func));
@@ -970,7 +982,7 @@
       // block. This will allow function calls to be inserted into the first
       // block without interfering with the instrumentation algorithm.
       if (opt_direct_reads_ && !first_block_split) {
-        if (ii->opcode() != SpvOpVariable) {
+        if (ii->opcode() != spv::Op::OpVariable) {
           SplitBlock(ii, bi, &new_blks);
           first_block_split = true;
         }
@@ -1001,7 +1013,9 @@
       // Restart instrumenting at beginning of last new block,
       // but skip over any new phi or copy instruction.
       ii = bi->begin();
-      if (ii->opcode() == SpvOpPhi || ii->opcode() == SpvOpCopyObject) ++ii;
+      if (ii->opcode() == spv::Op::OpPhi ||
+          ii->opcode() == spv::Op::OpCopyObject)
+        ++ii;
       new_blks.clear();
     }
   }
@@ -1040,12 +1054,13 @@
   // to clone any functions which are in the call trees of entrypoints
   // with differing execution models.
   uint32_t ecnt = 0;
-  uint32_t stage = SpvExecutionModelMax;
+  auto stage = spv::ExecutionModel::Max;
   for (auto& e : get_module()->entry_points()) {
     if (ecnt == 0)
-      stage = e.GetSingleWordInOperand(kEntryPointExecutionModelInIdx);
-    else if (e.GetSingleWordInOperand(kEntryPointExecutionModelInIdx) !=
-             stage) {
+      stage = spv::ExecutionModel(
+          e.GetSingleWordInOperand(kEntryPointExecutionModelInIdx));
+    else if (spv::ExecutionModel(e.GetSingleWordInOperand(
+                 kEntryPointExecutionModelInIdx)) != stage) {
       if (consumer()) {
         std::string message = "Mixed stage shader module not supported";
         consumer()(SPV_MSG_ERROR, 0, {0, 0, 0}, message.c_str());
@@ -1055,19 +1070,22 @@
     ++ecnt;
   }
   // Check for supported stages
-  if (stage != SpvExecutionModelVertex && stage != SpvExecutionModelFragment &&
-      stage != SpvExecutionModelGeometry &&
-      stage != SpvExecutionModelGLCompute &&
-      stage != SpvExecutionModelTessellationControl &&
-      stage != SpvExecutionModelTessellationEvaluation &&
-      stage != SpvExecutionModelTaskNV && stage != SpvExecutionModelMeshNV &&
-      stage != SpvExecutionModelRayGenerationNV &&
-      stage != SpvExecutionModelIntersectionNV &&
-      stage != SpvExecutionModelAnyHitNV &&
-      stage != SpvExecutionModelClosestHitNV &&
-      stage != SpvExecutionModelMissNV &&
-      stage != SpvExecutionModelCallableNV &&
-      stage != SpvExecutionModelTaskEXT && stage != SpvExecutionModelMeshEXT) {
+  if (stage != spv::ExecutionModel::Vertex &&
+      stage != spv::ExecutionModel::Fragment &&
+      stage != spv::ExecutionModel::Geometry &&
+      stage != spv::ExecutionModel::GLCompute &&
+      stage != spv::ExecutionModel::TessellationControl &&
+      stage != spv::ExecutionModel::TessellationEvaluation &&
+      stage != spv::ExecutionModel::TaskNV &&
+      stage != spv::ExecutionModel::MeshNV &&
+      stage != spv::ExecutionModel::RayGenerationNV &&
+      stage != spv::ExecutionModel::IntersectionNV &&
+      stage != spv::ExecutionModel::AnyHitNV &&
+      stage != spv::ExecutionModel::ClosestHitNV &&
+      stage != spv::ExecutionModel::MissNV &&
+      stage != spv::ExecutionModel::CallableNV &&
+      stage != spv::ExecutionModel::TaskEXT &&
+      stage != spv::ExecutionModel::MeshEXT) {
     if (consumer()) {
       std::string message = "Stage not supported by instrumentation";
       consumer()(SPV_MSG_ERROR, 0, {0, 0, 0}, message.c_str());
@@ -1079,7 +1097,7 @@
   for (auto& e : get_module()->entry_points()) {
     roots.push(e.GetSingleWordInOperand(kEntryPointFunctionIdInIdx));
   }
-  bool modified = InstProcessCallTreeFromRoots(pfn, &roots, stage);
+  bool modified = InstProcessCallTreeFromRoots(pfn, &roots, uint32_t(stage));
   return modified;
 }
 
diff --git a/source/opt/interface_var_sroa.cpp b/source/opt/interface_var_sroa.cpp
index 1b2cb36..9722060 100644
--- a/source/opt/interface_var_sroa.cpp
+++ b/source/opt/interface_var_sroa.cpp
@@ -41,11 +41,11 @@
 // Get the length of the OpTypeArray |array_type|.
 uint32_t GetArrayLength(analysis::DefUseManager* def_use_mgr,
                         Instruction* array_type) {
-  assert(array_type->opcode() == SpvOpTypeArray);
+  assert(array_type->opcode() == spv::Op::OpTypeArray);
   uint32_t const_int_id =
       array_type->GetSingleWordInOperand(kOpTypeArrayLengthInOperandIndex);
   Instruction* array_length_inst = def_use_mgr->GetDef(const_int_id);
-  assert(array_length_inst->opcode() == SpvOpConstant);
+  assert(array_length_inst->opcode() == spv::Op::OpConstant);
   return array_length_inst->GetSingleWordInOperand(
       kOpConstantValueInOperandIndex);
 }
@@ -53,7 +53,7 @@
 // Get the element type instruction of the OpTypeArray |array_type|.
 Instruction* GetArrayElementType(analysis::DefUseManager* def_use_mgr,
                                  Instruction* array_type) {
-  assert(array_type->opcode() == SpvOpTypeArray);
+  assert(array_type->opcode() == spv::Op::OpTypeArray);
   uint32_t elem_type_id =
       array_type->GetSingleWordInOperand(kOpTypeArrayElemTypeInOperandIndex);
   return def_use_mgr->GetDef(elem_type_id);
@@ -62,7 +62,7 @@
 // Get the column type instruction of the OpTypeMatrix |matrix_type|.
 Instruction* GetMatrixColumnType(analysis::DefUseManager* def_use_mgr,
                                  Instruction* matrix_type) {
-  assert(matrix_type->opcode() == SpvOpTypeMatrix);
+  assert(matrix_type->opcode() == spv::Op::OpTypeMatrix);
   uint32_t column_type_id =
       matrix_type->GetSingleWordInOperand(kOpTypeMatrixColTypeInOperandIndex);
   return def_use_mgr->GetDef(column_type_id);
@@ -77,14 +77,14 @@
   if (depth_to_component == 0) return type_id;
 
   Instruction* type_inst = def_use_mgr->GetDef(type_id);
-  if (type_inst->opcode() == SpvOpTypeArray) {
+  if (type_inst->opcode() == spv::Op::OpTypeArray) {
     uint32_t elem_type_id =
         type_inst->GetSingleWordInOperand(kOpTypeArrayElemTypeInOperandIndex);
     return GetComponentTypeOfArrayMatrix(def_use_mgr, elem_type_id,
                                          depth_to_component - 1);
   }
 
-  assert(type_inst->opcode() == SpvOpTypeMatrix);
+  assert(type_inst->opcode() == spv::Op::OpTypeMatrix);
   uint32_t column_type_id =
       type_inst->GetSingleWordInOperand(kOpTypeMatrixColTypeInOperandIndex);
   return GetComponentTypeOfArrayMatrix(def_use_mgr, column_type_id,
@@ -94,7 +94,7 @@
 // Creates an OpDecorate instruction whose Target is |var_id| and Decoration is
 // |decoration|. Adds |literal| as an extra operand of the instruction.
 void CreateDecoration(analysis::DecorationManager* decoration_mgr,
-                      uint32_t var_id, SpvDecoration decoration,
+                      uint32_t var_id, spv::Decoration decoration,
                       uint32_t literal) {
   std::vector<Operand> operands({
       {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {var_id}},
@@ -102,7 +102,7 @@
        {static_cast<uint32_t>(decoration)}},
       {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {literal}},
   });
-  decoration_mgr->AddDecoration(SpvOpDecorate, std::move(operands));
+  decoration_mgr->AddDecoration(spv::Op::OpDecorate, std::move(operands));
 }
 
 // Replaces load instructions with composite construct instructions in all the
@@ -128,8 +128,8 @@
 }
 
 // Returns the storage class of the instruction |var|.
-SpvStorageClass GetStorageClass(Instruction* var) {
-  return static_cast<SpvStorageClass>(
+spv::StorageClass GetStorageClass(Instruction* var) {
+  return static_cast<spv::StorageClass>(
       var->GetSingleWordInOperand(kOpVariableStorageClassInOperandIndex));
 }
 
@@ -137,16 +137,17 @@
 
 bool InterfaceVariableScalarReplacement::HasExtraArrayness(
     Instruction& entry_point, Instruction* var) {
-  SpvExecutionModel execution_model =
-      static_cast<SpvExecutionModel>(entry_point.GetSingleWordInOperand(0));
-  if (execution_model != SpvExecutionModelTessellationEvaluation &&
-      execution_model != SpvExecutionModelTessellationControl) {
+  spv::ExecutionModel execution_model =
+      static_cast<spv::ExecutionModel>(entry_point.GetSingleWordInOperand(0));
+  if (execution_model != spv::ExecutionModel::TessellationEvaluation &&
+      execution_model != spv::ExecutionModel::TessellationControl) {
     return false;
   }
-  if (!context()->get_decoration_mgr()->HasDecoration(var->result_id(),
-                                                      SpvDecorationPatch)) {
-    if (execution_model == SpvExecutionModelTessellationControl) return true;
-    return GetStorageClass(var) != SpvStorageClassOutput;
+  if (!context()->get_decoration_mgr()->HasDecoration(
+          var->result_id(), uint32_t(spv::Decoration::Patch))) {
+    if (execution_model == spv::ExecutionModel::TessellationControl)
+      return true;
+    return GetStorageClass(var) != spv::StorageClass::Output;
   }
   return false;
 }
@@ -163,7 +164,7 @@
 bool InterfaceVariableScalarReplacement::GetVariableLocation(
     Instruction* var, uint32_t* location) {
   return !context()->get_decoration_mgr()->WhileEachDecoration(
-      var->result_id(), SpvDecorationLocation,
+      var->result_id(), uint32_t(spv::Decoration::Location),
       [location](const Instruction& inst) {
         *location =
             inst.GetSingleWordInOperand(kOpDecorateLiteralInOperandIndex);
@@ -174,7 +175,7 @@
 bool InterfaceVariableScalarReplacement::GetVariableComponent(
     Instruction* var, uint32_t* component) {
   return !context()->get_decoration_mgr()->WhileEachDecoration(
-      var->result_id(), SpvDecorationComponent,
+      var->result_id(), uint32_t(spv::Decoration::Component),
       [component](const Instruction& inst) {
         *component =
             inst.GetSingleWordInOperand(kOpDecorateLiteralInOperandIndex);
@@ -190,11 +191,11 @@
        i < entry_point.NumInOperands(); ++i) {
     Instruction* interface_var = context()->get_def_use_mgr()->GetDef(
         entry_point.GetSingleWordInOperand(i));
-    assert(interface_var->opcode() == SpvOpVariable);
+    assert(interface_var->opcode() == spv::Op::OpVariable);
 
-    SpvStorageClass storage_class = GetStorageClass(interface_var);
-    if (storage_class != SpvStorageClassInput &&
-        storage_class != SpvStorageClassOutput) {
+    spv::StorageClass storage_class = GetStorageClass(interface_var);
+    if (storage_class != spv::StorageClass::Input &&
+        storage_class != spv::StorageClass::Output) {
       continue;
     }
 
@@ -205,10 +206,10 @@
 
 void InterfaceVariableScalarReplacement::KillInstructionAndUsers(
     Instruction* inst) {
-  if (inst->opcode() == SpvOpEntryPoint) {
+  if (inst->opcode() == spv::Op::OpEntryPoint) {
     return;
   }
-  if (inst->opcode() != SpvOpAccessChain) {
+  if (inst->opcode() != spv::Op::OpAccessChain) {
     context()->KillInst(inst);
     return;
   }
@@ -232,10 +233,10 @@
     uint32_t var_id) {
   context()->get_decoration_mgr()->RemoveDecorationsFrom(
       var_id, [](const Instruction& inst) {
-        uint32_t decoration =
-            inst.GetSingleWordInOperand(kOpDecorateDecorationInOperandIndex);
-        return decoration == SpvDecorationLocation ||
-               decoration == SpvDecorationComponent;
+        spv::Decoration decoration = spv::Decoration(
+            inst.GetSingleWordInOperand(kOpDecorateDecorationInOperandIndex));
+        return decoration == spv::Decoration::Location ||
+               decoration == spv::Decoration::Component;
       });
 }
 
@@ -307,9 +308,9 @@
   if (!vars.HasMultipleComponents()) {
     uint32_t var_id = vars.GetComponentVariable()->result_id();
     CreateDecoration(context()->get_decoration_mgr(), var_id,
-                     SpvDecorationLocation, *location);
+                     spv::Decoration::Location, *location);
     CreateDecoration(context()->get_decoration_mgr(), var_id,
-                     SpvDecorationComponent, component);
+                     spv::Decoration::Component, component);
     ++(*location);
     return;
   }
@@ -389,15 +390,15 @@
     std::unordered_map<Instruction*, Instruction*>* loads_to_component_values,
     std::unordered_map<Instruction*, Instruction*>*
         loads_for_access_chain_to_component_values) {
-  SpvOp opcode = interface_var_user->opcode();
-  if (opcode == SpvOpStore) {
+  spv::Op opcode = interface_var_user->opcode();
+  if (opcode == spv::Op::OpStore) {
     uint32_t value_id = interface_var_user->GetSingleWordInOperand(1);
     StoreComponentOfValueToScalarVar(value_id, interface_var_component_indices,
                                      scalar_var, extra_array_index,
                                      interface_var_user);
     return true;
   }
-  if (opcode == SpvOpLoad) {
+  if (opcode == spv::Op::OpLoad) {
     Instruction* scalar_load =
         LoadScalarVar(scalar_var, extra_array_index, interface_var_user);
     loads_to_component_values->insert({interface_var_user, scalar_load});
@@ -408,25 +409,25 @@
   // them only for the first element of the extra array.
   if (extra_array_index && *extra_array_index != 0) return true;
 
-  if (opcode == SpvOpDecorateId || opcode == SpvOpDecorateString ||
-      opcode == SpvOpDecorate) {
+  if (opcode == spv::Op::OpDecorateId || opcode == spv::Op::OpDecorateString ||
+      opcode == spv::Op::OpDecorate) {
     CloneAnnotationForVariable(interface_var_user, scalar_var->result_id());
     return true;
   }
 
-  if (opcode == SpvOpName) {
+  if (opcode == spv::Op::OpName) {
     std::unique_ptr<Instruction> new_inst(interface_var_user->Clone(context()));
     new_inst->SetInOperand(0, {scalar_var->result_id()});
     context()->AddDebug2Inst(std::move(new_inst));
     return true;
   }
 
-  if (opcode == SpvOpEntryPoint) {
+  if (opcode == spv::Op::OpEntryPoint) {
     return ReplaceInterfaceVarInEntryPoint(interface_var, interface_var_user,
                                            scalar_var->result_id());
   }
 
-  if (opcode == SpvOpAccessChain) {
+  if (opcode == spv::Op::OpAccessChain) {
     ReplaceAccessChainWith(interface_var_user, interface_var_component_indices,
                            scalar_var,
                            loads_for_access_chain_to_component_values);
@@ -445,8 +446,8 @@
 
 void InterfaceVariableScalarReplacement::UseBaseAccessChainForAccessChain(
     Instruction* access_chain, Instruction* base_access_chain) {
-  assert(base_access_chain->opcode() == SpvOpAccessChain &&
-         access_chain->opcode() == SpvOpAccessChain &&
+  assert(base_access_chain->opcode() == spv::Op::OpAccessChain &&
+         access_chain->opcode() == spv::Op::OpAccessChain &&
          access_chain->GetSingleWordInOperand(0) ==
              base_access_chain->result_id());
   Instruction::OperandList new_operands;
@@ -470,10 +471,10 @@
   uint32_t ptr_type_id =
       GetPointerType(*component_type_id, GetStorageClass(var));
 
-  std::unique_ptr<Instruction> new_access_chain(
-      new Instruction(context(), SpvOpAccessChain, ptr_type_id, TakeNextId(),
-                      std::initializer_list<Operand>{
-                          {SPV_OPERAND_TYPE_ID, {var->result_id()}}}));
+  std::unique_ptr<Instruction> new_access_chain(new Instruction(
+      context(), spv::Op::OpAccessChain, ptr_type_id, TakeNextId(),
+      std::initializer_list<Operand>{
+          {SPV_OPERAND_TYPE_ID, {var->result_id()}}}));
   for (uint32_t index_id : index_ids) {
     new_access_chain->AddOperand({SPV_OPERAND_TYPE_ID, {index_id}});
   }
@@ -490,12 +491,12 @@
   uint32_t ptr_type_id =
       GetPointerType(component_type_id, GetStorageClass(var));
   uint32_t index_id = context()->get_constant_mgr()->GetUIntConst(index);
-  std::unique_ptr<Instruction> new_access_chain(
-      new Instruction(context(), SpvOpAccessChain, ptr_type_id, TakeNextId(),
-                      std::initializer_list<Operand>{
-                          {SPV_OPERAND_TYPE_ID, {var->result_id()}},
-                          {SPV_OPERAND_TYPE_ID, {index_id}},
-                      }));
+  std::unique_ptr<Instruction> new_access_chain(new Instruction(
+      context(), spv::Op::OpAccessChain, ptr_type_id, TakeNextId(),
+      std::initializer_list<Operand>{
+          {SPV_OPERAND_TYPE_ID, {var->result_id()}},
+          {SPV_OPERAND_TYPE_ID, {index_id}},
+      }));
   Instruction* inst = new_access_chain.get();
   context()->get_def_use_mgr()->AnalyzeInstDefUse(inst);
   insert_before->InsertBefore(std::move(new_access_chain));
@@ -519,20 +520,20 @@
       [this, access_chain, &indexes, &interface_var_component_indices,
        scalar_var, loads_to_component_values](Instruction* user) {
         switch (user->opcode()) {
-          case SpvOpAccessChain: {
+          case spv::Op::OpAccessChain: {
             UseBaseAccessChainForAccessChain(user, access_chain);
             ReplaceAccessChainWith(user, interface_var_component_indices,
                                    scalar_var, loads_to_component_values);
             return;
           }
-          case SpvOpStore: {
+          case spv::Op::OpStore: {
             uint32_t value_id = user->GetSingleWordInOperand(1);
             StoreComponentOfValueToAccessChainToScalarVar(
                 value_id, interface_var_component_indices, scalar_var, indexes,
                 user);
             return;
           }
-          case SpvOpLoad: {
+          case spv::Op::OpLoad: {
             Instruction* value =
                 LoadAccessChainToVar(scalar_var, indexes, user);
             loads_to_component_values->insert({user, value});
@@ -546,9 +547,9 @@
 
 void InterfaceVariableScalarReplacement::CloneAnnotationForVariable(
     Instruction* annotation_inst, uint32_t var_id) {
-  assert(annotation_inst->opcode() == SpvOpDecorate ||
-         annotation_inst->opcode() == SpvOpDecorateId ||
-         annotation_inst->opcode() == SpvOpDecorateString);
+  assert(annotation_inst->opcode() == spv::Op::OpDecorate ||
+         annotation_inst->opcode() == spv::Op::OpDecorateId ||
+         annotation_inst->opcode() == spv::Op::OpDecorateString);
   std::unique_ptr<Instruction> new_inst(annotation_inst->Clone(context()));
   new_inst->SetInOperand(0, {var_id});
   context()->AddAnnotationInst(std::move(new_inst));
@@ -593,13 +594,13 @@
 
 uint32_t InterfaceVariableScalarReplacement::GetPointeeTypeIdOfVar(
     Instruction* var) {
-  assert(var->opcode() == SpvOpVariable);
+  assert(var->opcode() == spv::Op::OpVariable);
 
   uint32_t ptr_type_id = var->type_id();
   analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
   Instruction* ptr_type_inst = def_use_mgr->GetDef(ptr_type_id);
 
-  assert(ptr_type_inst->opcode() == SpvOpTypePointer &&
+  assert(ptr_type_inst->opcode() == spv::Op::OpTypePointer &&
          "Variable must have a pointer type.");
   return ptr_type_inst->GetSingleWordInOperand(kOpTypePtrTypeInOperandIndex);
 }
@@ -643,7 +644,7 @@
 Instruction* InterfaceVariableScalarReplacement::CreateLoad(
     uint32_t type_id, Instruction* ptr, Instruction* insert_before) {
   std::unique_ptr<Instruction> load(
-      new Instruction(context(), SpvOpLoad, type_id, TakeNextId(),
+      new Instruction(context(), spv::Op::OpLoad, type_id, TakeNextId(),
                       std::initializer_list<Operand>{
                           {SPV_OPERAND_TYPE_ID, {ptr->result_id()}}}));
   Instruction* load_inst = load.get();
@@ -660,7 +661,7 @@
       component_type_id, value_id, component_indices, extra_array_index));
 
   std::unique_ptr<Instruction> new_store(
-      new Instruction(context(), SpvOpStore));
+      new Instruction(context(), spv::Op::OpStore));
   new_store->AddOperand({SPV_OPERAND_TYPE_ID, {ptr->result_id()}});
   new_store->AddOperand(
       {SPV_OPERAND_TYPE_ID, {composite_extract->result_id()}});
@@ -678,7 +679,7 @@
     const std::vector<uint32_t>& indexes, const uint32_t* extra_first_index) {
   uint32_t component_id = TakeNextId();
   Instruction* composite_extract = new Instruction(
-      context(), SpvOpCompositeExtract, type_id, component_id,
+      context(), spv::Op::OpCompositeExtract, type_id, component_id,
       std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {composite_id}}});
   if (extra_first_index) {
     composite_extract->AddOperand(
@@ -731,8 +732,8 @@
                                             depth_to_component);
   }
   uint32_t new_id = context()->TakeNextId();
-  std::unique_ptr<Instruction> new_composite_construct(
-      new Instruction(context(), SpvOpCompositeConstruct, type_id, new_id, {}));
+  std::unique_ptr<Instruction> new_composite_construct(new Instruction(
+      context(), spv::Op::OpCompositeConstruct, type_id, new_id, {}));
   Instruction* composite_construct = new_composite_construct.get();
   def_use_mgr->AnalyzeInstDefUse(composite_construct);
 
@@ -789,7 +790,7 @@
 }
 
 uint32_t InterfaceVariableScalarReplacement::GetPointerType(
-    uint32_t type_id, SpvStorageClass storage_class) {
+    uint32_t type_id, spv::StorageClass storage_class) {
   analysis::Type* type = context()->get_type_mgr()->GetType(type_id);
   analysis::Pointer ptr_type(type, storage_class);
   return context()->get_type_mgr()->GetTypeInstruction(&ptr_type);
@@ -797,9 +798,9 @@
 
 InterfaceVariableScalarReplacement::NestedCompositeComponents
 InterfaceVariableScalarReplacement::CreateScalarInterfaceVarsForArray(
-    Instruction* interface_var_type, SpvStorageClass storage_class,
+    Instruction* interface_var_type, spv::StorageClass storage_class,
     uint32_t extra_array_length) {
-  assert(interface_var_type->opcode() == SpvOpTypeArray);
+  assert(interface_var_type->opcode() == spv::Op::OpTypeArray);
 
   analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
   uint32_t array_length = GetArrayLength(def_use_mgr, interface_var_type);
@@ -818,9 +819,9 @@
 
 InterfaceVariableScalarReplacement::NestedCompositeComponents
 InterfaceVariableScalarReplacement::CreateScalarInterfaceVarsForMatrix(
-    Instruction* interface_var_type, SpvStorageClass storage_class,
+    Instruction* interface_var_type, spv::StorageClass storage_class,
     uint32_t extra_array_length) {
-  assert(interface_var_type->opcode() == SpvOpTypeMatrix);
+  assert(interface_var_type->opcode() == spv::Op::OpTypeMatrix);
 
   analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
   uint32_t column_count = interface_var_type->GetSingleWordInOperand(
@@ -841,16 +842,16 @@
 
 InterfaceVariableScalarReplacement::NestedCompositeComponents
 InterfaceVariableScalarReplacement::CreateScalarInterfaceVarsForReplacement(
-    Instruction* interface_var_type, SpvStorageClass storage_class,
+    Instruction* interface_var_type, spv::StorageClass storage_class,
     uint32_t extra_array_length) {
   // Handle array case.
-  if (interface_var_type->opcode() == SpvOpTypeArray) {
+  if (interface_var_type->opcode() == spv::Op::OpTypeArray) {
     return CreateScalarInterfaceVarsForArray(interface_var_type, storage_class,
                                              extra_array_length);
   }
 
   // Handle matrix case.
-  if (interface_var_type->opcode() == SpvOpTypeMatrix) {
+  if (interface_var_type->opcode() == spv::Op::OpTypeMatrix) {
     return CreateScalarInterfaceVarsForMatrix(interface_var_type, storage_class,
                                               extra_array_length);
   }
@@ -865,7 +866,7 @@
       context()->get_type_mgr()->FindPointerToType(type_id, storage_class);
   uint32_t id = TakeNextId();
   std::unique_ptr<Instruction> variable(
-      new Instruction(context(), SpvOpVariable, ptr_type_id, id,
+      new Instruction(context(), spv::Op::OpVariable, ptr_type_id, id,
                       std::initializer_list<Operand>{
                           {SPV_OPERAND_TYPE_STORAGE_CLASS,
                            {static_cast<uint32_t>(storage_class)}}}));
@@ -948,8 +949,8 @@
       return Pass::Status::Failure;
     }
 
-    if (interface_var_type->opcode() != SpvOpTypeArray &&
-        interface_var_type->opcode() != SpvOpTypeMatrix) {
+    if (interface_var_type->opcode() != spv::Op::OpTypeArray &&
+        interface_var_type->opcode() != spv::Op::OpTypeMatrix) {
       continue;
     }
 
diff --git a/source/opt/interface_var_sroa.h b/source/opt/interface_var_sroa.h
index 23baad0..df7511b 100644
--- a/source/opt/interface_var_sroa.h
+++ b/source/opt/interface_var_sroa.h
@@ -115,7 +115,7 @@
   // |extra_array_length| is not zero, adds the extra arrayness to the created
   // scalar variables.
   NestedCompositeComponents CreateScalarInterfaceVarsForReplacement(
-      Instruction* interface_var_type, SpvStorageClass storage_class,
+      Instruction* interface_var_type, spv::StorageClass storage_class,
       uint32_t extra_array_length);
 
   // Creates scalar variables with the storage classe |storage_class| to replace
@@ -123,7 +123,7 @@
   // If |extra_array_length| is not zero, adds the extra arrayness to all the
   // scalar variables.
   NestedCompositeComponents CreateScalarInterfaceVarsForArray(
-      Instruction* interface_var_type, SpvStorageClass storage_class,
+      Instruction* interface_var_type, spv::StorageClass storage_class,
       uint32_t extra_array_length);
 
   // Creates scalar variables with the storage classe |storage_class| to replace
@@ -131,7 +131,7 @@
   // with. If |extra_array_length| is not zero, adds the extra arrayness to all
   // the scalar variables.
   NestedCompositeComponents CreateScalarInterfaceVarsForMatrix(
-      Instruction* interface_var_type, SpvStorageClass storage_class,
+      Instruction* interface_var_type, spv::StorageClass storage_class,
       uint32_t extra_array_length);
 
   // Recursively adds Location and Component decorations to variables in
@@ -345,7 +345,7 @@
 
   // Returns the result id of OpTypePointer instrunction whose Type
   // operand is |type_id| and Storage Class operand is |storage_class|.
-  uint32_t GetPointerType(uint32_t type_id, SpvStorageClass storage_class);
+  uint32_t GetPointerType(uint32_t type_id, spv::StorageClass storage_class);
 
   // Kills an instrunction |inst| and its users.
   void KillInstructionAndUsers(Instruction* inst);
diff --git a/source/opt/interp_fixup_pass.cpp b/source/opt/interp_fixup_pass.cpp
index e8cdd99..f44ac37 100644
--- a/source/opt/interp_fixup_pass.cpp
+++ b/source/opt/interp_fixup_pass.cpp
@@ -45,12 +45,12 @@
   uint32_t op1_id = inst->GetSingleWordInOperand(2);
 
   Instruction* load_inst = ctx->get_def_use_mgr()->GetDef(op1_id);
-  if (load_inst->opcode() != SpvOpLoad) return false;
+  if (load_inst->opcode() != spv::Op::OpLoad) return false;
 
   Instruction* base_inst = load_inst->GetBaseAddress();
-  USE_ASSERT(base_inst->opcode() == SpvOpVariable &&
-             base_inst->GetSingleWordInOperand(kSpvVariableStorageClassInIdx) ==
-                 SpvStorageClassInput &&
+  USE_ASSERT(base_inst->opcode() == spv::Op::OpVariable &&
+             spv::StorageClass(base_inst->GetSingleWordInOperand(
+                 kSpvVariableStorageClassInIdx)) == spv::StorageClass::Input &&
              "unexpected interpolant in InterpolateAt*");
 
   uint32_t ptr_id = load_inst->GetSingleWordInOperand(0);
diff --git a/source/opt/ir_builder.h b/source/opt/ir_builder.h
index 9d4fa8f..fd42944 100644
--- a/source/opt/ir_builder.h
+++ b/source/opt/ir_builder.h
@@ -58,7 +58,7 @@
       : InstructionBuilder(context, parent_block, parent_block->end(),
                            preserved_analyses) {}
 
-  Instruction* AddNullaryOp(uint32_t type_id, SpvOp opcode) {
+  Instruction* AddNullaryOp(uint32_t type_id, spv::Op opcode) {
     uint32_t result_id = 0;
     if (type_id != 0) {
       result_id = GetContext()->TakeNextId();
@@ -71,7 +71,7 @@
     return AddInstruction(std::move(new_inst));
   }
 
-  Instruction* AddUnaryOp(uint32_t type_id, SpvOp opcode, uint32_t operand1) {
+  Instruction* AddUnaryOp(uint32_t type_id, spv::Op opcode, uint32_t operand1) {
     uint32_t result_id = 0;
     if (type_id != 0) {
       result_id = GetContext()->TakeNextId();
@@ -85,7 +85,7 @@
     return AddInstruction(std::move(newUnOp));
   }
 
-  Instruction* AddBinaryOp(uint32_t type_id, SpvOp opcode, uint32_t operand1,
+  Instruction* AddBinaryOp(uint32_t type_id, spv::Op opcode, uint32_t operand1,
                            uint32_t operand2) {
     uint32_t result_id = 0;
     if (type_id != 0) {
@@ -95,13 +95,14 @@
       }
     }
     std::unique_ptr<Instruction> newBinOp(new Instruction(
-        GetContext(), opcode, type_id, opcode == SpvOpStore ? 0 : result_id,
+        GetContext(), opcode, type_id,
+        opcode == spv::Op::OpStore ? 0 : result_id,
         {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {operand1}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {operand2}}}));
     return AddInstruction(std::move(newBinOp));
   }
 
-  Instruction* AddTernaryOp(uint32_t type_id, SpvOp opcode, uint32_t operand1,
+  Instruction* AddTernaryOp(uint32_t type_id, spv::Op opcode, uint32_t operand1,
                             uint32_t operand2, uint32_t operand3) {
     uint32_t result_id = 0;
     if (type_id != 0) {
@@ -118,7 +119,7 @@
     return AddInstruction(std::move(newTernOp));
   }
 
-  Instruction* AddQuadOp(uint32_t type_id, SpvOp opcode, uint32_t operand1,
+  Instruction* AddQuadOp(uint32_t type_id, spv::Op opcode, uint32_t operand1,
                          uint32_t operand2, uint32_t operand3,
                          uint32_t operand4) {
     uint32_t result_id = 0;
@@ -137,7 +138,7 @@
     return AddInstruction(std::move(newQuadOp));
   }
 
-  Instruction* AddIdLiteralOp(uint32_t type_id, SpvOp opcode, uint32_t id,
+  Instruction* AddIdLiteralOp(uint32_t type_id, spv::Op opcode, uint32_t id,
                               uint32_t uliteral) {
     uint32_t result_id = 0;
     if (type_id != 0) {
@@ -157,7 +158,7 @@
   // |typid| must be the id of the instruction's type.
   // |operands| must be a sequence of operand ids.
   // Use |result| for the result id if non-zero.
-  Instruction* AddNaryOp(uint32_t type_id, SpvOp opcode,
+  Instruction* AddNaryOp(uint32_t type_id, spv::Op opcode,
                          const std::vector<uint32_t>& operands,
                          uint32_t result = 0) {
     std::vector<Operand> ops;
@@ -174,10 +175,10 @@
   // Creates a new selection merge instruction.
   // The id |merge_id| is the merge basic block id.
   Instruction* AddSelectionMerge(
-      uint32_t merge_id,
-      uint32_t selection_control = SpvSelectionControlMaskNone) {
+      uint32_t merge_id, uint32_t selection_control = static_cast<uint32_t>(
+                             spv::SelectionControlMask::MaskNone)) {
     std::unique_ptr<Instruction> new_branch_merge(new Instruction(
-        GetContext(), SpvOpSelectionMerge, 0, 0,
+        GetContext(), spv::Op::OpSelectionMerge, 0, 0,
         {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {merge_id}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_SELECTION_CONTROL,
           {selection_control}}}));
@@ -189,9 +190,10 @@
   // |continue_id| is the id of the continue block.
   // |loop_control| are the loop control flags to be added to the instruction.
   Instruction* AddLoopMerge(uint32_t merge_id, uint32_t continue_id,
-                            uint32_t loop_control = SpvLoopControlMaskNone) {
+                            uint32_t loop_control = static_cast<uint32_t>(
+                                spv::LoopControlMask::MaskNone)) {
     std::unique_ptr<Instruction> new_branch_merge(new Instruction(
-        GetContext(), SpvOpLoopMerge, 0, 0,
+        GetContext(), spv::Op::OpLoopMerge, 0, 0,
         {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {merge_id}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {continue_id}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_LOOP_CONTROL, {loop_control}}}));
@@ -203,7 +205,7 @@
   // well formed.
   Instruction* AddBranch(uint32_t label_id) {
     std::unique_ptr<Instruction> new_branch(new Instruction(
-        GetContext(), SpvOpBranch, 0, 0,
+        GetContext(), spv::Op::OpBranch, 0, 0,
         {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {label_id}}}));
     return AddInstruction(std::move(new_branch));
   }
@@ -226,12 +228,13 @@
   Instruction* AddConditionalBranch(
       uint32_t cond_id, uint32_t true_id, uint32_t false_id,
       uint32_t merge_id = kInvalidId,
-      uint32_t selection_control = SpvSelectionControlMaskNone) {
+      uint32_t selection_control =
+          static_cast<uint32_t>(spv::SelectionControlMask::MaskNone)) {
     if (merge_id != kInvalidId) {
       AddSelectionMerge(merge_id, selection_control);
     }
     std::unique_ptr<Instruction> new_branch(new Instruction(
-        GetContext(), SpvOpBranchConditional, 0, 0,
+        GetContext(), spv::Op::OpBranchConditional, 0, 0,
         {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {cond_id}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {true_id}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {false_id}}}));
@@ -255,7 +258,8 @@
       uint32_t selector_id, uint32_t default_id,
       const std::vector<std::pair<Operand::OperandData, uint32_t>>& targets,
       uint32_t merge_id = kInvalidId,
-      uint32_t selection_control = SpvSelectionControlMaskNone) {
+      uint32_t selection_control =
+          static_cast<uint32_t>(spv::SelectionControlMask::MaskNone)) {
     if (merge_id != kInvalidId) {
       AddSelectionMerge(merge_id, selection_control);
     }
@@ -272,7 +276,7 @@
           Operand{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {target.second}});
     }
     std::unique_ptr<Instruction> new_switch(
-        new Instruction(GetContext(), SpvOpSwitch, 0, 0, operands));
+        new Instruction(GetContext(), spv::Op::OpSwitch, 0, 0, operands));
     return AddInstruction(std::move(new_switch));
   }
 
@@ -283,7 +287,7 @@
   Instruction* AddPhi(uint32_t type, const std::vector<uint32_t>& incomings,
                       uint32_t result = 0) {
     assert(incomings.size() % 2 == 0 && "A sequence of pairs is expected");
-    return AddNaryOp(type, SpvOpPhi, incomings, result);
+    return AddNaryOp(type, spv::Op::OpPhi, incomings, result);
   }
 
   // Creates an addition instruction.
@@ -294,7 +298,7 @@
   Instruction* AddIAdd(uint32_t type, uint32_t op1, uint32_t op2) {
     // TODO(1841): Handle id overflow.
     std::unique_ptr<Instruction> inst(new Instruction(
-        GetContext(), SpvOpIAdd, type, GetContext()->TakeNextId(),
+        GetContext(), spv::Op::OpIAdd, type, GetContext()->TakeNextId(),
         {{SPV_OPERAND_TYPE_ID, {op1}}, {SPV_OPERAND_TYPE_ID, {op2}}}));
     return AddInstruction(std::move(inst));
   }
@@ -308,7 +312,7 @@
     uint32_t type = GetContext()->get_type_mgr()->GetId(&bool_type);
     // TODO(1841): Handle id overflow.
     std::unique_ptr<Instruction> inst(new Instruction(
-        GetContext(), SpvOpULessThan, type, GetContext()->TakeNextId(),
+        GetContext(), spv::Op::OpULessThan, type, GetContext()->TakeNextId(),
         {{SPV_OPERAND_TYPE_ID, {op1}}, {SPV_OPERAND_TYPE_ID, {op2}}}));
     return AddInstruction(std::move(inst));
   }
@@ -322,7 +326,7 @@
     uint32_t type = GetContext()->get_type_mgr()->GetId(&bool_type);
     // TODO(1841): Handle id overflow.
     std::unique_ptr<Instruction> inst(new Instruction(
-        GetContext(), SpvOpSLessThan, type, GetContext()->TakeNextId(),
+        GetContext(), spv::Op::OpSLessThan, type, GetContext()->TakeNextId(),
         {{SPV_OPERAND_TYPE_ID, {op1}}, {SPV_OPERAND_TYPE_ID, {op2}}}));
     return AddInstruction(std::move(inst));
   }
@@ -352,7 +356,7 @@
                          uint32_t false_value) {
     // TODO(1841): Handle id overflow.
     std::unique_ptr<Instruction> select(new Instruction(
-        GetContext(), SpvOpSelect, type, GetContext()->TakeNextId(),
+        GetContext(), spv::Op::OpSelect, type, GetContext()->TakeNextId(),
         std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {cond}},
                                        {SPV_OPERAND_TYPE_ID, {true_value}},
                                        {SPV_OPERAND_TYPE_ID, {false_value}}}));
@@ -378,7 +382,7 @@
     }
     // TODO(1841): Handle id overflow.
     std::unique_ptr<Instruction> construct(
-        new Instruction(GetContext(), SpvOpCompositeConstruct, type,
+        new Instruction(GetContext(), spv::Op::OpCompositeConstruct, type,
                         GetContext()->TakeNextId(), ops));
     return AddInstruction(std::move(construct));
   }
@@ -447,7 +451,7 @@
 
     // TODO(1841): Handle id overflow.
     std::unique_ptr<Instruction> new_inst(
-        new Instruction(GetContext(), SpvOpCompositeExtract, type,
+        new Instruction(GetContext(), spv::Op::OpCompositeExtract, type,
                         GetContext()->TakeNextId(), operands));
     return AddInstruction(std::move(new_inst));
   }
@@ -455,7 +459,7 @@
   // Creates an unreachable instruction.
   Instruction* AddUnreachable() {
     std::unique_ptr<Instruction> select(
-        new Instruction(GetContext(), SpvOpUnreachable, 0, 0,
+        new Instruction(GetContext(), spv::Op::OpUnreachable, 0, 0,
                         std::initializer_list<Operand>{}));
     return AddInstruction(std::move(select));
   }
@@ -471,7 +475,7 @@
 
     // TODO(1841): Handle id overflow.
     std::unique_ptr<Instruction> new_inst(
-        new Instruction(GetContext(), SpvOpAccessChain, type_id,
+        new Instruction(GetContext(), spv::Op::OpAccessChain, type_id,
                         GetContext()->TakeNextId(), operands));
     return AddInstruction(std::move(new_inst));
   }
@@ -482,7 +486,7 @@
 
     // TODO(1841): Handle id overflow.
     std::unique_ptr<Instruction> new_inst(
-        new Instruction(GetContext(), SpvOpLoad, type_id,
+        new Instruction(GetContext(), spv::Op::OpLoad, type_id,
                         GetContext()->TakeNextId(), operands));
     return AddInstruction(std::move(new_inst));
   }
@@ -491,7 +495,7 @@
     std::vector<Operand> operands;
     operands.push_back({SPV_OPERAND_TYPE_ID, {storage_class}});
     std::unique_ptr<Instruction> new_inst(
-        new Instruction(GetContext(), SpvOpVariable, type_id,
+        new Instruction(GetContext(), spv::Op::OpVariable, type_id,
                         GetContext()->TakeNextId(), operands));
     return AddInstruction(std::move(new_inst));
   }
@@ -502,7 +506,7 @@
     operands.push_back({SPV_OPERAND_TYPE_ID, {obj_id}});
 
     std::unique_ptr<Instruction> new_inst(
-        new Instruction(GetContext(), SpvOpStore, 0, 0, operands));
+        new Instruction(GetContext(), spv::Op::OpStore, 0, 0, operands));
     return AddInstruction(std::move(new_inst));
   }
 
@@ -518,8 +522,9 @@
     if (result_id == 0) {
       return nullptr;
     }
-    std::unique_ptr<Instruction> new_inst(new Instruction(
-        GetContext(), SpvOpFunctionCall, result_type, result_id, operands));
+    std::unique_ptr<Instruction> new_inst(
+        new Instruction(GetContext(), spv::Op::OpFunctionCall, result_type,
+                        result_id, operands));
     return AddInstruction(std::move(new_inst));
   }
 
@@ -538,8 +543,9 @@
       return nullptr;
     }
 
-    std::unique_ptr<Instruction> new_inst(new Instruction(
-        GetContext(), SpvOpVectorShuffle, result_type, result_id, operands));
+    std::unique_ptr<Instruction> new_inst(
+        new Instruction(GetContext(), spv::Op::OpVectorShuffle, result_type,
+                        result_id, operands));
     return AddInstruction(std::move(new_inst));
   }
 
@@ -560,7 +566,7 @@
     }
 
     std::unique_ptr<Instruction> new_inst(new Instruction(
-        GetContext(), SpvOpExtInst, result_type, result_id, operands));
+        GetContext(), spv::Op::OpExtInst, result_type, result_id, operands));
     return AddInstruction(std::move(new_inst));
   }
 
diff --git a/source/opt/ir_context.cpp b/source/opt/ir_context.cpp
index 9116d4b..6de5ad0 100644
--- a/source/opt/ir_context.cpp
+++ b/source/opt/ir_context.cpp
@@ -199,7 +199,8 @@
   if (constant_mgr_ && IsConstantInst(inst->opcode())) {
     constant_mgr_->RemoveId(inst->result_id());
   }
-  if (inst->opcode() == SpvOpCapability || inst->opcode() == SpvOpExtension) {
+  if (inst->opcode() == spv::Op::OpCapability ||
+      inst->opcode() == spv::Op::OpExtension) {
     // We reset the feature manager, instead of updating it, because it is just
     // as much work.  We would have to remove all capabilities implied by this
     // capability that are not also implied by the remaining OpCapability
@@ -402,8 +403,8 @@
   if (AreAnalysesValid(kAnalysisDebugInfo)) {
     get_debug_info_mgr()->AnalyzeDebugInst(inst);
   }
-  if (id_to_name_ &&
-      (inst->opcode() == SpvOpName || inst->opcode() == SpvOpMemberName)) {
+  if (id_to_name_ && (inst->opcode() == spv::Op::OpName ||
+                      inst->opcode() == spv::Op::OpMemberName)) {
     id_to_name_->insert({inst->GetSingleWordInOperand(0), inst});
   }
 }
@@ -431,7 +432,7 @@
   const auto opcode = inst->opcode();
   const uint32_t id = inst->result_id();
   // Kill id of OpFunction from DebugFunction.
-  if (opcode == SpvOpFunction) {
+  if (opcode == spv::Op::OpFunction) {
     for (auto it = module()->ext_inst_debuginfo_begin();
          it != module()->ext_inst_debuginfo_end(); ++it) {
       if (it->GetOpenCL100DebugOpcode() != OpenCLDebugInfo100DebugFunction)
@@ -445,7 +446,7 @@
     }
   }
   // Kill id of OpVariable for global variable from DebugGlobalVariable.
-  if (opcode == SpvOpVariable || IsConstantInst(opcode)) {
+  if (opcode == spv::Op::OpVariable || IsConstantInst(opcode)) {
     for (auto it = module()->ext_inst_debuginfo_begin();
          it != module()->ext_inst_debuginfo_end(); ++it) {
       if (it->GetCommonDebugOpcode() != CommonDebugInfoDebugGlobalVariable)
@@ -461,255 +462,258 @@
 }
 
 void IRContext::AddCombinatorsForCapability(uint32_t capability) {
-  if (capability == SpvCapabilityShader) {
-    combinator_ops_[0].insert({SpvOpNop,
-                               SpvOpUndef,
-                               SpvOpConstant,
-                               SpvOpConstantTrue,
-                               SpvOpConstantFalse,
-                               SpvOpConstantComposite,
-                               SpvOpConstantSampler,
-                               SpvOpConstantNull,
-                               SpvOpTypeVoid,
-                               SpvOpTypeBool,
-                               SpvOpTypeInt,
-                               SpvOpTypeFloat,
-                               SpvOpTypeVector,
-                               SpvOpTypeMatrix,
-                               SpvOpTypeImage,
-                               SpvOpTypeSampler,
-                               SpvOpTypeSampledImage,
-                               SpvOpTypeAccelerationStructureNV,
-                               SpvOpTypeAccelerationStructureKHR,
-                               SpvOpTypeRayQueryKHR,
-                               SpvOpTypeArray,
-                               SpvOpTypeRuntimeArray,
-                               SpvOpTypeStruct,
-                               SpvOpTypeOpaque,
-                               SpvOpTypePointer,
-                               SpvOpTypeFunction,
-                               SpvOpTypeEvent,
-                               SpvOpTypeDeviceEvent,
-                               SpvOpTypeReserveId,
-                               SpvOpTypeQueue,
-                               SpvOpTypePipe,
-                               SpvOpTypeForwardPointer,
-                               SpvOpVariable,
-                               SpvOpImageTexelPointer,
-                               SpvOpLoad,
-                               SpvOpAccessChain,
-                               SpvOpInBoundsAccessChain,
-                               SpvOpArrayLength,
-                               SpvOpVectorExtractDynamic,
-                               SpvOpVectorInsertDynamic,
-                               SpvOpVectorShuffle,
-                               SpvOpCompositeConstruct,
-                               SpvOpCompositeExtract,
-                               SpvOpCompositeInsert,
-                               SpvOpCopyObject,
-                               SpvOpTranspose,
-                               SpvOpSampledImage,
-                               SpvOpImageSampleImplicitLod,
-                               SpvOpImageSampleExplicitLod,
-                               SpvOpImageSampleDrefImplicitLod,
-                               SpvOpImageSampleDrefExplicitLod,
-                               SpvOpImageSampleProjImplicitLod,
-                               SpvOpImageSampleProjExplicitLod,
-                               SpvOpImageSampleProjDrefImplicitLod,
-                               SpvOpImageSampleProjDrefExplicitLod,
-                               SpvOpImageFetch,
-                               SpvOpImageGather,
-                               SpvOpImageDrefGather,
-                               SpvOpImageRead,
-                               SpvOpImage,
-                               SpvOpImageQueryFormat,
-                               SpvOpImageQueryOrder,
-                               SpvOpImageQuerySizeLod,
-                               SpvOpImageQuerySize,
-                               SpvOpImageQueryLevels,
-                               SpvOpImageQuerySamples,
-                               SpvOpConvertFToU,
-                               SpvOpConvertFToS,
-                               SpvOpConvertSToF,
-                               SpvOpConvertUToF,
-                               SpvOpUConvert,
-                               SpvOpSConvert,
-                               SpvOpFConvert,
-                               SpvOpQuantizeToF16,
-                               SpvOpBitcast,
-                               SpvOpSNegate,
-                               SpvOpFNegate,
-                               SpvOpIAdd,
-                               SpvOpFAdd,
-                               SpvOpISub,
-                               SpvOpFSub,
-                               SpvOpIMul,
-                               SpvOpFMul,
-                               SpvOpUDiv,
-                               SpvOpSDiv,
-                               SpvOpFDiv,
-                               SpvOpUMod,
-                               SpvOpSRem,
-                               SpvOpSMod,
-                               SpvOpFRem,
-                               SpvOpFMod,
-                               SpvOpVectorTimesScalar,
-                               SpvOpMatrixTimesScalar,
-                               SpvOpVectorTimesMatrix,
-                               SpvOpMatrixTimesVector,
-                               SpvOpMatrixTimesMatrix,
-                               SpvOpOuterProduct,
-                               SpvOpDot,
-                               SpvOpIAddCarry,
-                               SpvOpISubBorrow,
-                               SpvOpUMulExtended,
-                               SpvOpSMulExtended,
-                               SpvOpAny,
-                               SpvOpAll,
-                               SpvOpIsNan,
-                               SpvOpIsInf,
-                               SpvOpLogicalEqual,
-                               SpvOpLogicalNotEqual,
-                               SpvOpLogicalOr,
-                               SpvOpLogicalAnd,
-                               SpvOpLogicalNot,
-                               SpvOpSelect,
-                               SpvOpIEqual,
-                               SpvOpINotEqual,
-                               SpvOpUGreaterThan,
-                               SpvOpSGreaterThan,
-                               SpvOpUGreaterThanEqual,
-                               SpvOpSGreaterThanEqual,
-                               SpvOpULessThan,
-                               SpvOpSLessThan,
-                               SpvOpULessThanEqual,
-                               SpvOpSLessThanEqual,
-                               SpvOpFOrdEqual,
-                               SpvOpFUnordEqual,
-                               SpvOpFOrdNotEqual,
-                               SpvOpFUnordNotEqual,
-                               SpvOpFOrdLessThan,
-                               SpvOpFUnordLessThan,
-                               SpvOpFOrdGreaterThan,
-                               SpvOpFUnordGreaterThan,
-                               SpvOpFOrdLessThanEqual,
-                               SpvOpFUnordLessThanEqual,
-                               SpvOpFOrdGreaterThanEqual,
-                               SpvOpFUnordGreaterThanEqual,
-                               SpvOpShiftRightLogical,
-                               SpvOpShiftRightArithmetic,
-                               SpvOpShiftLeftLogical,
-                               SpvOpBitwiseOr,
-                               SpvOpBitwiseXor,
-                               SpvOpBitwiseAnd,
-                               SpvOpNot,
-                               SpvOpBitFieldInsert,
-                               SpvOpBitFieldSExtract,
-                               SpvOpBitFieldUExtract,
-                               SpvOpBitReverse,
-                               SpvOpBitCount,
-                               SpvOpPhi,
-                               SpvOpImageSparseSampleImplicitLod,
-                               SpvOpImageSparseSampleExplicitLod,
-                               SpvOpImageSparseSampleDrefImplicitLod,
-                               SpvOpImageSparseSampleDrefExplicitLod,
-                               SpvOpImageSparseSampleProjImplicitLod,
-                               SpvOpImageSparseSampleProjExplicitLod,
-                               SpvOpImageSparseSampleProjDrefImplicitLod,
-                               SpvOpImageSparseSampleProjDrefExplicitLod,
-                               SpvOpImageSparseFetch,
-                               SpvOpImageSparseGather,
-                               SpvOpImageSparseDrefGather,
-                               SpvOpImageSparseTexelsResident,
-                               SpvOpImageSparseRead,
-                               SpvOpSizeOf});
+  spv::Capability cap = spv::Capability(capability);
+  if (cap == spv::Capability::Shader) {
+    combinator_ops_[0].insert(
+        {(uint32_t)spv::Op::OpNop,
+         (uint32_t)spv::Op::OpUndef,
+         (uint32_t)spv::Op::OpConstant,
+         (uint32_t)spv::Op::OpConstantTrue,
+         (uint32_t)spv::Op::OpConstantFalse,
+         (uint32_t)spv::Op::OpConstantComposite,
+         (uint32_t)spv::Op::OpConstantSampler,
+         (uint32_t)spv::Op::OpConstantNull,
+         (uint32_t)spv::Op::OpTypeVoid,
+         (uint32_t)spv::Op::OpTypeBool,
+         (uint32_t)spv::Op::OpTypeInt,
+         (uint32_t)spv::Op::OpTypeFloat,
+         (uint32_t)spv::Op::OpTypeVector,
+         (uint32_t)spv::Op::OpTypeMatrix,
+         (uint32_t)spv::Op::OpTypeImage,
+         (uint32_t)spv::Op::OpTypeSampler,
+         (uint32_t)spv::Op::OpTypeSampledImage,
+         (uint32_t)spv::Op::OpTypeAccelerationStructureNV,
+         (uint32_t)spv::Op::OpTypeAccelerationStructureKHR,
+         (uint32_t)spv::Op::OpTypeRayQueryKHR,
+         (uint32_t)spv::Op::OpTypeArray,
+         (uint32_t)spv::Op::OpTypeRuntimeArray,
+         (uint32_t)spv::Op::OpTypeStruct,
+         (uint32_t)spv::Op::OpTypeOpaque,
+         (uint32_t)spv::Op::OpTypePointer,
+         (uint32_t)spv::Op::OpTypeFunction,
+         (uint32_t)spv::Op::OpTypeEvent,
+         (uint32_t)spv::Op::OpTypeDeviceEvent,
+         (uint32_t)spv::Op::OpTypeReserveId,
+         (uint32_t)spv::Op::OpTypeQueue,
+         (uint32_t)spv::Op::OpTypePipe,
+         (uint32_t)spv::Op::OpTypeForwardPointer,
+         (uint32_t)spv::Op::OpVariable,
+         (uint32_t)spv::Op::OpImageTexelPointer,
+         (uint32_t)spv::Op::OpLoad,
+         (uint32_t)spv::Op::OpAccessChain,
+         (uint32_t)spv::Op::OpInBoundsAccessChain,
+         (uint32_t)spv::Op::OpArrayLength,
+         (uint32_t)spv::Op::OpVectorExtractDynamic,
+         (uint32_t)spv::Op::OpVectorInsertDynamic,
+         (uint32_t)spv::Op::OpVectorShuffle,
+         (uint32_t)spv::Op::OpCompositeConstruct,
+         (uint32_t)spv::Op::OpCompositeExtract,
+         (uint32_t)spv::Op::OpCompositeInsert,
+         (uint32_t)spv::Op::OpCopyObject,
+         (uint32_t)spv::Op::OpTranspose,
+         (uint32_t)spv::Op::OpSampledImage,
+         (uint32_t)spv::Op::OpImageSampleImplicitLod,
+         (uint32_t)spv::Op::OpImageSampleExplicitLod,
+         (uint32_t)spv::Op::OpImageSampleDrefImplicitLod,
+         (uint32_t)spv::Op::OpImageSampleDrefExplicitLod,
+         (uint32_t)spv::Op::OpImageSampleProjImplicitLod,
+         (uint32_t)spv::Op::OpImageSampleProjExplicitLod,
+         (uint32_t)spv::Op::OpImageSampleProjDrefImplicitLod,
+         (uint32_t)spv::Op::OpImageSampleProjDrefExplicitLod,
+         (uint32_t)spv::Op::OpImageFetch,
+         (uint32_t)spv::Op::OpImageGather,
+         (uint32_t)spv::Op::OpImageDrefGather,
+         (uint32_t)spv::Op::OpImageRead,
+         (uint32_t)spv::Op::OpImage,
+         (uint32_t)spv::Op::OpImageQueryFormat,
+         (uint32_t)spv::Op::OpImageQueryOrder,
+         (uint32_t)spv::Op::OpImageQuerySizeLod,
+         (uint32_t)spv::Op::OpImageQuerySize,
+         (uint32_t)spv::Op::OpImageQueryLevels,
+         (uint32_t)spv::Op::OpImageQuerySamples,
+         (uint32_t)spv::Op::OpConvertFToU,
+         (uint32_t)spv::Op::OpConvertFToS,
+         (uint32_t)spv::Op::OpConvertSToF,
+         (uint32_t)spv::Op::OpConvertUToF,
+         (uint32_t)spv::Op::OpUConvert,
+         (uint32_t)spv::Op::OpSConvert,
+         (uint32_t)spv::Op::OpFConvert,
+         (uint32_t)spv::Op::OpQuantizeToF16,
+         (uint32_t)spv::Op::OpBitcast,
+         (uint32_t)spv::Op::OpSNegate,
+         (uint32_t)spv::Op::OpFNegate,
+         (uint32_t)spv::Op::OpIAdd,
+         (uint32_t)spv::Op::OpFAdd,
+         (uint32_t)spv::Op::OpISub,
+         (uint32_t)spv::Op::OpFSub,
+         (uint32_t)spv::Op::OpIMul,
+         (uint32_t)spv::Op::OpFMul,
+         (uint32_t)spv::Op::OpUDiv,
+         (uint32_t)spv::Op::OpSDiv,
+         (uint32_t)spv::Op::OpFDiv,
+         (uint32_t)spv::Op::OpUMod,
+         (uint32_t)spv::Op::OpSRem,
+         (uint32_t)spv::Op::OpSMod,
+         (uint32_t)spv::Op::OpFRem,
+         (uint32_t)spv::Op::OpFMod,
+         (uint32_t)spv::Op::OpVectorTimesScalar,
+         (uint32_t)spv::Op::OpMatrixTimesScalar,
+         (uint32_t)spv::Op::OpVectorTimesMatrix,
+         (uint32_t)spv::Op::OpMatrixTimesVector,
+         (uint32_t)spv::Op::OpMatrixTimesMatrix,
+         (uint32_t)spv::Op::OpOuterProduct,
+         (uint32_t)spv::Op::OpDot,
+         (uint32_t)spv::Op::OpIAddCarry,
+         (uint32_t)spv::Op::OpISubBorrow,
+         (uint32_t)spv::Op::OpUMulExtended,
+         (uint32_t)spv::Op::OpSMulExtended,
+         (uint32_t)spv::Op::OpAny,
+         (uint32_t)spv::Op::OpAll,
+         (uint32_t)spv::Op::OpIsNan,
+         (uint32_t)spv::Op::OpIsInf,
+         (uint32_t)spv::Op::OpLogicalEqual,
+         (uint32_t)spv::Op::OpLogicalNotEqual,
+         (uint32_t)spv::Op::OpLogicalOr,
+         (uint32_t)spv::Op::OpLogicalAnd,
+         (uint32_t)spv::Op::OpLogicalNot,
+         (uint32_t)spv::Op::OpSelect,
+         (uint32_t)spv::Op::OpIEqual,
+         (uint32_t)spv::Op::OpINotEqual,
+         (uint32_t)spv::Op::OpUGreaterThan,
+         (uint32_t)spv::Op::OpSGreaterThan,
+         (uint32_t)spv::Op::OpUGreaterThanEqual,
+         (uint32_t)spv::Op::OpSGreaterThanEqual,
+         (uint32_t)spv::Op::OpULessThan,
+         (uint32_t)spv::Op::OpSLessThan,
+         (uint32_t)spv::Op::OpULessThanEqual,
+         (uint32_t)spv::Op::OpSLessThanEqual,
+         (uint32_t)spv::Op::OpFOrdEqual,
+         (uint32_t)spv::Op::OpFUnordEqual,
+         (uint32_t)spv::Op::OpFOrdNotEqual,
+         (uint32_t)spv::Op::OpFUnordNotEqual,
+         (uint32_t)spv::Op::OpFOrdLessThan,
+         (uint32_t)spv::Op::OpFUnordLessThan,
+         (uint32_t)spv::Op::OpFOrdGreaterThan,
+         (uint32_t)spv::Op::OpFUnordGreaterThan,
+         (uint32_t)spv::Op::OpFOrdLessThanEqual,
+         (uint32_t)spv::Op::OpFUnordLessThanEqual,
+         (uint32_t)spv::Op::OpFOrdGreaterThanEqual,
+         (uint32_t)spv::Op::OpFUnordGreaterThanEqual,
+         (uint32_t)spv::Op::OpShiftRightLogical,
+         (uint32_t)spv::Op::OpShiftRightArithmetic,
+         (uint32_t)spv::Op::OpShiftLeftLogical,
+         (uint32_t)spv::Op::OpBitwiseOr,
+         (uint32_t)spv::Op::OpBitwiseXor,
+         (uint32_t)spv::Op::OpBitwiseAnd,
+         (uint32_t)spv::Op::OpNot,
+         (uint32_t)spv::Op::OpBitFieldInsert,
+         (uint32_t)spv::Op::OpBitFieldSExtract,
+         (uint32_t)spv::Op::OpBitFieldUExtract,
+         (uint32_t)spv::Op::OpBitReverse,
+         (uint32_t)spv::Op::OpBitCount,
+         (uint32_t)spv::Op::OpPhi,
+         (uint32_t)spv::Op::OpImageSparseSampleImplicitLod,
+         (uint32_t)spv::Op::OpImageSparseSampleExplicitLod,
+         (uint32_t)spv::Op::OpImageSparseSampleDrefImplicitLod,
+         (uint32_t)spv::Op::OpImageSparseSampleDrefExplicitLod,
+         (uint32_t)spv::Op::OpImageSparseSampleProjImplicitLod,
+         (uint32_t)spv::Op::OpImageSparseSampleProjExplicitLod,
+         (uint32_t)spv::Op::OpImageSparseSampleProjDrefImplicitLod,
+         (uint32_t)spv::Op::OpImageSparseSampleProjDrefExplicitLod,
+         (uint32_t)spv::Op::OpImageSparseFetch,
+         (uint32_t)spv::Op::OpImageSparseGather,
+         (uint32_t)spv::Op::OpImageSparseDrefGather,
+         (uint32_t)spv::Op::OpImageSparseTexelsResident,
+         (uint32_t)spv::Op::OpImageSparseRead,
+         (uint32_t)spv::Op::OpSizeOf});
   }
 }
 
 void IRContext::AddCombinatorsForExtension(Instruction* extension) {
-  assert(extension->opcode() == SpvOpExtInstImport &&
+  assert(extension->opcode() == spv::Op::OpExtInstImport &&
          "Expecting an import of an extension's instruction set.");
   const std::string extension_name = extension->GetInOperand(0).AsString();
   if (extension_name == "GLSL.std.450") {
-    combinator_ops_[extension->result_id()] = {GLSLstd450Round,
-                                               GLSLstd450RoundEven,
-                                               GLSLstd450Trunc,
-                                               GLSLstd450FAbs,
-                                               GLSLstd450SAbs,
-                                               GLSLstd450FSign,
-                                               GLSLstd450SSign,
-                                               GLSLstd450Floor,
-                                               GLSLstd450Ceil,
-                                               GLSLstd450Fract,
-                                               GLSLstd450Radians,
-                                               GLSLstd450Degrees,
-                                               GLSLstd450Sin,
-                                               GLSLstd450Cos,
-                                               GLSLstd450Tan,
-                                               GLSLstd450Asin,
-                                               GLSLstd450Acos,
-                                               GLSLstd450Atan,
-                                               GLSLstd450Sinh,
-                                               GLSLstd450Cosh,
-                                               GLSLstd450Tanh,
-                                               GLSLstd450Asinh,
-                                               GLSLstd450Acosh,
-                                               GLSLstd450Atanh,
-                                               GLSLstd450Atan2,
-                                               GLSLstd450Pow,
-                                               GLSLstd450Exp,
-                                               GLSLstd450Log,
-                                               GLSLstd450Exp2,
-                                               GLSLstd450Log2,
-                                               GLSLstd450Sqrt,
-                                               GLSLstd450InverseSqrt,
-                                               GLSLstd450Determinant,
-                                               GLSLstd450MatrixInverse,
-                                               GLSLstd450ModfStruct,
-                                               GLSLstd450FMin,
-                                               GLSLstd450UMin,
-                                               GLSLstd450SMin,
-                                               GLSLstd450FMax,
-                                               GLSLstd450UMax,
-                                               GLSLstd450SMax,
-                                               GLSLstd450FClamp,
-                                               GLSLstd450UClamp,
-                                               GLSLstd450SClamp,
-                                               GLSLstd450FMix,
-                                               GLSLstd450IMix,
-                                               GLSLstd450Step,
-                                               GLSLstd450SmoothStep,
-                                               GLSLstd450Fma,
-                                               GLSLstd450FrexpStruct,
-                                               GLSLstd450Ldexp,
-                                               GLSLstd450PackSnorm4x8,
-                                               GLSLstd450PackUnorm4x8,
-                                               GLSLstd450PackSnorm2x16,
-                                               GLSLstd450PackUnorm2x16,
-                                               GLSLstd450PackHalf2x16,
-                                               GLSLstd450PackDouble2x32,
-                                               GLSLstd450UnpackSnorm2x16,
-                                               GLSLstd450UnpackUnorm2x16,
-                                               GLSLstd450UnpackHalf2x16,
-                                               GLSLstd450UnpackSnorm4x8,
-                                               GLSLstd450UnpackUnorm4x8,
-                                               GLSLstd450UnpackDouble2x32,
-                                               GLSLstd450Length,
-                                               GLSLstd450Distance,
-                                               GLSLstd450Cross,
-                                               GLSLstd450Normalize,
-                                               GLSLstd450FaceForward,
-                                               GLSLstd450Reflect,
-                                               GLSLstd450Refract,
-                                               GLSLstd450FindILsb,
-                                               GLSLstd450FindSMsb,
-                                               GLSLstd450FindUMsb,
-                                               GLSLstd450InterpolateAtCentroid,
-                                               GLSLstd450InterpolateAtSample,
-                                               GLSLstd450InterpolateAtOffset,
-                                               GLSLstd450NMin,
-                                               GLSLstd450NMax,
-                                               GLSLstd450NClamp};
+    combinator_ops_[extension->result_id()] = {
+        (uint32_t)GLSLstd450Round,
+        (uint32_t)GLSLstd450RoundEven,
+        (uint32_t)GLSLstd450Trunc,
+        (uint32_t)GLSLstd450FAbs,
+        (uint32_t)GLSLstd450SAbs,
+        (uint32_t)GLSLstd450FSign,
+        (uint32_t)GLSLstd450SSign,
+        (uint32_t)GLSLstd450Floor,
+        (uint32_t)GLSLstd450Ceil,
+        (uint32_t)GLSLstd450Fract,
+        (uint32_t)GLSLstd450Radians,
+        (uint32_t)GLSLstd450Degrees,
+        (uint32_t)GLSLstd450Sin,
+        (uint32_t)GLSLstd450Cos,
+        (uint32_t)GLSLstd450Tan,
+        (uint32_t)GLSLstd450Asin,
+        (uint32_t)GLSLstd450Acos,
+        (uint32_t)GLSLstd450Atan,
+        (uint32_t)GLSLstd450Sinh,
+        (uint32_t)GLSLstd450Cosh,
+        (uint32_t)GLSLstd450Tanh,
+        (uint32_t)GLSLstd450Asinh,
+        (uint32_t)GLSLstd450Acosh,
+        (uint32_t)GLSLstd450Atanh,
+        (uint32_t)GLSLstd450Atan2,
+        (uint32_t)GLSLstd450Pow,
+        (uint32_t)GLSLstd450Exp,
+        (uint32_t)GLSLstd450Log,
+        (uint32_t)GLSLstd450Exp2,
+        (uint32_t)GLSLstd450Log2,
+        (uint32_t)GLSLstd450Sqrt,
+        (uint32_t)GLSLstd450InverseSqrt,
+        (uint32_t)GLSLstd450Determinant,
+        (uint32_t)GLSLstd450MatrixInverse,
+        (uint32_t)GLSLstd450ModfStruct,
+        (uint32_t)GLSLstd450FMin,
+        (uint32_t)GLSLstd450UMin,
+        (uint32_t)GLSLstd450SMin,
+        (uint32_t)GLSLstd450FMax,
+        (uint32_t)GLSLstd450UMax,
+        (uint32_t)GLSLstd450SMax,
+        (uint32_t)GLSLstd450FClamp,
+        (uint32_t)GLSLstd450UClamp,
+        (uint32_t)GLSLstd450SClamp,
+        (uint32_t)GLSLstd450FMix,
+        (uint32_t)GLSLstd450IMix,
+        (uint32_t)GLSLstd450Step,
+        (uint32_t)GLSLstd450SmoothStep,
+        (uint32_t)GLSLstd450Fma,
+        (uint32_t)GLSLstd450FrexpStruct,
+        (uint32_t)GLSLstd450Ldexp,
+        (uint32_t)GLSLstd450PackSnorm4x8,
+        (uint32_t)GLSLstd450PackUnorm4x8,
+        (uint32_t)GLSLstd450PackSnorm2x16,
+        (uint32_t)GLSLstd450PackUnorm2x16,
+        (uint32_t)GLSLstd450PackHalf2x16,
+        (uint32_t)GLSLstd450PackDouble2x32,
+        (uint32_t)GLSLstd450UnpackSnorm2x16,
+        (uint32_t)GLSLstd450UnpackUnorm2x16,
+        (uint32_t)GLSLstd450UnpackHalf2x16,
+        (uint32_t)GLSLstd450UnpackSnorm4x8,
+        (uint32_t)GLSLstd450UnpackUnorm4x8,
+        (uint32_t)GLSLstd450UnpackDouble2x32,
+        (uint32_t)GLSLstd450Length,
+        (uint32_t)GLSLstd450Distance,
+        (uint32_t)GLSLstd450Cross,
+        (uint32_t)GLSLstd450Normalize,
+        (uint32_t)GLSLstd450FaceForward,
+        (uint32_t)GLSLstd450Reflect,
+        (uint32_t)GLSLstd450Refract,
+        (uint32_t)GLSLstd450FindILsb,
+        (uint32_t)GLSLstd450FindSMsb,
+        (uint32_t)GLSLstd450FindUMsb,
+        (uint32_t)GLSLstd450InterpolateAtCentroid,
+        (uint32_t)GLSLstd450InterpolateAtSample,
+        (uint32_t)GLSLstd450InterpolateAtOffset,
+        (uint32_t)GLSLstd450NMin,
+        (uint32_t)GLSLstd450NMax,
+        (uint32_t)GLSLstd450NClamp};
   } else {
     // Map the result id to the empty set.
     combinator_ops_[extension->result_id()];
@@ -717,8 +721,9 @@
 }
 
 void IRContext::InitializeCombinators() {
-  get_feature_mgr()->GetCapabilities()->ForEach(
-      [this](SpvCapability cap) { AddCombinatorsForCapability(cap); });
+  get_feature_mgr()->GetCapabilities()->ForEach([this](spv::Capability cap) {
+    AddCombinatorsForCapability(uint32_t(cap));
+  });
 
   for (auto& extension : module()->ext_inst_imports()) {
     AddCombinatorsForExtension(&extension);
@@ -728,8 +733,8 @@
 }
 
 void IRContext::RemoveFromIdToName(const Instruction* inst) {
-  if (id_to_name_ &&
-      (inst->opcode() == SpvOpName || inst->opcode() == SpvOpMemberName)) {
+  if (id_to_name_ && (inst->opcode() == spv::Op::OpName ||
+                      inst->opcode() == spv::Op::OpMemberName)) {
     auto range = id_to_name_->equal_range(inst->GetSingleWordInOperand(0));
     for (auto it = range.first; it != range.second; ++it) {
       if (it->second == inst) {
@@ -758,15 +763,17 @@
 
 uint32_t IRContext::FindBuiltinInputVar(uint32_t builtin) {
   for (auto& a : module_->annotations()) {
-    if (a.opcode() != SpvOpDecorate) continue;
-    if (a.GetSingleWordInOperand(kSpvDecorateDecorationInIdx) !=
-        SpvDecorationBuiltIn)
+    if (spv::Op(a.opcode()) != spv::Op::OpDecorate) continue;
+    if (spv::Decoration(a.GetSingleWordInOperand(
+            kSpvDecorateDecorationInIdx)) != spv::Decoration::BuiltIn)
       continue;
     if (a.GetSingleWordInOperand(kSpvDecorateBuiltinInIdx) != builtin) continue;
     uint32_t target_id = a.GetSingleWordInOperand(kSpvDecorateTargetIdInIdx);
     Instruction* b_var = get_def_use_mgr()->GetDef(target_id);
-    if (b_var->opcode() != SpvOpVariable) continue;
-    if (b_var->GetSingleWordInOperand(0) != SpvStorageClassInput) continue;
+    if (b_var->opcode() != spv::Op::OpVariable) continue;
+    if (spv::StorageClass(b_var->GetSingleWordInOperand(0)) !=
+        spv::StorageClass::Input)
+      continue;
     return target_id;
   }
   return 0;
@@ -802,39 +809,39 @@
     // TODO(greg-lunarg): Add support for all builtins
     analysis::TypeManager* type_mgr = get_type_mgr();
     analysis::Type* reg_type;
-    switch (builtin) {
-      case SpvBuiltInFragCoord: {
+    switch (spv::BuiltIn(builtin)) {
+      case spv::BuiltIn::FragCoord: {
         analysis::Float float_ty(32);
         analysis::Type* reg_float_ty = type_mgr->GetRegisteredType(&float_ty);
         analysis::Vector v4float_ty(reg_float_ty, 4);
         reg_type = type_mgr->GetRegisteredType(&v4float_ty);
         break;
       }
-      case SpvBuiltInVertexIndex:
-      case SpvBuiltInInstanceIndex:
-      case SpvBuiltInPrimitiveId:
-      case SpvBuiltInInvocationId:
-      case SpvBuiltInSubgroupLocalInvocationId: {
+      case spv::BuiltIn::VertexIndex:
+      case spv::BuiltIn::InstanceIndex:
+      case spv::BuiltIn::PrimitiveId:
+      case spv::BuiltIn::InvocationId:
+      case spv::BuiltIn::SubgroupLocalInvocationId: {
         analysis::Integer uint_ty(32, false);
         reg_type = type_mgr->GetRegisteredType(&uint_ty);
         break;
       }
-      case SpvBuiltInGlobalInvocationId:
-      case SpvBuiltInLaunchIdNV: {
+      case spv::BuiltIn::GlobalInvocationId:
+      case spv::BuiltIn::LaunchIdNV: {
         analysis::Integer uint_ty(32, false);
         analysis::Type* reg_uint_ty = type_mgr->GetRegisteredType(&uint_ty);
         analysis::Vector v3uint_ty(reg_uint_ty, 3);
         reg_type = type_mgr->GetRegisteredType(&v3uint_ty);
         break;
       }
-      case SpvBuiltInTessCoord: {
+      case spv::BuiltIn::TessCoord: {
         analysis::Float float_ty(32);
         analysis::Type* reg_float_ty = type_mgr->GetRegisteredType(&float_ty);
         analysis::Vector v3float_ty(reg_float_ty, 3);
         reg_type = type_mgr->GetRegisteredType(&v3float_ty);
         break;
       }
-      case SpvBuiltInSubgroupLtMask: {
+      case spv::BuiltIn::SubgroupLtMask: {
         analysis::Integer uint_ty(32, false);
         analysis::Type* reg_uint_ty = type_mgr->GetRegisteredType(&uint_ty);
         analysis::Vector v4uint_ty(reg_uint_ty, 4);
@@ -848,17 +855,17 @@
     }
     uint32_t type_id = type_mgr->GetTypeInstruction(reg_type);
     uint32_t varTyPtrId =
-        type_mgr->FindPointerToType(type_id, SpvStorageClassInput);
+        type_mgr->FindPointerToType(type_id, spv::StorageClass::Input);
     // TODO(1841): Handle id overflow.
     var_id = TakeNextId();
     std::unique_ptr<Instruction> newVarOp(
-        new Instruction(this, SpvOpVariable, varTyPtrId, var_id,
+        new Instruction(this, spv::Op::OpVariable, varTyPtrId, var_id,
                         {{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
-                          {SpvStorageClassInput}}}));
+                          {uint32_t(spv::StorageClass::Input)}}}));
     get_def_use_mgr()->AnalyzeInstDefUse(&*newVarOp);
     module()->AddGlobalValue(std::move(newVarOp));
-    get_decoration_mgr()->AddDecorationVal(var_id, SpvDecorationBuiltIn,
-                                           builtin);
+    get_decoration_mgr()->AddDecorationVal(
+        var_id, uint32_t(spv::Decoration::BuiltIn), builtin);
     AddVarToEntryPoints(var_id);
   }
   builtin_var_id_map_[builtin] = var_id;
@@ -868,7 +875,7 @@
 void IRContext::AddCalls(const Function* func, std::queue<uint32_t>* todo) {
   for (auto bi = func->begin(); bi != func->end(); ++bi)
     for (auto ii = bi->begin(); ii != bi->end(); ++ii)
-      if (ii->opcode() == SpvOpFunctionCall)
+      if (ii->opcode() == spv::Op::OpFunctionCall)
         todo->push(ii->GetSingleWordInOperand(0));
 }
 
@@ -893,12 +900,12 @@
   for (auto& a : annotations()) {
     // TODO: Handle group decorations as well.  Currently not generate by any
     // front-end, but could be coming.
-    if (a.opcode() == SpvOp::SpvOpDecorate) {
-      if (a.GetSingleWordOperand(1) ==
-          SpvDecoration::SpvDecorationLinkageAttributes) {
+    if (a.opcode() == spv::Op::OpDecorate) {
+      if (spv::Decoration(a.GetSingleWordOperand(1)) ==
+          spv::Decoration::LinkageAttributes) {
         uint32_t lastOperand = a.NumOperands() - 1;
-        if (a.GetSingleWordOperand(lastOperand) ==
-            SpvLinkageType::SpvLinkageTypeExport) {
+        if (spv::LinkageType(a.GetSingleWordOperand(lastOperand)) ==
+            spv::LinkageType::Export) {
           uint32_t id = a.GetSingleWordOperand(0);
           if (GetFunction(id)) {
             roots.push(id);
@@ -1063,10 +1070,10 @@
       ->Dominates(enclosing_function->entry().get(), &bb);
 }
 
-SpvExecutionModel IRContext::GetStage() {
+spv::ExecutionModel IRContext::GetStage() {
   const auto& entry_points = module()->entry_points();
   if (entry_points.empty()) {
-    return SpvExecutionModelMax;
+    return spv::ExecutionModel::Max;
   }
 
   uint32_t stage = entry_points.begin()->GetSingleWordInOperand(
@@ -1080,7 +1087,7 @@
     EmitErrorMessage("Mixed stage shader module not supported", &(*it));
   }
 
-  return static_cast<SpvExecutionModel>(stage);
+  return static_cast<spv::ExecutionModel>(stage);
 }
 
 }  // namespace opt
diff --git a/source/opt/ir_context.h b/source/opt/ir_context.h
index 9dee84e..f5e513d 100644
--- a/source/opt/ir_context.h
+++ b/source/opt/ir_context.h
@@ -203,7 +203,7 @@
   inline IteratorRange<Module::const_inst_iterator> ext_inst_debuginfo() const;
 
   // Add |capability| to the module, if it is not already enabled.
-  inline void AddCapability(SpvCapability capability);
+  inline void AddCapability(spv::Capability capability);
 
   // Appends a capability instruction to this module.
   inline void AddCapability(std::unique_ptr<Instruction>&& c);
@@ -489,11 +489,11 @@
     const uint32_t kExtInstSetIdInIndx = 0;
     const uint32_t kExtInstInstructionInIndx = 1;
 
-    if (inst->opcode() != SpvOpExtInst) {
-      return combinator_ops_[0].count(inst->opcode()) != 0;
+    if (inst->opcode() != spv::Op::OpExtInst) {
+      return combinator_ops_[0].count(uint32_t(inst->opcode())) != 0;
     } else {
       uint32_t set = inst->GetSingleWordInOperand(kExtInstSetIdInIndx);
-      uint32_t op = inst->GetSingleWordInOperand(kExtInstInstructionInIndx);
+      auto op = inst->GetSingleWordInOperand(kExtInstInstructionInIndx);
       return combinator_ops_[set].count(op) != 0;
     }
   }
@@ -602,7 +602,7 @@
   }
 
   Function* GetFunction(Instruction* inst) {
-    if (inst->opcode() != SpvOpFunction) {
+    if (inst->opcode() != spv::Op::OpFunction) {
       return nullptr;
     }
     return GetFunction(inst->result_id());
@@ -638,7 +638,7 @@
 
   // Return the stage of the module. Will generate error if entry points don't
   // all have the same stage.
-  SpvExecutionModel GetStage();
+  spv::ExecutionModel GetStage();
 
  private:
   // Builds the def-use manager from scratch, even if it was already valid.
@@ -1038,10 +1038,10 @@
   return ((const Module*)module_.get())->ext_inst_debuginfo();
 }
 
-void IRContext::AddCapability(SpvCapability capability) {
+void IRContext::AddCapability(spv::Capability capability) {
   if (!get_feature_mgr()->HasCapability(capability)) {
     std::unique_ptr<Instruction> capability_inst(new Instruction(
-        this, SpvOpCapability, 0, 0,
+        this, spv::Op::OpCapability, 0, 0,
         {{SPV_OPERAND_TYPE_CAPABILITY, {static_cast<uint32_t>(capability)}}}));
     AddCapability(std::move(capability_inst));
   }
@@ -1051,7 +1051,7 @@
   AddCombinatorsForCapability(c->GetSingleWordInOperand(0));
   if (feature_mgr_ != nullptr) {
     feature_mgr_->AddCapability(
-        static_cast<SpvCapability>(c->GetSingleWordInOperand(0)));
+        static_cast<spv::Capability>(c->GetSingleWordInOperand(0)));
   }
   if (AreAnalysesValid(kAnalysisDefUse)) {
     get_def_use_mgr()->AnalyzeInstDefUse(c.get());
@@ -1062,7 +1062,7 @@
 void IRContext::AddExtension(const std::string& ext_name) {
   std::vector<uint32_t> ext_words = spvtools::utils::MakeVector(ext_name);
   AddExtension(std::unique_ptr<Instruction>(
-      new Instruction(this, SpvOpExtension, 0u, 0u,
+      new Instruction(this, spv::Op::OpExtension, 0u, 0u,
                       {{SPV_OPERAND_TYPE_LITERAL_STRING, ext_words}})));
 }
 
@@ -1079,7 +1079,7 @@
 void IRContext::AddExtInstImport(const std::string& name) {
   std::vector<uint32_t> ext_words = spvtools::utils::MakeVector(name);
   AddExtInstImport(std::unique_ptr<Instruction>(
-      new Instruction(this, SpvOpExtInstImport, 0u, TakeNextId(),
+      new Instruction(this, spv::Op::OpExtInstImport, 0u, TakeNextId(),
                       {{SPV_OPERAND_TYPE_LITERAL_STRING, ext_words}})));
 }
 
@@ -1112,7 +1112,8 @@
 
 void IRContext::AddDebug2Inst(std::unique_ptr<Instruction>&& d) {
   if (AreAnalysesValid(kAnalysisNameMap)) {
-    if (d->opcode() == SpvOpName || d->opcode() == SpvOpMemberName) {
+    if (d->opcode() == spv::Op::OpName ||
+        d->opcode() == spv::Op::OpMemberName) {
       // OpName and OpMemberName do not have result-ids. The target of the
       // instruction is at InOperand index 0.
       id_to_name_->insert({d->GetSingleWordInOperand(0), d.get()});
@@ -1175,8 +1176,8 @@
 void IRContext::BuildIdToNameMap() {
   id_to_name_ = MakeUnique<std::multimap<uint32_t, Instruction*>>();
   for (Instruction& debug_inst : debugs2()) {
-    if (debug_inst.opcode() == SpvOpMemberName ||
-        debug_inst.opcode() == SpvOpName) {
+    if (debug_inst.opcode() == spv::Op::OpMemberName ||
+        debug_inst.opcode() == spv::Op::OpName) {
       id_to_name_->insert({debug_inst.GetSingleWordInOperand(0), &debug_inst});
     }
   }
@@ -1199,7 +1200,7 @@
   auto result = id_to_name_->equal_range(struct_type_id);
   for (auto i = result.first; i != result.second; ++i) {
     auto* name_instr = i->second;
-    if (name_instr->opcode() == SpvOpMemberName &&
+    if (name_instr->opcode() == spv::Op::OpMemberName &&
         name_instr->GetSingleWordInOperand(1) == index) {
       return name_instr;
     }
diff --git a/source/opt/ir_loader.cpp b/source/opt/ir_loader.cpp
index 734ad55..4b78ddd 100644
--- a/source/opt/ir_loader.cpp
+++ b/source/opt/ir_loader.cpp
@@ -39,9 +39,9 @@
       last_dbg_scope_(kNoDebugScope, kNoInlinedAt) {}
 
 bool IsLineInst(const spv_parsed_instruction_t* inst) {
-  const auto opcode = static_cast<SpvOp>(inst->opcode);
+  const auto opcode = static_cast<spv::Op>(inst->opcode);
   if (IsOpLineInst(opcode)) return true;
-  if (opcode != SpvOpExtInst) return false;
+  if (opcode != spv::Op::OpExtInst) return false;
   if (inst->ext_inst_type != SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100)
     return false;
   const uint32_t ext_inst_index = inst->words[kExtInstSetIndex];
@@ -63,8 +63,9 @@
   // If it is a DebugScope or DebugNoScope of debug extension, we do not
   // create a new instruction, but simply keep the information in
   // struct DebugScope.
-  const auto opcode = static_cast<SpvOp>(inst->opcode);
-  if (opcode == SpvOpExtInst && spvExtInstIsDebugInfo(inst->ext_inst_type)) {
+  const auto opcode = static_cast<spv::Op>(inst->opcode);
+  if (opcode == spv::Op::OpExtInst &&
+      spvExtInstIsDebugInfo(inst->ext_inst_type)) {
     const uint32_t ext_inst_index = inst->words[kExtInstSetIndex];
     if (inst->ext_inst_type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100 ||
         inst->ext_inst_type ==
@@ -130,13 +131,13 @@
 
   // Handle function and basic block boundaries first, then normal
   // instructions.
-  if (opcode == SpvOpFunction) {
+  if (opcode == spv::Op::OpFunction) {
     if (function_ != nullptr) {
       Error(consumer_, src, loc, "function inside function");
       return false;
     }
     function_ = MakeUnique<Function>(std::move(spv_inst));
-  } else if (opcode == SpvOpFunctionEnd) {
+  } else if (opcode == spv::Op::OpFunctionEnd) {
     if (function_ == nullptr) {
       Error(consumer_, src, loc,
             "OpFunctionEnd without corresponding OpFunction");
@@ -149,7 +150,7 @@
     function_->SetFunctionEnd(std::move(spv_inst));
     module_->AddFunction(std::move(function_));
     function_ = nullptr;
-  } else if (opcode == SpvOpLabel) {
+  } else if (opcode == spv::Op::OpLabel) {
     if (function_ == nullptr) {
       Error(consumer_, src, loc, "OpLabel outside function");
       return false;
@@ -179,20 +180,20 @@
   } else {
     if (function_ == nullptr) {  // Outside function definition
       SPIRV_ASSERT(consumer_, block_ == nullptr);
-      if (opcode == SpvOpCapability) {
+      if (opcode == spv::Op::OpCapability) {
         module_->AddCapability(std::move(spv_inst));
-      } else if (opcode == SpvOpExtension) {
+      } else if (opcode == spv::Op::OpExtension) {
         module_->AddExtension(std::move(spv_inst));
-      } else if (opcode == SpvOpExtInstImport) {
+      } else if (opcode == spv::Op::OpExtInstImport) {
         module_->AddExtInstImport(std::move(spv_inst));
-      } else if (opcode == SpvOpMemoryModel) {
+      } else if (opcode == spv::Op::OpMemoryModel) {
         module_->SetMemoryModel(std::move(spv_inst));
-      } else if (opcode == SpvOpSamplerImageAddressingModeNV) {
+      } else if (opcode == spv::Op::OpSamplerImageAddressingModeNV) {
         module_->SetSampledImageAddressMode(std::move(spv_inst));
-      } else if (opcode == SpvOpEntryPoint) {
+      } else if (opcode == spv::Op::OpEntryPoint) {
         module_->AddEntryPoint(std::move(spv_inst));
-      } else if (opcode == SpvOpExecutionMode ||
-                 opcode == SpvOpExecutionModeId) {
+      } else if (opcode == spv::Op::OpExecutionMode ||
+                 opcode == spv::Op::OpExecutionModeId) {
         module_->AddExecutionMode(std::move(spv_inst));
       } else if (IsDebug1Inst(opcode)) {
         module_->AddDebug1Inst(std::move(spv_inst));
@@ -204,13 +205,13 @@
         module_->AddAnnotationInst(std::move(spv_inst));
       } else if (IsTypeInst(opcode)) {
         module_->AddType(std::move(spv_inst));
-      } else if (IsConstantInst(opcode) || opcode == SpvOpVariable ||
-                 opcode == SpvOpUndef) {
+      } else if (IsConstantInst(opcode) || opcode == spv::Op::OpVariable ||
+                 opcode == spv::Op::OpUndef) {
         module_->AddGlobalValue(std::move(spv_inst));
-      } else if (opcode == SpvOpExtInst &&
+      } else if (opcode == spv::Op::OpExtInst &&
                  spvExtInstIsDebugInfo(inst->ext_inst_type)) {
         module_->AddExtInstDebugInfo(std::move(spv_inst));
-      } else if (opcode == SpvOpExtInst &&
+      } else if (opcode == spv::Op::OpExtInst &&
                  spvExtInstIsNonSemantic(inst->ext_inst_type)) {
         // If there are no functions, add the non-semantic instructions to the
         // global values. Otherwise append it to the list of the last function.
@@ -229,11 +230,11 @@
         return false;
       }
     } else {
-      if (opcode == SpvOpLoopMerge || opcode == SpvOpSelectionMerge)
+      if (opcode == spv::Op::OpLoopMerge || opcode == spv::Op::OpSelectionMerge)
         last_dbg_scope_ = DebugScope(kNoDebugScope, kNoInlinedAt);
       if (last_dbg_scope_.GetLexicalScope() != kNoDebugScope)
         spv_inst->SetDebugScope(last_dbg_scope_);
-      if (opcode == SpvOpExtInst &&
+      if (opcode == spv::Op::OpExtInst &&
           spvExtInstIsDebugInfo(inst->ext_inst_type)) {
         const uint32_t ext_inst_index = inst->words[kExtInstSetIndex];
         if (inst->ext_inst_type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100) {
@@ -322,7 +323,7 @@
         }
       } else {
         if (block_ == nullptr) {  // Inside function but outside blocks
-          if (opcode != SpvOpFunctionParameter) {
+          if (opcode != spv::Op::OpFunctionParameter) {
             Errorf(consumer_, src, loc,
                    "Non-OpFunctionParameter (opcode: %d) found inside "
                    "function but outside basic block",
diff --git a/source/opt/licm_pass.cpp b/source/opt/licm_pass.cpp
index 82851fd..514518b 100644
--- a/source/opt/licm_pass.cpp
+++ b/source/opt/licm_pass.cpp
@@ -126,8 +126,8 @@
   }
   Instruction* insertion_point = &*pre_header_bb->tail();
   Instruction* previous_node = insertion_point->PreviousNode();
-  if (previous_node && (previous_node->opcode() == SpvOpLoopMerge ||
-                        previous_node->opcode() == SpvOpSelectionMerge)) {
+  if (previous_node && (previous_node->opcode() == spv::Op::OpLoopMerge ||
+                        previous_node->opcode() == spv::Op::OpSelectionMerge)) {
     insertion_point = previous_node;
   }
 
diff --git a/source/opt/liveness.cpp b/source/opt/liveness.cpp
index 08b1c6e..239ce67 100644
--- a/source/opt/liveness.cpp
+++ b/source/opt/liveness.cpp
@@ -39,10 +39,10 @@
   live_locs_.clear();
   live_builtins_.clear();
   // Mark all builtins live for frag shader.
-  if (context()->GetStage() == SpvExecutionModelFragment) {
-    live_builtins_.insert(SpvBuiltInPointSize);
-    live_builtins_.insert(SpvBuiltInClipDistance);
-    live_builtins_.insert(SpvBuiltInCullDistance);
+  if (context()->GetStage() == spv::ExecutionModel::Fragment) {
+    live_builtins_.insert(uint32_t(spv::BuiltIn::PointSize));
+    live_builtins_.insert(uint32_t(spv::BuiltIn::ClipDistance));
+    live_builtins_.insert(uint32_t(spv::BuiltIn::CullDistance));
   }
 }
 
@@ -50,8 +50,10 @@
   // There are only three builtins that can be analyzed and removed between
   // two stages: PointSize, ClipDistance and CullDistance. All others are
   // always consumed implicitly by the downstream stage.
-  return bi == SpvBuiltInPointSize || bi == SpvBuiltInClipDistance ||
-         bi == SpvBuiltInCullDistance;
+  const auto builtin = spv::BuiltIn(bi);
+  return builtin == spv::BuiltIn::PointSize ||
+         builtin == spv::BuiltIn::ClipDistance ||
+         builtin == spv::BuiltIn::CullDistance;
 }
 
 bool LivenessManager::AnalyzeBuiltIn(uint32_t id) {
@@ -59,16 +61,16 @@
   bool saw_builtin = false;
   // Analyze all builtin decorations of |id|.
   (void)deco_mgr->ForEachDecoration(
-      id, SpvDecorationBuiltIn,
+      id, uint32_t(spv::Decoration::BuiltIn),
       [this, &saw_builtin](const Instruction& deco_inst) {
         saw_builtin = true;
         // No need to process builtins in frag shader. All assumed used.
-        if (context()->GetStage() == SpvExecutionModelFragment) return;
-        uint32_t builtin = SpvBuiltInMax;
-        if (deco_inst.opcode() == SpvOpDecorate)
+        if (context()->GetStage() == spv::ExecutionModel::Fragment) return;
+        uint32_t builtin = uint32_t(spv::BuiltIn::Max);
+        if (deco_inst.opcode() == spv::Op::OpDecorate)
           builtin =
               deco_inst.GetSingleWordInOperand(kOpDecorateBuiltInLiteralInIdx);
-        else if (deco_inst.opcode() == SpvOpMemberDecorate)
+        else if (deco_inst.opcode() == spv::Op::OpMemberDecorate)
           builtin = deco_inst.GetSingleWordInOperand(
               kOpDecorateMemberBuiltInLiteralInIdx);
         else
@@ -173,10 +175,10 @@
   // first array index does not contribute to offset.
   auto stage = context()->GetStage();
   bool skip_first_index = false;
-  if ((input && (stage == SpvExecutionModelTessellationControl ||
-                 stage == SpvExecutionModelTessellationEvaluation ||
-                 stage == SpvExecutionModelGeometry)) ||
-      (!input && stage == SpvExecutionModelTessellationControl))
+  if ((input && (stage == spv::ExecutionModel::TessellationControl ||
+                 stage == spv::ExecutionModel::TessellationEvaluation ||
+                 stage == spv::ExecutionModel::Geometry)) ||
+      (!input && stage == spv::ExecutionModel::TessellationControl))
     skip_first_index = !is_patch;
   uint32_t ocnt = 0;
   ac->WhileEachInOperand([this, &ocnt, def_use_mgr, type_mgr, deco_mgr,
@@ -193,7 +195,7 @@
       }
       // If any non-constant index, mark the entire current object and return.
       auto idx_inst = def_use_mgr->GetDef(*opnd);
-      if (idx_inst->opcode() != SpvOpConstant) return false;
+      if (idx_inst->opcode() != spv::Op::OpConstant) return false;
       // If current type is struct, look for location decoration on member and
       // reset offset if found.
       auto index = idx_inst->GetSingleWordInOperand(0);
@@ -202,9 +204,9 @@
         uint32_t loc = 0;
         auto str_type_id = type_mgr->GetId(str_type);
         bool no_mem_loc = deco_mgr->WhileEachDecoration(
-            str_type_id, SpvDecorationLocation,
+            str_type_id, uint32_t(spv::Decoration::Location),
             [&loc, index, no_loc](const Instruction& deco) {
-              assert(deco.opcode() == SpvOpMemberDecorate &&
+              assert(deco.opcode() == spv::Op::OpMemberDecorate &&
                      "unexpected decoration");
               if (deco.GetSingleWordInOperand(kOpDecorateMemberMemberInIdx) ==
                   index) {
@@ -239,15 +241,16 @@
   uint32_t loc = 0;
   auto var_id = var->result_id();
   bool no_loc = deco_mgr->WhileEachDecoration(
-      var_id, SpvDecorationLocation, [&loc](const Instruction& deco) {
-        assert(deco.opcode() == SpvOpDecorate && "unexpected decoration");
+      var_id, uint32_t(spv::Decoration::Location),
+      [&loc](const Instruction& deco) {
+        assert(deco.opcode() == spv::Op::OpDecorate && "unexpected decoration");
         loc = deco.GetSingleWordInOperand(kDecorationLocationInIdx);
         return false;
       });
   // Find patch decoration if present
   bool is_patch = !deco_mgr->WhileEachDecoration(
-      var_id, SpvDecorationPatch, [](const Instruction& deco) {
-        if (deco.opcode() != SpvOpDecorate)
+      var_id, uint32_t(spv::Decoration::Patch), [](const Instruction& deco) {
+        if (deco.opcode() != spv::Op::OpDecorate)
           assert(false && "unexpected decoration");
         return false;
       });
@@ -255,14 +258,14 @@
   auto ptr_type = type_mgr->GetType(var->type_id())->AsPointer();
   assert(ptr_type && "unexpected var type");
   auto var_type = ptr_type->pointee_type();
-  if (ref->opcode() == SpvOpLoad) {
+  if (ref->opcode() == spv::Op::OpLoad) {
     assert(!no_loc && "missing input variable location");
     MarkLocsLive(loc, GetLocSize(var_type));
     return;
   }
   // Mark just those locations indicated by access chain
-  assert((ref->opcode() == SpvOpAccessChain ||
-          ref->opcode() == SpvOpInBoundsAccessChain) &&
+  assert((ref->opcode() == spv::Op::OpAccessChain ||
+          ref->opcode() == spv::Op::OpInBoundsAccessChain) &&
          "unexpected use of input variable");
   // Traverse access chain, compute location offset and type of reference
   // through constant indices and mark those locs live. Assert if no location
@@ -280,12 +283,12 @@
   analysis::TypeManager* type_mgr = context()->get_type_mgr();
   // Process all input variables
   for (auto& var : context()->types_values()) {
-    if (var.opcode() != SpvOpVariable) {
+    if (var.opcode() != spv::Op::OpVariable) {
       continue;
     }
     analysis::Type* var_type = type_mgr->GetType(var.type_id());
     analysis::Pointer* ptr_type = var_type->AsPointer();
-    if (ptr_type->storage_class() != SpvStorageClassInput) {
+    if (ptr_type->storage_class() != spv::StorageClass::Input) {
       continue;
     }
     // If var is builtin, mark live if analyzed and continue to next variable
@@ -308,8 +311,10 @@
     // Mark all used locations of var live
     def_use_mgr->ForEachUser(var_id, [this, &var](Instruction* user) {
       auto op = user->opcode();
-      if (op == SpvOpEntryPoint || op == SpvOpName || op == SpvOpDecorate)
+      if (op == spv::Op::OpEntryPoint || op == spv::Op::OpName ||
+          op == spv::Op::OpDecorate) {
         return;
+      }
       MarkRefLive(user, &var);
     });
   }
diff --git a/source/opt/local_access_chain_convert_pass.cpp b/source/opt/local_access_chain_convert_pass.cpp
index d11682f..ae21c2b 100644
--- a/source/opt/local_access_chain_convert_pass.cpp
+++ b/source/opt/local_access_chain_convert_pass.cpp
@@ -32,7 +32,7 @@
 }  // anonymous namespace
 
 void LocalAccessChainConvertPass::BuildAndAppendInst(
-    SpvOp opcode, uint32_t typeId, uint32_t resultId,
+    spv::Op opcode, uint32_t typeId, uint32_t resultId,
     const std::vector<Operand>& in_opnds,
     std::vector<std::unique_ptr<Instruction>>* newInsts) {
   std::unique_ptr<Instruction> newInst(
@@ -51,9 +51,9 @@
 
   *varId = ptrInst->GetSingleWordInOperand(kAccessChainPtrIdInIdx);
   const Instruction* varInst = get_def_use_mgr()->GetDef(*varId);
-  assert(varInst->opcode() == SpvOpVariable);
+  assert(varInst->opcode() == spv::Op::OpVariable);
   *varPteTypeId = GetPointeeTypeId(varInst);
-  BuildAndAppendInst(SpvOpLoad, *varPteTypeId, ldResultId,
+  BuildAndAppendInst(spv::Op::OpLoad, *varPteTypeId, ldResultId,
                      {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {*varId}}},
                      newInsts);
   return ldResultId;
@@ -108,7 +108,8 @@
 
   new_inst[0]->UpdateDebugInfoFrom(original_load);
   context()->get_decoration_mgr()->CloneDecorations(
-      original_load->result_id(), ldResultId, {SpvDecorationRelaxedPrecision});
+      original_load->result_id(), ldResultId,
+      {spv::Decoration::RelaxedPrecision});
   original_load->InsertBefore(std::move(new_inst));
   context()->get_debug_info_mgr()->AnalyzeDebugInst(
       original_load->PreviousNode());
@@ -123,7 +124,7 @@
   new_operands.emplace_back(
       Operand({spv_operand_type_t::SPV_OPERAND_TYPE_ID, {ldResultId}}));
   AppendConstantOperands(address_inst, &new_operands);
-  original_load->SetOpcode(SpvOpCompositeExtract);
+  original_load->SetOpcode(spv::Op::OpCompositeExtract);
   original_load->ReplaceOperands(new_operands);
   context()->UpdateDefUse(original_load);
   return true;
@@ -136,7 +137,7 @@
     // An access chain with no indices is essentially a copy.  However, we still
     // have to create a new store because the old ones will be deleted.
     BuildAndAppendInst(
-        SpvOpStore, 0, 0,
+        spv::Op::OpStore, 0, 0,
         {{spv_operand_type_t::SPV_OPERAND_TYPE_ID,
           {ptrInst->GetSingleWordInOperand(kAccessChainPtrIdInIdx)}},
          {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {valId}}},
@@ -154,7 +155,7 @@
   }
 
   context()->get_decoration_mgr()->CloneDecorations(
-      varId, ldResultId, {SpvDecorationRelaxedPrecision});
+      varId, ldResultId, {spv::Decoration::RelaxedPrecision});
 
   // Build and append Insert
   const uint32_t insResultId = TakeNextId();
@@ -165,14 +166,14 @@
       {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {valId}},
       {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {ldResultId}}};
   AppendConstantOperands(ptrInst, &ins_in_opnds);
-  BuildAndAppendInst(SpvOpCompositeInsert, varPteTypeId, insResultId,
+  BuildAndAppendInst(spv::Op::OpCompositeInsert, varPteTypeId, insResultId,
                      ins_in_opnds, newInsts);
 
   context()->get_decoration_mgr()->CloneDecorations(
-      varId, insResultId, {SpvDecorationRelaxedPrecision});
+      varId, insResultId, {spv::Decoration::RelaxedPrecision});
 
   // Build and append Store
-  BuildAndAppendInst(SpvOpStore, 0, 0,
+  BuildAndAppendInst(spv::Op::OpStore, 0, 0,
                      {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {varId}},
                       {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {insResultId}}},
                      newInsts);
@@ -185,7 +186,7 @@
   return acp->WhileEachInId([&inIdx, this](const uint32_t* tid) {
     if (inIdx > 0) {
       Instruction* opInst = get_def_use_mgr()->GetDef(*tid);
-      if (opInst->opcode() != SpvOpConstant) return false;
+      if (opInst->opcode() != spv::Op::OpConstant) return false;
       const auto* index =
           context()->get_constant_mgr()->GetConstantFromInst(opInst);
       int64_t index_value = index->GetSignExtendedValue();
@@ -204,13 +205,13 @@
             user->GetCommonDebugOpcode() == CommonDebugInfoDebugDeclare) {
           return true;
         }
-        SpvOp op = user->opcode();
-        if (IsNonPtrAccessChain(op) || op == SpvOpCopyObject) {
+        spv::Op op = user->opcode();
+        if (IsNonPtrAccessChain(op) || op == spv::Op::OpCopyObject) {
           if (!HasOnlySupportedRefs(user->result_id())) {
             return false;
           }
-        } else if (op != SpvOpStore && op != SpvOpLoad && op != SpvOpName &&
-                   !IsNonTypeDecorate(op)) {
+        } else if (op != spv::Op::OpStore && op != spv::Op::OpLoad &&
+                   op != spv::Op::OpName && !IsNonTypeDecorate(op)) {
           return false;
         }
         return true;
@@ -225,12 +226,12 @@
   for (auto bi = func->begin(); bi != func->end(); ++bi) {
     for (auto ii = bi->begin(); ii != bi->end(); ++ii) {
       switch (ii->opcode()) {
-        case SpvOpStore:
-        case SpvOpLoad: {
+        case spv::Op::OpStore:
+        case spv::Op::OpLoad: {
           uint32_t varId;
           Instruction* ptrInst = GetPtr(&*ii, &varId);
           if (!IsTargetVar(varId)) break;
-          const SpvOp op = ptrInst->opcode();
+          const spv::Op op = ptrInst->opcode();
           // Rule out variables with non-supported refs eg function calls
           if (!HasOnlySupportedRefs(varId)) {
             seen_non_target_vars_.insert(varId);
@@ -276,7 +277,7 @@
     std::vector<Instruction*> dead_instructions;
     for (auto ii = bi->begin(); ii != bi->end(); ++ii) {
       switch (ii->opcode()) {
-        case SpvOpLoad: {
+        case spv::Op::OpLoad: {
           uint32_t varId;
           Instruction* ptrInst = GetPtr(&*ii, &varId);
           if (!IsNonPtrAccessChain(ptrInst->opcode())) break;
@@ -286,7 +287,7 @@
           }
           modified = true;
         } break;
-        case SpvOpStore: {
+        case spv::Op::OpStore: {
           uint32_t varId;
           Instruction* store = &*ii;
           Instruction* ptrInst = GetPtr(store, &varId);
@@ -347,7 +348,7 @@
   // for the capability.  This pass is only looking at function scope symbols,
   // so we do not care if there are variable pointers on storage buffers.
   if (context()->get_feature_mgr()->HasCapability(
-          SpvCapabilityVariablePointers))
+          spv::Capability::VariablePointers))
     return false;
   // If any extension not in allowlist, return false
   for (auto& ei : get_module()->extensions()) {
@@ -359,7 +360,7 @@
   // around unknown extended
   // instruction sets even if they are non-semantic
   for (auto& inst : context()->module()->ext_inst_imports()) {
-    assert(inst.opcode() == SpvOpExtInstImport &&
+    assert(inst.opcode() == spv::Op::OpExtInstImport &&
            "Expecting an import of an extension's instruction set.");
     const std::string extension_name = inst.GetInOperand(0).AsString();
     if (spvtools::utils::starts_with(extension_name, "NonSemantic.") &&
@@ -375,7 +376,8 @@
   // support required in KillNamesAndDecorates().
   // TODO(greg-lunarg): Add support for OpGroupDecorate
   for (auto& ai : get_module()->annotations())
-    if (ai.opcode() == SpvOpGroupDecorate) return Status::SuccessWithoutChange;
+    if (ai.opcode() == spv::Op::OpGroupDecorate)
+      return Status::SuccessWithoutChange;
   // Do not process if any disallowed extensions are enabled
   if (!AllExtensionsSupported()) return Status::SuccessWithoutChange;
 
diff --git a/source/opt/local_access_chain_convert_pass.h b/source/opt/local_access_chain_convert_pass.h
index c3731b1..0cda196 100644
--- a/source/opt/local_access_chain_convert_pass.h
+++ b/source/opt/local_access_chain_convert_pass.h
@@ -64,7 +64,7 @@
 
   // Build instruction from |opcode|, |typeId|, |resultId|, and |in_opnds|.
   // Append to |newInsts|.
-  void BuildAndAppendInst(SpvOp opcode, uint32_t typeId, uint32_t resultId,
+  void BuildAndAppendInst(spv::Op opcode, uint32_t typeId, uint32_t resultId,
                           const std::vector<Operand>& in_opnds,
                           std::vector<std::unique_ptr<Instruction>>* newInsts);
 
diff --git a/source/opt/local_single_block_elim_pass.cpp b/source/opt/local_single_block_elim_pass.cpp
index a58e8e4..6678c04 100644
--- a/source/opt/local_single_block_elim_pass.cpp
+++ b/source/opt/local_single_block_elim_pass.cpp
@@ -37,13 +37,13 @@
             dbg_op == CommonDebugInfoDebugValue) {
           return true;
         }
-        SpvOp op = user->opcode();
-        if (IsNonPtrAccessChain(op) || op == SpvOpCopyObject) {
+        spv::Op op = user->opcode();
+        if (IsNonPtrAccessChain(op) || op == spv::Op::OpCopyObject) {
           if (!HasOnlySupportedRefs(user->result_id())) {
             return false;
           }
-        } else if (op != SpvOpStore && op != SpvOpLoad && op != SpvOpName &&
-                   !IsNonTypeDecorate(op)) {
+        } else if (op != spv::Op::OpStore && op != spv::Op::OpLoad &&
+                   op != spv::Op::OpName && !IsNonTypeDecorate(op)) {
           return false;
         }
         return true;
@@ -68,7 +68,7 @@
     for (auto ii = next; ii != bi->end(); ii = next) {
       ++next;
       switch (ii->opcode()) {
-        case SpvOpStore: {
+        case spv::Op::OpStore: {
           // Verify store variable is target type
           uint32_t varId;
           Instruction* ptrInst = GetPtr(&*ii, &varId);
@@ -77,7 +77,7 @@
           // If a store to the whole variable, remember it for succeeding
           // loads and stores. Otherwise forget any previous store to that
           // variable.
-          if (ptrInst->opcode() == SpvOpVariable) {
+          if (ptrInst->opcode() == spv::Op::OpVariable) {
             // If a previous store to same variable, mark the store
             // for deletion if not still used. Don't delete store
             // if debugging; let ssa-rewrite and DCE handle it
@@ -114,14 +114,14 @@
             var2load_.erase(varId);
           }
         } break;
-        case SpvOpLoad: {
+        case spv::Op::OpLoad: {
           // Verify store variable is target type
           uint32_t varId;
           Instruction* ptrInst = GetPtr(&*ii, &varId);
           if (!IsTargetVar(varId)) continue;
           if (!HasOnlySupportedRefs(varId)) continue;
           uint32_t replId = 0;
-          if (ptrInst->opcode() == SpvOpVariable) {
+          if (ptrInst->opcode() == spv::Op::OpVariable) {
             // If a load from a variable, look for a previous store or
             // load from that variable and use its value.
             auto si = var2store_.find(varId);
@@ -146,11 +146,11 @@
             instructions_to_kill.push_back(&*ii);
             modified = true;
           } else {
-            if (ptrInst->opcode() == SpvOpVariable)
+            if (ptrInst->opcode() == spv::Op::OpVariable)
               var2load_[varId] = &*ii;  // register load
           }
         } break;
-        case SpvOpFunctionCall: {
+        case spv::Op::OpFunctionCall: {
           // Conservatively assume all locals are redefined for now.
           // TODO(): Handle more optimally
           var2store_.clear();
@@ -192,7 +192,7 @@
   // around unknown extended
   // instruction sets even if they are non-semantic
   for (auto& inst : context()->module()->ext_inst_imports()) {
-    assert(inst.opcode() == SpvOpExtInstImport &&
+    assert(inst.opcode() == spv::Op::OpExtInstImport &&
            "Expecting an import of an extension's instruction set.");
     const std::string extension_name = inst.GetInOperand(0).AsString();
     if (spvtools::utils::starts_with(extension_name, "NonSemantic.") &&
@@ -205,14 +205,15 @@
 
 Pass::Status LocalSingleBlockLoadStoreElimPass::ProcessImpl() {
   // Assumes relaxed logical addressing only (see instruction.h).
-  if (context()->get_feature_mgr()->HasCapability(SpvCapabilityAddresses))
+  if (context()->get_feature_mgr()->HasCapability(spv::Capability::Addresses))
     return Status::SuccessWithoutChange;
 
   // Do not process if module contains OpGroupDecorate. Additional
   // support required in KillNamesAndDecorates().
   // TODO(greg-lunarg): Add support for OpGroupDecorate
   for (auto& ai : get_module()->annotations())
-    if (ai.opcode() == SpvOpGroupDecorate) return Status::SuccessWithoutChange;
+    if (ai.opcode() == spv::Op::OpGroupDecorate)
+      return Status::SuccessWithoutChange;
   // If any extensions in the module are not explicitly supported,
   // return unmodified.
   if (!AllExtensionsSupported()) return Status::SuccessWithoutChange;
diff --git a/source/opt/local_single_store_elim_pass.cpp b/source/opt/local_single_store_elim_pass.cpp
index 81648c7..2b2b8c1 100644
--- a/source/opt/local_single_store_elim_pass.cpp
+++ b/source/opt/local_single_store_elim_pass.cpp
@@ -37,7 +37,7 @@
   // Check all function scope variables in |func|.
   BasicBlock* entry_block = &*func->begin();
   for (Instruction& inst : *entry_block) {
-    if (inst.opcode() != SpvOpVariable) {
+    if (inst.opcode() != spv::Op::OpVariable) {
       break;
     }
 
@@ -57,7 +57,7 @@
   // around unknown extended
   // instruction sets even if they are non-semantic
   for (auto& inst : context()->module()->ext_inst_imports()) {
-    assert(inst.opcode() == SpvOpExtInstImport &&
+    assert(inst.opcode() == spv::Op::OpExtInstImport &&
            "Expecting an import of an extension's instruction set.");
     const std::string extension_name = inst.GetInOperand(0).AsString();
     if (spvtools::utils::starts_with(extension_name, "NonSemantic.") &&
@@ -70,7 +70,7 @@
 
 Pass::Status LocalSingleStoreElimPass::ProcessImpl() {
   // Assumes relaxed logical addressing only (see instruction.h)
-  if (context()->get_feature_mgr()->HasCapability(SpvCapabilityAddresses))
+  if (context()->get_feature_mgr()->HasCapability(spv::Capability::Addresses))
     return Status::SuccessWithoutChange;
 
   // Do not process if any disallowed extensions are enabled
@@ -194,7 +194,7 @@
 
   for (Instruction* user : users) {
     switch (user->opcode()) {
-      case SpvOpStore:
+      case spv::Op::OpStore:
         // Since we are in the relaxed addressing mode, the use has to be the
         // base address of the store, and not the value being store.  Otherwise,
         // we would have a pointer to a pointer to function scope memory, which
@@ -206,19 +206,19 @@
           return nullptr;
         }
         break;
-      case SpvOpAccessChain:
-      case SpvOpInBoundsAccessChain:
+      case spv::Op::OpAccessChain:
+      case spv::Op::OpInBoundsAccessChain:
         if (FeedsAStore(user)) {
           // Has a partial store.  Cannot propagate that.
           return nullptr;
         }
         break;
-      case SpvOpLoad:
-      case SpvOpImageTexelPointer:
-      case SpvOpName:
-      case SpvOpCopyObject:
+      case spv::Op::OpLoad:
+      case spv::Op::OpImageTexelPointer:
+      case spv::Op::OpName:
+      case spv::Op::OpCopyObject:
         break;
-      case SpvOpExtInst: {
+      case spv::Op::OpExtInst: {
         auto dbg_op = user->GetCommonDebugOpcode();
         if (dbg_op == CommonDebugInfoDebugDeclare ||
             dbg_op == CommonDebugInfoDebugValue) {
@@ -243,7 +243,7 @@
   analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
   def_use_mgr->ForEachUser(var_inst, [users, this](Instruction* user) {
     users->push_back(user);
-    if (user->opcode() == SpvOpCopyObject) {
+    if (user->opcode() == spv::Op::OpCopyObject) {
       FindUses(user, users);
     }
   });
@@ -253,15 +253,15 @@
   analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
   return !def_use_mgr->WhileEachUser(inst, [this](Instruction* user) {
     switch (user->opcode()) {
-      case SpvOpStore:
+      case spv::Op::OpStore:
         return false;
-      case SpvOpAccessChain:
-      case SpvOpInBoundsAccessChain:
-      case SpvOpCopyObject:
+      case spv::Op::OpAccessChain:
+      case spv::Op::OpInBoundsAccessChain:
+      case spv::Op::OpCopyObject:
         return !FeedsAStore(user);
-      case SpvOpLoad:
-      case SpvOpImageTexelPointer:
-      case SpvOpName:
+      case spv::Op::OpLoad:
+      case spv::Op::OpImageTexelPointer:
+      case spv::Op::OpName:
         return true;
       default:
         // Don't know if this instruction modifies the variable.
@@ -279,7 +279,7 @@
       context()->GetDominatorAnalysis(store_block->GetParent());
 
   uint32_t stored_id;
-  if (store_inst->opcode() == SpvOpStore)
+  if (store_inst->opcode() == spv::Op::OpStore)
     stored_id = store_inst->GetSingleWordInOperand(kStoreValIdInIdx);
   else
     stored_id = store_inst->GetSingleWordInOperand(kVariableInitIdInIdx);
@@ -287,12 +287,12 @@
   *all_rewritten = true;
   bool modified = false;
   for (Instruction* use : uses) {
-    if (use->opcode() == SpvOpStore) continue;
+    if (use->opcode() == spv::Op::OpStore) continue;
     auto dbg_op = use->GetCommonDebugOpcode();
     if (dbg_op == CommonDebugInfoDebugDeclare ||
         dbg_op == CommonDebugInfoDebugValue)
       continue;
-    if (use->opcode() == SpvOpLoad &&
+    if (use->opcode() == spv::Op::OpLoad &&
         dominator_analysis->Dominates(store_inst, use)) {
       modified = true;
       context()->KillNamesAndDecorates(use->result_id());
diff --git a/source/opt/loop_dependence.cpp b/source/opt/loop_dependence.cpp
index d8de699..d7256bf 100644
--- a/source/opt/loop_dependence.cpp
+++ b/source/opt/loop_dependence.cpp
@@ -192,8 +192,8 @@
   Instruction* destination_access_chain = GetOperandDefinition(destination, 0);
 
   auto num_access_chains =
-      (source_access_chain->opcode() == SpvOpAccessChain) +
-      (destination_access_chain->opcode() == SpvOpAccessChain);
+      (source_access_chain->opcode() == spv::Op::OpAccessChain) +
+      (destination_access_chain->opcode() == spv::Op::OpAccessChain);
 
   // If neither is an access chain, then they are load/store to a variable.
   if (num_access_chains == 0) {
@@ -211,7 +211,8 @@
 
   // If only one is an access chain, it could be accessing a part of a struct
   if (num_access_chains == 1) {
-    auto source_is_chain = source_access_chain->opcode() == SpvOpAccessChain;
+    auto source_is_chain =
+        source_access_chain->opcode() == spv::Op::OpAccessChain;
     auto access_chain =
         source_is_chain ? source_access_chain : destination_access_chain;
     auto variable =
@@ -238,8 +239,8 @@
       GetOperandDefinition(destination_access_chain, 0);
 
   // Nested access chains are not supported yet, bail out.
-  if (source_array->opcode() == SpvOpAccessChain ||
-      destination_array->opcode() == SpvOpAccessChain) {
+  if (source_array->opcode() == spv::Op::OpAccessChain ||
+      destination_array->opcode() == spv::Op::OpAccessChain) {
     for (auto& entry : distance_vector->GetEntries()) {
       entry = DistanceEntry();
     }
diff --git a/source/opt/loop_dependence_helpers.cpp b/source/opt/loop_dependence_helpers.cpp
index de27a0a..929c940 100644
--- a/source/opt/loop_dependence_helpers.cpp
+++ b/source/opt/loop_dependence_helpers.cpp
@@ -54,20 +54,20 @@
   }
   Instruction* lower_inst = GetOperandDefinition(cond_inst, 0);
   switch (cond_inst->opcode()) {
-    case SpvOpULessThan:
-    case SpvOpSLessThan:
-    case SpvOpULessThanEqual:
-    case SpvOpSLessThanEqual:
-    case SpvOpUGreaterThan:
-    case SpvOpSGreaterThan:
-    case SpvOpUGreaterThanEqual:
-    case SpvOpSGreaterThanEqual: {
+    case spv::Op::OpULessThan:
+    case spv::Op::OpSLessThan:
+    case spv::Op::OpULessThanEqual:
+    case spv::Op::OpSLessThanEqual:
+    case spv::Op::OpUGreaterThan:
+    case spv::Op::OpSGreaterThan:
+    case spv::Op::OpUGreaterThanEqual:
+    case spv::Op::OpSGreaterThanEqual: {
       // If we have a phi we are looking at the induction variable. We look
       // through the phi to the initial value of the phi upon entering the loop.
-      if (lower_inst->opcode() == SpvOpPhi) {
+      if (lower_inst->opcode() == spv::Op::OpPhi) {
         lower_inst = GetOperandDefinition(lower_inst, 0);
         // We don't handle looking through multiple phis.
-        if (lower_inst->opcode() == SpvOpPhi) {
+        if (lower_inst->opcode() == spv::Op::OpPhi) {
           return nullptr;
         }
       }
@@ -86,8 +86,8 @@
   }
   Instruction* upper_inst = GetOperandDefinition(cond_inst, 1);
   switch (cond_inst->opcode()) {
-    case SpvOpULessThan:
-    case SpvOpSLessThan: {
+    case spv::Op::OpULessThan:
+    case spv::Op::OpSLessThan: {
       // When we have a < condition we must subtract 1 from the analyzed upper
       // instruction.
       SENode* upper_bound = scalar_evolution_.SimplifyExpression(
@@ -96,8 +96,8 @@
               scalar_evolution_.CreateConstant(1)));
       return upper_bound;
     }
-    case SpvOpUGreaterThan:
-    case SpvOpSGreaterThan: {
+    case spv::Op::OpUGreaterThan:
+    case spv::Op::OpSGreaterThan: {
       // When we have a > condition we must add 1 to the analyzed upper
       // instruction.
       SENode* upper_bound =
@@ -106,10 +106,10 @@
               scalar_evolution_.CreateConstant(1)));
       return upper_bound;
     }
-    case SpvOpULessThanEqual:
-    case SpvOpSLessThanEqual:
-    case SpvOpUGreaterThanEqual:
-    case SpvOpSGreaterThanEqual: {
+    case spv::Op::OpULessThanEqual:
+    case spv::Op::OpSLessThanEqual:
+    case spv::Op::OpUGreaterThanEqual:
+    case spv::Op::OpSGreaterThanEqual: {
       // We don't need to modify the results of analyzing when we have <= or >=.
       SENode* upper_bound = scalar_evolution_.SimplifyExpression(
           scalar_evolution_.AnalyzeInstruction(upper_inst));
diff --git a/source/opt/loop_descriptor.cpp b/source/opt/loop_descriptor.cpp
index 13982d1..38e1cd4 100644
--- a/source/opt/loop_descriptor.cpp
+++ b/source/opt/loop_descriptor.cpp
@@ -39,7 +39,7 @@
 Instruction* Loop::GetInductionStepOperation(
     const Instruction* induction) const {
   // Induction must be a phi instruction.
-  assert(induction->opcode() == SpvOpPhi);
+  assert(induction->opcode() == spv::Op::OpPhi);
 
   Instruction* step = nullptr;
 
@@ -75,8 +75,8 @@
     return nullptr;
   }
 
-  if (def_use_manager->GetDef(lhs)->opcode() != SpvOp::SpvOpConstant &&
-      def_use_manager->GetDef(rhs)->opcode() != SpvOp::SpvOpConstant) {
+  if (def_use_manager->GetDef(lhs)->opcode() != spv::Op::OpConstant &&
+      def_use_manager->GetDef(rhs)->opcode() != spv::Op::OpConstant) {
     return nullptr;
   }
 
@@ -85,31 +85,31 @@
 
 // Returns true if the |step| operation is an induction variable step operation
 // which is currently handled.
-bool Loop::IsSupportedStepOp(SpvOp step) const {
+bool Loop::IsSupportedStepOp(spv::Op step) const {
   switch (step) {
-    case SpvOp::SpvOpISub:
-    case SpvOp::SpvOpIAdd:
+    case spv::Op::OpISub:
+    case spv::Op::OpIAdd:
       return true;
     default:
       return false;
   }
 }
 
-bool Loop::IsSupportedCondition(SpvOp condition) const {
+bool Loop::IsSupportedCondition(spv::Op condition) const {
   switch (condition) {
     // <
-    case SpvOp::SpvOpULessThan:
-    case SpvOp::SpvOpSLessThan:
+    case spv::Op::OpULessThan:
+    case spv::Op::OpSLessThan:
     // >
-    case SpvOp::SpvOpUGreaterThan:
-    case SpvOp::SpvOpSGreaterThan:
+    case spv::Op::OpUGreaterThan:
+    case spv::Op::OpSGreaterThan:
 
     // >=
-    case SpvOp::SpvOpSGreaterThanEqual:
-    case SpvOp::SpvOpUGreaterThanEqual:
+    case spv::Op::OpSGreaterThanEqual:
+    case spv::Op::OpUGreaterThanEqual:
     // <=
-    case SpvOp::SpvOpSLessThanEqual:
-    case SpvOp::SpvOpULessThanEqual:
+    case spv::Op::OpSLessThanEqual:
+    case spv::Op::OpULessThanEqual:
 
       return true;
     default:
@@ -117,7 +117,8 @@
   }
 }
 
-int64_t Loop::GetResidualConditionValue(SpvOp condition, int64_t initial_value,
+int64_t Loop::GetResidualConditionValue(spv::Op condition,
+                                        int64_t initial_value,
                                         int64_t step_value,
                                         size_t number_of_iterations,
                                         size_t factor) {
@@ -128,13 +129,13 @@
   // loop where just less than or greater than. Adding or subtracting one should
   // give a functionally equivalent value.
   switch (condition) {
-    case SpvOp::SpvOpSGreaterThanEqual:
-    case SpvOp::SpvOpUGreaterThanEqual: {
+    case spv::Op::OpSGreaterThanEqual:
+    case spv::Op::OpUGreaterThanEqual: {
       remainder -= 1;
       break;
     }
-    case SpvOp::SpvOpSLessThanEqual:
-    case SpvOp::SpvOpULessThanEqual: {
+    case spv::Op::OpSLessThanEqual:
+    case spv::Op::OpULessThanEqual: {
       remainder += 1;
       break;
     }
@@ -152,7 +153,7 @@
   }
   Instruction* branch_conditional = &*condition_block->tail();
   if (!branch_conditional ||
-      branch_conditional->opcode() != SpvOpBranchConditional) {
+      branch_conditional->opcode() != spv::Op::OpBranchConditional) {
     return nullptr;
   }
   Instruction* condition_inst = context_->get_def_use_mgr()->GetDef(
@@ -318,7 +319,7 @@
 void Loop::SetPreHeaderBlock(BasicBlock* preheader) {
   if (preheader) {
     assert(!IsInsideLoop(preheader) && "The preheader block is in the loop");
-    assert(preheader->tail()->opcode() == SpvOpBranch &&
+    assert(preheader->tail()->opcode() == spv::Op::OpBranch &&
            "The preheader block does not unconditionally branch to the header "
            "block");
     assert(preheader->tail()->GetSingleWordOperand(0) ==
@@ -443,7 +444,7 @@
                 BasicBlock* parent = ir_context->get_instr_block(use);
                 assert(parent && "Invalid analysis");
                 if (IsInsideLoop(parent)) return true;
-                if (use->opcode() != SpvOpPhi) return false;
+                if (use->opcode() != spv::Op::OpPhi) return false;
                 return exit_blocks.count(parent->id());
               }))
         return false;
@@ -486,7 +487,7 @@
     ordered_loop_blocks->push_back(loop_preheader_);
 
   bool is_shader =
-      context_->get_feature_mgr()->HasCapability(SpvCapabilityShader);
+      context_->get_feature_mgr()->HasCapability(spv::Capability::Shader);
   if (!is_shader) {
     cfg.ForEachBlockInReversePostOrder(
         loop_header_, [ordered_loop_blocks, this](BasicBlock* bb) {
@@ -647,7 +648,7 @@
   const Instruction& branch = *bb->ctail();
 
   // Make sure the branch is a conditional branch.
-  if (branch.opcode() != SpvOpBranchConditional) return nullptr;
+  if (branch.opcode() != spv::Op::OpBranchConditional) return nullptr;
 
   // Make sure one of the two possible branches is to the merge block.
   if (branch.GetSingleWordInOperand(1) == loop_merge_->id() ||
@@ -716,7 +717,7 @@
   }
 
   // If this is a subtraction step we should negate the step value.
-  if (step_inst->opcode() == SpvOp::SpvOpISub) {
+  if (step_inst->opcode() == spv::Op::OpISub) {
     step_value = -step_value;
   }
 
@@ -753,7 +754,7 @@
 // |step_value| where diff is calculated differently according to the
 // |condition| and uses the |condition_value| and |init_value|. If diff /
 // |step_value| is NOT cleanly divisible then we add one to the sum.
-int64_t Loop::GetIterations(SpvOp condition, int64_t condition_value,
+int64_t Loop::GetIterations(spv::Op condition, int64_t condition_value,
                             int64_t init_value, int64_t step_value) const {
   if (step_value == 0) {
     return 0;
@@ -762,8 +763,8 @@
   int64_t diff = 0;
 
   switch (condition) {
-    case SpvOp::SpvOpSLessThan:
-    case SpvOp::SpvOpULessThan: {
+    case spv::Op::OpSLessThan:
+    case spv::Op::OpULessThan: {
       // If the condition is not met to begin with the loop will never iterate.
       if (!(init_value < condition_value)) return 0;
 
@@ -778,8 +779,8 @@
 
       break;
     }
-    case SpvOp::SpvOpSGreaterThan:
-    case SpvOp::SpvOpUGreaterThan: {
+    case spv::Op::OpSGreaterThan:
+    case spv::Op::OpUGreaterThan: {
       // If the condition is not met to begin with the loop will never iterate.
       if (!(init_value > condition_value)) return 0;
 
@@ -795,12 +796,12 @@
       break;
     }
 
-    case SpvOp::SpvOpSGreaterThanEqual:
-    case SpvOp::SpvOpUGreaterThanEqual: {
+    case spv::Op::OpSGreaterThanEqual:
+    case spv::Op::OpUGreaterThanEqual: {
       // If the condition is not met to begin with the loop will never iterate.
       if (!(init_value >= condition_value)) return 0;
 
-      // We subtract one to make it the same as SpvOpGreaterThan as it is
+      // We subtract one to make it the same as spv::Op::OpGreaterThan as it is
       // functionally equivalent.
       diff = init_value - (condition_value - 1);
 
@@ -814,13 +815,13 @@
       break;
     }
 
-    case SpvOp::SpvOpSLessThanEqual:
-    case SpvOp::SpvOpULessThanEqual: {
+    case spv::Op::OpSLessThanEqual:
+    case spv::Op::OpULessThanEqual: {
       // If the condition is not met to begin with the loop will never iterate.
       if (!(init_value <= condition_value)) return 0;
 
-      // We add one to make it the same as SpvOpLessThan as it is functionally
-      // equivalent.
+      // We add one to make it the same as spv::Op::OpLessThan as it is
+      // functionally equivalent.
       diff = (condition_value + 1) - init_value;
 
       // If the operation is a less than operation then the diff and step must
@@ -854,7 +855,7 @@
 void Loop::GetInductionVariables(
     std::vector<Instruction*>& induction_variables) const {
   for (Instruction& inst : *loop_header_) {
-    if (inst.opcode() == SpvOp::SpvOpPhi) {
+    if (inst.opcode() == spv::Op::OpPhi) {
       induction_variables.push_back(&inst);
     }
   }
@@ -867,7 +868,7 @@
 
   Instruction* induction = nullptr;
   // Verify that the branch instruction is a conditional branch.
-  if (branch_inst.opcode() == SpvOp::SpvOpBranchConditional) {
+  if (branch_inst.opcode() == spv::Op::OpBranchConditional) {
     // From the branch instruction find the branch condition.
     analysis::DefUseManager* def_use_manager = context_->get_def_use_mgr();
 
@@ -883,7 +884,8 @@
           def_use_manager->GetDef(condition->GetSingleWordOperand(2));
 
       // Make sure the variable instruction used is a phi.
-      if (!variable_inst || variable_inst->opcode() != SpvOpPhi) return nullptr;
+      if (!variable_inst || variable_inst->opcode() != spv::Op::OpPhi)
+        return nullptr;
 
       // Make sure the phi instruction only has two incoming blocks. Each
       // incoming block will be represented by two in operands in the phi
diff --git a/source/opt/loop_descriptor.h b/source/opt/loop_descriptor.h
index df01227..35256bc 100644
--- a/source/opt/loop_descriptor.h
+++ b/source/opt/loop_descriptor.h
@@ -316,12 +316,12 @@
   // Returns true if we can deduce the number of loop iterations in the step
   // operation |step|. IsSupportedCondition must also be true for the condition
   // instruction.
-  bool IsSupportedStepOp(SpvOp step) const;
+  bool IsSupportedStepOp(spv::Op step) const;
 
   // Returns true if we can deduce the number of loop iterations in the
   // condition operation |condition|. IsSupportedStepOp must also be true for
   // the step instruction.
-  bool IsSupportedCondition(SpvOp condition) const;
+  bool IsSupportedCondition(spv::Op condition) const;
 
   // Creates the list of the loop's basic block in structured order and store
   // the result in |ordered_loop_blocks|. If |include_pre_header| is true, the
@@ -335,7 +335,7 @@
   // Given the loop |condition|, |initial_value|, |step_value|, the trip count
   // |number_of_iterations|, and the |unroll_factor| requested, get the new
   // condition value for the residual loop.
-  static int64_t GetResidualConditionValue(SpvOp condition,
+  static int64_t GetResidualConditionValue(spv::Op condition,
                                            int64_t initial_value,
                                            int64_t step_value,
                                            size_t number_of_iterations,
@@ -400,7 +400,7 @@
   // the induction variable. This method will return the number of iterations in
   // a loop with those values for a given |condition|.  Returns 0 if the number
   // of iterations could not be computed.
-  int64_t GetIterations(SpvOp condition, int64_t condition_value,
+  int64_t GetIterations(spv::Op condition, int64_t condition_value,
                         int64_t init_value, int64_t step_value) const;
 
   // This is to allow for loops to be removed mid iteration without invalidating
diff --git a/source/opt/loop_fission.cpp b/source/opt/loop_fission.cpp
index b4df8c6..2ae05c3 100644
--- a/source/opt/loop_fission.cpp
+++ b/source/opt/loop_fission.cpp
@@ -110,10 +110,10 @@
 };
 
 bool LoopFissionImpl::MovableInstruction(const Instruction& inst) const {
-  return inst.opcode() == SpvOp::SpvOpLoad ||
-         inst.opcode() == SpvOp::SpvOpStore ||
-         inst.opcode() == SpvOp::SpvOpSelectionMerge ||
-         inst.opcode() == SpvOp::SpvOpPhi || inst.IsOpcodeCodeMotionSafe();
+  return inst.opcode() == spv::Op::OpLoad ||
+         inst.opcode() == spv::Op::OpStore ||
+         inst.opcode() == spv::Op::OpSelectionMerge ||
+         inst.opcode() == spv::Op::OpPhi || inst.IsOpcodeCodeMotionSafe();
 }
 
 void LoopFissionImpl::TraverseUseDef(Instruction* inst,
@@ -143,14 +143,14 @@
     // same labels (i.e phis). We already preempt the inclusion of
     // OpSelectionMerge by adding related instructions to the seen_instructions_
     // set.
-    if (user->opcode() == SpvOp::SpvOpLoopMerge ||
-        user->opcode() == SpvOp::SpvOpLabel)
+    if (user->opcode() == spv::Op::OpLoopMerge ||
+        user->opcode() == spv::Op::OpLabel)
       return;
 
     // If the |report_loads| flag is set, set the class field
     // load_used_in_condition_ to false. This is used to check that none of the
     // condition checks in the loop rely on loads.
-    if (user->opcode() == SpvOp::SpvOpLoad && report_loads) {
+    if (user->opcode() == spv::Op::OpLoad && report_loads) {
       load_used_in_condition_ = true;
     }
 
@@ -167,7 +167,7 @@
     user->ForEachInOperand(traverse_operand);
 
     // For the first traversal we want to ignore the users of the phi.
-    if (ignore_phi_users && user->opcode() == SpvOp::SpvOpPhi) return;
+    if (ignore_phi_users && user->opcode() == spv::Op::OpPhi) return;
 
     // Traverse each user with this lambda.
     def_use->ForEachUser(user, traverser_functor);
@@ -214,7 +214,7 @@
 
     for (Instruction& inst : block) {
       // Ignore all instructions related to control flow.
-      if (inst.opcode() == SpvOp::SpvOpSelectionMerge || inst.IsBranch()) {
+      if (inst.opcode() == spv::Op::OpSelectionMerge || inst.IsBranch()) {
         TraverseUseDef(&inst, &instructions_to_ignore, true, true);
       }
     }
@@ -229,8 +229,8 @@
 
     for (Instruction& inst : block) {
       // Record the order that each load/store is seen.
-      if (inst.opcode() == SpvOp::SpvOpLoad ||
-          inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpLoad ||
+          inst.opcode() == spv::Op::OpStore) {
         instruction_order_[&inst] = instruction_order_.size();
       }
 
@@ -292,9 +292,9 @@
 
   // Populate the above lists.
   for (Instruction* inst : cloned_loop_instructions_) {
-    if (inst->opcode() == SpvOp::SpvOpStore) {
+    if (inst->opcode() == spv::Op::OpStore) {
       set_one_stores.push_back(inst);
-    } else if (inst->opcode() == SpvOp::SpvOpLoad) {
+    } else if (inst->opcode() == spv::Op::OpLoad) {
       set_one_loads.push_back(inst);
     }
 
@@ -316,7 +316,7 @@
 
     // Look at the dependency between the loads in the original and stores in
     // the cloned loops.
-    if (inst->opcode() == SpvOp::SpvOpLoad) {
+    if (inst->opcode() == spv::Op::OpLoad) {
       for (Instruction* store : set_one_stores) {
         DistanceVector vec{loop_depth};
 
@@ -334,7 +334,7 @@
           }
         }
       }
-    } else if (inst->opcode() == SpvOp::SpvOpStore) {
+    } else if (inst->opcode() == spv::Op::OpStore) {
       for (Instruction* load : set_one_loads) {
         DistanceVector vec{loop_depth};
 
@@ -387,7 +387,7 @@
       if (cloned_loop_instructions_.count(&inst) == 1 &&
           original_loop_instructions_.count(&inst) == 0) {
         instructions_to_kill.push_back(&inst);
-        if (inst.opcode() == SpvOp::SpvOpPhi) {
+        if (inst.opcode() == spv::Op::OpPhi) {
           context_->ReplaceAllUsesWith(
               inst.result_id(), clone_results.value_map_[inst.result_id()]);
         }
diff --git a/source/opt/loop_fusion.cpp b/source/opt/loop_fusion.cpp
index f3aab28..ca42d8a 100644
--- a/source/opt/loop_fusion.cpp
+++ b/source/opt/loop_fusion.cpp
@@ -193,14 +193,15 @@
   // in LCSSA form.
   for (auto block : block_to_check) {
     for (auto& inst : *block) {
-      if (inst.opcode() == SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         // Get the definition of the target to check it's function scope so
         // there are no observable side effects.
         auto variable =
             context_->get_def_use_mgr()->GetDef(inst.GetSingleWordInOperand(0));
 
-        if (variable->opcode() != SpvOpVariable ||
-            variable->GetSingleWordInOperand(0) != SpvStorageClassFunction) {
+        if (variable->opcode() != spv::Op::OpVariable ||
+            spv::StorageClass(variable->GetSingleWordInOperand(0)) !=
+                spv::StorageClass::Function) {
           return false;
         }
 
@@ -209,7 +210,7 @@
         context_->get_def_use_mgr()->ForEachUse(
             inst.GetSingleWordInOperand(0),
             [&is_used](Instruction* use_inst, uint32_t) {
-              if (use_inst->opcode() == SpvOpLoad) {
+              if (use_inst->opcode() == spv::Op::OpLoad) {
                 is_used = true;
               }
             });
@@ -217,11 +218,11 @@
         if (is_used) {
           return false;
         }
-      } else if (inst.opcode() == SpvOpPhi) {
+      } else if (inst.opcode() == spv::Op::OpPhi) {
         if (inst.NumInOperands() != 2) {
           return false;
         }
-      } else if (inst.opcode() != SpvOpBranch) {
+      } else if (inst.opcode() != spv::Op::OpBranch) {
         return false;
       }
     }
@@ -234,10 +235,12 @@
   for (const auto& block : loop->GetBlocks()) {
     for (const auto& inst : *containing_function_->FindBlock(block)) {
       auto opcode = inst.opcode();
-      if (opcode == SpvOpFunctionCall || opcode == SpvOpControlBarrier ||
-          opcode == SpvOpMemoryBarrier || opcode == SpvOpTypeNamedBarrier ||
-          opcode == SpvOpNamedBarrierInitialize ||
-          opcode == SpvOpMemoryNamedBarrier) {
+      if (opcode == spv::Op::OpFunctionCall ||
+          opcode == spv::Op::OpControlBarrier ||
+          opcode == spv::Op::OpMemoryBarrier ||
+          opcode == spv::Op::OpTypeNamedBarrier ||
+          opcode == spv::Op::OpNamedBarrierInitialize ||
+          opcode == spv::Op::OpMemoryNamedBarrier) {
         return true;
       }
     }
@@ -344,7 +347,7 @@
     auto access_location = context_->get_def_use_mgr()->GetDef(
         instruction->GetSingleWordInOperand(0));
 
-    while (access_location->opcode() == SpvOpAccessChain) {
+    while (access_location->opcode() == spv::Op::OpAccessChain) {
       access_location = context_->get_def_use_mgr()->GetDef(
           access_location->GetSingleWordInOperand(0));
     }
@@ -366,9 +369,9 @@
     }
 
     for (auto& instruction : *containing_function_->FindBlock(block_id)) {
-      if (instruction.opcode() == SpvOpLoad) {
+      if (instruction.opcode() == spv::Op::OpLoad) {
         loads.push_back(&instruction);
-      } else if (instruction.opcode() == SpvOpStore) {
+      } else if (instruction.opcode() == spv::Op::OpStore) {
         stores.push_back(&instruction);
       }
     }
@@ -556,7 +559,7 @@
   // Update merge block id in the header of |loop_0_| to the merge block of
   // |loop_1_|.
   loop_0_->GetHeaderBlock()->ForEachInst([this](Instruction* inst) {
-    if (inst->opcode() == SpvOpLoopMerge) {
+    if (inst->opcode() == spv::Op::OpLoopMerge) {
       inst->SetInOperand(0, {loop_1_->GetMergeBlock()->id()});
     }
   });
@@ -564,7 +567,7 @@
   // Update condition branch target in |loop_0_| to the merge block of
   // |loop_1_|.
   condition_block_of_0->ForEachInst([this](Instruction* inst) {
-    if (inst->opcode() == SpvOpBranchConditional) {
+    if (inst->opcode() == spv::Op::OpBranchConditional) {
       auto loop_0_merge_block_id = loop_0_->GetMergeBlock()->id();
 
       if (inst->GetSingleWordInOperand(1) == loop_0_merge_block_id) {
@@ -579,7 +582,8 @@
   // the header of |loop_1_| to the header of |loop_0_|.
   std::vector<Instruction*> instructions_to_move{};
   for (auto& instruction : *loop_1_->GetHeaderBlock()) {
-    if (instruction.opcode() == SpvOpPhi && &instruction != induction_1_) {
+    if (instruction.opcode() == spv::Op::OpPhi &&
+        &instruction != induction_1_) {
       instructions_to_move.push_back(&instruction);
     }
   }
diff --git a/source/opt/loop_peeling.cpp b/source/opt/loop_peeling.cpp
index 34f0a8d..c10bd2b 100644
--- a/source/opt/loop_peeling.cpp
+++ b/source/opt/loop_peeling.cpp
@@ -186,7 +186,7 @@
   operations->insert(iterator);
   iterator->ForEachInId([def_use_mgr, loop, operations, this](uint32_t* id) {
     Instruction* insn = def_use_mgr->GetDef(*id);
-    if (insn->opcode() == SpvOpLabel) {
+    if (insn->opcode() == spv::Op::OpLabel) {
       return;
     }
     if (operations->count(insn)) {
@@ -231,9 +231,9 @@
       if (!bb->WhileEachInst([this](Instruction* insn) {
             if (insn->IsBranch()) return true;
             switch (insn->opcode()) {
-              case SpvOpLabel:
-              case SpvOpSelectionMerge:
-              case SpvOpLoopMerge:
+              case spv::Op::OpLabel:
+              case spv::Op::OpSelectionMerge:
+              case spv::Op::OpLoopMerge:
                 return true;
               default:
                 break;
@@ -322,7 +322,7 @@
 
   BasicBlock* condition_block = cfg.block(condition_block_id);
   Instruction* exit_condition = condition_block->terminator();
-  assert(exit_condition->opcode() == SpvOpBranchConditional);
+  assert(exit_condition->opcode() == spv::Op::OpBranchConditional);
   BasicBlock::iterator insert_point = condition_block->tail();
   if (condition_block->GetMergeInst()) {
     --insert_point;
@@ -350,7 +350,7 @@
   // TODO(1841): Handle id overflow.
   std::unique_ptr<BasicBlock> new_bb =
       MakeUnique<BasicBlock>(std::unique_ptr<Instruction>(new Instruction(
-          context_, SpvOpLabel, 0, context_->TakeNextId(), {})));
+          context_, spv::Op::OpLabel, 0, context_->TakeNextId(), {})));
   // Update the loop descriptor.
   Loop* in_loop = (*loop_utils_.GetLoopDescriptor())[bb];
   if (in_loop) {
@@ -791,18 +791,18 @@
   return 0;
 }
 
-static bool IsHandledCondition(SpvOp opcode) {
+static bool IsHandledCondition(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpIEqual:
-    case SpvOpINotEqual:
-    case SpvOpUGreaterThan:
-    case SpvOpSGreaterThan:
-    case SpvOpUGreaterThanEqual:
-    case SpvOpSGreaterThanEqual:
-    case SpvOpULessThan:
-    case SpvOpSLessThan:
-    case SpvOpULessThanEqual:
-    case SpvOpSLessThanEqual:
+    case spv::Op::OpIEqual:
+    case spv::Op::OpINotEqual:
+    case spv::Op::OpUGreaterThan:
+    case spv::Op::OpSGreaterThan:
+    case spv::Op::OpUGreaterThanEqual:
+    case spv::Op::OpSGreaterThanEqual:
+    case spv::Op::OpULessThan:
+    case spv::Op::OpSLessThan:
+    case spv::Op::OpULessThanEqual:
+    case spv::Op::OpSLessThanEqual:
       return true;
     default:
       return false;
@@ -811,7 +811,7 @@
 
 LoopPeelingPass::LoopPeelingInfo::Direction
 LoopPeelingPass::LoopPeelingInfo::GetPeelingInfo(BasicBlock* bb) const {
-  if (bb->terminator()->opcode() != SpvOpBranchConditional) {
+  if (bb->terminator()->opcode() != spv::Op::OpBranchConditional) {
     return GetNoneDirection();
   }
 
@@ -886,27 +886,27 @@
   switch (condition->opcode()) {
     default:
       return GetNoneDirection();
-    case SpvOpIEqual:
-    case SpvOpINotEqual:
+    case spv::Op::OpIEqual:
+    case spv::Op::OpINotEqual:
       return HandleEquality(lhs, rhs);
-    case SpvOpUGreaterThan:
-    case SpvOpSGreaterThan: {
+    case spv::Op::OpUGreaterThan:
+    case spv::Op::OpSGreaterThan: {
       cmp_operator = CmpOperator::kGT;
       break;
     }
-    case SpvOpULessThan:
-    case SpvOpSLessThan: {
+    case spv::Op::OpULessThan:
+    case spv::Op::OpSLessThan: {
       cmp_operator = CmpOperator::kLT;
       break;
     }
     // We add one to transform >= into > and <= into <.
-    case SpvOpUGreaterThanEqual:
-    case SpvOpSGreaterThanEqual: {
+    case spv::Op::OpUGreaterThanEqual:
+    case spv::Op::OpSGreaterThanEqual: {
       cmp_operator = CmpOperator::kGE;
       break;
     }
-    case SpvOpULessThanEqual:
-    case SpvOpSLessThanEqual: {
+    case spv::Op::OpULessThanEqual:
+    case spv::Op::OpSLessThanEqual: {
       cmp_operator = CmpOperator::kLE;
       break;
     }
diff --git a/source/opt/loop_unroller.cpp b/source/opt/loop_unroller.cpp
index 6f4e6f4..e1d48f5 100644
--- a/source/opt/loop_unroller.cpp
+++ b/source/opt/loop_unroller.cpp
@@ -382,7 +382,7 @@
                                                           size_t factor) {
   // TODO(1841): Handle id overflow.
   std::unique_ptr<Instruction> new_label{new Instruction(
-      context_, SpvOp::SpvOpLabel, 0, context_->TakeNextId(), {})};
+      context_, spv::Op::OpLabel, 0, context_->TakeNextId(), {})};
   std::unique_ptr<BasicBlock> new_exit_bb{new BasicBlock(std::move(new_label))};
   new_exit_bb->SetParent(&function_);
 
@@ -991,7 +991,7 @@
 
   // Check that we can find and process the induction variable.
   const Instruction* induction = loop_->FindConditionVariable(condition);
-  if (!induction || induction->opcode() != SpvOpPhi) return false;
+  if (!induction || induction->opcode() != spv::Op::OpPhi) return false;
 
   // Check that we can find the number of loop iterations.
   if (!loop_->FindNumberOfIterations(induction, &*condition->ctail(), nullptr))
@@ -1015,7 +1015,7 @@
   // block.
   const Instruction& branch = *loop_->GetLatchBlock()->ctail();
   bool branching_assumption =
-      branch.opcode() == SpvOpBranch &&
+      branch.opcode() == spv::Op::OpBranch &&
       branch.GetSingleWordInOperand(0) == loop_->GetHeaderBlock()->id();
   if (!branching_assumption) {
     return false;
@@ -1043,10 +1043,10 @@
   // exit the loop.
   for (uint32_t label_id : loop_->GetBlocks()) {
     const BasicBlock* block = context_->cfg()->block(label_id);
-    if (block->ctail()->opcode() == SpvOp::SpvOpKill ||
-        block->ctail()->opcode() == SpvOp::SpvOpReturn ||
-        block->ctail()->opcode() == SpvOp::SpvOpReturnValue ||
-        block->ctail()->opcode() == SpvOp::SpvOpTerminateInvocation) {
+    if (block->ctail()->opcode() == spv::Op::OpKill ||
+        block->ctail()->opcode() == spv::Op::OpReturn ||
+        block->ctail()->opcode() == spv::Op::OpReturnValue ||
+        block->ctail()->opcode() == spv::Op::OpTerminateInvocation) {
       return false;
     }
   }
diff --git a/source/opt/loop_unswitch_pass.cpp b/source/opt/loop_unswitch_pass.cpp
index 1ee7e5e..b9ab389 100644
--- a/source/opt/loop_unswitch_pass.cpp
+++ b/source/opt/loop_unswitch_pass.cpp
@@ -77,7 +77,7 @@
       }
 
       if (bb->terminator()->IsBranch() &&
-          bb->terminator()->opcode() != SpvOpBranch) {
+          bb->terminator()->opcode() != spv::Op::OpBranch) {
         if (IsConditionNonConstantLoopInvariant(bb->terminator())) {
           switch_block_ = bb;
           break;
@@ -104,7 +104,7 @@
     // TODO(1841): Handle id overflow.
     BasicBlock* bb = &*ip.InsertBefore(std::unique_ptr<BasicBlock>(
         new BasicBlock(std::unique_ptr<Instruction>(new Instruction(
-            context_, SpvOpLabel, 0, context_->TakeNextId(), {})))));
+            context_, spv::Op::OpLabel, 0, context_->TakeNextId(), {})))));
     bb->SetParent(function_);
     def_use_mgr->AnalyzeInstDef(bb->GetLabelInst());
     context_->set_instr_block(bb->GetLabelInst(), bb);
@@ -113,7 +113,7 @@
   }
 
   Instruction* GetValueForDefaultPathForSwitch(Instruction* switch_inst) {
-    assert(switch_inst->opcode() == SpvOpSwitch &&
+    assert(switch_inst->opcode() == spv::Op::OpSwitch &&
            "The given instructoin must be an OpSwitch.");
 
     // Find a value that can be used to select the default path.
@@ -291,7 +291,7 @@
     /////////////////////////////
 
     Instruction* iv_condition = &*switch_block_->tail();
-    SpvOp iv_opcode = iv_condition->opcode();
+    spv::Op iv_opcode = iv_condition->opcode();
     Instruction* condition =
         def_use_mgr->GetDef(iv_condition->GetOperand(0).words[0]);
 
@@ -304,7 +304,7 @@
     std::vector<std::pair<Instruction*, BasicBlock*>> constant_branch;
     // Special case for the original loop
     Instruction* original_loop_constant_value;
-    if (iv_opcode == SpvOpBranchConditional) {
+    if (iv_opcode == spv::Op::OpBranchConditional) {
       constant_branch.emplace_back(
           cst_mgr->GetDefiningInstruction(cst_mgr->GetConstant(cond_type, {0})),
           nullptr);
@@ -401,7 +401,7 @@
     // Delete the old jump
     context_->KillInst(&*if_block->tail());
     InstructionBuilder builder(context_, if_block);
-    if (iv_opcode == SpvOpBranchConditional) {
+    if (iv_opcode == spv::Op::OpBranchConditional) {
       assert(constant_branch.size() == 1);
       builder.AddConditionalBranch(
           condition->result_id(), original_loop_target->id(),
@@ -509,7 +509,8 @@
     bool& is_uniform = dynamically_uniform_[var->result_id()];
     is_uniform = false;
 
-    dec_mgr->WhileEachDecoration(var->result_id(), SpvDecorationUniform,
+    dec_mgr->WhileEachDecoration(var->result_id(),
+                                 uint32_t(spv::Decoration::Uniform),
                                  [&is_uniform](const Instruction&) {
                                    is_uniform = true;
                                    return false;
@@ -526,14 +527,14 @@
     if (!post_dom_tree.Dominates(parent->id(), entry->id())) {
       return is_uniform = false;
     }
-    if (var->opcode() == SpvOpLoad) {
+    if (var->opcode() == spv::Op::OpLoad) {
       const uint32_t PtrTypeId =
           def_use_mgr->GetDef(var->GetSingleWordInOperand(0))->type_id();
       const Instruction* PtrTypeInst = def_use_mgr->GetDef(PtrTypeId);
-      uint32_t storage_class =
-          PtrTypeInst->GetSingleWordInOperand(kTypePointerStorageClassInIdx);
-      if (storage_class != SpvStorageClassUniform &&
-          storage_class != SpvStorageClassUniformConstant) {
+      auto storage_class = spv::StorageClass(
+          PtrTypeInst->GetSingleWordInOperand(kTypePointerStorageClassInIdx));
+      if (storage_class != spv::StorageClass::Uniform &&
+          storage_class != spv::StorageClass::UniformConstant) {
         return is_uniform = false;
       }
     } else {
@@ -553,7 +554,7 @@
   // dynamically uniform.
   bool IsConditionNonConstantLoopInvariant(Instruction* insn) {
     assert(insn->IsBranch());
-    assert(insn->opcode() != SpvOpBranch);
+    assert(insn->opcode() != spv::Op::OpBranch);
     analysis::DefUseManager* def_use_mgr = context_->get_def_use_mgr();
 
     Instruction* condition = def_use_mgr->GetDef(insn->GetOperand(0).words[0]);
diff --git a/source/opt/loop_utils.cpp b/source/opt/loop_utils.cpp
index 8c6d355..282fff6 100644
--- a/source/opt/loop_utils.cpp
+++ b/source/opt/loop_utils.cpp
@@ -71,10 +71,10 @@
     // UpdateManagers.
     void RewriteUse(BasicBlock* bb, Instruction* user, uint32_t operand_index) {
       assert(
-          (user->opcode() != SpvOpPhi || bb != GetParent(user)) &&
+          (user->opcode() != spv::Op::OpPhi || bb != GetParent(user)) &&
           "The root basic block must be the incoming edge if |user| is a phi "
           "instruction");
-      assert((user->opcode() == SpvOpPhi || bb == GetParent(user)) &&
+      assert((user->opcode() == spv::Op::OpPhi || bb == GetParent(user)) &&
              "The root basic block must be the instruction parent if |user| is "
              "not "
              "phi instruction");
@@ -293,7 +293,7 @@
             assert(use_parent);
             if (blocks.count(use_parent->id())) return;
 
-            if (use->opcode() == SpvOpPhi) {
+            if (use->opcode() == spv::Op::OpPhi) {
               // If the use is a Phi instruction and the incoming block is
               // coming from the loop, then that's consistent with LCSSA form.
               if (exit_bb.count(use_parent)) {
@@ -355,7 +355,7 @@
     // TODO(1841): Handle id overflow.
     BasicBlock& exit = *insert_pt.InsertBefore(std::unique_ptr<BasicBlock>(
         new BasicBlock(std::unique_ptr<Instruction>(new Instruction(
-            context_, SpvOpLabel, 0, context_->TakeNextId(), {})))));
+            context_, spv::Op::OpLabel, 0, context_->TakeNextId(), {})))));
     exit.SetParent(function);
 
     // Redirect in loop predecessors to |exit| block.
@@ -494,7 +494,7 @@
   // Create a new exit block/label for the new loop.
   // TODO(1841): Handle id overflow.
   std::unique_ptr<Instruction> new_label{new Instruction(
-      context_, SpvOp::SpvOpLabel, 0, context_->TakeNextId(), {})};
+      context_, spv::Op::OpLabel, 0, context_->TakeNextId(), {})};
   std::unique_ptr<BasicBlock> new_exit_bb{new BasicBlock(std::move(new_label))};
   new_exit_bb->SetParent(loop_->GetMergeBlock()->GetParent());
 
@@ -680,9 +680,9 @@
     const BasicBlock* bb = cfg.block(id);
     size_t bb_size = 0;
     bb->ForEachInst([&bb_size](const Instruction* insn) {
-      if (insn->opcode() == SpvOpLabel) return;
+      if (insn->opcode() == spv::Op::OpLabel) return;
       if (insn->IsNop()) return;
-      if (insn->opcode() == SpvOpPhi) return;
+      if (insn->opcode() == spv::Op::OpPhi) return;
       bb_size++;
     });
     block_sizes_[bb->id()] = bb_size;
diff --git a/source/opt/mem_pass.cpp b/source/opt/mem_pass.cpp
index ca4889b..5dd337b 100644
--- a/source/opt/mem_pass.cpp
+++ b/source/opt/mem_pass.cpp
@@ -39,15 +39,15 @@
 
 bool MemPass::IsBaseTargetType(const Instruction* typeInst) const {
   switch (typeInst->opcode()) {
-    case SpvOpTypeInt:
-    case SpvOpTypeFloat:
-    case SpvOpTypeBool:
-    case SpvOpTypeVector:
-    case SpvOpTypeMatrix:
-    case SpvOpTypeImage:
-    case SpvOpTypeSampler:
-    case SpvOpTypeSampledImage:
-    case SpvOpTypePointer:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeFloat:
+    case spv::Op::OpTypeBool:
+    case spv::Op::OpTypeVector:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeImage:
+    case spv::Op::OpTypeSampler:
+    case spv::Op::OpTypeSampledImage:
+    case spv::Op::OpTypePointer:
       return true;
     default:
       break;
@@ -57,14 +57,14 @@
 
 bool MemPass::IsTargetType(const Instruction* typeInst) const {
   if (IsBaseTargetType(typeInst)) return true;
-  if (typeInst->opcode() == SpvOpTypeArray) {
+  if (typeInst->opcode() == spv::Op::OpTypeArray) {
     if (!IsTargetType(
             get_def_use_mgr()->GetDef(typeInst->GetSingleWordOperand(1)))) {
       return false;
     }
     return true;
   }
-  if (typeInst->opcode() != SpvOpTypeStruct) return false;
+  if (typeInst->opcode() != spv::Op::OpTypeStruct) return false;
   // All struct members must be math type
   return typeInst->WhileEachInId([this](const uint32_t* tid) {
     Instruction* compTypeInst = get_def_use_mgr()->GetDef(*tid);
@@ -73,23 +73,24 @@
   });
 }
 
-bool MemPass::IsNonPtrAccessChain(const SpvOp opcode) const {
-  return opcode == SpvOpAccessChain || opcode == SpvOpInBoundsAccessChain;
+bool MemPass::IsNonPtrAccessChain(const spv::Op opcode) const {
+  return opcode == spv::Op::OpAccessChain ||
+         opcode == spv::Op::OpInBoundsAccessChain;
 }
 
 bool MemPass::IsPtr(uint32_t ptrId) {
   uint32_t varId = ptrId;
   Instruction* ptrInst = get_def_use_mgr()->GetDef(varId);
-  while (ptrInst->opcode() == SpvOpCopyObject) {
+  while (ptrInst->opcode() == spv::Op::OpCopyObject) {
     varId = ptrInst->GetSingleWordInOperand(kCopyObjectOperandInIdx);
     ptrInst = get_def_use_mgr()->GetDef(varId);
   }
-  const SpvOp op = ptrInst->opcode();
-  if (op == SpvOpVariable || IsNonPtrAccessChain(op)) return true;
+  const spv::Op op = ptrInst->opcode();
+  if (op == spv::Op::OpVariable || IsNonPtrAccessChain(op)) return true;
   const uint32_t varTypeId = ptrInst->type_id();
   if (varTypeId == 0) return false;
   const Instruction* varTypeInst = get_def_use_mgr()->GetDef(varTypeId);
-  return varTypeInst->opcode() == SpvOpTypePointer;
+  return varTypeInst->opcode() == spv::Op::OpTypePointer;
 }
 
 Instruction* MemPass::GetPtr(uint32_t ptrId, uint32_t* varId) {
@@ -97,24 +98,24 @@
   Instruction* ptrInst = get_def_use_mgr()->GetDef(*varId);
   Instruction* varInst;
 
-  if (ptrInst->opcode() == SpvOpConstantNull) {
+  if (ptrInst->opcode() == spv::Op::OpConstantNull) {
     *varId = 0;
     return ptrInst;
   }
 
-  if (ptrInst->opcode() != SpvOpVariable &&
-      ptrInst->opcode() != SpvOpFunctionParameter) {
+  if (ptrInst->opcode() != spv::Op::OpVariable &&
+      ptrInst->opcode() != spv::Op::OpFunctionParameter) {
     varInst = ptrInst->GetBaseAddress();
   } else {
     varInst = ptrInst;
   }
-  if (varInst->opcode() == SpvOpVariable) {
+  if (varInst->opcode() == spv::Op::OpVariable) {
     *varId = varInst->result_id();
   } else {
     *varId = 0;
   }
 
-  while (ptrInst->opcode() == SpvOpCopyObject) {
+  while (ptrInst->opcode() == spv::Op::OpCopyObject) {
     uint32_t temp = ptrInst->GetSingleWordInOperand(0);
     ptrInst = get_def_use_mgr()->GetDef(temp);
   }
@@ -123,8 +124,9 @@
 }
 
 Instruction* MemPass::GetPtr(Instruction* ip, uint32_t* varId) {
-  assert(ip->opcode() == SpvOpStore || ip->opcode() == SpvOpLoad ||
-         ip->opcode() == SpvOpImageTexelPointer || ip->IsAtomicWithLoad());
+  assert(ip->opcode() == spv::Op::OpStore || ip->opcode() == spv::Op::OpLoad ||
+         ip->opcode() == spv::Op::OpImageTexelPointer ||
+         ip->IsAtomicWithLoad());
 
   // All of these opcode place the pointer in position 0.
   const uint32_t ptrId = ip->GetSingleWordInOperand(0);
@@ -133,8 +135,8 @@
 
 bool MemPass::HasOnlyNamesAndDecorates(uint32_t id) const {
   return get_def_use_mgr()->WhileEachUser(id, [this](Instruction* user) {
-    SpvOp op = user->opcode();
-    if (op != SpvOpName && !IsNonTypeDecorate(op)) {
+    spv::Op op = user->opcode();
+    if (op != spv::Op::OpName && !IsNonTypeDecorate(op)) {
       return false;
     }
     return true;
@@ -147,14 +149,15 @@
 
 bool MemPass::HasLoads(uint32_t varId) const {
   return !get_def_use_mgr()->WhileEachUser(varId, [this](Instruction* user) {
-    SpvOp op = user->opcode();
+    spv::Op op = user->opcode();
     // TODO(): The following is slightly conservative. Could be
     // better handling of non-store/name.
-    if (IsNonPtrAccessChain(op) || op == SpvOpCopyObject) {
+    if (IsNonPtrAccessChain(op) || op == spv::Op::OpCopyObject) {
       if (HasLoads(user->result_id())) {
         return false;
       }
-    } else if (op != SpvOpStore && op != SpvOpName && !IsNonTypeDecorate(op)) {
+    } else if (op != spv::Op::OpStore && op != spv::Op::OpName &&
+               !IsNonTypeDecorate(op)) {
       return false;
     }
     return true;
@@ -164,12 +167,12 @@
 bool MemPass::IsLiveVar(uint32_t varId) const {
   const Instruction* varInst = get_def_use_mgr()->GetDef(varId);
   // assume live if not a variable eg. function parameter
-  if (varInst->opcode() != SpvOpVariable) return true;
+  if (varInst->opcode() != spv::Op::OpVariable) return true;
   // non-function scope vars are live
   const uint32_t varTypeId = varInst->type_id();
   const Instruction* varTypeInst = get_def_use_mgr()->GetDef(varTypeId);
-  if (varTypeInst->GetSingleWordInOperand(kTypePointerStorageClassInIdx) !=
-      SpvStorageClassFunction)
+  if (spv::StorageClass(varTypeInst->GetSingleWordInOperand(
+          kTypePointerStorageClassInIdx)) != spv::StorageClass::Function)
     return true;
   // test if variable is loaded from
   return HasLoads(varId);
@@ -177,10 +180,10 @@
 
 void MemPass::AddStores(uint32_t ptr_id, std::queue<Instruction*>* insts) {
   get_def_use_mgr()->ForEachUser(ptr_id, [this, insts](Instruction* user) {
-    SpvOp op = user->opcode();
+    spv::Op op = user->opcode();
     if (IsNonPtrAccessChain(op)) {
       AddStores(user->result_id(), insts);
-    } else if (op == SpvOpStore) {
+    } else if (op == spv::Op::OpStore) {
       insts->push(user);
     }
   });
@@ -193,7 +196,7 @@
   while (!deadInsts.empty()) {
     Instruction* di = deadInsts.front();
     // Don't delete labels
-    if (di->opcode() == SpvOpLabel) {
+    if (di->opcode() == spv::Op::OpLabel) {
       deadInsts.pop();
       continue;
     }
@@ -202,7 +205,7 @@
     di->ForEachInId([&ids](uint32_t* iid) { ids.insert(*iid); });
     uint32_t varId = 0;
     // Remember variable if dead load
-    if (di->opcode() == SpvOpLoad) (void)GetPtr(di, &varId);
+    if (di->opcode() == spv::Op::OpLoad) (void)GetPtr(di, &varId);
     if (call_back) {
       call_back(di);
     }
@@ -230,9 +233,9 @@
         dbg_op == CommonDebugInfoDebugValue) {
       return true;
     }
-    SpvOp op = user->opcode();
-    if (op != SpvOpStore && op != SpvOpLoad && op != SpvOpName &&
-        !IsNonTypeDecorate(op)) {
+    spv::Op op = user->opcode();
+    if (op != spv::Op::OpStore && op != spv::Op::OpLoad &&
+        op != spv::Op::OpName && !IsNonTypeDecorate(op)) {
       return false;
     }
     return true;
@@ -248,7 +251,7 @@
   }
 
   std::unique_ptr<Instruction> undef_inst(
-      new Instruction(context(), SpvOpUndef, type_id, undefId, {}));
+      new Instruction(context(), spv::Op::OpUndef, type_id, undefId, {}));
   get_def_use_mgr()->AnalyzeInstDefUse(&*undef_inst);
   get_module()->AddGlobalValue(std::move(undef_inst));
   type2undefs_[type_id] = undefId;
@@ -264,11 +267,11 @@
     return false;
   if (seen_target_vars_.find(varId) != seen_target_vars_.end()) return true;
   const Instruction* varInst = get_def_use_mgr()->GetDef(varId);
-  if (varInst->opcode() != SpvOpVariable) return false;
+  if (varInst->opcode() != spv::Op::OpVariable) return false;
   const uint32_t varTypeId = varInst->type_id();
   const Instruction* varTypeInst = get_def_use_mgr()->GetDef(varTypeId);
-  if (varTypeInst->GetSingleWordInOperand(kTypePointerStorageClassInIdx) !=
-      SpvStorageClassFunction) {
+  if (spv::StorageClass(varTypeInst->GetSingleWordInOperand(
+          kTypePointerStorageClassInIdx)) != spv::StorageClass::Function) {
     seen_non_target_vars_.insert(varId);
     return false;
   }
@@ -489,8 +492,8 @@
   for (auto& blk : *func) {
     for (auto& inst : blk) {
       switch (inst.opcode()) {
-        case SpvOpStore:
-        case SpvOpLoad: {
+        case spv::Op::OpStore:
+        case spv::Op::OpLoad: {
           uint32_t varId;
           (void)GetPtr(&inst, &varId);
           if (!IsTargetVar(varId)) break;
diff --git a/source/opt/mem_pass.h b/source/opt/mem_pass.h
index 5a77670..aef9e5f 100644
--- a/source/opt/mem_pass.h
+++ b/source/opt/mem_pass.h
@@ -80,7 +80,7 @@
   bool IsTargetType(const Instruction* typeInst) const;
 
   // Returns true if |opcode| is a non-ptr access chain op
-  bool IsNonPtrAccessChain(const SpvOp opcode) const;
+  bool IsNonPtrAccessChain(const spv::Op opcode) const;
 
   // Given the id |ptrId|, return true if the top-most non-CopyObj is
   // a variable, a non-ptr access chain or a parameter of pointer type.
@@ -117,8 +117,8 @@
   bool CFGCleanup(Function* func);
 
   // Return true if |op| is supported decorate.
-  inline bool IsNonTypeDecorate(uint32_t op) const {
-    return (op == SpvOpDecorate || op == SpvOpDecorateId);
+  inline bool IsNonTypeDecorate(spv::Op op) const {
+    return (op == spv::Op::OpDecorate || op == spv::Op::OpDecorateId);
   }
 
   // Return the id of an undef value with type |type_id|.  Create and insert an
diff --git a/source/opt/merge_return_pass.cpp b/source/opt/merge_return_pass.cpp
index 7710dea..c262ea0 100644
--- a/source/opt/merge_return_pass.cpp
+++ b/source/opt/merge_return_pass.cpp
@@ -30,7 +30,7 @@
 
 Pass::Status MergeReturnPass::Process() {
   bool is_shader =
-      context()->get_feature_mgr()->HasCapability(SpvCapabilityShader);
+      context()->get_feature_mgr()->HasCapability(spv::Capability::Shader);
 
   bool failed = false;
   ProcessFunction pfn = [&failed, is_shader, this](Function* function) {
@@ -74,16 +74,16 @@
 
 void MergeReturnPass::GenerateState(BasicBlock* block) {
   if (Instruction* mergeInst = block->GetMergeInst()) {
-    if (mergeInst->opcode() == SpvOpLoopMerge) {
+    if (mergeInst->opcode() == spv::Op::OpLoopMerge) {
       // If new loop, break to this loop merge block
       state_.emplace_back(mergeInst, mergeInst);
     } else {
       auto branchInst = mergeInst->NextNode();
-      if (branchInst->opcode() == SpvOpSwitch) {
+      if (branchInst->opcode() == spv::Op::OpSwitch) {
         // If switch inside of loop, break to innermost loop merge block.
         // Otherwise need to break to this switch merge block.
         auto lastMergeInst = state_.back().BreakMergeInst();
-        if (lastMergeInst && lastMergeInst->opcode() == SpvOpLoopMerge)
+        if (lastMergeInst && lastMergeInst->opcode() == spv::Op::OpLoopMerge)
           state_.emplace_back(lastMergeInst, mergeInst);
         else
           state_.emplace_back(mergeInst, mergeInst);
@@ -174,7 +174,7 @@
 void MergeReturnPass::CreateReturnBlock() {
   // Create a label for the new return block
   std::unique_ptr<Instruction> return_label(
-      new Instruction(context(), SpvOpLabel, 0u, TakeNextId(), {}));
+      new Instruction(context(), spv::Op::OpLabel, 0u, TakeNextId(), {}));
 
   // Create the new basic block
   std::unique_ptr<BasicBlock> return_block(
@@ -195,37 +195,41 @@
     // Load and return the final return value
     uint32_t loadId = TakeNextId();
     block->AddInstruction(MakeUnique<Instruction>(
-        context(), SpvOpLoad, function_->type_id(), loadId,
+        context(), spv::Op::OpLoad, function_->type_id(), loadId,
         std::initializer_list<Operand>{
             {SPV_OPERAND_TYPE_ID, {return_value_->result_id()}}}));
     Instruction* var_inst = block->terminator();
     context()->AnalyzeDefUse(var_inst);
     context()->set_instr_block(var_inst, block);
     context()->get_decoration_mgr()->CloneDecorations(
-        return_value_->result_id(), loadId, {SpvDecorationRelaxedPrecision});
+        return_value_->result_id(), loadId,
+        {spv::Decoration::RelaxedPrecision});
 
     block->AddInstruction(MakeUnique<Instruction>(
-        context(), SpvOpReturnValue, 0, 0,
+        context(), spv::Op::OpReturnValue, 0, 0,
         std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {loadId}}}));
     context()->AnalyzeDefUse(block->terminator());
     context()->set_instr_block(block->terminator(), block);
   } else {
-    block->AddInstruction(MakeUnique<Instruction>(context(), SpvOpReturn));
+    block->AddInstruction(
+        MakeUnique<Instruction>(context(), spv::Op::OpReturn));
     context()->AnalyzeDefUse(block->terminator());
     context()->set_instr_block(block->terminator(), block);
   }
 }
 
 void MergeReturnPass::ProcessStructuredBlock(BasicBlock* block) {
-  SpvOp tail_opcode = block->tail()->opcode();
-  if (tail_opcode == SpvOpReturn || tail_opcode == SpvOpReturnValue) {
+  spv::Op tail_opcode = block->tail()->opcode();
+  if (tail_opcode == spv::Op::OpReturn ||
+      tail_opcode == spv::Op::OpReturnValue) {
     if (!return_flag_) {
       AddReturnFlag();
     }
   }
 
-  if (tail_opcode == SpvOpReturn || tail_opcode == SpvOpReturnValue ||
-      tail_opcode == SpvOpUnreachable) {
+  if (tail_opcode == spv::Op::OpReturn ||
+      tail_opcode == spv::Op::OpReturnValue ||
+      tail_opcode == spv::Op::OpUnreachable) {
     assert(CurrentState().InBreakable() &&
            "Should be in the placeholder construct.");
     BranchToBlock(block, CurrentState().BreakMergeId());
@@ -234,8 +238,8 @@
 }
 
 void MergeReturnPass::BranchToBlock(BasicBlock* block, uint32_t target) {
-  if (block->tail()->opcode() == SpvOpReturn ||
-      block->tail()->opcode() == SpvOpReturnValue) {
+  if (block->tail()->opcode() == spv::Op::OpReturn ||
+      block->tail()->opcode() == spv::Op::OpReturnValue) {
     RecordReturned(block);
     RecordReturnValue(block);
   }
@@ -247,7 +251,7 @@
   UpdatePhiNodes(block, target_block);
 
   Instruction* return_inst = block->terminator();
-  return_inst->SetOpcode(SpvOpBranch);
+  return_inst->SetOpcode(spv::Op::OpBranch);
   return_inst->ReplaceOperands({{SPV_OPERAND_TYPE_ID, {target}}});
   context()->get_def_use_mgr()->AnalyzeInstDefUse(return_inst);
   new_edges_[target_block].insert(block->id());
@@ -276,7 +280,7 @@
         &inst,
         [&users_to_update, &dom_tree, &inst, inst_bb, this](Instruction* user) {
           BasicBlock* user_bb = nullptr;
-          if (user->opcode() != SpvOpPhi) {
+          if (user->opcode() != spv::Op::OpPhi) {
             user_bb = context()->get_instr_block(user);
           } else {
             // For OpPhi, the use should be considered to be in the predecessor.
@@ -325,15 +329,16 @@
     // instruction.  If not, the Spir-V will be invalid.
     Instruction* inst_type = get_def_use_mgr()->GetDef(inst.type_id());
     bool regenerateInstruction = false;
-    if (inst_type->opcode() == SpvOpTypePointer) {
+    if (inst_type->opcode() == spv::Op::OpTypePointer) {
       if (!context()->get_feature_mgr()->HasCapability(
-              SpvCapabilityVariablePointers)) {
+              spv::Capability::VariablePointers)) {
         regenerateInstruction = true;
       }
 
-      uint32_t storage_class = inst_type->GetSingleWordInOperand(0);
-      if (storage_class != SpvStorageClassWorkgroup &&
-          storage_class != SpvStorageClassStorageBuffer) {
+      auto storage_class =
+          spv::StorageClass(inst_type->GetSingleWordInOperand(0));
+      if (storage_class != spv::StorageClass::Workgroup &&
+          storage_class != spv::StorageClass::StorageBuffer) {
         regenerateInstruction = true;
       }
     }
@@ -343,7 +348,7 @@
       uint32_t new_id = TakeNextId();
       regen_inst->SetResultId(new_id);
       Instruction* insert_pos = &*merge_block->begin();
-      while (insert_pos->opcode() == SpvOpPhi) {
+      while (insert_pos->opcode() == spv::Op::OpPhi) {
         insert_pos = insert_pos->NextNode();
       }
       new_phi = insert_pos->InsertBefore(std::move(regen_inst));
@@ -459,7 +464,7 @@
 
   // Leave the phi instructions behind.
   auto iter = block->begin();
-  while (iter->opcode() == SpvOpPhi) {
+  while (iter->opcode() == spv::Op::OpPhi) {
     ++iter;
   }
 
@@ -478,7 +483,7 @@
 
   // If |block| was a continue target for a loop |old_body| is now the correct
   // continue target.
-  if (break_merge_inst->opcode() == SpvOpLoopMerge &&
+  if (break_merge_inst->opcode() == spv::Op::OpLoopMerge &&
       break_merge_inst->GetSingleWordInOperand(1) == block->id()) {
     break_merge_inst->SetInOperand(1, {old_body->id()});
     context()->UpdateDefUse(break_merge_inst);
@@ -531,8 +536,8 @@
 }
 
 void MergeReturnPass::RecordReturned(BasicBlock* block) {
-  if (block->tail()->opcode() != SpvOpReturn &&
-      block->tail()->opcode() != SpvOpReturnValue)
+  if (block->tail()->opcode() != spv::Op::OpReturn &&
+      block->tail()->opcode() != spv::Op::OpReturnValue)
     return;
 
   assert(return_flag_ && "Did not generate the return flag variable.");
@@ -550,7 +555,7 @@
   }
 
   std::unique_ptr<Instruction> return_store(new Instruction(
-      context(), SpvOpStore, 0, 0,
+      context(), spv::Op::OpStore, 0, 0,
       std::initializer_list<Operand>{
           {SPV_OPERAND_TYPE_ID, {return_flag_->result_id()}},
           {SPV_OPERAND_TYPE_ID, {constant_true_->result_id()}}}));
@@ -563,7 +568,7 @@
 
 void MergeReturnPass::RecordReturnValue(BasicBlock* block) {
   auto terminator = *block->tail();
-  if (terminator.opcode() != SpvOpReturnValue) {
+  if (terminator.opcode() != spv::Op::OpReturnValue) {
     return;
   }
 
@@ -571,7 +576,7 @@
          "Did not generate the variable to hold the return value.");
 
   std::unique_ptr<Instruction> value_store(new Instruction(
-      context(), SpvOpStore, 0, 0,
+      context(), spv::Op::OpStore, 0, 0,
       std::initializer_list<Operand>{
           {SPV_OPERAND_TYPE_ID, {return_value_->result_id()}},
           {SPV_OPERAND_TYPE_ID, {terminator.GetSingleWordInOperand(0u)}}}));
@@ -586,17 +591,19 @@
   if (return_value_) return;
 
   uint32_t return_type_id = function_->type_id();
-  if (get_def_use_mgr()->GetDef(return_type_id)->opcode() == SpvOpTypeVoid)
+  if (get_def_use_mgr()->GetDef(return_type_id)->opcode() ==
+      spv::Op::OpTypeVoid)
     return;
 
   uint32_t return_ptr_type = context()->get_type_mgr()->FindPointerToType(
-      return_type_id, SpvStorageClassFunction);
+      return_type_id, spv::StorageClass::Function);
 
   uint32_t var_id = TakeNextId();
-  std::unique_ptr<Instruction> returnValue(new Instruction(
-      context(), SpvOpVariable, return_ptr_type, var_id,
-      std::initializer_list<Operand>{
-          {SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}}}));
+  std::unique_ptr<Instruction> returnValue(
+      new Instruction(context(), spv::Op::OpVariable, return_ptr_type, var_id,
+                      std::initializer_list<Operand>{
+                          {SPV_OPERAND_TYPE_STORAGE_CLASS,
+                           {uint32_t(spv::StorageClass::Function)}}}));
 
   auto insert_iter = function_->begin()->begin();
   insert_iter.InsertBefore(std::move(returnValue));
@@ -606,7 +613,7 @@
   context()->set_instr_block(return_value_, entry_block);
 
   context()->get_decoration_mgr()->CloneDecorations(
-      function_->result_id(), var_id, {SpvDecorationRelaxedPrecision});
+      function_->result_id(), var_id, {spv::Decoration::RelaxedPrecision});
 }
 
 void MergeReturnPass::AddReturnFlag() {
@@ -625,14 +632,14 @@
       const_mgr->GetDefiningInstruction(false_const)->result_id();
 
   uint32_t bool_ptr_id =
-      type_mgr->FindPointerToType(bool_id, SpvStorageClassFunction);
+      type_mgr->FindPointerToType(bool_id, spv::StorageClass::Function);
 
   uint32_t var_id = TakeNextId();
   std::unique_ptr<Instruction> returnFlag(new Instruction(
-      context(), SpvOpVariable, bool_ptr_id, var_id,
-      std::initializer_list<Operand>{
-          {SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}},
-          {SPV_OPERAND_TYPE_ID, {const_false_id}}}));
+      context(), spv::Op::OpVariable, bool_ptr_id, var_id,
+      std::initializer_list<Operand>{{SPV_OPERAND_TYPE_STORAGE_CLASS,
+                                      {uint32_t(spv::StorageClass::Function)}},
+                                     {SPV_OPERAND_TYPE_ID, {const_false_id}}}));
 
   auto insert_iter = function_->begin()->begin();
 
@@ -648,8 +655,8 @@
   std::vector<BasicBlock*> return_blocks;
   for (auto& block : *function) {
     Instruction& terminator = *block.tail();
-    if (terminator.opcode() == SpvOpReturn ||
-        terminator.opcode() == SpvOpReturnValue) {
+    if (terminator.opcode() == spv::Op::OpReturn ||
+        terminator.opcode() == spv::Op::OpReturnValue) {
       return_blocks.push_back(&block);
     }
   }
@@ -670,7 +677,7 @@
   // Create new return.
   std::vector<Operand> phi_ops;
   for (auto block : return_blocks) {
-    if (block->tail()->opcode() == SpvOpReturnValue) {
+    if (block->tail()->opcode() == spv::Op::OpReturnValue) {
       phi_ops.push_back(
           {SPV_OPERAND_TYPE_ID, {block->tail()->GetSingleWordInOperand(0u)}});
       phi_ops.push_back({SPV_OPERAND_TYPE_ID, {block->id()}});
@@ -682,12 +689,12 @@
     uint32_t phi_result_id = TakeNextId();
     uint32_t phi_type_id = function->type_id();
     std::unique_ptr<Instruction> phi_inst(new Instruction(
-        context(), SpvOpPhi, phi_type_id, phi_result_id, phi_ops));
+        context(), spv::Op::OpPhi, phi_type_id, phi_result_id, phi_ops));
     ret_block_iter->AddInstruction(std::move(phi_inst));
     BasicBlock::iterator phiIter = ret_block_iter->tail();
 
     std::unique_ptr<Instruction> return_inst(
-        new Instruction(context(), SpvOpReturnValue, 0u, 0u,
+        new Instruction(context(), spv::Op::OpReturnValue, 0u, 0u,
                         {{SPV_OPERAND_TYPE_ID, {phi_result_id}}}));
     ret_block_iter->AddInstruction(std::move(return_inst));
     BasicBlock::iterator ret = ret_block_iter->tail();
@@ -697,14 +704,14 @@
     get_def_use_mgr()->AnalyzeInstDef(&*ret);
   } else {
     std::unique_ptr<Instruction> return_inst(
-        new Instruction(context(), SpvOpReturn));
+        new Instruction(context(), spv::Op::OpReturn));
     ret_block_iter->AddInstruction(std::move(return_inst));
   }
 
   // Replace returns with branches
   for (auto block : return_blocks) {
     context()->ForgetUses(block->terminator());
-    block->tail()->SetOpcode(SpvOpBranch);
+    block->tail()->SetOpcode(spv::Op::OpBranch);
     block->tail()->ReplaceOperands({{SPV_OPERAND_TYPE_ID, {return_id}}});
     get_def_use_mgr()->AnalyzeInstUse(block->terminator());
     get_def_use_mgr()->AnalyzeInstUse(block->GetLabelInst());
@@ -789,7 +796,7 @@
 
 BasicBlock* MergeReturnPass::CreateContinueTarget(uint32_t header_label_id) {
   std::unique_ptr<Instruction> label(
-      new Instruction(context(), SpvOpLabel, 0u, TakeNextId(), {}));
+      new Instruction(context(), spv::Op::OpLabel, 0u, TakeNextId(), {}));
 
   // Create the new basic block
   std::unique_ptr<BasicBlock> block(new BasicBlock(std::move(label)));
@@ -824,7 +831,7 @@
   // block to make sure the OpVariable instructions remain in the entry block.
   BasicBlock* start_block = &*function_->begin();
   auto split_pos = start_block->begin();
-  while (split_pos->opcode() == SpvOpVariable) {
+  while (split_pos->opcode() == spv::Op::OpVariable) {
     ++split_pos;
   }
 
@@ -865,7 +872,7 @@
     if (struct_cfg_analysis->IsContinueBlock(bb.id())) {
       // |bb| must be an empty block ending with a branch to the header.
       Instruction* inst = &*bb.begin();
-      if (inst->opcode() != SpvOpBranch) {
+      if (inst->opcode() != spv::Op::OpBranch) {
         return true;
       }
 
@@ -875,7 +882,7 @@
       }
     } else if (struct_cfg_analysis->IsMergeBlock(bb.id())) {
       // |bb| must be an empty block ending with OpUnreachable.
-      if (bb.begin()->opcode() != SpvOpUnreachable) {
+      if (bb.begin()->opcode() != spv::Op::OpUnreachable) {
         return true;
       }
     } else {
diff --git a/source/opt/module.cpp b/source/opt/module.cpp
index 2f788ff..a9710c6 100644
--- a/source/opt/module.cpp
+++ b/source/opt/module.cpp
@@ -69,14 +69,14 @@
   return const_insts;
 }
 
-uint32_t Module::GetGlobalValue(SpvOp opcode) const {
+uint32_t Module::GetGlobalValue(spv::Op opcode) const {
   for (auto& inst : types_values_) {
     if (inst.opcode() == opcode) return inst.result_id();
   }
   return 0;
 }
 
-void Module::AddGlobalValue(SpvOp opcode, uint32_t result_id,
+void Module::AddGlobalValue(spv::Op opcode, uint32_t result_id,
                             uint32_t type_id) {
   std::unique_ptr<Instruction> newGlobal(
       new Instruction(context(), opcode, type_id, result_id, {}));
@@ -180,21 +180,23 @@
                                      ->get_feature_mgr()
                                      ->GetExtInstImportId_Shader100DebugInfo();
         if (shader_set_id != 0) {
-          binary->push_back((5 << 16) | static_cast<uint16_t>(SpvOpExtInst));
+          binary->push_back((5 << 16) |
+                            static_cast<uint16_t>(spv::Op::OpExtInst));
           binary->push_back(context()->get_type_mgr()->GetVoidTypeId());
           binary->push_back(context()->TakeNextId());
           binary->push_back(shader_set_id);
           binary->push_back(NonSemanticShaderDebugInfo100DebugNoLine);
         } else {
-          binary->push_back((1 << 16) | static_cast<uint16_t>(SpvOpNoLine));
+          binary->push_back((1 << 16) |
+                            static_cast<uint16_t>(spv::Op::OpNoLine));
         }
         last_line_inst = nullptr;
       }
     }
 
-    if (opcode == SpvOpLabel) {
+    if (opcode == spv::Op::OpLabel) {
       between_label_and_phi_var = true;
-    } else if (opcode != SpvOpVariable && opcode != SpvOpPhi &&
+    } else if (opcode != spv::Op::OpVariable && opcode != spv::Op::OpPhi &&
                !spvtools::opt::IsOpLineInst(opcode)) {
       between_label_and_phi_var = false;
     }
@@ -223,7 +225,8 @@
     between_merge_and_branch = false;
     if (spvOpcodeIsBlockTerminator(opcode) || i->IsNoLine()) {
       last_line_inst = nullptr;
-    } else if (opcode == SpvOpLoopMerge || opcode == SpvOpSelectionMerge) {
+    } else if (opcode == spv::Op::OpLoopMerge ||
+               opcode == spv::Op::OpSelectionMerge) {
       between_merge_and_branch = true;
       last_line_inst = nullptr;
     } else if (i->IsLine()) {
@@ -272,7 +275,7 @@
 std::ostream& operator<<(std::ostream& str, const Module& module) {
   module.ForEachInst([&str](const Instruction* inst) {
     str << *inst;
-    if (inst->opcode() != SpvOpFunctionEnd) {
+    if (inst->opcode() != spv::Op::OpFunctionEnd) {
       str << std::endl;
     }
   });
diff --git a/source/opt/module.h b/source/opt/module.h
index 7a6be46..ed2f345 100644
--- a/source/opt/module.h
+++ b/source/opt/module.h
@@ -136,10 +136,10 @@
   std::vector<const Instruction*> GetConstants() const;
 
   // Return result id of global value with |opcode|, 0 if not present.
-  uint32_t GetGlobalValue(SpvOp opcode) const;
+  uint32_t GetGlobalValue(spv::Op opcode) const;
 
   // Add global value with |opcode|, |result_id| and |type_id|
-  void AddGlobalValue(SpvOp opcode, uint32_t result_id, uint32_t type_id);
+  void AddGlobalValue(spv::Op opcode, uint32_t result_id, uint32_t type_id);
 
   inline uint32_t id_bound() const { return header_.bound; }
 
diff --git a/source/opt/pass.cpp b/source/opt/pass.cpp
index 017aad1..144e743 100644
--- a/source/opt/pass.cpp
+++ b/source/opt/pass.cpp
@@ -56,11 +56,11 @@
 
 Instruction* Pass::GetBaseType(uint32_t ty_id) {
   Instruction* ty_inst = get_def_use_mgr()->GetDef(ty_id);
-  if (ty_inst->opcode() == SpvOpTypeMatrix) {
+  if (ty_inst->opcode() == spv::Op::OpTypeMatrix) {
     uint32_t vty_id = ty_inst->GetSingleWordInOperand(0);
     ty_inst = get_def_use_mgr()->GetDef(vty_id);
   }
-  if (ty_inst->opcode() == SpvOpTypeVector) {
+  if (ty_inst->opcode() == spv::Op::OpTypeVector) {
     uint32_t cty_id = ty_inst->GetSingleWordInOperand(0);
     ty_inst = get_def_use_mgr()->GetDef(cty_id);
   }
@@ -69,12 +69,12 @@
 
 bool Pass::IsFloat(uint32_t ty_id, uint32_t width) {
   Instruction* ty_inst = GetBaseType(ty_id);
-  if (ty_inst->opcode() != SpvOpTypeFloat) return false;
+  if (ty_inst->opcode() != spv::Op::OpTypeFloat) return false;
   return ty_inst->GetSingleWordInOperand(0) == width;
 }
 
 uint32_t Pass::GetNullId(uint32_t type_id) {
-  if (IsFloat(type_id, 16)) context()->AddCapability(SpvCapabilityFloat16);
+  if (IsFloat(type_id, 16)) context()->AddCapability(spv::Capability::Float16);
   analysis::TypeManager* type_mgr = context()->get_type_mgr();
   analysis::ConstantManager* const_mgr = context()->get_constant_mgr();
   const analysis::Type* type = type_mgr->GetType(type_id);
diff --git a/source/opt/private_to_local_pass.cpp b/source/opt/private_to_local_pass.cpp
index 80fb4c5..36e534f 100644
--- a/source/opt/private_to_local_pass.cpp
+++ b/source/opt/private_to_local_pass.cpp
@@ -35,18 +35,18 @@
 
   // Private variables require the shader capability.  If this is not a shader,
   // there is no work to do.
-  if (context()->get_feature_mgr()->HasCapability(SpvCapabilityAddresses))
+  if (context()->get_feature_mgr()->HasCapability(spv::Capability::Addresses))
     return Status::SuccessWithoutChange;
 
   std::vector<std::pair<Instruction*, Function*>> variables_to_move;
   std::unordered_set<uint32_t> localized_variables;
   for (auto& inst : context()->types_values()) {
-    if (inst.opcode() != SpvOpVariable) {
+    if (inst.opcode() != spv::Op::OpVariable) {
       continue;
     }
 
-    if (inst.GetSingleWordInOperand(kVariableStorageClassInIdx) !=
-        SpvStorageClassPrivate) {
+    if (spv::StorageClass(inst.GetSingleWordInOperand(
+            kVariableStorageClassInIdx)) != spv::StorageClass::Private) {
       continue;
     }
 
@@ -123,7 +123,8 @@
   context()->ForgetUses(variable);
 
   // Update the storage class of the variable.
-  variable->SetInOperand(kVariableStorageClassInIdx, {SpvStorageClassFunction});
+  variable->SetInOperand(kVariableStorageClassInIdx,
+                         {uint32_t(spv::StorageClass::Function)});
 
   // Update the type as well.
   uint32_t new_type_id = GetNewType(variable->type_id());
@@ -147,7 +148,7 @@
   uint32_t pointee_type_id =
       old_type_inst->GetSingleWordInOperand(kSpvTypePointerTypeIdInIdx);
   uint32_t new_type_id =
-      type_mgr->FindPointerToType(pointee_type_id, SpvStorageClassFunction);
+      type_mgr->FindPointerToType(pointee_type_id, spv::StorageClass::Function);
   if (new_type_id != 0) {
     context()->UpdateDefUse(context()->get_def_use_mgr()->GetDef(new_type_id));
   }
@@ -161,17 +162,17 @@
     return true;
   }
   switch (inst->opcode()) {
-    case SpvOpLoad:
-    case SpvOpStore:
-    case SpvOpImageTexelPointer:  // Treat like a load
+    case spv::Op::OpLoad:
+    case spv::Op::OpStore:
+    case spv::Op::OpImageTexelPointer:  // Treat like a load
       return true;
-    case SpvOpAccessChain:
+    case spv::Op::OpAccessChain:
       return context()->get_def_use_mgr()->WhileEachUser(
           inst, [this](const Instruction* user) {
             if (!IsValidUse(user)) return false;
             return true;
           });
-    case SpvOpName:
+    case spv::Op::OpName:
       return true;
     default:
       return spvOpcodeIsDecoration(inst->opcode());
@@ -188,13 +189,13 @@
     return true;
   }
   switch (inst->opcode()) {
-    case SpvOpLoad:
-    case SpvOpStore:
-    case SpvOpImageTexelPointer:  // Treat like a load
+    case spv::Op::OpLoad:
+    case spv::Op::OpStore:
+    case spv::Op::OpImageTexelPointer:  // Treat like a load
       // The type is fine because it is the type pointed to, and that does not
       // change.
       break;
-    case SpvOpAccessChain: {
+    case spv::Op::OpAccessChain: {
       context()->ForgetUses(inst);
       uint32_t new_type_id = GetNewType(inst->type_id());
       if (new_type_id == 0) {
@@ -208,8 +209,8 @@
         return false;
       }
     } break;
-    case SpvOpName:
-    case SpvOpEntryPoint:  // entry points will be updated separately.
+    case spv::Op::OpName:
+    case spv::Op::OpEntryPoint:  // entry points will be updated separately.
       break;
     default:
       assert(spvOpcodeIsDecoration(inst->opcode()) &&
diff --git a/source/opt/propagator.cpp b/source/opt/propagator.cpp
index 6a1f1aa..9cd6174 100644
--- a/source/opt/propagator.cpp
+++ b/source/opt/propagator.cpp
@@ -134,7 +134,7 @@
   // defined at an instruction D that should be simulated again, then the output
   // of D might affect |instr|, so we should simulate |instr| again.
   bool has_operands_to_simulate = false;
-  if (instr->opcode() == SpvOpPhi) {
+  if (instr->opcode() == spv::Op::OpPhi) {
     // For Phi instructions, an operand causes the Phi to be simulated again if
     // the operand comes from an edge that has not yet been traversed or if its
     // definition should be simulated again.
@@ -189,7 +189,7 @@
   // statement in it.
   if (!BlockHasBeenSimulated(block)) {
     block->ForEachInst([this, &changed](Instruction* instr) {
-      if (instr->opcode() != SpvOpPhi) {
+      if (instr->opcode() != spv::Op::OpPhi) {
         changed |= Simulate(instr);
       }
     });
diff --git a/source/opt/propagator.h b/source/opt/propagator.h
index ac7c0e7..71212c9 100644
--- a/source/opt/propagator.h
+++ b/source/opt/propagator.h
@@ -153,10 +153,10 @@
 //   std::map<uint32_t, uint32_t> values;
 //   const auto visit_fn = [&ctx, &values](Instruction* instr,
 //                                         BasicBlock** dest_bb) {
-//     if (instr->opcode() == SpvOpStore) {
+//     if (instr->opcode() == spv::Op::OpStore) {
 //       uint32_t rhs_id = instr->GetSingleWordOperand(1);
 //       Instruction* rhs_def = ctx->get_def_use_mgr()->GetDef(rhs_id);
-//       if (rhs_def->opcode() == SpvOpConstant) {
+//       if (rhs_def->opcode() == spv::Op::OpConstant) {
 //         uint32_t val = rhs_def->GetSingleWordOperand(2);
 //         values[rhs_id] = val;
 //         return SSAPropagator::kInteresting;
diff --git a/source/opt/reduce_load_size.cpp b/source/opt/reduce_load_size.cpp
index 56491b2..860ba21 100644
--- a/source/opt/reduce_load_size.cpp
+++ b/source/opt/reduce_load_size.cpp
@@ -38,7 +38,7 @@
 
   for (auto& func : *get_module()) {
     func.ForEachInst([&modified, this](Instruction* inst) {
-      if (inst->opcode() == SpvOpCompositeExtract) {
+      if (inst->opcode() == spv::Op::OpCompositeExtract) {
         if (ShouldReplaceExtract(inst)) {
           modified |= ReplaceExtract(inst);
         }
@@ -50,7 +50,7 @@
 }
 
 bool ReduceLoadSize::ReplaceExtract(Instruction* inst) {
-  assert(inst->opcode() == SpvOpCompositeExtract &&
+  assert(inst->opcode() == spv::Op::OpCompositeExtract &&
          "Wrong opcode.  Should be OpCompositeExtract.");
   analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr();
   analysis::TypeManager* type_mgr = context()->get_type_mgr();
@@ -60,7 +60,7 @@
       inst->GetSingleWordInOperand(kExtractCompositeIdInIdx);
   Instruction* composite_inst = def_use_mgr->GetDef(composite_id);
 
-  if (composite_inst->opcode() != SpvOpLoad) {
+  if (composite_inst->opcode() != spv::Op::OpLoad) {
     return false;
   }
 
@@ -71,16 +71,16 @@
   }
 
   Instruction* var = composite_inst->GetBaseAddress();
-  if (var == nullptr || var->opcode() != SpvOpVariable) {
+  if (var == nullptr || var->opcode() != spv::Op::OpVariable) {
     return false;
   }
 
-  SpvStorageClass storage_class = static_cast<SpvStorageClass>(
+  spv::StorageClass storage_class = static_cast<spv::StorageClass>(
       var->GetSingleWordInOperand(kVariableStorageClassInIdx));
   switch (storage_class) {
-    case SpvStorageClassUniform:
-    case SpvStorageClassUniformConstant:
-    case SpvStorageClassInput:
+    case spv::StorageClass::Uniform:
+    case spv::StorageClass::UniformConstant:
+    case spv::StorageClass::Input:
       break;
     default:
       return false;
@@ -124,7 +124,7 @@
   Instruction* op_inst = def_use_mgr->GetDef(
       inst->GetSingleWordInOperand(kExtractCompositeIdInIdx));
 
-  if (op_inst->opcode() != SpvOpLoad) {
+  if (op_inst->opcode() != spv::Op::OpLoad) {
     return false;
   }
 
@@ -139,7 +139,7 @@
   all_elements_used =
       !def_use_mgr->WhileEachUser(op_inst, [&elements_used](Instruction* use) {
         if (use->IsCommonDebugInstr()) return true;
-        if (use->opcode() != SpvOpCompositeExtract ||
+        if (use->opcode() != spv::Op::OpCompositeExtract ||
             use->NumInOperands() == 1) {
           return false;
         }
diff --git a/source/opt/reflect.h b/source/opt/reflect.h
index c2ffb0b..1c34600 100644
--- a/source/opt/reflect.h
+++ b/source/opt/reflect.h
@@ -24,41 +24,48 @@
 // following functions tend to be outdated and should be updated when SPIR-V
 // version bumps.
 
-inline bool IsDebug1Inst(SpvOp opcode) {
-  return (opcode >= SpvOpSourceContinued && opcode <= SpvOpSourceExtension) ||
-         opcode == SpvOpString;
+inline bool IsDebug1Inst(spv::Op opcode) {
+  return (opcode >= spv::Op::OpSourceContinued &&
+          opcode <= spv::Op::OpSourceExtension) ||
+         opcode == spv::Op::OpString;
 }
-inline bool IsDebug2Inst(SpvOp opcode) {
-  return opcode == SpvOpName || opcode == SpvOpMemberName;
+inline bool IsDebug2Inst(spv::Op opcode) {
+  return opcode == spv::Op::OpName || opcode == spv::Op::OpMemberName;
 }
-inline bool IsDebug3Inst(SpvOp opcode) {
-  return opcode == SpvOpModuleProcessed;
+inline bool IsDebug3Inst(spv::Op opcode) {
+  return opcode == spv::Op::OpModuleProcessed;
 }
-inline bool IsOpLineInst(SpvOp opcode) {
-  return opcode == SpvOpLine || opcode == SpvOpNoLine;
+inline bool IsOpLineInst(spv::Op opcode) {
+  return opcode == spv::Op::OpLine || opcode == spv::Op::OpNoLine;
 }
-inline bool IsAnnotationInst(SpvOp opcode) {
-  return (opcode >= SpvOpDecorate && opcode <= SpvOpGroupMemberDecorate) ||
-         opcode == SpvOpDecorateId || opcode == SpvOpDecorateStringGOOGLE ||
-         opcode == SpvOpMemberDecorateStringGOOGLE;
+inline bool IsAnnotationInst(spv::Op opcode) {
+  return (opcode >= spv::Op::OpDecorate &&
+          opcode <= spv::Op::OpGroupMemberDecorate) ||
+         opcode == spv::Op::OpDecorateId ||
+         opcode == spv::Op::OpDecorateStringGOOGLE ||
+         opcode == spv::Op::OpMemberDecorateStringGOOGLE;
 }
-inline bool IsTypeInst(SpvOp opcode) {
-  return (opcode >= SpvOpTypeVoid && opcode <= SpvOpTypeForwardPointer) ||
-         opcode == SpvOpTypePipeStorage || opcode == SpvOpTypeNamedBarrier ||
-         opcode == SpvOpTypeAccelerationStructureNV ||
-         opcode == SpvOpTypeAccelerationStructureKHR ||
-         opcode == SpvOpTypeRayQueryKHR ||
-         opcode == SpvOpTypeCooperativeMatrixNV;
+inline bool IsTypeInst(spv::Op opcode) {
+  return (opcode >= spv::Op::OpTypeVoid &&
+          opcode <= spv::Op::OpTypeForwardPointer) ||
+         opcode == spv::Op::OpTypePipeStorage ||
+         opcode == spv::Op::OpTypeNamedBarrier ||
+         opcode == spv::Op::OpTypeAccelerationStructureNV ||
+         opcode == spv::Op::OpTypeAccelerationStructureKHR ||
+         opcode == spv::Op::OpTypeRayQueryKHR ||
+         opcode == spv::Op::OpTypeCooperativeMatrixNV;
 }
-inline bool IsConstantInst(SpvOp opcode) {
-  return (opcode >= SpvOpConstantTrue && opcode <= SpvOpSpecConstantOp) ||
-         opcode == SpvOpConstantFunctionPointerINTEL;
+inline bool IsConstantInst(spv::Op opcode) {
+  return (opcode >= spv::Op::OpConstantTrue &&
+          opcode <= spv::Op::OpSpecConstantOp) ||
+         opcode == spv::Op::OpConstantFunctionPointerINTEL;
 }
-inline bool IsCompileTimeConstantInst(SpvOp opcode) {
-  return opcode >= SpvOpConstantTrue && opcode <= SpvOpConstantNull;
+inline bool IsCompileTimeConstantInst(spv::Op opcode) {
+  return opcode >= spv::Op::OpConstantTrue && opcode <= spv::Op::OpConstantNull;
 }
-inline bool IsSpecConstantInst(SpvOp opcode) {
-  return opcode >= SpvOpSpecConstantTrue && opcode <= SpvOpSpecConstantOp;
+inline bool IsSpecConstantInst(spv::Op opcode) {
+  return opcode >= spv::Op::OpSpecConstantTrue &&
+         opcode <= spv::Op::OpSpecConstantOp;
 }
 
 }  // namespace opt
diff --git a/source/opt/register_pressure.cpp b/source/opt/register_pressure.cpp
index 1ad3373..505210b 100644
--- a/source/opt/register_pressure.cpp
+++ b/source/opt/register_pressure.cpp
@@ -36,7 +36,7 @@
       : context_(context), bb_(bb) {}
 
   bool operator()(Instruction* insn) const {
-    return !(insn->opcode() == SpvOpPhi &&
+    return !(insn->opcode() == spv::Op::OpPhi &&
              context_->get_instr_block(insn) == bb_);
   }
 
@@ -49,9 +49,9 @@
 // physical register.
 bool CreatesRegisterUsage(Instruction* insn) {
   if (!insn->HasResultId()) return false;
-  if (insn->opcode() == SpvOpUndef) return false;
+  if (insn->opcode() == spv::Op::OpUndef) return false;
   if (IsConstantInst(insn->opcode())) return false;
-  if (insn->opcode() == SpvOpLabel) return false;
+  if (insn->opcode() == spv::Op::OpLabel) return false;
   return true;
 }
 
@@ -147,7 +147,7 @@
 
     live_inout->live_in_ = live_inout->live_out_;
     for (Instruction& insn : make_range(bb->rbegin(), bb->rend())) {
-      if (insn.opcode() == SpvOpPhi) {
+      if (insn.opcode() == spv::Op::OpPhi) {
         live_inout->live_in_.insert(&insn);
         break;
       }
@@ -224,7 +224,7 @@
       for (Instruction& insn : make_range(bb.rbegin(), bb.rend())) {
         // If it is a phi instruction, the register pressure will not change
         // anymore.
-        if (insn.opcode() == SpvOpPhi) {
+        if (insn.opcode() == spv::Op::OpPhi) {
           break;
         }
 
@@ -271,7 +271,7 @@
   RegisterLiveness::RegisterClass reg_class{type, false};
 
   insn->context()->get_decoration_mgr()->WhileEachDecoration(
-      insn->result_id(), SpvDecorationUniform,
+      insn->result_id(), uint32_t(spv::Decoration::Uniform),
       [&reg_class](const Instruction&) {
         reg_class.is_uniform_ = true;
         return false;
@@ -325,7 +325,7 @@
         loop_reg_pressure->used_registers_, live_inout->used_registers_);
 
     for (Instruction& insn : *bb) {
-      if (insn.opcode() == SpvOpPhi || !CreatesRegisterUsage(&insn) ||
+      if (insn.opcode() == spv::Op::OpPhi || !CreatesRegisterUsage(&insn) ||
           seen_insn.count(insn.result_id())) {
         continue;
       }
@@ -386,7 +386,7 @@
       [&l1, &l2](Instruction* insn) {
         BasicBlock* bb = insn->context()->get_instr_block(insn);
         return insn->HasResultId() &&
-               !(insn->opcode() == SpvOpPhi &&
+               !(insn->opcode() == spv::Op::OpPhi &&
                  (bb == l1.GetHeaderBlock() || bb == l2.GetHeaderBlock()));
       });
 
@@ -403,7 +403,7 @@
                      live_inout_info->live_out_.size());
 
     for (Instruction& insn : *bb) {
-      if (insn.opcode() == SpvOpPhi || !CreatesRegisterUsage(&insn) ||
+      if (insn.opcode() == spv::Op::OpPhi || !CreatesRegisterUsage(&insn) ||
           seen_insn.count(insn.result_id())) {
         continue;
       }
@@ -434,7 +434,7 @@
                      live_inout_info->live_out_.size());
 
     for (Instruction& insn : *bb) {
-      if (insn.opcode() == SpvOpPhi || !CreatesRegisterUsage(&insn) ||
+      if (insn.opcode() == spv::Op::OpPhi || !CreatesRegisterUsage(&insn) ||
           seen_insn.count(insn.result_id())) {
         continue;
       }
@@ -532,7 +532,7 @@
 
     std::unordered_set<uint32_t> die_in_block;
     for (Instruction& insn : make_range(bb->rbegin(), bb->rend())) {
-      if (insn.opcode() == SpvOpPhi) {
+      if (insn.opcode() == spv::Op::OpPhi) {
         break;
       }
 
diff --git a/source/opt/relax_float_ops_pass.cpp b/source/opt/relax_float_ops_pass.cpp
index 3fcf879..df925a2 100644
--- a/source/opt/relax_float_ops_pass.cpp
+++ b/source/opt/relax_float_ops_pass.cpp
@@ -25,7 +25,7 @@
   return target_ops_core_f_rslt_.count(inst->opcode()) != 0 ||
          target_ops_core_f_opnd_.count(inst->opcode()) != 0 ||
          sample_ops_.count(inst->opcode()) != 0 ||
-         (inst->opcode() == SpvOpExtInst &&
+         (inst->opcode() == spv::Op::OpExtInst &&
           inst->GetSingleWordInOperand(0) ==
               context()->get_feature_mgr()->GetExtInstImportId_GLSLstd450() &&
           target_ops_450_.count(inst->GetSingleWordInOperand(1)) != 0);
@@ -46,8 +46,9 @@
 
 bool RelaxFloatOpsPass::IsRelaxed(uint32_t r_id) {
   for (auto r_inst : get_decoration_mgr()->GetDecorationsFor(r_id, false))
-    if (r_inst->opcode() == SpvOpDecorate &&
-        r_inst->GetSingleWordInOperand(1) == SpvDecorationRelaxedPrecision)
+    if (r_inst->opcode() == spv::Op::OpDecorate &&
+        spv::Decoration(r_inst->GetSingleWordInOperand(1)) ==
+            spv::Decoration::RelaxedPrecision)
       return true;
   return false;
 }
@@ -58,7 +59,8 @@
   if (!IsFloat32(r_inst)) return false;
   if (IsRelaxed(r_id)) return false;
   if (!IsRelaxable(r_inst)) return false;
-  get_decoration_mgr()->AddDecoration(r_id, SpvDecorationRelaxedPrecision);
+  get_decoration_mgr()->AddDecoration(
+      r_id, uint32_t(spv::Decoration::RelaxedPrecision));
   return true;
 }
 
@@ -87,48 +89,48 @@
 
 void RelaxFloatOpsPass::Initialize() {
   target_ops_core_f_rslt_ = {
-      SpvOpLoad,
-      SpvOpPhi,
-      SpvOpVectorExtractDynamic,
-      SpvOpVectorInsertDynamic,
-      SpvOpVectorShuffle,
-      SpvOpCompositeExtract,
-      SpvOpCompositeConstruct,
-      SpvOpCompositeInsert,
-      SpvOpCopyObject,
-      SpvOpTranspose,
-      SpvOpConvertSToF,
-      SpvOpConvertUToF,
-      SpvOpFConvert,
-      // SpvOpQuantizeToF16,
-      SpvOpFNegate,
-      SpvOpFAdd,
-      SpvOpFSub,
-      SpvOpFMul,
-      SpvOpFDiv,
-      SpvOpFMod,
-      SpvOpVectorTimesScalar,
-      SpvOpMatrixTimesScalar,
-      SpvOpVectorTimesMatrix,
-      SpvOpMatrixTimesVector,
-      SpvOpMatrixTimesMatrix,
-      SpvOpOuterProduct,
-      SpvOpDot,
-      SpvOpSelect,
+      spv::Op::OpLoad,
+      spv::Op::OpPhi,
+      spv::Op::OpVectorExtractDynamic,
+      spv::Op::OpVectorInsertDynamic,
+      spv::Op::OpVectorShuffle,
+      spv::Op::OpCompositeExtract,
+      spv::Op::OpCompositeConstruct,
+      spv::Op::OpCompositeInsert,
+      spv::Op::OpCopyObject,
+      spv::Op::OpTranspose,
+      spv::Op::OpConvertSToF,
+      spv::Op::OpConvertUToF,
+      spv::Op::OpFConvert,
+      // spv::Op::OpQuantizeToF16,
+      spv::Op::OpFNegate,
+      spv::Op::OpFAdd,
+      spv::Op::OpFSub,
+      spv::Op::OpFMul,
+      spv::Op::OpFDiv,
+      spv::Op::OpFMod,
+      spv::Op::OpVectorTimesScalar,
+      spv::Op::OpMatrixTimesScalar,
+      spv::Op::OpVectorTimesMatrix,
+      spv::Op::OpMatrixTimesVector,
+      spv::Op::OpMatrixTimesMatrix,
+      spv::Op::OpOuterProduct,
+      spv::Op::OpDot,
+      spv::Op::OpSelect,
   };
   target_ops_core_f_opnd_ = {
-      SpvOpFOrdEqual,
-      SpvOpFUnordEqual,
-      SpvOpFOrdNotEqual,
-      SpvOpFUnordNotEqual,
-      SpvOpFOrdLessThan,
-      SpvOpFUnordLessThan,
-      SpvOpFOrdGreaterThan,
-      SpvOpFUnordGreaterThan,
-      SpvOpFOrdLessThanEqual,
-      SpvOpFUnordLessThanEqual,
-      SpvOpFOrdGreaterThanEqual,
-      SpvOpFUnordGreaterThanEqual,
+      spv::Op::OpFOrdEqual,
+      spv::Op::OpFUnordEqual,
+      spv::Op::OpFOrdNotEqual,
+      spv::Op::OpFUnordNotEqual,
+      spv::Op::OpFOrdLessThan,
+      spv::Op::OpFUnordLessThan,
+      spv::Op::OpFOrdGreaterThan,
+      spv::Op::OpFUnordGreaterThan,
+      spv::Op::OpFOrdLessThanEqual,
+      spv::Op::OpFUnordLessThanEqual,
+      spv::Op::OpFOrdGreaterThanEqual,
+      spv::Op::OpFUnordGreaterThanEqual,
   };
   target_ops_450_ = {
       GLSLstd450Round, GLSLstd450RoundEven, GLSLstd450Trunc, GLSLstd450FAbs,
@@ -147,31 +149,31 @@
       GLSLstd450Ldexp, GLSLstd450Length, GLSLstd450Distance, GLSLstd450Cross,
       GLSLstd450Normalize, GLSLstd450FaceForward, GLSLstd450Reflect,
       GLSLstd450Refract, GLSLstd450NMin, GLSLstd450NMax, GLSLstd450NClamp};
-  sample_ops_ = {SpvOpImageSampleImplicitLod,
-                 SpvOpImageSampleExplicitLod,
-                 SpvOpImageSampleDrefImplicitLod,
-                 SpvOpImageSampleDrefExplicitLod,
-                 SpvOpImageSampleProjImplicitLod,
-                 SpvOpImageSampleProjExplicitLod,
-                 SpvOpImageSampleProjDrefImplicitLod,
-                 SpvOpImageSampleProjDrefExplicitLod,
-                 SpvOpImageFetch,
-                 SpvOpImageGather,
-                 SpvOpImageDrefGather,
-                 SpvOpImageRead,
-                 SpvOpImageSparseSampleImplicitLod,
-                 SpvOpImageSparseSampleExplicitLod,
-                 SpvOpImageSparseSampleDrefImplicitLod,
-                 SpvOpImageSparseSampleDrefExplicitLod,
-                 SpvOpImageSparseSampleProjImplicitLod,
-                 SpvOpImageSparseSampleProjExplicitLod,
-                 SpvOpImageSparseSampleProjDrefImplicitLod,
-                 SpvOpImageSparseSampleProjDrefExplicitLod,
-                 SpvOpImageSparseFetch,
-                 SpvOpImageSparseGather,
-                 SpvOpImageSparseDrefGather,
-                 SpvOpImageSparseTexelsResident,
-                 SpvOpImageSparseRead};
+  sample_ops_ = {spv::Op::OpImageSampleImplicitLod,
+                 spv::Op::OpImageSampleExplicitLod,
+                 spv::Op::OpImageSampleDrefImplicitLod,
+                 spv::Op::OpImageSampleDrefExplicitLod,
+                 spv::Op::OpImageSampleProjImplicitLod,
+                 spv::Op::OpImageSampleProjExplicitLod,
+                 spv::Op::OpImageSampleProjDrefImplicitLod,
+                 spv::Op::OpImageSampleProjDrefExplicitLod,
+                 spv::Op::OpImageFetch,
+                 spv::Op::OpImageGather,
+                 spv::Op::OpImageDrefGather,
+                 spv::Op::OpImageRead,
+                 spv::Op::OpImageSparseSampleImplicitLod,
+                 spv::Op::OpImageSparseSampleExplicitLod,
+                 spv::Op::OpImageSparseSampleDrefImplicitLod,
+                 spv::Op::OpImageSparseSampleDrefExplicitLod,
+                 spv::Op::OpImageSparseSampleProjImplicitLod,
+                 spv::Op::OpImageSparseSampleProjExplicitLod,
+                 spv::Op::OpImageSparseSampleProjDrefImplicitLod,
+                 spv::Op::OpImageSparseSampleProjDrefExplicitLod,
+                 spv::Op::OpImageSparseFetch,
+                 spv::Op::OpImageSparseGather,
+                 spv::Op::OpImageSparseDrefGather,
+                 spv::Op::OpImageSparseTexelsResident,
+                 spv::Op::OpImageSparseRead};
 }
 
 }  // namespace opt
diff --git a/source/opt/relax_float_ops_pass.h b/source/opt/relax_float_ops_pass.h
index 5ee3d73..9e4606f 100644
--- a/source/opt/relax_float_ops_pass.h
+++ b/source/opt/relax_float_ops_pass.h
@@ -61,17 +61,23 @@
   // Initialize state for converting to half
   void Initialize();
 
+  struct hasher {
+    size_t operator()(const spv::Op& op) const noexcept {
+      return std::hash<uint32_t>()(uint32_t(op));
+    }
+  };
+
   // Set of float result core operations to be processed
-  std::unordered_set<uint32_t> target_ops_core_f_rslt_;
+  std::unordered_set<spv::Op, hasher> target_ops_core_f_rslt_;
 
   // Set of float operand core operations to be processed
-  std::unordered_set<uint32_t> target_ops_core_f_opnd_;
+  std::unordered_set<spv::Op, hasher> target_ops_core_f_opnd_;
 
   // Set of 450 extension operations to be processed
   std::unordered_set<uint32_t> target_ops_450_;
 
   // Set of sample operations
-  std::unordered_set<uint32_t> sample_ops_;
+  std::unordered_set<spv::Op, hasher> sample_ops_;
 };
 
 }  // namespace opt
diff --git a/source/opt/remove_dontinline_pass.cpp b/source/opt/remove_dontinline_pass.cpp
index 4dd1cd4..3750bc1 100644
--- a/source/opt/remove_dontinline_pass.cpp
+++ b/source/opt/remove_dontinline_pass.cpp
@@ -37,10 +37,11 @@
   uint32_t function_control =
       function_inst->GetSingleWordInOperand(kFunctionControlInOperandIdx);
 
-  if ((function_control & SpvFunctionControlDontInlineMask) == 0) {
+  if ((function_control & uint32_t(spv::FunctionControlMask::DontInline)) ==
+      0) {
     return false;
   }
-  function_control &= ~SpvFunctionControlDontInlineMask;
+  function_control &= ~uint32_t(spv::FunctionControlMask::DontInline);
   function_inst->SetInOperand(kFunctionControlInOperandIdx, {function_control});
   return true;
 }
diff --git a/source/opt/remove_duplicates_pass.cpp b/source/opt/remove_duplicates_pass.cpp
index 1ed8e2a..90c3acf 100644
--- a/source/opt/remove_duplicates_pass.cpp
+++ b/source/opt/remove_duplicates_pass.cpp
@@ -70,7 +70,7 @@
     return modified;
   }
 
-  std::unordered_map<std::string, SpvId> ext_inst_imports;
+  std::unordered_map<std::string, spv::Id> ext_inst_imports;
   for (auto* i = &*context()->ext_inst_import_begin(); i;) {
     auto res = ext_inst_imports.emplace(i->GetInOperand(0u).AsString(),
                                         i->result_id());
@@ -101,7 +101,8 @@
   std::vector<analysis::ForwardPointer> visited_forward_pointers;
   std::vector<Instruction*> to_delete;
   for (auto* i = &*context()->types_values_begin(); i; i = i->NextNode()) {
-    const bool is_i_forward_pointer = i->opcode() == SpvOpTypeForwardPointer;
+    const bool is_i_forward_pointer =
+        i->opcode() == spv::Op::OpTypeForwardPointer;
 
     // We only care about types.
     if (!spvOpcodeGeneratesType(i->opcode()) && !is_i_forward_pointer) {
@@ -110,7 +111,7 @@
 
     if (!is_i_forward_pointer) {
       // Is the current type equal to one of the types we have already visited?
-      SpvId id_to_keep = 0u;
+      spv::Id id_to_keep = 0u;
       analysis::Type* i_type = type_manager.GetType(i->result_id());
       assert(i_type);
       // TODO(dneto0): Use a trie to avoid quadratic behaviour? Extract the
@@ -137,7 +138,7 @@
     } else {
       analysis::ForwardPointer i_type(
           i->GetSingleWordInOperand(0u),
-          (SpvStorageClass)i->GetSingleWordInOperand(1u));
+          (spv::StorageClass)i->GetSingleWordInOperand(1u));
       i_type.SetTargetPointer(
           type_manager.GetType(i_type.target_id())->AsPointer());
 
diff --git a/source/opt/remove_unused_interface_variables_pass.cpp b/source/opt/remove_unused_interface_variables_pass.cpp
index 31e87bd..d4df1b2 100644
--- a/source/opt/remove_unused_interface_variables_pass.cpp
+++ b/source/opt/remove_unused_interface_variables_pass.cpp
@@ -31,13 +31,14 @@
         instruction.ForEachInId([&](const uint32_t* id) {
           if (used_variables_.count(*id)) return;
           auto* var = parent_.get_def_use_mgr()->GetDef(*id);
-          if (!var || var->opcode() != SpvOpVariable) return;
-          auto storage_class = var->GetSingleWordInOperand(0);
-          if (storage_class != SpvStorageClassFunction &&
+          if (!var || var->opcode() != spv::Op::OpVariable) return;
+          auto storage_class =
+              spv::StorageClass(var->GetSingleWordInOperand(0));
+          if (storage_class != spv::StorageClass::Function &&
               (parent_.get_module()->version() >=
                    SPV_SPIRV_VERSION_WORD(1, 4) ||
-               storage_class == SpvStorageClassInput ||
-               storage_class == SpvStorageClassOutput))
+               storage_class == spv::StorageClass::Input ||
+               storage_class == spv::StorageClass::Output))
             used_variables_.insert(*id);
         });
     return false;
@@ -90,4 +91,4 @@
   return (modified ? Status::SuccessWithChange : Status::SuccessWithoutChange);
 }
 }  // namespace opt
-}  // namespace spvtools
\ No newline at end of file
+}  // namespace spvtools
diff --git a/source/opt/replace_desc_array_access_using_var_index.cpp b/source/opt/replace_desc_array_access_using_var_index.cpp
index e97593e..1b233fb 100644
--- a/source/opt/replace_desc_array_access_using_var_index.cpp
+++ b/source/opt/replace_desc_array_access_using_var_index.cpp
@@ -54,8 +54,8 @@
   std::vector<Instruction*> work_list;
   get_def_use_mgr()->ForEachUser(var, [&work_list](Instruction* use) {
     switch (use->opcode()) {
-      case SpvOpAccessChain:
-      case SpvOpInBoundsAccessChain:
+      case spv::Op::OpAccessChain:
+      case spv::Op::OpInBoundsAccessChain:
         work_list.push_back(use);
         break;
       default:
@@ -132,8 +132,8 @@
     Instruction* operand = get_def_use_mgr()->GetDef(*idp);
     if (context()->get_instr_block(operand) != nullptr &&
         (HasImageOrImagePtrType(operand) ||
-         operand->opcode() == SpvOpAccessChain ||
-         operand->opcode() == SpvOpInBoundsAccessChain)) {
+         operand->opcode() == spv::Op::OpAccessChain ||
+         operand->opcode() == spv::Op::OpInBoundsAccessChain)) {
       work_list.push(operand);
     }
   };
@@ -158,22 +158,22 @@
 
 bool ReplaceDescArrayAccessUsingVarIndex::IsImageOrImagePtrType(
     const Instruction* type_inst) const {
-  if (type_inst->opcode() == SpvOpTypeImage ||
-      type_inst->opcode() == SpvOpTypeSampler ||
-      type_inst->opcode() == SpvOpTypeSampledImage) {
+  if (type_inst->opcode() == spv::Op::OpTypeImage ||
+      type_inst->opcode() == spv::Op::OpTypeSampler ||
+      type_inst->opcode() == spv::Op::OpTypeSampledImage) {
     return true;
   }
-  if (type_inst->opcode() == SpvOpTypePointer) {
+  if (type_inst->opcode() == spv::Op::OpTypePointer) {
     Instruction* pointee_type_inst = get_def_use_mgr()->GetDef(
         type_inst->GetSingleWordInOperand(kOpTypePointerInOperandType));
     return IsImageOrImagePtrType(pointee_type_inst);
   }
-  if (type_inst->opcode() == SpvOpTypeArray) {
+  if (type_inst->opcode() == spv::Op::OpTypeArray) {
     Instruction* element_type_inst = get_def_use_mgr()->GetDef(
         type_inst->GetSingleWordInOperand(kOpTypeArrayInOperandType));
     return IsImageOrImagePtrType(element_type_inst);
   }
-  if (type_inst->opcode() != SpvOpTypeStruct) return false;
+  if (type_inst->opcode() != spv::Op::OpTypeStruct) return false;
   for (uint32_t in_operand_idx = kOpTypeStructInOperandMember;
        in_operand_idx < type_inst->NumInOperands(); ++in_operand_idx) {
     Instruction* member_type_inst = get_def_use_mgr()->GetDef(
@@ -186,16 +186,16 @@
 bool ReplaceDescArrayAccessUsingVarIndex::IsConcreteType(
     uint32_t type_id) const {
   Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
-  if (type_inst->opcode() == SpvOpTypeInt ||
-      type_inst->opcode() == SpvOpTypeFloat) {
+  if (type_inst->opcode() == spv::Op::OpTypeInt ||
+      type_inst->opcode() == spv::Op::OpTypeFloat) {
     return true;
   }
-  if (type_inst->opcode() == SpvOpTypeVector ||
-      type_inst->opcode() == SpvOpTypeMatrix ||
-      type_inst->opcode() == SpvOpTypeArray) {
+  if (type_inst->opcode() == spv::Op::OpTypeVector ||
+      type_inst->opcode() == spv::Op::OpTypeMatrix ||
+      type_inst->opcode() == spv::Op::OpTypeArray) {
     return IsConcreteType(type_inst->GetSingleWordInOperand(0));
   }
-  if (type_inst->opcode() == SpvOpTypeStruct) {
+  if (type_inst->opcode() == spv::Op::OpTypeStruct) {
     for (uint32_t i = 0; i < type_inst->NumInOperands(); ++i) {
       if (!IsConcreteType(type_inst->GetSingleWordInOperand(i))) return false;
     }
@@ -322,8 +322,8 @@
 }
 
 BasicBlock* ReplaceDescArrayAccessUsingVarIndex::CreateNewBlock() const {
-  auto* new_block = new BasicBlock(std::unique_ptr<Instruction>(
-      new Instruction(context(), SpvOpLabel, 0, context()->TakeNextId(), {})));
+  auto* new_block = new BasicBlock(std::unique_ptr<Instruction>(new Instruction(
+      context(), spv::Op::OpLabel, 0, context()->TakeNextId(), {})));
   get_def_use_mgr()->AnalyzeInstDefUse(new_block->GetLabelInst());
   context()->set_instr_block(new_block->GetLabelInst(), new_block);
   return new_block;
@@ -422,7 +422,7 @@
     uint32_t old_incoming_block_id, uint32_t new_incoming_block_id) const {
   context()->ReplaceAllUsesWithPredicate(
       old_incoming_block_id, new_incoming_block_id,
-      [](Instruction* use) { return use->opcode() == SpvOpPhi; });
+      [](Instruction* use) { return use->opcode() == spv::Op::OpPhi; });
 }
 
 }  // namespace opt
diff --git a/source/opt/replace_invalid_opc.cpp b/source/opt/replace_invalid_opc.cpp
index 1dcd06f..2140973 100644
--- a/source/opt/replace_invalid_opc.cpp
+++ b/source/opt/replace_invalid_opc.cpp
@@ -23,16 +23,16 @@
 Pass::Status ReplaceInvalidOpcodePass::Process() {
   bool modified = false;
 
-  if (context()->get_feature_mgr()->HasCapability(SpvCapabilityLinkage)) {
+  if (context()->get_feature_mgr()->HasCapability(spv::Capability::Linkage)) {
     return Status::SuccessWithoutChange;
   }
 
-  SpvExecutionModel execution_model = GetExecutionModel();
-  if (execution_model == SpvExecutionModelKernel) {
+  spv::ExecutionModel execution_model = GetExecutionModel();
+  if (execution_model == spv::ExecutionModel::Kernel) {
     // We do not handle kernels.
     return Status::SuccessWithoutChange;
   }
-  if (execution_model == SpvExecutionModelMax) {
+  if (execution_model == spv::ExecutionModel::Max) {
     // Mixed execution models for the entry points.  This case is not currently
     // handled.
     return Status::SuccessWithoutChange;
@@ -44,19 +44,19 @@
   return (modified ? Status::SuccessWithChange : Status::SuccessWithoutChange);
 }
 
-SpvExecutionModel ReplaceInvalidOpcodePass::GetExecutionModel() {
-  SpvExecutionModel result = SpvExecutionModelMax;
+spv::ExecutionModel ReplaceInvalidOpcodePass::GetExecutionModel() {
+  spv::ExecutionModel result = spv::ExecutionModel::Max;
   bool first = true;
   for (Instruction& entry_point : get_module()->entry_points()) {
     if (first) {
-      result =
-          static_cast<SpvExecutionModel>(entry_point.GetSingleWordInOperand(0));
+      result = static_cast<spv::ExecutionModel>(
+          entry_point.GetSingleWordInOperand(0));
       first = false;
     } else {
-      SpvExecutionModel current_model =
-          static_cast<SpvExecutionModel>(entry_point.GetSingleWordInOperand(0));
+      spv::ExecutionModel current_model = static_cast<spv::ExecutionModel>(
+          entry_point.GetSingleWordInOperand(0));
       if (current_model != result) {
-        result = SpvExecutionModelMax;
+        result = spv::ExecutionModel::Max;
         break;
       }
     }
@@ -65,13 +65,13 @@
 }
 
 bool ReplaceInvalidOpcodePass::RewriteFunction(Function* function,
-                                               SpvExecutionModel model) {
+                                               spv::ExecutionModel model) {
   bool modified = false;
   Instruction* last_line_dbg_inst = nullptr;
   function->ForEachInst(
       [model, &modified, &last_line_dbg_inst, this](Instruction* inst) {
         // Track the debug information so we can have a meaningful message.
-        if (inst->opcode() == SpvOpLabel || inst->IsNoLine()) {
+        if (inst->opcode() == spv::Op::OpLabel || inst->IsNoLine()) {
           last_line_dbg_inst = nullptr;
           return;
         } else if (inst->IsLine()) {
@@ -80,15 +80,15 @@
         }
 
         bool replace = false;
-        if (model != SpvExecutionModelFragment &&
+        if (model != spv::ExecutionModel::Fragment &&
             IsFragmentShaderOnlyInstruction(inst)) {
           replace = true;
         }
 
-        if (model != SpvExecutionModelTessellationControl &&
-            model != SpvExecutionModelGLCompute) {
-          if (inst->opcode() == SpvOpControlBarrier) {
-            assert(model != SpvExecutionModelKernel &&
+        if (model != spv::ExecutionModel::TessellationControl &&
+            model != spv::ExecutionModel::GLCompute) {
+          if (inst->opcode() == spv::Op::OpControlBarrier) {
+            assert(model != spv::ExecutionModel::Kernel &&
                    "Expecting to be working on a shader module.");
             replace = true;
           }
@@ -101,7 +101,7 @@
           } else {
             // Get the name of the source file.
             uint32_t file_name_id = 0;
-            if (last_line_dbg_inst->opcode() == SpvOpLine) {
+            if (last_line_dbg_inst->opcode() == spv::Op::OpLine) {
               file_name_id = last_line_dbg_inst->GetSingleWordInOperand(0);
             } else {  // Shader100::DebugLine
               uint32_t debug_source_id =
@@ -131,26 +131,26 @@
 bool ReplaceInvalidOpcodePass::IsFragmentShaderOnlyInstruction(
     Instruction* inst) {
   switch (inst->opcode()) {
-    case SpvOpDPdx:
-    case SpvOpDPdy:
-    case SpvOpFwidth:
-    case SpvOpDPdxFine:
-    case SpvOpDPdyFine:
-    case SpvOpFwidthFine:
-    case SpvOpDPdxCoarse:
-    case SpvOpDPdyCoarse:
-    case SpvOpFwidthCoarse:
-    case SpvOpImageSampleImplicitLod:
-    case SpvOpImageSampleDrefImplicitLod:
-    case SpvOpImageSampleProjImplicitLod:
-    case SpvOpImageSampleProjDrefImplicitLod:
-    case SpvOpImageSparseSampleImplicitLod:
-    case SpvOpImageSparseSampleDrefImplicitLod:
-    case SpvOpImageQueryLod:
+    case spv::Op::OpDPdx:
+    case spv::Op::OpDPdy:
+    case spv::Op::OpFwidth:
+    case spv::Op::OpDPdxFine:
+    case spv::Op::OpDPdyFine:
+    case spv::Op::OpFwidthFine:
+    case spv::Op::OpDPdxCoarse:
+    case spv::Op::OpDPdyCoarse:
+    case spv::Op::OpFwidthCoarse:
+    case spv::Op::OpImageSampleImplicitLod:
+    case spv::Op::OpImageSampleDrefImplicitLod:
+    case spv::Op::OpImageSampleProjImplicitLod:
+    case spv::Op::OpImageSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleImplicitLod:
+    case spv::Op::OpImageSparseSampleDrefImplicitLod:
+    case spv::Op::OpImageQueryLod:
       // TODO: Teach |ReplaceInstruction| to handle block terminators.  Then
       // uncomment the OpKill case.
-      // case SpvOpKill:
-      // case SpvOpTerminateInstruction:
+      // case spv::Op::OpKill:
+      // case spv::Op::OpTerminateInstruction:
       return true;
     default:
       return false;
@@ -183,7 +183,7 @@
   analysis::TypeManager* type_mgr = context()->get_type_mgr();
 
   Instruction* type = context()->get_def_use_mgr()->GetDef(type_id);
-  if (type->opcode() == SpvOpTypeVector) {
+  if (type->opcode() == spv::Op::OpTypeVector) {
     uint32_t component_const =
         GetSpecialConstant(type->GetSingleWordInOperand(0));
     std::vector<uint32_t> ids;
@@ -192,7 +192,8 @@
     }
     special_const = const_mgr->GetConstant(type_mgr->GetType(type_id), ids);
   } else {
-    assert(type->opcode() == SpvOpTypeInt || type->opcode() == SpvOpTypeFloat);
+    assert(type->opcode() == spv::Op::OpTypeInt ||
+           type->opcode() == spv::Op::OpTypeFloat);
     std::vector<uint32_t> literal_words;
     for (uint32_t i = 0; i < type->GetSingleWordInOperand(0); i += 32) {
       literal_words.push_back(0xDEADBEEF);
@@ -204,7 +205,7 @@
   return const_mgr->GetDefiningInstruction(special_const)->result_id();
 }
 
-std::string ReplaceInvalidOpcodePass::BuildWarningMessage(SpvOp opcode) {
+std::string ReplaceInvalidOpcodePass::BuildWarningMessage(spv::Op opcode) {
   spv_opcode_desc opcode_info;
   context()->grammar().lookupOpcode(opcode, &opcode_info);
   std::string message = "Removing ";
diff --git a/source/opt/replace_invalid_opc.h b/source/opt/replace_invalid_opc.h
index 426bcac..3f0d16b 100644
--- a/source/opt/replace_invalid_opc.h
+++ b/source/opt/replace_invalid_opc.h
@@ -34,13 +34,13 @@
  private:
   // Returns the execution model that is used by every entry point in the
   // module. If more than one execution model is used in the module, then the
-  // return value is SpvExecutionModelMax.
-  SpvExecutionModel GetExecutionModel();
+  // return value is spv::ExecutionModel::Max.
+  spv::ExecutionModel GetExecutionModel();
 
   // Replaces all instructions in |function| that are invalid with execution
   // model |mode|, but valid for another shader model, with a special constant
   // value.  See |GetSpecialConstant|.
-  bool RewriteFunction(Function* function, SpvExecutionModel mode);
+  bool RewriteFunction(Function* function, spv::ExecutionModel mode);
 
   // Returns true if |inst| is valid for fragment shaders only.
   bool IsFragmentShaderOnlyInstruction(Instruction* inst);
@@ -58,7 +58,7 @@
   // width of the type has been reached. For a vector, each element of the
   // constant will be constructed the same way.
   uint32_t GetSpecialConstant(uint32_t type_id);
-  std::string BuildWarningMessage(SpvOp opcode);
+  std::string BuildWarningMessage(spv::Op opcode);
 };
 
 }  // namespace opt
diff --git a/source/opt/scalar_analysis.cpp b/source/opt/scalar_analysis.cpp
index 2b0a824..1356a0b 100644
--- a/source/opt/scalar_analysis.cpp
+++ b/source/opt/scalar_analysis.cpp
@@ -97,7 +97,7 @@
 
 SENode* ScalarEvolutionAnalysis::AnalyzeMultiplyOp(
     const Instruction* multiply) {
-  assert(multiply->opcode() == SpvOp::SpvOpIMul &&
+  assert(multiply->opcode() == spv::Op::OpIMul &&
          "Multiply node did not come from a multiply instruction");
   analysis::DefUseManager* def_use = context_->get_def_use_mgr();
 
@@ -168,21 +168,21 @@
 
   SENode* output = nullptr;
   switch (inst->opcode()) {
-    case SpvOp::SpvOpPhi: {
+    case spv::Op::OpPhi: {
       output = AnalyzePhiInstruction(inst);
       break;
     }
-    case SpvOp::SpvOpConstant:
-    case SpvOp::SpvOpConstantNull: {
+    case spv::Op::OpConstant:
+    case spv::Op::OpConstantNull: {
       output = AnalyzeConstant(inst);
       break;
     }
-    case SpvOp::SpvOpISub:
-    case SpvOp::SpvOpIAdd: {
+    case spv::Op::OpISub:
+    case spv::Op::OpIAdd: {
       output = AnalyzeAddOp(inst);
       break;
     }
-    case SpvOp::SpvOpIMul: {
+    case spv::Op::OpIMul: {
       output = AnalyzeMultiplyOp(inst);
       break;
     }
@@ -196,9 +196,9 @@
 }
 
 SENode* ScalarEvolutionAnalysis::AnalyzeConstant(const Instruction* inst) {
-  if (inst->opcode() == SpvOp::SpvOpConstantNull) return CreateConstant(0);
+  if (inst->opcode() == spv::Op::OpConstantNull) return CreateConstant(0);
 
-  assert(inst->opcode() == SpvOp::SpvOpConstant);
+  assert(inst->opcode() == spv::Op::OpConstant);
   assert(inst->NumInOperands() == 1);
   int64_t value = 0;
 
@@ -226,8 +226,8 @@
 // Handles both addition and subtraction. If the |sub| flag is set then the
 // addition will be op1+(-op2) otherwise op1+op2.
 SENode* ScalarEvolutionAnalysis::AnalyzeAddOp(const Instruction* inst) {
-  assert((inst->opcode() == SpvOp::SpvOpIAdd ||
-          inst->opcode() == SpvOp::SpvOpISub) &&
+  assert((inst->opcode() == spv::Op::OpIAdd ||
+          inst->opcode() == spv::Op::OpISub) &&
          "Add node must be created from a OpIAdd or OpISub instruction");
 
   analysis::DefUseManager* def_use = context_->get_def_use_mgr();
@@ -239,7 +239,7 @@
       AnalyzeInstruction(def_use->GetDef(inst->GetSingleWordInOperand(1)));
 
   // To handle subtraction we wrap the second operand in a unary negation node.
-  if (inst->opcode() == SpvOp::SpvOpISub) {
+  if (inst->opcode() == spv::Op::OpISub) {
     op2 = CreateNegation(op2);
   }
 
diff --git a/source/opt/scalar_replacement_pass.cpp b/source/opt/scalar_replacement_pass.cpp
index e27c828..ea198f5 100644
--- a/source/opt/scalar_replacement_pass.cpp
+++ b/source/opt/scalar_replacement_pass.cpp
@@ -56,7 +56,7 @@
   for (auto iter = entry.begin(); iter != entry.end(); ++iter) {
     // Function storage class OpVariables must appear as the first instructions
     // of the entry block.
-    if (iter->opcode() != SpvOpVariable) break;
+    if (iter->opcode() != spv::Op::OpVariable) break;
 
     Instruction* varInst = &*iter;
     if (CanReplaceVariable(varInst)) {
@@ -105,29 +105,29 @@
         }
         if (!IsAnnotationInst(user->opcode())) {
           switch (user->opcode()) {
-            case SpvOpLoad:
+            case spv::Op::OpLoad:
               if (ReplaceWholeLoad(user, replacements)) {
                 dead.push_back(user);
               } else {
                 return false;
               }
               break;
-            case SpvOpStore:
+            case spv::Op::OpStore:
               if (ReplaceWholeStore(user, replacements)) {
                 dead.push_back(user);
               } else {
                 return false;
               }
               break;
-            case SpvOpAccessChain:
-            case SpvOpInBoundsAccessChain:
+            case spv::Op::OpAccessChain:
+            case spv::Op::OpInBoundsAccessChain:
               if (ReplaceAccessChain(user, replacements))
                 dead.push_back(user);
               else
                 return false;
               break;
-            case SpvOpName:
-            case SpvOpMemberName:
+            case spv::Op::OpName:
+            case spv::Op::OpMemberName:
               break;
             default:
               assert(false && "Unexpected opcode");
@@ -155,7 +155,7 @@
 
   // Attempt to further scalarize.
   for (auto var : replacements) {
-    if (var->opcode() == SpvOpVariable) {
+    if (var->opcode() == spv::Op::OpVariable) {
       if (get_def_use_mgr()->NumUsers(var) == 0) {
         context()->KillInst(var);
       } else if (CanReplaceVariable(var)) {
@@ -179,7 +179,7 @@
   int32_t idx = 0;
   for (const auto* var : replacements) {
     Instruction* insert_before = var->NextNode();
-    while (insert_before->opcode() == SpvOpVariable)
+    while (insert_before->opcode() == spv::Op::OpVariable)
       insert_before = insert_before->NextNode();
     assert(insert_before != nullptr && "unexpected end of list");
     Instruction* added_dbg_value =
@@ -236,7 +236,7 @@
   BasicBlock::iterator where(load);
   for (auto var : replacements) {
     // Create a load of each replacement variable.
-    if (var->opcode() != SpvOpVariable) {
+    if (var->opcode() != spv::Op::OpVariable) {
       loads.push_back(var);
       continue;
     }
@@ -247,7 +247,7 @@
       return false;
     }
     std::unique_ptr<Instruction> newLoad(
-        new Instruction(context(), SpvOpLoad, type->result_id(), loadId,
+        new Instruction(context(), spv::Op::OpLoad, type->result_id(), loadId,
                         std::initializer_list<Operand>{
                             {SPV_OPERAND_TYPE_ID, {var->result_id()}}}));
     // Copy memory access attributes which start at index 1. Index 0 is the
@@ -269,8 +269,9 @@
     return false;
   }
   where = load;
-  std::unique_ptr<Instruction> compositeConstruct(new Instruction(
-      context(), SpvOpCompositeConstruct, load->type_id(), compositeId, {}));
+  std::unique_ptr<Instruction> compositeConstruct(
+      new Instruction(context(), spv::Op::OpCompositeConstruct, load->type_id(),
+                      compositeId, {}));
   for (auto l : loads) {
     Operand op(SPV_OPERAND_TYPE_ID,
                std::initializer_list<uint32_t>{l->result_id()});
@@ -294,7 +295,7 @@
   uint32_t elementIndex = 0;
   for (auto var : replacements) {
     // Create the extract.
-    if (var->opcode() != SpvOpVariable) {
+    if (var->opcode() != spv::Op::OpVariable) {
       elementIndex++;
       continue;
     }
@@ -305,7 +306,7 @@
       return false;
     }
     std::unique_ptr<Instruction> extract(new Instruction(
-        context(), SpvOpCompositeExtract, type->result_id(), extractId,
+        context(), spv::Op::OpCompositeExtract, type->result_id(), extractId,
         std::initializer_list<Operand>{
             {SPV_OPERAND_TYPE_ID, {storeInput}},
             {SPV_OPERAND_TYPE_LITERAL_INTEGER, {elementIndex++}}}));
@@ -316,7 +317,7 @@
 
     // Create the store.
     std::unique_ptr<Instruction> newStore(
-        new Instruction(context(), SpvOpStore, 0, 0,
+        new Instruction(context(), spv::Op::OpStore, 0, 0,
                         std::initializer_list<Operand>{
                             {SPV_OPERAND_TYPE_ID, {var->result_id()}},
                             {SPV_OPERAND_TYPE_ID, {extractId}}}));
@@ -390,7 +391,7 @@
 
   uint32_t elem = 0;
   switch (type->opcode()) {
-    case SpvOpTypeStruct:
+    case spv::Op::OpTypeStruct:
       type->ForEachInOperand(
           [this, inst, &elem, replacements, &components_used](uint32_t* id) {
             if (!components_used || components_used->count(elem)) {
@@ -401,7 +402,7 @@
             elem++;
           });
       break;
-    case SpvOpTypeArray:
+    case spv::Op::OpTypeArray:
       for (uint32_t i = 0; i != GetArrayLength(type); ++i) {
         if (!components_used || components_used->count(i)) {
           CreateVariable(type->GetSingleWordInOperand(0u), inst, i,
@@ -413,8 +414,8 @@
       }
       break;
 
-    case SpvOpTypeMatrix:
-    case SpvOpTypeVector:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeVector:
       for (uint32_t i = 0; i != GetNumElements(type); ++i) {
         CreateVariable(type->GetSingleWordInOperand(0u), inst, i, replacements);
       }
@@ -440,20 +441,20 @@
   // no type or member decorations that are necessary to transfer.
   for (auto inst :
        get_decoration_mgr()->GetDecorationsFor(source->result_id(), false)) {
-    assert(inst->opcode() == SpvOpDecorate);
-    uint32_t decoration = inst->GetSingleWordInOperand(1u);
-    if (decoration == SpvDecorationInvariant ||
-        decoration == SpvDecorationRestrict) {
+    assert(inst->opcode() == spv::Op::OpDecorate);
+    auto decoration = spv::Decoration(inst->GetSingleWordInOperand(1u));
+    if (decoration == spv::Decoration::Invariant ||
+        decoration == spv::Decoration::Restrict) {
       for (auto var : *replacements) {
         if (var == nullptr) {
           continue;
         }
 
-        std::unique_ptr<Instruction> annotation(
-            new Instruction(context(), SpvOpDecorate, 0, 0,
-                            std::initializer_list<Operand>{
-                                {SPV_OPERAND_TYPE_ID, {var->result_id()}},
-                                {SPV_OPERAND_TYPE_DECORATION, {decoration}}}));
+        std::unique_ptr<Instruction> annotation(new Instruction(
+            context(), spv::Op::OpDecorate, 0, 0,
+            std::initializer_list<Operand>{
+                {SPV_OPERAND_TYPE_ID, {var->result_id()}},
+                {SPV_OPERAND_TYPE_DECORATION, {uint32_t(decoration)}}}));
         for (uint32_t i = 2; i < inst->NumInOperands(); ++i) {
           Operand copy(inst->GetInOperand(i));
           annotation->AddOperand(std::move(copy));
@@ -475,10 +476,11 @@
     replacements->push_back(nullptr);
   }
 
-  std::unique_ptr<Instruction> variable(new Instruction(
-      context(), SpvOpVariable, ptrId, id,
-      std::initializer_list<Operand>{
-          {SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}}}));
+  std::unique_ptr<Instruction> variable(
+      new Instruction(context(), spv::Op::OpVariable, ptrId, id,
+                      std::initializer_list<Operand>{
+                          {SPV_OPERAND_TYPE_STORAGE_CLASS,
+                           {uint32_t(spv::StorageClass::Function)}}}));
 
   BasicBlock* block = context()->get_instr_block(varInst);
   block->begin().InsertBefore(std::move(variable));
@@ -494,7 +496,7 @@
   for (auto dec_inst :
        get_decoration_mgr()->GetDecorationsFor(typeInst->result_id(), false)) {
     uint32_t decoration;
-    if (dec_inst->opcode() != SpvOpMemberDecorate) {
+    if (dec_inst->opcode() != spv::Op::OpMemberDecorate) {
       continue;
     }
 
@@ -503,10 +505,10 @@
     }
 
     decoration = dec_inst->GetSingleWordInOperand(2u);
-    switch (decoration) {
-      case SpvDecorationRelaxedPrecision: {
+    switch (spv::Decoration(decoration)) {
+      case spv::Decoration::RelaxedPrecision: {
         std::unique_ptr<Instruction> new_dec_inst(
-            new Instruction(context(), SpvOpDecorate, 0, 0, {}));
+            new Instruction(context(), spv::Op::OpDecorate, 0, 0, {}));
         new_dec_inst->AddOperand(Operand(SPV_OPERAND_TYPE_ID, {id}));
         for (uint32_t i = 2; i < dec_inst->NumInOperandWords(); ++i) {
           new_dec_inst->AddOperand(Operand(dec_inst->GetInOperand(i)));
@@ -531,8 +533,8 @@
   analysis::Type* pointeeTy;
   std::unique_ptr<analysis::Pointer> pointerTy;
   std::tie(pointeeTy, pointerTy) =
-      context()->get_type_mgr()->GetTypeAndPointerType(id,
-                                                       SpvStorageClassFunction);
+      context()->get_type_mgr()->GetTypeAndPointerType(
+          id, spv::StorageClass::Function);
   uint32_t ptrId = 0;
   if (pointeeTy->IsUniqueType()) {
     // Non-ambiguous type, just ask the type manager for an id.
@@ -544,8 +546,9 @@
   // Ambiguous type. We must perform a linear search to try and find the right
   // type.
   for (auto global : context()->types_values()) {
-    if (global.opcode() == SpvOpTypePointer &&
-        global.GetSingleWordInOperand(0u) == SpvStorageClassFunction &&
+    if (global.opcode() == spv::Op::OpTypePointer &&
+        spv::StorageClass(global.GetSingleWordInOperand(0u)) ==
+            spv::StorageClass::Function &&
         global.GetSingleWordInOperand(1u) == id) {
       if (get_decoration_mgr()->GetDecorationsFor(id, false).empty()) {
         // Only reuse a decoration-less pointer of the correct type.
@@ -562,10 +565,10 @@
 
   ptrId = TakeNextId();
   context()->AddType(MakeUnique<Instruction>(
-      context(), SpvOpTypePointer, 0, ptrId,
-      std::initializer_list<Operand>{
-          {SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}},
-          {SPV_OPERAND_TYPE_ID, {id}}}));
+      context(), spv::Op::OpTypePointer, 0, ptrId,
+      std::initializer_list<Operand>{{SPV_OPERAND_TYPE_STORAGE_CLASS,
+                                      {uint32_t(spv::StorageClass::Function)}},
+                                     {SPV_OPERAND_TYPE_ID, {id}}}));
   Instruction* ptr = &*--context()->types_values_end();
   get_def_use_mgr()->AnalyzeInstDefUse(ptr);
   pointee_to_pointer_[id] = ptrId;
@@ -578,7 +581,7 @@
 void ScalarReplacementPass::GetOrCreateInitialValue(Instruction* source,
                                                     uint32_t index,
                                                     Instruction* newVar) {
-  assert(source->opcode() == SpvOpVariable);
+  assert(source->opcode() == spv::Op::OpVariable);
   if (source->NumInOperands() < 2) return;
 
   uint32_t initId = source->GetSingleWordInOperand(1u);
@@ -586,14 +589,14 @@
   Instruction* init = get_def_use_mgr()->GetDef(initId);
   uint32_t newInitId = 0;
   // TODO(dnovillo): Refactor this with constant propagation.
-  if (init->opcode() == SpvOpConstantNull) {
+  if (init->opcode() == spv::Op::OpConstantNull) {
     // Initialize to appropriate NULL.
     auto iter = type_to_null_.find(storageId);
     if (iter == type_to_null_.end()) {
       newInitId = TakeNextId();
       type_to_null_[storageId] = newInitId;
       context()->AddGlobalValue(
-          MakeUnique<Instruction>(context(), SpvOpConstantNull, storageId,
+          MakeUnique<Instruction>(context(), spv::Op::OpConstantNull, storageId,
                                   newInitId, std::initializer_list<Operand>{}));
       Instruction* newNull = &*--context()->types_values_end();
       get_def_use_mgr()->AnalyzeInstDefUse(newNull);
@@ -604,18 +607,19 @@
     // Create a new constant extract.
     newInitId = TakeNextId();
     context()->AddGlobalValue(MakeUnique<Instruction>(
-        context(), SpvOpSpecConstantOp, storageId, newInitId,
+        context(), spv::Op::OpSpecConstantOp, storageId, newInitId,
         std::initializer_list<Operand>{
-            {SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER, {SpvOpCompositeExtract}},
+            {SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER,
+             {uint32_t(spv::Op::OpCompositeExtract)}},
             {SPV_OPERAND_TYPE_ID, {init->result_id()}},
             {SPV_OPERAND_TYPE_LITERAL_INTEGER, {index}}}));
     Instruction* newSpecConst = &*--context()->types_values_end();
     get_def_use_mgr()->AnalyzeInstDefUse(newSpecConst);
-  } else if (init->opcode() == SpvOpConstantComposite) {
+  } else if (init->opcode() == spv::Op::OpConstantComposite) {
     // Get the appropriate index constant.
     newInitId = init->GetSingleWordInOperand(index);
     Instruction* element = get_def_use_mgr()->GetDef(newInitId);
-    if (element->opcode() == SpvOpUndef) {
+    if (element->opcode() == spv::Op::OpUndef) {
       // Undef is not a valid initializer for a variable.
       newInitId = 0;
     }
@@ -630,7 +634,7 @@
 
 uint64_t ScalarReplacementPass::GetArrayLength(
     const Instruction* arrayType) const {
-  assert(arrayType->opcode() == SpvOpTypeArray);
+  assert(arrayType->opcode() == spv::Op::OpTypeArray);
   const Instruction* length =
       get_def_use_mgr()->GetDef(arrayType->GetSingleWordInOperand(1u));
   return context()
@@ -640,8 +644,8 @@
 }
 
 uint64_t ScalarReplacementPass::GetNumElements(const Instruction* type) const {
-  assert(type->opcode() == SpvOpTypeVector ||
-         type->opcode() == SpvOpTypeMatrix);
+  assert(type->opcode() == spv::Op::OpTypeVector ||
+         type->opcode() == spv::Op::OpTypeMatrix);
   const Operand& op = type->GetInOperand(1u);
   assert(op.words.size() <= 2);
   uint64_t len = 0;
@@ -659,7 +663,7 @@
 
 Instruction* ScalarReplacementPass::GetStorageType(
     const Instruction* inst) const {
-  assert(inst->opcode() == SpvOpVariable);
+  assert(inst->opcode() == spv::Op::OpVariable);
 
   uint32_t ptrTypeId = inst->type_id();
   uint32_t typeId =
@@ -669,10 +673,11 @@
 
 bool ScalarReplacementPass::CanReplaceVariable(
     const Instruction* varInst) const {
-  assert(varInst->opcode() == SpvOpVariable);
+  assert(varInst->opcode() == spv::Op::OpVariable);
 
   // Can only replace function scope variables.
-  if (varInst->GetSingleWordInOperand(0u) != SpvStorageClassFunction) {
+  if (spv::StorageClass(varInst->GetSingleWordInOperand(0u)) !=
+      spv::StorageClass::Function) {
     return false;
   }
 
@@ -702,14 +707,14 @@
   }
 
   switch (typeInst->opcode()) {
-    case SpvOpTypeStruct:
+    case spv::Op::OpTypeStruct:
       // Don't bother with empty structs or very large structs.
       if (typeInst->NumInOperands() == 0 ||
           IsLargerThanSizeLimit(typeInst->NumInOperands())) {
         return false;
       }
       return true;
-    case SpvOpTypeArray:
+    case spv::Op::OpTypeArray:
       if (IsSpecConstant(typeInst->GetSingleWordInOperand(1u))) {
         return false;
       }
@@ -721,12 +726,12 @@
       // re-enabled.
       //// Specifically including matrix and vector in an attempt to reduce the
       //// number of vector registers required.
-      // case SpvOpTypeMatrix:
-      // case SpvOpTypeVector:
+      // case spv::Op::OpTypeMatrix:
+      // case spv::Op::OpTypeVector:
       //  if (IsLargerThanSizeLimit(GetNumElements(typeInst))) return false;
       //  return true;
 
-    case SpvOpTypeRuntimeArray:
+    case spv::Op::OpTypeRuntimeArray:
     default:
       return false;
   }
@@ -737,26 +742,26 @@
   for (auto inst :
        get_decoration_mgr()->GetDecorationsFor(typeInst->result_id(), false)) {
     uint32_t decoration;
-    if (inst->opcode() == SpvOpDecorate) {
+    if (inst->opcode() == spv::Op::OpDecorate) {
       decoration = inst->GetSingleWordInOperand(1u);
     } else {
-      assert(inst->opcode() == SpvOpMemberDecorate);
+      assert(inst->opcode() == spv::Op::OpMemberDecorate);
       decoration = inst->GetSingleWordInOperand(2u);
     }
 
-    switch (decoration) {
-      case SpvDecorationRowMajor:
-      case SpvDecorationColMajor:
-      case SpvDecorationArrayStride:
-      case SpvDecorationMatrixStride:
-      case SpvDecorationCPacked:
-      case SpvDecorationInvariant:
-      case SpvDecorationRestrict:
-      case SpvDecorationOffset:
-      case SpvDecorationAlignment:
-      case SpvDecorationAlignmentId:
-      case SpvDecorationMaxByteOffset:
-      case SpvDecorationRelaxedPrecision:
+    switch (spv::Decoration(decoration)) {
+      case spv::Decoration::RowMajor:
+      case spv::Decoration::ColMajor:
+      case spv::Decoration::ArrayStride:
+      case spv::Decoration::MatrixStride:
+      case spv::Decoration::CPacked:
+      case spv::Decoration::Invariant:
+      case spv::Decoration::Restrict:
+      case spv::Decoration::Offset:
+      case spv::Decoration::Alignment:
+      case spv::Decoration::AlignmentId:
+      case spv::Decoration::MaxByteOffset:
+      case spv::Decoration::RelaxedPrecision:
         break;
       default:
         return false;
@@ -769,14 +774,14 @@
 bool ScalarReplacementPass::CheckAnnotations(const Instruction* varInst) const {
   for (auto inst :
        get_decoration_mgr()->GetDecorationsFor(varInst->result_id(), false)) {
-    assert(inst->opcode() == SpvOpDecorate);
-    uint32_t decoration = inst->GetSingleWordInOperand(1u);
+    assert(inst->opcode() == spv::Op::OpDecorate);
+    auto decoration = spv::Decoration(inst->GetSingleWordInOperand(1u));
     switch (decoration) {
-      case SpvDecorationInvariant:
-      case SpvDecorationRestrict:
-      case SpvDecorationAlignment:
-      case SpvDecorationAlignmentId:
-      case SpvDecorationMaxByteOffset:
+      case spv::Decoration::Invariant:
+      case spv::Decoration::Restrict:
+      case spv::Decoration::Alignment:
+      case spv::Decoration::AlignmentId:
+      case spv::Decoration::MaxByteOffset:
         break;
       default:
         return false;
@@ -816,8 +821,8 @@
     // Annotations are check as a group separately.
     if (!IsAnnotationInst(user->opcode())) {
       switch (user->opcode()) {
-        case SpvOpAccessChain:
-        case SpvOpInBoundsAccessChain:
+        case spv::Op::OpAccessChain:
+        case spv::Op::OpInBoundsAccessChain:
           if (index == 2u && user->NumInOperands() > 1) {
             uint32_t id = user->GetSingleWordInOperand(1u);
             const Instruction* opInst = get_def_use_mgr()->GetDef(id);
@@ -835,16 +840,16 @@
             ok = false;
           }
           break;
-        case SpvOpLoad:
+        case spv::Op::OpLoad:
           if (!CheckLoad(user, index)) ok = false;
           stats->num_full_accesses++;
           break;
-        case SpvOpStore:
+        case spv::Op::OpStore:
           if (!CheckStore(user, index)) ok = false;
           stats->num_full_accesses++;
           break;
-        case SpvOpName:
-        case SpvOpMemberName:
+        case spv::Op::OpName:
+        case spv::Op::OpMemberName:
           break;
         default:
           ok = false;
@@ -861,24 +866,24 @@
   get_def_use_mgr()->ForEachUse(
       inst, [this, &ok](const Instruction* user, uint32_t index) {
         switch (user->opcode()) {
-          case SpvOpAccessChain:
-          case SpvOpInBoundsAccessChain:
+          case spv::Op::OpAccessChain:
+          case spv::Op::OpInBoundsAccessChain:
             if (index != 2u) {
               ok = false;
             } else {
               if (!CheckUsesRelaxed(user)) ok = false;
             }
             break;
-          case SpvOpLoad:
+          case spv::Op::OpLoad:
             if (!CheckLoad(user, index)) ok = false;
             break;
-          case SpvOpStore:
+          case spv::Op::OpStore:
             if (!CheckStore(user, index)) ok = false;
             break;
-          case SpvOpImageTexelPointer:
+          case spv::Op::OpImageTexelPointer:
             if (!CheckImageTexelPointer(index)) ok = false;
             break;
-          case SpvOpExtInst:
+          case spv::Op::OpExtInst:
             if (user->GetCommonDebugOpcode() != CommonDebugInfoDebugDeclare ||
                 !CheckDebugDeclare(index))
               ok = false;
@@ -900,7 +905,8 @@
                                       uint32_t index) const {
   if (index != 2u) return false;
   if (inst->NumInOperands() >= 2 &&
-      inst->GetSingleWordInOperand(1u) & SpvMemoryAccessVolatileMask)
+      inst->GetSingleWordInOperand(1u) &
+          uint32_t(spv::MemoryAccessMask::Volatile))
     return false;
   return true;
 }
@@ -909,7 +915,8 @@
                                        uint32_t index) const {
   if (index != 0u) return false;
   if (inst->NumInOperands() >= 3 &&
-      inst->GetSingleWordInOperand(2u) & SpvMemoryAccessVolatileMask)
+      inst->GetSingleWordInOperand(2u) &
+          uint32_t(spv::MemoryAccessMask::Volatile))
     return false;
   return true;
 }
@@ -936,11 +943,11 @@
   def_use_mgr->WhileEachUser(inst, [&result, def_use_mgr,
                                     this](Instruction* use) {
     switch (use->opcode()) {
-      case SpvOpLoad: {
+      case spv::Op::OpLoad: {
         // Look for extract from the load.
         std::vector<uint32_t> t;
         if (def_use_mgr->WhileEachUser(use, [&t](Instruction* use2) {
-              if (use2->opcode() != SpvOpCompositeExtract ||
+              if (use2->opcode() != spv::Op::OpCompositeExtract ||
                   use2->NumInOperands() <= 1) {
                 return false;
               }
@@ -954,13 +961,13 @@
           return false;
         }
       }
-      case SpvOpName:
-      case SpvOpMemberName:
-      case SpvOpStore:
+      case spv::Op::OpName:
+      case spv::Op::OpMemberName:
+      case spv::Op::OpStore:
         // No components are used.
         return true;
-      case SpvOpAccessChain:
-      case SpvOpInBoundsAccessChain: {
+      case spv::Op::OpAccessChain:
+      case spv::Op::OpInBoundsAccessChain: {
         // Add the first index it if is a constant.
         // TODO: Could be improved by checking if the address is used in a load.
         analysis::ConstantManager* const_mgr = context()->get_constant_mgr();
@@ -988,16 +995,16 @@
 
 uint64_t ScalarReplacementPass::GetMaxLegalIndex(
     const Instruction* var_inst) const {
-  assert(var_inst->opcode() == SpvOpVariable &&
+  assert(var_inst->opcode() == spv::Op::OpVariable &&
          "|var_inst| must be a variable instruction.");
   Instruction* type = GetStorageType(var_inst);
   switch (type->opcode()) {
-    case SpvOpTypeStruct:
+    case spv::Op::OpTypeStruct:
       return type->NumInOperands();
-    case SpvOpTypeArray:
+    case spv::Op::OpTypeArray:
       return GetArrayLength(type);
-    case SpvOpTypeMatrix:
-    case SpvOpTypeVector:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeVector:
       return GetNumElements(type);
     default:
       return 0;
diff --git a/source/opt/scalar_replacement_pass.h b/source/opt/scalar_replacement_pass.h
index 6a66dfb..1faed2f 100644
--- a/source/opt/scalar_replacement_pass.h
+++ b/source/opt/scalar_replacement_pass.h
@@ -104,10 +104,10 @@
   // Returns true if the uses of |inst| are acceptable for scalarization.
   //
   // Recursively checks all the uses of |inst|. For |inst| specifically, only
-  // allows SpvOpAccessChain, SpvOpInBoundsAccessChain, SpvOpLoad and
-  // SpvOpStore. Access chains must have the first index be a compile-time
-  // constant. Subsequent uses of access chains (including other access chains)
-  // are checked in a more relaxed manner.
+  // allows spv::Op::OpAccessChain, spv::Op::OpInBoundsAccessChain,
+  // spv::Op::OpLoad and spv::Op::OpStore. Access chains must have the first
+  // index be a compile-time constant. Subsequent uses of access chains
+  // (including other access chains) are checked in a more relaxed manner.
   bool CheckUses(const Instruction* inst) const;
 
   // Helper function for the above |CheckUses|.
diff --git a/source/opt/set_spec_constant_default_value_pass.cpp b/source/opt/set_spec_constant_default_value_pass.cpp
index 4def2b0..c42dc1b 100644
--- a/source/opt/set_spec_constant_default_value_pass.cpp
+++ b/source/opt/set_spec_constant_default_value_pass.cpp
@@ -139,9 +139,9 @@
 // decoration.
 bool CanHaveSpecIdDecoration(const Instruction& inst) {
   switch (inst.opcode()) {
-    case SpvOp::SpvOpSpecConstant:
-    case SpvOp::SpvOpSpecConstantFalse:
-    case SpvOp::SpvOpSpecConstantTrue:
+    case spv::Op::OpSpecConstant:
+    case spv::Op::OpSpecConstantFalse:
+    case spv::Op::OpSpecConstantTrue:
       return true;
     default:
       return false;
@@ -165,7 +165,7 @@
   if (def_use_mgr->WhileEachUser(&decoration_group_defining_inst,
                                  [&group_decorate_inst](Instruction* user) {
                                    if (user->opcode() ==
-                                       SpvOp::SpvOpGroupDecorate) {
+                                       spv::Op::OpGroupDecorate) {
                                      group_decorate_inst = user;
                                      return false;
                                    }
@@ -240,10 +240,10 @@
   // default value of the target spec constant.
   for (Instruction& inst : context()->annotations()) {
     // Only process 'OpDecorate SpecId' instructions
-    if (inst.opcode() != SpvOp::SpvOpDecorate) continue;
+    if (inst.opcode() != spv::Op::OpDecorate) continue;
     if (inst.NumOperands() != kOpDecorateSpecIdNumOperands) continue;
     if (inst.GetSingleWordInOperand(kDecorationOperandIndex) !=
-        uint32_t(SpvDecoration::SpvDecorationSpecId)) {
+        uint32_t(spv::Decoration::SpecId)) {
       continue;
     }
 
@@ -255,7 +255,7 @@
     // target_id might be a decoration group id.
     Instruction* spec_inst = nullptr;
     if (Instruction* target_inst = get_def_use_mgr()->GetDef(target_id)) {
-      if (target_inst->opcode() == SpvOp::SpvOpDecorationGroup) {
+      if (target_inst->opcode() == spv::Op::OpDecorationGroup) {
         spec_inst =
             GetSpecIdTargetFromDecorationGroup(*target_inst, get_def_use_mgr());
       } else {
@@ -301,7 +301,7 @@
     // Update the operand bit patterns of the spec constant defining
     // instruction.
     switch (spec_inst->opcode()) {
-      case SpvOp::SpvOpSpecConstant:
+      case spv::Op::OpSpecConstant:
         // If the new value is the same with the original value, no
         // need to do anything. Otherwise update the operand words.
         if (spec_inst->GetInOperand(kOpSpecConstantLiteralInOperandIndex)
@@ -311,19 +311,19 @@
           modified = true;
         }
         break;
-      case SpvOp::SpvOpSpecConstantTrue:
+      case spv::Op::OpSpecConstantTrue:
         // If the new value is also 'true', no need to change anything.
         // Otherwise, set the opcode to OpSpecConstantFalse;
         if (!static_cast<bool>(bit_pattern.front())) {
-          spec_inst->SetOpcode(SpvOp::SpvOpSpecConstantFalse);
+          spec_inst->SetOpcode(spv::Op::OpSpecConstantFalse);
           modified = true;
         }
         break;
-      case SpvOp::SpvOpSpecConstantFalse:
+      case spv::Op::OpSpecConstantFalse:
         // If the new value is also 'false', no need to change anything.
         // Otherwise, set the opcode to OpSpecConstantTrue;
         if (static_cast<bool>(bit_pattern.front())) {
-          spec_inst->SetOpcode(SpvOp::SpvOpSpecConstantTrue);
+          spec_inst->SetOpcode(spv::Op::OpSpecConstantTrue);
           modified = true;
         }
         break;
diff --git a/source/opt/simplification_pass.cpp b/source/opt/simplification_pass.cpp
index 43ec15f..dbda397 100644
--- a/source/opt/simplification_pass.cpp
+++ b/source/opt/simplification_pass.cpp
@@ -69,12 +69,12 @@
        &folder, &inst_seen, this](BasicBlock* bb) {
         for (Instruction* inst = &*bb->begin(); inst; inst = inst->NextNode()) {
           inst_seen.insert(inst);
-          if (inst->opcode() == SpvOpPhi) {
+          if (inst->opcode() == spv::Op::OpPhi) {
             process_phis.insert(inst);
           }
 
           bool is_foldable_copy =
-              inst->opcode() == SpvOpCopyObject &&
+              inst->opcode() == spv::Op::OpCopyObject &&
               context()->get_decoration_mgr()->HaveSubsetOfDecorations(
                   inst->result_id(), inst->GetSingleWordInOperand(0));
 
@@ -91,7 +91,7 @@
 
             AddNewOperands(inst, &inst_seen, &work_list);
 
-            if (inst->opcode() == SpvOpCopyObject) {
+            if (inst->opcode() == spv::Op::OpCopyObject) {
               context()->ReplaceAllUsesWithPredicate(
                   inst->result_id(), inst->GetSingleWordInOperand(0),
                   [](Instruction* user) {
@@ -104,7 +104,7 @@
                   });
               inst_to_kill.insert(inst);
               in_work_list.insert(inst);
-            } else if (inst->opcode() == SpvOpNop) {
+            } else if (inst->opcode() == spv::Op::OpNop) {
               inst_to_kill.insert(inst);
               in_work_list.insert(inst);
             }
@@ -121,7 +121,7 @@
     inst_seen.insert(inst);
 
     bool is_foldable_copy =
-        inst->opcode() == SpvOpCopyObject &&
+        inst->opcode() == spv::Op::OpCopyObject &&
         context()->get_decoration_mgr()->HaveSubsetOfDecorations(
             inst->result_id(), inst->GetSingleWordInOperand(0));
 
@@ -130,7 +130,7 @@
       context()->AnalyzeUses(inst);
       get_def_use_mgr()->ForEachUser(
           inst, [&work_list, &in_work_list](Instruction* use) {
-            if (!use->IsDecoration() && use->opcode() != SpvOpName &&
+            if (!use->IsDecoration() && use->opcode() != spv::Op::OpName &&
                 in_work_list.insert(use).second) {
               work_list.push_back(use);
             }
@@ -138,7 +138,7 @@
 
       AddNewOperands(inst, &inst_seen, &work_list);
 
-      if (inst->opcode() == SpvOpCopyObject) {
+      if (inst->opcode() == spv::Op::OpCopyObject) {
         context()->ReplaceAllUsesWithPredicate(
             inst->result_id(), inst->GetSingleWordInOperand(0),
             [](Instruction* user) {
@@ -150,7 +150,7 @@
             });
         inst_to_kill.insert(inst);
         in_work_list.insert(inst);
-      } else if (inst->opcode() == SpvOpNop) {
+      } else if (inst->opcode() == spv::Op::OpNop) {
         inst_to_kill.insert(inst);
         in_work_list.insert(inst);
       }
diff --git a/source/opt/spread_volatile_semantics.cpp b/source/opt/spread_volatile_semantics.cpp
index b61fd0f..73c7393 100644
--- a/source/opt/spread_volatile_semantics.cpp
+++ b/source/opt/spread_volatile_semantics.cpp
@@ -30,23 +30,24 @@
 bool HasBuiltinDecoration(analysis::DecorationManager* decoration_manager,
                           uint32_t var_id, uint32_t built_in) {
   return decoration_manager->FindDecoration(
-      var_id, SpvDecorationBuiltIn, [built_in](const Instruction& inst) {
+      var_id, uint32_t(spv::Decoration::BuiltIn),
+      [built_in](const Instruction& inst) {
         return built_in == inst.GetSingleWordInOperand(
                                kOpDecorateInOperandBuiltinDecoration);
       });
 }
 
-bool IsBuiltInForRayTracingVolatileSemantics(uint32_t built_in) {
+bool IsBuiltInForRayTracingVolatileSemantics(spv::BuiltIn built_in) {
   switch (built_in) {
-    case SpvBuiltInSMIDNV:
-    case SpvBuiltInWarpIDNV:
-    case SpvBuiltInSubgroupSize:
-    case SpvBuiltInSubgroupLocalInvocationId:
-    case SpvBuiltInSubgroupEqMask:
-    case SpvBuiltInSubgroupGeMask:
-    case SpvBuiltInSubgroupGtMask:
-    case SpvBuiltInSubgroupLeMask:
-    case SpvBuiltInSubgroupLtMask:
+    case spv::BuiltIn::SMIDNV:
+    case spv::BuiltIn::WarpIDNV:
+    case spv::BuiltIn::SubgroupSize:
+    case spv::BuiltIn::SubgroupLocalInvocationId:
+    case spv::BuiltIn::SubgroupEqMask:
+    case spv::BuiltIn::SubgroupGeMask:
+    case spv::BuiltIn::SubgroupGtMask:
+    case spv::BuiltIn::SubgroupLeMask:
+    case spv::BuiltIn::SubgroupLtMask:
       return true;
     default:
       return false;
@@ -56,16 +57,17 @@
 bool HasBuiltinForRayTracingVolatileSemantics(
     analysis::DecorationManager* decoration_manager, uint32_t var_id) {
   return decoration_manager->FindDecoration(
-      var_id, SpvDecorationBuiltIn, [](const Instruction& inst) {
-        uint32_t built_in =
-            inst.GetSingleWordInOperand(kOpDecorateInOperandBuiltinDecoration);
+      var_id, uint32_t(spv::Decoration::BuiltIn), [](const Instruction& inst) {
+        spv::BuiltIn built_in = spv::BuiltIn(
+            inst.GetSingleWordInOperand(kOpDecorateInOperandBuiltinDecoration));
         return IsBuiltInForRayTracingVolatileSemantics(built_in);
       });
 }
 
 bool HasVolatileDecoration(analysis::DecorationManager* decoration_manager,
                            uint32_t var_id) {
-  return decoration_manager->HasDecoration(var_id, SpvDecorationVolatile);
+  return decoration_manager->HasDecoration(var_id,
+                                           uint32_t(spv::Decoration::Volatile));
 }
 
 }  // namespace
@@ -76,7 +78,7 @@
   }
   const bool is_vk_memory_model_enabled =
       context()->get_feature_mgr()->HasCapability(
-          SpvCapabilityVulkanMemoryModel);
+          spv::Capability::VulkanMemoryModel);
   CollectTargetsForVolatileSemantics(is_vk_memory_model_enabled);
 
   // If VulkanMemoryModel capability is not enabled, we have to set Volatile
@@ -128,15 +130,16 @@
         }
         uint32_t memory_operands =
             load->GetSingleWordInOperand(kOpLoadInOperandMemoryOperands);
-        return (memory_operands & SpvMemoryAccessVolatileMask) != 0;
+        return (memory_operands & uint32_t(spv::MemoryAccessMask::Volatile)) !=
+               0;
       },
       funcs);
 }
 
 bool SpreadVolatileSemantics::HasInterfaceInConflictOfVolatileSemantics() {
   for (Instruction& entry_point : get_module()->entry_points()) {
-    SpvExecutionModel execution_model =
-        static_cast<SpvExecutionModel>(entry_point.GetSingleWordInOperand(0));
+    spv::ExecutionModel execution_model =
+        static_cast<spv::ExecutionModel>(entry_point.GetSingleWordInOperand(0));
     for (uint32_t operand_index = kOpEntryPointInOperandInterface;
          operand_index < entry_point.NumInOperands(); ++operand_index) {
       uint32_t var_id = entry_point.GetSingleWordInOperand(operand_index);
@@ -170,8 +173,8 @@
 void SpreadVolatileSemantics::CollectTargetsForVolatileSemantics(
     const bool is_vk_memory_model_enabled) {
   for (Instruction& entry_point : get_module()->entry_points()) {
-    SpvExecutionModel execution_model =
-        static_cast<SpvExecutionModel>(entry_point.GetSingleWordInOperand(0));
+    spv::ExecutionModel execution_model =
+        static_cast<spv::ExecutionModel>(entry_point.GetSingleWordInOperand(0));
     for (uint32_t operand_index = kOpEntryPointInOperandInterface;
          operand_index < entry_point.NumInOperands(); ++operand_index) {
       uint32_t var_id = entry_point.GetSingleWordInOperand(operand_index);
@@ -194,9 +197,10 @@
     return;
   }
   get_decoration_mgr()->AddDecoration(
-      SpvOpDecorate, {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {var_id}},
-                      {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
-                       {SpvDecorationVolatile}}});
+      spv::Op::OpDecorate,
+      {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {var_id}},
+       {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
+        {uint32_t(spv::Decoration::Volatile)}}});
 }
 
 bool SpreadVolatileSemantics::VisitLoadsOfPointersToVariableInEntries(
@@ -217,17 +221,17 @@
             return true;
           }
 
-          if (user->opcode() == SpvOpAccessChain ||
-              user->opcode() == SpvOpInBoundsAccessChain ||
-              user->opcode() == SpvOpPtrAccessChain ||
-              user->opcode() == SpvOpInBoundsPtrAccessChain ||
-              user->opcode() == SpvOpCopyObject) {
+          if (user->opcode() == spv::Op::OpAccessChain ||
+              user->opcode() == spv::Op::OpInBoundsAccessChain ||
+              user->opcode() == spv::Op::OpPtrAccessChain ||
+              user->opcode() == spv::Op::OpInBoundsPtrAccessChain ||
+              user->opcode() == spv::Op::OpCopyObject) {
             if (ptr_id == user->GetSingleWordInOperand(0))
               worklist.push_back(user->result_id());
             return true;
           }
 
-          if (user->opcode() != SpvOpLoad) {
+          if (user->opcode() != spv::Op::OpLoad) {
             return true;
           }
 
@@ -250,12 +254,12 @@
         [](Instruction* load) {
           if (load->NumInOperands() <= kOpLoadInOperandMemoryOperands) {
             load->AddOperand({SPV_OPERAND_TYPE_MEMORY_ACCESS,
-                              {SpvMemoryAccessVolatileMask}});
+                              {uint32_t(spv::MemoryAccessMask::Volatile)}});
             return true;
           }
           uint32_t memory_operands =
               load->GetSingleWordInOperand(kOpLoadInOperandMemoryOperands);
-          memory_operands |= SpvMemoryAccessVolatileMask;
+          memory_operands |= uint32_t(spv::MemoryAccessMask::Volatile);
           load->SetInOperand(kOpLoadInOperandMemoryOperands, {memory_operands});
           return true;
         },
@@ -264,29 +268,29 @@
 }
 
 bool SpreadVolatileSemantics::IsTargetForVolatileSemantics(
-    uint32_t var_id, SpvExecutionModel execution_model) {
+    uint32_t var_id, spv::ExecutionModel execution_model) {
   analysis::DecorationManager* decoration_manager =
       context()->get_decoration_mgr();
-  if (execution_model == SpvExecutionModelFragment) {
+  if (execution_model == spv::ExecutionModel::Fragment) {
     return get_module()->version() >= SPV_SPIRV_VERSION_WORD(1, 6) &&
            HasBuiltinDecoration(decoration_manager, var_id,
-                                SpvBuiltInHelperInvocation);
+                                uint32_t(spv::BuiltIn::HelperInvocation));
   }
 
-  if (execution_model == SpvExecutionModelIntersectionKHR ||
-      execution_model == SpvExecutionModelIntersectionNV) {
+  if (execution_model == spv::ExecutionModel::IntersectionKHR ||
+      execution_model == spv::ExecutionModel::IntersectionNV) {
     if (HasBuiltinDecoration(decoration_manager, var_id,
-                             SpvBuiltInRayTmaxKHR)) {
+                             uint32_t(spv::BuiltIn::RayTmaxKHR))) {
       return true;
     }
   }
 
   switch (execution_model) {
-    case SpvExecutionModelRayGenerationKHR:
-    case SpvExecutionModelClosestHitKHR:
-    case SpvExecutionModelMissKHR:
-    case SpvExecutionModelCallableKHR:
-    case SpvExecutionModelIntersectionKHR:
+    case spv::ExecutionModel::RayGenerationKHR:
+    case spv::ExecutionModel::ClosestHitKHR:
+    case spv::ExecutionModel::MissKHR:
+    case spv::ExecutionModel::CallableKHR:
+    case spv::ExecutionModel::IntersectionKHR:
       return HasBuiltinForRayTracingVolatileSemantics(decoration_manager,
                                                       var_id);
     default:
diff --git a/source/opt/spread_volatile_semantics.h b/source/opt/spread_volatile_semantics.h
index 014858d..4cbb526 100644
--- a/source/opt/spread_volatile_semantics.h
+++ b/source/opt/spread_volatile_semantics.h
@@ -39,7 +39,8 @@
   // have an execution model.
   bool HasNoExecutionModel() {
     return get_module()->entry_points().empty() &&
-           context()->get_feature_mgr()->HasCapability(SpvCapabilityLinkage);
+           context()->get_feature_mgr()->HasCapability(
+               spv::Capability::Linkage);
   }
 
   // Iterates interface variables and spreads the Volatile semantics if it has
@@ -52,7 +53,7 @@
   // VUID-StandaloneSpirv-VulkanMemoryModel-04678 or
   // VUID-StandaloneSpirv-VulkanMemoryModel-04679.
   bool IsTargetForVolatileSemantics(uint32_t var_id,
-                                    SpvExecutionModel execution_model);
+                                    spv::ExecutionModel execution_model);
 
   // Collects interface variables that need the volatile semantics.
   // |is_vk_memory_model_enabled| is true if VulkanMemoryModel capability is
diff --git a/source/opt/ssa_rewrite_pass.cpp b/source/opt/ssa_rewrite_pass.cpp
index 22d8110..de4b0ca 100644
--- a/source/opt/ssa_rewrite_pass.cpp
+++ b/source/opt/ssa_rewrite_pass.cpp
@@ -300,12 +300,12 @@
 
 void SSARewriter::ProcessStore(Instruction* inst, BasicBlock* bb) {
   auto opcode = inst->opcode();
-  assert((opcode == SpvOpStore || opcode == SpvOpVariable) &&
+  assert((opcode == spv::Op::OpStore || opcode == spv::Op::OpVariable) &&
          "Expecting a store or a variable definition instruction.");
 
   uint32_t var_id = 0;
   uint32_t val_id = 0;
-  if (opcode == SpvOpStore) {
+  if (opcode == spv::Op::OpStore) {
     (void)pass_->GetPtr(inst, &var_id);
     val_id = inst->GetSingleWordInOperand(kStoreValIdInIdx);
   } else if (inst->NumInOperands() >= 2) {
@@ -443,9 +443,9 @@
 
   for (auto& inst : *bb) {
     auto opcode = inst.opcode();
-    if (opcode == SpvOpStore || opcode == SpvOpVariable) {
+    if (opcode == spv::Op::OpStore || opcode == spv::Op::OpVariable) {
       ProcessStore(&inst, bb);
-    } else if (inst.opcode() == SpvOpLoad) {
+    } else if (inst.opcode() == spv::Op::OpLoad) {
       if (!ProcessLoad(&inst, bb)) {
         return false;
       }
@@ -545,7 +545,7 @@
     // Generate a new OpPhi instruction and insert it in its basic
     // block.
     std::unique_ptr<Instruction> phi_inst(
-        new Instruction(pass_->context(), SpvOpPhi, type_id,
+        new Instruction(pass_->context(), spv::Op::OpPhi, type_id,
                         phi_candidate->result_id(), phi_operands));
     generated_phis.push_back(phi_inst.get());
     pass_->get_def_use_mgr()->AnalyzeInstDef(&*phi_inst);
@@ -554,7 +554,7 @@
     insert_it = insert_it.InsertBefore(std::move(phi_inst));
     pass_->context()->get_decoration_mgr()->CloneDecorations(
         phi_candidate->var_id(), phi_candidate->result_id(),
-        {SpvDecorationRelaxedPrecision});
+        {spv::Decoration::RelaxedPrecision});
 
     // Add DebugValue for the new OpPhi instruction.
     insert_it->SetDebugScope(local_var->GetDebugScope());
diff --git a/source/opt/strength_reduction_pass.cpp b/source/opt/strength_reduction_pass.cpp
index ab7c4eb..8f3a8a3 100644
--- a/source/opt/strength_reduction_pass.cpp
+++ b/source/opt/strength_reduction_pass.cpp
@@ -70,7 +70,7 @@
 
 bool StrengthReductionPass::ReplaceMultiplyByPowerOf2(
     BasicBlock::iterator* inst) {
-  assert((*inst)->opcode() == SpvOp::SpvOpIMul &&
+  assert((*inst)->opcode() == spv::Op::OpIMul &&
          "Only works for multiplication of integers.");
   bool modified = false;
 
@@ -84,7 +84,7 @@
   for (int i = 0; i < 2; i++) {
     uint32_t opId = (*inst)->GetSingleWordInOperand(i);
     Instruction* opInst = get_def_use_mgr()->GetDef(opId);
-    if (opInst->opcode() == SpvOp::SpvOpConstant) {
+    if (opInst->opcode() == spv::Op::OpConstant) {
       // We found a constant operand.
       uint32_t constVal = opInst->GetSingleWordOperand(2);
 
@@ -101,7 +101,7 @@
                              {shiftConstResultId});
         newOperands.push_back(shiftOperand);
         std::unique_ptr<Instruction> newInstruction(
-            new Instruction(context(), SpvOp::SpvOpShiftLeftLogical,
+            new Instruction(context(), spv::Op::OpShiftLeftLogical,
                             (*inst)->type_id(), newResultId, newOperands));
 
         // Insert the new instruction and update the data structures.
@@ -133,7 +133,7 @@
   for (auto iter = get_module()->types_values_begin();
        iter != get_module()->types_values_end(); ++iter) {
     switch (iter->opcode()) {
-      case SpvOp::SpvOpConstant:
+      case spv::Op::OpConstant:
         if (iter->type_id() == uint32_type_id_) {
           uint32_t value = iter->GetSingleWordOperand(2);
           if (value <= 32) constant_ids_[value] = iter->result_id();
@@ -159,9 +159,8 @@
     uint32_t resultId = TakeNextId();
     Operand constant(spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
                      {val});
-    std::unique_ptr<Instruction> newConstant(
-        new Instruction(context(), SpvOp::SpvOpConstant, uint32_type_id_,
-                        resultId, {constant}));
+    std::unique_ptr<Instruction> newConstant(new Instruction(
+        context(), spv::Op::OpConstant, uint32_type_id_, resultId, {constant}));
     get_module()->AddGlobalValue(std::move(newConstant));
 
     // Notify the DefUseManager about this constant.
@@ -184,7 +183,7 @@
     for (auto& bb : func) {
       for (auto inst = bb.begin(); inst != bb.end(); ++inst) {
         switch (inst->opcode()) {
-          case SpvOp::SpvOpIMul:
+          case spv::Op::OpIMul:
             if (ReplaceMultiplyByPowerOf2(&inst)) modified = true;
             break;
           default:
diff --git a/source/opt/strip_debug_info_pass.cpp b/source/opt/strip_debug_info_pass.cpp
index 6a0ebf2..f81bced 100644
--- a/source/opt/strip_debug_info_pass.cpp
+++ b/source/opt/strip_debug_info_pass.cpp
@@ -37,13 +37,13 @@
   if (uses_non_semantic_info) {
     for (auto& inst : context()->module()->debugs1()) {
       switch (inst.opcode()) {
-        case SpvOpString: {
+        case spv::Op::OpString: {
           analysis::DefUseManager* def_use = context()->get_def_use_mgr();
 
           // see if this string is used anywhere by a non-semantic instruction
           bool no_nonsemantic_use =
               def_use->WhileEachUser(&inst, [def_use](Instruction* use) {
-                if (use->opcode() == SpvOpExtInst) {
+                if (use->opcode() == spv::Op::OpExtInst) {
                   auto ext_inst_set =
                       def_use->GetDef(use->GetSingleWordInOperand(0u));
                   const std::string extension_name =
@@ -83,7 +83,8 @@
   // when that instruction is killed, which will lead to a double kill.
   std::sort(to_kill.begin(), to_kill.end(),
             [](Instruction* lhs, Instruction* rhs) -> bool {
-              if (lhs->opcode() == SpvOpName && rhs->opcode() != SpvOpName)
+              if (lhs->opcode() == spv::Op::OpName &&
+                  rhs->opcode() != spv::Op::OpName)
                 return true;
               return false;
             });
diff --git a/source/opt/strip_nonsemantic_info_pass.cpp b/source/opt/strip_nonsemantic_info_pass.cpp
index cd1fbb6..8899690 100644
--- a/source/opt/strip_nonsemantic_info_pass.cpp
+++ b/source/opt/strip_nonsemantic_info_pass.cpp
@@ -32,27 +32,31 @@
   bool other_uses_for_decorate_string = false;
   for (auto& inst : context()->module()->annotations()) {
     switch (inst.opcode()) {
-      case SpvOpDecorateStringGOOGLE:
-        if (inst.GetSingleWordInOperand(1) == SpvDecorationHlslSemanticGOOGLE ||
-            inst.GetSingleWordInOperand(1) == SpvDecorationUserTypeGOOGLE) {
+      case spv::Op::OpDecorateStringGOOGLE:
+        if (spv::Decoration(inst.GetSingleWordInOperand(1)) ==
+                spv::Decoration::HlslSemanticGOOGLE ||
+            spv::Decoration(inst.GetSingleWordInOperand(1)) ==
+                spv::Decoration::UserTypeGOOGLE) {
           to_remove.push_back(&inst);
         } else {
           other_uses_for_decorate_string = true;
         }
         break;
 
-      case SpvOpMemberDecorateStringGOOGLE:
-        if (inst.GetSingleWordInOperand(2) == SpvDecorationHlslSemanticGOOGLE ||
-            inst.GetSingleWordInOperand(2) == SpvDecorationUserTypeGOOGLE) {
+      case spv::Op::OpMemberDecorateStringGOOGLE:
+        if (spv::Decoration(inst.GetSingleWordInOperand(2)) ==
+                spv::Decoration::HlslSemanticGOOGLE ||
+            spv::Decoration(inst.GetSingleWordInOperand(2)) ==
+                spv::Decoration::UserTypeGOOGLE) {
           to_remove.push_back(&inst);
         } else {
           other_uses_for_decorate_string = true;
         }
         break;
 
-      case SpvOpDecorateId:
-        if (inst.GetSingleWordInOperand(1) ==
-            SpvDecorationHlslCounterBufferGOOGLE) {
+      case spv::Op::OpDecorateId:
+        if (spv::Decoration(inst.GetSingleWordInOperand(1)) ==
+            spv::Decoration::HlslCounterBufferGOOGLE) {
           to_remove.push_back(&inst);
         }
         break;
@@ -79,7 +83,7 @@
   // remove any extended inst imports that are non semantic
   std::unordered_set<uint32_t> non_semantic_sets;
   for (auto& inst : context()->module()->ext_inst_imports()) {
-    assert(inst.opcode() == SpvOpExtInstImport &&
+    assert(inst.opcode() == spv::Op::OpExtInstImport &&
            "Expecting an import of an extension's instruction set.");
     const std::string extension_name = inst.GetInOperand(0).AsString();
     if (spvtools::utils::starts_with(extension_name, "NonSemantic.")) {
@@ -93,7 +97,7 @@
   if (!non_semantic_sets.empty()) {
     context()->module()->ForEachInst(
         [&non_semantic_sets, &to_remove](Instruction* inst) {
-          if (inst->opcode() == SpvOpExtInst) {
+          if (inst->opcode() == spv::Op::OpExtInst) {
             if (non_semantic_sets.find(inst->GetSingleWordInOperand(0)) !=
                 non_semantic_sets.end()) {
               to_remove.push_back(inst);
diff --git a/source/opt/struct_cfg_analysis.cpp b/source/opt/struct_cfg_analysis.cpp
index 203db87..d39cebb 100644
--- a/source/opt/struct_cfg_analysis.cpp
+++ b/source/opt/struct_cfg_analysis.cpp
@@ -27,7 +27,7 @@
 StructuredCFGAnalysis::StructuredCFGAnalysis(IRContext* ctx) : context_(ctx) {
   // If this is not a shader, there are no merge instructions, and not
   // structured CFG to analyze.
-  if (!context_->get_feature_mgr()->HasCapability(SpvCapabilityShader)) {
+  if (!context_->get_feature_mgr()->HasCapability(spv::Capability::Shader)) {
     return;
   }
 
@@ -82,7 +82,7 @@
           merge_inst->GetSingleWordInOperand(kMergeNodeIndex);
       new_state.cinfo.containing_construct = block->id();
 
-      if (merge_inst->opcode() == SpvOpLoopMerge) {
+      if (merge_inst->opcode() == spv::Op::OpLoopMerge) {
         new_state.cinfo.containing_loop = block->id();
         new_state.cinfo.containing_switch = 0;
         new_state.continue_node =
@@ -98,7 +98,7 @@
         new_state.cinfo.in_continue = state.back().cinfo.in_continue;
         new_state.continue_node = state.back().continue_node;
 
-        if (merge_inst->NextNode()->opcode() == SpvOpSwitch) {
+        if (merge_inst->NextNode()->opcode() == spv::Op::OpSwitch) {
           new_state.cinfo.containing_switch = block->id();
         } else {
           new_state.cinfo.containing_switch =
@@ -226,7 +226,7 @@
     for (auto& bb : func) {
       if (IsInContainingLoopsContinueConstruct(bb.id())) {
         for (const Instruction& inst : bb) {
-          if (inst.opcode() == SpvOpFunctionCall) {
+          if (inst.opcode() == spv::Op::OpFunctionCall) {
             funcs_to_process.push(inst.GetSingleWordInOperand(0));
           }
         }
diff --git a/source/opt/type_manager.cpp b/source/opt/type_manager.cpp
index a0006f5..4568c0d 100644
--- a/source/opt/type_manager.cpp
+++ b/source/opt/type_manager.cpp
@@ -49,7 +49,7 @@
 }
 
 std::pair<Type*, std::unique_ptr<Pointer>> TypeManager::GetTypeAndPointerType(
-    uint32_t id, SpvStorageClass sc) const {
+    uint32_t id, spv::StorageClass sc) const {
   Type* type = GetType(id);
   if (type) {
     return std::make_pair(type, MakeUnique<Pointer>(type, sc));
@@ -220,10 +220,10 @@
 
   RegisterType(id, *type);
   switch (type->kind()) {
-#define DefineParameterlessCase(kind)                                     \
-  case Type::k##kind:                                                     \
-    typeInst = MakeUnique<Instruction>(context(), SpvOpType##kind, 0, id, \
-                                       std::initializer_list<Operand>{}); \
+#define DefineParameterlessCase(kind)                                         \
+  case Type::k##kind:                                                         \
+    typeInst = MakeUnique<Instruction>(context(), spv::Op::OpType##kind, 0,   \
+                                       id, std::initializer_list<Operand>{}); \
     break
     DefineParameterlessCase(Void);
     DefineParameterlessCase(Bool);
@@ -239,7 +239,7 @@
 #undef DefineParameterlessCase
     case Type::kInteger:
       typeInst = MakeUnique<Instruction>(
-          context(), SpvOpTypeInt, 0, id,
+          context(), spv::Op::OpTypeInt, 0, id,
           std::initializer_list<Operand>{
               {SPV_OPERAND_TYPE_LITERAL_INTEGER, {type->AsInteger()->width()}},
               {SPV_OPERAND_TYPE_LITERAL_INTEGER,
@@ -247,7 +247,7 @@
       break;
     case Type::kFloat:
       typeInst = MakeUnique<Instruction>(
-          context(), SpvOpTypeFloat, 0, id,
+          context(), spv::Op::OpTypeFloat, 0, id,
           std::initializer_list<Operand>{
               {SPV_OPERAND_TYPE_LITERAL_INTEGER, {type->AsFloat()->width()}}});
       break;
@@ -257,7 +257,7 @@
         return 0;
       }
       typeInst =
-          MakeUnique<Instruction>(context(), SpvOpTypeVector, 0, id,
+          MakeUnique<Instruction>(context(), spv::Op::OpTypeVector, 0, id,
                                   std::initializer_list<Operand>{
                                       {SPV_OPERAND_TYPE_ID, {subtype}},
                                       {SPV_OPERAND_TYPE_LITERAL_INTEGER,
@@ -270,7 +270,7 @@
         return 0;
       }
       typeInst =
-          MakeUnique<Instruction>(context(), SpvOpTypeMatrix, 0, id,
+          MakeUnique<Instruction>(context(), spv::Op::OpTypeMatrix, 0, id,
                                   std::initializer_list<Operand>{
                                       {SPV_OPERAND_TYPE_ID, {subtype}},
                                       {SPV_OPERAND_TYPE_LITERAL_INTEGER,
@@ -284,7 +284,7 @@
         return 0;
       }
       typeInst = MakeUnique<Instruction>(
-          context(), SpvOpTypeImage, 0, id,
+          context(), spv::Op::OpTypeImage, 0, id,
           std::initializer_list<Operand>{
               {SPV_OPERAND_TYPE_ID, {subtype}},
               {SPV_OPERAND_TYPE_DIMENSIONALITY,
@@ -308,7 +308,7 @@
         return 0;
       }
       typeInst = MakeUnique<Instruction>(
-          context(), SpvOpTypeSampledImage, 0, id,
+          context(), spv::Op::OpTypeSampledImage, 0, id,
           std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {subtype}}});
       break;
     }
@@ -318,7 +318,7 @@
         return 0;
       }
       typeInst = MakeUnique<Instruction>(
-          context(), SpvOpTypeArray, 0, id,
+          context(), spv::Op::OpTypeArray, 0, id,
           std::initializer_list<Operand>{
               {SPV_OPERAND_TYPE_ID, {subtype}},
               {SPV_OPERAND_TYPE_ID, {type->AsArray()->LengthId()}}});
@@ -331,7 +331,7 @@
         return 0;
       }
       typeInst = MakeUnique<Instruction>(
-          context(), SpvOpTypeRuntimeArray, 0, id,
+          context(), spv::Op::OpTypeRuntimeArray, 0, id,
           std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {subtype}}});
       break;
     }
@@ -346,7 +346,7 @@
         ops.push_back(Operand(SPV_OPERAND_TYPE_ID, {member_type_id}));
       }
       typeInst =
-          MakeUnique<Instruction>(context(), SpvOpTypeStruct, 0, id, ops);
+          MakeUnique<Instruction>(context(), spv::Op::OpTypeStruct, 0, id, ops);
       break;
     }
     case Type::kOpaque: {
@@ -354,7 +354,7 @@
       // Convert to null-terminated packed UTF-8 string.
       std::vector<uint32_t> words = spvtools::utils::MakeVector(opaque->name());
       typeInst = MakeUnique<Instruction>(
-          context(), SpvOpTypeOpaque, 0, id,
+          context(), spv::Op::OpTypeOpaque, 0, id,
           std::initializer_list<Operand>{
               {SPV_OPERAND_TYPE_LITERAL_STRING, words}});
       break;
@@ -366,7 +366,7 @@
         return 0;
       }
       typeInst = MakeUnique<Instruction>(
-          context(), SpvOpTypePointer, 0, id,
+          context(), spv::Op::OpTypePointer, 0, id,
           std::initializer_list<Operand>{
               {SPV_OPERAND_TYPE_STORAGE_CLASS,
                {static_cast<uint32_t>(pointer->storage_class())}},
@@ -388,20 +388,20 @@
         }
         ops.push_back(Operand(SPV_OPERAND_TYPE_ID, {paramater_type_id}));
       }
-      typeInst =
-          MakeUnique<Instruction>(context(), SpvOpTypeFunction, 0, id, ops);
+      typeInst = MakeUnique<Instruction>(context(), spv::Op::OpTypeFunction, 0,
+                                         id, ops);
       break;
     }
     case Type::kPipe:
       typeInst = MakeUnique<Instruction>(
-          context(), SpvOpTypePipe, 0, id,
+          context(), spv::Op::OpTypePipe, 0, id,
           std::initializer_list<Operand>{
               {SPV_OPERAND_TYPE_ACCESS_QUALIFIER,
                {static_cast<uint32_t>(type->AsPipe()->access_qualifier())}}});
       break;
     case Type::kForwardPointer:
       typeInst = MakeUnique<Instruction>(
-          context(), SpvOpTypeForwardPointer, 0, 0,
+          context(), spv::Op::OpTypeForwardPointer, 0, 0,
           std::initializer_list<Operand>{
               {SPV_OPERAND_TYPE_ID, {type->AsForwardPointer()->target_id()}},
               {SPV_OPERAND_TYPE_STORAGE_CLASS,
@@ -416,7 +416,7 @@
         return 0;
       }
       typeInst = MakeUnique<Instruction>(
-          context(), SpvOpTypeCooperativeMatrixNV, 0, id,
+          context(), spv::Op::OpTypeCooperativeMatrixNV, 0, id,
           std::initializer_list<Operand>{
               {SPV_OPERAND_TYPE_ID, {component_type}},
               {SPV_OPERAND_TYPE_SCOPE_ID, {coop_mat->scope_id()}},
@@ -435,7 +435,7 @@
 }
 
 uint32_t TypeManager::FindPointerToType(uint32_t type_id,
-                                        SpvStorageClass storage_class) {
+                                        spv::StorageClass storage_class) {
   Type* pointeeTy = GetType(type_id);
   Pointer pointerTy(pointeeTy, storage_class);
   if (pointeeTy->IsUniqueType(true)) {
@@ -447,11 +447,11 @@
   Module::inst_iterator type_itr = context()->module()->types_values_begin();
   for (; type_itr != context()->module()->types_values_end(); ++type_itr) {
     const Instruction* type_inst = &*type_itr;
-    if (type_inst->opcode() == SpvOpTypePointer &&
+    if (type_inst->opcode() == spv::Op::OpTypePointer &&
         type_inst->GetSingleWordOperand(kSpvTypePointerTypeIdInIdx) ==
             type_id &&
-        type_inst->GetSingleWordOperand(kSpvTypePointerStorageClass) ==
-            storage_class)
+        spv::StorageClass(type_inst->GetSingleWordOperand(
+            kSpvTypePointerStorageClass)) == storage_class)
       return type_inst->result_id();
   }
 
@@ -459,7 +459,7 @@
   // TODO(1841): Handle id overflow.
   uint32_t resultId = context()->TakeNextId();
   std::unique_ptr<Instruction> type_inst(
-      new Instruction(context(), SpvOpTypePointer, 0, resultId,
+      new Instruction(context(), spv::Op::OpTypePointer, 0, resultId,
                       {{spv_operand_type_t::SPV_OPERAND_TYPE_STORAGE_CLASS,
                         {uint32_t(storage_class)}},
                        {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {type_id}}}));
@@ -495,7 +495,8 @@
     ops.push_back(Operand(SPV_OPERAND_TYPE_LITERAL_INTEGER, {decoration[i]}));
   }
   context()->AddAnnotationInst(MakeUnique<Instruction>(
-      context(), (element == 0 ? SpvOpDecorate : SpvOpMemberDecorate), 0, 0,
+      context(),
+      (element == 0 ? spv::Op::OpDecorate : spv::Op::OpMemberDecorate), 0, 0,
       ops));
   Instruction* inst = &*--context()->annotation_end();
   context()->get_def_use_mgr()->AnalyzeInstUse(inst);
@@ -665,46 +666,47 @@
 
   Type* type = nullptr;
   switch (inst.opcode()) {
-    case SpvOpTypeVoid:
+    case spv::Op::OpTypeVoid:
       type = new Void();
       break;
-    case SpvOpTypeBool:
+    case spv::Op::OpTypeBool:
       type = new Bool();
       break;
-    case SpvOpTypeInt:
+    case spv::Op::OpTypeInt:
       type = new Integer(inst.GetSingleWordInOperand(0),
                          inst.GetSingleWordInOperand(1));
       break;
-    case SpvOpTypeFloat:
+    case spv::Op::OpTypeFloat:
       type = new Float(inst.GetSingleWordInOperand(0));
       break;
-    case SpvOpTypeVector:
+    case spv::Op::OpTypeVector:
       type = new Vector(GetType(inst.GetSingleWordInOperand(0)),
                         inst.GetSingleWordInOperand(1));
       break;
-    case SpvOpTypeMatrix:
+    case spv::Op::OpTypeMatrix:
       type = new Matrix(GetType(inst.GetSingleWordInOperand(0)),
                         inst.GetSingleWordInOperand(1));
       break;
-    case SpvOpTypeImage: {
-      const SpvAccessQualifier access =
-          inst.NumInOperands() < 8
-              ? SpvAccessQualifierReadOnly
-              : static_cast<SpvAccessQualifier>(inst.GetSingleWordInOperand(7));
+    case spv::Op::OpTypeImage: {
+      const spv::AccessQualifier access =
+          inst.NumInOperands() < 8 ? spv::AccessQualifier::ReadOnly
+                                   : static_cast<spv::AccessQualifier>(
+                                         inst.GetSingleWordInOperand(7));
       type = new Image(
           GetType(inst.GetSingleWordInOperand(0)),
-          static_cast<SpvDim>(inst.GetSingleWordInOperand(1)),
+          static_cast<spv::Dim>(inst.GetSingleWordInOperand(1)),
           inst.GetSingleWordInOperand(2), inst.GetSingleWordInOperand(3) == 1,
           inst.GetSingleWordInOperand(4) == 1, inst.GetSingleWordInOperand(5),
-          static_cast<SpvImageFormat>(inst.GetSingleWordInOperand(6)), access);
+          static_cast<spv::ImageFormat>(inst.GetSingleWordInOperand(6)),
+          access);
     } break;
-    case SpvOpTypeSampler:
+    case spv::Op::OpTypeSampler:
       type = new Sampler();
       break;
-    case SpvOpTypeSampledImage:
+    case spv::Op::OpTypeSampledImage:
       type = new SampledImage(GetType(inst.GetSingleWordInOperand(0)));
       break;
-    case SpvOpTypeArray: {
+    case spv::Op::OpTypeArray: {
       const uint32_t length_id = inst.GetSingleWordInOperand(1);
       const Instruction* length_constant_inst = id_to_constant_inst_[length_id];
       assert(length_constant_inst);
@@ -717,11 +719,11 @@
       // Only OpSpecConstant has a SpecId.
       uint32_t spec_id = 0u;
       bool has_spec_id = false;
-      if (length_constant_inst->opcode() == SpvOpSpecConstant) {
+      if (length_constant_inst->opcode() == spv::Op::OpSpecConstant) {
         context()->get_decoration_mgr()->ForEachDecoration(
-            length_id, SpvDecorationSpecId,
+            length_id, uint32_t(spv::Decoration::SpecId),
             [&spec_id, &has_spec_id](const Instruction& decoration) {
-              assert(decoration.opcode() == SpvOpDecorate);
+              assert(decoration.opcode() == spv::Op::OpDecorate);
               spec_id = decoration.GetSingleWordOperand(2u);
               has_spec_id = true;
             });
@@ -730,7 +732,8 @@
       if (has_spec_id) {
         extra_words.push_back(spec_id);
       }
-      if ((opcode == SpvOpConstant) || (opcode == SpvOpSpecConstant)) {
+      if ((opcode == spv::Op::OpConstant) ||
+          (opcode == spv::Op::OpSpecConstant)) {
         // Always include the literal constant words.  In the spec constant
         // case, the constant might not be overridden, so it's still
         // significant.
@@ -754,7 +757,7 @@
         return type;
       }
     } break;
-    case SpvOpTypeRuntimeArray:
+    case spv::Op::OpTypeRuntimeArray:
       type = new RuntimeArray(GetType(inst.GetSingleWordInOperand(0)));
       if (id_to_incomplete_type_.count(inst.GetSingleWordInOperand(0))) {
         incomplete_types_.emplace_back(inst.result_id(), type);
@@ -762,7 +765,7 @@
         return type;
       }
       break;
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       std::vector<const Type*> element_types;
       bool incomplete_type = false;
       for (uint32_t i = 0; i < inst.NumInOperands(); ++i) {
@@ -780,14 +783,14 @@
         return type;
       }
     } break;
-    case SpvOpTypeOpaque: {
+    case spv::Op::OpTypeOpaque: {
       type = new Opaque(inst.GetInOperand(0).AsString());
     } break;
-    case SpvOpTypePointer: {
+    case spv::Op::OpTypePointer: {
       uint32_t pointee_type_id = inst.GetSingleWordInOperand(1);
       type = new Pointer(
           GetType(pointee_type_id),
-          static_cast<SpvStorageClass>(inst.GetSingleWordInOperand(0)));
+          static_cast<spv::StorageClass>(inst.GetSingleWordInOperand(0)));
 
       if (id_to_incomplete_type_.count(pointee_type_id)) {
         incomplete_types_.emplace_back(inst.result_id(), type);
@@ -797,7 +800,7 @@
       id_to_incomplete_type_.erase(inst.result_id());
 
     } break;
-    case SpvOpTypeFunction: {
+    case spv::Op::OpTypeFunction: {
       bool incomplete_type = false;
       uint32_t return_type_id = inst.GetSingleWordInOperand(0);
       if (id_to_incomplete_type_.count(return_type_id)) {
@@ -821,47 +824,47 @@
         return type;
       }
     } break;
-    case SpvOpTypeEvent:
+    case spv::Op::OpTypeEvent:
       type = new Event();
       break;
-    case SpvOpTypeDeviceEvent:
+    case spv::Op::OpTypeDeviceEvent:
       type = new DeviceEvent();
       break;
-    case SpvOpTypeReserveId:
+    case spv::Op::OpTypeReserveId:
       type = new ReserveId();
       break;
-    case SpvOpTypeQueue:
+    case spv::Op::OpTypeQueue:
       type = new Queue();
       break;
-    case SpvOpTypePipe:
+    case spv::Op::OpTypePipe:
       type = new Pipe(
-          static_cast<SpvAccessQualifier>(inst.GetSingleWordInOperand(0)));
+          static_cast<spv::AccessQualifier>(inst.GetSingleWordInOperand(0)));
       break;
-    case SpvOpTypeForwardPointer: {
+    case spv::Op::OpTypeForwardPointer: {
       // Handling of forward pointers is different from the other types.
       uint32_t target_id = inst.GetSingleWordInOperand(0);
-      type = new ForwardPointer(target_id, static_cast<SpvStorageClass>(
+      type = new ForwardPointer(target_id, static_cast<spv::StorageClass>(
                                                inst.GetSingleWordInOperand(1)));
       incomplete_types_.emplace_back(target_id, type);
       id_to_incomplete_type_[target_id] = type;
       return type;
     }
-    case SpvOpTypePipeStorage:
+    case spv::Op::OpTypePipeStorage:
       type = new PipeStorage();
       break;
-    case SpvOpTypeNamedBarrier:
+    case spv::Op::OpTypeNamedBarrier:
       type = new NamedBarrier();
       break;
-    case SpvOpTypeAccelerationStructureNV:
+    case spv::Op::OpTypeAccelerationStructureNV:
       type = new AccelerationStructureNV();
       break;
-    case SpvOpTypeCooperativeMatrixNV:
+    case spv::Op::OpTypeCooperativeMatrixNV:
       type = new CooperativeMatrixNV(GetType(inst.GetSingleWordInOperand(0)),
                                      inst.GetSingleWordInOperand(1),
                                      inst.GetSingleWordInOperand(2),
                                      inst.GetSingleWordInOperand(3));
       break;
-    case SpvOpTypeRayQueryKHR:
+    case spv::Op::OpTypeRayQueryKHR:
       type = new RayQueryKHR();
       break;
     default:
@@ -886,11 +889,11 @@
 }
 
 void TypeManager::AttachDecoration(const Instruction& inst, Type* type) {
-  const SpvOp opcode = inst.opcode();
+  const spv::Op opcode = inst.opcode();
   if (!IsAnnotationInst(opcode)) return;
 
   switch (opcode) {
-    case SpvOpDecorate: {
+    case spv::Op::OpDecorate: {
       const auto count = inst.NumOperands();
       std::vector<uint32_t> data;
       for (uint32_t i = 1; i < count; ++i) {
@@ -898,7 +901,7 @@
       }
       type->AddDecoration(std::move(data));
     } break;
-    case SpvOpMemberDecorate: {
+    case spv::Op::OpMemberDecorate: {
       const auto count = inst.NumOperands();
       const uint32_t index = inst.GetSingleWordOperand(1);
       std::vector<uint32_t> data;
diff --git a/source/opt/type_manager.h b/source/opt/type_manager.h
index 72e37f4..2417d49 100644
--- a/source/opt/type_manager.h
+++ b/source/opt/type_manager.h
@@ -99,7 +99,7 @@
   //
   // |id| must be a registered type.
   std::pair<Type*, std::unique_ptr<Pointer>> GetTypeAndPointerType(
-      uint32_t id, SpvStorageClass sc) const;
+      uint32_t id, spv::StorageClass sc) const;
 
   // Returns an id for a declaration representing |type|.  Returns 0 if the type
   // does not exists, and could not be generated.
@@ -112,7 +112,7 @@
   // Find pointer to type and storage in module, return its resultId.  If it is
   // not found, a new type is created, and its id is returned.  Returns 0 if the
   // type could not be created.
-  uint32_t FindPointerToType(uint32_t type_id, SpvStorageClass storage_class);
+  uint32_t FindPointerToType(uint32_t type_id, spv::StorageClass storage_class);
 
   // Registers |id| to |type|.
   //
diff --git a/source/opt/types.cpp b/source/opt/types.cpp
index 056aceb..b8aaa39 100644
--- a/source/opt/types.cpp
+++ b/source/opt/types.cpp
@@ -24,7 +24,6 @@
 
 #include "source/util/hash_combine.h"
 #include "source/util/make_unique.h"
-#include "spirv/unified1/spirv.h"
 
 namespace spvtools {
 namespace opt {
@@ -357,8 +356,9 @@
   return element_type_->ComputeHashValue(hash, seen);
 }
 
-Image::Image(Type* type, SpvDim dimen, uint32_t d, bool array, bool multisample,
-             uint32_t sampling, SpvImageFormat f, SpvAccessQualifier qualifier)
+Image::Image(Type* type, spv::Dim dimen, uint32_t d, bool array,
+             bool multisample, uint32_t sampling, spv::ImageFormat f,
+             spv::AccessQualifier qualifier)
     : Type(kImage),
       sampled_type_(type),
       dim_(dimen),
@@ -383,9 +383,9 @@
 
 std::string Image::str() const {
   std::ostringstream oss;
-  oss << "image(" << sampled_type_->str() << ", " << dim_ << ", " << depth_
-      << ", " << arrayed_ << ", " << ms_ << ", " << sampled_ << ", " << format_
-      << ", " << access_qualifier_ << ")";
+  oss << "image(" << sampled_type_->str() << ", " << uint32_t(dim_) << ", "
+      << depth_ << ", " << arrayed_ << ", " << ms_ << ", " << sampled_ << ", "
+      << uint32_t(format_) << ", " << uint32_t(access_qualifier_) << ")";
   return oss.str();
 }
 
@@ -557,7 +557,7 @@
   return hash_combine(hash, name_);
 }
 
-Pointer::Pointer(const Type* type, SpvStorageClass sc)
+Pointer::Pointer(const Type* type, spv::StorageClass sc)
     : Type(kPointer), pointee_type_(type), storage_class_(sc) {}
 
 bool Pointer::IsSameImpl(const Type* that, IsSameCache* seen) const {
@@ -636,7 +636,7 @@
 
 std::string Pipe::str() const {
   std::ostringstream oss;
-  oss << "pipe(" << access_qualifier_ << ")";
+  oss << "pipe(" << uint32_t(access_qualifier_) << ")";
   return oss.str();
 }
 
diff --git a/source/opt/types.h b/source/opt/types.h
index a92669e..645dbd4 100644
--- a/source/opt/types.h
+++ b/source/opt/types.h
@@ -302,9 +302,9 @@
 
 class Image : public Type {
  public:
-  Image(Type* type, SpvDim dimen, uint32_t d, bool array, bool multisample,
-        uint32_t sampling, SpvImageFormat f,
-        SpvAccessQualifier qualifier = SpvAccessQualifierReadOnly);
+  Image(Type* type, spv::Dim dimen, uint32_t d, bool array, bool multisample,
+        uint32_t sampling, spv::ImageFormat f,
+        spv::AccessQualifier qualifier = spv::AccessQualifier::ReadOnly);
   Image(const Image&) = default;
 
   std::string str() const override;
@@ -313,13 +313,13 @@
   const Image* AsImage() const override { return this; }
 
   const Type* sampled_type() const { return sampled_type_; }
-  SpvDim dim() const { return dim_; }
+  spv::Dim dim() const { return dim_; }
   uint32_t depth() const { return depth_; }
   bool is_arrayed() const { return arrayed_; }
   bool is_multisampled() const { return ms_; }
   uint32_t sampled() const { return sampled_; }
-  SpvImageFormat format() const { return format_; }
-  SpvAccessQualifier access_qualifier() const { return access_qualifier_; }
+  spv::ImageFormat format() const { return format_; }
+  spv::AccessQualifier access_qualifier() const { return access_qualifier_; }
 
   size_t ComputeExtraStateHash(size_t hash, SeenTypes* seen) const override;
 
@@ -327,13 +327,13 @@
   bool IsSameImpl(const Type* that, IsSameCache*) const override;
 
   Type* sampled_type_;
-  SpvDim dim_;
+  spv::Dim dim_;
   uint32_t depth_;
   bool arrayed_;
   bool ms_;
   uint32_t sampled_;
-  SpvImageFormat format_;
-  SpvAccessQualifier access_qualifier_;
+  spv::ImageFormat format_;
+  spv::AccessQualifier access_qualifier_;
 };
 
 class SampledImage : public Type {
@@ -491,12 +491,12 @@
 
 class Pointer : public Type {
  public:
-  Pointer(const Type* pointee, SpvStorageClass sc);
+  Pointer(const Type* pointee, spv::StorageClass sc);
   Pointer(const Pointer&) = default;
 
   std::string str() const override;
   const Type* pointee_type() const { return pointee_type_; }
-  SpvStorageClass storage_class() const { return storage_class_; }
+  spv::StorageClass storage_class() const { return storage_class_; }
 
   Pointer* AsPointer() override { return this; }
   const Pointer* AsPointer() const override { return this; }
@@ -509,7 +509,7 @@
   bool IsSameImpl(const Type* that, IsSameCache*) const override;
 
   const Type* pointee_type_;
-  SpvStorageClass storage_class_;
+  spv::StorageClass storage_class_;
 };
 
 class Function : public Type {
@@ -540,7 +540,7 @@
 
 class Pipe : public Type {
  public:
-  Pipe(SpvAccessQualifier qualifier)
+  Pipe(spv::AccessQualifier qualifier)
       : Type(kPipe), access_qualifier_(qualifier) {}
   Pipe(const Pipe&) = default;
 
@@ -549,19 +549,19 @@
   Pipe* AsPipe() override { return this; }
   const Pipe* AsPipe() const override { return this; }
 
-  SpvAccessQualifier access_qualifier() const { return access_qualifier_; }
+  spv::AccessQualifier access_qualifier() const { return access_qualifier_; }
 
   size_t ComputeExtraStateHash(size_t hash, SeenTypes* seen) const override;
 
  private:
   bool IsSameImpl(const Type* that, IsSameCache*) const override;
 
-  SpvAccessQualifier access_qualifier_;
+  spv::AccessQualifier access_qualifier_;
 };
 
 class ForwardPointer : public Type {
  public:
-  ForwardPointer(uint32_t id, SpvStorageClass sc)
+  ForwardPointer(uint32_t id, spv::StorageClass sc)
       : Type(kForwardPointer),
         target_id_(id),
         storage_class_(sc),
@@ -570,7 +570,7 @@
 
   uint32_t target_id() const { return target_id_; }
   void SetTargetPointer(const Pointer* pointer) { pointer_ = pointer; }
-  SpvStorageClass storage_class() const { return storage_class_; }
+  spv::StorageClass storage_class() const { return storage_class_; }
   const Pointer* target_pointer() const { return pointer_; }
 
   std::string str() const override;
@@ -584,7 +584,7 @@
   bool IsSameImpl(const Type* that, IsSameCache*) const override;
 
   uint32_t target_id_;
-  SpvStorageClass storage_class_;
+  spv::StorageClass storage_class_;
   const Pointer* pointer_;
 };
 
diff --git a/source/opt/unify_const_pass.cpp b/source/opt/unify_const_pass.cpp
index 6bfa11a..e017a00 100644
--- a/source/opt/unify_const_pass.cpp
+++ b/source/opt/unify_const_pass.cpp
@@ -139,12 +139,12 @@
     // processing is up to a descendant. This makes comparing the key array
     // always valid for judging duplication.
     switch (inst->opcode()) {
-      case SpvOp::SpvOpConstantTrue:
-      case SpvOp::SpvOpConstantFalse:
-      case SpvOp::SpvOpConstant:
-      case SpvOp::SpvOpConstantNull:
-      case SpvOp::SpvOpConstantSampler:
-      case SpvOp::SpvOpConstantComposite:
+      case spv::Op::OpConstantTrue:
+      case spv::Op::OpConstantFalse:
+      case spv::Op::OpConstant:
+      case spv::Op::OpConstantNull:
+      case spv::Op::OpConstantSampler:
+      case spv::Op::OpConstantComposite:
       // Only spec constants defined with OpSpecConstantOp and
       // OpSpecConstantComposite should be processed in this pass. Spec
       // constants defined with OpSpecConstant{|True|False} are decorated with
@@ -154,8 +154,8 @@
       // unique. When all the operands/components are the same between two
       // OpSpecConstant{Op|Composite} results, their result values must be the
       // same so are unifiable.
-      case SpvOp::SpvOpSpecConstantOp:
-      case SpvOp::SpvOpSpecConstantComposite: {
+      case spv::Op::OpSpecConstantOp:
+      case spv::Op::OpSpecConstantComposite: {
         uint32_t id = defined_constants.LookupEquivalentResultFor(*inst);
         if (id != inst->result_id()) {
           // The constant is a duplicated one, use the cached constant to
diff --git a/source/opt/upgrade_memory_model.cpp b/source/opt/upgrade_memory_model.cpp
index 9d6a5bc..1b439a6 100644
--- a/source/opt/upgrade_memory_model.cpp
+++ b/source/opt/upgrade_memory_model.cpp
@@ -28,14 +28,16 @@
 Pass::Status UpgradeMemoryModel::Process() {
   // TODO: This pass needs changes to support cooperative matrices.
   if (context()->get_feature_mgr()->HasCapability(
-          SpvCapabilityCooperativeMatrixNV)) {
+          spv::Capability::CooperativeMatrixNV)) {
     return Pass::Status::SuccessWithoutChange;
   }
 
   // Only update Logical GLSL450 to Logical VulkanKHR.
   Instruction* memory_model = get_module()->GetMemoryModel();
-  if (memory_model->GetSingleWordInOperand(0u) != SpvAddressingModelLogical ||
-      memory_model->GetSingleWordInOperand(1u) != SpvMemoryModelGLSL450) {
+  if (memory_model->GetSingleWordInOperand(0u) !=
+          uint32_t(spv::AddressingModel::Logical) ||
+      memory_model->GetSingleWordInOperand(1u) !=
+          uint32_t(spv::MemoryModel::GLSL450)) {
     return Pass::Status::SuccessWithoutChange;
   }
 
@@ -55,16 +57,17 @@
   // 3. Modify the memory model.
   Instruction* memory_model = get_module()->GetMemoryModel();
   context()->AddCapability(MakeUnique<Instruction>(
-      context(), SpvOpCapability, 0, 0,
+      context(), spv::Op::OpCapability, 0, 0,
       std::initializer_list<Operand>{
-          {SPV_OPERAND_TYPE_CAPABILITY, {SpvCapabilityVulkanMemoryModelKHR}}}));
+          {SPV_OPERAND_TYPE_CAPABILITY,
+           {uint32_t(spv::Capability::VulkanMemoryModelKHR)}}}));
   const std::string extension = "SPV_KHR_vulkan_memory_model";
   std::vector<uint32_t> words = spvtools::utils::MakeVector(extension);
   context()->AddExtension(
-      MakeUnique<Instruction>(context(), SpvOpExtension, 0, 0,
+      MakeUnique<Instruction>(context(), spv::Op::OpExtension, 0, 0,
                               std::initializer_list<Operand>{
                                   {SPV_OPERAND_TYPE_LITERAL_STRING, words}}));
-  memory_model->SetInOperand(1u, {SpvMemoryModelVulkanKHR});
+  memory_model->SetInOperand(1u, {uint32_t(spv::MemoryModel::VulkanKHR)});
 }
 
 void UpgradeMemoryModel::UpgradeInstructions() {
@@ -79,7 +82,7 @@
   // In SPIR-V 1.4 or later, normalize OpCopyMemory* access operands.
   for (auto& func : *get_module()) {
     func.ForEachInst([this](Instruction* inst) {
-      if (inst->opcode() == SpvOpExtInst) {
+      if (inst->opcode() == spv::Op::OpExtInst) {
         auto ext_inst = inst->GetSingleWordInOperand(1u);
         if (ext_inst == GLSLstd450Modf || ext_inst == GLSLstd450Frexp) {
           auto import =
@@ -89,9 +92,10 @@
           }
         }
       } else if (get_module()->version() >= SPV_SPIRV_VERSION_WORD(1, 4)) {
-        if (inst->opcode() == SpvOpCopyMemory ||
-            inst->opcode() == SpvOpCopyMemorySized) {
-          uint32_t start_operand = inst->opcode() == SpvOpCopyMemory ? 2u : 3u;
+        if (inst->opcode() == spv::Op::OpCopyMemory ||
+            inst->opcode() == spv::Op::OpCopyMemorySized) {
+          uint32_t start_operand =
+              inst->opcode() == spv::Op::OpCopyMemory ? 2u : 3u;
           if (inst->NumInOperands() > start_operand) {
             auto num_access_words = MemoryAccessNumWords(
                 inst->GetSingleWordInOperand(start_operand));
@@ -105,10 +109,10 @@
             }
           } else {
             // Add two memory access operands.
-            inst->AddOperand(
-                {SPV_OPERAND_TYPE_MEMORY_ACCESS, {SpvMemoryAccessMaskNone}});
-            inst->AddOperand(
-                {SPV_OPERAND_TYPE_MEMORY_ACCESS, {SpvMemoryAccessMaskNone}});
+            inst->AddOperand({SPV_OPERAND_TYPE_MEMORY_ACCESS,
+                              {uint32_t(spv::MemoryAccessMask::MaskNone)}});
+            inst->AddOperand({SPV_OPERAND_TYPE_MEMORY_ACCESS,
+                              {uint32_t(spv::MemoryAccessMask::MaskNone)}});
           }
         }
       }
@@ -129,23 +133,23 @@
       bool dst_coherent = false;
       bool dst_volatile = false;
       uint32_t start_operand = 0u;
-      SpvScope scope = SpvScopeQueueFamilyKHR;
-      SpvScope src_scope = SpvScopeQueueFamilyKHR;
-      SpvScope dst_scope = SpvScopeQueueFamilyKHR;
+      spv::Scope scope = spv::Scope::QueueFamilyKHR;
+      spv::Scope src_scope = spv::Scope::QueueFamilyKHR;
+      spv::Scope dst_scope = spv::Scope::QueueFamilyKHR;
       switch (inst->opcode()) {
-        case SpvOpLoad:
-        case SpvOpStore:
+        case spv::Op::OpLoad:
+        case spv::Op::OpStore:
           std::tie(is_coherent, is_volatile, scope) =
               GetInstructionAttributes(inst->GetSingleWordInOperand(0u));
           break;
-        case SpvOpImageRead:
-        case SpvOpImageSparseRead:
-        case SpvOpImageWrite:
+        case spv::Op::OpImageRead:
+        case spv::Op::OpImageSparseRead:
+        case spv::Op::OpImageWrite:
           std::tie(is_coherent, is_volatile, scope) =
               GetInstructionAttributes(inst->GetSingleWordInOperand(0u));
           break;
-        case SpvOpCopyMemory:
-        case SpvOpCopyMemorySized:
+        case spv::Op::OpCopyMemory:
+        case spv::Op::OpCopyMemorySized:
           std::tie(dst_coherent, dst_volatile, dst_scope) =
               GetInstructionAttributes(inst->GetSingleWordInOperand(0u));
           std::tie(src_coherent, src_volatile, src_scope) =
@@ -156,17 +160,17 @@
       }
 
       switch (inst->opcode()) {
-        case SpvOpLoad:
+        case spv::Op::OpLoad:
           UpgradeFlags(inst, 1u, is_coherent, is_volatile, kVisibility,
                        kMemory);
           break;
-        case SpvOpStore:
+        case spv::Op::OpStore:
           UpgradeFlags(inst, 2u, is_coherent, is_volatile, kAvailability,
                        kMemory);
           break;
-        case SpvOpCopyMemory:
-        case SpvOpCopyMemorySized:
-          start_operand = inst->opcode() == SpvOpCopyMemory ? 2u : 3u;
+        case spv::Op::OpCopyMemory:
+        case spv::Op::OpCopyMemorySized:
+          start_operand = inst->opcode() == spv::Op::OpCopyMemory ? 2u : 3u;
           if (get_module()->version() >= SPV_SPIRV_VERSION_WORD(1, 4)) {
             // There are guaranteed to be two memory access operands at this
             // point so treat source and target separately.
@@ -183,11 +187,11 @@
                          kVisibility, kMemory);
           }
           break;
-        case SpvOpImageRead:
-        case SpvOpImageSparseRead:
+        case spv::Op::OpImageRead:
+        case spv::Op::OpImageSparseRead:
           UpgradeFlags(inst, 2u, is_coherent, is_volatile, kVisibility, kImage);
           break;
-        case SpvOpImageWrite:
+        case spv::Op::OpImageWrite:
           UpgradeFlags(inst, 3u, is_coherent, is_volatile, kAvailability,
                        kImage);
           break;
@@ -205,7 +209,7 @@
         // There are two memory access operands. The first is for the target and
         // the second is for the source.
         if (dst_coherent || src_coherent) {
-          start_operand = inst->opcode() == SpvOpCopyMemory ? 2u : 3u;
+          start_operand = inst->opcode() == spv::Op::OpCopyMemory ? 2u : 3u;
           std::vector<Operand> new_operands;
           uint32_t num_access_words =
               MemoryAccessNumWords(inst->GetSingleWordInOperand(start_operand));
@@ -255,13 +259,13 @@
       if (spvOpcodeIsAtomicOp(inst->opcode())) {
         bool unused_coherent = false;
         bool is_volatile = false;
-        SpvScope unused_scope = SpvScopeQueueFamilyKHR;
+        spv::Scope unused_scope = spv::Scope::QueueFamilyKHR;
         std::tie(unused_coherent, is_volatile, unused_scope) =
             GetInstructionAttributes(inst->GetSingleWordInOperand(0));
 
         UpgradeSemantics(inst, 2u, is_volatile);
-        if (inst->opcode() == SpvOpAtomicCompareExchange ||
-            inst->opcode() == SpvOpAtomicCompareExchangeWeak) {
+        if (inst->opcode() == spv::Op::OpAtomicCompareExchange ||
+            inst->opcode() == spv::Op::OpAtomicCompareExchangeWeak) {
           UpgradeSemantics(inst, 3u, is_volatile);
         }
       }
@@ -286,14 +290,14 @@
     value = constant->GetU32();
   }
 
-  value |= SpvMemorySemanticsVolatileMask;
+  value |= uint32_t(spv::MemorySemanticsMask::Volatile);
   auto new_constant = context()->get_constant_mgr()->GetConstant(type, {value});
   auto new_semantics =
       context()->get_constant_mgr()->GetDefiningInstruction(new_constant);
   inst->SetInOperand(in_operand, {new_semantics->result_id()});
 }
 
-std::tuple<bool, bool, SpvScope> UpgradeMemoryModel::GetInstructionAttributes(
+std::tuple<bool, bool, spv::Scope> UpgradeMemoryModel::GetInstructionAttributes(
     uint32_t id) {
   // |id| is a pointer used in a memory/image instruction. Need to determine if
   // that pointer points to volatile or coherent memory. Workgroup storage
@@ -302,8 +306,8 @@
   Instruction* inst = context()->get_def_use_mgr()->GetDef(id);
   analysis::Type* type = context()->get_type_mgr()->GetType(inst->type_id());
   if (type->AsPointer() &&
-      type->AsPointer()->storage_class() == SpvStorageClassWorkgroup) {
-    return std::make_tuple(true, false, SpvScopeWorkgroup);
+      type->AsPointer()->storage_class() == spv::StorageClass::Workgroup) {
+    return std::make_tuple(true, false, spv::Scope::Workgroup);
   }
 
   bool is_coherent = false;
@@ -313,7 +317,7 @@
       TraceInstruction(context()->get_def_use_mgr()->GetDef(id),
                        std::vector<uint32_t>(), &visited);
 
-  return std::make_tuple(is_coherent, is_volatile, SpvScopeQueueFamilyKHR);
+  return std::make_tuple(is_coherent, is_volatile, spv::Scope::QueueFamilyKHR);
 }
 
 std::pair<bool, bool> UpgradeMemoryModel::TraceInstruction(
@@ -336,10 +340,10 @@
   bool is_coherent = false;
   bool is_volatile = false;
   switch (inst->opcode()) {
-    case SpvOpVariable:
-    case SpvOpFunctionParameter:
-      is_coherent |= HasDecoration(inst, 0, SpvDecorationCoherent);
-      is_volatile |= HasDecoration(inst, 0, SpvDecorationVolatile);
+    case spv::Op::OpVariable:
+    case spv::Op::OpFunctionParameter:
+      is_coherent |= HasDecoration(inst, 0, spv::Decoration::Coherent);
+      is_volatile |= HasDecoration(inst, 0, spv::Decoration::Volatile);
       if (!is_coherent || !is_volatile) {
         bool type_coherent = false;
         bool type_volatile = false;
@@ -349,14 +353,14 @@
         is_volatile |= type_volatile;
       }
       break;
-    case SpvOpAccessChain:
-    case SpvOpInBoundsAccessChain:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
       // Store indices in reverse order.
       for (uint32_t i = inst->NumInOperands() - 1; i > 0; --i) {
         indices.push_back(inst->GetSingleWordInOperand(i));
       }
       break;
-    case SpvOpPtrAccessChain:
+    case spv::Op::OpPtrAccessChain:
       // Store indices in reverse order. Skip the |Element| operand.
       for (uint32_t i = inst->NumInOperands() - 1; i > 1; --i) {
         indices.push_back(inst->GetSingleWordInOperand(i));
@@ -375,8 +379,8 @@
 
   // Variables and function parameters are sources. Continue searching until we
   // reach them.
-  if (inst->opcode() != SpvOpVariable &&
-      inst->opcode() != SpvOpFunctionParameter) {
+  if (inst->opcode() != spv::Op::OpVariable &&
+      inst->opcode() != spv::Op::OpFunctionParameter) {
     inst->ForEachInId([this, &is_coherent, &is_volatile, &indices,
                        &visited](const uint32_t* id_ptr) {
       Instruction* op_inst = context()->get_def_use_mgr()->GetDef(*id_ptr);
@@ -404,24 +408,24 @@
   bool is_coherent = false;
   bool is_volatile = false;
   Instruction* type_inst = context()->get_def_use_mgr()->GetDef(type_id);
-  assert(type_inst->opcode() == SpvOpTypePointer);
+  assert(type_inst->opcode() == spv::Op::OpTypePointer);
   Instruction* element_inst = context()->get_def_use_mgr()->GetDef(
       type_inst->GetSingleWordInOperand(1u));
   for (int i = (int)indices.size() - 1; i >= 0; --i) {
     if (is_coherent && is_volatile) break;
 
-    if (element_inst->opcode() == SpvOpTypePointer) {
+    if (element_inst->opcode() == spv::Op::OpTypePointer) {
       element_inst = context()->get_def_use_mgr()->GetDef(
           element_inst->GetSingleWordInOperand(1u));
-    } else if (element_inst->opcode() == SpvOpTypeStruct) {
+    } else if (element_inst->opcode() == spv::Op::OpTypeStruct) {
       uint32_t index = indices.at(i);
       Instruction* index_inst = context()->get_def_use_mgr()->GetDef(index);
-      assert(index_inst->opcode() == SpvOpConstant);
+      assert(index_inst->opcode() == spv::Op::OpConstant);
       uint64_t value = GetIndexValue(index_inst);
       is_coherent |= HasDecoration(element_inst, static_cast<uint32_t>(value),
-                                   SpvDecorationCoherent);
+                                   spv::Decoration::Coherent);
       is_volatile |= HasDecoration(element_inst, static_cast<uint32_t>(value),
-                                   SpvDecorationVolatile);
+                                   spv::Decoration::Volatile);
       element_inst = context()->get_def_use_mgr()->GetDef(
           element_inst->GetSingleWordInOperand(static_cast<uint32_t>(value)));
     } else {
@@ -457,13 +461,13 @@
 
     if (!visited.insert(def).second) continue;
 
-    if (def->opcode() == SpvOpTypeStruct) {
+    if (def->opcode() == spv::Op::OpTypeStruct) {
       // Any member decorated with coherent and/or volatile is enough to have
       // the related operation be flagged as coherent and/or volatile.
       is_coherent |= HasDecoration(def, std::numeric_limits<uint32_t>::max(),
-                                   SpvDecorationCoherent);
+                                   spv::Decoration::Coherent);
       is_volatile |= HasDecoration(def, std::numeric_limits<uint32_t>::max(),
-                                   SpvDecorationVolatile);
+                                   spv::Decoration::Volatile);
       if (is_coherent && is_volatile)
         return std::make_pair(is_coherent, is_volatile);
 
@@ -475,7 +479,7 @@
     } else if (spvOpcodeIsComposite(def->opcode())) {
       stack.push_back(context()->get_def_use_mgr()->GetDef(
           def->GetSingleWordInOperand(0u)));
-    } else if (def->opcode() == SpvOpTypePointer) {
+    } else if (def->opcode() == spv::Op::OpTypePointer) {
       stack.push_back(context()->get_def_use_mgr()->GetDef(
           def->GetSingleWordInOperand(1u)));
     }
@@ -504,14 +508,15 @@
 }
 
 bool UpgradeMemoryModel::HasDecoration(const Instruction* inst, uint32_t value,
-                                       SpvDecoration decoration) {
+                                       spv::Decoration decoration) {
   // If the iteration was terminated early then an appropriate decoration was
   // found.
   return !context()->get_decoration_mgr()->WhileEachDecoration(
-      inst->result_id(), decoration, [value](const Instruction& i) {
-        if (i.opcode() == SpvOpDecorate || i.opcode() == SpvOpDecorateId) {
+      inst->result_id(), (uint32_t)decoration, [value](const Instruction& i) {
+        if (i.opcode() == spv::Op::OpDecorate ||
+            i.opcode() == spv::Op::OpDecorateId) {
           return false;
-        } else if (i.opcode() == SpvOpMemberDecorate) {
+        } else if (i.opcode() == spv::Op::OpMemberDecorate) {
           if (value == i.GetSingleWordInOperand(1u) ||
               value == std::numeric_limits<uint32_t>::max())
             return false;
@@ -533,27 +538,27 @@
   }
   if (is_coherent) {
     if (inst_type == kMemory) {
-      flags |= SpvMemoryAccessNonPrivatePointerKHRMask;
+      flags |= uint32_t(spv::MemoryAccessMask::NonPrivatePointerKHR);
       if (operation_type == kVisibility) {
-        flags |= SpvMemoryAccessMakePointerVisibleKHRMask;
+        flags |= uint32_t(spv::MemoryAccessMask::MakePointerVisibleKHR);
       } else {
-        flags |= SpvMemoryAccessMakePointerAvailableKHRMask;
+        flags |= uint32_t(spv::MemoryAccessMask::MakePointerAvailableKHR);
       }
     } else {
-      flags |= SpvImageOperandsNonPrivateTexelKHRMask;
+      flags |= uint32_t(spv::ImageOperandsMask::NonPrivateTexelKHR);
       if (operation_type == kVisibility) {
-        flags |= SpvImageOperandsMakeTexelVisibleKHRMask;
+        flags |= uint32_t(spv::ImageOperandsMask::MakeTexelVisibleKHR);
       } else {
-        flags |= SpvImageOperandsMakeTexelAvailableKHRMask;
+        flags |= uint32_t(spv::ImageOperandsMask::MakeTexelAvailableKHR);
       }
     }
   }
 
   if (is_volatile) {
     if (inst_type == kMemory) {
-      flags |= SpvMemoryAccessVolatileMask;
+      flags |= uint32_t(spv::MemoryAccessMask::Volatile);
     } else {
-      flags |= SpvImageOperandsVolatileTexelKHRMask;
+      flags |= uint32_t(spv::ImageOperandsMask::VolatileTexelKHR);
     }
   }
 
@@ -566,7 +571,7 @@
   }
 }
 
-uint32_t UpgradeMemoryModel::GetScopeConstant(SpvScope scope) {
+uint32_t UpgradeMemoryModel::GetScopeConstant(spv::Scope scope) {
   analysis::Integer int_ty(32, false);
   uint32_t int_id = context()->get_type_mgr()->GetTypeInstruction(&int_ty);
   const analysis::Constant* constant =
@@ -587,15 +592,19 @@
       context()->get_decoration_mgr()->RemoveDecorationsFrom(
           inst->result_id(), [](const Instruction& dec) {
             switch (dec.opcode()) {
-              case SpvOpDecorate:
-              case SpvOpDecorateId:
-                if (dec.GetSingleWordInOperand(1u) == SpvDecorationCoherent ||
-                    dec.GetSingleWordInOperand(1u) == SpvDecorationVolatile)
+              case spv::Op::OpDecorate:
+              case spv::Op::OpDecorateId:
+                if (spv::Decoration(dec.GetSingleWordInOperand(1u)) ==
+                        spv::Decoration::Coherent ||
+                    spv::Decoration(dec.GetSingleWordInOperand(1u)) ==
+                        spv::Decoration::Volatile)
                   return true;
                 break;
-              case SpvOpMemberDecorate:
-                if (dec.GetSingleWordInOperand(2u) == SpvDecorationCoherent ||
-                    dec.GetSingleWordInOperand(2u) == SpvDecorationVolatile)
+              case spv::Op::OpMemberDecorate:
+                if (spv::Decoration(dec.GetSingleWordInOperand(2u)) ==
+                        spv::Decoration::Coherent ||
+                    spv::Decoration(dec.GetSingleWordInOperand(2u)) ==
+                        spv::Decoration::Volatile)
                   return true;
                 break;
               default:
@@ -616,7 +625,7 @@
     for (auto& block : *function) {
       block.ForEachInst([this, &barriers,
                          &operates_on_output](Instruction* inst) {
-        if (inst->opcode() == SpvOpControlBarrier) {
+        if (inst->opcode() == spv::Op::OpControlBarrier) {
           barriers.push_back(inst);
         } else if (!operates_on_output) {
           // This instruction operates on output storage class if it is a
@@ -625,7 +634,7 @@
           analysis::Type* type =
               context()->get_type_mgr()->GetType(inst->type_id());
           if (type && type->AsPointer() &&
-              type->AsPointer()->storage_class() == SpvStorageClassOutput) {
+              type->AsPointer()->storage_class() == spv::StorageClass::Output) {
             operates_on_output = true;
             return;
           }
@@ -635,7 +644,8 @@
             analysis::Type* op_type =
                 context()->get_type_mgr()->GetType(op_inst->type_id());
             if (op_type && op_type->AsPointer() &&
-                op_type->AsPointer()->storage_class() == SpvStorageClassOutput)
+                op_type->AsPointer()->storage_class() ==
+                    spv::StorageClass::Output)
               operates_on_output = true;
           });
         }
@@ -646,7 +656,8 @@
 
   std::queue<uint32_t> roots;
   for (auto& e : get_module()->entry_points())
-    if (e.GetSingleWordInOperand(0u) == SpvExecutionModelTessellationControl) {
+    if (spv::ExecutionModel(e.GetSingleWordInOperand(0u)) ==
+        spv::ExecutionModel::TessellationControl) {
       roots.push(e.GetSingleWordInOperand(1u));
       if (context()->ProcessCallTreeFromRoots(CollectBarriers, &roots)) {
         for (auto barrier : barriers) {
@@ -659,8 +670,9 @@
           uint64_t semantics_value = GetIndexValue(semantics_inst);
           const analysis::Constant* constant =
               context()->get_constant_mgr()->GetConstant(
-                  semantics_type, {static_cast<uint32_t>(semantics_value) |
-                                   SpvMemorySemanticsOutputMemoryKHRMask});
+                  semantics_type,
+                  {static_cast<uint32_t>(semantics_value) |
+                   uint32_t(spv::MemorySemanticsMask::OutputMemoryKHR)});
           barrier->SetInOperand(2u, {context()
                                          ->get_constant_mgr()
                                          ->GetDefiningInstruction(constant)
@@ -680,15 +692,15 @@
     // * Workgroup ops (e.g. async_copy) have at most workgroup scope.
     if (spvOpcodeIsAtomicOp(inst->opcode())) {
       if (IsDeviceScope(inst->GetSingleWordInOperand(1))) {
-        inst->SetInOperand(1, {GetScopeConstant(SpvScopeQueueFamilyKHR)});
+        inst->SetInOperand(1, {GetScopeConstant(spv::Scope::QueueFamilyKHR)});
       }
-    } else if (inst->opcode() == SpvOpControlBarrier) {
+    } else if (inst->opcode() == spv::Op::OpControlBarrier) {
       if (IsDeviceScope(inst->GetSingleWordInOperand(1))) {
-        inst->SetInOperand(1, {GetScopeConstant(SpvScopeQueueFamilyKHR)});
+        inst->SetInOperand(1, {GetScopeConstant(spv::Scope::QueueFamilyKHR)});
       }
-    } else if (inst->opcode() == SpvOpMemoryBarrier) {
+    } else if (inst->opcode() == spv::Op::OpMemoryBarrier) {
       if (IsDeviceScope(inst->GetSingleWordInOperand(0))) {
-        inst->SetInOperand(0, {GetScopeConstant(SpvScopeQueueFamilyKHR)});
+        inst->SetInOperand(0, {GetScopeConstant(spv::Scope::QueueFamilyKHR)});
       }
     }
   });
@@ -704,14 +716,14 @@
   assert(type->width() == 32 || type->width() == 64);
   if (type->width() == 32) {
     if (type->IsSigned())
-      return static_cast<uint32_t>(constant->GetS32()) == SpvScopeDevice;
+      return static_cast<spv::Scope>(constant->GetS32()) == spv::Scope::Device;
     else
-      return static_cast<uint32_t>(constant->GetU32()) == SpvScopeDevice;
+      return static_cast<spv::Scope>(constant->GetU32()) == spv::Scope::Device;
   } else {
     if (type->IsSigned())
-      return static_cast<uint32_t>(constant->GetS64()) == SpvScopeDevice;
+      return static_cast<spv::Scope>(constant->GetS64()) == spv::Scope::Device;
     else
-      return static_cast<uint32_t>(constant->GetU64()) == SpvScopeDevice;
+      return static_cast<spv::Scope>(constant->GetU64()) == spv::Scope::Device;
   }
 
   assert(false);
@@ -758,9 +770,9 @@
 
 uint32_t UpgradeMemoryModel::MemoryAccessNumWords(uint32_t mask) {
   uint32_t result = 1;
-  if (mask & SpvMemoryAccessAlignedMask) ++result;
-  if (mask & SpvMemoryAccessMakePointerAvailableKHRMask) ++result;
-  if (mask & SpvMemoryAccessMakePointerVisibleKHRMask) ++result;
+  if (mask & uint32_t(spv::MemoryAccessMask::Aligned)) ++result;
+  if (mask & uint32_t(spv::MemoryAccessMask::MakePointerAvailableKHR)) ++result;
+  if (mask & uint32_t(spv::MemoryAccessMask::MakePointerVisibleKHR)) ++result;
   return result;
 }
 
diff --git a/source/opt/upgrade_memory_model.h b/source/opt/upgrade_memory_model.h
index f75304e..489436b 100644
--- a/source/opt/upgrade_memory_model.h
+++ b/source/opt/upgrade_memory_model.h
@@ -71,7 +71,7 @@
   void UpgradeAtomics();
 
   // Returns whether |id| is coherent and/or volatile.
-  std::tuple<bool, bool, SpvScope> GetInstructionAttributes(uint32_t id);
+  std::tuple<bool, bool, spv::Scope> GetInstructionAttributes(uint32_t id);
 
   // Traces |inst| to determine if it is coherent and/or volatile.
   // |indices| tracks the access chain indices seen so far.
@@ -84,7 +84,7 @@
   // match the index or |value| must be a maximum allowable value. The max
   // value allows any element to match.
   bool HasDecoration(const Instruction* inst, uint32_t value,
-                     SpvDecoration decoration);
+                     spv::Decoration decoration);
 
   // Returns whether |type_id| indexed via |indices| is coherent and/or
   // volatile.
@@ -108,7 +108,7 @@
                         bool is_volatile);
 
   // Returns the result id for a constant for |scope|.
-  uint32_t GetScopeConstant(SpvScope scope);
+  uint32_t GetScopeConstant(spv::Scope scope);
 
   // Returns the value of |index_inst|. |index_inst| must be an OpConstant of
   // integer type.g
@@ -127,7 +127,7 @@
   // scope.
   void UpgradeMemoryScope();
 
-  // Returns true if |scope_id| is SpvScopeDevice.
+  // Returns true if |scope_id| is spv::Scope::Device.
   bool IsDeviceScope(uint32_t scope_id);
 
   // Upgrades GLSL.std.450 modf and frexp. Both instructions are replaced with
diff --git a/source/opt/value_number_table.cpp b/source/opt/value_number_table.cpp
index 5271e3f..743dc52 100644
--- a/source/opt/value_number_table.cpp
+++ b/source/opt/value_number_table.cpp
@@ -57,9 +57,9 @@
   }
 
   switch (inst->opcode()) {
-    case SpvOpSampledImage:
-    case SpvOpImage:
-    case SpvOpVariable:
+    case spv::Op::OpSampledImage:
+    case spv::Op::OpImage:
+    case spv::Op::OpVariable:
       value = TakeNextValueNumber();
       id_to_value_[inst->result_id()] = value;
       return value;
@@ -82,7 +82,7 @@
   analysis::DecorationManager* dec_mgr = context()->get_decoration_mgr();
 
   // When we copy an object, the value numbers should be the same.
-  if (inst->opcode() == SpvOpCopyObject &&
+  if (inst->opcode() == spv::Op::OpCopyObject &&
       dec_mgr->HaveTheSameDecorations(inst->result_id(),
                                       inst->GetSingleWordInOperand(0))) {
     value = GetValueNumber(inst->GetSingleWordInOperand(0));
@@ -94,7 +94,7 @@
 
   // Phi nodes are a type of copy.  If all of the inputs have the same value
   // number, then we can assign the result of the phi the same value number.
-  if (inst->opcode() == SpvOpPhi && inst->NumInOperands() > 0 &&
+  if (inst->opcode() == spv::Op::OpPhi && inst->NumInOperands() > 0 &&
       dec_mgr->HaveTheSameDecorations(inst->result_id(),
                                       inst->GetSingleWordInOperand(0))) {
     value = GetValueNumber(inst->GetSingleWordInOperand(0));
@@ -226,7 +226,7 @@
   // instructions that are the same except for the result to hash to the
   // same value.
   std::u32string h;
-  h.push_back(inst.opcode());
+  h.push_back(uint32_t(inst.opcode()));
   h.push_back(inst.type_id());
   for (uint32_t i = 0; i < inst.NumInOperands(); ++i) {
     const auto& opnd = inst.GetInOperand(i);
diff --git a/source/opt/vector_dce.cpp b/source/opt/vector_dce.cpp
index 28d94a0..189eef0 100644
--- a/source/opt/vector_dce.cpp
+++ b/source/opt/vector_dce.cpp
@@ -68,17 +68,17 @@
     Instruction* current_inst = current_item.instruction;
 
     switch (current_inst->opcode()) {
-      case SpvOpCompositeExtract:
+      case spv::Op::OpCompositeExtract:
         MarkExtractUseAsLive(current_inst, current_item.components,
                              live_components, &work_list);
         break;
-      case SpvOpCompositeInsert:
+      case spv::Op::OpCompositeInsert:
         MarkInsertUsesAsLive(current_item, live_components, &work_list);
         break;
-      case SpvOpVectorShuffle:
+      case spv::Op::OpVectorShuffle:
         MarkVectorShuffleUsesAsLive(current_item, live_components, &work_list);
         break;
-      case SpvOpCompositeConstruct:
+      case spv::Op::OpCompositeConstruct:
         MarkCompositeContructUsesAsLive(current_item, live_components,
                                         &work_list);
         break;
@@ -347,11 +347,11 @@
     }
 
     switch (current_inst->opcode()) {
-      case SpvOpCompositeInsert:
+      case spv::Op::OpCompositeInsert:
         modified |= RewriteInsertInstruction(
             current_inst, live_component->second, &dead_dbg_value);
         break;
-      case SpvOpCompositeConstruct:
+      case spv::Op::OpCompositeConstruct:
         // TODO: The members that are not live can be replaced by an undef
         // or constant. This will remove uses of those values, and possibly
         // create opportunities for ADCE.
diff --git a/source/opt/workaround1209.cpp b/source/opt/workaround1209.cpp
index d6e9d2c..0cf954a 100644
--- a/source/opt/workaround1209.cpp
+++ b/source/opt/workaround1209.cpp
@@ -43,13 +43,13 @@
         loop_merges.pop();
       }
 
-      if (bb->tail()->opcode() == SpvOpUnreachable) {
+      if (bb->tail()->opcode() == spv::Op::OpUnreachable) {
         if (!loop_merges.empty()) {
           // We found an OpUnreachable inside a loop.
           // Replace it with an unconditional branch to the loop merge.
           context()->KillInst(&*bb->tail());
           std::unique_ptr<Instruction> new_branch(
-              new Instruction(context(), SpvOpBranch, 0, 0,
+              new Instruction(context(), spv::Op::OpBranch, 0, 0,
                               {{spv_operand_type_t::SPV_OPERAND_TYPE_ID,
                                 {loop_merges.top()}}}));
           context()->AnalyzeDefUse(&*new_branch);
diff --git a/source/opt/wrap_opkill.cpp b/source/opt/wrap_opkill.cpp
index 51432a7..c0c6d62 100644
--- a/source/opt/wrap_opkill.cpp
+++ b/source/opt/wrap_opkill.cpp
@@ -28,7 +28,8 @@
     Function* func = context()->GetFunction(func_id);
     bool successful = func->WhileEachInst([this, &modified](Instruction* inst) {
       const auto opcode = inst->opcode();
-      if ((opcode == SpvOpKill) || (opcode == SpvOpTerminateInvocation)) {
+      if ((opcode == spv::Op::OpKill) ||
+          (opcode == spv::Op::OpTerminateInvocation)) {
         modified = true;
         if (!ReplaceWithFunctionCall(inst)) {
           return false;
@@ -56,8 +57,8 @@
 }
 
 bool WrapOpKill::ReplaceWithFunctionCall(Instruction* inst) {
-  assert((inst->opcode() == SpvOpKill ||
-          inst->opcode() == SpvOpTerminateInvocation) &&
+  assert((inst->opcode() == spv::Op::OpKill ||
+          inst->opcode() == spv::Op::OpTerminateInvocation) &&
          "|inst| must be an OpKill or OpTerminateInvocation instruction.");
   InstructionBuilder ir_builder(
       context(), inst,
@@ -76,14 +77,15 @@
   Instruction* return_inst = nullptr;
   uint32_t return_type_id = GetOwningFunctionsReturnType(inst);
   if (return_type_id != GetVoidTypeId()) {
-    Instruction* undef = ir_builder.AddNullaryOp(return_type_id, SpvOpUndef);
+    Instruction* undef =
+        ir_builder.AddNullaryOp(return_type_id, spv::Op::OpUndef);
     if (undef == nullptr) {
       return false;
     }
     return_inst =
-        ir_builder.AddUnaryOp(0, SpvOpReturnValue, undef->result_id());
+        ir_builder.AddUnaryOp(0, spv::Op::OpReturnValue, undef->result_id());
   } else {
-    return_inst = ir_builder.AddNullaryOp(0, SpvOpReturn);
+    return_inst = ir_builder.AddNullaryOp(0, spv::Op::OpReturn);
   }
 
   if (return_inst == nullptr) {
@@ -115,13 +117,13 @@
   return type_mgr->GetTypeInstruction(&func_type);
 }
 
-uint32_t WrapOpKill::GetKillingFuncId(SpvOp opcode) {
+uint32_t WrapOpKill::GetKillingFuncId(spv::Op opcode) {
   //  Parameterize by opcode
-  assert(opcode == SpvOpKill || opcode == SpvOpTerminateInvocation);
+  assert(opcode == spv::Op::OpKill || opcode == spv::Op::OpTerminateInvocation);
 
   std::unique_ptr<Function>* const killing_func =
-      (opcode == SpvOpKill) ? &opkill_function_
-                            : &opterminateinvocation_function_;
+      (opcode == spv::Op::OpKill) ? &opkill_function_
+                                  : &opterminateinvocation_function_;
 
   if (*killing_func != nullptr) {
     return (*killing_func)->result_id();
@@ -139,14 +141,14 @@
 
   // Generate the function start instruction
   std::unique_ptr<Instruction> func_start(new Instruction(
-      context(), SpvOpFunction, void_type_id, killing_func_id, {}));
+      context(), spv::Op::OpFunction, void_type_id, killing_func_id, {}));
   func_start->AddOperand({SPV_OPERAND_TYPE_FUNCTION_CONTROL, {0}});
   func_start->AddOperand({SPV_OPERAND_TYPE_ID, {GetVoidFunctionTypeId()}});
   (*killing_func).reset(new Function(std::move(func_start)));
 
   // Generate the function end instruction
   std::unique_ptr<Instruction> func_end(
-      new Instruction(context(), SpvOpFunctionEnd, 0, 0, {}));
+      new Instruction(context(), spv::Op::OpFunctionEnd, 0, 0, {}));
   (*killing_func)->SetFunctionEnd(std::move(func_end));
 
   // Create the one basic block for the function.
@@ -155,7 +157,7 @@
     return 0;
   }
   std::unique_ptr<Instruction> label_inst(
-      new Instruction(context(), SpvOpLabel, 0, lab_id, {}));
+      new Instruction(context(), spv::Op::OpLabel, 0, lab_id, {}));
   std::unique_ptr<BasicBlock> bb(new BasicBlock(std::move(label_inst)));
 
   // Add the OpKill to the basic block
diff --git a/source/opt/wrap_opkill.h b/source/opt/wrap_opkill.h
index 7e43ca6..c9eb888 100644
--- a/source/opt/wrap_opkill.h
+++ b/source/opt/wrap_opkill.h
@@ -53,7 +53,7 @@
   // Return the id of a function that has return type void, has no parameters,
   // and contains a single instruction, which is |opcode|, either OpKill or
   // OpTerminateInvocation.  Returns 0 if the function could not be generated.
-  uint32_t GetKillingFuncId(SpvOp opcode);
+  uint32_t GetKillingFuncId(spv::Op opcode);
 
   // Returns the id of the return type for the function that contains |inst|.
   // Returns 0 if |inst| is not in a function.
diff --git a/source/reduce/conditional_branch_to_simple_conditional_branch_opportunity_finder.cpp b/source/reduce/conditional_branch_to_simple_conditional_branch_opportunity_finder.cpp
index 2cd779a..93b51a1 100644
--- a/source/reduce/conditional_branch_to_simple_conditional_branch_opportunity_finder.cpp
+++ b/source/reduce/conditional_branch_to_simple_conditional_branch_opportunity_finder.cpp
@@ -36,9 +36,9 @@
     for (auto* function : GetTargetFunctions(context, target_function)) {
       // Consider every block in the function.
       for (auto& block : *function) {
-        // The terminator must be SpvOpBranchConditional.
+        // The terminator must be spv::Op::OpBranchConditional.
         opt::Instruction* terminator = block.terminator();
-        if (terminator->opcode() != SpvOpBranchConditional) {
+        if (terminator->opcode() != spv::Op::OpBranchConditional) {
           continue;
         }
 
diff --git a/source/reduce/merge_blocks_reduction_opportunity.cpp b/source/reduce/merge_blocks_reduction_opportunity.cpp
index a2c3b40..e626d60 100644
--- a/source/reduce/merge_blocks_reduction_opportunity.cpp
+++ b/source/reduce/merge_blocks_reduction_opportunity.cpp
@@ -23,7 +23,7 @@
 MergeBlocksReductionOpportunity::MergeBlocksReductionOpportunity(
     opt::IRContext* context, opt::Function* function, opt::BasicBlock* block) {
   // Precondition: the terminator has to be OpBranch.
-  assert(block->terminator()->opcode() == SpvOpBranch);
+  assert(block->terminator()->opcode() == spv::Op::OpBranch);
   context_ = context;
   function_ = function;
   // Get the successor block associated with the OpBranch.
diff --git a/source/reduce/operand_to_const_reduction_opportunity_finder.cpp b/source/reduce/operand_to_const_reduction_opportunity_finder.cpp
index eb7498a..c6196f3 100644
--- a/source/reduce/operand_to_const_reduction_opportunity_finder.cpp
+++ b/source/reduce/operand_to_const_reduction_opportunity_finder.cpp
@@ -50,7 +50,7 @@
                 // The argument is already a constant.
                 continue;
               }
-              if (def->opcode() == SpvOpFunction) {
+              if (def->opcode() == spv::Op::OpFunction) {
                 // The argument refers to a function, e.g. the function called
                 // by OpFunctionCall; avoid replacing this with a constant of
                 // the function's return type.
diff --git a/source/reduce/operand_to_undef_reduction_opportunity_finder.cpp b/source/reduce/operand_to_undef_reduction_opportunity_finder.cpp
index 06bf955..c7bc121 100644
--- a/source/reduce/operand_to_undef_reduction_opportunity_finder.cpp
+++ b/source/reduce/operand_to_undef_reduction_opportunity_finder.cpp
@@ -32,7 +32,7 @@
         auto type_id = inst.type_id();
         if (type_id) {
           auto type_id_def = context->get_def_use_mgr()->GetDef(type_id);
-          if (type_id_def->opcode() == SpvOpTypePointer) {
+          if (type_id_def->opcode() == spv::Op::OpTypePointer) {
             continue;
           }
         }
@@ -57,7 +57,7 @@
             }
 
             // Don't replace function operands with undef.
-            if (operand_id_def->opcode() == SpvOpFunction) {
+            if (operand_id_def->opcode() == spv::Op::OpFunction) {
               continue;
             }
 
@@ -68,7 +68,7 @@
                   context->get_def_use_mgr()->GetDef(operand_type_id);
 
               // Skip pointer operands.
-              if (operand_type_id_def->opcode() == SpvOpTypePointer) {
+              if (operand_type_id_def->opcode() == spv::Op::OpTypePointer) {
                 continue;
               }
 
diff --git a/source/reduce/reduction_util.cpp b/source/reduce/reduction_util.cpp
index 511f432..c9882d5 100644
--- a/source/reduce/reduction_util.cpp
+++ b/source/reduce/reduction_util.cpp
@@ -26,7 +26,7 @@
 uint32_t FindOrCreateGlobalVariable(opt::IRContext* context,
                                     uint32_t pointer_type_id) {
   for (auto& inst : context->module()->types_values()) {
-    if (inst.opcode() != SpvOpVariable) {
+    if (inst.opcode() != spv::Op::OpVariable) {
       continue;
     }
     if (inst.type_id() == pointer_type_id) {
@@ -35,7 +35,7 @@
   }
   const uint32_t variable_id = context->TakeNextId();
   auto variable_inst = MakeUnique<opt::Instruction>(
-      context, SpvOpVariable, pointer_type_id, variable_id,
+      context, spv::Op::OpVariable, pointer_type_id, variable_id,
       opt::Instruction::OperandList(
           {{SPV_OPERAND_TYPE_STORAGE_CLASS,
             {static_cast<uint32_t>(context->get_type_mgr()
@@ -53,7 +53,7 @@
   assert(context->get_type_mgr()
              ->GetType(pointer_type_id)
              ->AsPointer()
-             ->storage_class() == SpvStorageClassFunction);
+             ->storage_class() == spv::StorageClass::Function);
 
   // Go through the instructions in the function's first block until we find a
   // suitable variable, or go past all the variables.
@@ -62,7 +62,7 @@
     // We will either find a suitable variable, or find a non-variable
     // instruction; we won't exhaust all instructions.
     assert(iter != function->begin()->end());
-    if (iter->opcode() != SpvOpVariable) {
+    if (iter->opcode() != spv::Op::OpVariable) {
       // If we see a non-variable, we have gone through all the variables.
       break;
     }
@@ -74,16 +74,17 @@
   // function's entry block.
   const uint32_t variable_id = context->TakeNextId();
   auto variable_inst = MakeUnique<opt::Instruction>(
-      context, SpvOpVariable, pointer_type_id, variable_id,
+      context, spv::Op::OpVariable, pointer_type_id, variable_id,
       opt::Instruction::OperandList(
-          {{SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}}}));
+          {{SPV_OPERAND_TYPE_STORAGE_CLASS,
+            {uint32_t(spv::StorageClass::Function)}}}));
   iter->InsertBefore(std::move(variable_inst));
   return variable_id;
 }
 
 uint32_t FindOrCreateGlobalUndef(opt::IRContext* context, uint32_t type_id) {
   for (auto& inst : context->module()->types_values()) {
-    if (inst.opcode() != SpvOpUndef) {
+    if (inst.opcode() != spv::Op::OpUndef) {
       continue;
     }
     if (inst.type_id() == type_id) {
@@ -91,8 +92,9 @@
     }
   }
   const uint32_t undef_id = context->TakeNextId();
-  auto undef_inst = MakeUnique<opt::Instruction>(
-      context, SpvOpUndef, type_id, undef_id, opt::Instruction::OperandList());
+  auto undef_inst =
+      MakeUnique<opt::Instruction>(context, spv::Op::OpUndef, type_id, undef_id,
+                                   opt::Instruction::OperandList());
   assert(undef_id == undef_inst->result_id());
   context->module()->AddGlobalValue(std::move(undef_inst));
   return undef_id;
diff --git a/source/reduce/remove_selection_reduction_opportunity_finder.cpp b/source/reduce/remove_selection_reduction_opportunity_finder.cpp
index 74df1b8..6abadf2 100644
--- a/source/reduce/remove_selection_reduction_opportunity_finder.cpp
+++ b/source/reduce/remove_selection_reduction_opportunity_finder.cpp
@@ -36,7 +36,7 @@
   for (auto* function : GetTargetFunctions(context, target_function)) {
     for (auto& block : *function) {
       if (auto merge_instruction = block.GetMergeInst()) {
-        if (merge_instruction->opcode() == SpvOpLoopMerge) {
+        if (merge_instruction->opcode() == spv::Op::OpLoopMerge) {
           uint32_t merge_block_id =
               merge_instruction->GetSingleWordOperand(kMergeNodeIndex);
           uint32_t continue_block_id =
@@ -54,7 +54,7 @@
   for (auto& function : *context->module()) {
     for (auto& block : function) {
       if (auto merge_instruction = block.GetMergeInst()) {
-        if (merge_instruction->opcode() == SpvOpSelectionMerge) {
+        if (merge_instruction->opcode() == spv::Op::OpSelectionMerge) {
           if (CanOpSelectionMergeBeRemoved(
                   context, block, merge_instruction,
                   merge_and_continue_blocks_from_loops)) {
diff --git a/source/reduce/remove_struct_member_reduction_opportunity.cpp b/source/reduce/remove_struct_member_reduction_opportunity.cpp
index e72ed35..3309fd0 100644
--- a/source/reduce/remove_struct_member_reduction_opportunity.cpp
+++ b/source/reduce/remove_struct_member_reduction_opportunity.cpp
@@ -36,14 +36,14 @@
       struct_type_, [this, &decorations_to_kill](opt::Instruction* user,
                                                  uint32_t /*operand_index*/) {
         switch (user->opcode()) {
-          case SpvOpCompositeConstruct:
-          case SpvOpConstantComposite:
+          case spv::Op::OpCompositeConstruct:
+          case spv::Op::OpConstantComposite:
             // This use is constructing a composite of the struct type, so we
             // must remove the id that was provided for the member we are
             // removing.
             user->RemoveInOperand(member_index_);
             break;
-          case SpvOpMemberDecorate:
+          case spv::Op::OpMemberDecorate:
             // This use is decorating a member of the struct.
             if (user->GetSingleWordInOperand(1) == member_index_) {
               // The member we are removing is being decorated, so we record
@@ -78,8 +78,8 @@
     for (auto& block : function) {
       for (auto& inst : block) {
         switch (inst.opcode()) {
-          case SpvOpAccessChain:
-          case SpvOpInBoundsAccessChain: {
+          case spv::Op::OpAccessChain:
+          case spv::Op::OpInBoundsAccessChain: {
             // These access chain instructions take sequences of ids for
             // indexing, starting from input operand 1.
             auto composite_type_id =
@@ -90,8 +90,8 @@
                     ->GetSingleWordInOperand(1);
             AdjustAccessedIndices(composite_type_id, 1, false, context, &inst);
           } break;
-          case SpvOpPtrAccessChain:
-          case SpvOpInBoundsPtrAccessChain: {
+          case spv::Op::OpPtrAccessChain:
+          case spv::Op::OpInBoundsPtrAccessChain: {
             // These access chain instructions take sequences of ids for
             // indexing, starting from input operand 2.
             auto composite_type_id =
@@ -102,7 +102,7 @@
                     ->GetSingleWordInOperand(1);
             AdjustAccessedIndices(composite_type_id, 2, false, context, &inst);
           } break;
-          case SpvOpCompositeExtract: {
+          case spv::Op::OpCompositeExtract: {
             // OpCompositeExtract uses literals for indexing, starting at input
             // operand 1.
             auto composite_type_id =
@@ -111,7 +111,7 @@
                     ->type_id();
             AdjustAccessedIndices(composite_type_id, 1, true, context, &inst);
           } break;
-          case SpvOpCompositeInsert: {
+          case spv::Op::OpCompositeInsert: {
             // OpCompositeInsert uses literals for indexing, starting at input
             // operand 2.
             auto composite_type_id =
@@ -146,13 +146,13 @@
        i < composite_access_instruction->NumInOperands(); i++) {
     auto type_inst = context->get_def_use_mgr()->GetDef(next_type);
     switch (type_inst->opcode()) {
-      case SpvOpTypeArray:
-      case SpvOpTypeMatrix:
-      case SpvOpTypeRuntimeArray:
-      case SpvOpTypeVector:
+      case spv::Op::OpTypeArray:
+      case spv::Op::OpTypeMatrix:
+      case spv::Op::OpTypeRuntimeArray:
+      case spv::Op::OpTypeVector:
         next_type = type_inst->GetSingleWordInOperand(0);
         break;
-      case SpvOpTypeStruct: {
+      case spv::Op::OpTypeStruct: {
         // Struct types are special because (a) we may need to adjust the index
         // being used, if the struct type is the one from which we are removing
         // a member, and (b) the type encountered by following the current index
diff --git a/source/reduce/remove_unused_instruction_reduction_opportunity_finder.cpp b/source/reduce/remove_unused_instruction_reduction_opportunity_finder.cpp
index d7bb3a8..fbbeb34 100644
--- a/source/reduce/remove_unused_instruction_reduction_opportunity_finder.cpp
+++ b/source/reduce/remove_unused_instruction_reduction_opportunity_finder.cpp
@@ -103,8 +103,8 @@
           continue;
         }
         if (spvOpcodeIsBlockTerminator(inst.opcode()) ||
-            inst.opcode() == SpvOpSelectionMerge ||
-            inst.opcode() == SpvOpLoopMerge) {
+            inst.opcode() == spv::Op::OpSelectionMerge ||
+            inst.opcode() == spv::Op::OpLoopMerge) {
           // In this reduction pass we do not want to affect static
           // control flow.
           continue;
@@ -133,7 +133,7 @@
       &inst, [this](opt::Instruction* user, uint32_t use_index) -> bool {
         return (user->IsDecoration() &&
                 !IsIndependentlyRemovableDecoration(*user)) ||
-               (user->opcode() == SpvOpEntryPoint && use_index > 2);
+               (user->opcode() == spv::Op::OpEntryPoint && use_index > 2);
       });
 }
 
@@ -141,13 +141,13 @@
     IsIndependentlyRemovableDecoration(const opt::Instruction& inst) const {
   uint32_t decoration;
   switch (inst.opcode()) {
-    case SpvOpDecorate:
-    case SpvOpDecorateId:
-    case SpvOpDecorateString:
+    case spv::Op::OpDecorate:
+    case spv::Op::OpDecorateId:
+    case spv::Op::OpDecorateString:
       decoration = inst.GetSingleWordInOperand(1u);
       break;
-    case SpvOpMemberDecorate:
-    case SpvOpMemberDecorateString:
+    case spv::Op::OpMemberDecorate:
+    case spv::Op::OpMemberDecorateString:
       decoration = inst.GetSingleWordInOperand(2u);
       break;
     default:
@@ -160,12 +160,12 @@
   // not change the shader interface, will not make the shader invalid, will
   // actually be found in practice, etc.
 
-  switch (decoration) {
-    case SpvDecorationRelaxedPrecision:
-    case SpvDecorationNoSignedWrap:
-    case SpvDecorationNoContraction:
-    case SpvDecorationNoUnsignedWrap:
-    case SpvDecorationUserSemantic:
+  switch (spv::Decoration(decoration)) {
+    case spv::Decoration::RelaxedPrecision:
+    case spv::Decoration::NoSignedWrap:
+    case spv::Decoration::NoContraction:
+    case spv::Decoration::NoUnsignedWrap:
+    case spv::Decoration::UserSemantic:
       return true;
     default:
       return false;
diff --git a/source/reduce/remove_unused_struct_member_reduction_opportunity_finder.cpp b/source/reduce/remove_unused_struct_member_reduction_opportunity_finder.cpp
index cd0c4e4..db381e0 100644
--- a/source/reduce/remove_unused_struct_member_reduction_opportunity_finder.cpp
+++ b/source/reduce/remove_unused_struct_member_reduction_opportunity_finder.cpp
@@ -43,7 +43,7 @@
 
   // Consider every struct type in the module.
   for (auto& type_or_value : context->types_values()) {
-    if (type_or_value.opcode() != SpvOpTypeStruct) {
+    if (type_or_value.opcode() != spv::Op::OpTypeStruct) {
       continue;
     }
 
@@ -60,7 +60,7 @@
         &type_or_value,
         [&unused_members](opt::Instruction* user, uint32_t /*operand_index*/) {
           switch (user->opcode()) {
-            case SpvOpMemberName:
+            case spv::Op::OpMemberName:
               unused_members.erase(user->GetSingleWordInOperand(1));
               break;
             default:
@@ -91,8 +91,8 @@
           // The way the helper is invoked depends on whether the instruction
           // uses literal or id indices, and the offset into the instruction's
           // input operands from which index operands are provided.
-          case SpvOpAccessChain:
-          case SpvOpInBoundsAccessChain: {
+          case spv::Op::OpAccessChain:
+          case spv::Op::OpInBoundsAccessChain: {
             auto composite_type_id =
                 context->get_def_use_mgr()
                     ->GetDef(context->get_def_use_mgr()
@@ -102,8 +102,8 @@
             MarkAccessedMembersAsUsed(context, composite_type_id, 1, false,
                                       inst, &unused_member_to_structs);
           } break;
-          case SpvOpPtrAccessChain:
-          case SpvOpInBoundsPtrAccessChain: {
+          case spv::Op::OpPtrAccessChain:
+          case spv::Op::OpInBoundsPtrAccessChain: {
             auto composite_type_id =
                 context->get_def_use_mgr()
                     ->GetDef(context->get_def_use_mgr()
@@ -113,7 +113,7 @@
             MarkAccessedMembersAsUsed(context, composite_type_id, 2, false,
                                       inst, &unused_member_to_structs);
           } break;
-          case SpvOpCompositeExtract: {
+          case spv::Op::OpCompositeExtract: {
             auto composite_type_id =
                 context->get_def_use_mgr()
                     ->GetDef(inst.GetSingleWordInOperand(0))
@@ -121,7 +121,7 @@
             MarkAccessedMembersAsUsed(context, composite_type_id, 1, true, inst,
                                       &unused_member_to_structs);
           } break;
-          case SpvOpCompositeInsert: {
+          case spv::Op::OpCompositeInsert: {
             auto composite_type_id =
                 context->get_def_use_mgr()
                     ->GetDef(inst.GetSingleWordInOperand(1))
@@ -163,13 +163,13 @@
        i < composite_access_instruction.NumInOperands(); i++) {
     auto type_inst = context->get_def_use_mgr()->GetDef(next_type);
     switch (type_inst->opcode()) {
-      case SpvOpTypeArray:
-      case SpvOpTypeMatrix:
-      case SpvOpTypeRuntimeArray:
-      case SpvOpTypeVector:
+      case spv::Op::OpTypeArray:
+      case spv::Op::OpTypeMatrix:
+      case spv::Op::OpTypeRuntimeArray:
+      case spv::Op::OpTypeVector:
         next_type = type_inst->GetSingleWordInOperand(0);
         break;
-      case SpvOpTypeStruct: {
+      case spv::Op::OpTypeStruct: {
         uint32_t index_operand =
             composite_access_instruction.GetSingleWordInOperand(i);
         uint32_t member = literal_indices ? index_operand
diff --git a/source/reduce/simple_conditional_branch_to_branch_opportunity_finder.cpp b/source/reduce/simple_conditional_branch_to_branch_opportunity_finder.cpp
index d867c3a..9637f0f 100644
--- a/source/reduce/simple_conditional_branch_to_branch_opportunity_finder.cpp
+++ b/source/reduce/simple_conditional_branch_to_branch_opportunity_finder.cpp
@@ -29,15 +29,15 @@
   for (auto* function : GetTargetFunctions(context, target_function)) {
     // Consider every block in the function.
     for (auto& block : *function) {
-      // The terminator must be SpvOpBranchConditional.
+      // The terminator must be spv::Op::OpBranchConditional.
       opt::Instruction* terminator = block.terminator();
-      if (terminator->opcode() != SpvOpBranchConditional) {
+      if (terminator->opcode() != spv::Op::OpBranchConditional) {
         continue;
       }
       // It must not be a selection header, as these cannot be followed by
       // OpBranch.
       if (block.GetMergeInst() &&
-          block.GetMergeInst()->opcode() == SpvOpSelectionMerge) {
+          block.GetMergeInst()->opcode() == spv::Op::OpSelectionMerge) {
         continue;
       }
       // The conditional branch must be simplified.
diff --git a/source/reduce/simple_conditional_branch_to_branch_reduction_opportunity.cpp b/source/reduce/simple_conditional_branch_to_branch_reduction_opportunity.cpp
index a2be0c4..6d772b5 100644
--- a/source/reduce/simple_conditional_branch_to_branch_reduction_opportunity.cpp
+++ b/source/reduce/simple_conditional_branch_to_branch_reduction_opportunity.cpp
@@ -31,7 +31,8 @@
 }
 
 void SimpleConditionalBranchToBranchReductionOpportunity::Apply() {
-  assert(conditional_branch_instruction_->opcode() == SpvOpBranchConditional &&
+  assert(conditional_branch_instruction_->opcode() ==
+             spv::Op::OpBranchConditional &&
          "SimpleConditionalBranchToBranchReductionOpportunity: branch was not "
          "a conditional branch");
 
@@ -46,7 +47,7 @@
   // ->
   // OpBranch %block_id
 
-  conditional_branch_instruction_->SetOpcode(SpvOpBranch);
+  conditional_branch_instruction_->SetOpcode(spv::Op::OpBranch);
   conditional_branch_instruction_->ReplaceOperands(
       {{SPV_OPERAND_TYPE_ID,
         {conditional_branch_instruction_->GetSingleWordInOperand(
diff --git a/source/reduce/structured_construct_to_block_reduction_opportunity.cpp b/source/reduce/structured_construct_to_block_reduction_opportunity.cpp
index ed73841..cc5ffe3 100644
--- a/source/reduce/structured_construct_to_block_reduction_opportunity.cpp
+++ b/source/reduce/structured_construct_to_block_reduction_opportunity.cpp
@@ -55,7 +55,7 @@
 
   // The terminator for the header block is changed to be an unconditional
   // branch to the merge block.
-  header_block->terminator()->SetOpcode(SpvOpBranch);
+  header_block->terminator()->SetOpcode(spv::Op::OpBranch);
   header_block->terminator()->SetInOperands(
       {{SPV_OPERAND_TYPE_ID, {merge_block->id()}}});
 
diff --git a/source/reduce/structured_loop_to_selection_reduction_opportunity.cpp b/source/reduce/structured_loop_to_selection_reduction_opportunity.cpp
index 850af45..45b9528 100644
--- a/source/reduce/structured_loop_to_selection_reduction_opportunity.cpp
+++ b/source/reduce/structured_loop_to_selection_reduction_opportunity.cpp
@@ -129,12 +129,12 @@
   // Figure out which operands of the terminator need to be considered for
   // redirection.
   std::vector<uint32_t> operand_indices;
-  if (terminator->opcode() == SpvOpBranch) {
+  if (terminator->opcode() == spv::Op::OpBranch) {
     operand_indices = {0};
-  } else if (terminator->opcode() == SpvOpBranchConditional) {
+  } else if (terminator->opcode() == spv::Op::OpBranchConditional) {
     operand_indices = {1, 2};
   } else {
-    assert(terminator->opcode() == SpvOpSwitch);
+    assert(terminator->opcode() == spv::Op::OpSwitch);
     for (uint32_t label_index = 1; label_index < terminator->NumOperands();
          label_index += 2) {
       operand_indices.push_back(label_index);
@@ -179,18 +179,19 @@
   auto loop_merge_inst = loop_construct_header_->GetLoopMergeInst();
   auto const loop_merge_block_id =
       loop_merge_inst->GetSingleWordOperand(kMergeNodeIndex);
-  loop_merge_inst->SetOpcode(SpvOpSelectionMerge);
+  loop_merge_inst->SetOpcode(spv::Op::OpSelectionMerge);
   loop_merge_inst->ReplaceOperands(
       {{loop_merge_inst->GetOperand(kMergeNodeIndex).type,
         {loop_merge_block_id}},
-       {SPV_OPERAND_TYPE_SELECTION_CONTROL, {SpvSelectionControlMaskNone}}});
+       {SPV_OPERAND_TYPE_SELECTION_CONTROL,
+        {uint32_t(spv::SelectionControlMask::MaskNone)}}});
 
   // The loop header either finishes with OpBranch or OpBranchConditional.
   // The latter is fine for a selection.  In the former case we need to turn
   // it into OpBranchConditional.  We use "true" as the condition, and make
   // the "else" branch be the merge block.
   auto terminator = loop_construct_header_->terminator();
-  if (terminator->opcode() == SpvOpBranch) {
+  if (terminator->opcode() == spv::Op::OpBranch) {
     opt::analysis::Bool temp;
     const opt::analysis::Bool* bool_type =
         context_->get_type_mgr()->GetRegisteredType(&temp)->AsBool();
@@ -199,7 +200,7 @@
     auto true_const_result_id =
         const_mgr->GetDefiningInstruction(true_const)->result_id();
     auto original_branch_id = terminator->GetSingleWordOperand(0);
-    terminator->SetOpcode(SpvOpBranchConditional);
+    terminator->SetOpcode(spv::Op::OpBranchConditional);
     terminator->ReplaceOperands({{SPV_OPERAND_TYPE_ID, {true_const_result_id}},
                                  {SPV_OPERAND_TYPE_ID, {original_branch_id}},
                                  {SPV_OPERAND_TYPE_ID, {loop_merge_block_id}}});
@@ -215,7 +216,7 @@
   // Consider each instruction in the function.
   for (auto& block : *loop_construct_header_->GetParent()) {
     for (auto& def : block) {
-      if (def.opcode() == SpvOpVariable) {
+      if (def.opcode() == spv::Op::OpVariable) {
         // Variables are defined at the start of the function, and can be
         // accessed by all blocks, even by unreachable blocks that have no
         // dominators, so we do not need to worry about them.
@@ -233,11 +234,11 @@
         // access chain, in which case replace it with some (possibly fresh)
         // variable (as we cannot load from / store to OpUndef).
         if (!DefinitionSufficientlyDominatesUse(&def, use, index, block)) {
-          if (def.opcode() == SpvOpAccessChain) {
+          if (def.opcode() == spv::Op::OpAccessChain) {
             auto pointer_type =
                 context_->get_type_mgr()->GetType(def.type_id())->AsPointer();
             switch (pointer_type->storage_class()) {
-              case SpvStorageClassFunction:
+              case spv::StorageClass::Function:
                 use->SetOperand(
                     index, {FindOrCreateFunctionVariable(
                                context_, loop_construct_header_->GetParent(),
@@ -270,7 +271,7 @@
                                        opt::Instruction* use,
                                        uint32_t use_index,
                                        opt::BasicBlock& def_block) {
-  if (use->opcode() == SpvOpPhi) {
+  if (use->opcode() == spv::Op::OpPhi) {
     // A use in a phi doesn't need to be dominated by its definition, but the
     // associated parent block does need to be dominated by the definition.
     return context_->GetDominatorAnalysis(loop_construct_header_->GetParent())
diff --git a/source/table.h b/source/table.h
index 5adf04a..8097f13 100644
--- a/source/table.h
+++ b/source/table.h
@@ -21,9 +21,9 @@
 
 typedef struct spv_opcode_desc_t {
   const char* name;
-  const SpvOp opcode;
+  const spv::Op opcode;
   const uint32_t numCapabilities;
-  const SpvCapability* capabilities;
+  const spv::Capability* capabilities;
   // operandTypes[0..numTypes-1] describe logical operands for the instruction.
   // The operand types include result id and result-type id, followed by
   // the types of arguments.
@@ -48,7 +48,7 @@
   const char* name;
   const uint32_t value;
   const uint32_t numCapabilities;
-  const SpvCapability* capabilities;
+  const spv::Capability* capabilities;
   // A set of extensions that enable this feature. If empty then this operand
   // value is in core and its availability is subject to minVersion. The
   // assembler, binary parser, and disassembler ignore this rule, so you can
@@ -73,7 +73,7 @@
   const char* name;
   const uint32_t ext_inst;
   const uint32_t numCapabilities;
-  const SpvCapability* capabilities;
+  const spv::Capability* capabilities;
   const spv_operand_type_t operandTypes[16];  // TODO: Smaller/larger?
 } spv_ext_inst_desc_t;
 
diff --git a/source/text.cpp b/source/text.cpp
index 90f69c5..8f77d62 100644
--- a/source/text.cpp
+++ b/source/text.cpp
@@ -227,7 +227,8 @@
 
       // Set the extended instruction type.
       // The import set id is the 3rd operand of OpExtInst.
-      if (pInst->opcode == SpvOpExtInst && pInst->words.size() == 4) {
+      if (spv::Op(pInst->opcode) == spv::Op::OpExtInst &&
+          pInst->words.size() == 4) {
         auto ext_inst_type = context->getExtInstTypeForId(pInst->words[3]);
         if (ext_inst_type == SPV_EXT_INST_TYPE_NONE) {
           return context->diagnostic()
@@ -279,7 +280,7 @@
       // The assembler accepts the symbolic name for the opcode, but without
       // the "Op" prefix.  For example, "IAdd" is accepted.  The number
       // of the opcode is emitted.
-      SpvOp opcode;
+      spv::Op opcode;
       if (grammar.lookupSpecConstantOpcode(textValue, &opcode)) {
         return context->diagnostic() << "Invalid " << spvOperandTypeStr(type)
                                      << " '" << textValue << "'.";
@@ -327,8 +328,8 @@
       // The encoding for OpConstant, OpSpecConstant and OpSwitch all
       // depend on either their own result-id or the result-id of
       // one of their parameters.
-      if (SpvOpConstant == pInst->opcode ||
-          SpvOpSpecConstant == pInst->opcode) {
+      if (spv::Op::OpConstant == pInst->opcode ||
+          spv::Op::OpSpecConstant == pInst->opcode) {
         // The type of the literal is determined by the type Id of the
         // instruction.
         expected_type =
@@ -344,7 +345,7 @@
                  << "Type for " << opcode_name
                  << " must be a scalar floating point or integer type";
         }
-      } else if (pInst->opcode == SpvOpSwitch) {
+      } else if (pInst->opcode == spv::Op::OpSwitch) {
         // The type of the literal is the same as the type of the selector.
         expected_type = context->getTypeOfValueInstruction(pInst->words[1]);
         if (!spvtools::isScalarIntegral(expected_type)) {
@@ -375,7 +376,7 @@
       }
 
       // NOTE: Special case for extended instruction library import
-      if (SpvOpExtInstImport == pInst->opcode) {
+      if (spv::Op::OpExtInstImport == pInst->opcode) {
         const spv_ext_inst_type_t ext_inst_type =
             spvExtInstImportTypeGet(literal.str.c_str());
         if (SPV_EXT_INST_TYPE_NONE == ext_inst_type) {
@@ -688,7 +689,7 @@
                        uint32_t* header) {
   if (!header) return SPV_ERROR_INVALID_BINARY;
 
-  header[SPV_INDEX_MAGIC_NUMBER] = SpvMagicNumber;
+  header[SPV_INDEX_MAGIC_NUMBER] = spv::MagicNumber;
   header[SPV_INDEX_VERSION_NUMBER] = spvVersionForTargetEnv(env);
   header[SPV_INDEX_GENERATOR_NUMBER] =
       SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS_ASSEMBLER, kAssemblerVersion);
@@ -722,7 +723,7 @@
     // being parsed. A malformed input might feature such an operand *before*
     // the opcode is known. To guard against accessing an uninitialized opcode,
     // the instruction's opcode is initialized to a default value.
-    inst.opcode = SpvOpMax;
+    inst.opcode = spv::Op::Max;
 
     if (spvTextEncodeOpcode(grammar, &context, &inst)) {
       return SPV_ERROR_INVALID_TEXT;
diff --git a/source/text_handler.cpp b/source/text_handler.cpp
index 15c1741..35c4b83 100644
--- a/source/text_handler.cpp
+++ b/source/text_handler.cpp
@@ -323,12 +323,12 @@
                         << " has already been used to generate a type";
   }
 
-  if (pInst->opcode == SpvOpTypeInt) {
+  if (pInst->opcode == spv::Op::OpTypeInt) {
     if (pInst->words.size() != 4)
       return diagnostic() << "Invalid OpTypeInt instruction";
     types_[value] = {pInst->words[2], pInst->words[3] != 0,
                      IdTypeClass::kScalarIntegerType};
-  } else if (pInst->opcode == SpvOpTypeFloat) {
+  } else if (pInst->opcode == spv::Op::OpTypeFloat) {
     if (pInst->words.size() != 3)
       return diagnostic() << "Invalid OpTypeFloat instruction";
     types_[value] = {pInst->words[2], false, IdTypeClass::kScalarFloatType};
diff --git a/source/val/construct.cpp b/source/val/construct.cpp
index 52e61d5..1b6a54f 100644
--- a/source/val/construct.cpp
+++ b/source/val/construct.cpp
@@ -164,8 +164,8 @@
     //  ii. The immediate dominator of |block|.
     auto NextBlock = [](const BasicBlock* block) -> const BasicBlock* {
       for (auto& use : block->label()->uses()) {
-        if ((use.first->opcode() == SpvOpLoopMerge ||
-             use.first->opcode() == SpvOpSelectionMerge) &&
+        if ((use.first->opcode() == spv::Op::OpLoopMerge ||
+             use.first->opcode() == spv::Op::OpSelectionMerge) &&
             use.second == 1 &&
             use.first->block()->structurally_dominates(*block)) {
           return use.first->block();
@@ -181,10 +181,10 @@
       auto terminator = block->terminator();
       auto index = terminator - &_.ordered_instructions()[0];
       auto merge_inst = &_.ordered_instructions()[index - 1];
-      if (merge_inst->opcode() == SpvOpLoopMerge ||
-          (header->terminator()->opcode() != SpvOpSwitch &&
-           merge_inst->opcode() == SpvOpSelectionMerge &&
-           terminator->opcode() == SpvOpSwitch)) {
+      if (merge_inst->opcode() == spv::Op::OpLoopMerge ||
+          (header->terminator()->opcode() != spv::Op::OpSwitch &&
+           merge_inst->opcode() == spv::Op::OpSelectionMerge &&
+           terminator->opcode() == spv::Op::OpSwitch)) {
         auto merge_target = merge_inst->GetOperandAs<uint32_t>(0u);
         auto merge_block = merge_inst->function()->GetBlock(merge_target).first;
         if (merge_block->structurally_dominates(*header)) {
@@ -192,22 +192,22 @@
           continue;
         }
 
-        if ((!seen_switch || merge_inst->opcode() == SpvOpLoopMerge) &&
+        if ((!seen_switch || merge_inst->opcode() == spv::Op::OpLoopMerge) &&
             dest->id() == merge_target) {
           return true;
-        } else if (merge_inst->opcode() == SpvOpLoopMerge) {
+        } else if (merge_inst->opcode() == spv::Op::OpLoopMerge) {
           auto continue_target = merge_inst->GetOperandAs<uint32_t>(1u);
           if (dest->id() == continue_target) {
             return true;
           }
         }
 
-        if (terminator->opcode() == SpvOpSwitch) {
+        if (terminator->opcode() == spv::Op::OpSwitch) {
           seen_switch = true;
         }
 
         // Hit an enclosing loop and didn't break or continue.
-        if (merge_inst->opcode() == SpvOpLoopMerge) return false;
+        if (merge_inst->opcode() == spv::Op::OpLoopMerge) return false;
       }
 
       block = NextBlock(block);
diff --git a/source/val/decoration.h b/source/val/decoration.h
index 4f53f20..384cc57 100644
--- a/source/val/decoration.h
+++ b/source/val/decoration.h
@@ -39,33 +39,33 @@
 //
 // Example 1: Decoration for an object<id> with no parameters:
 // OpDecorate %obj Flat
-//            dec_type_ = SpvDecorationFlat
+//            dec_type_ = spv::Decoration::Flat
 //              params_ = empty vector
 // struct_member_index_ = kInvalidMember
 //
 // Example 2: Decoration for an object<id> with two parameters:
 // OpDecorate %obj LinkageAttributes "link" Import
-//            dec_type_ = SpvDecorationLinkageAttributes
+//            dec_type_ = spv::Decoration::LinkageAttributes
 //              params_ = vector { link, Import }
 // struct_member_index_ = kInvalidMember
 //
 // Example 3: Decoration for a member of a structure with one parameter:
 // OpMemberDecorate %struct 2 Offset 2
-//            dec_type_ = SpvDecorationOffset
+//            dec_type_ = spv::Decoration::Offset
 //              params_ = vector { 2 }
 // struct_member_index_ = 2
 //
 class Decoration {
  public:
   enum { kInvalidMember = -1 };
-  Decoration(SpvDecoration t,
+  Decoration(spv::Decoration t,
              const std::vector<uint32_t>& parameters = std::vector<uint32_t>(),
              uint32_t member_index = kInvalidMember)
       : dec_type_(t), params_(parameters), struct_member_index_(member_index) {}
 
   void set_struct_member_index(uint32_t index) { struct_member_index_ = index; }
   int struct_member_index() const { return struct_member_index_; }
-  SpvDecoration dec_type() const { return dec_type_; }
+  spv::Decoration dec_type() const { return dec_type_; }
   std::vector<uint32_t>& params() { return params_; }
   const std::vector<uint32_t>& params() const { return params_; }
 
@@ -84,7 +84,7 @@
   }
 
  private:
-  SpvDecoration dec_type_;
+  spv::Decoration dec_type_;
   std::vector<uint32_t> params_;
 
   // If the decoration applies to a member of a structure type, then the index
diff --git a/source/val/function.cpp b/source/val/function.cpp
index fc7ccd0..8b4423a 100644
--- a/source/val/function.cpp
+++ b/source/val/function.cpp
@@ -33,7 +33,7 @@
 static const uint32_t kInvalidId = 0x400000;
 
 Function::Function(uint32_t function_id, uint32_t result_type_id,
-                   SpvFunctionControlMask function_control,
+                   spv::FunctionControlMask function_control,
                    uint32_t function_type_id)
     : id_(function_id),
       function_type_id_(function_type_id),
@@ -371,10 +371,10 @@
   return block_depth_[bb];
 }
 
-void Function::RegisterExecutionModelLimitation(SpvExecutionModel model,
+void Function::RegisterExecutionModelLimitation(spv::ExecutionModel model,
                                                 const std::string& message) {
   execution_model_limitations_.push_back(
-      [model, message](SpvExecutionModel in_model, std::string* out_message) {
+      [model, message](spv::ExecutionModel in_model, std::string* out_message) {
         if (model != in_model) {
           if (out_message) {
             *out_message = message;
@@ -385,7 +385,7 @@
       });
 }
 
-bool Function::IsCompatibleWithExecutionModel(SpvExecutionModel model,
+bool Function::IsCompatibleWithExecutionModel(spv::ExecutionModel model,
                                               std::string* reason) const {
   bool return_value = true;
   std::stringstream ss_reason;
diff --git a/source/val/function.h b/source/val/function.h
index 126b1dc..4811794 100644
--- a/source/val/function.h
+++ b/source/val/function.h
@@ -55,7 +55,8 @@
 class Function {
  public:
   Function(uint32_t id, uint32_t result_type_id,
-           SpvFunctionControlMask function_control, uint32_t function_type_id);
+           spv::FunctionControlMask function_control,
+           uint32_t function_type_id);
 
   /// Registers a function parameter in the current function
   /// @return Returns SPV_SUCCESS if the call was successful
@@ -80,7 +81,8 @@
   ///
   /// @return Returns SPV_SUCCESS if the call was successful
   spv_result_t RegisterBlockVariable(uint32_t type_id, uint32_t id,
-                                     SpvStorageClass storage, uint32_t init_id);
+                                     spv::StorageClass storage,
+                                     uint32_t init_id);
 
   /// Registers a loop merge construct in the function
   ///
@@ -205,12 +207,12 @@
 
   /// Registers execution model limitation such as "Feature X is only available
   /// with Execution Model Y".
-  void RegisterExecutionModelLimitation(SpvExecutionModel model,
+  void RegisterExecutionModelLimitation(spv::ExecutionModel model,
                                         const std::string& message);
 
   /// Registers execution model limitation with an |is_compatible| functor.
   void RegisterExecutionModelLimitation(
-      std::function<bool(SpvExecutionModel, std::string*)> is_compatible) {
+      std::function<bool(spv::ExecutionModel, std::string*)> is_compatible) {
     execution_model_limitations_.push_back(is_compatible);
   }
 
@@ -227,7 +229,7 @@
   /// Returns true if the given execution model passes the limitations stored in
   /// execution_model_limitations_. Returns false otherwise and fills optional
   /// |reason| parameter.
-  bool IsCompatibleWithExecutionModel(SpvExecutionModel model,
+  bool IsCompatibleWithExecutionModel(spv::ExecutionModel model,
                                       std::string* reason = nullptr) const;
 
   // Inserts id to the set of functions called from this function.
@@ -286,7 +288,7 @@
   uint32_t result_type_id_;
 
   /// The control fo the function
-  SpvFunctionControlMask function_control_;
+  spv::FunctionControlMask function_control_;
 
   /// The type of declaration of each function
   FunctionDecl declaration_type_;
@@ -381,7 +383,7 @@
   /// function. The functor stored in the list return true if execution model
   /// is compatible, false otherwise. If the functor returns false, it can also
   /// optionally fill the string parameter with the reason for incompatibility.
-  std::list<std::function<bool(SpvExecutionModel, std::string*)>>
+  std::list<std::function<bool(spv::ExecutionModel, std::string*)>>
       execution_model_limitations_;
 
   /// Stores limitations imposed by instructions used within the function.
diff --git a/source/val/instruction.h b/source/val/instruction.h
index 6d1f9f4..c524bd3 100644
--- a/source/val/instruction.h
+++ b/source/val/instruction.h
@@ -42,7 +42,7 @@
 
   uint32_t id() const { return inst_.result_id; }
   uint32_t type_id() const { return inst_.type_id; }
-  SpvOp opcode() const { return static_cast<SpvOp>(inst_.opcode); }
+  spv::Op opcode() const { return static_cast<spv::Op>(inst_.opcode); }
 
   /// Returns the Function where the instruction was defined. nullptr if it was
   /// defined outside of a Function
@@ -87,13 +87,13 @@
   }
 
   bool IsNonSemantic() const {
-    return opcode() == SpvOp::SpvOpExtInst &&
+    return opcode() == spv::Op::OpExtInst &&
            spvExtInstIsNonSemantic(inst_.ext_inst_type);
   }
 
   /// True if this is an OpExtInst for debug info extension.
   bool IsDebugInfo() const {
-    return opcode() == SpvOp::SpvOpExtInst &&
+    return opcode() == spv::Op::OpExtInst &&
            spvExtInstIsDebugInfo(inst_.ext_inst_type);
   }
 
diff --git a/source/val/validate.cpp b/source/val/validate.cpp
index efb9225..10f3d43 100644
--- a/source/val/validate.cpp
+++ b/source/val/validate.cpp
@@ -66,15 +66,15 @@
 
 // Parses the beginning of the module searching for OpExtension instructions.
 // Registers extensions if recognized. Returns SPV_REQUESTED_TERMINATION
-// once an instruction which is not SpvOpCapability and SpvOpExtension is
-// encountered. According to the SPIR-V spec extensions are declared after
-// capabilities and before everything else.
+// once an instruction which is not spv::Op::OpCapability and
+// spv::Op::OpExtension is encountered. According to the SPIR-V spec extensions
+// are declared after capabilities and before everything else.
 spv_result_t ProcessExtensions(void* user_data,
                                const spv_parsed_instruction_t* inst) {
-  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
-  if (opcode == SpvOpCapability) return SPV_SUCCESS;
+  const spv::Op opcode = static_cast<spv::Op>(inst->opcode);
+  if (opcode == spv::Op::OpCapability) return SPV_SUCCESS;
 
-  if (opcode == SpvOpExtension) {
+  if (opcode == spv::Op::OpExtension) {
     ValidationState_t& _ = *(reinterpret_cast<ValidationState_t*>(user_data));
     RegisterExtension(_, inst);
     return SPV_SUCCESS;
@@ -123,7 +123,7 @@
   _.ComputeFunctionToEntryPointMapping();
   _.ComputeRecursiveEntryPoints();
 
-  if (_.entry_points().empty() && !_.HasCapability(SpvCapabilityLinkage)) {
+  if (_.entry_points().empty() && !_.HasCapability(spv::Capability::Linkage)) {
     return _.diag(SPV_ERROR_INVALID_BINARY, nullptr)
            << "No OpEntryPoint instruction was found. This is only allowed if "
               "the Linkage capability is being used.";
@@ -218,9 +218,9 @@
       // able to, briefly, de-const the instruction.
       Instruction* inst = const_cast<Instruction*>(&instruction);
 
-      if (inst->opcode() == SpvOpEntryPoint) {
+      if (inst->opcode() == spv::Op::OpEntryPoint) {
         const auto entry_point = inst->GetOperandAs<uint32_t>(1);
-        const auto execution_model = inst->GetOperandAs<SpvExecutionModel>(0);
+        const auto execution_model = inst->GetOperandAs<spv::ExecutionModel>(0);
         const std::string desc_name = inst->GetOperandAs<std::string>(2);
 
         ValidationState_t::EntryPointDescription desc;
@@ -236,7 +236,7 @@
         if (visited_entry_points.size() > 0) {
           for (const Instruction* check_inst : visited_entry_points) {
             const auto check_execution_model =
-                check_inst->GetOperandAs<SpvExecutionModel>(0);
+                check_inst->GetOperandAs<spv::ExecutionModel>(0);
             const std::string check_name =
                 check_inst->GetOperandAs<std::string>(2);
 
@@ -250,12 +250,12 @@
         }
         visited_entry_points.push_back(inst);
 
-        has_mask_task_nv |= (execution_model == SpvExecutionModelTaskNV ||
-                             execution_model == SpvExecutionModelMeshNV);
-        has_mask_task_ext |= (execution_model == SpvExecutionModelTaskEXT ||
-                              execution_model == SpvExecutionModelMeshEXT);
+        has_mask_task_nv |= (execution_model == spv::ExecutionModel::TaskNV ||
+                             execution_model == spv::ExecutionModel::MeshNV);
+        has_mask_task_ext |= (execution_model == spv::ExecutionModel::TaskEXT ||
+                              execution_model == spv::ExecutionModel::MeshEXT);
       }
-      if (inst->opcode() == SpvOpFunctionCall) {
+      if (inst->opcode() == spv::Op::OpFunctionCall) {
         if (!vstate->in_function_body()) {
           return vstate->diag(SPV_ERROR_INVALID_LAYOUT, &instruction)
                  << "A FunctionCall must happen within a function body.";
@@ -286,7 +286,7 @@
     {
       Instruction* inst = const_cast<Instruction*>(&instruction);
       vstate->RegisterInstruction(inst);
-      if (inst->opcode() == SpvOpTypeForwardPointer) {
+      if (inst->opcode() == spv::Op::OpTypeForwardPointer) {
         vstate->RegisterForwardPointer(inst->GetOperandAs<uint32_t>(0));
       }
     }
@@ -300,7 +300,7 @@
     return vstate->diag(SPV_ERROR_INVALID_LAYOUT, nullptr)
            << "Missing OpFunctionEnd at end of module.";
 
-  if (vstate->HasCapability(SpvCapabilityBindlessTextureNV) &&
+  if (vstate->HasCapability(spv::Capability::BindlessTextureNV) &&
       !vstate->has_samplerimage_variable_address_mode_specified())
     return vstate->diag(SPV_ERROR_INVALID_LAYOUT, nullptr)
            << "Missing required OpSamplerImageAddressingModeNV instruction.";
@@ -368,8 +368,9 @@
     if (auto error = MeshShadingPass(*vstate, &instruction)) return error;
   }
 
-  // Validate the preconditions involving adjacent instructions. e.g. SpvOpPhi
-  // must only be preceded by SpvOpLabel, SpvOpPhi, or SpvOpLine.
+  // Validate the preconditions involving adjacent instructions. e.g.
+  // spv::Op::OpPhi must only be preceded by spv::Op::OpLabel, spv::Op::OpPhi,
+  // or spv::Op::OpLine.
   if (auto error = ValidateAdjacency(*vstate)) return error;
 
   if (auto error = ValidateEntryPoints(*vstate)) return error;
diff --git a/source/val/validate.h b/source/val/validate.h
index 4b953ba..fd84b06 100644
--- a/source/val/validate.h
+++ b/source/val/validate.h
@@ -69,8 +69,8 @@
 /// instructions.
 ///
 /// This function will iterate over all instructions and check for any required
-/// predecessor and/or successor instructions. e.g. SpvOpPhi must only be
-/// preceded by SpvOpLabel, SpvOpPhi, or SpvOpLine.
+/// predecessor and/or successor instructions. e.g. spv::Op::OpPhi must only be
+/// preceded by spv::Op::OpLabel, spv::Op::OpPhi, or spv::Op::OpLine.
 ///
 /// @param[in] _ the validation state of the module
 ///
diff --git a/source/val/validate_adjacency.cpp b/source/val/validate_adjacency.cpp
index 8e6c373..50c2e92 100644
--- a/source/val/validate_adjacency.cpp
+++ b/source/val/validate_adjacency.cpp
@@ -46,15 +46,15 @@
   for (size_t i = 0; i < instructions.size(); ++i) {
     const auto& inst = instructions[i];
     switch (inst.opcode()) {
-      case SpvOpFunction:
-      case SpvOpFunctionParameter:
+      case spv::Op::OpFunction:
+      case spv::Op::OpFunctionParameter:
         adjacency_status = IN_NEW_FUNCTION;
         break;
-      case SpvOpLabel:
+      case spv::Op::OpLabel:
         adjacency_status =
             adjacency_status == IN_NEW_FUNCTION ? IN_ENTRY_BLOCK : PHI_VALID;
         break;
-      case SpvOpExtInst:
+      case spv::Op::OpExtInst:
         // If it is a debug info instruction, we do not change the status to
         // allow debug info instructions before OpVariable in a function.
         // TODO(https://gitlab.khronos.org/spirv/SPIR-V/issues/533): We need
@@ -67,7 +67,7 @@
           adjacency_status = PHI_AND_VAR_INVALID;
         }
         break;
-      case SpvOpPhi:
+      case spv::Op::OpPhi:
         if (adjacency_status != PHI_VALID) {
           return _.diag(SPV_ERROR_INVALID_DATA, &inst)
                  << "OpPhi must appear within a non-entry block before all "
@@ -75,15 +75,15 @@
                  << "(except for OpLine, which can be mixed with OpPhi).";
         }
         break;
-      case SpvOpLine:
-      case SpvOpNoLine:
+      case spv::Op::OpLine:
+      case spv::Op::OpNoLine:
         break;
-      case SpvOpLoopMerge:
+      case spv::Op::OpLoopMerge:
         adjacency_status = PHI_AND_VAR_INVALID;
         if (i != (instructions.size() - 1)) {
           switch (instructions[i + 1].opcode()) {
-            case SpvOpBranch:
-            case SpvOpBranchConditional:
+            case spv::Op::OpBranch:
+            case spv::Op::OpBranchConditional:
               break;
             default:
               return _.diag(SPV_ERROR_INVALID_DATA, &inst)
@@ -94,12 +94,12 @@
           }
         }
         break;
-      case SpvOpSelectionMerge:
+      case spv::Op::OpSelectionMerge:
         adjacency_status = PHI_AND_VAR_INVALID;
         if (i != (instructions.size() - 1)) {
           switch (instructions[i + 1].opcode()) {
-            case SpvOpBranchConditional:
-            case SpvOpSwitch:
+            case spv::Op::OpBranchConditional:
+            case spv::Op::OpSwitch:
               break;
             default:
               return _.diag(SPV_ERROR_INVALID_DATA, &inst)
@@ -110,8 +110,9 @@
           }
         }
         break;
-      case SpvOpVariable:
-        if (inst.GetOperandAs<SpvStorageClass>(2) == SpvStorageClassFunction &&
+      case spv::Op::OpVariable:
+        if (inst.GetOperandAs<spv::StorageClass>(2) ==
+                spv::StorageClass::Function &&
             adjacency_status != IN_ENTRY_BLOCK) {
           return _.diag(SPV_ERROR_INVALID_DATA, &inst)
                  << "All OpVariable instructions in a function must be the "
diff --git a/source/val/validate_annotation.cpp b/source/val/validate_annotation.cpp
index 21f999b..2d13456 100644
--- a/source/val/validate_annotation.cpp
+++ b/source/val/validate_annotation.cpp
@@ -24,12 +24,12 @@
 
 // Returns true if the decoration takes ID parameters.
 // TODO(dneto): This can be generated from the grammar.
-bool DecorationTakesIdParameters(SpvDecoration type) {
+bool DecorationTakesIdParameters(spv::Decoration type) {
   switch (type) {
-    case SpvDecorationUniformId:
-    case SpvDecorationAlignmentId:
-    case SpvDecorationMaxByteOffsetId:
-    case SpvDecorationHlslCounterBufferGOOGLE:
+    case spv::Decoration::UniformId:
+    case spv::Decoration::AlignmentId:
+    case spv::Decoration::MaxByteOffsetId:
+    case spv::Decoration::HlslCounterBufferGOOGLE:
       return true;
     default:
       break;
@@ -37,14 +37,14 @@
   return false;
 }
 
-bool IsMemberDecorationOnly(SpvDecoration dec) {
+bool IsMemberDecorationOnly(spv::Decoration dec) {
   switch (dec) {
-    case SpvDecorationRowMajor:
-    case SpvDecorationColMajor:
-    case SpvDecorationMatrixStride:
+    case spv::Decoration::RowMajor:
+    case spv::Decoration::ColMajor:
+    case spv::Decoration::MatrixStride:
       // SPIR-V spec bug? Offset is generated on variables when dealing with
       // transform feedback.
-      // case SpvDecorationOffset:
+      // case spv::Decoration::Offset:
       return true;
     default:
       break;
@@ -52,42 +52,42 @@
   return false;
 }
 
-bool IsNotMemberDecoration(SpvDecoration dec) {
+bool IsNotMemberDecoration(spv::Decoration dec) {
   switch (dec) {
-    case SpvDecorationSpecId:
-    case SpvDecorationBlock:
-    case SpvDecorationBufferBlock:
-    case SpvDecorationArrayStride:
-    case SpvDecorationGLSLShared:
-    case SpvDecorationGLSLPacked:
-    case SpvDecorationCPacked:
+    case spv::Decoration::SpecId:
+    case spv::Decoration::Block:
+    case spv::Decoration::BufferBlock:
+    case spv::Decoration::ArrayStride:
+    case spv::Decoration::GLSLShared:
+    case spv::Decoration::GLSLPacked:
+    case spv::Decoration::CPacked:
     // TODO: https://github.com/KhronosGroup/glslang/issues/703:
     // glslang applies Restrict to structure members.
-    // case SpvDecorationRestrict:
-    case SpvDecorationAliased:
-    case SpvDecorationConstant:
-    case SpvDecorationUniform:
-    case SpvDecorationUniformId:
-    case SpvDecorationSaturatedConversion:
-    case SpvDecorationIndex:
-    case SpvDecorationBinding:
-    case SpvDecorationDescriptorSet:
-    case SpvDecorationFuncParamAttr:
-    case SpvDecorationFPRoundingMode:
-    case SpvDecorationFPFastMathMode:
-    case SpvDecorationLinkageAttributes:
-    case SpvDecorationNoContraction:
-    case SpvDecorationInputAttachmentIndex:
-    case SpvDecorationAlignment:
-    case SpvDecorationMaxByteOffset:
-    case SpvDecorationAlignmentId:
-    case SpvDecorationMaxByteOffsetId:
-    case SpvDecorationNoSignedWrap:
-    case SpvDecorationNoUnsignedWrap:
-    case SpvDecorationNonUniform:
-    case SpvDecorationRestrictPointer:
-    case SpvDecorationAliasedPointer:
-    case SpvDecorationCounterBuffer:
+    // case spv::Decoration::Restrict:
+    case spv::Decoration::Aliased:
+    case spv::Decoration::Constant:
+    case spv::Decoration::Uniform:
+    case spv::Decoration::UniformId:
+    case spv::Decoration::SaturatedConversion:
+    case spv::Decoration::Index:
+    case spv::Decoration::Binding:
+    case spv::Decoration::DescriptorSet:
+    case spv::Decoration::FuncParamAttr:
+    case spv::Decoration::FPRoundingMode:
+    case spv::Decoration::FPFastMathMode:
+    case spv::Decoration::LinkageAttributes:
+    case spv::Decoration::NoContraction:
+    case spv::Decoration::InputAttachmentIndex:
+    case spv::Decoration::Alignment:
+    case spv::Decoration::MaxByteOffset:
+    case spv::Decoration::AlignmentId:
+    case spv::Decoration::MaxByteOffsetId:
+    case spv::Decoration::NoSignedWrap:
+    case spv::Decoration::NoUnsignedWrap:
+    case spv::Decoration::NonUniform:
+    case spv::Decoration::RestrictPointer:
+    case spv::Decoration::AliasedPointer:
+    case spv::Decoration::CounterBuffer:
       return true;
     default:
       break;
@@ -95,7 +95,7 @@
   return false;
 }
 
-spv_result_t ValidateDecorationTarget(ValidationState_t& _, SpvDecoration dec,
+spv_result_t ValidateDecorationTarget(ValidationState_t& _, spv::Decoration dec,
                                       const Instruction* inst,
                                       const Instruction* target) {
   auto fail = [&_, dec, inst, target](uint32_t vuid) -> DiagnosticStream {
@@ -106,76 +106,76 @@
     return ds;
   };
   switch (dec) {
-    case SpvDecorationSpecId:
+    case spv::Decoration::SpecId:
       if (!spvOpcodeIsScalarSpecConstant(target->opcode())) {
         return fail(0) << "must be a scalar specialization constant";
       }
       break;
-    case SpvDecorationBlock:
-    case SpvDecorationBufferBlock:
-    case SpvDecorationGLSLShared:
-    case SpvDecorationGLSLPacked:
-    case SpvDecorationCPacked:
-      if (target->opcode() != SpvOpTypeStruct) {
+    case spv::Decoration::Block:
+    case spv::Decoration::BufferBlock:
+    case spv::Decoration::GLSLShared:
+    case spv::Decoration::GLSLPacked:
+    case spv::Decoration::CPacked:
+      if (target->opcode() != spv::Op::OpTypeStruct) {
         return fail(0) << "must be a structure type";
       }
       break;
-    case SpvDecorationArrayStride:
-      if (target->opcode() != SpvOpTypeArray &&
-          target->opcode() != SpvOpTypeRuntimeArray &&
-          target->opcode() != SpvOpTypePointer) {
+    case spv::Decoration::ArrayStride:
+      if (target->opcode() != spv::Op::OpTypeArray &&
+          target->opcode() != spv::Op::OpTypeRuntimeArray &&
+          target->opcode() != spv::Op::OpTypePointer) {
         return fail(0) << "must be an array or pointer type";
       }
       break;
-    case SpvDecorationBuiltIn:
-      if (target->opcode() != SpvOpVariable &&
+    case spv::Decoration::BuiltIn:
+      if (target->opcode() != spv::Op::OpVariable &&
           !spvOpcodeIsConstant(target->opcode())) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "BuiltIns can only target variables, structure members or "
                   "constants";
       }
-      if (_.HasCapability(SpvCapabilityShader) &&
-          inst->GetOperandAs<SpvBuiltIn>(2) == SpvBuiltInWorkgroupSize) {
+      if (_.HasCapability(spv::Capability::Shader) &&
+          inst->GetOperandAs<spv::BuiltIn>(2) == spv::BuiltIn::WorkgroupSize) {
         if (!spvOpcodeIsConstant(target->opcode())) {
           return fail(0) << "must be a constant for WorkgroupSize";
         }
-      } else if (target->opcode() != SpvOpVariable) {
+      } else if (target->opcode() != spv::Op::OpVariable) {
         return fail(0) << "must be a variable";
       }
       break;
-    case SpvDecorationNoPerspective:
-    case SpvDecorationFlat:
-    case SpvDecorationPatch:
-    case SpvDecorationCentroid:
-    case SpvDecorationSample:
-    case SpvDecorationRestrict:
-    case SpvDecorationAliased:
-    case SpvDecorationVolatile:
-    case SpvDecorationCoherent:
-    case SpvDecorationNonWritable:
-    case SpvDecorationNonReadable:
-    case SpvDecorationXfbBuffer:
-    case SpvDecorationXfbStride:
-    case SpvDecorationComponent:
-    case SpvDecorationStream:
-    case SpvDecorationRestrictPointer:
-    case SpvDecorationAliasedPointer:
-      if (target->opcode() != SpvOpVariable &&
-          target->opcode() != SpvOpFunctionParameter) {
+    case spv::Decoration::NoPerspective:
+    case spv::Decoration::Flat:
+    case spv::Decoration::Patch:
+    case spv::Decoration::Centroid:
+    case spv::Decoration::Sample:
+    case spv::Decoration::Restrict:
+    case spv::Decoration::Aliased:
+    case spv::Decoration::Volatile:
+    case spv::Decoration::Coherent:
+    case spv::Decoration::NonWritable:
+    case spv::Decoration::NonReadable:
+    case spv::Decoration::XfbBuffer:
+    case spv::Decoration::XfbStride:
+    case spv::Decoration::Component:
+    case spv::Decoration::Stream:
+    case spv::Decoration::RestrictPointer:
+    case spv::Decoration::AliasedPointer:
+      if (target->opcode() != spv::Op::OpVariable &&
+          target->opcode() != spv::Op::OpFunctionParameter) {
         return fail(0) << "must be a memory object declaration";
       }
-      if (_.GetIdOpcode(target->type_id()) != SpvOpTypePointer) {
+      if (_.GetIdOpcode(target->type_id()) != spv::Op::OpTypePointer) {
         return fail(0) << "must be a pointer type";
       }
       break;
-    case SpvDecorationInvariant:
-    case SpvDecorationConstant:
-    case SpvDecorationLocation:
-    case SpvDecorationIndex:
-    case SpvDecorationBinding:
-    case SpvDecorationDescriptorSet:
-    case SpvDecorationInputAttachmentIndex:
-      if (target->opcode() != SpvOpVariable) {
+    case spv::Decoration::Invariant:
+    case spv::Decoration::Constant:
+    case spv::Decoration::Location:
+    case spv::Decoration::Index:
+    case spv::Decoration::Binding:
+    case spv::Decoration::DescriptorSet:
+    case spv::Decoration::InputAttachmentIndex:
+      if (target->opcode() != spv::Op::OpVariable) {
         return fail(0) << "must be a variable";
       }
       break;
@@ -185,57 +185,57 @@
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
     // The following were all checked as pointer types above.
-    SpvStorageClass sc = SpvStorageClassUniform;
+    spv::StorageClass sc = spv::StorageClass::Uniform;
     const auto type = _.FindDef(target->type_id());
     if (type && type->operands().size() > 2) {
-      sc = type->GetOperandAs<SpvStorageClass>(1);
+      sc = type->GetOperandAs<spv::StorageClass>(1);
     }
     switch (dec) {
-      case SpvDecorationLocation:
-      case SpvDecorationComponent:
+      case spv::Decoration::Location:
+      case spv::Decoration::Component:
         // Location is used for input, output and ray tracing stages.
-        if (sc != SpvStorageClassInput && sc != SpvStorageClassOutput &&
-            sc != SpvStorageClassRayPayloadKHR &&
-            sc != SpvStorageClassIncomingRayPayloadKHR &&
-            sc != SpvStorageClassHitAttributeKHR &&
-            sc != SpvStorageClassCallableDataKHR &&
-            sc != SpvStorageClassIncomingCallableDataKHR &&
-            sc != SpvStorageClassShaderRecordBufferKHR) {
+        if (sc != spv::StorageClass::Input && sc != spv::StorageClass::Output &&
+            sc != spv::StorageClass::RayPayloadKHR &&
+            sc != spv::StorageClass::IncomingRayPayloadKHR &&
+            sc != spv::StorageClass::HitAttributeKHR &&
+            sc != spv::StorageClass::CallableDataKHR &&
+            sc != spv::StorageClass::IncomingCallableDataKHR &&
+            sc != spv::StorageClass::ShaderRecordBufferKHR) {
           return _.diag(SPV_ERROR_INVALID_ID, target)
                  << _.VkErrorID(6672) << _.SpvDecorationString(dec)
                  << " decoration must not be applied to this storage class";
         }
         break;
-      case SpvDecorationIndex:
+      case spv::Decoration::Index:
         // Langauge from SPIR-V definition of Index
-        if (sc != SpvStorageClassOutput) {
+        if (sc != spv::StorageClass::Output) {
           return fail(0) << "must be in the Output storage class";
         }
         break;
-      case SpvDecorationBinding:
-      case SpvDecorationDescriptorSet:
-        if (sc != SpvStorageClassStorageBuffer &&
-            sc != SpvStorageClassUniform &&
-            sc != SpvStorageClassUniformConstant) {
+      case spv::Decoration::Binding:
+      case spv::Decoration::DescriptorSet:
+        if (sc != spv::StorageClass::StorageBuffer &&
+            sc != spv::StorageClass::Uniform &&
+            sc != spv::StorageClass::UniformConstant) {
           return fail(6491) << "must be in the StorageBuffer, Uniform, or "
                                "UniformConstant storage class";
         }
         break;
-      case SpvDecorationInputAttachmentIndex:
-        if (sc != SpvStorageClassUniformConstant) {
+      case spv::Decoration::InputAttachmentIndex:
+        if (sc != spv::StorageClass::UniformConstant) {
           return fail(6678) << "must be in the UniformConstant storage class";
         }
         break;
-      case SpvDecorationFlat:
-      case SpvDecorationNoPerspective:
-      case SpvDecorationCentroid:
-      case SpvDecorationSample:
-        if (sc != SpvStorageClassInput && sc != SpvStorageClassOutput) {
+      case spv::Decoration::Flat:
+      case spv::Decoration::NoPerspective:
+      case spv::Decoration::Centroid:
+      case spv::Decoration::Sample:
+        if (sc != spv::StorageClass::Input && sc != spv::StorageClass::Output) {
           return fail(4670) << "storage class must be Input or Output";
         }
         break;
-      case SpvDecorationPerVertexKHR:
-        if (sc != SpvStorageClassInput) {
+      case spv::Decoration::PerVertexKHR:
+        if (sc != spv::StorageClass::Input) {
           return fail(6777) << "storage class must be Input";
         }
         break;
@@ -247,7 +247,7 @@
 }
 
 spv_result_t ValidateDecorate(ValidationState_t& _, const Instruction* inst) {
-  const auto decoration = inst->GetOperandAs<SpvDecoration>(1);
+  const auto decoration = inst->GetOperandAs<spv::Decoration>(1);
   const auto target_id = inst->GetOperandAs<uint32_t>(0);
   const auto target = _.FindDef(target_id);
   if (!target) {
@@ -255,8 +255,8 @@
   }
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    if ((decoration == SpvDecorationGLSLShared) ||
-        (decoration == SpvDecorationGLSLPacked)) {
+    if ((decoration == spv::Decoration::GLSLShared) ||
+        (decoration == spv::Decoration::GLSLPacked)) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << _.VkErrorID(4669) << "OpDecorate decoration '"
              << _.SpvDecorationString(decoration)
@@ -270,7 +270,7 @@
               "OpDecorateId";
   }
 
-  if (target->opcode() != SpvOpDecorationGroup) {
+  if (target->opcode() != spv::Op::OpDecorationGroup) {
     if (IsMemberDecorationOnly(decoration)) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << _.SpvDecorationString(decoration)
@@ -287,7 +287,7 @@
 }
 
 spv_result_t ValidateDecorateId(ValidationState_t& _, const Instruction* inst) {
-  const auto decoration = inst->GetOperandAs<SpvDecoration>(1);
+  const auto decoration = inst->GetOperandAs<spv::Decoration>(1);
   if (!DecorationTakesIdParameters(decoration)) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Decorations that don't take ID parameters may not be used with "
@@ -306,7 +306,7 @@
                                     const Instruction* inst) {
   const auto struct_type_id = inst->GetOperandAs<uint32_t>(0);
   const auto struct_type = _.FindDef(struct_type_id);
-  if (!struct_type || SpvOpTypeStruct != struct_type->opcode()) {
+  if (!struct_type || spv::Op::OpTypeStruct != struct_type->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "OpMemberDecorate Structure type <id> "
            << _.getIdName(struct_type_id) << " is not a struct type.";
@@ -323,7 +323,7 @@
            << " members. Largest valid index is " << member_count - 1 << ".";
   }
 
-  const auto decoration = inst->GetOperandAs<SpvDecoration>(2);
+  const auto decoration = inst->GetOperandAs<spv::Decoration>(2);
   if (IsNotMemberDecoration(decoration)) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << _.SpvDecorationString(decoration)
@@ -339,10 +339,11 @@
   const auto decoration_group = _.FindDef(decoration_group_id);
   for (auto pair : decoration_group->uses()) {
     auto use = pair.first;
-    if (use->opcode() != SpvOpDecorate && use->opcode() != SpvOpGroupDecorate &&
-        use->opcode() != SpvOpGroupMemberDecorate &&
-        use->opcode() != SpvOpName && use->opcode() != SpvOpDecorateId &&
-        !use->IsNonSemantic()) {
+    if (use->opcode() != spv::Op::OpDecorate &&
+        use->opcode() != spv::Op::OpGroupDecorate &&
+        use->opcode() != spv::Op::OpGroupMemberDecorate &&
+        use->opcode() != spv::Op::OpName &&
+        use->opcode() != spv::Op::OpDecorateId && !use->IsNonSemantic()) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "Result id of OpDecorationGroup can only "
              << "be targeted by OpName, OpGroupDecorate, "
@@ -356,7 +357,8 @@
                                    const Instruction* inst) {
   const auto decoration_group_id = inst->GetOperandAs<uint32_t>(0);
   auto decoration_group = _.FindDef(decoration_group_id);
-  if (!decoration_group || SpvOpDecorationGroup != decoration_group->opcode()) {
+  if (!decoration_group ||
+      spv::Op::OpDecorationGroup != decoration_group->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "OpGroupDecorate Decoration group <id> "
            << _.getIdName(decoration_group_id) << " is not a decoration group.";
@@ -364,7 +366,7 @@
   for (unsigned i = 1; i < inst->operands().size(); ++i) {
     auto target_id = inst->GetOperandAs<uint32_t>(i);
     auto target = _.FindDef(target_id);
-    if (!target || target->opcode() == SpvOpDecorationGroup) {
+    if (!target || target->opcode() == spv::Op::OpDecorationGroup) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "OpGroupDecorate may not target OpDecorationGroup <id> "
              << _.getIdName(target_id);
@@ -377,7 +379,8 @@
                                          const Instruction* inst) {
   const auto decoration_group_id = inst->GetOperandAs<uint32_t>(0);
   const auto decoration_group = _.FindDef(decoration_group_id);
-  if (!decoration_group || SpvOpDecorationGroup != decoration_group->opcode()) {
+  if (!decoration_group ||
+      spv::Op::OpDecorationGroup != decoration_group->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "OpGroupMemberDecorate Decoration group <id> "
            << _.getIdName(decoration_group_id) << " is not a decoration group.";
@@ -388,7 +391,7 @@
     const uint32_t struct_id = inst->GetOperandAs<uint32_t>(i);
     const uint32_t index = inst->GetOperandAs<uint32_t>(i + 1);
     auto struct_instr = _.FindDef(struct_id);
-    if (!struct_instr || SpvOpTypeStruct != struct_instr->opcode()) {
+    if (!struct_instr || spv::Op::OpTypeStruct != struct_instr->opcode()) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "OpGroupMemberDecorate Structure type <id> "
              << _.getIdName(struct_id) << " is not a struct type.";
@@ -413,10 +416,11 @@
 spv_result_t RegisterDecorations(ValidationState_t& _,
                                  const Instruction* inst) {
   switch (inst->opcode()) {
-    case SpvOpDecorate:
-    case SpvOpDecorateId: {
+    case spv::Op::OpDecorate:
+    case spv::Op::OpDecorateId: {
       const uint32_t target_id = inst->word(1);
-      const SpvDecoration dec_type = static_cast<SpvDecoration>(inst->word(2));
+      const spv::Decoration dec_type =
+          static_cast<spv::Decoration>(inst->word(2));
       std::vector<uint32_t> dec_params;
       if (inst->words().size() > 3) {
         dec_params.insert(dec_params.end(), inst->words().begin() + 3,
@@ -425,10 +429,11 @@
       _.RegisterDecorationForId(target_id, Decoration(dec_type, dec_params));
       break;
     }
-    case SpvOpMemberDecorate: {
+    case spv::Op::OpMemberDecorate: {
       const uint32_t struct_id = inst->word(1);
       const uint32_t index = inst->word(2);
-      const SpvDecoration dec_type = static_cast<SpvDecoration>(inst->word(3));
+      const spv::Decoration dec_type =
+          static_cast<spv::Decoration>(inst->word(3));
       std::vector<uint32_t> dec_params;
       if (inst->words().size() > 4) {
         dec_params.insert(dec_params.end(), inst->words().begin() + 4,
@@ -438,12 +443,12 @@
                                 Decoration(dec_type, dec_params, index));
       break;
     }
-    case SpvOpDecorationGroup: {
+    case spv::Op::OpDecorationGroup: {
       // We don't need to do anything right now. Assigning decorations to groups
       // will be taken care of via OpGroupDecorate.
       break;
     }
-    case SpvOpGroupDecorate: {
+    case spv::Op::OpGroupDecorate: {
       // Word 1 is the group <id>. All subsequent words are target <id>s that
       // are going to be decorated with the decorations.
       const uint32_t decoration_group_id = inst->word(1);
@@ -456,7 +461,7 @@
       }
       break;
     }
-    case SpvOpGroupMemberDecorate: {
+    case spv::Op::OpGroupMemberDecorate: {
       // Word 1 is the Decoration Group <id> followed by (struct<id>,literal)
       // pairs. All decorations of the group should be applied to all the struct
       // members that are specified in the instructions.
@@ -486,24 +491,24 @@
 
 spv_result_t AnnotationPass(ValidationState_t& _, const Instruction* inst) {
   switch (inst->opcode()) {
-    case SpvOpDecorate:
+    case spv::Op::OpDecorate:
       if (auto error = ValidateDecorate(_, inst)) return error;
       break;
-    case SpvOpDecorateId:
+    case spv::Op::OpDecorateId:
       if (auto error = ValidateDecorateId(_, inst)) return error;
       break;
-    // TODO(dneto): SpvOpDecorateStringGOOGLE
+    // TODO(dneto): spv::Op::OpDecorateStringGOOGLE
     // See https://github.com/KhronosGroup/SPIRV-Tools/issues/2253
-    case SpvOpMemberDecorate:
+    case spv::Op::OpMemberDecorate:
       if (auto error = ValidateMemberDecorate(_, inst)) return error;
       break;
-    case SpvOpDecorationGroup:
+    case spv::Op::OpDecorationGroup:
       if (auto error = ValidateDecorationGroup(_, inst)) return error;
       break;
-    case SpvOpGroupDecorate:
+    case spv::Op::OpGroupDecorate:
       if (auto error = ValidateGroupDecorate(_, inst)) return error;
       break;
-    case SpvOpGroupMemberDecorate:
+    case spv::Op::OpGroupMemberDecorate:
       if (auto error = ValidateGroupMemberDecorate(_, inst)) return error;
       break;
     default:
diff --git a/source/val/validate_arithmetics.cpp b/source/val/validate_arithmetics.cpp
index bae9b5d..a082eeb 100644
--- a/source/val/validate_arithmetics.cpp
+++ b/source/val/validate_arithmetics.cpp
@@ -28,19 +28,20 @@
 
 // Validates correctness of arithmetic instructions.
 spv_result_t ArithmeticsPass(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   const uint32_t result_type = inst->type_id();
 
   switch (opcode) {
-    case SpvOpFAdd:
-    case SpvOpFSub:
-    case SpvOpFMul:
-    case SpvOpFDiv:
-    case SpvOpFRem:
-    case SpvOpFMod:
-    case SpvOpFNegate: {
+    case spv::Op::OpFAdd:
+    case spv::Op::OpFSub:
+    case spv::Op::OpFMul:
+    case spv::Op::OpFDiv:
+    case spv::Op::OpFRem:
+    case spv::Op::OpFMod:
+    case spv::Op::OpFNegate: {
       bool supportsCoopMat =
-          (opcode != SpvOpFMul && opcode != SpvOpFRem && opcode != SpvOpFMod);
+          (opcode != spv::Op::OpFMul && opcode != spv::Op::OpFRem &&
+           opcode != spv::Op::OpFMod);
       if (!_.IsFloatScalarType(result_type) &&
           !_.IsFloatVectorType(result_type) &&
           !(supportsCoopMat && _.IsFloatCooperativeMatrixType(result_type)))
@@ -59,9 +60,9 @@
       break;
     }
 
-    case SpvOpUDiv:
-    case SpvOpUMod: {
-      bool supportsCoopMat = (opcode == SpvOpUDiv);
+    case spv::Op::OpUDiv:
+    case spv::Op::OpUMod: {
+      bool supportsCoopMat = (opcode == spv::Op::OpUDiv);
       if (!_.IsUnsignedIntScalarType(result_type) &&
           !_.IsUnsignedIntVectorType(result_type) &&
           !(supportsCoopMat &&
@@ -81,15 +82,16 @@
       break;
     }
 
-    case SpvOpISub:
-    case SpvOpIAdd:
-    case SpvOpIMul:
-    case SpvOpSDiv:
-    case SpvOpSMod:
-    case SpvOpSRem:
-    case SpvOpSNegate: {
+    case spv::Op::OpISub:
+    case spv::Op::OpIAdd:
+    case spv::Op::OpIMul:
+    case spv::Op::OpSDiv:
+    case spv::Op::OpSMod:
+    case spv::Op::OpSRem:
+    case spv::Op::OpSNegate: {
       bool supportsCoopMat =
-          (opcode != SpvOpIMul && opcode != SpvOpSRem && opcode != SpvOpSMod);
+          (opcode != spv::Op::OpIMul && opcode != spv::Op::OpSRem &&
+           opcode != spv::Op::OpSMod);
       if (!_.IsIntScalarType(result_type) && !_.IsIntVectorType(result_type) &&
           !(supportsCoopMat && _.IsIntCooperativeMatrixType(result_type)))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -125,7 +127,7 @@
       break;
     }
 
-    case SpvOpDot: {
+    case spv::Op::OpDot: {
       if (!_.IsFloatScalarType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected float scalar type as Result Type: "
@@ -162,7 +164,7 @@
       break;
     }
 
-    case SpvOpVectorTimesScalar: {
+    case spv::Op::OpVectorTimesScalar: {
       if (!_.IsFloatVectorType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected float vector type as Result Type: "
@@ -185,7 +187,7 @@
       break;
     }
 
-    case SpvOpMatrixTimesScalar: {
+    case spv::Op::OpMatrixTimesScalar: {
       if (!_.IsFloatMatrixType(result_type) &&
           !_.IsCooperativeMatrixType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -209,7 +211,7 @@
       break;
     }
 
-    case SpvOpVectorTimesMatrix: {
+    case spv::Op::OpVectorTimesMatrix: {
       const uint32_t vector_type_id = _.GetOperandTypeId(inst, 2);
       const uint32_t matrix_type_id = _.GetOperandTypeId(inst, 3);
 
@@ -259,7 +261,7 @@
       break;
     }
 
-    case SpvOpMatrixTimesVector: {
+    case spv::Op::OpMatrixTimesVector: {
       const uint32_t matrix_type_id = _.GetOperandTypeId(inst, 2);
       const uint32_t vector_type_id = _.GetOperandTypeId(inst, 3);
 
@@ -303,7 +305,7 @@
       break;
     }
 
-    case SpvOpMatrixTimesMatrix: {
+    case spv::Op::OpMatrixTimesMatrix: {
       const uint32_t left_type_id = _.GetOperandTypeId(inst, 2);
       const uint32_t right_type_id = _.GetOperandTypeId(inst, 3);
 
@@ -369,7 +371,7 @@
       break;
     }
 
-    case SpvOpOuterProduct: {
+    case spv::Op::OpOuterProduct: {
       const uint32_t left_type_id = _.GetOperandTypeId(inst, 2);
       const uint32_t right_type_id = _.GetOperandTypeId(inst, 3);
 
@@ -407,10 +409,10 @@
       break;
     }
 
-    case SpvOpIAddCarry:
-    case SpvOpISubBorrow:
-    case SpvOpUMulExtended:
-    case SpvOpSMulExtended: {
+    case spv::Op::OpIAddCarry:
+    case spv::Op::OpISubBorrow:
+    case spv::Op::OpUMulExtended:
+    case spv::Op::OpSMulExtended: {
       std::vector<uint32_t> result_types;
       if (!_.GetStructMemberTypes(result_type, &result_types))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -422,7 +424,7 @@
                << "Expected Result Type struct to have two members: "
                << spvOpcodeString(opcode);
 
-      if (opcode == SpvOpSMulExtended) {
+      if (opcode == spv::Op::OpSMulExtended) {
         if (!_.IsIntScalarType(result_types[0]) &&
             !_.IsIntVectorType(result_types[0]))
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -453,7 +455,7 @@
       break;
     }
 
-    case SpvOpCooperativeMatrixMulAddNV: {
+    case spv::Op::OpCooperativeMatrixMulAddNV: {
       const uint32_t D_type_id = _.GetOperandTypeId(inst, 1);
       const uint32_t A_type_id = _.GetOperandTypeId(inst, 2);
       const uint32_t B_type_id = _.GetOperandTypeId(inst, 3);
diff --git a/source/val/validate_atomics.cpp b/source/val/validate_atomics.cpp
index bf565c3..d6b094c 100644
--- a/source/val/validate_atomics.cpp
+++ b/source/val/validate_atomics.cpp
@@ -29,18 +29,18 @@
 
 namespace {
 
-bool IsStorageClassAllowedByUniversalRules(uint32_t storage_class) {
+bool IsStorageClassAllowedByUniversalRules(spv::StorageClass storage_class) {
   switch (storage_class) {
-    case SpvStorageClassUniform:
-    case SpvStorageClassStorageBuffer:
-    case SpvStorageClassWorkgroup:
-    case SpvStorageClassCrossWorkgroup:
-    case SpvStorageClassGeneric:
-    case SpvStorageClassAtomicCounter:
-    case SpvStorageClassImage:
-    case SpvStorageClassFunction:
-    case SpvStorageClassPhysicalStorageBuffer:
-    case SpvStorageClassTaskPayloadWorkgroupEXT:
+    case spv::StorageClass::Uniform:
+    case spv::StorageClass::StorageBuffer:
+    case spv::StorageClass::Workgroup:
+    case spv::StorageClass::CrossWorkgroup:
+    case spv::StorageClass::Generic:
+    case spv::StorageClass::AtomicCounter:
+    case spv::StorageClass::Image:
+    case spv::StorageClass::Function:
+    case spv::StorageClass::PhysicalStorageBuffer:
+    case spv::StorageClass::TaskPayloadWorkgroupEXT:
       return true;
       break;
     default:
@@ -48,10 +48,10 @@
   }
 }
 
-bool HasReturnType(uint32_t opcode) {
+bool HasReturnType(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpAtomicStore:
-    case SpvOpAtomicFlagClear:
+    case spv::Op::OpAtomicStore:
+    case spv::Op::OpAtomicFlagClear:
       return false;
       break;
     default:
@@ -59,11 +59,11 @@
   }
 }
 
-bool HasOnlyFloatReturnType(uint32_t opcode) {
+bool HasOnlyFloatReturnType(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpAtomicFAddEXT:
-    case SpvOpAtomicFMinEXT:
-    case SpvOpAtomicFMaxEXT:
+    case spv::Op::OpAtomicFAddEXT:
+    case spv::Op::OpAtomicFMinEXT:
+    case spv::Op::OpAtomicFMaxEXT:
       return true;
       break;
     default:
@@ -71,21 +71,21 @@
   }
 }
 
-bool HasOnlyIntReturnType(uint32_t opcode) {
+bool HasOnlyIntReturnType(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpAtomicCompareExchange:
-    case SpvOpAtomicCompareExchangeWeak:
-    case SpvOpAtomicIIncrement:
-    case SpvOpAtomicIDecrement:
-    case SpvOpAtomicIAdd:
-    case SpvOpAtomicISub:
-    case SpvOpAtomicSMin:
-    case SpvOpAtomicUMin:
-    case SpvOpAtomicSMax:
-    case SpvOpAtomicUMax:
-    case SpvOpAtomicAnd:
-    case SpvOpAtomicOr:
-    case SpvOpAtomicXor:
+    case spv::Op::OpAtomicCompareExchange:
+    case spv::Op::OpAtomicCompareExchangeWeak:
+    case spv::Op::OpAtomicIIncrement:
+    case spv::Op::OpAtomicIDecrement:
+    case spv::Op::OpAtomicIAdd:
+    case spv::Op::OpAtomicISub:
+    case spv::Op::OpAtomicSMin:
+    case spv::Op::OpAtomicUMin:
+    case spv::Op::OpAtomicSMax:
+    case spv::Op::OpAtomicUMax:
+    case spv::Op::OpAtomicAnd:
+    case spv::Op::OpAtomicOr:
+    case spv::Op::OpAtomicXor:
       return true;
       break;
     default:
@@ -93,10 +93,10 @@
   }
 }
 
-bool HasIntOrFloatReturnType(uint32_t opcode) {
+bool HasIntOrFloatReturnType(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpAtomicLoad:
-    case SpvOpAtomicExchange:
+    case spv::Op::OpAtomicLoad:
+    case spv::Op::OpAtomicExchange:
       return true;
       break;
     default:
@@ -104,9 +104,9 @@
   }
 }
 
-bool HasOnlyBoolReturnType(uint32_t opcode) {
+bool HasOnlyBoolReturnType(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpAtomicFlagTestAndSet:
+    case spv::Op::OpAtomicFlagTestAndSet:
       return true;
       break;
     default:
@@ -121,29 +121,29 @@
 
 // Validates correctness of atomic instructions.
 spv_result_t AtomicsPass(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   switch (opcode) {
-    case SpvOpAtomicLoad:
-    case SpvOpAtomicStore:
-    case SpvOpAtomicExchange:
-    case SpvOpAtomicFAddEXT:
-    case SpvOpAtomicCompareExchange:
-    case SpvOpAtomicCompareExchangeWeak:
-    case SpvOpAtomicIIncrement:
-    case SpvOpAtomicIDecrement:
-    case SpvOpAtomicIAdd:
-    case SpvOpAtomicISub:
-    case SpvOpAtomicSMin:
-    case SpvOpAtomicUMin:
-    case SpvOpAtomicFMinEXT:
-    case SpvOpAtomicSMax:
-    case SpvOpAtomicUMax:
-    case SpvOpAtomicFMaxEXT:
-    case SpvOpAtomicAnd:
-    case SpvOpAtomicOr:
-    case SpvOpAtomicXor:
-    case SpvOpAtomicFlagTestAndSet:
-    case SpvOpAtomicFlagClear: {
+    case spv::Op::OpAtomicLoad:
+    case spv::Op::OpAtomicStore:
+    case spv::Op::OpAtomicExchange:
+    case spv::Op::OpAtomicFAddEXT:
+    case spv::Op::OpAtomicCompareExchange:
+    case spv::Op::OpAtomicCompareExchangeWeak:
+    case spv::Op::OpAtomicIIncrement:
+    case spv::Op::OpAtomicIDecrement:
+    case spv::Op::OpAtomicIAdd:
+    case spv::Op::OpAtomicISub:
+    case spv::Op::OpAtomicSMin:
+    case spv::Op::OpAtomicUMin:
+    case spv::Op::OpAtomicFMinEXT:
+    case spv::Op::OpAtomicSMax:
+    case spv::Op::OpAtomicUMax:
+    case spv::Op::OpAtomicFMaxEXT:
+    case spv::Op::OpAtomicAnd:
+    case spv::Op::OpAtomicOr:
+    case spv::Op::OpAtomicXor:
+    case spv::Op::OpAtomicFlagTestAndSet:
+    case spv::Op::OpAtomicFlagClear: {
       const uint32_t result_type = inst->type_id();
 
       // All current atomics only are scalar result
@@ -177,7 +177,7 @@
       uint32_t operand_index = HasReturnType(opcode) ? 2 : 0;
       const uint32_t pointer_type = _.GetOperandTypeId(inst, operand_index++);
       uint32_t data_type = 0;
-      uint32_t storage_class = 0;
+      spv::StorageClass storage_class;
       if (!_.GetPointerTypeInfo(pointer_type, &data_type, &storage_class)) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << spvOpcodeString(opcode)
@@ -185,8 +185,8 @@
       }
 
       // Can't use result_type because OpAtomicStore doesn't have a result
-      if ( _.IsIntScalarType(data_type) &&_.GetBitWidth(data_type) == 64 &&
-          !_.HasCapability(SpvCapabilityInt64Atomics)) {
+      if (_.IsIntScalarType(data_type) && _.GetBitWidth(data_type) == 64 &&
+          !_.HasCapability(spv::Capability::Int64Atomics)) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << spvOpcodeString(opcode)
                << ": 64-bit atomics require the Int64Atomics capability";
@@ -200,69 +200,69 @@
       }
 
       // Then Shader rules
-      if (_.HasCapability(SpvCapabilityShader)) {
+      if (_.HasCapability(spv::Capability::Shader)) {
         // Vulkan environment rule
         if (spvIsVulkanEnv(_.context()->target_env)) {
-          if ((storage_class != SpvStorageClassUniform) &&
-              (storage_class != SpvStorageClassStorageBuffer) &&
-              (storage_class != SpvStorageClassWorkgroup) &&
-              (storage_class != SpvStorageClassImage) &&
-              (storage_class != SpvStorageClassPhysicalStorageBuffer) &&
-              (storage_class != SpvStorageClassTaskPayloadWorkgroupEXT)) {
+          if ((storage_class != spv::StorageClass::Uniform) &&
+              (storage_class != spv::StorageClass::StorageBuffer) &&
+              (storage_class != spv::StorageClass::Workgroup) &&
+              (storage_class != spv::StorageClass::Image) &&
+              (storage_class != spv::StorageClass::PhysicalStorageBuffer) &&
+              (storage_class != spv::StorageClass::TaskPayloadWorkgroupEXT)) {
             return _.diag(SPV_ERROR_INVALID_DATA, inst)
                    << _.VkErrorID(4686) << spvOpcodeString(opcode)
                    << ": Vulkan spec only allows storage classes for atomic to "
                       "be: Uniform, Workgroup, Image, StorageBuffer, "
                       "PhysicalStorageBuffer or TaskPayloadWorkgroupEXT.";
           }
-        } else if (storage_class == SpvStorageClassFunction) {
+        } else if (storage_class == spv::StorageClass::Function) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << spvOpcodeString(opcode)
                  << ": Function storage class forbidden when the Shader "
                     "capability is declared.";
         }
 
-        if (opcode == SpvOpAtomicFAddEXT) {
+        if (opcode == spv::Op::OpAtomicFAddEXT) {
           // result type being float checked already
           if ((_.GetBitWidth(result_type) == 16) &&
-              (!_.HasCapability(SpvCapabilityAtomicFloat16AddEXT))) {
+              (!_.HasCapability(spv::Capability::AtomicFloat16AddEXT))) {
             return _.diag(SPV_ERROR_INVALID_DATA, inst)
                    << spvOpcodeString(opcode)
                    << ": float add atomics require the AtomicFloat32AddEXT "
                       "capability";
           }
           if ((_.GetBitWidth(result_type) == 32) &&
-              (!_.HasCapability(SpvCapabilityAtomicFloat32AddEXT))) {
+              (!_.HasCapability(spv::Capability::AtomicFloat32AddEXT))) {
             return _.diag(SPV_ERROR_INVALID_DATA, inst)
                    << spvOpcodeString(opcode)
                    << ": float add atomics require the AtomicFloat32AddEXT "
                       "capability";
           }
           if ((_.GetBitWidth(result_type) == 64) &&
-              (!_.HasCapability(SpvCapabilityAtomicFloat64AddEXT))) {
+              (!_.HasCapability(spv::Capability::AtomicFloat64AddEXT))) {
             return _.diag(SPV_ERROR_INVALID_DATA, inst)
                    << spvOpcodeString(opcode)
                    << ": float add atomics require the AtomicFloat64AddEXT "
                       "capability";
           }
-        } else if (opcode == SpvOpAtomicFMinEXT ||
-                   opcode == SpvOpAtomicFMaxEXT) {
+        } else if (opcode == spv::Op::OpAtomicFMinEXT ||
+                   opcode == spv::Op::OpAtomicFMaxEXT) {
           if ((_.GetBitWidth(result_type) == 16) &&
-              (!_.HasCapability(SpvCapabilityAtomicFloat16MinMaxEXT))) {
+              (!_.HasCapability(spv::Capability::AtomicFloat16MinMaxEXT))) {
             return _.diag(SPV_ERROR_INVALID_DATA, inst)
                    << spvOpcodeString(opcode)
                    << ": float min/max atomics require the "
                       "AtomicFloat16MinMaxEXT capability";
           }
           if ((_.GetBitWidth(result_type) == 32) &&
-              (!_.HasCapability(SpvCapabilityAtomicFloat32MinMaxEXT))) {
+              (!_.HasCapability(spv::Capability::AtomicFloat32MinMaxEXT))) {
             return _.diag(SPV_ERROR_INVALID_DATA, inst)
                    << spvOpcodeString(opcode)
                    << ": float min/max atomics require the "
                       "AtomicFloat32MinMaxEXT capability";
           }
           if ((_.GetBitWidth(result_type) == 64) &&
-              (!_.HasCapability(SpvCapabilityAtomicFloat64MinMaxEXT))) {
+              (!_.HasCapability(spv::Capability::AtomicFloat64MinMaxEXT))) {
             return _.diag(SPV_ERROR_INVALID_DATA, inst)
                    << spvOpcodeString(opcode)
                    << ": float min/max atomics require the "
@@ -273,10 +273,10 @@
 
       // And finally OpenCL environment rules
       if (spvIsOpenCLEnv(_.context()->target_env)) {
-        if ((storage_class != SpvStorageClassFunction) &&
-            (storage_class != SpvStorageClassWorkgroup) &&
-            (storage_class != SpvStorageClassCrossWorkgroup) &&
-            (storage_class != SpvStorageClassGeneric)) {
+        if ((storage_class != spv::StorageClass::Function) &&
+            (storage_class != spv::StorageClass::Workgroup) &&
+            (storage_class != spv::StorageClass::CrossWorkgroup) &&
+            (storage_class != spv::StorageClass::Generic)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << spvOpcodeString(opcode)
                  << ": storage class must be Function, Workgroup, "
@@ -284,7 +284,7 @@
         }
 
         if (_.context()->target_env == SPV_ENV_OPENCL_1_2) {
-          if (storage_class == SpvStorageClassGeneric) {
+          if (storage_class == spv::StorageClass::Generic) {
             return _.diag(SPV_ERROR_INVALID_DATA, inst)
                    << "Storage class cannot be Generic in OpenCL 1.2 "
                       "environment";
@@ -293,15 +293,15 @@
       }
 
       // If result and pointer type are different, need to do special check here
-      if (opcode == SpvOpAtomicFlagTestAndSet ||
-          opcode == SpvOpAtomicFlagClear) {
+      if (opcode == spv::Op::OpAtomicFlagTestAndSet ||
+          opcode == spv::Op::OpAtomicFlagClear) {
         if (!_.IsIntScalarType(data_type) || _.GetBitWidth(data_type) != 32) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << spvOpcodeString(opcode)
                  << ": expected Pointer to point to a value of 32-bit integer "
                     "type";
         }
-      } else if (opcode == SpvOpAtomicStore) {
+      } else if (opcode == spv::Op::OpAtomicStore) {
         if (!_.IsFloatScalarType(data_type) && !_.IsIntScalarType(data_type)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << spvOpcodeString(opcode)
@@ -325,8 +325,8 @@
                                                memory_scope))
         return error;
 
-      if (opcode == SpvOpAtomicCompareExchange ||
-          opcode == SpvOpAtomicCompareExchangeWeak) {
+      if (opcode == spv::Op::OpAtomicCompareExchange ||
+          opcode == spv::Op::OpAtomicCompareExchangeWeak) {
         const auto unequal_semantics_index = operand_index++;
         if (auto error = ValidateMemorySemantics(
                 _, inst, unequal_semantics_index, memory_scope))
@@ -346,15 +346,15 @@
             _.EvalInt32IfConst(
                 inst->GetOperandAs<uint32_t>(unequal_semantics_index));
         if (is_equal_const && is_unequal_const &&
-            ((equal_value & SpvMemorySemanticsVolatileMask) ^
-             (unequal_value & SpvMemorySemanticsVolatileMask))) {
+            ((equal_value & uint32_t(spv::MemorySemanticsMask::Volatile)) ^
+             (unequal_value & uint32_t(spv::MemorySemanticsMask::Volatile)))) {
           return _.diag(SPV_ERROR_INVALID_ID, inst)
                  << "Volatile mask setting must match for Equal and Unequal "
                     "memory semantics";
         }
       }
 
-      if (opcode == SpvOpAtomicStore) {
+      if (opcode == spv::Op::OpAtomicStore) {
         const uint32_t value_type = _.GetOperandTypeId(inst, 3);
         if (value_type != data_type) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -362,10 +362,11 @@
                  << ": expected Value type and the type pointed to by "
                     "Pointer to be the same";
         }
-      } else if (opcode != SpvOpAtomicLoad && opcode != SpvOpAtomicIIncrement &&
-                 opcode != SpvOpAtomicIDecrement &&
-                 opcode != SpvOpAtomicFlagTestAndSet &&
-                 opcode != SpvOpAtomicFlagClear) {
+      } else if (opcode != spv::Op::OpAtomicLoad &&
+                 opcode != spv::Op::OpAtomicIIncrement &&
+                 opcode != spv::Op::OpAtomicIDecrement &&
+                 opcode != spv::Op::OpAtomicFlagTestAndSet &&
+                 opcode != spv::Op::OpAtomicFlagClear) {
         const uint32_t value_type = _.GetOperandTypeId(inst, operand_index++);
         if (value_type != result_type) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -374,8 +375,8 @@
         }
       }
 
-      if (opcode == SpvOpAtomicCompareExchange ||
-          opcode == SpvOpAtomicCompareExchangeWeak) {
+      if (opcode == spv::Op::OpAtomicCompareExchange ||
+          opcode == spv::Op::OpAtomicCompareExchangeWeak) {
         const uint32_t comparator_type =
             _.GetOperandTypeId(inst, operand_index++);
         if (comparator_type != result_type) {
diff --git a/source/val/validate_barriers.cpp b/source/val/validate_barriers.cpp
index 03225d8..59d886a 100644
--- a/source/val/validate_barriers.cpp
+++ b/source/val/validate_barriers.cpp
@@ -32,20 +32,20 @@
 
 // Validates correctness of barrier instructions.
 spv_result_t BarriersPass(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   const uint32_t result_type = inst->type_id();
 
   switch (opcode) {
-    case SpvOpControlBarrier: {
+    case spv::Op::OpControlBarrier: {
       if (_.version() < SPV_SPIRV_VERSION_WORD(1, 3)) {
         _.function(inst->function()->id())
             ->RegisterExecutionModelLimitation(
-                [](SpvExecutionModel model, std::string* message) {
-                  if (model != SpvExecutionModelTessellationControl &&
-                      model != SpvExecutionModelGLCompute &&
-                      model != SpvExecutionModelKernel &&
-                      model != SpvExecutionModelTaskNV &&
-                      model != SpvExecutionModelMeshNV) {
+                [](spv::ExecutionModel model, std::string* message) {
+                  if (model != spv::ExecutionModel::TessellationControl &&
+                      model != spv::ExecutionModel::GLCompute &&
+                      model != spv::ExecutionModel::Kernel &&
+                      model != spv::ExecutionModel::TaskNV &&
+                      model != spv::ExecutionModel::MeshNV) {
                     if (message) {
                       *message =
                           "OpControlBarrier requires one of the following "
@@ -76,7 +76,7 @@
       break;
     }
 
-    case SpvOpMemoryBarrier: {
+    case spv::Op::OpMemoryBarrier: {
       const uint32_t memory_scope = inst->word(1);
 
       if (auto error = ValidateMemoryScope(_, inst, memory_scope)) {
@@ -89,8 +89,8 @@
       break;
     }
 
-    case SpvOpNamedBarrierInitialize: {
-      if (_.GetIdOpcode(result_type) != SpvOpTypeNamedBarrier) {
+    case spv::Op::OpNamedBarrierInitialize: {
+      if (_.GetIdOpcode(result_type) != spv::Op::OpTypeNamedBarrier) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << spvOpcodeString(opcode)
                << ": expected Result Type to be OpTypeNamedBarrier";
@@ -106,9 +106,9 @@
       break;
     }
 
-    case SpvOpMemoryNamedBarrier: {
+    case spv::Op::OpMemoryNamedBarrier: {
       const uint32_t named_barrier_type = _.GetOperandTypeId(inst, 0);
-      if (_.GetIdOpcode(named_barrier_type) != SpvOpTypeNamedBarrier) {
+      if (_.GetIdOpcode(named_barrier_type) != spv::Op::OpTypeNamedBarrier) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << spvOpcodeString(opcode)
                << ": expected Named Barrier to be of type OpTypeNamedBarrier";
diff --git a/source/val/validate_bitwise.cpp b/source/val/validate_bitwise.cpp
index e6e97c4..87c9556 100644
--- a/source/val/validate_bitwise.cpp
+++ b/source/val/validate_bitwise.cpp
@@ -27,7 +27,7 @@
 // Validates when base and result need to be the same type
 spv_result_t ValidateBaseType(ValidationState_t& _, const Instruction* inst,
                               const uint32_t base_type) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
 
   if (!_.IsIntScalarType(base_type) && !_.IsIntVectorType(base_type)) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -47,7 +47,7 @@
   }
 
   // OpBitCount just needs same number of components
-  if (base_type != inst->type_id() && opcode != SpvOpBitCount) {
+  if (base_type != inst->type_id() && opcode != spv::Op::OpBitCount) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Base Type to be equal to Result Type: "
            << spvOpcodeString(opcode);
@@ -58,13 +58,13 @@
 
 // Validates correctness of bitwise instructions.
 spv_result_t BitwisePass(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   const uint32_t result_type = inst->type_id();
 
   switch (opcode) {
-    case SpvOpShiftRightLogical:
-    case SpvOpShiftRightArithmetic:
-    case SpvOpShiftLeftLogical: {
+    case spv::Op::OpShiftRightLogical:
+    case spv::Op::OpShiftRightArithmetic:
+    case spv::Op::OpShiftLeftLogical: {
       if (!_.IsIntScalarType(result_type) && !_.IsIntVectorType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected int scalar or vector type as Result Type: "
@@ -103,10 +103,10 @@
       break;
     }
 
-    case SpvOpBitwiseOr:
-    case SpvOpBitwiseXor:
-    case SpvOpBitwiseAnd:
-    case SpvOpNot: {
+    case spv::Op::OpBitwiseOr:
+    case spv::Op::OpBitwiseXor:
+    case spv::Op::OpBitwiseAnd:
+    case spv::Op::OpNot: {
       if (!_.IsIntScalarType(result_type) && !_.IsIntVectorType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected int scalar or vector type as Result Type: "
@@ -140,7 +140,7 @@
       break;
     }
 
-    case SpvOpBitFieldInsert: {
+    case spv::Op::OpBitFieldInsert: {
       const uint32_t base_type = _.GetOperandTypeId(inst, 2);
       const uint32_t insert_type = _.GetOperandTypeId(inst, 3);
       const uint32_t offset_type = _.GetOperandTypeId(inst, 4);
@@ -167,8 +167,8 @@
       break;
     }
 
-    case SpvOpBitFieldSExtract:
-    case SpvOpBitFieldUExtract: {
+    case spv::Op::OpBitFieldSExtract:
+    case spv::Op::OpBitFieldUExtract: {
       const uint32_t base_type = _.GetOperandTypeId(inst, 2);
       const uint32_t offset_type = _.GetOperandTypeId(inst, 3);
       const uint32_t count_type = _.GetOperandTypeId(inst, 4);
@@ -189,7 +189,7 @@
       break;
     }
 
-    case SpvOpBitReverse: {
+    case spv::Op::OpBitReverse: {
       const uint32_t base_type = _.GetOperandTypeId(inst, 2);
 
       if (spv_result_t error = ValidateBaseType(_, inst, base_type)) {
@@ -199,7 +199,7 @@
       break;
     }
 
-    case SpvOpBitCount: {
+    case spv::Op::OpBitCount: {
       if (!_.IsIntScalarType(result_type) && !_.IsIntVectorType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected int scalar or vector type as Result Type: "
diff --git a/source/val/validate_builtins.cpp b/source/val/validate_builtins.cpp
index 6f4b0f9..c07dcad 100644
--- a/source/val/validate_builtins.cpp
+++ b/source/val/validate_builtins.cpp
@@ -62,7 +62,7 @@
                                const Instruction& inst,
                                uint32_t* underlying_type) {
   if (decoration.struct_member_index() != Decoration::kInvalidMember) {
-    if (inst.opcode() != SpvOpTypeStruct) {
+    if (inst.opcode() != spv::Op::OpTypeStruct) {
       return _.diag(SPV_ERROR_INVALID_DATA, &inst)
              << GetIdDesc(inst)
              << "Attempted to get underlying data type via member index for "
@@ -72,7 +72,7 @@
     return SPV_SUCCESS;
   }
 
-  if (inst.opcode() == SpvOpTypeStruct) {
+  if (inst.opcode() == spv::Op::OpTypeStruct) {
     return _.diag(SPV_ERROR_INVALID_DATA, &inst)
            << GetIdDesc(inst)
            << " did not find an member index to get underlying data type for "
@@ -84,7 +84,7 @@
     return SPV_SUCCESS;
   }
 
-  uint32_t storage_class = 0;
+  spv::StorageClass storage_class;
   if (!_.GetPointerTypeInfo(inst.type_id(), underlying_type, &storage_class)) {
     return _.diag(SPV_ERROR_INVALID_DATA, &inst)
            << GetIdDesc(inst)
@@ -95,22 +95,22 @@
 }
 
 // Returns Storage Class used by the instruction if applicable.
-// Returns SpvStorageClassMax if not.
-SpvStorageClass GetStorageClass(const Instruction& inst) {
+// Returns spv::StorageClass::Max if not.
+spv::StorageClass GetStorageClass(const Instruction& inst) {
   switch (inst.opcode()) {
-    case SpvOpTypePointer:
-    case SpvOpTypeForwardPointer: {
-      return SpvStorageClass(inst.word(2));
+    case spv::Op::OpTypePointer:
+    case spv::Op::OpTypeForwardPointer: {
+      return spv::StorageClass(inst.word(2));
     }
-    case SpvOpVariable: {
-      return SpvStorageClass(inst.word(3));
+    case spv::Op::OpVariable: {
+      return spv::StorageClass(inst.word(3));
     }
-    case SpvOpGenericCastToPtrExplicit: {
-      return SpvStorageClass(inst.word(4));
+    case spv::Op::OpGenericCastToPtrExplicit: {
+      return spv::StorageClass(inst.word(4));
     }
     default: { break; }
   }
-  return SpvStorageClassMax;
+  return spv::StorageClass::Max;
 }
 
 typedef enum VUIDError_ {
@@ -123,52 +123,52 @@
 const static uint32_t NumVUIDBuiltins = 36;
 
 typedef struct {
-  SpvBuiltIn builtIn;
+  spv::BuiltIn builtIn;
   uint32_t vuid[VUIDErrorMax];  // execution mode, storage class, type VUIDs
 } BuiltinVUIDMapping;
 
 std::array<BuiltinVUIDMapping, NumVUIDBuiltins> builtinVUIDInfo = {{
     // clang-format off
-    {SpvBuiltInSubgroupEqMask,            {0,    4370, 4371}},
-    {SpvBuiltInSubgroupGeMask,            {0,    4372, 4373}},
-    {SpvBuiltInSubgroupGtMask,            {0,    4374, 4375}},
-    {SpvBuiltInSubgroupLeMask,            {0,    4376, 4377}},
-    {SpvBuiltInSubgroupLtMask,            {0,    4378, 4379}},
-    {SpvBuiltInSubgroupLocalInvocationId, {0,    4380, 4381}},
-    {SpvBuiltInSubgroupSize,              {0,    4382, 4383}},
-    {SpvBuiltInGlobalInvocationId,        {4236, 4237, 4238}},
-    {SpvBuiltInLocalInvocationId,         {4281, 4282, 4283}},
-    {SpvBuiltInNumWorkgroups,             {4296, 4297, 4298}},
-    {SpvBuiltInNumSubgroups,              {4293, 4294, 4295}},
-    {SpvBuiltInSubgroupId,                {4367, 4368, 4369}},
-    {SpvBuiltInWorkgroupId,               {4422, 4423, 4424}},
-    {SpvBuiltInHitKindKHR,                {4242, 4243, 4244}},
-    {SpvBuiltInHitTNV,                    {4245, 4246, 4247}},
-    {SpvBuiltInInstanceCustomIndexKHR,    {4251, 4252, 4253}},
-    {SpvBuiltInInstanceId,                {4254, 4255, 4256}},
-    {SpvBuiltInRayGeometryIndexKHR,       {4345, 4346, 4347}},
-    {SpvBuiltInObjectRayDirectionKHR,     {4299, 4300, 4301}},
-    {SpvBuiltInObjectRayOriginKHR,        {4302, 4303, 4304}},
-    {SpvBuiltInObjectToWorldKHR,          {4305, 4306, 4307}},
-    {SpvBuiltInWorldToObjectKHR,          {4434, 4435, 4436}},
-    {SpvBuiltInIncomingRayFlagsKHR,       {4248, 4249, 4250}},
-    {SpvBuiltInRayTminKHR,                {4351, 4352, 4353}},
-    {SpvBuiltInRayTmaxKHR,                {4348, 4349, 4350}},
-    {SpvBuiltInWorldRayDirectionKHR,      {4428, 4429, 4430}},
-    {SpvBuiltInWorldRayOriginKHR,         {4431, 4432, 4433}},
-    {SpvBuiltInLaunchIdKHR,               {4266, 4267, 4268}},
-    {SpvBuiltInLaunchSizeKHR,             {4269, 4270, 4271}},
-    {SpvBuiltInFragInvocationCountEXT,    {4217, 4218, 4219}},
-    {SpvBuiltInFragSizeEXT,               {4220, 4221, 4222}},
-    {SpvBuiltInFragStencilRefEXT,         {4223, 4224, 4225}},
-    {SpvBuiltInFullyCoveredEXT,           {4232, 4233, 4234}},
-    {SpvBuiltInCullMaskKHR,               {6735, 6736, 6737}},
-    {SpvBuiltInBaryCoordKHR,              {4154, 4155, 4156}},
-    {SpvBuiltInBaryCoordNoPerspKHR,       {4160, 4161, 4162}},
+    {spv::BuiltIn::SubgroupEqMask,            {0,    4370, 4371}},
+    {spv::BuiltIn::SubgroupGeMask,            {0,    4372, 4373}},
+    {spv::BuiltIn::SubgroupGtMask,            {0,    4374, 4375}},
+    {spv::BuiltIn::SubgroupLeMask,            {0,    4376, 4377}},
+    {spv::BuiltIn::SubgroupLtMask,            {0,    4378, 4379}},
+    {spv::BuiltIn::SubgroupLocalInvocationId, {0,    4380, 4381}},
+    {spv::BuiltIn::SubgroupSize,              {0,    4382, 4383}},
+    {spv::BuiltIn::GlobalInvocationId,        {4236, 4237, 4238}},
+    {spv::BuiltIn::LocalInvocationId,         {4281, 4282, 4283}},
+    {spv::BuiltIn::NumWorkgroups,             {4296, 4297, 4298}},
+    {spv::BuiltIn::NumSubgroups,              {4293, 4294, 4295}},
+    {spv::BuiltIn::SubgroupId,                {4367, 4368, 4369}},
+    {spv::BuiltIn::WorkgroupId,               {4422, 4423, 4424}},
+    {spv::BuiltIn::HitKindKHR,                {4242, 4243, 4244}},
+    {spv::BuiltIn::HitTNV,                    {4245, 4246, 4247}},
+    {spv::BuiltIn::InstanceCustomIndexKHR,    {4251, 4252, 4253}},
+    {spv::BuiltIn::InstanceId,                {4254, 4255, 4256}},
+    {spv::BuiltIn::RayGeometryIndexKHR,       {4345, 4346, 4347}},
+    {spv::BuiltIn::ObjectRayDirectionKHR,     {4299, 4300, 4301}},
+    {spv::BuiltIn::ObjectRayOriginKHR,        {4302, 4303, 4304}},
+    {spv::BuiltIn::ObjectToWorldKHR,          {4305, 4306, 4307}},
+    {spv::BuiltIn::WorldToObjectKHR,          {4434, 4435, 4436}},
+    {spv::BuiltIn::IncomingRayFlagsKHR,       {4248, 4249, 4250}},
+    {spv::BuiltIn::RayTminKHR,                {4351, 4352, 4353}},
+    {spv::BuiltIn::RayTmaxKHR,                {4348, 4349, 4350}},
+    {spv::BuiltIn::WorldRayDirectionKHR,      {4428, 4429, 4430}},
+    {spv::BuiltIn::WorldRayOriginKHR,         {4431, 4432, 4433}},
+    {spv::BuiltIn::LaunchIdKHR,               {4266, 4267, 4268}},
+    {spv::BuiltIn::LaunchSizeKHR,             {4269, 4270, 4271}},
+    {spv::BuiltIn::FragInvocationCountEXT,    {4217, 4218, 4219}},
+    {spv::BuiltIn::FragSizeEXT,               {4220, 4221, 4222}},
+    {spv::BuiltIn::FragStencilRefEXT,         {4223, 4224, 4225}},
+    {spv::BuiltIn::FullyCoveredEXT,           {4232, 4233, 4234}},
+    {spv::BuiltIn::CullMaskKHR,               {6735, 6736, 6737}},
+    {spv::BuiltIn::BaryCoordKHR,              {4154, 4155, 4156}},
+    {spv::BuiltIn::BaryCoordNoPerspKHR,       {4160, 4161, 4162}},
     // clang-format off
 } };
 
-uint32_t GetVUIDForBuiltin(SpvBuiltIn builtIn, VUIDError type) {
+uint32_t GetVUIDForBuiltin(spv::BuiltIn builtIn, VUIDError type) {
   uint32_t vuid = 0;
   for (const auto& iter: builtinVUIDInfo) {
     if (iter.builtIn == builtIn) {
@@ -180,57 +180,57 @@
   return vuid;
 }
 
-bool IsExecutionModelValidForRtBuiltIn(SpvBuiltIn builtin,
-                                       SpvExecutionModel stage) {
+bool IsExecutionModelValidForRtBuiltIn(spv::BuiltIn builtin,
+                                       spv::ExecutionModel stage) {
   switch (builtin) {
-    case SpvBuiltInHitKindKHR:
-    case SpvBuiltInHitTNV:
-      if (stage == SpvExecutionModelAnyHitKHR ||
-          stage == SpvExecutionModelClosestHitKHR) {
+    case spv::BuiltIn::HitKindKHR:
+    case spv::BuiltIn::HitTNV:
+      if (stage == spv::ExecutionModel::AnyHitKHR ||
+          stage == spv::ExecutionModel::ClosestHitKHR) {
         return true;
       }
       break;
-    case SpvBuiltInInstanceCustomIndexKHR:
-    case SpvBuiltInInstanceId:
-    case SpvBuiltInRayGeometryIndexKHR:
-    case SpvBuiltInObjectRayDirectionKHR:
-    case SpvBuiltInObjectRayOriginKHR:
-    case SpvBuiltInObjectToWorldKHR:
-    case SpvBuiltInWorldToObjectKHR:
+    case spv::BuiltIn::InstanceCustomIndexKHR:
+    case spv::BuiltIn::InstanceId:
+    case spv::BuiltIn::RayGeometryIndexKHR:
+    case spv::BuiltIn::ObjectRayDirectionKHR:
+    case spv::BuiltIn::ObjectRayOriginKHR:
+    case spv::BuiltIn::ObjectToWorldKHR:
+    case spv::BuiltIn::WorldToObjectKHR:
       switch (stage) {
-        case SpvExecutionModelIntersectionKHR:
-        case SpvExecutionModelAnyHitKHR:
-        case SpvExecutionModelClosestHitKHR:
+        case spv::ExecutionModel::IntersectionKHR:
+        case spv::ExecutionModel::AnyHitKHR:
+        case spv::ExecutionModel::ClosestHitKHR:
           return true;
         default:
           return false;
       }
       break;
-    case SpvBuiltInIncomingRayFlagsKHR:
-    case SpvBuiltInRayTminKHR:
-    case SpvBuiltInRayTmaxKHR:
-    case SpvBuiltInWorldRayDirectionKHR:
-    case SpvBuiltInWorldRayOriginKHR:
-    case SpvBuiltInCullMaskKHR:
+    case spv::BuiltIn::IncomingRayFlagsKHR:
+    case spv::BuiltIn::RayTminKHR:
+    case spv::BuiltIn::RayTmaxKHR:
+    case spv::BuiltIn::WorldRayDirectionKHR:
+    case spv::BuiltIn::WorldRayOriginKHR:
+    case spv::BuiltIn::CullMaskKHR:
       switch (stage) {
-        case SpvExecutionModelIntersectionKHR:
-        case SpvExecutionModelAnyHitKHR:
-        case SpvExecutionModelClosestHitKHR:
-        case SpvExecutionModelMissKHR:
+        case spv::ExecutionModel::IntersectionKHR:
+        case spv::ExecutionModel::AnyHitKHR:
+        case spv::ExecutionModel::ClosestHitKHR:
+        case spv::ExecutionModel::MissKHR:
           return true;
         default:
           return false;
       }
       break;
-    case SpvBuiltInLaunchIdKHR:
-    case SpvBuiltInLaunchSizeKHR:
+    case spv::BuiltIn::LaunchIdKHR:
+    case spv::BuiltIn::LaunchSizeKHR:
       switch (stage) {
-        case SpvExecutionModelRayGenerationKHR:
-        case SpvExecutionModelIntersectionKHR:
-        case SpvExecutionModelAnyHitKHR:
-        case SpvExecutionModelClosestHitKHR:
-        case SpvExecutionModelMissKHR:
-        case SpvExecutionModelCallableKHR:
+        case spv::ExecutionModel::RayGenerationKHR:
+        case spv::ExecutionModel::IntersectionKHR:
+        case spv::ExecutionModel::AnyHitKHR:
+        case spv::ExecutionModel::ClosestHitKHR:
+        case spv::ExecutionModel::MissKHR:
+        case spv::ExecutionModel::CallableKHR:
           return true;
         default:
           return false;
@@ -559,7 +559,7 @@
   // |referenced_from_inst| - instruction which references id defined by
   //                          |referenced_inst| from within a function.
   spv_result_t ValidateNotCalledWithExecutionModel(
-      int vuid, const char* comment, SpvExecutionModel execution_model,
+      int vuid, const char* comment, spv::ExecutionModel execution_model,
       const Decoration& decoration, const Instruction& built_in_inst,
       const Instruction& referenced_inst,
       const Instruction& referenced_from_inst);
@@ -642,7 +642,7 @@
       const Decoration& decoration, const Instruction& built_in_inst,
       const Instruction& referenced_inst,
       const Instruction& referenced_from_inst,
-      SpvExecutionModel execution_model = SpvExecutionModelMax) const;
+      spv::ExecutionModel execution_model = spv::ExecutionModel::Max) const;
 
   // Generates strings like "ID <51> (OpTypePointer) uses storage class
   // UniformConstant".
@@ -671,12 +671,12 @@
   const std::vector<uint32_t>* entry_points_ = &no_entry_points;
 
   // Execution models with which the current function can be called.
-  std::set<SpvExecutionModel> execution_models_;
+  std::set<spv::ExecutionModel> execution_models_;
 };
 
 void BuiltInsValidator::Update(const Instruction& inst) {
-  const SpvOp opcode = inst.opcode();
-  if (opcode == SpvOpFunction) {
+  const spv::Op opcode = inst.opcode();
+  if (opcode == spv::Op::OpFunction) {
     // Entering a function.
     assert(function_id_ == 0);
     function_id_ = inst.id();
@@ -691,7 +691,7 @@
     }
   }
 
-  if (opcode == SpvOpFunctionEnd) {
+  if (opcode == spv::Op::OpFunctionEnd) {
     // Exiting a function.
     assert(function_id_ != 0);
     function_id_ = 0;
@@ -704,7 +704,7 @@
     const Decoration& decoration, const Instruction& inst) const {
   std::ostringstream ss;
   if (decoration.struct_member_index() != Decoration::kInvalidMember) {
-    assert(inst.opcode() == SpvOpTypeStruct);
+    assert(inst.opcode() == spv::Op::OpTypeStruct);
     ss << "Member #" << decoration.struct_member_index();
     ss << " of struct ID <" << inst.id() << ">";
   } else {
@@ -716,7 +716,7 @@
 std::string BuiltInsValidator::GetReferenceDesc(
     const Decoration& decoration, const Instruction& built_in_inst,
     const Instruction& referenced_inst, const Instruction& referenced_from_inst,
-    SpvExecutionModel execution_model) const {
+    spv::ExecutionModel execution_model) const {
   std::ostringstream ss;
   ss << GetIdDesc(referenced_from_inst) << " is referencing "
      << GetIdDesc(referenced_inst);
@@ -729,10 +729,10 @@
                                       decoration.params()[0]);
   if (function_id_) {
     ss << " in function <" << function_id_ << ">";
-    if (execution_model != SpvExecutionModelMax) {
+    if (execution_model != spv::ExecutionModel::Max) {
       ss << " called with execution model ";
       ss << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_EXECUTION_MODEL,
-                                          execution_model);
+                                          uint32_t(execution_model));
     }
   }
   ss << ".";
@@ -744,7 +744,7 @@
   std::ostringstream ss;
   ss << GetIdDesc(inst) << " uses storage class ";
   ss << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_STORAGE_CLASS,
-                                      GetStorageClass(inst));
+                                      uint32_t(GetStorageClass(inst)));
   ss << ".";
   return ss.str();
 }
@@ -803,7 +803,7 @@
   }
 
   // Strip the array, if present.
-  if (_.GetIdOpcode(underlying_type) == SpvOpTypeArray) {
+  if (_.GetIdOpcode(underlying_type) == spv::Op::OpTypeArray) {
     underlying_type = _.FindDef(underlying_type)->word(2u);
   }
 
@@ -839,7 +839,7 @@
   }
 
   // Strip the array, if present.
-  if (_.GetIdOpcode(underlying_type) == SpvOpTypeArray) {
+  if (_.GetIdOpcode(underlying_type) == spv::Op::OpTypeArray) {
     underlying_type = _.FindDef(underlying_type)->word(2u);
   }
 
@@ -922,7 +922,7 @@
   }
 
   // Strip the array, if present.
-  if (_.GetIdOpcode(underlying_type) == SpvOpTypeArray) {
+  if (_.GetIdOpcode(underlying_type) == spv::Op::OpTypeArray) {
     underlying_type = _.FindDef(underlying_type)->word(2u);
   }
 
@@ -983,7 +983,7 @@
   }
 
   const Instruction* const type_inst = _.FindDef(underlying_type);
-  if (type_inst->opcode() != SpvOpTypeArray) {
+  if (type_inst->opcode() != spv::Op::OpTypeArray) {
     return diag(GetDefinitionDesc(decoration, inst) + " is not an array.");
   }
 
@@ -1029,9 +1029,9 @@
   }
 
   // Strip an extra layer of arraying if present.
-  if (_.GetIdOpcode(underlying_type) == SpvOpTypeArray) {
+  if (_.GetIdOpcode(underlying_type) == spv::Op::OpTypeArray) {
     uint32_t subtype = _.FindDef(underlying_type)->word(2u);
-    if (_.GetIdOpcode(subtype) == SpvOpTypeArray) {
+    if (_.GetIdOpcode(subtype) == spv::Op::OpTypeArray) {
       underlying_type = subtype;
     }
   }
@@ -1046,7 +1046,7 @@
     const std::function<spv_result_t(const std::string& message)>& diag,
     uint32_t underlying_type) {
   const Instruction* const type_inst = _.FindDef(underlying_type);
-  if (type_inst->opcode() != SpvOpTypeArray) {
+  if (type_inst->opcode() != spv::Op::OpTypeArray) {
     return diag(GetDefinitionDesc(decoration, inst) + " is not an array.");
   }
 
@@ -1107,14 +1107,14 @@
 }
 
 spv_result_t BuiltInsValidator::ValidateNotCalledWithExecutionModel(
-    int vuid, const char* comment, SpvExecutionModel execution_model,
+    int vuid, const char* comment, spv::ExecutionModel execution_model,
     const Decoration& decoration, const Instruction& built_in_inst,
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (function_id_) {
     if (execution_models_.count(execution_model)) {
       const char* execution_model_str = _.grammar().lookupOperandName(
-          SPV_OPERAND_TYPE_EXECUTION_MODEL, execution_model);
+          SPV_OPERAND_TYPE_EXECUTION_MODEL, uint32_t(execution_model));
       const char* built_in_str = _.grammar().lookupOperandName(
           SPV_OPERAND_TYPE_BUILT_IN, decoration.params()[0]);
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
@@ -1149,11 +1149,11 @@
     const Instruction& referenced_from_inst) {
   uint32_t operand = decoration.params()[0];
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput &&
-        storage_class != SpvStorageClassOutput) {
-      uint32_t vuid = (decoration.params()[0] == SpvBuiltInClipDistance) ? 4190 : 4199;
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input &&
+        storage_class != spv::StorageClass::Output) {
+      uint32_t vuid = (spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::ClipDistance) ? 4190 : 4199;
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(vuid) << "Vulkan spec allows BuiltIn "
              << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -1165,54 +1165,54 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    if (storage_class == SpvStorageClassInput) {
+    if (storage_class == spv::StorageClass::Input) {
       assert(function_id_ == 0);
-      uint32_t vuid = (decoration.params()[0] == SpvBuiltInClipDistance) ? 4188 : 4197;
+      uint32_t vuid = (spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::ClipDistance) ? 4188 : 4197;
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, vuid,
           "Vulkan spec doesn't allow BuiltIn ClipDistance/CullDistance to be "
           "used for variables with Input storage class if execution model is "
           "Vertex.",
-          SpvExecutionModelVertex, decoration, built_in_inst,
+          spv::ExecutionModel::Vertex, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, vuid,
           "Vulkan spec doesn't allow BuiltIn ClipDistance/CullDistance to be "
           "used for variables with Input storage class if execution model is "
           "MeshNV.",
-          SpvExecutionModelMeshNV, decoration, built_in_inst,
+          spv::ExecutionModel::MeshNV, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, vuid,
           "Vulkan spec doesn't allow BuiltIn ClipDistance/CullDistance to be "
           "used for variables with Input storage class if execution model is "
           "MeshEXT.",
-          SpvExecutionModelMeshEXT, decoration, built_in_inst,
+          spv::ExecutionModel::MeshEXT, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
     }
 
-    if (storage_class == SpvStorageClassOutput) {
+    if (storage_class == spv::StorageClass::Output) {
       assert(function_id_ == 0);
-      uint32_t vuid = (decoration.params()[0] == SpvBuiltInClipDistance) ? 4189 : 4198;
+      uint32_t vuid = (spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::ClipDistance) ? 4189 : 4198;
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, vuid,
           "Vulkan spec doesn't allow BuiltIn ClipDistance/CullDistance to be "
           "used for variables with Output storage class if execution model is "
           "Fragment.",
-          SpvExecutionModelFragment, decoration, built_in_inst,
+          spv::ExecutionModel::Fragment, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
       switch (execution_model) {
-        case SpvExecutionModelFragment:
-        case SpvExecutionModelVertex: {
+        case spv::ExecutionModel::Fragment:
+        case spv::ExecutionModel::Vertex: {
           if (spv_result_t error = ValidateF32Arr(
                   decoration, built_in_inst, /* Any number of components */ 0,
                   [this, &decoration, &referenced_from_inst](
                       const std::string& message) -> spv_result_t {
                     uint32_t vuid =
-                        (decoration.params()[0] == SpvBuiltInClipDistance)
+                        (spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::ClipDistance)
                             ? 4191
                             : 4200;
                     return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
@@ -1228,11 +1228,11 @@
           }
           break;
         }
-        case SpvExecutionModelTessellationControl:
-        case SpvExecutionModelTessellationEvaluation:
-        case SpvExecutionModelGeometry:
-        case SpvExecutionModelMeshNV:
-        case SpvExecutionModelMeshEXT: {
+        case spv::ExecutionModel::TessellationControl:
+        case spv::ExecutionModel::TessellationEvaluation:
+        case spv::ExecutionModel::Geometry:
+        case spv::ExecutionModel::MeshNV:
+        case spv::ExecutionModel::MeshEXT: {
           if (decoration.struct_member_index() != Decoration::kInvalidMember) {
             // The outer level of array is applied on the variable.
             if (spv_result_t error = ValidateF32Arr(
@@ -1240,7 +1240,7 @@
                     [this, &decoration, &referenced_from_inst](
                         const std::string& message) -> spv_result_t {
                       uint32_t vuid =
-                          (decoration.params()[0] == SpvBuiltInClipDistance)
+                          (spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::ClipDistance)
                               ? 4191
                               : 4200;
                       return _.diag(SPV_ERROR_INVALID_DATA,
@@ -1261,7 +1261,7 @@
                     [this, &decoration, &referenced_from_inst](
                         const std::string& message) -> spv_result_t {
                       uint32_t vuid =
-                          (decoration.params()[0] == SpvBuiltInClipDistance)
+                          (spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::ClipDistance)
                               ? 4191
                               : 4200;
                       return _.diag(SPV_ERROR_INVALID_DATA,
@@ -1282,7 +1282,7 @@
 
         default: {
           uint32_t vuid =
-              (decoration.params()[0] == SpvBuiltInClipDistance) ? 4187 : 4196;
+              (spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::ClipDistance) ? 4187 : 4196;
           return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                  << _.VkErrorID(vuid) << "Vulkan spec allows BuiltIn "
                  << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -1335,9 +1335,9 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4211) << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn FragCoord to be only used for "
@@ -1347,8 +1347,8 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelFragment) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Fragment) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4210)
                << spvLogStringForEnv(_.context()->target_env)
@@ -1396,9 +1396,9 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassOutput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Output) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4214) << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn FragDepth to be only used for "
@@ -1408,8 +1408,8 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelFragment) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Fragment) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4213)
                << spvLogStringForEnv(_.context()->target_env)
@@ -1424,7 +1424,7 @@
       // Every entry point from which this function is called needs to have
       // Execution Mode DepthReplacing.
       const auto* modes = _.GetExecutionModes(entry_point);
-      if (!modes || !modes->count(SpvExecutionModeDepthReplacing)) {
+      if (!modes || !modes->count(spv::ExecutionMode::DepthReplacing)) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4216)
                << spvLogStringForEnv(_.context()->target_env)
@@ -1472,9 +1472,9 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4230) << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn FrontFacing to be only used for "
@@ -1484,8 +1484,8 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelFragment) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Fragment) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4229)
                << spvLogStringForEnv(_.context()->target_env)
@@ -1532,9 +1532,9 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4240)
              << "Vulkan spec allows BuiltIn HelperInvocation to be only used "
@@ -1544,8 +1544,8 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelFragment) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Fragment) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4239)
                << "Vulkan spec allows BuiltIn HelperInvocation to be used only "
@@ -1592,9 +1592,9 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4258)
              << "Vulkan spec allows BuiltIn InvocationId to be only used for "
@@ -1604,9 +1604,9 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelTessellationControl &&
-          execution_model != SpvExecutionModelGeometry) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::TessellationControl &&
+          execution_model != spv::ExecutionModel::Geometry) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4257)
                << "Vulkan spec allows BuiltIn InvocationId to be used only "
@@ -1653,9 +1653,9 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4264) << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn InstanceIndex to be only used for "
@@ -1665,8 +1665,8 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelVertex) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Vertex) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4263)
                << spvLogStringForEnv(_.context()->target_env)
@@ -1713,9 +1713,9 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4309)
              << "Vulkan spec allows BuiltIn PatchVertices to be only used for "
@@ -1725,9 +1725,9 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelTessellationControl &&
-          execution_model != SpvExecutionModelTessellationEvaluation) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::TessellationControl &&
+          execution_model != spv::ExecutionModel::TessellationEvaluation) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4308)
                << "Vulkan spec allows BuiltIn PatchVertices to be used only "
@@ -1775,9 +1775,9 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4312)
              << "Vulkan spec allows BuiltIn PointCoord to be only used for "
@@ -1787,8 +1787,8 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelFragment) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Fragment) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4311)
                << "Vulkan spec allows BuiltIn PointCoord to be used only with "
@@ -1820,10 +1820,10 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput &&
-        storage_class != SpvStorageClassOutput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input &&
+        storage_class != spv::StorageClass::Output) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4316)
              << "Vulkan spec allows BuiltIn PointSize to be only used for "
@@ -1833,20 +1833,20 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    if (storage_class == SpvStorageClassInput) {
+    if (storage_class == spv::StorageClass::Input) {
       assert(function_id_ == 0);
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, 4315,
           "Vulkan spec doesn't allow BuiltIn PointSize to be used for "
           "variables with Input storage class if execution model is "
           "Vertex.",
-          SpvExecutionModelVertex, decoration, built_in_inst,
+          spv::ExecutionModel::Vertex, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
       switch (execution_model) {
-        case SpvExecutionModelVertex: {
+        case spv::ExecutionModel::Vertex: {
           if (spv_result_t error = ValidateF32(
                   decoration, built_in_inst,
                   [this, &referenced_from_inst](
@@ -1861,11 +1861,11 @@
           }
           break;
         }
-        case SpvExecutionModelTessellationControl:
-        case SpvExecutionModelTessellationEvaluation:
-        case SpvExecutionModelGeometry:
-        case SpvExecutionModelMeshNV:
-        case SpvExecutionModelMeshEXT: {
+        case spv::ExecutionModel::TessellationControl:
+        case spv::ExecutionModel::TessellationEvaluation:
+        case spv::ExecutionModel::Geometry:
+        case spv::ExecutionModel::MeshNV:
+        case spv::ExecutionModel::MeshEXT: {
           // PointSize can be a per-vertex variable for tessellation control,
           // tessellation evaluation and geometry shader stages. In such cases
           // variables will have an array of 32-bit floats.
@@ -1938,10 +1938,10 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput &&
-        storage_class != SpvStorageClassOutput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input &&
+        storage_class != spv::StorageClass::Output) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4320) << "Vulkan spec allows BuiltIn Position to be only used for "
                 "variables with Input or Output storage class. "
@@ -1950,34 +1950,34 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    if (storage_class == SpvStorageClassInput) {
+    if (storage_class == spv::StorageClass::Input) {
       assert(function_id_ == 0);
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, 4319,
           "Vulkan spec doesn't allow BuiltIn Position to be used "
           "for variables "
           "with Input storage class if execution model is Vertex.",
-          SpvExecutionModelVertex, decoration, built_in_inst,
+          spv::ExecutionModel::Vertex, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, 4319,
           "Vulkan spec doesn't allow BuiltIn Position to be used "
           "for variables "
           "with Input storage class if execution model is MeshNV.",
-          SpvExecutionModelMeshNV, decoration, built_in_inst,
+          spv::ExecutionModel::MeshNV, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, 4319,
           "Vulkan spec doesn't allow BuiltIn Position to be used "
           "for variables "
           "with Input storage class if execution model is MeshEXT.",
-          SpvExecutionModelMeshEXT, decoration, built_in_inst,
+          spv::ExecutionModel::MeshEXT, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
       switch (execution_model) {
-        case SpvExecutionModelVertex: {
+        case spv::ExecutionModel::Vertex: {
           if (spv_result_t error = ValidateF32Vec(
                   decoration, built_in_inst, 4,
                   [this, &referenced_from_inst](
@@ -1993,11 +1993,11 @@
           }
           break;
         }
-        case SpvExecutionModelGeometry:
-        case SpvExecutionModelTessellationControl:
-        case SpvExecutionModelTessellationEvaluation:
-        case SpvExecutionModelMeshNV:
-        case SpvExecutionModelMeshEXT: {
+        case spv::ExecutionModel::Geometry:
+        case spv::ExecutionModel::TessellationControl:
+        case spv::ExecutionModel::TessellationEvaluation:
+        case spv::ExecutionModel::MeshNV:
+        case spv::ExecutionModel::MeshEXT: {
           // Position can be a per-vertex variable for tessellation control,
           // tessellation evaluation, geometry and mesh shader stages. In such
           // cases variables will have an array of 4-component 32-bit float
@@ -2103,10 +2103,10 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput &&
-        storage_class != SpvStorageClassOutput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input &&
+        storage_class != spv::StorageClass::Output) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << "Vulkan spec allows BuiltIn PrimitiveId to be only used for "
                 "variables with Input or Output storage class. "
@@ -2115,63 +2115,63 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    if (storage_class == SpvStorageClassOutput) {
+    if (storage_class == spv::StorageClass::Output) {
       assert(function_id_ == 0);
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, 4334,
           "Vulkan spec doesn't allow BuiltIn PrimitiveId to be used for "
           "variables with Output storage class if execution model is "
           "TessellationControl.",
-          SpvExecutionModelTessellationControl, decoration, built_in_inst,
+          spv::ExecutionModel::TessellationControl, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, 4334,
           "Vulkan spec doesn't allow BuiltIn PrimitiveId to be used for "
           "variables with Output storage class if execution model is "
           "TessellationEvaluation.",
-          SpvExecutionModelTessellationEvaluation, decoration, built_in_inst,
+          spv::ExecutionModel::TessellationEvaluation, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, 4334,
           "Vulkan spec doesn't allow BuiltIn PrimitiveId to be used for "
           "variables with Output storage class if execution model is "
           "Fragment.",
-          SpvExecutionModelFragment, decoration, built_in_inst,
+          spv::ExecutionModel::Fragment, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, 4334,
           "Vulkan spec doesn't allow BuiltIn PrimitiveId to be used for "
           "variables with Output storage class if execution model is "
           "IntersectionKHR.",
-          SpvExecutionModelIntersectionKHR, decoration, built_in_inst,
+          spv::ExecutionModel::IntersectionKHR, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, 4334,
           "Vulkan spec doesn't allow BuiltIn PrimitiveId to be used for "
           "variables with Output storage class if execution model is "
           "AnyHitKHR.",
-          SpvExecutionModelAnyHitKHR, decoration, built_in_inst,
+          spv::ExecutionModel::AnyHitKHR, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, 4334,
           "Vulkan spec doesn't allow BuiltIn PrimitiveId to be used for "
           "variables with Output storage class if execution model is "
           "ClosestHitKHR.",
-          SpvExecutionModelClosestHitKHR, decoration, built_in_inst,
+          spv::ExecutionModel::ClosestHitKHR, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
       switch (execution_model) {
-        case SpvExecutionModelFragment:
-        case SpvExecutionModelTessellationControl:
-        case SpvExecutionModelTessellationEvaluation:
-        case SpvExecutionModelGeometry:
-        case SpvExecutionModelMeshNV:
-        case SpvExecutionModelMeshEXT:
-        case SpvExecutionModelIntersectionKHR:
-        case SpvExecutionModelAnyHitKHR:
-        case SpvExecutionModelClosestHitKHR: {
+        case spv::ExecutionModel::Fragment:
+        case spv::ExecutionModel::TessellationControl:
+        case spv::ExecutionModel::TessellationEvaluation:
+        case spv::ExecutionModel::Geometry:
+        case spv::ExecutionModel::MeshNV:
+        case spv::ExecutionModel::MeshEXT:
+        case spv::ExecutionModel::IntersectionKHR:
+        case spv::ExecutionModel::AnyHitKHR:
+        case spv::ExecutionModel::ClosestHitKHR: {
           // Ok.
           break;
         }
@@ -2225,9 +2225,9 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4355)
              << "Vulkan spec allows BuiltIn SampleId to be only used for "
@@ -2237,8 +2237,8 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelFragment) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Fragment) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4354)
                << "Vulkan spec allows BuiltIn SampleId to be used only with "
@@ -2284,10 +2284,10 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput &&
-        storage_class != SpvStorageClassOutput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input &&
+        storage_class != spv::StorageClass::Output) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4358)
              << "Vulkan spec allows BuiltIn SampleMask to be only used for "
@@ -2297,8 +2297,8 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelFragment) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Fragment) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4357)
                << "Vulkan spec allows BuiltIn SampleMask to be used only "
@@ -2346,9 +2346,9 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4361)
              << "Vulkan spec allows BuiltIn SamplePosition to be only used "
@@ -2359,8 +2359,8 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelFragment) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Fragment) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4360)
                << "Vulkan spec allows BuiltIn SamplePosition to be used only "
@@ -2408,9 +2408,9 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4388)
              << "Vulkan spec allows BuiltIn TessCoord to be only used for "
@@ -2420,8 +2420,8 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelTessellationEvaluation) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::TessellationEvaluation) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4387)
                << "Vulkan spec allows BuiltIn TessCoord to be used only with "
@@ -2490,10 +2490,10 @@
     const Instruction& referenced_from_inst) {
   uint32_t operand = decoration.params()[0];
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput &&
-        storage_class != SpvStorageClassOutput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input &&
+        storage_class != spv::StorageClass::Output) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << "Vulkan spec allows BuiltIn "
              << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -2505,42 +2505,42 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    if (storage_class == SpvStorageClassInput) {
+    if (storage_class == spv::StorageClass::Input) {
       assert(function_id_ == 0);
-      uint32_t vuid = (decoration.params()[0] == SpvBuiltInTessLevelOuter) ? 4391 : 4395;
+      uint32_t vuid = (spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::TessLevelOuter) ? 4391 : 4395;
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, vuid,
           "Vulkan spec doesn't allow TessLevelOuter/TessLevelInner to be "
           "used "
           "for variables with Input storage class if execution model is "
           "TessellationControl.",
-          SpvExecutionModelTessellationControl, decoration, built_in_inst,
+          spv::ExecutionModel::TessellationControl, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
     }
 
-    if (storage_class == SpvStorageClassOutput) {
+    if (storage_class == spv::StorageClass::Output) {
       assert(function_id_ == 0);
-      uint32_t vuid = (decoration.params()[0] == SpvBuiltInTessLevelOuter) ? 4392 : 4396;
+      uint32_t vuid = (spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::TessLevelOuter) ? 4392 : 4396;
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind(
           &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, vuid,
           "Vulkan spec doesn't allow TessLevelOuter/TessLevelInner to be "
           "used "
           "for variables with Output storage class if execution model is "
           "TessellationEvaluation.",
-          SpvExecutionModelTessellationEvaluation, decoration, built_in_inst,
+          spv::ExecutionModel::TessellationEvaluation, decoration, built_in_inst,
           referenced_from_inst, std::placeholders::_1));
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
       switch (execution_model) {
-        case SpvExecutionModelTessellationControl:
-        case SpvExecutionModelTessellationEvaluation: {
+        case spv::ExecutionModel::TessellationControl:
+        case spv::ExecutionModel::TessellationEvaluation: {
           // Ok.
           break;
         }
 
         default: {
-          uint32_t vuid = (operand == SpvBuiltInTessLevelOuter) ? 4390 : 4394;
+          uint32_t vuid = (spv::BuiltIn(operand) == spv::BuiltIn::TessLevelOuter) ? 4390 : 4394;
           return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                  << _.VkErrorID(vuid) << "Vulkan spec allows BuiltIn "
                  << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -2623,9 +2623,9 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4399) << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn VertexIndex to be only used for "
@@ -2635,8 +2635,8 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelVertex) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Vertex) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4398)
                << spvLogStringForEnv(_.context()->target_env)
@@ -2670,7 +2670,7 @@
               [this, &decoration,
                &inst](const std::string& message) -> spv_result_t {
                 uint32_t vuid =
-                    (decoration.params()[0] == SpvBuiltInLayer) ? 4276 : 4408;
+                    (spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::Layer) ? 4276 : 4408;
                 return _.diag(SPV_ERROR_INVALID_DATA, &inst)
                        << _.VkErrorID(vuid)
                        << "According to the Vulkan spec BuiltIn "
@@ -2687,7 +2687,7 @@
               [this, &decoration,
                &inst](const std::string& message) -> spv_result_t {
                 uint32_t vuid =
-                    (decoration.params()[0] == SpvBuiltInLayer) ? 4276 : 4408;
+                    (spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::Layer) ? 4276 : 4408;
                 return _.diag(SPV_ERROR_INVALID_DATA, &inst)
                        << _.VkErrorID(vuid)
                        << "According to the Vulkan spec BuiltIn "
@@ -2711,10 +2711,10 @@
     const Instruction& referenced_from_inst) {
   uint32_t operand = decoration.params()[0];
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput &&
-        storage_class != SpvStorageClassOutput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input &&
+        storage_class != spv::StorageClass::Output) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << "Vulkan spec allows BuiltIn "
              << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -2726,15 +2726,15 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    if (storage_class == SpvStorageClassInput) {
+    if (storage_class == spv::StorageClass::Input) {
       assert(function_id_ == 0);
       for (const auto em :
-           {SpvExecutionModelVertex, SpvExecutionModelTessellationEvaluation,
-            SpvExecutionModelGeometry, SpvExecutionModelMeshNV,
-            SpvExecutionModelMeshEXT}) {
+           {spv::ExecutionModel::Vertex, spv::ExecutionModel::TessellationEvaluation,
+            spv::ExecutionModel::Geometry, spv::ExecutionModel::MeshNV,
+            spv::ExecutionModel::MeshEXT}) {
         id_to_at_reference_checks_[referenced_from_inst.id()].push_back(
             std::bind(&BuiltInsValidator::ValidateNotCalledWithExecutionModel,
-                      this, ((operand == SpvBuiltInLayer) ? 4274 : 4406),
+                      this, ((spv::BuiltIn(operand) == spv::BuiltIn::Layer) ? 4274 : 4406),
                       "Vulkan spec doesn't allow BuiltIn Layer and "
                       "ViewportIndex to be "
                       "used for variables with Input storage class if "
@@ -2745,46 +2745,46 @@
       }
     }
 
-    if (storage_class == SpvStorageClassOutput) {
+    if (storage_class == spv::StorageClass::Output) {
       assert(function_id_ == 0);
       id_to_at_reference_checks_[referenced_from_inst.id()].push_back(
           std::bind(&BuiltInsValidator::ValidateNotCalledWithExecutionModel,
-                    this, ((operand == SpvBuiltInLayer) ? 4275 : 4407),
+                    this, ((spv::BuiltIn(operand) == spv::BuiltIn::Layer) ? 4275 : 4407),
                     "Vulkan spec doesn't allow BuiltIn Layer and "
                     "ViewportIndex to be "
                     "used for variables with Output storage class if "
                     "execution model is "
                     "Fragment.",
-                    SpvExecutionModelFragment, decoration, built_in_inst,
+                    spv::ExecutionModel::Fragment, decoration, built_in_inst,
                     referenced_from_inst, std::placeholders::_1));
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
       switch (execution_model) {
-        case SpvExecutionModelGeometry:
-        case SpvExecutionModelFragment:
-        case SpvExecutionModelMeshNV:
-        case SpvExecutionModelMeshEXT:
+        case spv::ExecutionModel::Geometry:
+        case spv::ExecutionModel::Fragment:
+        case spv::ExecutionModel::MeshNV:
+        case spv::ExecutionModel::MeshEXT:
           // Ok.
           break;
-        case SpvExecutionModelVertex:
-        case SpvExecutionModelTessellationEvaluation: {
-          if (!_.HasCapability(SpvCapabilityShaderViewportIndexLayerEXT)) {
-            if (operand == SpvBuiltInViewportIndex &&
-                _.HasCapability(SpvCapabilityShaderViewportIndex))
+        case spv::ExecutionModel::Vertex:
+        case spv::ExecutionModel::TessellationEvaluation: {
+          if (!_.HasCapability(spv::Capability::ShaderViewportIndexLayerEXT)) {
+            if (spv::BuiltIn(operand) == spv::BuiltIn::ViewportIndex &&
+                _.HasCapability(spv::Capability::ShaderViewportIndex))
               break;  // Ok
-            if (operand == SpvBuiltInLayer &&
-                _.HasCapability(SpvCapabilityShaderLayer))
+            if (spv::BuiltIn(operand) == spv::BuiltIn::Layer &&
+                _.HasCapability(spv::Capability::ShaderLayer))
               break;  // Ok
 
             const char* capability = "ShaderViewportIndexLayerEXT";
 
-            if (operand == SpvBuiltInViewportIndex)
+            if (spv::BuiltIn(operand) == spv::BuiltIn::ViewportIndex)
               capability = "ShaderViewportIndexLayerEXT or ShaderViewportIndex";
-            if (operand == SpvBuiltInLayer)
+            if (spv::BuiltIn(operand) == spv::BuiltIn::Layer)
               capability = "ShaderViewportIndexLayerEXT or ShaderLayer";
 
-            uint32_t vuid = (operand == SpvBuiltInLayer) ? 4273 : 4405;
+            uint32_t vuid = (spv::BuiltIn(operand) == spv::BuiltIn::Layer) ? 4273 : 4405;
             return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                    << _.VkErrorID(vuid) << "Using BuiltIn "
                    << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -2795,7 +2795,7 @@
           break;
         }
         default: {
-          uint32_t vuid = (operand == SpvBuiltInLayer) ? 4272 : 4404;
+          uint32_t vuid = (spv::BuiltIn(operand) == spv::BuiltIn::Layer) ? 4272 : 4404;
           return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                  << _.VkErrorID(vuid) << "Vulkan spec allows BuiltIn "
                  << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -2823,7 +2823,7 @@
 spv_result_t BuiltInsValidator::ValidateFragmentShaderF32Vec3InputAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
     if (spv_result_t error = ValidateF32Vec(
             decoration, inst, 3,
             [this, &inst, builtin](const std::string& message) -> spv_result_t {
@@ -2833,7 +2833,7 @@
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn "
                      << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                                      builtin)
+                                                      uint32_t(builtin))
                      << " variable needs to be a 3-component 32-bit float "
                         "vector. "
                      << message;
@@ -2853,29 +2853,29 @@
     const Instruction& referenced_from_inst) {
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(vuid) << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
              << " to be only used for variables with Input storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                  referenced_from_inst)
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelFragment) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Fragment) {
         uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(vuid)
                << spvLogStringForEnv(_.context()->target_env)
                << " spec allows BuiltIn "
-               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
                << " to be used only with Fragment execution model. "
                << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                    referenced_from_inst, execution_model);
@@ -2897,7 +2897,7 @@
 spv_result_t BuiltInsValidator::ValidateComputeShaderI32Vec3InputAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
     if (spv_result_t error = ValidateI32Vec(
             decoration, inst, 3,
             [this, &inst, builtin](const std::string& message) -> spv_result_t {
@@ -2907,7 +2907,7 @@
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn "
                      << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                                      builtin)
+                                                      uint32_t(builtin))
                      << " variable needs to be a 3-component 32-bit int "
                         "vector. "
                      << message;
@@ -2926,27 +2926,27 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(vuid) << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
              << " to be only used for variables with Input storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                  referenced_from_inst)
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      bool has_vulkan_model = execution_model == SpvExecutionModelGLCompute ||
-                              execution_model == SpvExecutionModelTaskNV ||
-                              execution_model == SpvExecutionModelMeshNV ||
-                              execution_model == SpvExecutionModelTaskEXT ||
-                              execution_model == SpvExecutionModelMeshEXT;
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      bool has_vulkan_model = execution_model == spv::ExecutionModel::GLCompute ||
+                              execution_model == spv::ExecutionModel::TaskNV ||
+                              execution_model == spv::ExecutionModel::MeshNV ||
+                              execution_model == spv::ExecutionModel::TaskEXT ||
+                              execution_model == spv::ExecutionModel::MeshEXT;
 
       if (spvIsVulkanEnv(_.context()->target_env) && !has_vulkan_model) {
         uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
@@ -2954,7 +2954,7 @@
                << _.VkErrorID(vuid)
                << spvLogStringForEnv(_.context()->target_env)
                << " spec allows BuiltIn "
-               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
                << " to be used only with GLCompute, MeshNV, TaskNV, MeshEXT or"
                << " TaskEXT execution model. "
                << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
@@ -2977,11 +2977,11 @@
 spv_result_t BuiltInsValidator::ValidateComputeI32InputAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
     if (decoration.struct_member_index() != Decoration::kInvalidMember) {
       return _.diag(SPV_ERROR_INVALID_DATA, &inst)
              << "BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
              << " cannot be used as a member decoration ";
     }
     if (spv_result_t error = ValidateI32(
@@ -2993,7 +2993,7 @@
                      << "According to the "
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn "
-                     << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+                     << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
                      << " variable needs to be a 32-bit int "
                         "vector. "
                      << message;
@@ -3011,35 +3011,35 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(vuid)
              << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
              << " to be only used for variables with Input storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                  referenced_from_inst)
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      bool has_vulkan_model = execution_model == SpvExecutionModelGLCompute ||
-                              execution_model == SpvExecutionModelTaskNV ||
-                              execution_model == SpvExecutionModelMeshNV ||
-                              execution_model == SpvExecutionModelTaskEXT ||
-                              execution_model == SpvExecutionModelMeshEXT;
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      bool has_vulkan_model = execution_model == spv::ExecutionModel::GLCompute ||
+                              execution_model == spv::ExecutionModel::TaskNV ||
+                              execution_model == spv::ExecutionModel::MeshNV ||
+                              execution_model == spv::ExecutionModel::TaskEXT ||
+                              execution_model == spv::ExecutionModel::MeshEXT;
       if (spvIsVulkanEnv(_.context()->target_env) && !has_vulkan_model) {
         uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(vuid)
                << spvLogStringForEnv(_.context()->target_env)
                << " spec allows BuiltIn "
-               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
                << " to be used only with GLCompute, MeshNV, TaskNV, MeshEXT or "
                << "TaskEXT execution model. "
                << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
@@ -3062,11 +3062,11 @@
 spv_result_t BuiltInsValidator::ValidateI32InputAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
     if (decoration.struct_member_index() != Decoration::kInvalidMember) {
       return _.diag(SPV_ERROR_INVALID_DATA, &inst)
              << "BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
              << " cannot be used as a member decoration ";
     }
     if (spv_result_t error = ValidateI32(
@@ -3078,21 +3078,21 @@
                      << "According to the "
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn "
-                     << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+                     << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
                      << " variable needs to be a 32-bit int. " << message;
             })) {
       return error;
     }
 
-    const SpvStorageClass storage_class = GetStorageClass(inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
       return _.diag(SPV_ERROR_INVALID_DATA, &inst)
              << _.VkErrorID(vuid)
              << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
              << " to be only used for variables with Input storage class. "
              << GetReferenceDesc(decoration, inst, inst, inst) << " "
              << GetStorageClassDesc(inst);
@@ -3105,11 +3105,11 @@
 spv_result_t BuiltInsValidator::ValidateI32Vec4InputAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
     if (decoration.struct_member_index() != Decoration::kInvalidMember) {
       return _.diag(SPV_ERROR_INVALID_DATA, &inst)
              << "BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
              << " cannot be used as a member decoration ";
     }
     if (spv_result_t error = ValidateI32Vec(
@@ -3121,7 +3121,7 @@
                      << "According to the "
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn "
-                     << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+                     << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
                      << " variable needs to be a 4-component 32-bit int "
                         "vector. "
                      << message;
@@ -3129,15 +3129,15 @@
       return error;
     }
 
-    const SpvStorageClass storage_class = GetStorageClass(inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
       return _.diag(SPV_ERROR_INVALID_DATA, &inst)
              << _.VkErrorID(vuid)
              << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
              << " to be only used for variables with Input storage class. "
              << GetReferenceDesc(decoration, inst, inst, inst) << " "
              << GetStorageClassDesc(inst);
@@ -3182,12 +3182,12 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelGLCompute &&
-          execution_model != SpvExecutionModelTaskNV &&
-          execution_model != SpvExecutionModelMeshNV &&
-          execution_model != SpvExecutionModelTaskEXT &&
-          execution_model != SpvExecutionModelMeshEXT) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::GLCompute &&
+          execution_model != spv::ExecutionModel::TaskNV &&
+          execution_model != spv::ExecutionModel::MeshNV &&
+          execution_model != spv::ExecutionModel::TaskEXT &&
+          execution_model != spv::ExecutionModel::MeshEXT) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4425)
                << spvLogStringForEnv(_.context()->target_env)
@@ -3219,7 +3219,7 @@
             decoration, inst,
             [this, &inst,
              &decoration](const std::string& message) -> spv_result_t {
-              uint32_t vuid = (decoration.params()[0] == SpvBuiltInBaseInstance)
+              uint32_t vuid = (spv::BuiltIn(decoration.params()[0]) == spv::BuiltIn::BaseInstance)
                                   ? 4183
                                   : 4186;
               return _.diag(SPV_ERROR_INVALID_DATA, &inst)
@@ -3243,10 +3243,10 @@
     const Instruction& referenced_from_inst) {
   uint32_t operand = decoration.params()[0];
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
-      uint32_t vuid = (operand == SpvBuiltInBaseInstance) ? 4182 : 4185;
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
+      uint32_t vuid = (spv::BuiltIn(operand) == spv::BuiltIn::BaseInstance) ? 4182 : 4185;
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(vuid) << "Vulkan spec allows BuiltIn "
              << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -3257,9 +3257,9 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelVertex) {
-        uint32_t vuid = (operand == SpvBuiltInBaseInstance) ? 4181 : 4184;
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Vertex) {
+        uint32_t vuid = (spv::BuiltIn(operand) == spv::BuiltIn::BaseInstance) ? 4181 : 4184;
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(vuid) << "Vulkan spec allows BuiltIn "
                << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -3310,9 +3310,9 @@
     const Instruction& referenced_from_inst) {
   uint32_t operand = decoration.params()[0];
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4208) << "Vulkan spec allows BuiltIn "
              << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -3323,12 +3323,12 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelVertex &&
-          execution_model != SpvExecutionModelMeshNV &&
-          execution_model != SpvExecutionModelTaskNV &&
-          execution_model != SpvExecutionModelMeshEXT &&
-          execution_model != SpvExecutionModelTaskEXT) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Vertex &&
+          execution_model != spv::ExecutionModel::MeshNV &&
+          execution_model != spv::ExecutionModel::TaskNV &&
+          execution_model != spv::ExecutionModel::MeshEXT &&
+          execution_model != spv::ExecutionModel::TaskEXT) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4207) << "Vulkan spec allows BuiltIn "
                << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -3380,9 +3380,9 @@
     const Instruction& referenced_from_inst) {
   uint32_t operand = decoration.params()[0];
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4402) << "Vulkan spec allows BuiltIn "
              << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -3393,8 +3393,8 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model == SpvExecutionModelGLCompute) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model == spv::ExecutionModel::GLCompute) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4401) << "Vulkan spec allows BuiltIn "
                << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -3444,9 +3444,9 @@
     const Instruction& referenced_from_inst) {
   uint32_t operand = decoration.params()[0];
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4205) << "Vulkan spec allows BuiltIn "
              << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -3472,7 +3472,7 @@
                                             const Instruction& inst) {
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
     if (spv_result_t error = ValidateI32(
             decoration, inst,
             [this, &inst, &builtin](const std::string& message) -> spv_result_t {
@@ -3482,7 +3482,7 @@
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn "
                      << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                                      builtin)
+                                                      uint32_t(builtin))
                      << " variable needs to be a 32-bit int scalar. "
                      << message;
             })) {
@@ -3499,29 +3499,29 @@
     const Instruction& referenced_from_inst) {
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(vuid) << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
              << " to be only used for variables with Input storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                  referenced_from_inst)
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelFragment) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Fragment) {
         uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(vuid)
                << spvLogStringForEnv(_.context()->target_env)
                << " spec allows BuiltIn "
-               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
                << " to be used only with Fragment execution model. "
                << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                    referenced_from_inst, execution_model);
@@ -3542,7 +3542,7 @@
 spv_result_t BuiltInsValidator::ValidateFragSizeAtDefinition(const Decoration& decoration,
                                             const Instruction& inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
     if (spv_result_t error = ValidateI32Vec(
             decoration, inst, 2,
             [this, &inst, &builtin](const std::string& message) -> spv_result_t {
@@ -3552,7 +3552,7 @@
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn "
                      << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                                      builtin)
+                                                      uint32_t(builtin))
                      << " variable needs to be a 2-component 32-bit int vector. "
                      << message;
             })) {
@@ -3569,29 +3569,29 @@
     const Instruction& referenced_from_inst) {
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(vuid) << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
              << " to be only used for variables with Input storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                  referenced_from_inst)
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelFragment) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Fragment) {
         uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(vuid)
                << spvLogStringForEnv(_.context()->target_env)
                << " spec allows BuiltIn "
-               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
                << " to be used only with Fragment execution model. "
                << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                    referenced_from_inst, execution_model);
@@ -3612,7 +3612,7 @@
 spv_result_t BuiltInsValidator::ValidateFragStencilRefAtDefinition(const Decoration& decoration,
                                             const Instruction& inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
     if (spv_result_t error = ValidateI(
             decoration, inst,
             [this, &inst, &builtin](const std::string& message) -> spv_result_t {
@@ -3622,7 +3622,7 @@
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn "
                      << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                                      builtin)
+                                                      uint32_t(builtin))
                      << " variable needs to be a int scalar. "
                      << message;
             })) {
@@ -3639,29 +3639,29 @@
     const Instruction& referenced_from_inst) {
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassOutput) {
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Output) {
       uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(vuid) << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
              << " to be only used for variables with Output storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                  referenced_from_inst)
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelFragment) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Fragment) {
         uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(vuid)
                << spvLogStringForEnv(_.context()->target_env)
                << " spec allows BuiltIn "
-               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
                << " to be used only with Fragment execution model. "
                << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                    referenced_from_inst, execution_model);
@@ -3682,7 +3682,7 @@
 spv_result_t BuiltInsValidator::ValidateFullyCoveredAtDefinition(const Decoration& decoration,
                                                const Instruction& inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
     if (spv_result_t error = ValidateBool(
             decoration, inst,
             [this, &inst, &builtin](const std::string& message) -> spv_result_t {
@@ -3692,7 +3692,7 @@
                      << spvLogStringForEnv(_.context()->target_env)
                      << " spec BuiltIn "
                      << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
-                                                      builtin)
+                                                      uint32_t(builtin))
                      << " variable needs to be a bool scalar. "
                      << message;
             })) {
@@ -3709,29 +3709,29 @@
     const Instruction& referenced_from_inst) {
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(vuid) << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn "
-             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+             << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
              << " to be only used for variables with Input storage class. "
              << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                  referenced_from_inst)
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelFragment) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Fragment) {
         uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(vuid)
                << spvLogStringForEnv(_.context()->target_env)
                << " spec allows BuiltIn "
-               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, builtin)
+               << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
                << " to be used only with Fragment execution model. "
                << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                    referenced_from_inst, execution_model);
@@ -3778,9 +3778,9 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << spvLogStringForEnv(_.context()->target_env)
              << " spec allows BuiltIn "
@@ -3832,9 +3832,9 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassOutput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Output) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4485) << "Vulkan spec allows BuiltIn "
              << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -3845,12 +3845,12 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
       switch (execution_model) {
-        case SpvExecutionModelVertex:
-        case SpvExecutionModelGeometry:
-        case SpvExecutionModelMeshNV:
-        case SpvExecutionModelMeshEXT:
+        case spv::ExecutionModel::Vertex:
+        case spv::ExecutionModel::Geometry:
+        case spv::ExecutionModel::MeshNV:
+        case spv::ExecutionModel::MeshEXT:
           break;
         default: {
           return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
@@ -3905,9 +3905,9 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(4491) << "Vulkan spec allows BuiltIn "
              << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -3918,8 +3918,8 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
-      if (execution_model != SpvExecutionModelFragment) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
+      if (execution_model != spv::ExecutionModel::Fragment) {
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
                << _.VkErrorID(4490) << "Vulkan spec allows BuiltIn "
                << _.grammar().lookupOperandName(SPV_OPERAND_TYPE_BUILT_IN,
@@ -3944,11 +3944,11 @@
 spv_result_t BuiltInsValidator::ValidateRayTracingBuiltinsAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
     switch (builtin) {
-      case SpvBuiltInHitTNV:
-      case SpvBuiltInRayTminKHR:
-      case SpvBuiltInRayTmaxKHR:
+      case spv::BuiltIn::HitTNV:
+      case spv::BuiltIn::RayTminKHR:
+      case spv::BuiltIn::RayTmaxKHR:
         // f32 scalar
         if (spv_result_t error = ValidateF32(
                 decoration, inst,
@@ -3959,19 +3959,19 @@
                          << _.VkErrorID(vuid)
                          << "According to the Vulkan spec BuiltIn "
                          << _.grammar().lookupOperandName(
-                                SPV_OPERAND_TYPE_BUILT_IN, builtin)
+                                SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
                          << " variable needs to be a 32-bit float scalar. "
                          << message;
                 })) {
           return error;
         }
         break;
-      case SpvBuiltInHitKindKHR:
-      case SpvBuiltInInstanceCustomIndexKHR:
-      case SpvBuiltInInstanceId:
-      case SpvBuiltInRayGeometryIndexKHR:
-      case SpvBuiltInIncomingRayFlagsKHR:
-      case SpvBuiltInCullMaskKHR:
+      case spv::BuiltIn::HitKindKHR:
+      case spv::BuiltIn::InstanceCustomIndexKHR:
+      case spv::BuiltIn::InstanceId:
+      case spv::BuiltIn::RayGeometryIndexKHR:
+      case spv::BuiltIn::IncomingRayFlagsKHR:
+      case spv::BuiltIn::CullMaskKHR:
         // i32 scalar
         if (spv_result_t error = ValidateI32(
                 decoration, inst,
@@ -3982,17 +3982,17 @@
                          << _.VkErrorID(vuid)
                          << "According to the Vulkan spec BuiltIn "
                          << _.grammar().lookupOperandName(
-                                SPV_OPERAND_TYPE_BUILT_IN, builtin)
+                                SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
                          << " variable needs to be a 32-bit int scalar. "
                          << message;
                 })) {
           return error;
         }
         break;
-      case SpvBuiltInObjectRayDirectionKHR:
-      case SpvBuiltInObjectRayOriginKHR:
-      case SpvBuiltInWorldRayDirectionKHR:
-      case SpvBuiltInWorldRayOriginKHR:
+      case spv::BuiltIn::ObjectRayDirectionKHR:
+      case spv::BuiltIn::ObjectRayOriginKHR:
+      case spv::BuiltIn::WorldRayDirectionKHR:
+      case spv::BuiltIn::WorldRayOriginKHR:
         // f32 vec3
         if (spv_result_t error = ValidateF32Vec(
                 decoration, inst, 3,
@@ -4003,7 +4003,7 @@
                          << _.VkErrorID(vuid)
                          << "According to the Vulkan spec BuiltIn "
                          << _.grammar().lookupOperandName(
-                                SPV_OPERAND_TYPE_BUILT_IN, builtin)
+                                SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
                          << " variable needs to be a 3-component 32-bit float "
                             "vector. "
                          << message;
@@ -4011,8 +4011,8 @@
           return error;
         }
         break;
-      case SpvBuiltInLaunchIdKHR:
-      case SpvBuiltInLaunchSizeKHR:
+      case spv::BuiltIn::LaunchIdKHR:
+      case spv::BuiltIn::LaunchSizeKHR:
         // i32 vec3
         if (spv_result_t error = ValidateI32Vec(
                 decoration, inst, 3,
@@ -4023,7 +4023,7 @@
                          << _.VkErrorID(vuid)
                          << "According to the Vulkan spec BuiltIn "
                          << _.grammar().lookupOperandName(
-                                SPV_OPERAND_TYPE_BUILT_IN, builtin)
+                                SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
                          << " variable needs to be a 3-component 32-bit int "
                             "vector. "
                          << message;
@@ -4031,8 +4031,8 @@
           return error;
         }
         break;
-      case SpvBuiltInObjectToWorldKHR:
-      case SpvBuiltInWorldToObjectKHR:
+      case spv::BuiltIn::ObjectToWorldKHR:
+      case spv::BuiltIn::WorldToObjectKHR:
         // f32 mat4x3
         if (spv_result_t error = ValidateF32Mat(
                 decoration, inst, 3, 4,
@@ -4043,7 +4043,7 @@
                          << _.VkErrorID(vuid)
                          << "According to the Vulkan spec BuiltIn "
                          << _.grammar().lookupOperandName(
-                                SPV_OPERAND_TYPE_BUILT_IN, builtin)
+                                SPV_OPERAND_TYPE_BUILT_IN, uint32_t(builtin))
                          << " variable needs to be a matrix with"
                          << " 4 columns of 3-component vectors of 32-bit "
                             "floats. "
@@ -4067,10 +4067,10 @@
     const Instruction& referenced_inst,
     const Instruction& referenced_from_inst) {
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    const SpvBuiltIn builtin = SpvBuiltIn(decoration.params()[0]);
-    const SpvStorageClass storage_class = GetStorageClass(referenced_from_inst);
-    if (storage_class != SpvStorageClassMax &&
-        storage_class != SpvStorageClassInput) {
+    const spv::BuiltIn builtin = spv::BuiltIn(decoration.params()[0]);
+    const spv::StorageClass storage_class = GetStorageClass(referenced_from_inst);
+    if (storage_class != spv::StorageClass::Max &&
+        storage_class != spv::StorageClass::Input) {
       uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorStorageClass);
       return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
              << _.VkErrorID(vuid) << "Vulkan spec allows BuiltIn "
@@ -4082,7 +4082,7 @@
              << " " << GetStorageClassDesc(referenced_from_inst);
     }
 
-    for (const SpvExecutionModel execution_model : execution_models_) {
+    for (const spv::ExecutionModel execution_model : execution_models_) {
       if (!IsExecutionModelValidForRtBuiltIn(builtin, execution_model)) {
         uint32_t vuid = GetVUIDForBuiltin(builtin, VUIDErrorExecutionModel);
         return _.diag(SPV_ERROR_INVALID_DATA, &referenced_from_inst)
@@ -4091,7 +4091,7 @@
                                                 decoration.params()[0])
                << " to be used with the execution model "
                << _.grammar().lookupOperandName(
-                      SPV_OPERAND_TYPE_EXECUTION_MODEL, execution_model)
+                      SPV_OPERAND_TYPE_EXECUTION_MODEL, uint32_t(execution_model))
                << ".\n"
                << GetReferenceDesc(decoration, built_in_inst, referenced_inst,
                                    referenced_from_inst, execution_model);
@@ -4112,7 +4112,7 @@
 
 spv_result_t BuiltInsValidator::ValidateSingleBuiltInAtDefinition(
     const Decoration& decoration, const Instruction& inst) {
-  const SpvBuiltIn label = SpvBuiltIn(decoration.params()[0]);
+  const spv::BuiltIn label = spv::BuiltIn(decoration.params()[0]);
 
   if (!spvIsVulkanEnv(_.context()->target_env)) {
     // Early return. All currently implemented rules are based on Vulkan spec.
@@ -4129,166 +4129,166 @@
   // If the newly added enum has validation rules associated with it
   // consider leaving a TODO and/or creating an issue.
   switch (label) {
-    case SpvBuiltInClipDistance:
-    case SpvBuiltInCullDistance: {
+    case spv::BuiltIn::ClipDistance:
+    case spv::BuiltIn::CullDistance: {
       return ValidateClipOrCullDistanceAtDefinition(decoration, inst);
     }
-    case SpvBuiltInFragCoord: {
+    case spv::BuiltIn::FragCoord: {
       return ValidateFragCoordAtDefinition(decoration, inst);
     }
-    case SpvBuiltInFragDepth: {
+    case spv::BuiltIn::FragDepth: {
       return ValidateFragDepthAtDefinition(decoration, inst);
     }
-    case SpvBuiltInFrontFacing: {
+    case spv::BuiltIn::FrontFacing: {
       return ValidateFrontFacingAtDefinition(decoration, inst);
     }
-    case SpvBuiltInGlobalInvocationId:
-    case SpvBuiltInLocalInvocationId:
-    case SpvBuiltInNumWorkgroups:
-    case SpvBuiltInWorkgroupId: {
+    case spv::BuiltIn::GlobalInvocationId:
+    case spv::BuiltIn::LocalInvocationId:
+    case spv::BuiltIn::NumWorkgroups:
+    case spv::BuiltIn::WorkgroupId: {
       return ValidateComputeShaderI32Vec3InputAtDefinition(decoration, inst);
     }
-    case SpvBuiltInBaryCoordKHR:
-    case SpvBuiltInBaryCoordNoPerspKHR: {
+    case spv::BuiltIn::BaryCoordKHR:
+    case spv::BuiltIn::BaryCoordNoPerspKHR: {
       return ValidateFragmentShaderF32Vec3InputAtDefinition(decoration, inst);
     }
-    case SpvBuiltInHelperInvocation: {
+    case spv::BuiltIn::HelperInvocation: {
       return ValidateHelperInvocationAtDefinition(decoration, inst);
     }
-    case SpvBuiltInInvocationId: {
+    case spv::BuiltIn::InvocationId: {
       return ValidateInvocationIdAtDefinition(decoration, inst);
     }
-    case SpvBuiltInInstanceIndex: {
+    case spv::BuiltIn::InstanceIndex: {
       return ValidateInstanceIndexAtDefinition(decoration, inst);
     }
-    case SpvBuiltInLayer:
-    case SpvBuiltInViewportIndex: {
+    case spv::BuiltIn::Layer:
+    case spv::BuiltIn::ViewportIndex: {
       return ValidateLayerOrViewportIndexAtDefinition(decoration, inst);
     }
-    case SpvBuiltInPatchVertices: {
+    case spv::BuiltIn::PatchVertices: {
       return ValidatePatchVerticesAtDefinition(decoration, inst);
     }
-    case SpvBuiltInPointCoord: {
+    case spv::BuiltIn::PointCoord: {
       return ValidatePointCoordAtDefinition(decoration, inst);
     }
-    case SpvBuiltInPointSize: {
+    case spv::BuiltIn::PointSize: {
       return ValidatePointSizeAtDefinition(decoration, inst);
     }
-    case SpvBuiltInPosition: {
+    case spv::BuiltIn::Position: {
       return ValidatePositionAtDefinition(decoration, inst);
     }
-    case SpvBuiltInPrimitiveId: {
+    case spv::BuiltIn::PrimitiveId: {
       return ValidatePrimitiveIdAtDefinition(decoration, inst);
     }
-    case SpvBuiltInSampleId: {
+    case spv::BuiltIn::SampleId: {
       return ValidateSampleIdAtDefinition(decoration, inst);
     }
-    case SpvBuiltInSampleMask: {
+    case spv::BuiltIn::SampleMask: {
       return ValidateSampleMaskAtDefinition(decoration, inst);
     }
-    case SpvBuiltInSamplePosition: {
+    case spv::BuiltIn::SamplePosition: {
       return ValidateSamplePositionAtDefinition(decoration, inst);
     }
-    case SpvBuiltInSubgroupId:
-    case SpvBuiltInNumSubgroups: {
+    case spv::BuiltIn::SubgroupId:
+    case spv::BuiltIn::NumSubgroups: {
       return ValidateComputeI32InputAtDefinition(decoration, inst);
     }
-    case SpvBuiltInSubgroupLocalInvocationId:
-    case SpvBuiltInSubgroupSize: {
+    case spv::BuiltIn::SubgroupLocalInvocationId:
+    case spv::BuiltIn::SubgroupSize: {
       return ValidateI32InputAtDefinition(decoration, inst);
     }
-    case SpvBuiltInSubgroupEqMask:
-    case SpvBuiltInSubgroupGeMask:
-    case SpvBuiltInSubgroupGtMask:
-    case SpvBuiltInSubgroupLeMask:
-    case SpvBuiltInSubgroupLtMask: {
+    case spv::BuiltIn::SubgroupEqMask:
+    case spv::BuiltIn::SubgroupGeMask:
+    case spv::BuiltIn::SubgroupGtMask:
+    case spv::BuiltIn::SubgroupLeMask:
+    case spv::BuiltIn::SubgroupLtMask: {
       return ValidateI32Vec4InputAtDefinition(decoration, inst);
     }
-    case SpvBuiltInTessCoord: {
+    case spv::BuiltIn::TessCoord: {
       return ValidateTessCoordAtDefinition(decoration, inst);
     }
-    case SpvBuiltInTessLevelOuter: {
+    case spv::BuiltIn::TessLevelOuter: {
       return ValidateTessLevelOuterAtDefinition(decoration, inst);
     }
-    case SpvBuiltInTessLevelInner: {
+    case spv::BuiltIn::TessLevelInner: {
       return ValidateTessLevelInnerAtDefinition(decoration, inst);
     }
-    case SpvBuiltInVertexIndex: {
+    case spv::BuiltIn::VertexIndex: {
       return ValidateVertexIndexAtDefinition(decoration, inst);
     }
-    case SpvBuiltInWorkgroupSize: {
+    case spv::BuiltIn::WorkgroupSize: {
       return ValidateWorkgroupSizeAtDefinition(decoration, inst);
     }
-    case SpvBuiltInVertexId: {
+    case spv::BuiltIn::VertexId: {
       return ValidateVertexIdAtDefinition(decoration, inst);
     }
-    case SpvBuiltInLocalInvocationIndex: {
+    case spv::BuiltIn::LocalInvocationIndex: {
       return ValidateLocalInvocationIndexAtDefinition(decoration, inst);
     }
-    case SpvBuiltInCoreIDARM:
-    case SpvBuiltInCoreCountARM:
-    case SpvBuiltInCoreMaxIDARM:
-    case SpvBuiltInWarpIDARM:
-    case SpvBuiltInWarpMaxIDARM:
-    case SpvBuiltInWarpsPerSMNV:
-    case SpvBuiltInSMCountNV:
-    case SpvBuiltInWarpIDNV:
-    case SpvBuiltInSMIDNV: {
+    case spv::BuiltIn::CoreIDARM:
+    case spv::BuiltIn::CoreCountARM:
+    case spv::BuiltIn::CoreMaxIDARM:
+    case spv::BuiltIn::WarpIDARM:
+    case spv::BuiltIn::WarpMaxIDARM:
+    case spv::BuiltIn::WarpsPerSMNV:
+    case spv::BuiltIn::SMCountNV:
+    case spv::BuiltIn::WarpIDNV:
+    case spv::BuiltIn::SMIDNV: {
       return ValidateNVSMOrARMCoreBuiltinsAtDefinition(decoration, inst);
     }
-    case SpvBuiltInBaseInstance:
-    case SpvBuiltInBaseVertex: {
+    case spv::BuiltIn::BaseInstance:
+    case spv::BuiltIn::BaseVertex: {
       return ValidateBaseInstanceOrVertexAtDefinition(decoration, inst);
     }
-    case SpvBuiltInDrawIndex: {
+    case spv::BuiltIn::DrawIndex: {
       return ValidateDrawIndexAtDefinition(decoration, inst);
     }
-    case SpvBuiltInViewIndex: {
+    case spv::BuiltIn::ViewIndex: {
       return ValidateViewIndexAtDefinition(decoration, inst);
     }
-    case SpvBuiltInDeviceIndex: {
+    case spv::BuiltIn::DeviceIndex: {
       return ValidateDeviceIndexAtDefinition(decoration, inst);
     }
-    case SpvBuiltInFragInvocationCountEXT: {
-      // alias SpvBuiltInInvocationsPerPixelNV
+    case spv::BuiltIn::FragInvocationCountEXT: {
+      // alias spv::BuiltIn::InvocationsPerPixelNV
       return ValidateFragInvocationCountAtDefinition(decoration, inst);
     }
-    case SpvBuiltInFragSizeEXT: {
-      // alias SpvBuiltInFragmentSizeNV
+    case spv::BuiltIn::FragSizeEXT: {
+      // alias spv::BuiltIn::FragmentSizeNV
       return ValidateFragSizeAtDefinition(decoration, inst);
     }
-    case SpvBuiltInFragStencilRefEXT: {
+    case spv::BuiltIn::FragStencilRefEXT: {
       return ValidateFragStencilRefAtDefinition(decoration, inst);
     }
-    case SpvBuiltInFullyCoveredEXT:{
+    case spv::BuiltIn::FullyCoveredEXT:{
       return ValidateFullyCoveredAtDefinition(decoration, inst);
     }
     // Ray tracing builtins
-    case SpvBuiltInHitKindKHR:  // alias SpvBuiltInHitKindNV
-    case SpvBuiltInHitTNV:      // NOT present in KHR
-    case SpvBuiltInInstanceId:
-    case SpvBuiltInLaunchIdKHR:           // alias SpvBuiltInLaunchIdNV
-    case SpvBuiltInLaunchSizeKHR:         // alias SpvBuiltInLaunchSizeNV
-    case SpvBuiltInWorldRayOriginKHR:     // alias SpvBuiltInWorldRayOriginNV
-    case SpvBuiltInWorldRayDirectionKHR:  // alias SpvBuiltInWorldRayDirectionNV
-    case SpvBuiltInObjectRayOriginKHR:    // alias SpvBuiltInObjectRayOriginNV
-    case SpvBuiltInObjectRayDirectionKHR:   // alias
-                                            // SpvBuiltInObjectRayDirectionNV
-    case SpvBuiltInRayTminKHR:              // alias SpvBuiltInRayTminNV
-    case SpvBuiltInRayTmaxKHR:              // alias SpvBuiltInRayTmaxNV
-    case SpvBuiltInInstanceCustomIndexKHR:  // alias
-                                            // SpvBuiltInInstanceCustomIndexNV
-    case SpvBuiltInObjectToWorldKHR:        // alias SpvBuiltInObjectToWorldNV
-    case SpvBuiltInWorldToObjectKHR:        // alias SpvBuiltInWorldToObjectNV
-    case SpvBuiltInIncomingRayFlagsKHR:    // alias SpvBuiltInIncomingRayFlagsNV
-    case SpvBuiltInRayGeometryIndexKHR:    // NOT present in NV
-    case SpvBuiltInCullMaskKHR: {
+    case spv::BuiltIn::HitKindKHR:  // alias spv::BuiltIn::HitKindNV
+    case spv::BuiltIn::HitTNV:      // NOT present in KHR
+    case spv::BuiltIn::InstanceId:
+    case spv::BuiltIn::LaunchIdKHR:           // alias spv::BuiltIn::LaunchIdNV
+    case spv::BuiltIn::LaunchSizeKHR:         // alias spv::BuiltIn::LaunchSizeNV
+    case spv::BuiltIn::WorldRayOriginKHR:     // alias spv::BuiltIn::WorldRayOriginNV
+    case spv::BuiltIn::WorldRayDirectionKHR:  // alias spv::BuiltIn::WorldRayDirectionNV
+    case spv::BuiltIn::ObjectRayOriginKHR:    // alias spv::BuiltIn::ObjectRayOriginNV
+    case spv::BuiltIn::ObjectRayDirectionKHR:   // alias
+                                            // spv::BuiltIn::ObjectRayDirectionNV
+    case spv::BuiltIn::RayTminKHR:              // alias spv::BuiltIn::RayTminNV
+    case spv::BuiltIn::RayTmaxKHR:              // alias spv::BuiltIn::RayTmaxNV
+    case spv::BuiltIn::InstanceCustomIndexKHR:  // alias
+                                            // spv::BuiltIn::InstanceCustomIndexNV
+    case spv::BuiltIn::ObjectToWorldKHR:        // alias spv::BuiltIn::ObjectToWorldNV
+    case spv::BuiltIn::WorldToObjectKHR:        // alias spv::BuiltIn::WorldToObjectNV
+    case spv::BuiltIn::IncomingRayFlagsKHR:    // alias spv::BuiltIn::IncomingRayFlagsNV
+    case spv::BuiltIn::RayGeometryIndexKHR:    // NOT present in NV
+    case spv::BuiltIn::CullMaskKHR: {
       return ValidateRayTracingBuiltinsAtDefinition(decoration, inst);
     }
-    case SpvBuiltInPrimitiveShadingRateKHR: {
+    case spv::BuiltIn::PrimitiveShadingRateKHR: {
       return ValidatePrimitiveShadingRateAtDefinition(decoration, inst);
     }
-    case SpvBuiltInShadingRateKHR: {
+    case spv::BuiltIn::ShadingRateKHR: {
       return ValidateShadingRateAtDefinition(decoration, inst);
     }
     default:
@@ -4310,7 +4310,7 @@
     assert(inst);
 
     for (const auto& decoration : kv.second) {
-      if (decoration.dec_type() != SpvDecorationBuiltIn) {
+      if (decoration.dec_type() != spv::Decoration::BuiltIn) {
         continue;
       }
 
diff --git a/source/val/validate_capability.cpp b/source/val/validate_capability.cpp
index 8efd554..d70c827 100644
--- a/source/val/validate_capability.cpp
+++ b/source/val/validate_capability.cpp
@@ -29,74 +29,82 @@
 namespace {
 
 bool IsSupportGuaranteedVulkan_1_0(uint32_t capability) {
-  switch (capability) {
-    case SpvCapabilityMatrix:
-    case SpvCapabilityShader:
-    case SpvCapabilityInputAttachment:
-    case SpvCapabilitySampled1D:
-    case SpvCapabilityImage1D:
-    case SpvCapabilitySampledBuffer:
-    case SpvCapabilityImageBuffer:
-    case SpvCapabilityImageQuery:
-    case SpvCapabilityDerivativeControl:
+  switch (spv::Capability(capability)) {
+    case spv::Capability::Matrix:
+    case spv::Capability::Shader:
+    case spv::Capability::InputAttachment:
+    case spv::Capability::Sampled1D:
+    case spv::Capability::Image1D:
+    case spv::Capability::SampledBuffer:
+    case spv::Capability::ImageBuffer:
+    case spv::Capability::ImageQuery:
+    case spv::Capability::DerivativeControl:
       return true;
+    default:
+      break;
   }
   return false;
 }
 
 bool IsSupportGuaranteedVulkan_1_1(uint32_t capability) {
   if (IsSupportGuaranteedVulkan_1_0(capability)) return true;
-  switch (capability) {
-    case SpvCapabilityDeviceGroup:
-    case SpvCapabilityMultiView:
+  switch (spv::Capability(capability)) {
+    case spv::Capability::DeviceGroup:
+    case spv::Capability::MultiView:
       return true;
+    default:
+      break;
   }
   return false;
 }
 
 bool IsSupportGuaranteedVulkan_1_2(uint32_t capability) {
   if (IsSupportGuaranteedVulkan_1_1(capability)) return true;
-  switch (capability) {
-    case SpvCapabilityShaderNonUniform:
+  switch (spv::Capability(capability)) {
+    case spv::Capability::ShaderNonUniform:
       return true;
+    default:
+      break;
   }
   return false;
 }
 
 bool IsSupportOptionalVulkan_1_0(uint32_t capability) {
-  switch (capability) {
-    case SpvCapabilityGeometry:
-    case SpvCapabilityTessellation:
-    case SpvCapabilityFloat64:
-    case SpvCapabilityInt64:
-    case SpvCapabilityInt16:
-    case SpvCapabilityTessellationPointSize:
-    case SpvCapabilityGeometryPointSize:
-    case SpvCapabilityImageGatherExtended:
-    case SpvCapabilityStorageImageMultisample:
-    case SpvCapabilityUniformBufferArrayDynamicIndexing:
-    case SpvCapabilitySampledImageArrayDynamicIndexing:
-    case SpvCapabilityStorageBufferArrayDynamicIndexing:
-    case SpvCapabilityStorageImageArrayDynamicIndexing:
-    case SpvCapabilityClipDistance:
-    case SpvCapabilityCullDistance:
-    case SpvCapabilityImageCubeArray:
-    case SpvCapabilitySampleRateShading:
-    case SpvCapabilitySparseResidency:
-    case SpvCapabilityMinLod:
-    case SpvCapabilitySampledCubeArray:
-    case SpvCapabilityImageMSArray:
-    case SpvCapabilityStorageImageExtendedFormats:
-    case SpvCapabilityInterpolationFunction:
-    case SpvCapabilityStorageImageReadWithoutFormat:
-    case SpvCapabilityStorageImageWriteWithoutFormat:
-    case SpvCapabilityMultiViewport:
-    case SpvCapabilityInt64Atomics:
-    case SpvCapabilityTransformFeedback:
-    case SpvCapabilityGeometryStreams:
-    case SpvCapabilityFloat16:
-    case SpvCapabilityInt8:
+  switch (spv::Capability(capability)) {
+    case spv::Capability::Geometry:
+    case spv::Capability::Tessellation:
+    case spv::Capability::Float64:
+    case spv::Capability::Int64:
+    case spv::Capability::Int16:
+    case spv::Capability::TessellationPointSize:
+    case spv::Capability::GeometryPointSize:
+    case spv::Capability::ImageGatherExtended:
+    case spv::Capability::StorageImageMultisample:
+    case spv::Capability::UniformBufferArrayDynamicIndexing:
+    case spv::Capability::SampledImageArrayDynamicIndexing:
+    case spv::Capability::StorageBufferArrayDynamicIndexing:
+    case spv::Capability::StorageImageArrayDynamicIndexing:
+    case spv::Capability::ClipDistance:
+    case spv::Capability::CullDistance:
+    case spv::Capability::ImageCubeArray:
+    case spv::Capability::SampleRateShading:
+    case spv::Capability::SparseResidency:
+    case spv::Capability::MinLod:
+    case spv::Capability::SampledCubeArray:
+    case spv::Capability::ImageMSArray:
+    case spv::Capability::StorageImageExtendedFormats:
+    case spv::Capability::InterpolationFunction:
+    case spv::Capability::StorageImageReadWithoutFormat:
+    case spv::Capability::StorageImageWriteWithoutFormat:
+    case spv::Capability::MultiViewport:
+    case spv::Capability::Int64Atomics:
+    case spv::Capability::TransformFeedback:
+    case spv::Capability::GeometryStreams:
+    case spv::Capability::Float16:
+    case spv::Capability::Int8:
       return true;
+    default:
+      break;
   }
   return false;
 }
@@ -104,27 +112,29 @@
 bool IsSupportOptionalVulkan_1_1(uint32_t capability) {
   if (IsSupportOptionalVulkan_1_0(capability)) return true;
 
-  switch (capability) {
-    case SpvCapabilityGroupNonUniform:
-    case SpvCapabilityGroupNonUniformVote:
-    case SpvCapabilityGroupNonUniformArithmetic:
-    case SpvCapabilityGroupNonUniformBallot:
-    case SpvCapabilityGroupNonUniformShuffle:
-    case SpvCapabilityGroupNonUniformShuffleRelative:
-    case SpvCapabilityGroupNonUniformClustered:
-    case SpvCapabilityGroupNonUniformQuad:
-    case SpvCapabilityDrawParameters:
-    // Alias SpvCapabilityStorageBuffer16BitAccess.
-    case SpvCapabilityStorageUniformBufferBlock16:
-    // Alias SpvCapabilityUniformAndStorageBuffer16BitAccess.
-    case SpvCapabilityStorageUniform16:
-    case SpvCapabilityStoragePushConstant16:
-    case SpvCapabilityStorageInputOutput16:
-    case SpvCapabilityDeviceGroup:
-    case SpvCapabilityMultiView:
-    case SpvCapabilityVariablePointersStorageBuffer:
-    case SpvCapabilityVariablePointers:
+  switch (spv::Capability(capability)) {
+    case spv::Capability::GroupNonUniform:
+    case spv::Capability::GroupNonUniformVote:
+    case spv::Capability::GroupNonUniformArithmetic:
+    case spv::Capability::GroupNonUniformBallot:
+    case spv::Capability::GroupNonUniformShuffle:
+    case spv::Capability::GroupNonUniformShuffleRelative:
+    case spv::Capability::GroupNonUniformClustered:
+    case spv::Capability::GroupNonUniformQuad:
+    case spv::Capability::DrawParameters:
+    // Alias spv::Capability::StorageBuffer16BitAccess.
+    case spv::Capability::StorageUniformBufferBlock16:
+    // Alias spv::Capability::UniformAndStorageBuffer16BitAccess.
+    case spv::Capability::StorageUniform16:
+    case spv::Capability::StoragePushConstant16:
+    case spv::Capability::StorageInputOutput16:
+    case spv::Capability::DeviceGroup:
+    case spv::Capability::MultiView:
+    case spv::Capability::VariablePointersStorageBuffer:
+    case spv::Capability::VariablePointers:
       return true;
+    default:
+      break;
   }
   return false;
 }
@@ -132,47 +142,51 @@
 bool IsSupportOptionalVulkan_1_2(uint32_t capability) {
   if (IsSupportOptionalVulkan_1_1(capability)) return true;
 
-  switch (capability) {
-    case SpvCapabilityDenormPreserve:
-    case SpvCapabilityDenormFlushToZero:
-    case SpvCapabilitySignedZeroInfNanPreserve:
-    case SpvCapabilityRoundingModeRTE:
-    case SpvCapabilityRoundingModeRTZ:
-    case SpvCapabilityVulkanMemoryModel:
-    case SpvCapabilityVulkanMemoryModelDeviceScope:
-    case SpvCapabilityStorageBuffer8BitAccess:
-    case SpvCapabilityUniformAndStorageBuffer8BitAccess:
-    case SpvCapabilityStoragePushConstant8:
-    case SpvCapabilityShaderViewportIndex:
-    case SpvCapabilityShaderLayer:
-    case SpvCapabilityPhysicalStorageBufferAddresses:
-    case SpvCapabilityRuntimeDescriptorArray:
-    case SpvCapabilityUniformTexelBufferArrayDynamicIndexing:
-    case SpvCapabilityStorageTexelBufferArrayDynamicIndexing:
-    case SpvCapabilityUniformBufferArrayNonUniformIndexing:
-    case SpvCapabilitySampledImageArrayNonUniformIndexing:
-    case SpvCapabilityStorageBufferArrayNonUniformIndexing:
-    case SpvCapabilityStorageImageArrayNonUniformIndexing:
-    case SpvCapabilityInputAttachmentArrayNonUniformIndexing:
-    case SpvCapabilityUniformTexelBufferArrayNonUniformIndexing:
-    case SpvCapabilityStorageTexelBufferArrayNonUniformIndexing:
+  switch (spv::Capability(capability)) {
+    case spv::Capability::DenormPreserve:
+    case spv::Capability::DenormFlushToZero:
+    case spv::Capability::SignedZeroInfNanPreserve:
+    case spv::Capability::RoundingModeRTE:
+    case spv::Capability::RoundingModeRTZ:
+    case spv::Capability::VulkanMemoryModel:
+    case spv::Capability::VulkanMemoryModelDeviceScope:
+    case spv::Capability::StorageBuffer8BitAccess:
+    case spv::Capability::UniformAndStorageBuffer8BitAccess:
+    case spv::Capability::StoragePushConstant8:
+    case spv::Capability::ShaderViewportIndex:
+    case spv::Capability::ShaderLayer:
+    case spv::Capability::PhysicalStorageBufferAddresses:
+    case spv::Capability::RuntimeDescriptorArray:
+    case spv::Capability::UniformTexelBufferArrayDynamicIndexing:
+    case spv::Capability::StorageTexelBufferArrayDynamicIndexing:
+    case spv::Capability::UniformBufferArrayNonUniformIndexing:
+    case spv::Capability::SampledImageArrayNonUniformIndexing:
+    case spv::Capability::StorageBufferArrayNonUniformIndexing:
+    case spv::Capability::StorageImageArrayNonUniformIndexing:
+    case spv::Capability::InputAttachmentArrayNonUniformIndexing:
+    case spv::Capability::UniformTexelBufferArrayNonUniformIndexing:
+    case spv::Capability::StorageTexelBufferArrayNonUniformIndexing:
       return true;
+    default:
+      break;
   }
   return false;
 }
 
 bool IsSupportGuaranteedOpenCL_1_2(uint32_t capability, bool embedded_profile) {
-  switch (capability) {
-    case SpvCapabilityAddresses:
-    case SpvCapabilityFloat16Buffer:
-    case SpvCapabilityInt16:
-    case SpvCapabilityInt8:
-    case SpvCapabilityKernel:
-    case SpvCapabilityLinkage:
-    case SpvCapabilityVector16:
+  switch (spv::Capability(capability)) {
+    case spv::Capability::Addresses:
+    case spv::Capability::Float16Buffer:
+    case spv::Capability::Int16:
+    case spv::Capability::Int8:
+    case spv::Capability::Kernel:
+    case spv::Capability::Linkage:
+    case spv::Capability::Vector16:
       return true;
-    case SpvCapabilityInt64:
+    case spv::Capability::Int64:
       return !embedded_profile;
+    default:
+      break;
   }
   return false;
 }
@@ -180,12 +194,14 @@
 bool IsSupportGuaranteedOpenCL_2_0(uint32_t capability, bool embedded_profile) {
   if (IsSupportGuaranteedOpenCL_1_2(capability, embedded_profile)) return true;
 
-  switch (capability) {
-    case SpvCapabilityDeviceEnqueue:
-    case SpvCapabilityGenericPointer:
-    case SpvCapabilityGroups:
-    case SpvCapabilityPipes:
+  switch (spv::Capability(capability)) {
+    case spv::Capability::DeviceEnqueue:
+    case spv::Capability::GenericPointer:
+    case spv::Capability::Groups:
+    case spv::Capability::Pipes:
       return true;
+    default:
+      break;
   }
   return false;
 }
@@ -193,19 +209,23 @@
 bool IsSupportGuaranteedOpenCL_2_2(uint32_t capability, bool embedded_profile) {
   if (IsSupportGuaranteedOpenCL_2_0(capability, embedded_profile)) return true;
 
-  switch (capability) {
-    case SpvCapabilitySubgroupDispatch:
-    case SpvCapabilityPipeStorage:
+  switch (spv::Capability(capability)) {
+    case spv::Capability::SubgroupDispatch:
+    case spv::Capability::PipeStorage:
       return true;
+    default:
+      break;
   }
   return false;
 }
 
 bool IsSupportOptionalOpenCL_1_2(uint32_t capability) {
-  switch (capability) {
-    case SpvCapabilityImageBasic:
-    case SpvCapabilityFloat64:
+  switch (spv::Capability(capability)) {
+    case spv::Capability::ImageBasic:
+    case spv::Capability::Float64:
       return true;
+    default:
+      break;
   }
   return false;
 }
@@ -229,14 +249,16 @@
 
 bool IsEnabledByCapabilityOpenCL_1_2(ValidationState_t& _,
                                      uint32_t capability) {
-  if (_.HasCapability(SpvCapabilityImageBasic)) {
-    switch (capability) {
-      case SpvCapabilityLiteralSampler:
-      case SpvCapabilitySampled1D:
-      case SpvCapabilityImage1D:
-      case SpvCapabilitySampledBuffer:
-      case SpvCapabilityImageBuffer:
+  if (_.HasCapability(spv::Capability::ImageBasic)) {
+    switch (spv::Capability(capability)) {
+      case spv::Capability::LiteralSampler:
+      case spv::Capability::Sampled1D:
+      case spv::Capability::Image1D:
+      case spv::Capability::SampledBuffer:
+      case spv::Capability::ImageBuffer:
         return true;
+      default:
+        break;
     }
     return false;
   }
@@ -245,15 +267,17 @@
 
 bool IsEnabledByCapabilityOpenCL_2_0(ValidationState_t& _,
                                      uint32_t capability) {
-  if (_.HasCapability(SpvCapabilityImageBasic)) {
-    switch (capability) {
-      case SpvCapabilityImageReadWrite:
-      case SpvCapabilityLiteralSampler:
-      case SpvCapabilitySampled1D:
-      case SpvCapabilityImage1D:
-      case SpvCapabilitySampledBuffer:
-      case SpvCapabilityImageBuffer:
+  if (_.HasCapability(spv::Capability::ImageBasic)) {
+    switch (spv::Capability(capability)) {
+      case spv::Capability::ImageReadWrite:
+      case spv::Capability::LiteralSampler:
+      case spv::Capability::Sampled1D:
+      case spv::Capability::Image1D:
+      case spv::Capability::SampledBuffer:
+      case spv::Capability::ImageBuffer:
         return true;
+      default:
+        break;
     }
     return false;
   }
@@ -265,7 +289,7 @@
 // Validates that capability declarations use operands allowed in the current
 // context.
 spv_result_t CapabilityPass(ValidationState_t& _, const Instruction* inst) {
-  if (inst->opcode() != SpvOpCapability) return SPV_SUCCESS;
+  if (inst->opcode() != spv::Op::OpCapability) return SPV_SUCCESS;
 
   assert(inst->operands().size() == 1);
 
diff --git a/source/val/validate_cfg.cpp b/source/val/validate_cfg.cpp
index cc0b999..06e4d67 100644
--- a/source/val/validate_cfg.cpp
+++ b/source/val/validate_cfg.cpp
@@ -54,7 +54,7 @@
            << "OpPhi must not have void result type";
   }
   if (_.IsPointerType(inst->type_id()) &&
-      _.addressing_model() == SpvAddressingModelLogical) {
+      _.addressing_model() == spv::AddressingModel::Logical) {
     if (!_.features().variable_pointers) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Using pointers with OpPhi requires capability "
@@ -64,13 +64,14 @@
 
   const Instruction* type_inst = _.FindDef(inst->type_id());
   assert(type_inst);
-  const SpvOp type_opcode = type_inst->opcode();
+  const spv::Op type_opcode = type_inst->opcode();
 
   if (!_.options()->before_hlsl_legalization &&
-      !_.HasCapability(SpvCapabilityBindlessTextureNV)) {
-    if (type_opcode == SpvOpTypeSampledImage ||
-        (_.HasCapability(SpvCapabilityShader) &&
-         (type_opcode == SpvOpTypeImage || type_opcode == SpvOpTypeSampler))) {
+      !_.HasCapability(spv::Capability::BindlessTextureNV)) {
+    if (type_opcode == spv::Op::OpTypeSampledImage ||
+        (_.HasCapability(spv::Capability::Shader) &&
+         (type_opcode == spv::Op::OpTypeImage ||
+          type_opcode == spv::Op::OpTypeSampler))) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "Result type cannot be Op" << spvOpcodeString(type_opcode);
     }
@@ -108,7 +109,7 @@
                << " type <id> " << _.getIdName(inc_type_id) << ".";
       }
     } else {
-      if (_.GetIdOpcode(inc_id) != SpvOpLabel) {
+      if (_.GetIdOpcode(inc_id) != spv::Op::OpLabel) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << "OpPhi's incoming basic block <id> " << _.getIdName(inc_id)
                << " is not an OpLabel.";
@@ -143,7 +144,7 @@
   // target operands must be OpLabel
   const auto id = inst->GetOperandAs<uint32_t>(0);
   const auto target = _.FindDef(id);
-  if (!target || SpvOpLabel != target->opcode()) {
+  if (!target || spv::Op::OpLabel != target->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "'Target Label' operands for OpBranch must be the ID "
               "of an OpLabel instruction";
@@ -178,7 +179,7 @@
   // PerformCfgChecks already checks for that
   const auto true_id = inst->GetOperandAs<uint32_t>(1);
   const auto true_target = _.FindDef(true_id);
-  if (!true_target || SpvOpLabel != true_target->opcode()) {
+  if (!true_target || spv::Op::OpLabel != true_target->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "The 'True Label' operand for OpBranchConditional must be the "
               "ID of an OpLabel instruction";
@@ -186,7 +187,7 @@
 
   const auto false_id = inst->GetOperandAs<uint32_t>(2);
   const auto false_target = _.FindDef(false_id);
-  if (!false_target || SpvOpLabel != false_target->opcode()) {
+  if (!false_target || spv::Op::OpLabel != false_target->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "The 'False Label' operand for OpBranchConditional must be the "
               "ID of an OpLabel instruction";
@@ -213,7 +214,7 @@
   }
 
   const auto default_label = _.FindDef(inst->GetOperandAs<uint32_t>(1));
-  if (default_label->opcode() != SpvOpLabel) {
+  if (default_label->opcode() != spv::Op::OpLabel) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Default must be an OpLabel instruction";
   }
@@ -223,7 +224,7 @@
     // literal, id
     const auto id = inst->GetOperandAs<uint32_t>(i + 1);
     const auto target = _.FindDef(id);
-    if (!target || SpvOpLabel != target->opcode()) {
+    if (!target || spv::Op::OpLabel != target->opcode()) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "'Target Label' operands for OpSwitch must be IDs of an "
                 "OpLabel instruction";
@@ -243,14 +244,14 @@
            << " does not represent a value.";
   }
   auto value_type = _.FindDef(value->type_id());
-  if (!value_type || SpvOpTypeVoid == value_type->opcode()) {
+  if (!value_type || spv::Op::OpTypeVoid == value_type->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "OpReturnValue value's type <id> "
            << _.getIdName(value->type_id()) << " is missing or void.";
   }
 
-  if (_.addressing_model() == SpvAddressingModelLogical &&
-      SpvOpTypePointer == value_type->opcode() &&
+  if (_.addressing_model() == spv::AddressingModel::Logical &&
+      spv::Op::OpTypePointer == value_type->opcode() &&
       !_.features().variable_pointers && !_.options()->relax_logical_pointer) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "OpReturnValue value's type <id> "
@@ -270,10 +271,15 @@
   return SPV_SUCCESS;
 }
 
+uint32_t operator>>(const spv::LoopControlShift& lhs,
+                    const spv::LoopControlShift& rhs) {
+  return uint32_t(lhs) >> uint32_t(rhs);
+}
+
 spv_result_t ValidateLoopMerge(ValidationState_t& _, const Instruction* inst) {
   const auto merge_id = inst->GetOperandAs<uint32_t>(0);
   const auto merge = _.FindDef(merge_id);
-  if (!merge || merge->opcode() != SpvOpLabel) {
+  if (!merge || merge->opcode() != spv::Op::OpLabel) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Merge Block " << _.getIdName(merge_id) << " must be an OpLabel";
   }
@@ -284,7 +290,7 @@
 
   const auto continue_id = inst->GetOperandAs<uint32_t>(1);
   const auto continue_target = _.FindDef(continue_id);
-  if (!continue_target || continue_target->opcode() != SpvOpLabel) {
+  if (!continue_target || continue_target->opcode() != spv::Op::OpLabel) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Continue Target " << _.getIdName(continue_id)
            << " must be an OpLabel";
@@ -295,36 +301,36 @@
            << "Merge Block and Continue Target must be different ids";
   }
 
-  const auto loop_control = inst->GetOperandAs<uint32_t>(2);
-  if ((loop_control >> SpvLoopControlUnrollShift) & 0x1 &&
-      (loop_control >> SpvLoopControlDontUnrollShift) & 0x1) {
+  const auto loop_control = inst->GetOperandAs<spv::LoopControlShift>(2);
+  if ((loop_control >> spv::LoopControlShift::Unroll) & 0x1 &&
+      (loop_control >> spv::LoopControlShift::DontUnroll) & 0x1) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Unroll and DontUnroll loop controls must not both be specified";
   }
-  if ((loop_control >> SpvLoopControlDontUnrollShift) & 0x1 &&
-      (loop_control >> SpvLoopControlPeelCountShift) & 0x1) {
+  if ((loop_control >> spv::LoopControlShift::DontUnroll) & 0x1 &&
+      (loop_control >> spv::LoopControlShift::PeelCount) & 0x1) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst) << "PeelCount and DontUnroll "
                                                    "loop controls must not "
                                                    "both be specified";
   }
-  if ((loop_control >> SpvLoopControlDontUnrollShift) & 0x1 &&
-      (loop_control >> SpvLoopControlPartialCountShift) & 0x1) {
+  if ((loop_control >> spv::LoopControlShift::DontUnroll) & 0x1 &&
+      (loop_control >> spv::LoopControlShift::PartialCount) & 0x1) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst) << "PartialCount and "
                                                    "DontUnroll loop controls "
                                                    "must not both be specified";
   }
 
   uint32_t operand = 3;
-  if ((loop_control >> SpvLoopControlDependencyLengthShift) & 0x1) {
+  if ((loop_control >> spv::LoopControlShift::DependencyLength) & 0x1) {
     ++operand;
   }
-  if ((loop_control >> SpvLoopControlMinIterationsShift) & 0x1) {
+  if ((loop_control >> spv::LoopControlShift::MinIterations) & 0x1) {
     ++operand;
   }
-  if ((loop_control >> SpvLoopControlMaxIterationsShift) & 0x1) {
+  if ((loop_control >> spv::LoopControlShift::MaxIterations) & 0x1) {
     ++operand;
   }
-  if ((loop_control >> SpvLoopControlIterationMultipleShift) & 0x1) {
+  if ((loop_control >> spv::LoopControlShift::IterationMultiple) & 0x1) {
     if (inst->operands().size() < operand ||
         inst->GetOperandAs<uint32_t>(operand) == 0) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst) << "IterationMultiple loop "
@@ -333,10 +339,10 @@
     }
     ++operand;
   }
-  if ((loop_control >> SpvLoopControlPeelCountShift) & 0x1) {
+  if ((loop_control >> spv::LoopControlShift::PeelCount) & 0x1) {
     ++operand;
   }
-  if ((loop_control >> SpvLoopControlPartialCountShift) & 0x1) {
+  if ((loop_control >> spv::LoopControlShift::PartialCount) & 0x1) {
     ++operand;
   }
 
@@ -644,9 +650,9 @@
     const auto index = terminator - &_.ordered_instructions()[0];
     auto* merge = &_.ordered_instructions()[index - 1];
     // Marks merges and continues as seen.
-    if (merge->opcode() == SpvOpSelectionMerge) {
+    if (merge->opcode() == spv::Op::OpSelectionMerge) {
       seen.insert(merge->GetOperandAs<uint32_t>(0));
-    } else if (merge->opcode() == SpvOpLoopMerge) {
+    } else if (merge->opcode() == spv::Op::OpLoopMerge) {
       seen.insert(merge->GetOperandAs<uint32_t>(0));
       seen.insert(merge->GetOperandAs<uint32_t>(1));
     } else {
@@ -657,7 +663,7 @@
     // Skip unreachable blocks.
     if (!block->structurally_reachable()) continue;
 
-    if (terminator->opcode() == SpvOpBranchConditional) {
+    if (terminator->opcode() == spv::Op::OpBranchConditional) {
       const auto true_label = terminator->GetOperandAs<uint32_t>(1);
       const auto false_label = terminator->GetOperandAs<uint32_t>(2);
       // Mark the upcoming blocks as seen now, but only error out if this block
@@ -669,7 +675,7 @@
         return _.diag(SPV_ERROR_INVALID_CFG, terminator)
                << "Selection must be structured";
       }
-    } else if (terminator->opcode() == SpvOpSwitch) {
+    } else if (terminator->opcode() == spv::Op::OpSwitch) {
       if (!merge) {
         return _.diag(SPV_ERROR_INVALID_CFG, terminator)
                << "OpSwitch must be preceded by an OpSelectionMerge "
@@ -798,8 +804,8 @@
           block->is_type(BlockType::kBlockTypeLoop)) {
         size_t index = (block->terminator() - &_.ordered_instructions()[0]) - 1;
         const auto& merge_inst = _.ordered_instructions()[index];
-        if (merge_inst.opcode() == SpvOpSelectionMerge ||
-            merge_inst.opcode() == SpvOpLoopMerge) {
+        if (merge_inst.opcode() == spv::Op::OpSelectionMerge ||
+            merge_inst.opcode() == spv::Op::OpLoopMerge) {
           uint32_t merge_id = merge_inst.GetOperandAs<uint32_t>(0);
           auto merge_block = function->GetBlock(merge_id).first;
           if (merge_block->structurally_reachable() &&
@@ -854,7 +860,7 @@
 
     // Checks rules for case constructs.
     if (construct.type() == ConstructType::kSelection &&
-        header->terminator()->opcode() == SpvOpSwitch) {
+        header->terminator()->opcode() == spv::Op::OpSwitch) {
       const auto terminator = header->terminator();
       if (auto error =
               StructuredSwitchChecks(_, function, terminator, header, merge)) {
@@ -928,7 +934,7 @@
       }
       // If we have structured control flow, check that no block has a control
       // flow nesting depth larger than the limit.
-      if (_.HasCapability(SpvCapabilityShader)) {
+      if (_.HasCapability(spv::Capability::Shader)) {
         const int control_flow_nesting_depth_limit =
             _.options()->universal_limits_.max_control_flow_nesting_depth;
         for (auto block = begin(blocks); block != end(blocks); ++block) {
@@ -942,7 +948,7 @@
     }
 
     /// Structured control flow checks are only required for shader capabilities
-    if (_.HasCapability(SpvCapabilityShader)) {
+    if (_.HasCapability(spv::Capability::Shader)) {
       // Calculate structural dominance.
       postorder.clear();
       std::vector<const BasicBlock*> postdom_postorder;
@@ -998,9 +1004,9 @@
 }
 
 spv_result_t CfgPass(ValidationState_t& _, const Instruction* inst) {
-  SpvOp opcode = inst->opcode();
+  spv::Op opcode = inst->opcode();
   switch (opcode) {
-    case SpvOpLabel:
+    case spv::Op::OpLabel:
       if (auto error = _.current_function().RegisterBlock(inst->id()))
         return error;
 
@@ -1009,7 +1015,7 @@
       // passes the OpLabel ends up not being part of the basic block it starts.
       _.current_function().current_block()->set_label(inst);
       break;
-    case SpvOpLoopMerge: {
+    case spv::Op::OpLoopMerge: {
       uint32_t merge_block = inst->GetOperandAs<uint32_t>(0);
       uint32_t continue_block = inst->GetOperandAs<uint32_t>(1);
       CFG_ASSERT(MergeBlockAssert, merge_block);
@@ -1018,20 +1024,20 @@
                                                               continue_block))
         return error;
     } break;
-    case SpvOpSelectionMerge: {
+    case spv::Op::OpSelectionMerge: {
       uint32_t merge_block = inst->GetOperandAs<uint32_t>(0);
       CFG_ASSERT(MergeBlockAssert, merge_block);
 
       if (auto error = _.current_function().RegisterSelectionMerge(merge_block))
         return error;
     } break;
-    case SpvOpBranch: {
+    case spv::Op::OpBranch: {
       uint32_t target = inst->GetOperandAs<uint32_t>(0);
       CFG_ASSERT(FirstBlockAssert, target);
 
       _.current_function().RegisterBlockEnd({target});
     } break;
-    case SpvOpBranchConditional: {
+    case spv::Op::OpBranchConditional: {
       uint32_t tlabel = inst->GetOperandAs<uint32_t>(1);
       uint32_t flabel = inst->GetOperandAs<uint32_t>(2);
       CFG_ASSERT(FirstBlockAssert, tlabel);
@@ -1040,7 +1046,7 @@
       _.current_function().RegisterBlockEnd({tlabel, flabel});
     } break;
 
-    case SpvOpSwitch: {
+    case spv::Op::OpSwitch: {
       std::vector<uint32_t> cases;
       for (size_t i = 1; i < inst->operands().size(); i += 2) {
         uint32_t target = inst->GetOperandAs<uint32_t>(i);
@@ -1049,44 +1055,44 @@
       }
       _.current_function().RegisterBlockEnd({cases});
     } break;
-    case SpvOpReturn: {
+    case spv::Op::OpReturn: {
       const uint32_t return_type = _.current_function().GetResultTypeId();
       const Instruction* return_type_inst = _.FindDef(return_type);
       assert(return_type_inst);
-      if (return_type_inst->opcode() != SpvOpTypeVoid)
+      if (return_type_inst->opcode() != spv::Op::OpTypeVoid)
         return _.diag(SPV_ERROR_INVALID_CFG, inst)
                << "OpReturn can only be called from a function with void "
                << "return type.";
       _.current_function().RegisterBlockEnd(std::vector<uint32_t>());
       break;
     }
-    case SpvOpKill:
-    case SpvOpReturnValue:
-    case SpvOpUnreachable:
-    case SpvOpTerminateInvocation:
-    case SpvOpIgnoreIntersectionKHR:
-    case SpvOpTerminateRayKHR:
-    case SpvOpEmitMeshTasksEXT:
+    case spv::Op::OpKill:
+    case spv::Op::OpReturnValue:
+    case spv::Op::OpUnreachable:
+    case spv::Op::OpTerminateInvocation:
+    case spv::Op::OpIgnoreIntersectionKHR:
+    case spv::Op::OpTerminateRayKHR:
+    case spv::Op::OpEmitMeshTasksEXT:
       _.current_function().RegisterBlockEnd(std::vector<uint32_t>());
       // Ops with dedicated passes check for the Execution Model there
-      if (opcode == SpvOpKill) {
+      if (opcode == spv::Op::OpKill) {
         _.current_function().RegisterExecutionModelLimitation(
-            SpvExecutionModelFragment,
+            spv::ExecutionModel::Fragment,
             "OpKill requires Fragment execution model");
       }
-      if (opcode == SpvOpTerminateInvocation) {
+      if (opcode == spv::Op::OpTerminateInvocation) {
         _.current_function().RegisterExecutionModelLimitation(
-            SpvExecutionModelFragment,
+            spv::ExecutionModel::Fragment,
             "OpTerminateInvocation requires Fragment execution model");
       }
-      if (opcode == SpvOpIgnoreIntersectionKHR) {
+      if (opcode == spv::Op::OpIgnoreIntersectionKHR) {
         _.current_function().RegisterExecutionModelLimitation(
-            SpvExecutionModelAnyHitKHR,
+            spv::ExecutionModel::AnyHitKHR,
             "OpIgnoreIntersectionKHR requires AnyHitKHR execution model");
       }
-      if (opcode == SpvOpTerminateRayKHR) {
+      if (opcode == spv::Op::OpTerminateRayKHR) {
         _.current_function().RegisterExecutionModelLimitation(
-            SpvExecutionModelAnyHitKHR,
+            spv::ExecutionModel::AnyHitKHR,
             "OpTerminateRayKHR requires AnyHitKHR execution model");
       }
 
@@ -1140,22 +1146,22 @@
 
 spv_result_t ControlFlowPass(ValidationState_t& _, const Instruction* inst) {
   switch (inst->opcode()) {
-    case SpvOpPhi:
+    case spv::Op::OpPhi:
       if (auto error = ValidatePhi(_, inst)) return error;
       break;
-    case SpvOpBranch:
+    case spv::Op::OpBranch:
       if (auto error = ValidateBranch(_, inst)) return error;
       break;
-    case SpvOpBranchConditional:
+    case spv::Op::OpBranchConditional:
       if (auto error = ValidateBranchConditional(_, inst)) return error;
       break;
-    case SpvOpReturnValue:
+    case spv::Op::OpReturnValue:
       if (auto error = ValidateReturnValue(_, inst)) return error;
       break;
-    case SpvOpSwitch:
+    case spv::Op::OpSwitch:
       if (auto error = ValidateSwitch(_, inst)) return error;
       break;
-    case SpvOpLoopMerge:
+    case spv::Op::OpLoopMerge:
       if (auto error = ValidateLoopMerge(_, inst)) return error;
       break;
     default:
diff --git a/source/val/validate_composites.cpp b/source/val/validate_composites.cpp
index c3d948d..e777f16 100644
--- a/source/val/validate_composites.cpp
+++ b/source/val/validate_composites.cpp
@@ -35,9 +35,10 @@
 spv_result_t GetExtractInsertValueType(ValidationState_t& _,
                                        const Instruction* inst,
                                        uint32_t* member_type) {
-  const SpvOp opcode = inst->opcode();
-  assert(opcode == SpvOpCompositeExtract || opcode == SpvOpCompositeInsert);
-  uint32_t word_index = opcode == SpvOpCompositeExtract ? 4 : 5;
+  const spv::Op opcode = inst->opcode();
+  assert(opcode == spv::Op::OpCompositeExtract ||
+         opcode == spv::Op::OpCompositeInsert);
+  uint32_t word_index = opcode == spv::Op::OpCompositeExtract ? 4 : 5;
   const uint32_t num_words = static_cast<uint32_t>(inst->words().size());
   const uint32_t composite_id_index = word_index - 1;
   const uint32_t num_indices = num_words - word_index;
@@ -66,7 +67,7 @@
     const Instruction* const type_inst = _.FindDef(*member_type);
     assert(type_inst);
     switch (type_inst->opcode()) {
-      case SpvOpTypeVector: {
+      case spv::Op::OpTypeVector: {
         *member_type = type_inst->word(2);
         const uint32_t vector_size = type_inst->word(3);
         if (component_index >= vector_size) {
@@ -76,7 +77,7 @@
         }
         break;
       }
-      case SpvOpTypeMatrix: {
+      case spv::Op::OpTypeMatrix: {
         *member_type = type_inst->word(2);
         const uint32_t num_cols = type_inst->word(3);
         if (component_index >= num_cols) {
@@ -86,7 +87,7 @@
         }
         break;
       }
-      case SpvOpTypeArray: {
+      case spv::Op::OpTypeArray: {
         uint64_t array_size = 0;
         auto size = _.FindDef(type_inst->word(3));
         *member_type = type_inst->word(2);
@@ -105,12 +106,12 @@
         }
         break;
       }
-      case SpvOpTypeRuntimeArray: {
+      case spv::Op::OpTypeRuntimeArray: {
         *member_type = type_inst->word(2);
         // Array size is unknown.
         break;
       }
-      case SpvOpTypeStruct: {
+      case spv::Op::OpTypeStruct: {
         const size_t num_struct_members = type_inst->words().size() - 2;
         if (component_index >= num_struct_members) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -123,7 +124,7 @@
         *member_type = type_inst->word(component_index + 2);
         break;
       }
-      case SpvOpTypeCooperativeMatrixNV: {
+      case spv::Op::OpTypeCooperativeMatrixNV: {
         *member_type = type_inst->word(2);
         break;
       }
@@ -140,15 +141,15 @@
 spv_result_t ValidateVectorExtractDynamic(ValidationState_t& _,
                                           const Instruction* inst) {
   const uint32_t result_type = inst->type_id();
-  const SpvOp result_opcode = _.GetIdOpcode(result_type);
+  const spv::Op result_opcode = _.GetIdOpcode(result_type);
   if (!spvOpcodeIsScalarType(result_opcode)) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Result Type to be a scalar type";
   }
 
   const uint32_t vector_type = _.GetOperandTypeId(inst, 2);
-  const SpvOp vector_opcode = _.GetIdOpcode(vector_type);
-  if (vector_opcode != SpvOpTypeVector) {
+  const spv::Op vector_opcode = _.GetIdOpcode(vector_type);
+  if (vector_opcode != spv::Op::OpTypeVector) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Vector type to be OpTypeVector";
   }
@@ -164,7 +165,7 @@
            << "Expected Index to be int scalar";
   }
 
-  if (_.HasCapability(SpvCapabilityShader) &&
+  if (_.HasCapability(spv::Capability::Shader) &&
       _.ContainsLimitedUseIntOrFloatType(inst->type_id())) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Cannot extract from a vector of 8- or 16-bit types";
@@ -175,8 +176,8 @@
 spv_result_t ValidateVectorInsertDyanmic(ValidationState_t& _,
                                          const Instruction* inst) {
   const uint32_t result_type = inst->type_id();
-  const SpvOp result_opcode = _.GetIdOpcode(result_type);
-  if (result_opcode != SpvOpTypeVector) {
+  const spv::Op result_opcode = _.GetIdOpcode(result_type);
+  if (result_opcode != spv::Op::OpTypeVector) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Result Type to be OpTypeVector";
   }
@@ -200,7 +201,7 @@
            << "Expected Index to be int scalar";
   }
 
-  if (_.HasCapability(SpvCapabilityShader) &&
+  if (_.HasCapability(spv::Capability::Shader) &&
       _.ContainsLimitedUseIntOrFloatType(inst->type_id())) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Cannot insert into a vector of 8- or 16-bit types";
@@ -212,9 +213,9 @@
                                         const Instruction* inst) {
   const uint32_t num_operands = static_cast<uint32_t>(inst->operands().size());
   const uint32_t result_type = inst->type_id();
-  const SpvOp result_opcode = _.GetIdOpcode(result_type);
+  const spv::Op result_opcode = _.GetIdOpcode(result_type);
   switch (result_opcode) {
-    case SpvOpTypeVector: {
+    case spv::Op::OpTypeVector: {
       const uint32_t num_result_components = _.GetDimension(result_type);
       const uint32_t result_component_type = _.GetComponentType(result_type);
       uint32_t given_component_count = 0;
@@ -230,7 +231,7 @@
         if (operand_type == result_component_type) {
           ++given_component_count;
         } else {
-          if (_.GetIdOpcode(operand_type) != SpvOpTypeVector ||
+          if (_.GetIdOpcode(operand_type) != spv::Op::OpTypeVector ||
               _.GetComponentType(operand_type) != result_component_type) {
             return _.diag(SPV_ERROR_INVALID_DATA, inst)
                    << "Expected Constituents to be scalars or vectors of"
@@ -249,7 +250,7 @@
 
       break;
     }
-    case SpvOpTypeMatrix: {
+    case spv::Op::OpTypeMatrix: {
       uint32_t result_num_rows = 0;
       uint32_t result_num_cols = 0;
       uint32_t result_col_type = 0;
@@ -277,10 +278,10 @@
 
       break;
     }
-    case SpvOpTypeArray: {
+    case spv::Op::OpTypeArray: {
       const Instruction* const array_inst = _.FindDef(result_type);
       assert(array_inst);
-      assert(array_inst->opcode() == SpvOpTypeArray);
+      assert(array_inst->opcode() == spv::Op::OpTypeArray);
 
       auto size = _.FindDef(array_inst->word(3));
       if (spvOpcodeIsSpecConstant(size->opcode())) {
@@ -312,10 +313,10 @@
 
       break;
     }
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       const Instruction* const struct_inst = _.FindDef(result_type);
       assert(struct_inst);
-      assert(struct_inst->opcode() == SpvOpTypeStruct);
+      assert(struct_inst->opcode() == spv::Op::OpTypeStruct);
 
       if (struct_inst->operands().size() + 1 != num_operands) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -336,7 +337,7 @@
 
       break;
     }
-    case SpvOpTypeCooperativeMatrixNV: {
+    case spv::Op::OpTypeCooperativeMatrixNV: {
       const auto result_type_inst = _.FindDef(result_type);
       assert(result_type_inst);
       const auto component_type_id =
@@ -362,7 +363,7 @@
     }
   }
 
-  if (_.HasCapability(SpvCapabilityShader) &&
+  if (_.HasCapability(spv::Capability::Shader) &&
       _.ContainsLimitedUseIntOrFloatType(inst->type_id())) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Cannot create a composite containing 8- or 16-bit types";
@@ -386,7 +387,7 @@
            << spvOpcodeString(_.GetIdOpcode(member_type)) << ").";
   }
 
-  if (_.HasCapability(SpvCapabilityShader) &&
+  if (_.HasCapability(spv::Capability::Shader) &&
       _.ContainsLimitedUseIntOrFloatType(inst->type_id())) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Cannot extract from a composite of 8- or 16-bit types";
@@ -421,7 +422,7 @@
            << spvOpcodeString(_.GetIdOpcode(member_type)) << ").";
   }
 
-  if (_.HasCapability(SpvCapabilityShader) &&
+  if (_.HasCapability(spv::Capability::Shader) &&
       _.ContainsLimitedUseIntOrFloatType(inst->type_id())) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Cannot insert into a composite of 8- or 16-bit types";
@@ -480,7 +481,7 @@
            << "to be the reverse of those of Result Type";
   }
 
-  if (_.HasCapability(SpvCapabilityShader) &&
+  if (_.HasCapability(spv::Capability::Shader) &&
       _.ContainsLimitedUseIntOrFloatType(inst->type_id())) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Cannot transpose matrices of 16-bit floats";
@@ -491,11 +492,12 @@
 spv_result_t ValidateVectorShuffle(ValidationState_t& _,
                                    const Instruction* inst) {
   auto resultType = _.FindDef(inst->type_id());
-  if (!resultType || resultType->opcode() != SpvOpTypeVector) {
+  if (!resultType || resultType->opcode() != spv::Op::OpTypeVector) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "The Result Type of OpVectorShuffle must be"
            << " OpTypeVector. Found Op"
-           << spvOpcodeString(static_cast<SpvOp>(resultType->opcode())) << ".";
+           << spvOpcodeString(static_cast<spv::Op>(resultType->opcode()))
+           << ".";
   }
 
   // The number of components in Result Type must be the same as the number of
@@ -515,11 +517,11 @@
   auto vector1Type = _.FindDef(vector1Object->type_id());
   auto vector2Object = _.FindDef(inst->GetOperandAs<uint32_t>(3));
   auto vector2Type = _.FindDef(vector2Object->type_id());
-  if (!vector1Type || vector1Type->opcode() != SpvOpTypeVector) {
+  if (!vector1Type || vector1Type->opcode() != spv::Op::OpTypeVector) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "The type of Vector 1 must be OpTypeVector.";
   }
-  if (!vector2Type || vector2Type->opcode() != SpvOpTypeVector) {
+  if (!vector2Type || vector2Type->opcode() != spv::Op::OpTypeVector) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "The type of Vector 2 must be OpTypeVector.";
   }
@@ -548,7 +550,7 @@
     }
   }
 
-  if (_.HasCapability(SpvCapabilityShader) &&
+  if (_.HasCapability(spv::Capability::Shader) &&
       _.ContainsLimitedUseIntOrFloatType(inst->type_id())) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Cannot shuffle a vector of 8- or 16-bit types";
@@ -572,7 +574,7 @@
            << "Result Type does not logically match the Operand type";
   }
 
-  if (_.HasCapability(SpvCapabilityShader) &&
+  if (_.HasCapability(spv::Capability::Shader) &&
       _.ContainsLimitedUseIntOrFloatType(inst->type_id())) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Cannot copy composites of 8- or 16-bit types";
@@ -586,23 +588,23 @@
 // Validates correctness of composite instructions.
 spv_result_t CompositesPass(ValidationState_t& _, const Instruction* inst) {
   switch (inst->opcode()) {
-    case SpvOpVectorExtractDynamic:
+    case spv::Op::OpVectorExtractDynamic:
       return ValidateVectorExtractDynamic(_, inst);
-    case SpvOpVectorInsertDynamic:
+    case spv::Op::OpVectorInsertDynamic:
       return ValidateVectorInsertDyanmic(_, inst);
-    case SpvOpVectorShuffle:
+    case spv::Op::OpVectorShuffle:
       return ValidateVectorShuffle(_, inst);
-    case SpvOpCompositeConstruct:
+    case spv::Op::OpCompositeConstruct:
       return ValidateCompositeConstruct(_, inst);
-    case SpvOpCompositeExtract:
+    case spv::Op::OpCompositeExtract:
       return ValidateCompositeExtract(_, inst);
-    case SpvOpCompositeInsert:
+    case spv::Op::OpCompositeInsert:
       return ValidateCompositeInsert(_, inst);
-    case SpvOpCopyObject:
+    case spv::Op::OpCopyObject:
       return ValidateCopyObject(_, inst);
-    case SpvOpTranspose:
+    case spv::Op::OpTranspose:
       return ValidateTranspose(_, inst);
-    case SpvOpCopyLogical:
+    case spv::Op::OpCopyLogical:
       return ValidateCopyLogical(_, inst);
     default:
       break;
diff --git a/source/val/validate_constants.cpp b/source/val/validate_constants.cpp
index fdfaea5..a8ee5a6 100644
--- a/source/val/validate_constants.cpp
+++ b/source/val/validate_constants.cpp
@@ -24,7 +24,7 @@
 spv_result_t ValidateConstantBool(ValidationState_t& _,
                                   const Instruction* inst) {
   auto type = _.FindDef(inst->type_id());
-  if (!type || type->opcode() != SpvOpTypeBool) {
+  if (!type || type->opcode() != spv::Op::OpTypeBool) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Op" << spvOpcodeString(inst->opcode()) << " Result Type <id> "
            << _.getIdName(inst->type_id()) << " is not a boolean type.";
@@ -46,7 +46,7 @@
 
   const auto constituent_count = inst->words().size() - 3;
   switch (result_type->opcode()) {
-    case SpvOpTypeVector: {
+    case spv::Op::OpTypeVector: {
       const auto component_count = result_type->GetOperandAs<uint32_t>(2);
       if (component_count != constituent_count) {
         // TODO: Output ID's on diagnostic
@@ -85,7 +85,7 @@
         }
       }
     } break;
-    case SpvOpTypeMatrix: {
+    case spv::Op::OpTypeMatrix: {
       const auto column_count = result_type->GetOperandAs<uint32_t>(2);
       if (column_count != constituent_count) {
         // TODO: Output ID's on diagnostic
@@ -155,7 +155,7 @@
         }
       }
     } break;
-    case SpvOpTypeArray: {
+    case spv::Op::OpTypeArray: {
       auto element_type = _.FindDef(result_type->GetOperandAs<uint32_t>(1));
       if (!element_type) {
         return _.diag(SPV_ERROR_INVALID_ID, result_type)
@@ -203,7 +203,7 @@
         }
       }
     } break;
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       const auto member_count = result_type->words().size() - 2;
       if (member_count != constituent_count) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
@@ -243,7 +243,7 @@
         }
       }
     } break;
-    case SpvOpTypeCooperativeMatrixNV: {
+    case spv::Op::OpTypeCooperativeMatrixNV: {
       if (1 != constituent_count) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << opcode_name << " Constituent <id> "
@@ -281,7 +281,7 @@
 spv_result_t ValidateConstantSampler(ValidationState_t& _,
                                      const Instruction* inst) {
   const auto result_type = _.FindDef(inst->type_id());
-  if (!result_type || result_type->opcode() != SpvOpTypeSampler) {
+  if (!result_type || result_type->opcode() != spv::Op::OpTypeSampler) {
     return _.diag(SPV_ERROR_INVALID_ID, result_type)
            << "OpConstantSampler Result Type <id> "
            << _.getIdName(inst->type_id()) << " is not a sampler type.";
@@ -298,23 +298,23 @@
   uint16_t opcode;
   uint16_t word_count;
   spvOpcodeSplit(instruction[0], &word_count, &opcode);
-  switch (static_cast<SpvOp>(opcode)) {
-    case SpvOpTypeBool:
-    case SpvOpTypeInt:
-    case SpvOpTypeFloat:
-    case SpvOpTypeEvent:
-    case SpvOpTypeDeviceEvent:
-    case SpvOpTypeReserveId:
-    case SpvOpTypeQueue:
+  switch (static_cast<spv::Op>(opcode)) {
+    case spv::Op::OpTypeBool:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeFloat:
+    case spv::Op::OpTypeEvent:
+    case spv::Op::OpTypeDeviceEvent:
+    case spv::Op::OpTypeReserveId:
+    case spv::Op::OpTypeQueue:
       return true;
-    case SpvOpTypeArray:
-    case SpvOpTypeMatrix:
-    case SpvOpTypeCooperativeMatrixNV:
-    case SpvOpTypeVector: {
+    case spv::Op::OpTypeArray:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeCooperativeMatrixNV:
+    case spv::Op::OpTypeVector: {
       auto base_type = _.FindDef(instruction[2]);
       return base_type && IsTypeNullable(base_type->words(), _);
     }
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       for (size_t elementIndex = 2; elementIndex < instruction.size();
            ++elementIndex) {
         auto element = _.FindDef(instruction[elementIndex]);
@@ -322,8 +322,9 @@
       }
       return true;
     }
-    case SpvOpTypePointer:
-      if (instruction[2] == SpvStorageClassPhysicalStorageBuffer) {
+    case spv::Op::OpTypePointer:
+      if (spv::StorageClass(instruction[2]) ==
+          spv::StorageClass::PhysicalStorageBuffer) {
         return false;
       }
       return true;
@@ -351,7 +352,8 @@
   auto type_id = inst->GetOperandAs<const uint32_t>(0);
   auto type_instruction = _.FindDef(type_id);
   auto type_opcode = type_instruction->opcode();
-  if (type_opcode != SpvOpTypeInt && type_opcode != SpvOpTypeFloat) {
+  if (type_opcode != spv::Op::OpTypeInt &&
+      type_opcode != spv::Op::OpTypeFloat) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Specialization constant "
                                                    "must be an integer or "
                                                    "floating-point number.";
@@ -361,22 +363,22 @@
 
 spv_result_t ValidateSpecConstantOp(ValidationState_t& _,
                                     const Instruction* inst) {
-  const auto op = inst->GetOperandAs<SpvOp>(2);
+  const auto op = inst->GetOperandAs<spv::Op>(2);
 
   // The binary parser already ensures that the op is valid for *some*
   // environment.  Here we check restrictions.
   switch (op) {
-    case SpvOpQuantizeToF16:
-      if (!_.HasCapability(SpvCapabilityShader)) {
+    case spv::Op::OpQuantizeToF16:
+      if (!_.HasCapability(spv::Capability::Shader)) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << "Specialization constant operation " << spvOpcodeString(op)
                << " requires Shader capability";
       }
       break;
 
-    case SpvOpUConvert:
+    case spv::Op::OpUConvert:
       if (!_.features().uconvert_spec_constant_op &&
-          !_.HasCapability(SpvCapabilityKernel)) {
+          !_.HasCapability(spv::Capability::Kernel)) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << "Prior to SPIR-V 1.4, specialization constant operation "
                   "UConvert requires Kernel capability or extension "
@@ -384,27 +386,27 @@
       }
       break;
 
-    case SpvOpConvertFToS:
-    case SpvOpConvertSToF:
-    case SpvOpConvertFToU:
-    case SpvOpConvertUToF:
-    case SpvOpConvertPtrToU:
-    case SpvOpConvertUToPtr:
-    case SpvOpGenericCastToPtr:
-    case SpvOpPtrCastToGeneric:
-    case SpvOpBitcast:
-    case SpvOpFNegate:
-    case SpvOpFAdd:
-    case SpvOpFSub:
-    case SpvOpFMul:
-    case SpvOpFDiv:
-    case SpvOpFRem:
-    case SpvOpFMod:
-    case SpvOpAccessChain:
-    case SpvOpInBoundsAccessChain:
-    case SpvOpPtrAccessChain:
-    case SpvOpInBoundsPtrAccessChain:
-      if (!_.HasCapability(SpvCapabilityKernel)) {
+    case spv::Op::OpConvertFToS:
+    case spv::Op::OpConvertSToF:
+    case spv::Op::OpConvertFToU:
+    case spv::Op::OpConvertUToF:
+    case spv::Op::OpConvertPtrToU:
+    case spv::Op::OpConvertUToPtr:
+    case spv::Op::OpGenericCastToPtr:
+    case spv::Op::OpPtrCastToGeneric:
+    case spv::Op::OpBitcast:
+    case spv::Op::OpFNegate:
+    case spv::Op::OpFAdd:
+    case spv::Op::OpFSub:
+    case spv::Op::OpFMul:
+    case spv::Op::OpFDiv:
+    case spv::Op::OpFRem:
+    case spv::Op::OpFMod:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
+    case spv::Op::OpPtrAccessChain:
+    case spv::Op::OpInBoundsPtrAccessChain:
+      if (!_.HasCapability(spv::Capability::Kernel)) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << "Specialization constant operation " << spvOpcodeString(op)
                << " requires Kernel capability";
@@ -423,26 +425,26 @@
 
 spv_result_t ConstantPass(ValidationState_t& _, const Instruction* inst) {
   switch (inst->opcode()) {
-    case SpvOpConstantTrue:
-    case SpvOpConstantFalse:
-    case SpvOpSpecConstantTrue:
-    case SpvOpSpecConstantFalse:
+    case spv::Op::OpConstantTrue:
+    case spv::Op::OpConstantFalse:
+    case spv::Op::OpSpecConstantTrue:
+    case spv::Op::OpSpecConstantFalse:
       if (auto error = ValidateConstantBool(_, inst)) return error;
       break;
-    case SpvOpConstantComposite:
-    case SpvOpSpecConstantComposite:
+    case spv::Op::OpConstantComposite:
+    case spv::Op::OpSpecConstantComposite:
       if (auto error = ValidateConstantComposite(_, inst)) return error;
       break;
-    case SpvOpConstantSampler:
+    case spv::Op::OpConstantSampler:
       if (auto error = ValidateConstantSampler(_, inst)) return error;
       break;
-    case SpvOpConstantNull:
+    case spv::Op::OpConstantNull:
       if (auto error = ValidateConstantNull(_, inst)) return error;
       break;
-    case SpvOpSpecConstant:
+    case spv::Op::OpSpecConstant:
       if (auto error = ValidateSpecConstant(_, inst)) return error;
       break;
-    case SpvOpSpecConstantOp:
+    case spv::Op::OpSpecConstantOp:
       if (auto error = ValidateSpecConstantOp(_, inst)) return error;
       break;
     default:
@@ -452,7 +454,7 @@
   // Generally disallow creating 8- or 16-bit constants unless the full
   // capabilities are present.
   if (spvOpcodeIsConstant(inst->opcode()) &&
-      _.HasCapability(SpvCapabilityShader) &&
+      _.HasCapability(spv::Capability::Shader) &&
       !_.IsPointerType(inst->type_id()) &&
       _.ContainsLimitedUseIntOrFloatType(inst->type_id())) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
diff --git a/source/val/validate_conversion.cpp b/source/val/validate_conversion.cpp
index dc6b151..c67b196 100644
--- a/source/val/validate_conversion.cpp
+++ b/source/val/validate_conversion.cpp
@@ -27,11 +27,11 @@
 
 // Validates correctness of conversion instructions.
 spv_result_t ConversionPass(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   const uint32_t result_type = inst->type_id();
 
   switch (opcode) {
-    case SpvOpConvertFToU: {
+    case spv::Op::OpConvertFToU: {
       if (!_.IsUnsignedIntScalarType(result_type) &&
           !_.IsUnsignedIntVectorType(result_type) &&
           !_.IsUnsignedIntCooperativeMatrixType(result_type))
@@ -62,7 +62,7 @@
       break;
     }
 
-    case SpvOpConvertFToS: {
+    case spv::Op::OpConvertFToS: {
       if (!_.IsIntScalarType(result_type) && !_.IsIntVectorType(result_type) &&
           !_.IsIntCooperativeMatrixType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -92,8 +92,8 @@
       break;
     }
 
-    case SpvOpConvertSToF:
-    case SpvOpConvertUToF: {
+    case spv::Op::OpConvertSToF:
+    case spv::Op::OpConvertUToF: {
       if (!_.IsFloatScalarType(result_type) &&
           !_.IsFloatVectorType(result_type) &&
           !_.IsFloatCooperativeMatrixType(result_type))
@@ -124,7 +124,7 @@
       break;
     }
 
-    case SpvOpUConvert: {
+    case spv::Op::OpUConvert: {
       if (!_.IsUnsignedIntScalarType(result_type) &&
           !_.IsUnsignedIntVectorType(result_type) &&
           !_.IsUnsignedIntCooperativeMatrixType(result_type))
@@ -160,7 +160,7 @@
       break;
     }
 
-    case SpvOpSConvert: {
+    case spv::Op::OpSConvert: {
       if (!_.IsIntScalarType(result_type) && !_.IsIntVectorType(result_type) &&
           !_.IsIntCooperativeMatrixType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -195,7 +195,7 @@
       break;
     }
 
-    case SpvOpFConvert: {
+    case spv::Op::OpFConvert: {
       if (!_.IsFloatScalarType(result_type) &&
           !_.IsFloatVectorType(result_type) &&
           !_.IsFloatCooperativeMatrixType(result_type))
@@ -231,7 +231,7 @@
       break;
     }
 
-    case SpvOpQuantizeToF16: {
+    case spv::Op::OpQuantizeToF16: {
       if ((!_.IsFloatScalarType(result_type) &&
            !_.IsFloatVectorType(result_type)) ||
           _.GetBitWidth(result_type) != 32)
@@ -247,7 +247,7 @@
       break;
     }
 
-    case SpvOpConvertPtrToU: {
+    case spv::Op::OpConvertPtrToU: {
       if (!_.IsUnsignedIntScalarType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected unsigned int scalar type as Result Type: "
@@ -258,17 +258,18 @@
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected input to be a pointer: " << spvOpcodeString(opcode);
 
-      if (_.addressing_model() == SpvAddressingModelLogical)
+      if (_.addressing_model() == spv::AddressingModel::Logical)
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Logical addressing not supported: "
                << spvOpcodeString(opcode);
 
-      if (_.addressing_model() == SpvAddressingModelPhysicalStorageBuffer64) {
-        uint32_t input_storage_class = 0;
+      if (_.addressing_model() ==
+          spv::AddressingModel::PhysicalStorageBuffer64) {
+        spv::StorageClass input_storage_class;
         uint32_t input_data_type = 0;
         _.GetPointerTypeInfo(input_type, &input_data_type,
                              &input_storage_class);
-        if (input_storage_class != SpvStorageClassPhysicalStorageBuffer)
+        if (input_storage_class != spv::StorageClass::PhysicalStorageBuffer)
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << "Pointer storage class must be PhysicalStorageBuffer: "
                  << spvOpcodeString(opcode);
@@ -286,8 +287,8 @@
       break;
     }
 
-    case SpvOpSatConvertSToU:
-    case SpvOpSatConvertUToS: {
+    case spv::Op::OpSatConvertSToU:
+    case spv::Op::OpSatConvertUToS: {
       if (!_.IsIntScalarType(result_type) && !_.IsIntVectorType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected int scalar or vector type as Result Type: "
@@ -307,7 +308,7 @@
       break;
     }
 
-    case SpvOpConvertUToPtr: {
+    case spv::Op::OpConvertUToPtr: {
       if (!_.IsPointerType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected Result Type to be a pointer: "
@@ -318,17 +319,18 @@
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected int scalar as input: " << spvOpcodeString(opcode);
 
-      if (_.addressing_model() == SpvAddressingModelLogical)
+      if (_.addressing_model() == spv::AddressingModel::Logical)
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Logical addressing not supported: "
                << spvOpcodeString(opcode);
 
-      if (_.addressing_model() == SpvAddressingModelPhysicalStorageBuffer64) {
-        uint32_t result_storage_class = 0;
+      if (_.addressing_model() ==
+          spv::AddressingModel::PhysicalStorageBuffer64) {
+        spv::StorageClass result_storage_class;
         uint32_t result_data_type = 0;
         _.GetPointerTypeInfo(result_type, &result_data_type,
                              &result_storage_class);
-        if (result_storage_class != SpvStorageClassPhysicalStorageBuffer)
+        if (result_storage_class != spv::StorageClass::PhysicalStorageBuffer)
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << "Pointer storage class must be PhysicalStorageBuffer: "
                  << spvOpcodeString(opcode);
@@ -346,8 +348,8 @@
       break;
     }
 
-    case SpvOpPtrCastToGeneric: {
-      uint32_t result_storage_class = 0;
+    case spv::Op::OpPtrCastToGeneric: {
+      spv::StorageClass result_storage_class;
       uint32_t result_data_type = 0;
       if (!_.GetPointerTypeInfo(result_type, &result_data_type,
                                 &result_storage_class))
@@ -355,22 +357,22 @@
                << "Expected Result Type to be a pointer: "
                << spvOpcodeString(opcode);
 
-      if (result_storage_class != SpvStorageClassGeneric)
+      if (result_storage_class != spv::StorageClass::Generic)
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected Result Type to have storage class Generic: "
                << spvOpcodeString(opcode);
 
       const uint32_t input_type = _.GetOperandTypeId(inst, 2);
-      uint32_t input_storage_class = 0;
+      spv::StorageClass input_storage_class;
       uint32_t input_data_type = 0;
       if (!_.GetPointerTypeInfo(input_type, &input_data_type,
                                 &input_storage_class))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected input to be a pointer: " << spvOpcodeString(opcode);
 
-      if (input_storage_class != SpvStorageClassWorkgroup &&
-          input_storage_class != SpvStorageClassCrossWorkgroup &&
-          input_storage_class != SpvStorageClassFunction)
+      if (input_storage_class != spv::StorageClass::Workgroup &&
+          input_storage_class != spv::StorageClass::CrossWorkgroup &&
+          input_storage_class != spv::StorageClass::Function)
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected input to have storage class Workgroup, "
                << "CrossWorkgroup or Function: " << spvOpcodeString(opcode);
@@ -382,8 +384,8 @@
       break;
     }
 
-    case SpvOpGenericCastToPtr: {
-      uint32_t result_storage_class = 0;
+    case spv::Op::OpGenericCastToPtr: {
+      spv::StorageClass result_storage_class;
       uint32_t result_data_type = 0;
       if (!_.GetPointerTypeInfo(result_type, &result_data_type,
                                 &result_storage_class))
@@ -391,22 +393,22 @@
                << "Expected Result Type to be a pointer: "
                << spvOpcodeString(opcode);
 
-      if (result_storage_class != SpvStorageClassWorkgroup &&
-          result_storage_class != SpvStorageClassCrossWorkgroup &&
-          result_storage_class != SpvStorageClassFunction)
+      if (result_storage_class != spv::StorageClass::Workgroup &&
+          result_storage_class != spv::StorageClass::CrossWorkgroup &&
+          result_storage_class != spv::StorageClass::Function)
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected Result Type to have storage class Workgroup, "
                << "CrossWorkgroup or Function: " << spvOpcodeString(opcode);
 
       const uint32_t input_type = _.GetOperandTypeId(inst, 2);
-      uint32_t input_storage_class = 0;
+      spv::StorageClass input_storage_class;
       uint32_t input_data_type = 0;
       if (!_.GetPointerTypeInfo(input_type, &input_data_type,
                                 &input_storage_class))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected input to be a pointer: " << spvOpcodeString(opcode);
 
-      if (input_storage_class != SpvStorageClassGeneric)
+      if (input_storage_class != spv::StorageClass::Generic)
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected input to have storage class Generic: "
                << spvOpcodeString(opcode);
@@ -418,8 +420,8 @@
       break;
     }
 
-    case SpvOpGenericCastToPtrExplicit: {
-      uint32_t result_storage_class = 0;
+    case spv::Op::OpGenericCastToPtrExplicit: {
+      spv::StorageClass result_storage_class;
       uint32_t result_data_type = 0;
       if (!_.GetPointerTypeInfo(result_type, &result_data_type,
                                 &result_storage_class))
@@ -427,21 +429,22 @@
                << "Expected Result Type to be a pointer: "
                << spvOpcodeString(opcode);
 
-      const uint32_t target_storage_class = inst->word(4);
+      const auto target_storage_class =
+          inst->GetOperandAs<spv::StorageClass>(3);
       if (result_storage_class != target_storage_class)
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected Result Type to be of target storage class: "
                << spvOpcodeString(opcode);
 
       const uint32_t input_type = _.GetOperandTypeId(inst, 2);
-      uint32_t input_storage_class = 0;
+      spv::StorageClass input_storage_class;
       uint32_t input_data_type = 0;
       if (!_.GetPointerTypeInfo(input_type, &input_data_type,
                                 &input_storage_class))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected input to be a pointer: " << spvOpcodeString(opcode);
 
-      if (input_storage_class != SpvStorageClassGeneric)
+      if (input_storage_class != spv::StorageClass::Generic)
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected input to have storage class Generic: "
                << spvOpcodeString(opcode);
@@ -451,16 +454,16 @@
                << "Expected input and Result Type to point to the same type: "
                << spvOpcodeString(opcode);
 
-      if (target_storage_class != SpvStorageClassWorkgroup &&
-          target_storage_class != SpvStorageClassCrossWorkgroup &&
-          target_storage_class != SpvStorageClassFunction)
+      if (target_storage_class != spv::StorageClass::Workgroup &&
+          target_storage_class != spv::StorageClass::CrossWorkgroup &&
+          target_storage_class != spv::StorageClass::Function)
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected target storage class to be Workgroup, "
                << "CrossWorkgroup or Function: " << spvOpcodeString(opcode);
       break;
     }
 
-    case SpvOpBitcast: {
+    case spv::Op::OpBitcast: {
       const uint32_t input_type = _.GetOperandTypeId(inst, 2);
       if (!input_type)
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -490,10 +493,10 @@
           _.HasExtension(kSPV_KHR_physical_storage_buffer)) {
         const bool result_is_int_vector = _.IsIntVectorType(result_type);
         const bool result_has_int32 =
-            _.ContainsSizedIntOrFloatType(result_type, SpvOpTypeInt, 32);
+            _.ContainsSizedIntOrFloatType(result_type, spv::Op::OpTypeInt, 32);
         const bool input_is_int_vector = _.IsIntVectorType(input_type);
         const bool input_has_int32 =
-            _.ContainsSizedIntOrFloatType(input_type, SpvOpTypeInt, 32);
+            _.ContainsSizedIntOrFloatType(input_type, spv::Op::OpTypeInt, 32);
         if (result_is_pointer && !input_is_pointer && !input_is_int_scalar &&
             !(input_is_int_vector && input_has_int32))
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -534,7 +537,7 @@
       break;
     }
 
-    case SpvOpConvertUToAccelerationStructureKHR: {
+    case spv::Op::OpConvertUToAccelerationStructureKHR: {
       if (!_.IsAccelerationStructureType(result_type)) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected Result Type to be a Acceleration Structure: "
@@ -556,13 +559,13 @@
       break;
   }
 
-  if (_.HasCapability(SpvCapabilityShader)) {
+  if (_.HasCapability(spv::Capability::Shader)) {
     switch (inst->opcode()) {
-      case SpvOpConvertFToU:
-      case SpvOpConvertFToS:
-      case SpvOpConvertSToF:
-      case SpvOpConvertUToF:
-      case SpvOpBitcast:
+      case spv::Op::OpConvertFToU:
+      case spv::Op::OpConvertFToS:
+      case spv::Op::OpConvertSToF:
+      case spv::Op::OpConvertUToF:
+      case spv::Op::OpBitcast:
         if (_.ContainsLimitedUseIntOrFloatType(inst->type_id()) ||
             _.ContainsLimitedUseIntOrFloatType(_.GetOperandTypeId(inst, 2u))) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
diff --git a/source/val/validate_debug.cpp b/source/val/validate_debug.cpp
index 7ab597a..c433c93 100644
--- a/source/val/validate_debug.cpp
+++ b/source/val/validate_debug.cpp
@@ -26,7 +26,7 @@
 spv_result_t ValidateMemberName(ValidationState_t& _, const Instruction* inst) {
   const auto type_id = inst->GetOperandAs<uint32_t>(0);
   const auto type = _.FindDef(type_id);
-  if (!type || SpvOpTypeStruct != type->opcode()) {
+  if (!type || spv::Op::OpTypeStruct != type->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "OpMemberName Type <id> " << _.getIdName(type_id)
            << " is not a struct type.";
@@ -45,7 +45,7 @@
 spv_result_t ValidateLine(ValidationState_t& _, const Instruction* inst) {
   const auto file_id = inst->GetOperandAs<uint32_t>(0);
   const auto file = _.FindDef(file_id);
-  if (!file || SpvOpString != file->opcode()) {
+  if (!file || spv::Op::OpString != file->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "OpLine Target <id> " << _.getIdName(file_id)
            << " is not an OpString.";
@@ -57,10 +57,10 @@
 
 spv_result_t DebugPass(ValidationState_t& _, const Instruction* inst) {
   switch (inst->opcode()) {
-    case SpvOpMemberName:
+    case spv::Op::OpMemberName:
       if (auto error = ValidateMemberName(_, inst)) return error;
       break;
-    case SpvOpLine:
+    case spv::Op::OpLine:
       if (auto error = ValidateLine(_, inst)) return error;
       break;
     default:
diff --git a/source/val/validate_decorations.cpp b/source/val/validate_decorations.cpp
index cd0ff20..55a2681 100644
--- a/source/val/validate_decorations.cpp
+++ b/source/val/validate_decorations.cpp
@@ -50,7 +50,7 @@
 
 // A functor for hashing decoration types.
 struct SpvDecorationHash {
-  std::size_t operator()(SpvDecoration dec) const {
+  std::size_t operator()(spv::Decoration dec) const {
     return static_cast<std::size_t>(dec);
   }
 };
@@ -72,7 +72,7 @@
 // Returns the array stride of the given array type.
 uint32_t GetArrayStride(uint32_t array_id, ValidationState_t& vstate) {
   for (auto& decoration : vstate.id_decorations(array_id)) {
-    if (SpvDecorationArrayStride == decoration.dec_type()) {
+    if (spv::Decoration::ArrayStride == decoration.dec_type()) {
       return decoration.params()[0];
     }
   }
@@ -82,9 +82,10 @@
 // Returns true if the given variable has a BuiltIn decoration.
 bool isBuiltInVar(uint32_t var_id, ValidationState_t& vstate) {
   const auto& decorations = vstate.id_decorations(var_id);
-  return std::any_of(
-      decorations.begin(), decorations.end(),
-      [](const Decoration& d) { return SpvDecorationBuiltIn == d.dec_type(); });
+  return std::any_of(decorations.begin(), decorations.end(),
+                     [](const Decoration& d) {
+                       return spv::Decoration::BuiltIn == d.dec_type();
+                     });
 }
 
 // Returns true if the given structure type has any members with BuiltIn
@@ -93,7 +94,7 @@
   const auto& decorations = vstate.id_decorations(struct_id);
   return std::any_of(
       decorations.begin(), decorations.end(), [](const Decoration& d) {
-        return SpvDecorationBuiltIn == d.dec_type() &&
+        return spv::Decoration::BuiltIn == d.dec_type() &&
                Decoration::kInvalidMember != d.struct_member_index();
       });
 }
@@ -101,20 +102,21 @@
 // Returns true if the given structure type has a Block decoration.
 bool isBlock(uint32_t struct_id, ValidationState_t& vstate) {
   const auto& decorations = vstate.id_decorations(struct_id);
-  return std::any_of(
-      decorations.begin(), decorations.end(),
-      [](const Decoration& d) { return SpvDecorationBlock == d.dec_type(); });
+  return std::any_of(decorations.begin(), decorations.end(),
+                     [](const Decoration& d) {
+                       return spv::Decoration::Block == d.dec_type();
+                     });
 }
 
 // Returns true if the given ID has the Import LinkageAttributes decoration.
 bool hasImportLinkageAttribute(uint32_t id, ValidationState_t& vstate) {
   const auto& decorations = vstate.id_decorations(id);
-  return std::any_of(decorations.begin(), decorations.end(),
-                     [](const Decoration& d) {
-                       return SpvDecorationLinkageAttributes == d.dec_type() &&
-                              d.params().size() >= 2u &&
-                              d.params().back() == SpvLinkageTypeImport;
-                     });
+  return std::any_of(
+      decorations.begin(), decorations.end(), [](const Decoration& d) {
+        return spv::Decoration::LinkageAttributes == d.dec_type() &&
+               d.params().size() >= 2u &&
+               spv::LinkageType(d.params().back()) == spv::LinkageType::Import;
+      });
 }
 
 // Returns a vector of all members of a structure.
@@ -125,7 +127,7 @@
 }
 
 // Returns a vector of all members of a structure that have specific type.
-std::vector<uint32_t> getStructMembers(uint32_t struct_id, SpvOp type,
+std::vector<uint32_t> getStructMembers(uint32_t struct_id, spv::Op type,
                                        ValidationState_t& vstate) {
   std::vector<uint32_t> members;
   for (auto id : getStructMembers(struct_id, vstate)) {
@@ -142,21 +144,21 @@
   const auto* inst = vstate.FindDef(struct_id);
   std::vector<bool> hasOffset;
   std::vector<uint32_t> struct_members;
-  if (inst->opcode() == SpvOpTypeStruct) {
+  if (inst->opcode() == spv::Op::OpTypeStruct) {
     // Check offsets of member decorations.
     struct_members = getStructMembers(struct_id, vstate);
     hasOffset.resize(struct_members.size(), false);
 
     for (auto& decoration : vstate.id_decorations(struct_id)) {
-      if (SpvDecorationOffset == decoration.dec_type() &&
+      if (spv::Decoration::Offset == decoration.dec_type() &&
           Decoration::kInvalidMember != decoration.struct_member_index()) {
         // Offset 0xffffffff is not valid so ignore it for simplicity's sake.
         if (decoration.params()[0] == 0xffffffff) return true;
         hasOffset[decoration.struct_member_index()] = true;
       }
     }
-  } else if (inst->opcode() == SpvOpTypeArray ||
-             inst->opcode() == SpvOpTypeRuntimeArray) {
+  } else if (inst->opcode() == spv::Op::OpTypeArray ||
+             inst->opcode() == spv::Op::OpTypeRuntimeArray) {
     hasOffset.resize(1, true);
     struct_members.push_back(inst->GetOperandAs<uint32_t>(1u));
   }
@@ -191,18 +193,18 @@
   // Minimal alignment is byte-aligned.
   uint32_t baseAlignment = 1;
   switch (inst->opcode()) {
-    case SpvOpTypeSampledImage:
-    case SpvOpTypeSampler:
-    case SpvOpTypeImage:
-      if (vstate.HasCapability(SpvCapabilityBindlessTextureNV))
+    case spv::Op::OpTypeSampledImage:
+    case spv::Op::OpTypeSampler:
+    case spv::Op::OpTypeImage:
+      if (vstate.HasCapability(spv::Capability::BindlessTextureNV))
         return baseAlignment = vstate.samplerimage_variable_address_mode() / 8;
       assert(0);
       return 0;
-    case SpvOpTypeInt:
-    case SpvOpTypeFloat:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeFloat:
       baseAlignment = words[2] / 8;
       break;
-    case SpvOpTypeVector: {
+    case spv::Op::OpTypeVector: {
       const auto componentId = words[2];
       const auto numComponents = words[3];
       const auto componentAlignment = getBaseAlignment(
@@ -211,7 +213,7 @@
           componentAlignment * (numComponents == 3 ? 4 : numComponents);
       break;
     }
-    case SpvOpTypeMatrix: {
+    case spv::Op::OpTypeMatrix: {
       const auto column_type = words[2];
       if (inherited.majorness == kColumnMajor) {
         baseAlignment = getBaseAlignment(column_type, roundUp, inherited,
@@ -229,13 +231,13 @@
       }
       if (roundUp) baseAlignment = align(baseAlignment, 16u);
     } break;
-    case SpvOpTypeArray:
-    case SpvOpTypeRuntimeArray:
+    case spv::Op::OpTypeArray:
+    case spv::Op::OpTypeRuntimeArray:
       baseAlignment =
           getBaseAlignment(words[2], roundUp, inherited, constraints, vstate);
       if (roundUp) baseAlignment = align(baseAlignment, 16u);
       break;
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       const auto members = getStructMembers(member_id, vstate);
       for (uint32_t memberIdx = 0, numMembers = uint32_t(members.size());
            memberIdx < numMembers; ++memberIdx) {
@@ -249,7 +251,7 @@
       if (roundUp) baseAlignment = align(baseAlignment, 16u);
       break;
     }
-    case SpvOpTypePointer:
+    case spv::Op::OpTypePointer:
       baseAlignment = vstate.pointer_size_and_alignment();
       break;
     default:
@@ -265,24 +267,24 @@
   const auto inst = vstate.FindDef(type_id);
   const auto& words = inst->words();
   switch (inst->opcode()) {
-    case SpvOpTypeSampledImage:
-    case SpvOpTypeSampler:
-    case SpvOpTypeImage:
-      if (vstate.HasCapability(SpvCapabilityBindlessTextureNV))
+    case spv::Op::OpTypeSampledImage:
+    case spv::Op::OpTypeSampler:
+    case spv::Op::OpTypeImage:
+      if (vstate.HasCapability(spv::Capability::BindlessTextureNV))
         return vstate.samplerimage_variable_address_mode() / 8;
       assert(0);
       return 0;
-    case SpvOpTypeInt:
-    case SpvOpTypeFloat:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeFloat:
       return words[2] / 8;
-    case SpvOpTypeVector:
-    case SpvOpTypeMatrix:
-    case SpvOpTypeArray:
-    case SpvOpTypeRuntimeArray: {
+    case spv::Op::OpTypeVector:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeArray:
+    case spv::Op::OpTypeRuntimeArray: {
       const auto compositeMemberTypeId = words[2];
       return getScalarAlignment(compositeMemberTypeId, vstate);
     }
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       const auto members = getStructMembers(type_id, vstate);
       uint32_t max_member_alignment = 1;
       for (uint32_t memberIdx = 0, numMembers = uint32_t(members.size());
@@ -295,7 +297,7 @@
       }
       return max_member_alignment;
     } break;
-    case SpvOpTypePointer:
+    case spv::Op::OpTypePointer:
       return vstate.pointer_size_and_alignment();
     default:
       assert(0);
@@ -312,17 +314,17 @@
   const auto inst = vstate.FindDef(member_id);
   const auto& words = inst->words();
   switch (inst->opcode()) {
-    case SpvOpTypeSampledImage:
-    case SpvOpTypeSampler:
-    case SpvOpTypeImage:
-      if (vstate.HasCapability(SpvCapabilityBindlessTextureNV))
+    case spv::Op::OpTypeSampledImage:
+    case spv::Op::OpTypeSampler:
+    case spv::Op::OpTypeImage:
+      if (vstate.HasCapability(spv::Capability::BindlessTextureNV))
         return vstate.samplerimage_variable_address_mode() / 8;
       assert(0);
       return 0;
-    case SpvOpTypeInt:
-    case SpvOpTypeFloat:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeFloat:
       return words[2] / 8;
-    case SpvOpTypeVector: {
+    case spv::Op::OpTypeVector: {
       const auto componentId = words[2];
       const auto numComponents = words[3];
       const auto componentSize =
@@ -330,10 +332,10 @@
       const auto size = componentSize * numComponents;
       return size;
     }
-    case SpvOpTypeArray: {
+    case spv::Op::OpTypeArray: {
       const auto sizeInst = vstate.FindDef(words[3]);
       if (spvOpcodeIsSpecConstant(sizeInst->opcode())) return 0;
-      assert(SpvOpConstant == sizeInst->opcode());
+      assert(spv::Op::OpConstant == sizeInst->opcode());
       const uint32_t num_elem = sizeInst->words()[3];
       const uint32_t elem_type = words[2];
       const uint32_t elem_size =
@@ -344,9 +346,9 @@
           (num_elem - 1) * GetArrayStride(member_id, vstate) + elem_size;
       return size;
     }
-    case SpvOpTypeRuntimeArray:
+    case spv::Op::OpTypeRuntimeArray:
       return 0;
-    case SpvOpTypeMatrix: {
+    case spv::Op::OpTypeMatrix: {
       const auto num_columns = words[3];
       if (inherited.majorness == kColumnMajor) {
         return num_columns * inherited.matrix_stride;
@@ -362,7 +364,7 @@
                num_columns * scalar_elem_size;
       }
     }
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       const auto& members = getStructMembers(member_id, vstate);
       if (members.empty()) return 0;
       const auto lastIdx = uint32_t(members.size() - 1);
@@ -374,7 +376,7 @@
       for (auto decoration = member_decorations.begin;
            decoration != member_decorations.end; ++decoration) {
         assert(decoration->struct_member_index() == (int)lastIdx);
-        if (SpvDecorationOffset == decoration->dec_type()) {
+        if (spv::Decoration::Offset == decoration->dec_type()) {
           offset = decoration->params()[0];
         }
       }
@@ -384,7 +386,7 @@
       const auto& constraint = constraints[std::make_pair(lastMember, lastIdx)];
       return offset + getSize(lastMember, constraint, constraints, vstate);
     }
-    case SpvOpTypePointer:
+    case spv::Op::OpTypePointer:
       return vstate.pointer_size_and_alignment();
     default:
       assert(0);
@@ -477,7 +479,7 @@
          decoration != member_decorations.end; ++decoration) {
       assert(decoration->struct_member_index() == (int)memberIdx);
       switch (decoration->dec_type()) {
-        case SpvDecorationOffset:
+        case spv::Decoration::Offset:
           offset = decoration->params()[0];
           break;
         default:
@@ -517,7 +519,7 @@
     if (offset == 0xffffffff)
       return fail(memberIdx) << "is missing an Offset decoration";
     if (!scalar_block_layout && relaxed_block_layout &&
-        opcode == SpvOpTypeVector) {
+        opcode == spv::Op::OpTypeVector) {
       // In relaxed block layout, the vector offset must be aligned to the
       // vector's scalar element type.
       const auto componentId = inst->words()[2];
@@ -541,21 +543,20 @@
                              << nextValidOffset - 1;
     if (!scalar_block_layout && relaxed_block_layout) {
       // Check improper straddle of vectors.
-      if (SpvOpTypeVector == opcode &&
+      if (spv::Op::OpTypeVector == opcode &&
           hasImproperStraddle(id, offset, constraint, constraints, vstate))
         return fail(memberIdx)
                << "is an improperly straddling vector at offset " << offset;
     }
     // Check struct members recursively.
     spv_result_t recursive_status = SPV_SUCCESS;
-    if (SpvOpTypeStruct == opcode &&
+    if (spv::Op::OpTypeStruct == opcode &&
         SPV_SUCCESS != (recursive_status = checkLayout(
                             id, storage_class_str, decoration_str, blockRules,
-                            scalar_block_layout,
-                            offset, constraints, vstate)))
+                            scalar_block_layout, offset, constraints, vstate)))
       return recursive_status;
     // Check matrix stride.
-    if (SpvOpTypeMatrix == opcode) {
+    if (spv::Op::OpTypeMatrix == opcode) {
       const auto stride = constraint.matrix_stride;
       if (!IsAlignedTo(stride, alignment)) {
         return fail(memberIdx) << "is a matrix with stride " << stride
@@ -566,14 +567,14 @@
     // Check arrays and runtime arrays recursively.
     auto array_inst = inst;
     auto array_alignment = alignment;
-    while (array_inst->opcode() == SpvOpTypeArray ||
-           array_inst->opcode() == SpvOpTypeRuntimeArray) {
+    while (array_inst->opcode() == spv::Op::OpTypeArray ||
+           array_inst->opcode() == spv::Op::OpTypeRuntimeArray) {
       const auto typeId = array_inst->word(2);
       const auto element_inst = vstate.FindDef(typeId);
       // Check array stride.
       uint32_t array_stride = 0;
       for (auto& decoration : vstate.id_decorations(array_inst->id())) {
-        if (SpvDecorationArrayStride == decoration.dec_type()) {
+        if (spv::Decoration::ArrayStride == decoration.dec_type()) {
           array_stride = decoration.params()[0];
           if (array_stride == 0) {
             return fail(memberIdx) << "contains an array with stride 0";
@@ -588,7 +589,7 @@
       bool is_int32 = false;
       bool is_const = false;
       uint32_t num_elements = 0;
-      if (array_inst->opcode() == SpvOpTypeArray) {
+      if (array_inst->opcode() == spv::Op::OpTypeArray) {
         std::tie(is_int32, is_const, num_elements) =
             vstate.EvalInt32IfConst(array_inst->word(3));
       }
@@ -597,7 +598,7 @@
       // limitation to this check if the array size is a spec constant or is a
       // runtime array then we will only check a single element. This means
       // some improper straddles might be missed.
-      if (SpvOpTypeStruct == element_inst->opcode()) {
+      if (spv::Op::OpTypeStruct == element_inst->opcode()) {
         std::vector<bool> seen(16, false);
         for (uint32_t i = 0; i < num_elements; ++i) {
           uint32_t next_offset = i * array_stride + offset;
@@ -633,7 +634,7 @@
     }
     nextValidOffset = offset + size;
     if (!scalar_block_layout && blockRules &&
-        (SpvOpTypeArray == opcode || SpvOpTypeStruct == opcode)) {
+        (spv::Op::OpTypeArray == opcode || spv::Op::OpTypeStruct == opcode)) {
       // Uniform block rules don't permit anything in the padding of a struct
       // or array.
       nextValidOffset = align(nextValidOffset, alignment);
@@ -644,15 +645,15 @@
 
 // Returns true if variable or structure id has given decoration. Handles also
 // nested structures.
-bool hasDecoration(uint32_t id, SpvDecoration decoration,
+bool hasDecoration(uint32_t id, spv::Decoration decoration,
                    ValidationState_t& vstate) {
   for (auto& dec : vstate.id_decorations(id)) {
     if (decoration == dec.dec_type()) return true;
   }
-  if (SpvOpTypeStruct != vstate.FindDef(id)->opcode()) {
+  if (spv::Op::OpTypeStruct != vstate.FindDef(id)->opcode()) {
     return false;
   }
-  for (auto member_id : getStructMembers(id, SpvOpTypeStruct, vstate)) {
+  for (auto member_id : getStructMembers(id, spv::Op::OpTypeStruct, vstate)) {
     if (hasDecoration(member_id, decoration, vstate)) {
       return true;
     }
@@ -662,8 +663,8 @@
 
 // Returns true if all ids of given type have a specified decoration.
 bool checkForRequiredDecoration(uint32_t struct_id,
-                                std::function<bool(SpvDecoration)> checker,
-                                SpvOp type, ValidationState_t& vstate) {
+                                std::function<bool(spv::Decoration)> checker,
+                                spv::Op type, ValidationState_t& vstate) {
   const auto& members = getStructMembers(struct_id, vstate);
   for (size_t memberIdx = 0; memberIdx < members.size(); memberIdx++) {
     const auto id = members[memberIdx];
@@ -682,7 +683,7 @@
       return false;
     }
   }
-  for (auto id : getStructMembers(struct_id, SpvOpTypeStruct, vstate)) {
+  for (auto id : getStructMembers(struct_id, spv::Op::OpTypeStruct, vstate)) {
     if (!checkForRequiredDecoration(id, checker, type, vstate)) {
       return false;
     }
@@ -738,8 +739,8 @@
   const auto& decorations = vstate.id_decorations(var_id);
   for (const auto& d : decorations) {
     if (spvIsVulkanEnv(vstate.context()->target_env)) {
-      if (d.dec_type() == SpvDecorationLocation ||
-          d.dec_type() == SpvDecorationComponent) {
+      if (d.dec_type() == spv::Decoration::Location ||
+          d.dec_type() == spv::Decoration::Component) {
         return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(var_id))
                << vstate.VkErrorID(4915) << "A BuiltIn variable (id " << var_id
                << ") cannot have any Location or Component decorations";
@@ -762,18 +763,18 @@
       std::unordered_set<Instruction*> seen_vars;
       for (auto interface : desc.interfaces) {
         Instruction* var_instr = vstate.FindDef(interface);
-        if (!var_instr || SpvOpVariable != var_instr->opcode()) {
+        if (!var_instr || spv::Op::OpVariable != var_instr->opcode()) {
           return vstate.diag(SPV_ERROR_INVALID_ID, var_instr)
                  << "Interfaces passed to OpEntryPoint must be of type "
                     "OpTypeVariable. Found Op"
                  << spvOpcodeString(var_instr->opcode()) << ".";
         }
-        const SpvStorageClass storage_class =
-            var_instr->GetOperandAs<SpvStorageClass>(2);
+        const spv::StorageClass storage_class =
+            var_instr->GetOperandAs<spv::StorageClass>(2);
         if (vstate.version() >= SPV_SPIRV_VERSION_WORD(1, 4)) {
           // Starting in 1.4, OpEntryPoint must list all global variables
           // it statically uses and those interfaces must be unique.
-          if (storage_class == SpvStorageClassFunction) {
+          if (storage_class == spv::StorageClass::Function) {
             return vstate.diag(SPV_ERROR_INVALID_ID, var_instr)
                    << "OpEntryPoint interfaces should only list global "
                       "variables";
@@ -785,14 +786,14 @@
                    << vstate.getIdName(interface) << " is disallowed";
           }
         } else {
-          if (storage_class != SpvStorageClassInput &&
-              storage_class != SpvStorageClassOutput) {
+          if (storage_class != spv::StorageClass::Input &&
+              storage_class != spv::StorageClass::Output) {
             return vstate.diag(SPV_ERROR_INVALID_ID, var_instr)
                    << "OpEntryPoint interfaces must be OpVariables with "
                       "Storage Class of Input(1) or Output(3). Found Storage "
                       "Class "
-                   << storage_class << " for Entry Point id " << entry_point
-                   << ".";
+                   << uint32_t(storage_class) << " for Entry Point id "
+                   << entry_point << ".";
           }
         }
 
@@ -803,7 +804,7 @@
         // to.
         const uint32_t type_id = ptr_instr->word(3);
         Instruction* type_instr = vstate.FindDef(type_id);
-        if (type_instr && SpvOpTypeStruct == type_instr->opcode() &&
+        if (type_instr && spv::Op::OpTypeStruct == type_instr->opcode() &&
             isBuiltInStruct(type_id, vstate)) {
           if (!isBlock(type_id, vstate)) {
             return vstate.diag(SPV_ERROR_INVALID_DATA, vstate.FindDef(type_id))
@@ -814,8 +815,9 @@
                       "OpVariable with a structure type that is a block not "
                       "decorated with Location.";
           }
-          if (storage_class == SpvStorageClassInput) ++num_builtin_block_inputs;
-          if (storage_class == SpvStorageClassOutput)
+          if (storage_class == spv::StorageClass::Input)
+            ++num_builtin_block_inputs;
+          if (storage_class == spv::StorageClass::Output)
             ++num_builtin_block_outputs;
           if (num_builtin_block_inputs > 1 || num_builtin_block_outputs > 1)
             break;
@@ -826,12 +828,13 @@
             return error;
         }
 
-        if (storage_class == SpvStorageClassWorkgroup) {
+        if (storage_class == spv::StorageClass::Workgroup) {
           ++num_workgroup_variables;
-          if (type_instr && SpvOpTypeStruct == type_instr->opcode()) {
-            if (hasDecoration(type_id, SpvDecorationBlock, vstate))
+          if (type_instr && spv::Op::OpTypeStruct == type_instr->opcode()) {
+            if (hasDecoration(type_id, spv::Decoration::Block, vstate))
               ++num_workgroup_variables_with_block;
-            if (hasDecoration(var_instr->id(), SpvDecorationAliased, vstate))
+            if (hasDecoration(var_instr->id(), spv::Decoration::Aliased,
+                              vstate))
               ++num_workgroup_variables_with_aliased;
           }
         }
@@ -839,17 +842,17 @@
         if (spvIsVulkanEnv(vstate.context()->target_env)) {
           const auto* models = vstate.GetExecutionModels(entry_point);
           const bool has_frag =
-              models->find(SpvExecutionModelFragment) != models->end();
+              models->find(spv::ExecutionModel::Fragment) != models->end();
           const bool has_vert =
-              models->find(SpvExecutionModelVertex) != models->end();
+              models->find(spv::ExecutionModel::Vertex) != models->end();
           for (const auto& decoration :
                vstate.id_decorations(var_instr->id())) {
-            if (decoration == SpvDecorationFlat ||
-                decoration == SpvDecorationNoPerspective ||
-                decoration == SpvDecorationSample ||
-                decoration == SpvDecorationCentroid) {
+            if (decoration == spv::Decoration::Flat ||
+                decoration == spv::Decoration::NoPerspective ||
+                decoration == spv::Decoration::Sample ||
+                decoration == spv::Decoration::Centroid) {
               // VUID 04670 already validates these decorations are input/output
-              if (storage_class == SpvStorageClassInput &&
+              if (storage_class == spv::StorageClass::Input &&
                   (models->size() > 1 || has_vert)) {
                 return vstate.diag(SPV_ERROR_INVALID_ID, var_instr)
                        << vstate.VkErrorID(6202)
@@ -858,7 +861,7 @@
                           "execution model as an Input storage class for Entry "
                           "Point id "
                        << entry_point << ".";
-              } else if (storage_class == SpvStorageClassOutput &&
+              } else if (storage_class == spv::StorageClass::Output &&
                          (models->size() > 1 || has_frag)) {
                 return vstate.diag(SPV_ERROR_INVALID_ID, var_instr)
                        << vstate.VkErrorID(6201)
@@ -872,8 +875,9 @@
           }
 
           const bool has_flat =
-              hasDecoration(var_instr->id(), SpvDecorationFlat, vstate);
-          if (has_frag && storage_class == SpvStorageClassInput && !has_flat &&
+              hasDecoration(var_instr->id(), spv::Decoration::Flat, vstate);
+          if (has_frag && storage_class == spv::StorageClass::Input &&
+              !has_flat &&
               ((vstate.IsFloatScalarType(type_id) &&
                 vstate.GetBitWidth(type_id) == 64) ||
                vstate.IsIntScalarOrVectorType(type_id))) {
@@ -898,7 +902,7 @@
       // The LinkageAttributes Decoration cannot be applied to functions
       // targeted by an OpEntryPoint instruction
       for (auto& decoration : vstate.id_decorations(entry_point)) {
-        if (SpvDecorationLinkageAttributes == decoration.dec_type()) {
+        if (spv::Decoration::LinkageAttributes == decoration.dec_type()) {
           const std::string linkage_name =
               spvtools::utils::MakeString(decoration.params());
           return vstate.diag(SPV_ERROR_INVALID_BINARY,
@@ -910,7 +914,8 @@
         }
       }
 
-      if (vstate.HasCapability(SpvCapabilityWorkgroupMemoryExplicitLayoutKHR) &&
+      if (vstate.HasCapability(
+              spv::Capability::WorkgroupMemoryExplicitLayoutKHR) &&
           num_workgroup_variables > 0 &&
           num_workgroup_variables_with_block > 0) {
         if (num_workgroup_variables != num_workgroup_variables_with_block) {
@@ -964,13 +969,13 @@
          decoration != member_decorations.end; ++decoration) {
       assert(decoration->struct_member_index() == (int)memberIdx);
       switch (decoration->dec_type()) {
-        case SpvDecorationRowMajor:
+        case spv::Decoration::RowMajor:
           constraint.majorness = kRowMajor;
           break;
-        case SpvDecorationColMajor:
+        case spv::Decoration::ColMajor:
           constraint.majorness = kColumnMajor;
           break;
-        case SpvDecorationMatrixStride:
+        case spv::Decoration::MatrixStride:
           constraint.matrix_stride = decoration->params()[0];
           break;
         default:
@@ -983,12 +988,12 @@
     const auto member_type_inst = vstate.FindDef(member_type_id);
     const auto opcode = member_type_inst->opcode();
     switch (opcode) {
-      case SpvOpTypeArray:
-      case SpvOpTypeRuntimeArray:
+      case spv::Op::OpTypeArray:
+      case spv::Op::OpTypeRuntimeArray:
         ComputeMemberConstraintsForArray(constraints, member_type_id, inherited,
                                          vstate);
         break;
-      case SpvOpTypeStruct:
+      case spv::Op::OpTypeStruct:
         ComputeMemberConstraintsForStruct(constraints, member_type_id,
                                           inherited, vstate);
         break;
@@ -1007,12 +1012,12 @@
   const auto elem_type_inst = vstate.FindDef(elem_type_id);
   const auto opcode = elem_type_inst->opcode();
   switch (opcode) {
-    case SpvOpTypeArray:
-    case SpvOpTypeRuntimeArray:
+    case spv::Op::OpTypeArray:
+    case spv::Op::OpTypeRuntimeArray:
       ComputeMemberConstraintsForArray(constraints, elem_type_id, inherited,
                                        vstate);
       break;
-    case SpvOpTypeStruct:
+    case spv::Op::OpTypeStruct:
       ComputeMemberConstraintsForStruct(constraints, elem_type_id, inherited,
                                         vstate);
       break;
@@ -1026,16 +1031,18 @@
   std::unordered_set<uint32_t> uses_push_constant;
   for (const auto& inst : vstate.ordered_instructions()) {
     const auto& words = inst.words();
-    if (SpvOpVariable == inst.opcode()) {
+    if (spv::Op::OpVariable == inst.opcode()) {
       const auto var_id = inst.id();
       // For storage class / decoration combinations, see Vulkan 14.5.4 "Offset
       // and Stride Assignment".
-      const auto storageClass = words[3];
-      const bool uniform = storageClass == SpvStorageClassUniform;
+      const auto storageClass = inst.GetOperandAs<spv::StorageClass>(2);
+      const bool uniform = storageClass == spv::StorageClass::Uniform;
       const bool uniform_constant =
-          storageClass == SpvStorageClassUniformConstant;
-      const bool push_constant = storageClass == SpvStorageClassPushConstant;
-      const bool storage_buffer = storageClass == SpvStorageClassStorageBuffer;
+          storageClass == spv::StorageClass::UniformConstant;
+      const bool push_constant =
+          storageClass == spv::StorageClass::PushConstant;
+      const bool storage_buffer =
+          storageClass == spv::StorageClass::StorageBuffer;
 
       if (spvIsVulkanEnv(vstate.context()->target_env)) {
         // Vulkan: There must be no more than one PushConstant block per entry
@@ -1059,7 +1066,7 @@
         if (uniform_constant) {
           auto entry_points = vstate.EntryPointReferences(var_id);
           if (!entry_points.empty() &&
-              !hasDecoration(var_id, SpvDecorationDescriptorSet, vstate)) {
+              !hasDecoration(var_id, spv::Decoration::DescriptorSet, vstate)) {
             return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(var_id))
                    << vstate.VkErrorID(6677) << "UniformConstant id '" << var_id
                    << "' is missing DescriptorSet decoration.\n"
@@ -1068,7 +1075,7 @@
                       "decorations specified";
           }
           if (!entry_points.empty() &&
-              !hasDecoration(var_id, SpvDecorationBinding, vstate)) {
+              !hasDecoration(var_id, spv::Decoration::Binding, vstate)) {
             return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(var_id))
                    << vstate.VkErrorID(6677) << "UniformConstant id '" << var_id
                    << "' is missing Binding decoration.\n"
@@ -1080,14 +1087,14 @@
       }
 
       if (spvIsOpenGLEnv(vstate.context()->target_env)) {
-        bool has_block = hasDecoration(var_id, SpvDecorationBlock, vstate);
+        bool has_block = hasDecoration(var_id, spv::Decoration::Block, vstate);
         bool has_buffer_block =
-            hasDecoration(var_id, SpvDecorationBufferBlock, vstate);
+            hasDecoration(var_id, spv::Decoration::BufferBlock, vstate);
         if ((uniform && (has_block || has_buffer_block)) ||
             (storage_buffer && has_block)) {
           auto entry_points = vstate.EntryPointReferences(var_id);
           if (!entry_points.empty() &&
-              !hasDecoration(var_id, SpvDecorationBinding, vstate)) {
+              !hasDecoration(var_id, spv::Decoration::Binding, vstate)) {
             return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(var_id))
                    << (uniform ? "Uniform" : "Storage Buffer") << " id '"
                    << var_id << "' is missing Binding decoration.\n"
@@ -1099,24 +1106,25 @@
       }
 
       const bool phys_storage_buffer =
-          storageClass == SpvStorageClassPhysicalStorageBuffer;
+          storageClass == spv::StorageClass::PhysicalStorageBuffer;
       const bool workgroup =
-          storageClass == SpvStorageClassWorkgroup &&
-          vstate.HasCapability(SpvCapabilityWorkgroupMemoryExplicitLayoutKHR);
+          storageClass == spv::StorageClass::Workgroup &&
+          vstate.HasCapability(
+              spv::Capability::WorkgroupMemoryExplicitLayoutKHR);
       if (uniform || push_constant || storage_buffer || phys_storage_buffer ||
           workgroup) {
         const auto ptrInst = vstate.FindDef(words[1]);
-        assert(SpvOpTypePointer == ptrInst->opcode());
+        assert(spv::Op::OpTypePointer == ptrInst->opcode());
         auto id = ptrInst->words()[3];
         auto id_inst = vstate.FindDef(id);
         // Jump through one level of arraying.
-        if (!workgroup && (id_inst->opcode() == SpvOpTypeArray ||
-                           id_inst->opcode() == SpvOpTypeRuntimeArray)) {
+        if (!workgroup && (id_inst->opcode() == spv::Op::OpTypeArray ||
+                           id_inst->opcode() == spv::Op::OpTypeRuntimeArray)) {
           id = id_inst->GetOperandAs<uint32_t>(1u);
           id_inst = vstate.FindDef(id);
         }
         // Struct requirement is checked on variables so just move on here.
-        if (SpvOpTypeStruct != id_inst->opcode()) continue;
+        if (spv::Op::OpTypeStruct != id_inst->opcode()) continue;
         MemberConstraints constraints;
         ComputeMemberConstraintsForStruct(&constraints, id, LayoutConstraints(),
                                           vstate);
@@ -1128,9 +1136,9 @@
                                                   : "StorageBuffer"));
 
         if (spvIsVulkanEnv(vstate.context()->target_env)) {
-          const bool block = hasDecoration(id, SpvDecorationBlock, vstate);
+          const bool block = hasDecoration(id, spv::Decoration::Block, vstate);
           const bool buffer_block =
-              hasDecoration(id, SpvDecorationBufferBlock, vstate);
+              hasDecoration(id, spv::Decoration::BufferBlock, vstate);
           if (storage_buffer && buffer_block) {
             return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(var_id))
                    << vstate.VkErrorID(6675) << "Storage buffer id '" << var_id
@@ -1168,7 +1176,8 @@
           if (uniform || storage_buffer) {
             auto entry_points = vstate.EntryPointReferences(var_id);
             if (!entry_points.empty() &&
-                !hasDecoration(var_id, SpvDecorationDescriptorSet, vstate)) {
+                !hasDecoration(var_id, spv::Decoration::DescriptorSet,
+                               vstate)) {
               return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(var_id))
                      << vstate.VkErrorID(6677) << sc_str << " id '" << var_id
                      << "' is missing DescriptorSet decoration.\n"
@@ -1177,7 +1186,7 @@
                         "decorations specified";
             }
             if (!entry_points.empty() &&
-                !hasDecoration(var_id, SpvDecorationBinding, vstate)) {
+                !hasDecoration(var_id, spv::Decoration::Binding, vstate)) {
               return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(var_id))
                      << vstate.VkErrorID(6677) << sc_str << " id '" << var_id
                      << "' is missing Binding decoration.\n"
@@ -1189,8 +1198,9 @@
         }
 
         for (const auto& dec : vstate.id_decorations(id)) {
-          const bool blockDeco = SpvDecorationBlock == dec.dec_type();
-          const bool bufferDeco = SpvDecorationBufferBlock == dec.dec_type();
+          const bool blockDeco = spv::Decoration::Block == dec.dec_type();
+          const bool bufferDeco =
+              spv::Decoration::BufferBlock == dec.dec_type();
           const bool blockRules = uniform && blockDeco;
           const bool bufferRules =
               (uniform && bufferDeco) ||
@@ -1220,24 +1230,24 @@
                         "decorations.";
             }
 
-            if (!checkForRequiredDecoration(id,
-                                            [](SpvDecoration d) {
-                                              return d ==
-                                                     SpvDecorationArrayStride;
-                                            },
-                                            SpvOpTypeArray, vstate)) {
+            if (!checkForRequiredDecoration(
+                    id,
+                    [](spv::Decoration d) {
+                      return d == spv::Decoration::ArrayStride;
+                    },
+                    spv::Op::OpTypeArray, vstate)) {
               return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(id))
                      << "Structure id " << id << " decorated as " << deco_str
                      << " must be explicitly laid out with ArrayStride "
                         "decorations.";
             }
 
-            if (!checkForRequiredDecoration(id,
-                                            [](SpvDecoration d) {
-                                              return d ==
-                                                     SpvDecorationMatrixStride;
-                                            },
-                                            SpvOpTypeMatrix, vstate)) {
+            if (!checkForRequiredDecoration(
+                    id,
+                    [](spv::Decoration d) {
+                      return d == spv::Decoration::MatrixStride;
+                    },
+                    spv::Op::OpTypeMatrix, vstate)) {
               return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(id))
                      << "Structure id " << id << " decorated as " << deco_str
                      << " must be explicitly laid out with MatrixStride "
@@ -1246,11 +1256,11 @@
 
             if (!checkForRequiredDecoration(
                     id,
-                    [](SpvDecoration d) {
-                      return d == SpvDecorationRowMajor ||
-                             d == SpvDecorationColMajor;
+                    [](spv::Decoration d) {
+                      return d == spv::Decoration::RowMajor ||
+                             d == spv::Decoration::ColMajor;
                     },
-                    SpvOpTypeMatrix, vstate)) {
+                    spv::Op::OpTypeMatrix, vstate)) {
               return vstate.diag(SPV_ERROR_INVALID_ID, vstate.FindDef(id))
                      << "Structure id " << id << " decorated as " << deco_str
                      << " must be explicitly laid out with RowMajor or "
@@ -1280,18 +1290,18 @@
 }
 
 // Returns true if |decoration| cannot be applied to the same id more than once.
-bool AtMostOncePerId(SpvDecoration decoration) {
-  return decoration == SpvDecorationArrayStride;
+bool AtMostOncePerId(spv::Decoration decoration) {
+  return decoration == spv::Decoration::ArrayStride;
 }
 
 // Returns true if |decoration| cannot be applied to the same member more than
 // once.
-bool AtMostOncePerMember(SpvDecoration decoration) {
+bool AtMostOncePerMember(spv::Decoration decoration) {
   switch (decoration) {
-    case SpvDecorationOffset:
-    case SpvDecorationMatrixStride:
-    case SpvDecorationRowMajor:
-    case SpvDecorationColMajor:
+    case spv::Decoration::Offset:
+    case spv::Decoration::MatrixStride:
+    case spv::Decoration::RowMajor:
+    case spv::Decoration::ColMajor:
       return true;
     default:
       return false;
@@ -1299,32 +1309,32 @@
 }
 
 spv_result_t CheckDecorationsCompatibility(ValidationState_t& vstate) {
-  using PerIDKey = std::tuple<SpvDecoration, uint32_t>;
-  using PerMemberKey = std::tuple<SpvDecoration, uint32_t, uint32_t>;
+  using PerIDKey = std::tuple<spv::Decoration, uint32_t>;
+  using PerMemberKey = std::tuple<spv::Decoration, uint32_t, uint32_t>;
 
   // An Array of pairs where the decorations in the pair cannot both be applied
   // to the same id.
-  static const SpvDecoration mutually_exclusive_per_id[][2] = {
-      {SpvDecorationBlock, SpvDecorationBufferBlock},
-      {SpvDecorationRestrict, SpvDecorationAliased}};
+  static const spv::Decoration mutually_exclusive_per_id[][2] = {
+      {spv::Decoration::Block, spv::Decoration::BufferBlock},
+      {spv::Decoration::Restrict, spv::Decoration::Aliased}};
   static const auto num_mutually_exclusive_per_id_pairs =
-      sizeof(mutually_exclusive_per_id) / (2 * sizeof(SpvDecoration));
+      sizeof(mutually_exclusive_per_id) / (2 * sizeof(spv::Decoration));
 
   // An Array of pairs where the decorations in the pair cannot both be applied
   // to the same member.
-  static const SpvDecoration mutually_exclusive_per_member[][2] = {
-      {SpvDecorationRowMajor, SpvDecorationColMajor}};
+  static const spv::Decoration mutually_exclusive_per_member[][2] = {
+      {spv::Decoration::RowMajor, spv::Decoration::ColMajor}};
   static const auto num_mutually_exclusive_per_mem_pairs =
-      sizeof(mutually_exclusive_per_member) / (2 * sizeof(SpvDecoration));
+      sizeof(mutually_exclusive_per_member) / (2 * sizeof(spv::Decoration));
 
   std::set<PerIDKey> seen_per_id;
   std::set<PerMemberKey> seen_per_member;
 
   for (const auto& inst : vstate.ordered_instructions()) {
     const auto& words = inst.words();
-    if (SpvOpDecorate == inst.opcode()) {
+    if (spv::Op::OpDecorate == inst.opcode()) {
       const auto id = words[1];
-      const auto dec_type = static_cast<SpvDecoration>(words[2]);
+      const auto dec_type = static_cast<spv::Decoration>(words[2]);
       const auto k = PerIDKey(dec_type, id);
       const auto already_used = !seen_per_id.insert(k).second;
       if (already_used && AtMostOncePerId(dec_type)) {
@@ -1337,7 +1347,7 @@
       // an ID.
       for (uint32_t pair_idx = 0;
            pair_idx < num_mutually_exclusive_per_id_pairs; ++pair_idx) {
-        SpvDecoration excl_dec_type = SpvDecorationMax;
+        spv::Decoration excl_dec_type = spv::Decoration::Max;
         if (mutually_exclusive_per_id[pair_idx][0] == dec_type) {
           excl_dec_type = mutually_exclusive_per_id[pair_idx][1];
         } else if (mutually_exclusive_per_id[pair_idx][1] == dec_type) {
@@ -1355,10 +1365,10 @@
                  << " is not allowed.";
         }
       }
-    } else if (SpvOpMemberDecorate == inst.opcode()) {
+    } else if (spv::Op::OpMemberDecorate == inst.opcode()) {
       const auto id = words[1];
       const auto member_id = words[2];
-      const auto dec_type = static_cast<SpvDecoration>(words[3]);
+      const auto dec_type = static_cast<spv::Decoration>(words[3]);
       const auto k = PerMemberKey(dec_type, id, member_id);
       const auto already_used = !seen_per_member.insert(k).second;
       if (already_used && AtMostOncePerMember(dec_type)) {
@@ -1371,7 +1381,7 @@
       // a (ID, member) tuple.
       for (uint32_t pair_idx = 0;
            pair_idx < num_mutually_exclusive_per_mem_pairs; ++pair_idx) {
-        SpvDecoration excl_dec_type = SpvDecorationMax;
+        spv::Decoration excl_dec_type = spv::Decoration::Max;
         if (mutually_exclusive_per_member[pair_idx][0] == dec_type) {
           excl_dec_type = mutually_exclusive_per_member[pair_idx][1];
         } else if (mutually_exclusive_per_member[pair_idx][1] == dec_type) {
@@ -1397,7 +1407,7 @@
 
 spv_result_t CheckVulkanMemoryModelDeprecatedDecorations(
     ValidationState_t& vstate) {
-  if (vstate.memory_model() != SpvMemoryModelVulkanKHR) return SPV_SUCCESS;
+  if (vstate.memory_model() != spv::MemoryModel::VulkanKHR) return SPV_SUCCESS;
 
   std::string msg;
   std::ostringstream str(msg);
@@ -1406,10 +1416,10 @@
     const auto id = inst->id();
     for (const auto& dec : vstate.id_decorations(id)) {
       const auto member = dec.struct_member_index();
-      if (dec.dec_type() == SpvDecorationCoherent ||
-          dec.dec_type() == SpvDecorationVolatile) {
-        str << (dec.dec_type() == SpvDecorationCoherent ? "Coherent"
-                                                        : "Volatile");
+      if (dec.dec_type() == spv::Decoration::Coherent ||
+          dec.dec_type() == spv::Decoration::Volatile) {
+        str << (dec.dec_type() == spv::Decoration::Coherent ? "Coherent"
+                                                            : "Volatile");
         str << " decoration targeting " << vstate.getIdName(id);
         if (member != Decoration::kInvalidMember) {
           str << " (member index " << member << ")";
@@ -1430,7 +1440,7 @@
                                            const Decoration& decoration) {
   // Validates width-only conversion instruction for floating-point object
   // i.e., OpFConvert
-  if (inst.opcode() != SpvOpFConvert) {
+  if (inst.opcode() != spv::Op::OpFConvert) {
     return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
            << "FPRoundingMode decoration can be applied only to a "
               "width-only conversion instruction for floating-point "
@@ -1438,8 +1448,9 @@
   }
 
   if (spvIsVulkanEnv(vstate.context()->target_env)) {
-    const auto mode = decoration.params()[0];
-    if ((mode != SpvFPRoundingModeRTE) && (mode != SpvFPRoundingModeRTZ)) {
+    const auto mode = spv::FPRoundingMode(decoration.params()[0]);
+    if ((mode != spv::FPRoundingMode::RTE) &&
+        (mode != spv::FPRoundingMode::RTZ)) {
       return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
              << vstate.VkErrorID(4675)
              << "In Vulkan, the FPRoundingMode mode must only by RTE or RTZ.";
@@ -1449,11 +1460,11 @@
   // Validates Object operand of an OpStore
   for (const auto& use : inst.uses()) {
     const auto store = use.first;
-    if (store->opcode() == SpvOpFConvert) continue;
+    if (store->opcode() == spv::Op::OpFConvert) continue;
     if (spvOpcodeIsDebug(store->opcode())) continue;
     if (store->IsNonSemantic()) continue;
     if (spvOpcodeIsDecoration(store->opcode())) continue;
-    if (store->opcode() != SpvOpStore) {
+    if (store->opcode() != spv::Op::OpStore) {
       return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
              << "FPRoundingMode decoration can be applied only to the "
                 "Object operand of an OpStore.";
@@ -1479,12 +1490,13 @@
     }
 
     // Validates storage class of the pointer to the OpStore
-    const auto storage = ptr_type->GetOperandAs<uint32_t>(1);
-    if (storage != SpvStorageClassStorageBuffer &&
-        storage != SpvStorageClassUniform &&
-        storage != SpvStorageClassPushConstant &&
-        storage != SpvStorageClassInput && storage != SpvStorageClassOutput &&
-        storage != SpvStorageClassPhysicalStorageBuffer) {
+    const auto storage = ptr_type->GetOperandAs<spv::StorageClass>(1);
+    if (storage != spv::StorageClass::StorageBuffer &&
+        storage != spv::StorageClass::Uniform &&
+        storage != spv::StorageClass::PushConstant &&
+        storage != spv::StorageClass::Input &&
+        storage != spv::StorageClass::Output &&
+        storage != spv::StorageClass::PhysicalStorageBuffer) {
       return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
              << "FPRoundingMode decoration can be applied only to the "
                 "Object operand of an OpStore in the StorageBuffer, "
@@ -1509,16 +1521,17 @@
     // First, it must be a variable or function parameter.
     const auto opcode = inst.opcode();
     const auto type_id = inst.type_id();
-    if (opcode != SpvOpVariable && opcode != SpvOpFunctionParameter) {
+    if (opcode != spv::Op::OpVariable &&
+        opcode != spv::Op::OpFunctionParameter) {
       return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
              << "Target of NonWritable decoration must be a memory object "
                 "declaration (a variable or a function parameter)";
     }
-    const auto var_storage_class = opcode == SpvOpVariable
-                                       ? inst.GetOperandAs<SpvStorageClass>(2)
-                                       : SpvStorageClassMax;
-    if ((var_storage_class == SpvStorageClassFunction ||
-         var_storage_class == SpvStorageClassPrivate) &&
+    const auto var_storage_class = opcode == spv::Op::OpVariable
+                                       ? inst.GetOperandAs<spv::StorageClass>(2)
+                                       : spv::StorageClass::Max;
+    if ((var_storage_class == spv::StorageClass::Function ||
+         var_storage_class == spv::StorageClass::Private) &&
         vstate.features().nonwritable_var_in_function_or_private) {
       // New permitted feature in SPIR-V 1.4.
     } else if (
@@ -1548,8 +1561,9 @@
 spv_result_t CheckUniformDecoration(ValidationState_t& vstate,
                                     const Instruction& inst,
                                     const Decoration& decoration) {
-  const char* const dec_name =
-      decoration.dec_type() == SpvDecorationUniform ? "Uniform" : "UniformId";
+  const char* const dec_name = decoration.dec_type() == spv::Decoration::Uniform
+                                   ? "Uniform"
+                                   : "UniformId";
 
   // Uniform or UniformId must decorate an "object"
   //  - has a result ID
@@ -1563,7 +1577,7 @@
            << dec_name << " decoration applied to a non-object";
   }
   if (Instruction* type_inst = vstate.FindDef(inst.type_id())) {
-    if (type_inst->opcode() == SpvOpTypeVoid) {
+    if (type_inst->opcode() == spv::Op::OpTypeVoid) {
       return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
              << dec_name << " decoration applied to a value with void type";
     }
@@ -1577,7 +1591,7 @@
   // Use of Uniform with OpDecorate is checked elsewhere.
   // Use of UniformId with OpDecorateId is checked elsewhere.
 
-  if (decoration.dec_type() == SpvDecorationUniformId) {
+  if (decoration.dec_type() == spv::Decoration::UniformId) {
     assert(decoration.params().size() == 1 &&
            "Grammar ensures UniformId has one parameter");
 
@@ -1598,13 +1612,13 @@
                                         const Instruction& inst,
                                         const Decoration& decoration) {
   switch (inst.opcode()) {
-    case SpvOpIAdd:
-    case SpvOpISub:
-    case SpvOpIMul:
-    case SpvOpShiftLeftLogical:
-    case SpvOpSNegate:
+    case spv::Op::OpIAdd:
+    case spv::Op::OpISub:
+    case spv::Op::OpIMul:
+    case spv::Op::OpShiftLeftLogical:
+    case spv::Op::OpSNegate:
       return SPV_SUCCESS;
-    case SpvOpExtInst:
+    case spv::Op::OpExtInst:
       // TODO(dneto): Only certain extended instructions allow these
       // decorations.  For now allow anything.
       return SPV_SUCCESS;
@@ -1613,7 +1627,7 @@
   }
 
   return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
-         << (decoration.dec_type() == SpvDecorationNoSignedWrap
+         << (decoration.dec_type() == spv::Decoration::NoSignedWrap
                  ? "NoSignedWrap"
                  : "NoUnsignedWrap")
          << " decoration may not be applied to "
@@ -1634,24 +1648,25 @@
   if (decoration.struct_member_index() == Decoration::kInvalidMember) {
     // The target must be a memory object declaration.
     const auto opcode = inst.opcode();
-    if (opcode != SpvOpVariable && opcode != SpvOpFunctionParameter) {
+    if (opcode != spv::Op::OpVariable &&
+        opcode != spv::Op::OpFunctionParameter) {
       return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
              << "Target of Component decoration must be a memory object "
                 "declaration (a variable or a function parameter)";
     }
 
     // Only valid for the Input and Output Storage Classes.
-    const auto storage_class = opcode == SpvOpVariable
-                                   ? inst.GetOperandAs<SpvStorageClass>(2)
-                                   : SpvStorageClassMax;
-    if (storage_class != SpvStorageClassInput &&
-        storage_class != SpvStorageClassOutput &&
-        storage_class != SpvStorageClassMax) {
+    const auto storage_class = opcode == spv::Op::OpVariable
+                                   ? inst.GetOperandAs<spv::StorageClass>(2)
+                                   : spv::StorageClass::Max;
+    if (storage_class != spv::StorageClass::Input &&
+        storage_class != spv::StorageClass::Output &&
+        storage_class != spv::StorageClass::Max) {
       return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
              << "Target of Component decoration is invalid: must point to a "
                 "Storage Class of Input(1) or Output(3). Found Storage "
                 "Class "
-             << storage_class;
+             << uint32_t(storage_class);
     }
 
     type_id = inst.type_id();
@@ -1660,7 +1675,7 @@
       type_id = pointer->GetOperandAs<uint32_t>(2);
     }
   } else {
-    if (inst.opcode() != SpvOpTypeStruct) {
+    if (inst.opcode() != spv::Op::OpTypeStruct) {
       return vstate.diag(SPV_ERROR_INVALID_DATA, &inst)
              << "Attempted to get underlying data type via member index for "
                 "non-struct type.";
@@ -1670,7 +1685,7 @@
 
   if (spvIsVulkanEnv(vstate.context()->target_env)) {
     // Strip the array, if present.
-    if (vstate.GetIdOpcode(type_id) == SpvOpTypeArray) {
+    if (vstate.GetIdOpcode(type_id) == spv::Op::OpTypeArray) {
       type_id = vstate.FindDef(type_id)->word(2u);
     }
 
@@ -1734,9 +1749,10 @@
                                   const Instruction& inst,
                                   const Decoration& decoration) {
   assert(inst.id() && "Parser ensures the target of the decoration has an ID");
-  if (inst.opcode() != SpvOpTypeStruct) {
-    const char* const dec_name =
-        decoration.dec_type() == SpvDecorationBlock ? "Block" : "BufferBlock";
+  if (inst.opcode() != spv::Op::OpTypeStruct) {
+    const char* const dec_name = decoration.dec_type() == spv::Decoration::Block
+                                     ? "Block"
+                                     : "BufferBlock";
     return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
            << dec_name << " decoration on a non-struct type.";
   }
@@ -1746,10 +1762,10 @@
 spv_result_t CheckLocationDecoration(ValidationState_t& vstate,
                                      const Instruction& inst,
                                      const Decoration& decoration) {
-  if (inst.opcode() == SpvOpVariable) return SPV_SUCCESS;
+  if (inst.opcode() == spv::Op::OpVariable) return SPV_SUCCESS;
 
   if (decoration.struct_member_index() != Decoration::kInvalidMember &&
-      inst.opcode() == SpvOpTypeStruct) {
+      inst.opcode() == spv::Op::OpTypeStruct) {
     return SPV_SUCCESS;
   }
 
@@ -1769,7 +1785,7 @@
   }
 
   if (decoration.struct_member_index() != Decoration::kInvalidMember &&
-      inst.opcode() == SpvOpTypeStruct) {
+      inst.opcode() == spv::Op::OpTypeStruct) {
     return SPV_SUCCESS;
   }
   return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
@@ -1788,7 +1804,7 @@
 // propagated down to the group members.
 spv_result_t CheckDecorationsFromDecoration(ValidationState_t& vstate) {
   // Some rules are only checked for shaders.
-  const bool is_shader = vstate.HasCapability(SpvCapabilityShader);
+  const bool is_shader = vstate.HasCapability(spv::Capability::Shader);
 
   for (const auto& kv : vstate.id_decorations()) {
     const uint32_t id = kv.first;
@@ -1800,37 +1816,37 @@
 
     // We assume the decorations applied to a decoration group have already
     // been propagated down to the group members.
-    if (inst->opcode() == SpvOpDecorationGroup) continue;
+    if (inst->opcode() == spv::Op::OpDecorationGroup) continue;
 
     for (const auto& decoration : decorations) {
       switch (decoration.dec_type()) {
-        case SpvDecorationComponent:
+        case spv::Decoration::Component:
           PASS_OR_BAIL(CheckComponentDecoration(vstate, *inst, decoration));
           break;
-        case SpvDecorationFPRoundingMode:
+        case spv::Decoration::FPRoundingMode:
           if (is_shader)
             PASS_OR_BAIL(
                 CheckFPRoundingModeForShaders(vstate, *inst, decoration));
           break;
-        case SpvDecorationNonWritable:
+        case spv::Decoration::NonWritable:
           PASS_OR_BAIL(CheckNonWritableDecoration(vstate, *inst, decoration));
           break;
-        case SpvDecorationUniform:
-        case SpvDecorationUniformId:
+        case spv::Decoration::Uniform:
+        case spv::Decoration::UniformId:
           PASS_OR_BAIL(CheckUniformDecoration(vstate, *inst, decoration));
           break;
-        case SpvDecorationNoSignedWrap:
-        case SpvDecorationNoUnsignedWrap:
+        case spv::Decoration::NoSignedWrap:
+        case spv::Decoration::NoUnsignedWrap:
           PASS_OR_BAIL(CheckIntegerWrapDecoration(vstate, *inst, decoration));
           break;
-        case SpvDecorationBlock:
-        case SpvDecorationBufferBlock:
+        case spv::Decoration::Block:
+        case spv::Decoration::BufferBlock:
           PASS_OR_BAIL(CheckBlockDecoration(vstate, *inst, decoration));
           break;
-        case SpvDecorationLocation:
+        case spv::Decoration::Location:
           PASS_OR_BAIL(CheckLocationDecoration(vstate, *inst, decoration));
           break;
-        case SpvDecorationRelaxedPrecision:
+        case spv::Decoration::RelaxedPrecision:
           PASS_OR_BAIL(
               CheckRelaxPrecisionDecoration(vstate, *inst, decoration));
           break;
diff --git a/source/val/validate_derivatives.cpp b/source/val/validate_derivatives.cpp
index 25b941a..d87240f 100644
--- a/source/val/validate_derivatives.cpp
+++ b/source/val/validate_derivatives.cpp
@@ -28,25 +28,26 @@
 
 // Validates correctness of derivative instructions.
 spv_result_t DerivativesPass(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   const uint32_t result_type = inst->type_id();
 
   switch (opcode) {
-    case SpvOpDPdx:
-    case SpvOpDPdy:
-    case SpvOpFwidth:
-    case SpvOpDPdxFine:
-    case SpvOpDPdyFine:
-    case SpvOpFwidthFine:
-    case SpvOpDPdxCoarse:
-    case SpvOpDPdyCoarse:
-    case SpvOpFwidthCoarse: {
+    case spv::Op::OpDPdx:
+    case spv::Op::OpDPdy:
+    case spv::Op::OpFwidth:
+    case spv::Op::OpDPdxFine:
+    case spv::Op::OpDPdyFine:
+    case spv::Op::OpFwidthFine:
+    case spv::Op::OpDPdxCoarse:
+    case spv::Op::OpDPdyCoarse:
+    case spv::Op::OpFwidthCoarse: {
       if (!_.IsFloatScalarOrVectorType(result_type)) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected Result Type to be float scalar or vector type: "
                << spvOpcodeString(opcode);
       }
-      if (!_.ContainsSizedIntOrFloatType(result_type, SpvOpTypeFloat, 32)) {
+      if (!_.ContainsSizedIntOrFloatType(result_type, spv::Op::OpTypeFloat,
+                                         32)) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Result type component width must be 32 bits";
       }
@@ -58,10 +59,10 @@
                << spvOpcodeString(opcode);
       }
       _.function(inst->function()->id())
-          ->RegisterExecutionModelLimitation([opcode](SpvExecutionModel model,
+          ->RegisterExecutionModelLimitation([opcode](spv::ExecutionModel model,
                                                       std::string* message) {
-            if (model != SpvExecutionModelFragment &&
-                model != SpvExecutionModelGLCompute) {
+            if (model != spv::ExecutionModel::Fragment &&
+                model != spv::ExecutionModel::GLCompute) {
               if (message) {
                 *message =
                     std::string(
@@ -80,11 +81,11 @@
             const auto* models = state.GetExecutionModels(entry_point->id());
             const auto* modes = state.GetExecutionModes(entry_point->id());
             if (models &&
-                models->find(SpvExecutionModelGLCompute) != models->end() &&
+                models->find(spv::ExecutionModel::GLCompute) != models->end() &&
                 (!modes ||
-                 (modes->find(SpvExecutionModeDerivativeGroupLinearNV) ==
+                 (modes->find(spv::ExecutionMode::DerivativeGroupLinearNV) ==
                       modes->end() &&
-                  modes->find(SpvExecutionModeDerivativeGroupQuadsNV) ==
+                  modes->find(spv::ExecutionMode::DerivativeGroupQuadsNV) ==
                       modes->end()))) {
               if (message) {
                 *message = std::string(
diff --git a/source/val/validate_execution_limitations.cpp b/source/val/validate_execution_limitations.cpp
index e1f4d7b..00c6603 100644
--- a/source/val/validate_execution_limitations.cpp
+++ b/source/val/validate_execution_limitations.cpp
@@ -22,7 +22,7 @@
 
 spv_result_t ValidateExecutionLimitations(ValidationState_t& _,
                                           const Instruction* inst) {
-  if (inst->opcode() != SpvOpFunction) {
+  if (inst->opcode() != spv::Op::OpFunction) {
     return SPV_SUCCESS;
   }
 
diff --git a/source/val/validate_extensions.cpp b/source/val/validate_extensions.cpp
index 1e69cb3..98c691b 100644
--- a/source/val/validate_extensions.cpp
+++ b/source/val/validate_extensions.cpp
@@ -40,9 +40,9 @@
 namespace {
 
 uint32_t GetSizeTBitWidth(const ValidationState_t& _) {
-  if (_.addressing_model() == SpvAddressingModelPhysical32) return 32;
+  if (_.addressing_model() == spv::AddressingModel::Physical32) return 32;
 
-  if (_.addressing_model() == SpvAddressingModelPhysical64) return 64;
+  if (_.addressing_model() == spv::AddressingModel::Physical64) return 64;
 
   return 0;
 }
@@ -50,7 +50,7 @@
 bool IsIntScalar(ValidationState_t& _, uint32_t id, bool must_len32,
                  bool must_unsigned) {
   auto type = _.FindDef(id);
-  if (!type || type->opcode() != SpvOpTypeInt) {
+  if (!type || type->opcode() != spv::Op::OpTypeInt) {
     return false;
   }
 
@@ -63,7 +63,7 @@
 
 bool IsUint32Constant(ValidationState_t& _, uint32_t id) {
   auto inst = _.FindDef(id);
-  if (!inst || inst->opcode() != SpvOpConstant) {
+  if (!inst || inst->opcode() != spv::Op::OpConstant) {
     return false;
   }
 
@@ -79,7 +79,7 @@
 // is a result id of an instruction with |expected_opcode|.
 spv_result_t ValidateOperandForDebugInfo(
     ValidationState_t& _, const std::string& operand_name,
-    SpvOp expected_opcode, const Instruction* inst, uint32_t word_index,
+    spv::Op expected_opcode, const Instruction* inst, uint32_t word_index,
     const std::function<std::string()>& ext_inst_name) {
   auto* operand = _.FindDef(inst->word(word_index));
   if (operand->opcode() != expected_opcode) {
@@ -137,7 +137,7 @@
     const Instruction* inst, uint32_t word_index) {
   if (inst->words().size() <= word_index) return false;
   auto* debug_inst = _.FindDef(inst->word(word_index));
-  if (debug_inst->opcode() != SpvOpExtInst ||
+  if (debug_inst->opcode() != spv::Op::OpExtInst ||
       (debug_inst->ext_inst_type() != SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100 &&
        debug_inst->ext_inst_type() !=
            SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100) ||
@@ -155,7 +155,7 @@
     const Instruction* inst, uint32_t word_index) {
   if (inst->words().size() <= word_index) return false;
   auto* debug_inst = _.FindDef(inst->word(word_index));
-  if (debug_inst->opcode() != SpvOpExtInst ||
+  if (debug_inst->opcode() != spv::Op::OpExtInst ||
       (debug_inst->ext_inst_type() !=
        SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100) ||
       !expectation(
@@ -276,7 +276,7 @@
                                            const Instruction* inst) {
   const auto kernel_id = inst->GetOperandAs<uint32_t>(4);
   const auto kernel = _.FindDef(kernel_id);
-  if (kernel->opcode() != SpvOpFunction) {
+  if (kernel->opcode() != spv::Op::OpFunction) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Kernel does not reference a function";
   }
@@ -299,14 +299,14 @@
            << "Kernel does not reference an entry-point";
   }
   for (auto exec_model : *exec_models) {
-    if (exec_model != SpvExecutionModelGLCompute) {
+    if (exec_model != spv::ExecutionModel::GLCompute) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "Kernel must refer only to GLCompute entry-points";
     }
   }
 
   auto name = _.FindDef(inst->GetOperandAs<uint32_t>(5));
-  if (!name || name->opcode() != SpvOpString) {
+  if (!name || name->opcode() != spv::Op::OpString) {
     return _.diag(SPV_ERROR_INVALID_ID, inst) << "Name must be an OpString";
   }
 
@@ -329,11 +329,11 @@
 spv_result_t ValidateClspvReflectionArgumentInfo(ValidationState_t& _,
                                                  const Instruction* inst) {
   const auto num_operands = inst->operands().size();
-  if (_.GetIdOpcode(inst->GetOperandAs<uint32_t>(4)) != SpvOpString) {
+  if (_.GetIdOpcode(inst->GetOperandAs<uint32_t>(4)) != spv::Op::OpString) {
     return _.diag(SPV_ERROR_INVALID_ID, inst) << "Name must be an OpString";
   }
   if (num_operands > 5) {
-    if (_.GetIdOpcode(inst->GetOperandAs<uint32_t>(5)) != SpvOpString) {
+    if (_.GetIdOpcode(inst->GetOperandAs<uint32_t>(5)) != spv::Op::OpString) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "TypeName must be an OpString";
     }
@@ -366,7 +366,7 @@
 spv_result_t ValidateKernelDecl(ValidationState_t& _, const Instruction* inst) {
   const auto decl_id = inst->GetOperandAs<uint32_t>(4);
   const auto decl = _.FindDef(decl_id);
-  if (!decl || decl->opcode() != SpvOpExtInst) {
+  if (!decl || decl->opcode() != spv::Op::OpExtInst) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Kernel must be a Kernel extended instruction";
   }
@@ -389,7 +389,7 @@
 spv_result_t ValidateArgInfo(ValidationState_t& _, const Instruction* inst,
                              uint32_t info_index) {
   auto info = _.FindDef(inst->GetOperandAs<uint32_t>(info_index));
-  if (!info || info->opcode() != SpvOpExtInst) {
+  if (!info || info->opcode() != spv::Op::OpExtInst) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "ArgInfo must be an ArgumentInfo extended instruction";
   }
@@ -599,7 +599,7 @@
            << "Binding must be a 32-bit unsigned integer OpConstant";
   }
 
-  if (_.GetIdOpcode(inst->GetOperandAs<uint32_t>(6)) != SpvOpString) {
+  if (_.GetIdOpcode(inst->GetOperandAs<uint32_t>(6)) != spv::Op::OpString) {
     return _.diag(SPV_ERROR_INVALID_ID, inst) << "Data must be an OpString";
   }
 
@@ -705,7 +705,7 @@
 
 bool IsConstIntScalarTypeWith32Or64Bits(ValidationState_t& _,
                                         Instruction* instr) {
-  if (instr->opcode() != SpvOpConstant) return false;
+  if (instr->opcode() != spv::Op::OpConstant) return false;
   if (!_.IsIntScalarType(instr->type_id())) return false;
   uint32_t size_in_bits = _.GetBitWidth(instr->type_id());
   return size_in_bits == 32 || size_in_bits == 64;
@@ -714,7 +714,7 @@
 bool IsConstWithIntScalarType(ValidationState_t& _, const Instruction* inst,
                               uint32_t word_index) {
   auto* int_scalar_const = _.FindDef(inst->word(word_index));
-  if (int_scalar_const->opcode() == SpvOpConstant &&
+  if (int_scalar_const->opcode() == spv::Op::OpConstant &&
       _.IsIntScalarType(int_scalar_const->type_id())) {
     return true;
   }
@@ -1020,7 +1020,7 @@
                  << "expected operand X type to be equal to Result Type";
         }
 
-        uint32_t i_storage_class = 0;
+        spv::StorageClass i_storage_class;
         uint32_t i_data_type = 0;
         if (!_.GetPointerTypeInfo(i_type, &i_data_type, &i_storage_class)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -1075,7 +1075,7 @@
                  << "expected operand X type to be equal to Result Type";
         }
 
-        uint32_t exp_storage_class = 0;
+        spv::StorageClass exp_storage_class;
         uint32_t exp_data_type = 0;
         if (!_.GetPointerTypeInfo(exp_type, &exp_data_type,
                                   &exp_storage_class)) {
@@ -1424,7 +1424,7 @@
       case GLSLstd450InterpolateAtCentroid:
       case GLSLstd450InterpolateAtSample:
       case GLSLstd450InterpolateAtOffset: {
-        if (!_.HasCapability(SpvCapabilityInterpolationFunction)) {
+        if (!_.HasCapability(spv::Capability::InterpolationFunction)) {
           return _.diag(SPV_ERROR_INVALID_CAPABILITY, inst)
                  << ext_inst_name()
                  << " requires capability InterpolationFunction";
@@ -1444,11 +1444,11 @@
         uint32_t interp_id = inst->GetOperandAs<uint32_t>(4);
         auto* interp_inst = _.FindDef(interp_id);
         uint32_t interpolant_type = (_.options()->before_hlsl_legalization &&
-                                     interp_inst->opcode() == SpvOpLoad)
+                                     interp_inst->opcode() == spv::Op::OpLoad)
                                         ? _.GetOperandTypeId(interp_inst, 2)
                                         : _.GetOperandTypeId(inst, 4);
 
-        uint32_t interpolant_storage_class = 0;
+        spv::StorageClass interpolant_storage_class;
         uint32_t interpolant_data_type = 0;
         if (!_.GetPointerTypeInfo(interpolant_type, &interpolant_data_type,
                                   &interpolant_storage_class)) {
@@ -1463,7 +1463,7 @@
                  << "expected Interpolant data type to be equal to Result Type";
         }
 
-        if (interpolant_storage_class != SpvStorageClassInput) {
+        if (interpolant_storage_class != spv::StorageClass::Input) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << ext_inst_name() << ": "
                  << "expected Interpolant storage class to be Input";
@@ -1492,7 +1492,7 @@
 
         _.function(inst->function()->id())
             ->RegisterExecutionModelLimitation(
-                SpvExecutionModelFragment,
+                spv::ExecutionModel::Fragment,
                 ext_inst_name() +
                     std::string(" requires Fragment execution model"));
         break;
@@ -1662,7 +1662,7 @@
         }
 
         const uint32_t p_type = _.GetOperandTypeId(inst, 5);
-        uint32_t p_storage_class = 0;
+        spv::StorageClass p_storage_class;
         uint32_t p_data_type = 0;
         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -1670,10 +1670,10 @@
                  << "expected the last operand to be a pointer";
         }
 
-        if (p_storage_class != SpvStorageClassGeneric &&
-            p_storage_class != SpvStorageClassCrossWorkgroup &&
-            p_storage_class != SpvStorageClassWorkgroup &&
-            p_storage_class != SpvStorageClassFunction) {
+        if (p_storage_class != spv::StorageClass::Generic &&
+            p_storage_class != spv::StorageClass::CrossWorkgroup &&
+            p_storage_class != spv::StorageClass::Workgroup &&
+            p_storage_class != spv::StorageClass::Function) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << ext_inst_name() << ": "
                  << "expected storage class of the pointer to be Generic, "
@@ -1724,7 +1724,7 @@
         }
 
         const uint32_t p_type = _.GetOperandTypeId(inst, operand_index++);
-        uint32_t p_storage_class = 0;
+        spv::StorageClass p_storage_class;
         uint32_t p_data_type = 0;
         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -1732,10 +1732,10 @@
                  << "expected the last operand to be a pointer";
         }
 
-        if (p_storage_class != SpvStorageClassGeneric &&
-            p_storage_class != SpvStorageClassCrossWorkgroup &&
-            p_storage_class != SpvStorageClassWorkgroup &&
-            p_storage_class != SpvStorageClassFunction) {
+        if (p_storage_class != spv::StorageClass::Generic &&
+            p_storage_class != spv::StorageClass::CrossWorkgroup &&
+            p_storage_class != spv::StorageClass::Workgroup &&
+            p_storage_class != spv::StorageClass::Function) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << ext_inst_name() << ": "
                  << "expected storage class of the pointer to be Generic, "
@@ -2254,7 +2254,7 @@
                  << "-bit integer for the addressing model used in the module)";
         }
 
-        uint32_t p_storage_class = 0;
+        spv::StorageClass p_storage_class;
         uint32_t p_data_type = 0;
         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -2262,11 +2262,11 @@
                  << "expected operand P to be a pointer";
         }
 
-        if (p_storage_class != SpvStorageClassUniformConstant &&
-            p_storage_class != SpvStorageClassGeneric &&
-            p_storage_class != SpvStorageClassCrossWorkgroup &&
-            p_storage_class != SpvStorageClassWorkgroup &&
-            p_storage_class != SpvStorageClassFunction) {
+        if (p_storage_class != spv::StorageClass::UniformConstant &&
+            p_storage_class != spv::StorageClass::Generic &&
+            p_storage_class != spv::StorageClass::CrossWorkgroup &&
+            p_storage_class != spv::StorageClass::Workgroup &&
+            p_storage_class != spv::StorageClass::Function) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << ext_inst_name() << ": "
                  << "expected operand P storage class to be UniformConstant, "
@@ -2291,7 +2291,7 @@
       }
 
       case OpenCLLIB::Vstoren: {
-        if (_.GetIdOpcode(result_type) != SpvOpTypeVoid) {
+        if (_.GetIdOpcode(result_type) != spv::Op::OpTypeVoid) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << ext_inst_name() << ": expected Result Type to be void";
         }
@@ -2329,7 +2329,7 @@
                  << "-bit integer for the addressing model used in the module)";
         }
 
-        uint32_t p_storage_class = 0;
+        spv::StorageClass p_storage_class;
         uint32_t p_data_type = 0;
         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -2337,10 +2337,10 @@
                  << "expected operand P to be a pointer";
         }
 
-        if (p_storage_class != SpvStorageClassGeneric &&
-            p_storage_class != SpvStorageClassCrossWorkgroup &&
-            p_storage_class != SpvStorageClassWorkgroup &&
-            p_storage_class != SpvStorageClassFunction) {
+        if (p_storage_class != spv::StorageClass::Generic &&
+            p_storage_class != spv::StorageClass::CrossWorkgroup &&
+            p_storage_class != spv::StorageClass::Workgroup &&
+            p_storage_class != spv::StorageClass::Function) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << ext_inst_name() << ": "
                  << "expected operand P storage class to be Generic, "
@@ -2382,7 +2382,7 @@
                  << "-bit integer for the addressing model used in the module)";
         }
 
-        uint32_t p_storage_class = 0;
+        spv::StorageClass p_storage_class;
         uint32_t p_data_type = 0;
         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -2390,11 +2390,11 @@
                  << "expected operand P to be a pointer";
         }
 
-        if (p_storage_class != SpvStorageClassUniformConstant &&
-            p_storage_class != SpvStorageClassGeneric &&
-            p_storage_class != SpvStorageClassCrossWorkgroup &&
-            p_storage_class != SpvStorageClassWorkgroup &&
-            p_storage_class != SpvStorageClassFunction) {
+        if (p_storage_class != spv::StorageClass::UniformConstant &&
+            p_storage_class != spv::StorageClass::Generic &&
+            p_storage_class != spv::StorageClass::CrossWorkgroup &&
+            p_storage_class != spv::StorageClass::Workgroup &&
+            p_storage_class != spv::StorageClass::Function) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << ext_inst_name() << ": "
                  << "expected operand P storage class to be UniformConstant, "
@@ -2444,7 +2444,7 @@
                  << "-bit integer for the addressing model used in the module)";
         }
 
-        uint32_t p_storage_class = 0;
+        spv::StorageClass p_storage_class;
         uint32_t p_data_type = 0;
         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -2452,11 +2452,11 @@
                  << "expected operand P to be a pointer";
         }
 
-        if (p_storage_class != SpvStorageClassUniformConstant &&
-            p_storage_class != SpvStorageClassGeneric &&
-            p_storage_class != SpvStorageClassCrossWorkgroup &&
-            p_storage_class != SpvStorageClassWorkgroup &&
-            p_storage_class != SpvStorageClassFunction) {
+        if (p_storage_class != spv::StorageClass::UniformConstant &&
+            p_storage_class != spv::StorageClass::Generic &&
+            p_storage_class != spv::StorageClass::CrossWorkgroup &&
+            p_storage_class != spv::StorageClass::Workgroup &&
+            p_storage_class != spv::StorageClass::Function) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << ext_inst_name() << ": "
                  << "expected operand P storage class to be UniformConstant, "
@@ -2486,7 +2486,7 @@
       case OpenCLLIB::Vstore_halfn_r:
       case OpenCLLIB::Vstorea_halfn:
       case OpenCLLIB::Vstorea_halfn_r: {
-        if (_.GetIdOpcode(result_type) != SpvOpTypeVoid) {
+        if (_.GetIdOpcode(result_type) != spv::Op::OpTypeVoid) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << ext_inst_name() << ": expected Result Type to be void";
         }
@@ -2537,7 +2537,7 @@
                  << "-bit integer for the addressing model used in the module)";
         }
 
-        uint32_t p_storage_class = 0;
+        spv::StorageClass p_storage_class;
         uint32_t p_data_type = 0;
         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -2545,10 +2545,10 @@
                  << "expected operand P to be a pointer";
         }
 
-        if (p_storage_class != SpvStorageClassGeneric &&
-            p_storage_class != SpvStorageClassCrossWorkgroup &&
-            p_storage_class != SpvStorageClassWorkgroup &&
-            p_storage_class != SpvStorageClassFunction) {
+        if (p_storage_class != spv::StorageClass::Generic &&
+            p_storage_class != spv::StorageClass::CrossWorkgroup &&
+            p_storage_class != spv::StorageClass::Workgroup &&
+            p_storage_class != spv::StorageClass::Function) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << ext_inst_name() << ": "
                  << "expected operand P storage class to be Generic, "
@@ -2653,7 +2653,7 @@
         }
 
         const uint32_t format_type = _.GetOperandTypeId(inst, 4);
-        uint32_t format_storage_class = 0;
+        spv::StorageClass format_storage_class;
         uint32_t format_data_type = 0;
         if (!_.GetPointerTypeInfo(format_type, &format_data_type,
                                   &format_storage_class)) {
@@ -2662,7 +2662,7 @@
                  << "expected operand Format to be a pointer";
         }
 
-        if (format_storage_class != SpvStorageClassUniformConstant) {
+        if (format_storage_class != spv::StorageClass::UniformConstant) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << ext_inst_name() << ": "
                  << "expected Format storage class to be UniformConstant";
@@ -2678,7 +2678,7 @@
       }
 
       case OpenCLLIB::Prefetch: {
-        if (_.GetIdOpcode(result_type) != SpvOpTypeVoid) {
+        if (_.GetIdOpcode(result_type) != spv::Op::OpTypeVoid) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << ext_inst_name() << ": expected Result Type to be void";
         }
@@ -2686,7 +2686,7 @@
         const uint32_t p_type = _.GetOperandTypeId(inst, 4);
         const uint32_t num_elements_type = _.GetOperandTypeId(inst, 5);
 
-        uint32_t p_storage_class = 0;
+        spv::StorageClass p_storage_class;
         uint32_t p_data_type = 0;
         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -2694,7 +2694,7 @@
                  << "expected operand Ptr to be a pointer";
         }
 
-        if (p_storage_class != SpvStorageClassCrossWorkgroup) {
+        if (p_storage_class != spv::StorageClass::CrossWorkgroup) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << ext_inst_name() << ": "
                  << "expected operand Ptr storage class to be CrossWorkgroup";
@@ -2857,13 +2857,13 @@
           break;
         }
         case CommonDebugInfoDebugSource: {
-          CHECK_OPERAND("File", SpvOpString, 5);
-          if (num_words == 7) CHECK_OPERAND("Text", SpvOpString, 6);
+          CHECK_OPERAND("File", spv::Op::OpString, 5);
+          if (num_words == 7) CHECK_OPERAND("Text", spv::Op::OpString, 6);
           break;
         }
         case CommonDebugInfoDebugTypeBasic: {
-          CHECK_OPERAND("Name", SpvOpString, 5);
-          CHECK_OPERAND("Size", SpvOpConstant, 6);
+          CHECK_OPERAND("Name", spv::Op::OpString, 5);
+          CHECK_OPERAND("Size", spv::Op::OpConstant, 6);
           CHECK_CONST_UINT_OPERAND("Encoding", 7);
           break;
         }
@@ -2966,7 +2966,7 @@
           break;
         }
         case CommonDebugInfoDebugTypedef: {
-          CHECK_OPERAND("Name", SpvOpString, 5);
+          CHECK_OPERAND("Name", spv::Op::OpString, 5);
           auto validate_base_type =
               ValidateOperandBaseType(_, inst, 6, ext_inst_name);
           if (validate_base_type != SPV_SUCCESS) return validate_base_type;
@@ -2983,7 +2983,7 @@
           auto* return_type = _.FindDef(inst->word(6));
           // TODO: We need a spec discussion that we have to allow return and
           // parameter types of a DebugTypeFunction to have template parameter.
-          if (return_type->opcode() != SpvOpTypeVoid) {
+          if (return_type->opcode() != spv::Op::OpTypeVoid) {
             auto validate_return = ValidateOperandDebugType(
                 _, "Return Type", inst, 6, ext_inst_name, true);
             if (validate_return != SPV_SUCCESS) return validate_return;
@@ -2996,7 +2996,7 @@
           break;
         }
         case CommonDebugInfoDebugTypeEnum: {
-          CHECK_OPERAND("Name", SpvOpString, 5);
+          CHECK_OPERAND("Name", spv::Op::OpString, 5);
           if (!DoesDebugInfoOperandMatchExpectation(
                   _,
                   [](CommonDebugInfoInstructions dbg_inst) {
@@ -3014,7 +3014,7 @@
           auto validate_parent =
               ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
           if (validate_parent != SPV_SUCCESS) return validate_parent;
-          CHECK_OPERAND("Size", SpvOpConstant, 11);
+          CHECK_OPERAND("Size", spv::Op::OpConstant, 11);
           auto* size = _.FindDef(inst->word(11));
           if (!_.IsIntScalarType(size->type_id()) || !size->word(3)) {
             return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -3024,27 +3024,27 @@
           CHECK_CONST_UINT_OPERAND("Flags", 12);
           for (uint32_t word_index = 13; word_index + 1 < num_words;
                word_index += 2) {
-            CHECK_OPERAND("Value", SpvOpConstant, word_index);
-            CHECK_OPERAND("Name", SpvOpString, word_index + 1);
+            CHECK_OPERAND("Value", spv::Op::OpConstant, word_index);
+            CHECK_OPERAND("Name", spv::Op::OpString, word_index + 1);
           }
           break;
         }
         case CommonDebugInfoDebugTypeComposite: {
-          CHECK_OPERAND("Name", SpvOpString, 5);
+          CHECK_OPERAND("Name", spv::Op::OpString, 5);
           CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7);
           CHECK_CONST_UINT_OPERAND("Line", 8);
           CHECK_CONST_UINT_OPERAND("Column", 9);
           auto validate_parent =
               ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
           if (validate_parent != SPV_SUCCESS) return validate_parent;
-          CHECK_OPERAND("Linkage Name", SpvOpString, 11);
+          CHECK_OPERAND("Linkage Name", spv::Op::OpString, 11);
           if (!DoesDebugInfoOperandMatchExpectation(
                   _,
                   [](CommonDebugInfoInstructions dbg_inst) {
                     return dbg_inst == CommonDebugInfoDebugInfoNone;
                   },
                   inst, 12)) {
-            CHECK_OPERAND("Size", SpvOpConstant, 12);
+            CHECK_OPERAND("Size", spv::Op::OpConstant, 12);
           }
           CHECK_CONST_UINT_OPERAND("Flags", 13);
           for (uint32_t word_index = 14; word_index < num_words; ++word_index) {
@@ -3066,7 +3066,7 @@
           break;
         }
         case CommonDebugInfoDebugTypeMember: {
-          CHECK_OPERAND("Name", SpvOpString, 5);
+          CHECK_OPERAND("Name", spv::Op::OpString, 5);
           // TODO: We need a spec discussion that we have to allow member types
           // to have template parameter.
           auto validate_type =
@@ -3077,17 +3077,19 @@
           CHECK_CONST_UINT_OPERAND("Column", 9);
           // NonSemantic.Shader.DebugInfo doesn't have the Parent operand
           if (vulkanDebugInfo) {
-            CHECK_OPERAND("Offset", SpvOpConstant, 10);
-            CHECK_OPERAND("Size", SpvOpConstant, 11);
+            CHECK_OPERAND("Offset", spv::Op::OpConstant, 10);
+            CHECK_OPERAND("Size", spv::Op::OpConstant, 11);
             CHECK_CONST_UINT_OPERAND("Flags", 12);
-            if (num_words == 14) CHECK_OPERAND("Value", SpvOpConstant, 13);
+            if (num_words == 14)
+              CHECK_OPERAND("Value", spv::Op::OpConstant, 13);
           } else {
             CHECK_DEBUG_OPERAND("Parent", CommonDebugInfoDebugTypeComposite,
                                 10);
-            CHECK_OPERAND("Offset", SpvOpConstant, 11);
-            CHECK_OPERAND("Size", SpvOpConstant, 12);
+            CHECK_OPERAND("Offset", spv::Op::OpConstant, 11);
+            CHECK_OPERAND("Size", spv::Op::OpConstant, 12);
             CHECK_CONST_UINT_OPERAND("Flags", 13);
-            if (num_words == 15) CHECK_OPERAND("Value", SpvOpConstant, 14);
+            if (num_words == 15)
+              CHECK_OPERAND("Value", spv::Op::OpConstant, 14);
           }
           break;
         }
@@ -3114,13 +3116,13 @@
                    << "expected operand Parent must be class or struct debug "
                       "type";
           }
-          CHECK_OPERAND("Offset", SpvOpConstant, 7);
-          CHECK_OPERAND("Size", SpvOpConstant, 8);
+          CHECK_OPERAND("Offset", spv::Op::OpConstant, 7);
+          CHECK_OPERAND("Size", spv::Op::OpConstant, 8);
           CHECK_CONST_UINT_OPERAND("Flags", 9);
           break;
         }
         case CommonDebugInfoDebugFunction: {
-          CHECK_OPERAND("Name", SpvOpString, 5);
+          CHECK_OPERAND("Name", spv::Op::OpString, 5);
           auto validate_type = ValidateOperandDebugType(_, "Type", inst, 6,
                                                         ext_inst_name, false);
           if (validate_type != SPV_SUCCESS) return validate_type;
@@ -3130,7 +3132,7 @@
           auto validate_parent =
               ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
           if (validate_parent != SPV_SUCCESS) return validate_parent;
-          CHECK_OPERAND("Linkage Name", SpvOpString, 11);
+          CHECK_OPERAND("Linkage Name", spv::Op::OpString, 11);
           CHECK_CONST_UINT_OPERAND("Flags", 12);
           CHECK_CONST_UINT_OPERAND("Scope Line", 13);
           // NonSemantic.Shader.DebugInfo.100 doesn't include a reference to the
@@ -3147,7 +3149,7 @@
                       return dbg_inst == CommonDebugInfoDebugInfoNone;
                     },
                     inst, 14)) {
-              CHECK_OPERAND("Function", SpvOpFunction, 14);
+              CHECK_OPERAND("Function", spv::Op::OpFunction, 14);
             }
             if (num_words == 16) {
               CHECK_DEBUG_OPERAND("Declaration",
@@ -3157,7 +3159,7 @@
           break;
         }
         case CommonDebugInfoDebugFunctionDeclaration: {
-          CHECK_OPERAND("Name", SpvOpString, 5);
+          CHECK_OPERAND("Name", spv::Op::OpString, 5);
           auto validate_type = ValidateOperandDebugType(_, "Type", inst, 6,
                                                         ext_inst_name, false);
           if (validate_type != SPV_SUCCESS) return validate_type;
@@ -3167,7 +3169,7 @@
           auto validate_parent =
               ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
           if (validate_parent != SPV_SUCCESS) return validate_parent;
-          CHECK_OPERAND("Linkage Name", SpvOpString, 11);
+          CHECK_OPERAND("Linkage Name", spv::Op::OpString, 11);
           CHECK_CONST_UINT_OPERAND("Flags", 12);
           break;
         }
@@ -3178,7 +3180,7 @@
           auto validate_parent =
               ValidateOperandLexicalScope(_, "Parent", inst, 8, ext_inst_name);
           if (validate_parent != SPV_SUCCESS) return validate_parent;
-          if (num_words == 10) CHECK_OPERAND("Name", SpvOpString, 9);
+          if (num_words == 10) CHECK_OPERAND("Name", spv::Op::OpString, 9);
           break;
         }
         case CommonDebugInfoDebugScope: {
@@ -3191,7 +3193,7 @@
           break;
         }
         case CommonDebugInfoDebugLocalVariable: {
-          CHECK_OPERAND("Name", SpvOpString, 5);
+          CHECK_OPERAND("Name", spv::Op::OpString, 5);
           // TODO: We need a spec discussion that we have to allow local
           // variable types to have template parameter.
           auto validate_type =
@@ -3213,8 +3215,8 @@
           CHECK_DEBUG_OPERAND("Local Variable",
                               CommonDebugInfoDebugLocalVariable, 5);
           auto* operand = _.FindDef(inst->word(6));
-          if (operand->opcode() != SpvOpVariable &&
-              operand->opcode() != SpvOpFunctionParameter) {
+          if (operand->opcode() != spv::Op::OpVariable &&
+              operand->opcode() != spv::Op::OpFunctionParameter) {
             return _.diag(SPV_ERROR_INVALID_DATA, inst)
                    << ext_inst_name() << ": "
                    << "expected operand Variable must be a result id of "
@@ -3276,7 +3278,7 @@
           break;
         }
         case CommonDebugInfoDebugTypeTemplateParameter: {
-          CHECK_OPERAND("Name", SpvOpString, 5);
+          CHECK_OPERAND("Name", spv::Op::OpString, 5);
           auto validate_actual_type = ValidateOperandDebugType(
               _, "Actual Type", inst, 6, ext_inst_name, false);
           if (validate_actual_type != SPV_SUCCESS) return validate_actual_type;
@@ -3286,7 +3288,7 @@
                     return dbg_inst == CommonDebugInfoDebugInfoNone;
                   },
                   inst, 7)) {
-            CHECK_OPERAND("Value", SpvOpConstant, 7);
+            CHECK_OPERAND("Value", spv::Op::OpConstant, 7);
           }
           CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 8);
           CHECK_CONST_UINT_OPERAND("Line", 9);
@@ -3294,7 +3296,7 @@
           break;
         }
         case CommonDebugInfoDebugGlobalVariable: {
-          CHECK_OPERAND("Name", SpvOpString, 5);
+          CHECK_OPERAND("Name", spv::Op::OpString, 5);
           auto validate_type = ValidateOperandDebugType(_, "Type", inst, 6,
                                                         ext_inst_name, false);
           if (validate_type != SPV_SUCCESS) return validate_type;
@@ -3304,7 +3306,7 @@
           auto validate_scope =
               ValidateOperandLexicalScope(_, "Scope", inst, 10, ext_inst_name);
           if (validate_scope != SPV_SUCCESS) return validate_scope;
-          CHECK_OPERAND("Linkage Name", SpvOpString, 11);
+          CHECK_OPERAND("Linkage Name", spv::Op::OpString, 11);
           if (!DoesDebugInfoOperandMatchExpectation(
                   _,
                   [](CommonDebugInfoInstructions dbg_inst) {
@@ -3312,8 +3314,8 @@
                   },
                   inst, 12)) {
             auto* operand = _.FindDef(inst->word(12));
-            if (operand->opcode() != SpvOpVariable &&
-                operand->opcode() != SpvOpConstant) {
+            if (operand->opcode() != spv::Op::OpVariable &&
+                operand->opcode() != spv::Op::OpConstant) {
               return _.diag(SPV_ERROR_INVALID_DATA, inst)
                      << ext_inst_name() << ": "
                      << "expected operand Variable must be a result id of "
@@ -3401,10 +3403,10 @@
 }
 
 spv_result_t ExtensionPass(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
-  if (opcode == SpvOpExtension) return ValidateExtension(_, inst);
-  if (opcode == SpvOpExtInstImport) return ValidateExtInstImport(_, inst);
-  if (opcode == SpvOpExtInst) return ValidateExtInst(_, inst);
+  const spv::Op opcode = inst->opcode();
+  if (opcode == spv::Op::OpExtension) return ValidateExtension(_, inst);
+  if (opcode == spv::Op::OpExtInstImport) return ValidateExtInstImport(_, inst);
+  if (opcode == spv::Op::OpExtInst) return ValidateExtInst(_, inst);
 
   return SPV_SUCCESS;
 }
diff --git a/source/val/validate_function.cpp b/source/val/validate_function.cpp
index 0ccf5a9..db402aa 100644
--- a/source/val/validate_function.cpp
+++ b/source/val/validate_function.cpp
@@ -28,7 +28,8 @@
 // of the decorations that apply to |a|.
 bool DoPointeesLogicallyMatch(val::Instruction* a, val::Instruction* b,
                               ValidationState_t& _) {
-  if (a->opcode() != SpvOpTypePointer || b->opcode() != SpvOpTypePointer) {
+  if (a->opcode() != spv::Op::OpTypePointer ||
+      b->opcode() != spv::Op::OpTypePointer) {
     return false;
   }
 
@@ -56,7 +57,7 @@
 spv_result_t ValidateFunction(ValidationState_t& _, const Instruction* inst) {
   const auto function_type_id = inst->GetOperandAs<uint32_t>(3);
   const auto function_type = _.FindDef(function_type_id);
-  if (!function_type || SpvOpTypeFunction != function_type->opcode()) {
+  if (!function_type || spv::Op::OpTypeFunction != function_type->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "OpFunction Function Type <id> " << _.getIdName(function_type_id)
            << " is not a function type.";
@@ -70,21 +71,21 @@
            << _.getIdName(return_id) << ".";
   }
 
-  const std::vector<SpvOp> acceptable = {
-      SpvOpGroupDecorate,
-      SpvOpDecorate,
-      SpvOpEnqueueKernel,
-      SpvOpEntryPoint,
-      SpvOpExecutionMode,
-      SpvOpExecutionModeId,
-      SpvOpFunctionCall,
-      SpvOpGetKernelNDrangeSubGroupCount,
-      SpvOpGetKernelNDrangeMaxSubGroupSize,
-      SpvOpGetKernelWorkGroupSize,
-      SpvOpGetKernelPreferredWorkGroupSizeMultiple,
-      SpvOpGetKernelLocalSizeForSubgroupCount,
-      SpvOpGetKernelMaxNumSubgroups,
-      SpvOpName};
+  const std::vector<spv::Op> acceptable = {
+      spv::Op::OpGroupDecorate,
+      spv::Op::OpDecorate,
+      spv::Op::OpEnqueueKernel,
+      spv::Op::OpEntryPoint,
+      spv::Op::OpExecutionMode,
+      spv::Op::OpExecutionModeId,
+      spv::Op::OpFunctionCall,
+      spv::Op::OpGetKernelNDrangeSubGroupCount,
+      spv::Op::OpGetKernelNDrangeMaxSubGroupSize,
+      spv::Op::OpGetKernelWorkGroupSize,
+      spv::Op::OpGetKernelPreferredWorkGroupSizeMultiple,
+      spv::Op::OpGetKernelLocalSizeForSubgroupCount,
+      spv::Op::OpGetKernelMaxNumSubgroups,
+      spv::Op::OpName};
   for (auto& pair : inst->uses()) {
     const auto* use = pair.first;
     if (std::find(acceptable.begin(), acceptable.end(), use->opcode()) ==
@@ -112,14 +113,14 @@
   auto func_inst = &_.ordered_instructions()[inst_num];
   while (--inst_num) {
     func_inst = &_.ordered_instructions()[inst_num];
-    if (func_inst->opcode() == SpvOpFunction) {
+    if (func_inst->opcode() == spv::Op::OpFunction) {
       break;
-    } else if (func_inst->opcode() == SpvOpFunctionParameter) {
+    } else if (func_inst->opcode() == spv::Op::OpFunctionParameter) {
       ++param_index;
     }
   }
 
-  if (func_inst->opcode() != SpvOpFunction) {
+  if (func_inst->opcode() != spv::Op::OpFunction) {
     return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
            << "Function parameter must be preceded by a function.";
   }
@@ -150,25 +151,25 @@
   // Validate that PhysicalStorageBuffer have one of Restrict, Aliased,
   // RestrictPointer, or AliasedPointer.
   auto param_nonarray_type_id = param_type->id();
-  while (_.GetIdOpcode(param_nonarray_type_id) == SpvOpTypeArray) {
+  while (_.GetIdOpcode(param_nonarray_type_id) == spv::Op::OpTypeArray) {
     param_nonarray_type_id =
         _.FindDef(param_nonarray_type_id)->GetOperandAs<uint32_t>(1u);
   }
-  if (_.GetIdOpcode(param_nonarray_type_id) == SpvOpTypePointer) {
+  if (_.GetIdOpcode(param_nonarray_type_id) == spv::Op::OpTypePointer) {
     auto param_nonarray_type = _.FindDef(param_nonarray_type_id);
-    if (param_nonarray_type->GetOperandAs<uint32_t>(1u) ==
-        SpvStorageClassPhysicalStorageBuffer) {
+    if (param_nonarray_type->GetOperandAs<spv::StorageClass>(1u) ==
+        spv::StorageClass::PhysicalStorageBuffer) {
       // check for Aliased or Restrict
       const auto& decorations = _.id_decorations(inst->id());
 
       bool foundAliased = std::any_of(
           decorations.begin(), decorations.end(), [](const Decoration& d) {
-            return SpvDecorationAliased == d.dec_type();
+            return spv::Decoration::Aliased == d.dec_type();
           });
 
       bool foundRestrict = std::any_of(
           decorations.begin(), decorations.end(), [](const Decoration& d) {
-            return SpvDecorationRestrict == d.dec_type();
+            return spv::Decoration::Restrict == d.dec_type();
           });
 
       if (!foundAliased && !foundRestrict) {
@@ -187,20 +188,20 @@
       const auto pointee_type_id =
           param_nonarray_type->GetOperandAs<uint32_t>(2);
       const auto pointee_type = _.FindDef(pointee_type_id);
-      if (SpvOpTypePointer == pointee_type->opcode() &&
-          pointee_type->GetOperandAs<uint32_t>(1u) ==
-              SpvStorageClassPhysicalStorageBuffer) {
+      if (spv::Op::OpTypePointer == pointee_type->opcode() &&
+          pointee_type->GetOperandAs<spv::StorageClass>(1u) ==
+              spv::StorageClass::PhysicalStorageBuffer) {
         // check for AliasedPointer/RestrictPointer
         const auto& decorations = _.id_decorations(inst->id());
 
         bool foundAliased = std::any_of(
             decorations.begin(), decorations.end(), [](const Decoration& d) {
-              return SpvDecorationAliasedPointer == d.dec_type();
+              return spv::Decoration::AliasedPointer == d.dec_type();
             });
 
         bool foundRestrict = std::any_of(
             decorations.begin(), decorations.end(), [](const Decoration& d) {
-              return SpvDecorationRestrictPointer == d.dec_type();
+              return spv::Decoration::RestrictPointer == d.dec_type();
             });
 
         if (!foundAliased && !foundRestrict) {
@@ -226,7 +227,7 @@
                                   const Instruction* inst) {
   const auto function_id = inst->GetOperandAs<uint32_t>(2);
   const auto function = _.FindDef(function_id);
-  if (!function || SpvOpFunction != function->opcode()) {
+  if (!function || spv::Op::OpFunction != function->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "OpFunctionCall Function <id> " << _.getIdName(function_id)
            << " is not a function.";
@@ -242,7 +243,7 @@
 
   const auto function_type_id = function->GetOperandAs<uint32_t>(3);
   const auto function_type = _.FindDef(function_type_id);
-  if (!function_type || function_type->opcode() != SpvOpTypeFunction) {
+  if (!function_type || function_type->opcode() != spv::Op::OpTypeFunction) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Missing function type definition.";
   }
@@ -285,20 +286,21 @@
       }
     }
 
-    if (_.addressing_model() == SpvAddressingModelLogical) {
-      if (parameter_type->opcode() == SpvOpTypePointer &&
+    if (_.addressing_model() == spv::AddressingModel::Logical) {
+      if (parameter_type->opcode() == spv::Op::OpTypePointer &&
           !_.options()->relax_logical_pointer) {
-        SpvStorageClass sc = parameter_type->GetOperandAs<SpvStorageClass>(1u);
+        spv::StorageClass sc =
+            parameter_type->GetOperandAs<spv::StorageClass>(1u);
         // Validate which storage classes can be pointer operands.
         switch (sc) {
-          case SpvStorageClassUniformConstant:
-          case SpvStorageClassFunction:
-          case SpvStorageClassPrivate:
-          case SpvStorageClassWorkgroup:
-          case SpvStorageClassAtomicCounter:
+          case spv::StorageClass::UniformConstant:
+          case spv::StorageClass::Function:
+          case spv::StorageClass::Private:
+          case spv::StorageClass::Workgroup:
+          case spv::StorageClass::AtomicCounter:
             // These are always allowed.
             break;
-          case SpvStorageClassStorageBuffer:
+          case spv::StorageClass::StorageBuffer:
             if (!_.features().variable_pointers) {
               return _.diag(SPV_ERROR_INVALID_ID, inst)
                      << "StorageBuffer pointer operand "
@@ -313,13 +315,14 @@
         }
 
         // Validate memory object declaration requirements.
-        if (argument->opcode() != SpvOpVariable &&
-            argument->opcode() != SpvOpFunctionParameter) {
+        if (argument->opcode() != spv::Op::OpVariable &&
+            argument->opcode() != spv::Op::OpFunctionParameter) {
           const bool ssbo_vptr = _.features().variable_pointers &&
-                                 sc == SpvStorageClassStorageBuffer;
-          const bool wg_vptr = _.HasCapability(SpvCapabilityVariablePointers) &&
-                               sc == SpvStorageClassWorkgroup;
-          const bool uc_ptr = sc == SpvStorageClassUniformConstant;
+                                 sc == spv::StorageClass::StorageBuffer;
+          const bool wg_vptr =
+              _.HasCapability(spv::Capability::VariablePointers) &&
+              sc == spv::StorageClass::Workgroup;
+          const bool uc_ptr = sc == spv::StorageClass::UniformConstant;
           if (!ssbo_vptr && !wg_vptr && !uc_ptr) {
             return _.diag(SPV_ERROR_INVALID_ID, inst)
                    << "Pointer operand " << _.getIdName(argument_id)
@@ -336,13 +339,13 @@
 
 spv_result_t FunctionPass(ValidationState_t& _, const Instruction* inst) {
   switch (inst->opcode()) {
-    case SpvOpFunction:
+    case spv::Op::OpFunction:
       if (auto error = ValidateFunction(_, inst)) return error;
       break;
-    case SpvOpFunctionParameter:
+    case spv::Op::OpFunctionParameter:
       if (auto error = ValidateFunctionParameter(_, inst)) return error;
       break;
-    case SpvOpFunctionCall:
+    case spv::Op::OpFunctionCall:
       if (auto error = ValidateFunctionCall(_, inst)) return error;
       break;
     default:
diff --git a/source/val/validate_id.cpp b/source/val/validate_id.cpp
index 2bab203..89a5ddd 100644
--- a/source/val/validate_id.cpp
+++ b/source/val/validate_id.cpp
@@ -71,7 +71,7 @@
           const Instruction* use = use_index_pair.first;
           if (const BasicBlock* use_block = use->block()) {
             if (use_block->reachable() == false) continue;
-            if (use->opcode() == SpvOpPhi) {
+            if (use->opcode() == spv::Op::OpPhi) {
               if (phi_ids.insert(use->id()).second) {
                 phi_instructions.push_back(use);
               }
@@ -131,7 +131,7 @@
 // instruction operand's ID can be forward referenced.
 spv_result_t IdPass(ValidationState_t& _, Instruction* inst) {
   auto can_have_forward_declared_ids =
-      inst->opcode() == SpvOpExtInst &&
+      inst->opcode() == spv::Op::OpExtInst &&
               spvExtInstIsDebugInfo(inst->ext_inst_type())
           ? spvDbgInfoExtOperandCanBeForwardDeclaredFunction(
                 inst->ext_inst_type(), inst->word(4))
@@ -172,23 +172,27 @@
           if (spvOpcodeGeneratesType(def->opcode()) &&
               !spvOpcodeGeneratesType(opcode) && !spvOpcodeIsDebug(opcode) &&
               !inst->IsDebugInfo() && !inst->IsNonSemantic() &&
-              !spvOpcodeIsDecoration(opcode) && opcode != SpvOpFunction &&
-              opcode != SpvOpCooperativeMatrixLengthNV &&
-              !(opcode == SpvOpSpecConstantOp &&
-                inst->word(3) == SpvOpCooperativeMatrixLengthNV)) {
+              !spvOpcodeIsDecoration(opcode) && opcode != spv::Op::OpFunction &&
+              opcode != spv::Op::OpCooperativeMatrixLengthNV &&
+              !(opcode == spv::Op::OpSpecConstantOp &&
+                spv::Op(inst->word(3)) ==
+                    spv::Op::OpCooperativeMatrixLengthNV)) {
             return _.diag(SPV_ERROR_INVALID_ID, inst)
                    << "Operand " << _.getIdName(operand_word)
                    << " cannot be a type";
           } else if (def->type_id() == 0 && !spvOpcodeGeneratesType(opcode) &&
                      !spvOpcodeIsDebug(opcode) && !inst->IsDebugInfo() &&
                      !inst->IsNonSemantic() && !spvOpcodeIsDecoration(opcode) &&
-                     !spvOpcodeIsBranch(opcode) && opcode != SpvOpPhi &&
-                     opcode != SpvOpExtInst && opcode != SpvOpExtInstImport &&
-                     opcode != SpvOpSelectionMerge &&
-                     opcode != SpvOpLoopMerge && opcode != SpvOpFunction &&
-                     opcode != SpvOpCooperativeMatrixLengthNV &&
-                     !(opcode == SpvOpSpecConstantOp &&
-                       inst->word(3) == SpvOpCooperativeMatrixLengthNV)) {
+                     !spvOpcodeIsBranch(opcode) && opcode != spv::Op::OpPhi &&
+                     opcode != spv::Op::OpExtInst &&
+                     opcode != spv::Op::OpExtInstImport &&
+                     opcode != spv::Op::OpSelectionMerge &&
+                     opcode != spv::Op::OpLoopMerge &&
+                     opcode != spv::Op::OpFunction &&
+                     opcode != spv::Op::OpCooperativeMatrixLengthNV &&
+                     !(opcode == spv::Op::OpSpecConstantOp &&
+                       spv::Op(inst->word(3)) ==
+                           spv::Op::OpCooperativeMatrixLengthNV)) {
             return _.diag(SPV_ERROR_INVALID_ID, inst)
                    << "Operand " << _.getIdName(operand_word)
                    << " requires a type";
diff --git a/source/val/validate_image.cpp b/source/val/validate_image.cpp
index 9c7c8c1..8f0e6c4 100644
--- a/source/val/validate_image.cpp
+++ b/source/val/validate_image.cpp
@@ -32,47 +32,47 @@
 namespace val {
 namespace {
 
-// Performs compile time check that all SpvImageOperandsXXX cases are handled in
-// this module. If SpvImageOperandsXXX list changes, this function will fail the
-// build.
-// For all other purposes this is a placeholder function.
+// Performs compile time check that all spv::ImageOperandsMask::XXX cases are
+// handled in this module. If spv::ImageOperandsMask::XXX list changes, this
+// function will fail the build. For all other purposes this is a placeholder
+// function.
 bool CheckAllImageOperandsHandled() {
-  SpvImageOperandsMask enum_val = SpvImageOperandsBiasMask;
+  spv::ImageOperandsMask enum_val = spv::ImageOperandsMask::Bias;
 
   // Some improvised code to prevent the compiler from considering enum_val
   // constant and optimizing the switch away.
   uint32_t stack_var = 0;
   if (reinterpret_cast<uintptr_t>(&stack_var) % 256)
-    enum_val = SpvImageOperandsLodMask;
+    enum_val = spv::ImageOperandsMask::Lod;
 
   switch (enum_val) {
     // Please update the validation rules in this module if you are changing
     // the list of image operands, and add new enum values to this switch.
-    case SpvImageOperandsMaskNone:
+    case spv::ImageOperandsMask::MaskNone:
       return false;
-    case SpvImageOperandsBiasMask:
-    case SpvImageOperandsLodMask:
-    case SpvImageOperandsGradMask:
-    case SpvImageOperandsConstOffsetMask:
-    case SpvImageOperandsOffsetMask:
-    case SpvImageOperandsConstOffsetsMask:
-    case SpvImageOperandsSampleMask:
-    case SpvImageOperandsMinLodMask:
+    case spv::ImageOperandsMask::Bias:
+    case spv::ImageOperandsMask::Lod:
+    case spv::ImageOperandsMask::Grad:
+    case spv::ImageOperandsMask::ConstOffset:
+    case spv::ImageOperandsMask::Offset:
+    case spv::ImageOperandsMask::ConstOffsets:
+    case spv::ImageOperandsMask::Sample:
+    case spv::ImageOperandsMask::MinLod:
 
     // TODO(dneto): Support image operands related to the Vulkan memory model.
     // https://gitlab.khronos.org/spirv/spirv-tools/issues/32
-    case SpvImageOperandsMakeTexelAvailableKHRMask:
-    case SpvImageOperandsMakeTexelVisibleKHRMask:
-    case SpvImageOperandsNonPrivateTexelKHRMask:
-    case SpvImageOperandsVolatileTexelKHRMask:
-    case SpvImageOperandsSignExtendMask:
-    case SpvImageOperandsZeroExtendMask:
+    case spv::ImageOperandsMask::MakeTexelAvailableKHR:
+    case spv::ImageOperandsMask::MakeTexelVisibleKHR:
+    case spv::ImageOperandsMask::NonPrivateTexelKHR:
+    case spv::ImageOperandsMask::VolatileTexelKHR:
+    case spv::ImageOperandsMask::SignExtend:
+    case spv::ImageOperandsMask::ZeroExtend:
     // TODO(jaebaek): Move this line properly after handling image offsets
     //                operand. This line temporarily fixes CI failure that
     //                blocks other PRs.
     // https://github.com/KhronosGroup/SPIRV-Tools/issues/4565
-    case SpvImageOperandsOffsetsMask:
-    case SpvImageOperandsNontemporalMask:
+    case spv::ImageOperandsMask::Offsets:
+    case spv::ImageOperandsMask::Nontemporal:
       return true;
   }
   return false;
@@ -81,13 +81,13 @@
 // Used by GetImageTypeInfo. See OpTypeImage spec for more information.
 struct ImageTypeInfo {
   uint32_t sampled_type = 0;
-  SpvDim dim = SpvDimMax;
+  spv::Dim dim = spv::Dim::Max;
   uint32_t depth = 0;
   uint32_t arrayed = 0;
   uint32_t multisampled = 0;
   uint32_t sampled = 0;
-  SpvImageFormat format = SpvImageFormatMax;
-  SpvAccessQualifier access_qualifier = SpvAccessQualifierMax;
+  spv::ImageFormat format = spv::ImageFormat::Max;
+  spv::AccessQualifier access_qualifier = spv::AccessQualifier::Max;
 };
 
 // Provides information on image type. |id| should be object of either
@@ -100,39 +100,39 @@
   const Instruction* inst = _.FindDef(id);
   assert(inst);
 
-  if (inst->opcode() == SpvOpTypeSampledImage) {
+  if (inst->opcode() == spv::Op::OpTypeSampledImage) {
     inst = _.FindDef(inst->word(2));
     assert(inst);
   }
 
-  if (inst->opcode() != SpvOpTypeImage) return false;
+  if (inst->opcode() != spv::Op::OpTypeImage) return false;
 
   const size_t num_words = inst->words().size();
   if (num_words != 9 && num_words != 10) return false;
 
   info->sampled_type = inst->word(2);
-  info->dim = static_cast<SpvDim>(inst->word(3));
+  info->dim = static_cast<spv::Dim>(inst->word(3));
   info->depth = inst->word(4);
   info->arrayed = inst->word(5);
   info->multisampled = inst->word(6);
   info->sampled = inst->word(7);
-  info->format = static_cast<SpvImageFormat>(inst->word(8));
-  info->access_qualifier = num_words < 10
-                               ? SpvAccessQualifierMax
-                               : static_cast<SpvAccessQualifier>(inst->word(9));
+  info->format = static_cast<spv::ImageFormat>(inst->word(8));
+  info->access_qualifier =
+      num_words < 10 ? spv::AccessQualifier::Max
+                     : static_cast<spv::AccessQualifier>(inst->word(9));
   return true;
 }
 
-bool IsImplicitLod(SpvOp opcode) {
+bool IsImplicitLod(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpImageSampleImplicitLod:
-    case SpvOpImageSampleDrefImplicitLod:
-    case SpvOpImageSampleProjImplicitLod:
-    case SpvOpImageSampleProjDrefImplicitLod:
-    case SpvOpImageSparseSampleImplicitLod:
-    case SpvOpImageSparseSampleDrefImplicitLod:
-    case SpvOpImageSparseSampleProjImplicitLod:
-    case SpvOpImageSparseSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSampleImplicitLod:
+    case spv::Op::OpImageSampleDrefImplicitLod:
+    case spv::Op::OpImageSampleProjImplicitLod:
+    case spv::Op::OpImageSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleImplicitLod:
+    case spv::Op::OpImageSparseSampleDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleProjImplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefImplicitLod:
       return true;
     default:
       break;
@@ -140,16 +140,16 @@
   return false;
 }
 
-bool IsExplicitLod(SpvOp opcode) {
+bool IsExplicitLod(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpImageSampleExplicitLod:
-    case SpvOpImageSampleDrefExplicitLod:
-    case SpvOpImageSampleProjExplicitLod:
-    case SpvOpImageSampleProjDrefExplicitLod:
-    case SpvOpImageSparseSampleExplicitLod:
-    case SpvOpImageSparseSampleDrefExplicitLod:
-    case SpvOpImageSparseSampleProjExplicitLod:
-    case SpvOpImageSparseSampleProjDrefExplicitLod:
+    case spv::Op::OpImageSampleExplicitLod:
+    case spv::Op::OpImageSampleDrefExplicitLod:
+    case spv::Op::OpImageSampleProjExplicitLod:
+    case spv::Op::OpImageSampleProjDrefExplicitLod:
+    case spv::Op::OpImageSparseSampleExplicitLod:
+    case spv::Op::OpImageSparseSampleDrefExplicitLod:
+    case spv::Op::OpImageSparseSampleProjExplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefExplicitLod:
       return true;
     default:
       break;
@@ -157,22 +157,22 @@
   return false;
 }
 
-bool IsValidLodOperand(const ValidationState_t& _, SpvOp opcode) {
+bool IsValidLodOperand(const ValidationState_t& _, spv::Op opcode) {
   switch (opcode) {
-    case SpvOpImageRead:
-    case SpvOpImageWrite:
-    case SpvOpImageSparseRead:
-      return _.HasCapability(SpvCapabilityImageReadWriteLodAMD);
+    case spv::Op::OpImageRead:
+    case spv::Op::OpImageWrite:
+    case spv::Op::OpImageSparseRead:
+      return _.HasCapability(spv::Capability::ImageReadWriteLodAMD);
     default:
       return IsExplicitLod(opcode);
   }
 }
 
-bool IsValidGatherLodBiasAMD(const ValidationState_t& _, SpvOp opcode) {
+bool IsValidGatherLodBiasAMD(const ValidationState_t& _, spv::Op opcode) {
   switch (opcode) {
-    case SpvOpImageGather:
-    case SpvOpImageSparseGather:
-      return _.HasCapability(SpvCapabilityImageGatherBiasLodAMD);
+    case spv::Op::OpImageGather:
+    case spv::Op::OpImageSparseGather:
+      return _.HasCapability(spv::Capability::ImageGatherBiasLodAMD);
     default:
       break;
   }
@@ -181,16 +181,16 @@
 
 // Returns true if the opcode is a Image instruction which applies
 // homogenous projection to the coordinates.
-bool IsProj(SpvOp opcode) {
+bool IsProj(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpImageSampleProjImplicitLod:
-    case SpvOpImageSampleProjDrefImplicitLod:
-    case SpvOpImageSparseSampleProjImplicitLod:
-    case SpvOpImageSparseSampleProjDrefImplicitLod:
-    case SpvOpImageSampleProjExplicitLod:
-    case SpvOpImageSampleProjDrefExplicitLod:
-    case SpvOpImageSparseSampleProjExplicitLod:
-    case SpvOpImageSparseSampleProjDrefExplicitLod:
+    case spv::Op::OpImageSampleProjImplicitLod:
+    case spv::Op::OpImageSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleProjImplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSampleProjExplicitLod:
+    case spv::Op::OpImageSampleProjDrefExplicitLod:
+    case spv::Op::OpImageSparseSampleProjExplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefExplicitLod:
       return true;
     default:
       break;
@@ -204,21 +204,21 @@
   uint32_t plane_size = 0;
   // If this switch breaks your build, please add new values below.
   switch (info.dim) {
-    case SpvDim1D:
-    case SpvDimBuffer:
+    case spv::Dim::Dim1D:
+    case spv::Dim::Buffer:
       plane_size = 1;
       break;
-    case SpvDim2D:
-    case SpvDimRect:
-    case SpvDimSubpassData:
+    case spv::Dim::Dim2D:
+    case spv::Dim::Rect:
+    case spv::Dim::SubpassData:
       plane_size = 2;
       break;
-    case SpvDim3D:
-    case SpvDimCube:
+    case spv::Dim::Dim3D:
+    case spv::Dim::Cube:
       // For Cube direction vector is used instead of UV.
       plane_size = 3;
       break;
-    case SpvDimMax:
+    case spv::Dim::Max:
       assert(0);
       break;
   }
@@ -228,10 +228,10 @@
 
 // Returns minimal number of coordinates based on image dim, arrayed and whether
 // the instruction uses projection coordinates.
-uint32_t GetMinCoordSize(SpvOp opcode, const ImageTypeInfo& info) {
-  if (info.dim == SpvDimCube &&
-      (opcode == SpvOpImageRead || opcode == SpvOpImageWrite ||
-       opcode == SpvOpImageSparseRead)) {
+uint32_t GetMinCoordSize(spv::Op opcode, const ImageTypeInfo& info) {
+  if (info.dim == spv::Dim::Cube &&
+      (opcode == spv::Op::OpImageRead || opcode == spv::Op::OpImageWrite ||
+       opcode == spv::Op::OpImageSparseRead)) {
     // These opcodes use UV for Cube, not direction vector.
     return 3;
   }
@@ -248,7 +248,7 @@
   static const bool kAllImageOperandsHandled = CheckAllImageOperandsHandled();
   (void)kAllImageOperandsHandled;
 
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   const size_t num_words = inst->words().size();
 
   const bool have_explicit_mask = (word_index - 1 < num_words);
@@ -257,14 +257,14 @@
   if (have_explicit_mask) {
     // NonPrivate, Volatile, SignExtend, ZeroExtend take no operand words.
     const uint32_t mask_bits_having_operands =
-        mask & ~uint32_t(SpvImageOperandsNonPrivateTexelKHRMask |
-                         SpvImageOperandsVolatileTexelKHRMask |
-                         SpvImageOperandsSignExtendMask |
-                         SpvImageOperandsZeroExtendMask |
-                         SpvImageOperandsNontemporalMask);
+        mask & ~uint32_t(spv::ImageOperandsMask::NonPrivateTexelKHR |
+                         spv::ImageOperandsMask::VolatileTexelKHR |
+                         spv::ImageOperandsMask::SignExtend |
+                         spv::ImageOperandsMask::ZeroExtend |
+                         spv::ImageOperandsMask::Nontemporal);
     size_t expected_num_image_operand_words =
         spvtools::utils::CountSetBits(mask_bits_having_operands);
-    if (mask & SpvImageOperandsGradMask) {
+    if (mask & uint32_t(spv::ImageOperandsMask::Grad)) {
       // Grad uses two words.
       ++expected_num_image_operand_words;
     }
@@ -279,7 +279,8 @@
            << "Number of image operand ids doesn't correspond to the bit mask";
   }
 
-  if (info.multisampled & (0 == (mask & SpvImageOperandsSampleMask))) {
+  if (info.multisampled &
+      (0 == (mask & uint32_t(spv::ImageOperandsMask::Sample)))) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Image Operand Sample is required for operation on "
               "multi-sampled image";
@@ -289,10 +290,11 @@
   // the module to be invalid.
   if (mask == 0) return SPV_SUCCESS;
 
-  if (spvtools::utils::CountSetBits(mask & (SpvImageOperandsOffsetMask |
-                                            SpvImageOperandsConstOffsetMask |
-                                            SpvImageOperandsConstOffsetsMask |
-                                            SpvImageOperandsOffsetsMask)) > 1) {
+  if (spvtools::utils::CountSetBits(
+          mask & uint32_t(spv::ImageOperandsMask::Offset |
+                          spv::ImageOperandsMask::ConstOffset |
+                          spv::ImageOperandsMask::ConstOffsets |
+                          spv::ImageOperandsMask::Offsets)) > 1) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << _.VkErrorID(4662)
            << "Image Operands Offset, ConstOffset, ConstOffsets, Offsets "
@@ -306,7 +308,7 @@
 
   // The checks should be done in the order of definition of OperandImage.
 
-  if (mask & SpvImageOperandsBiasMask) {
+  if (mask & uint32_t(spv::ImageOperandsMask::Bias)) {
     if (!is_implicit_lod && !is_valid_gather_lod_bias_amd) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand Bias can only be used with ImplicitLod opcodes";
@@ -318,8 +320,8 @@
              << "Expected Image Operand Bias to be float scalar";
     }
 
-    if (info.dim != SpvDim1D && info.dim != SpvDim2D && info.dim != SpvDim3D &&
-        info.dim != SpvDimCube) {
+    if (info.dim != spv::Dim::Dim1D && info.dim != spv::Dim::Dim2D &&
+        info.dim != spv::Dim::Dim3D && info.dim != spv::Dim::Cube) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand Bias requires 'Dim' parameter to be 1D, 2D, 3D "
                 "or Cube";
@@ -328,15 +330,16 @@
     // Multisampled is already checked.
   }
 
-  if (mask & SpvImageOperandsLodMask) {
-    if (!is_valid_lod_operand && opcode != SpvOpImageFetch &&
-        opcode != SpvOpImageSparseFetch && !is_valid_gather_lod_bias_amd) {
+  if (mask & uint32_t(spv::ImageOperandsMask::Lod)) {
+    if (!is_valid_lod_operand && opcode != spv::Op::OpImageFetch &&
+        opcode != spv::Op::OpImageSparseFetch &&
+        !is_valid_gather_lod_bias_amd) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand Lod can only be used with ExplicitLod opcodes "
              << "and OpImageFetch";
     }
 
-    if (mask & SpvImageOperandsGradMask) {
+    if (mask & uint32_t(spv::ImageOperandsMask::Grad)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand bits Lod and Grad cannot be set at the same "
                 "time";
@@ -357,8 +360,8 @@
       }
     }
 
-    if (info.dim != SpvDim1D && info.dim != SpvDim2D && info.dim != SpvDim3D &&
-        info.dim != SpvDimCube) {
+    if (info.dim != spv::Dim::Dim1D && info.dim != spv::Dim::Dim2D &&
+        info.dim != spv::Dim::Dim3D && info.dim != spv::Dim::Cube) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand Lod requires 'Dim' parameter to be 1D, 2D, 3D "
                 "or Cube";
@@ -367,7 +370,7 @@
     // Multisampled is already checked.
   }
 
-  if (mask & SpvImageOperandsGradMask) {
+  if (mask & uint32_t(spv::ImageOperandsMask::Grad)) {
     if (!is_explicit_lod) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand Grad can only be used with ExplicitLod opcodes";
@@ -400,8 +403,8 @@
     // Multisampled is already checked.
   }
 
-  if (mask & SpvImageOperandsConstOffsetMask) {
-    if (info.dim == SpvDimCube) {
+  if (mask & uint32_t(spv::ImageOperandsMask::ConstOffset)) {
+    if (info.dim == spv::Dim::Cube) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand ConstOffset cannot be used with Cube Image "
                 "'Dim'";
@@ -429,8 +432,8 @@
     }
   }
 
-  if (mask & SpvImageOperandsOffsetMask) {
-    if (info.dim == SpvDimCube) {
+  if (mask & uint32_t(spv::ImageOperandsMask::Offset)) {
+    if (info.dim == spv::Dim::Cube) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand Offset cannot be used with Cube Image 'Dim'";
     }
@@ -453,9 +456,10 @@
 
     if (!_.options()->before_hlsl_legalization &&
         spvIsVulkanEnv(_.context()->target_env)) {
-      if (opcode != SpvOpImageGather && opcode != SpvOpImageDrefGather &&
-          opcode != SpvOpImageSparseGather &&
-          opcode != SpvOpImageSparseDrefGather) {
+      if (opcode != spv::Op::OpImageGather &&
+          opcode != spv::Op::OpImageDrefGather &&
+          opcode != spv::Op::OpImageSparseGather &&
+          opcode != spv::Op::OpImageSparseDrefGather) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << _.VkErrorID(4663)
                << "Image Operand Offset can only be used with "
@@ -464,16 +468,17 @@
     }
   }
 
-  if (mask & SpvImageOperandsConstOffsetsMask) {
-    if (opcode != SpvOpImageGather && opcode != SpvOpImageDrefGather &&
-        opcode != SpvOpImageSparseGather &&
-        opcode != SpvOpImageSparseDrefGather) {
+  if (mask & uint32_t(spv::ImageOperandsMask::ConstOffsets)) {
+    if (opcode != spv::Op::OpImageGather &&
+        opcode != spv::Op::OpImageDrefGather &&
+        opcode != spv::Op::OpImageSparseGather &&
+        opcode != spv::Op::OpImageSparseDrefGather) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand ConstOffsets can only be used with "
                 "OpImageGather and OpImageDrefGather";
     }
 
-    if (info.dim == SpvDimCube) {
+    if (info.dim == spv::Dim::Cube) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand ConstOffsets cannot be used with Cube Image "
                 "'Dim'";
@@ -484,7 +489,7 @@
     const Instruction* type_inst = _.FindDef(type_id);
     assert(type_inst);
 
-    if (type_inst->opcode() != SpvOpTypeArray) {
+    if (type_inst->opcode() != spv::Op::OpTypeArray) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Expected Image Operand ConstOffsets to be an array of size 4";
     }
@@ -513,10 +518,11 @@
     }
   }
 
-  if (mask & SpvImageOperandsSampleMask) {
-    if (opcode != SpvOpImageFetch && opcode != SpvOpImageRead &&
-        opcode != SpvOpImageWrite && opcode != SpvOpImageSparseFetch &&
-        opcode != SpvOpImageSparseRead) {
+  if (mask & uint32_t(spv::ImageOperandsMask::Sample)) {
+    if (opcode != spv::Op::OpImageFetch && opcode != spv::Op::OpImageRead &&
+        opcode != spv::Op::OpImageWrite &&
+        opcode != spv::Op::OpImageSparseFetch &&
+        opcode != spv::Op::OpImageSparseRead) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand Sample can only be used with OpImageFetch, "
              << "OpImageRead, OpImageWrite, OpImageSparseFetch and "
@@ -535,8 +541,8 @@
     }
   }
 
-  if (mask & SpvImageOperandsMinLodMask) {
-    if (!is_implicit_lod && !(mask & SpvImageOperandsGradMask)) {
+  if (mask & uint32_t(spv::ImageOperandsMask::MinLod)) {
+    if (!is_implicit_lod && !(mask & uint32_t(spv::ImageOperandsMask::Grad))) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand MinLod can only be used with ImplicitLod "
              << "opcodes or together with Image Operand Grad";
@@ -548,8 +554,8 @@
              << "Expected Image Operand MinLod to be float scalar";
     }
 
-    if (info.dim != SpvDim1D && info.dim != SpvDim2D && info.dim != SpvDim3D &&
-        info.dim != SpvDimCube) {
+    if (info.dim != spv::Dim::Dim1D && info.dim != spv::Dim::Dim2D &&
+        info.dim != spv::Dim::Dim3D && info.dim != spv::Dim::Cube) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand MinLod requires 'Dim' parameter to be 1D, 2D, "
                 "3D or Cube";
@@ -561,16 +567,16 @@
     }
   }
 
-  if (mask & SpvImageOperandsMakeTexelAvailableKHRMask) {
+  if (mask & uint32_t(spv::ImageOperandsMask::MakeTexelAvailableKHR)) {
     // Checked elsewhere: capability and memory model are correct.
-    if (opcode != SpvOpImageWrite) {
+    if (opcode != spv::Op::OpImageWrite) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand MakeTexelAvailableKHR can only be used with Op"
-             << spvOpcodeString(SpvOpImageWrite) << ": Op"
+             << spvOpcodeString(spv::Op::OpImageWrite) << ": Op"
              << spvOpcodeString(opcode);
     }
 
-    if (!(mask & SpvImageOperandsNonPrivateTexelKHRMask)) {
+    if (!(mask & uint32_t(spv::ImageOperandsMask::NonPrivateTexelKHR))) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand MakeTexelAvailableKHR requires "
                 "NonPrivateTexelKHR is also specified: Op"
@@ -582,17 +588,18 @@
       return error;
   }
 
-  if (mask & SpvImageOperandsMakeTexelVisibleKHRMask) {
+  if (mask & uint32_t(spv::ImageOperandsMask::MakeTexelVisibleKHR)) {
     // Checked elsewhere: capability and memory model are correct.
-    if (opcode != SpvOpImageRead && opcode != SpvOpImageSparseRead) {
+    if (opcode != spv::Op::OpImageRead &&
+        opcode != spv::Op::OpImageSparseRead) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand MakeTexelVisibleKHR can only be used with Op"
-             << spvOpcodeString(SpvOpImageRead) << " or Op"
-             << spvOpcodeString(SpvOpImageSparseRead) << ": Op"
+             << spvOpcodeString(spv::Op::OpImageRead) << " or Op"
+             << spvOpcodeString(spv::Op::OpImageSparseRead) << ": Op"
              << spvOpcodeString(opcode);
     }
 
-    if (!(mask & SpvImageOperandsNonPrivateTexelKHRMask)) {
+    if (!(mask & uint32_t(spv::ImageOperandsMask::NonPrivateTexelKHR))) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Operand MakeTexelVisibleKHR requires NonPrivateTexelKHR "
                 "is also specified: Op"
@@ -603,7 +610,7 @@
     if (auto error = ValidateMemoryScope(_, inst, visible_scope)) return error;
   }
 
-  if (mask & SpvImageOperandsSignExtendMask) {
+  if (mask & uint32_t(spv::ImageOperandsMask::SignExtend)) {
     // Checked elsewhere: SPIR-V 1.4 version or later.
 
     // "The texel value is converted to the target value via sign extension.
@@ -616,7 +623,7 @@
     // setup.
   }
 
-  if (mask & SpvImageOperandsZeroExtendMask) {
+  if (mask & uint32_t(spv::ImageOperandsMask::ZeroExtend)) {
     // Checked elsewhere: SPIR-V 1.4 version or later.
 
     // "The texel value is converted to the target value via zero extension.
@@ -629,11 +636,11 @@
     // setup.
   }
 
-  if (mask & SpvImageOperandsOffsetsMask) {
+  if (mask & uint32_t(spv::ImageOperandsMask::Offsets)) {
     // TODO: add validation
   }
 
-  if (mask & SpvImageOperandsNontemporalMask) {
+  if (mask & uint32_t(spv::ImageOperandsMask::Nontemporal)) {
     // Checked elsewhere: SPIR-V 1.6 version or later.
   }
 
@@ -643,8 +650,8 @@
 // Validate OpImage*Proj* instructions
 spv_result_t ValidateImageProj(ValidationState_t& _, const Instruction* inst,
                                const ImageTypeInfo& info) {
-  if (info.dim != SpvDim1D && info.dim != SpvDim2D && info.dim != SpvDim3D &&
-      info.dim != SpvDimRect) {
+  if (info.dim != spv::Dim::Dim1D && info.dim != spv::Dim::Dim2D &&
+      info.dim != spv::Dim::Dim3D && info.dim != spv::Dim::Rect) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Image 'Dim' parameter to be 1D, 2D, 3D or Rect";
   }
@@ -667,25 +674,27 @@
                                     const Instruction* inst,
                                     const ImageTypeInfo& info) {
   if (info.sampled == 2) {
-    if (info.dim == SpvDim1D && !_.HasCapability(SpvCapabilityImage1D)) {
+    if (info.dim == spv::Dim::Dim1D &&
+        !_.HasCapability(spv::Capability::Image1D)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Capability Image1D is required to access storage image";
-    } else if (info.dim == SpvDimRect &&
-               !_.HasCapability(SpvCapabilityImageRect)) {
+    } else if (info.dim == spv::Dim::Rect &&
+               !_.HasCapability(spv::Capability::ImageRect)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Capability ImageRect is required to access storage image";
-    } else if (info.dim == SpvDimBuffer &&
-               !_.HasCapability(SpvCapabilityImageBuffer)) {
+    } else if (info.dim == spv::Dim::Buffer &&
+               !_.HasCapability(spv::Capability::ImageBuffer)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Capability ImageBuffer is required to access storage image";
-    } else if (info.dim == SpvDimCube && info.arrayed == 1 &&
-               !_.HasCapability(SpvCapabilityImageCubeArray)) {
+    } else if (info.dim == spv::Dim::Cube && info.arrayed == 1 &&
+               !_.HasCapability(spv::Capability::ImageCubeArray)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Capability ImageCubeArray is required to access "
              << "storage image";
     }
 
-    if (info.multisampled == 1 && !_.HasCapability(SpvCapabilityImageMSArray)) {
+    if (info.multisampled == 1 &&
+        !_.HasCapability(spv::Capability::ImageMSArray)) {
 #if 0
       // TODO(atgoo@github.com) The description of this rule in the spec
       // is unclear and Glslang doesn't declare ImageMSArray. Need to clarify
@@ -704,21 +713,21 @@
 }
 
 // Returns true if opcode is *ImageSparse*, false otherwise.
-bool IsSparse(SpvOp opcode) {
+bool IsSparse(spv::Op opcode) {
   switch (opcode) {
-    case SpvOpImageSparseSampleImplicitLod:
-    case SpvOpImageSparseSampleExplicitLod:
-    case SpvOpImageSparseSampleDrefImplicitLod:
-    case SpvOpImageSparseSampleDrefExplicitLod:
-    case SpvOpImageSparseSampleProjImplicitLod:
-    case SpvOpImageSparseSampleProjExplicitLod:
-    case SpvOpImageSparseSampleProjDrefImplicitLod:
-    case SpvOpImageSparseSampleProjDrefExplicitLod:
-    case SpvOpImageSparseFetch:
-    case SpvOpImageSparseGather:
-    case SpvOpImageSparseDrefGather:
-    case SpvOpImageSparseTexelsResident:
-    case SpvOpImageSparseRead: {
+    case spv::Op::OpImageSparseSampleImplicitLod:
+    case spv::Op::OpImageSparseSampleExplicitLod:
+    case spv::Op::OpImageSparseSampleDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleDrefExplicitLod:
+    case spv::Op::OpImageSparseSampleProjImplicitLod:
+    case spv::Op::OpImageSparseSampleProjExplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefExplicitLod:
+    case spv::Op::OpImageSparseFetch:
+    case spv::Op::OpImageSparseGather:
+    case spv::Op::OpImageSparseDrefGather:
+    case spv::Op::OpImageSparseTexelsResident:
+    case spv::Op::OpImageSparseRead: {
       return true;
     }
 
@@ -733,13 +742,13 @@
 // Not valid for sparse image opcodes which do not return a struct.
 spv_result_t GetActualResultType(ValidationState_t& _, const Instruction* inst,
                                  uint32_t* actual_result_type) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
 
   if (IsSparse(opcode)) {
     const Instruction* const type_inst = _.FindDef(inst->type_id());
     assert(type_inst);
 
-    if (!type_inst || type_inst->opcode() != SpvOpTypeStruct) {
+    if (!type_inst || type_inst->opcode() != spv::Op::OpTypeStruct) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Expected Result Type to be OpTypeStruct";
     }
@@ -761,7 +770,7 @@
 
 // Returns a string describing actual result type of an opcode.
 // Not valid for sparse image opcodes which do not return a struct.
-const char* GetActualResultTypeStr(SpvOp opcode) {
+const char* GetActualResultTypeStr(spv::Op opcode) {
   if (IsSparse(opcode)) return "Result Type's second member";
   return "Result Type";
 }
@@ -777,7 +786,7 @@
 
   if (_.IsIntScalarType(info.sampled_type) &&
       (64 == _.GetBitWidth(info.sampled_type)) &&
-      !_.HasCapability(SpvCapabilityInt64ImageEXT)) {
+      !_.HasCapability(spv::Capability::Int64ImageEXT)) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Capability Int64ImageEXT is required when using Sampled Type of "
               "64-bit int";
@@ -802,10 +811,10 @@
              << "Sampled Type must be OpTypeVoid in the OpenCL environment.";
     }
   } else {
-    const SpvOp sampled_type_opcode = _.GetIdOpcode(info.sampled_type);
-    if (sampled_type_opcode != SpvOpTypeVoid &&
-        sampled_type_opcode != SpvOpTypeInt &&
-        sampled_type_opcode != SpvOpTypeFloat) {
+    const spv::Op sampled_type_opcode = _.GetIdOpcode(info.sampled_type);
+    if (sampled_type_opcode != spv::Op::OpTypeVoid &&
+        sampled_type_opcode != spv::Op::OpTypeInt &&
+        sampled_type_opcode != spv::Op::OpTypeFloat) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Expected Sampled Type to be either void or"
              << " numerical scalar type";
@@ -835,19 +844,19 @@
            << "Invalid Sampled " << info.sampled << " (must be 0, 1 or 2)";
   }
 
-  if (info.dim == SpvDimSubpassData) {
+  if (info.dim == spv::Dim::SubpassData) {
     if (info.sampled != 2) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << _.VkErrorID(6214) << "Dim SubpassData requires Sampled to be 2";
     }
 
-    if (info.format != SpvImageFormatUnknown) {
+    if (info.format != spv::ImageFormat::Unknown) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Dim SubpassData requires format Unknown";
     }
   } else {
     if (info.multisampled && (info.sampled == 2) &&
-        !_.HasCapability(SpvCapabilityStorageImageMultisample)) {
+        !_.HasCapability(spv::Capability::StorageImageMultisample)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Capability StorageImageMultisample is required when using "
                 "multisampled storage image";
@@ -855,8 +864,8 @@
   }
 
   if (spvIsOpenCLEnv(target_env)) {
-    if ((info.arrayed == 1) && (info.dim != SpvDim1D) &&
-        (info.dim != SpvDim2D)) {
+    if ((info.arrayed == 1) && (info.dim != spv::Dim::Dim1D) &&
+        (info.dim != spv::Dim::Dim2D)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "In the OpenCL environment, Arrayed may only be set to 1 "
              << "when Dim is either 1D or 2D.";
@@ -872,7 +881,7 @@
              << "Sampled must be 0 in the OpenCL environment.";
     }
 
-    if (info.access_qualifier == SpvAccessQualifierMax) {
+    if (info.access_qualifier == spv::AccessQualifier::Max) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "In the OpenCL environment, the optional Access Qualifier"
              << " must be present.";
@@ -886,7 +895,7 @@
              << "Sampled must be 1 or 2 in the Vulkan environment.";
     }
 
-    if (info.dim == SpvDimSubpassData && info.arrayed != 0) {
+    if (info.dim == spv::Dim::SubpassData && info.arrayed != 0) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << _.VkErrorID(6214) << "Dim SubpassData requires Arrayed to be 0";
     }
@@ -898,7 +907,7 @@
 spv_result_t ValidateTypeSampledImage(ValidationState_t& _,
                                       const Instruction* inst) {
   const uint32_t image_type = inst->word(2);
-  if (_.GetIdOpcode(image_type) != SpvOpTypeImage) {
+  if (_.GetIdOpcode(image_type) != spv::Op::OpTypeImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Image to be of type OpTypeImage";
   }
@@ -918,7 +927,8 @@
   }
 
   // This covers both OpTypeSampledImage and OpSampledImage.
-  if (_.version() >= SPV_SPIRV_VERSION_WORD(1, 6) && info.dim == SpvDimBuffer) {
+  if (_.version() >= SPV_SPIRV_VERSION_WORD(1, 6) &&
+      info.dim == spv::Dim::Buffer) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "In SPIR-V 1.6 or later, sampled image dimension must not be "
               "Buffer";
@@ -927,31 +937,31 @@
   return SPV_SUCCESS;
 }
 
-bool IsAllowedSampledImageOperand(SpvOp opcode, ValidationState_t& _) {
+bool IsAllowedSampledImageOperand(spv::Op opcode, ValidationState_t& _) {
   switch (opcode) {
-    case SpvOpSampledImage:
-    case SpvOpImageSampleImplicitLod:
-    case SpvOpImageSampleExplicitLod:
-    case SpvOpImageSampleDrefImplicitLod:
-    case SpvOpImageSampleDrefExplicitLod:
-    case SpvOpImageSampleProjImplicitLod:
-    case SpvOpImageSampleProjExplicitLod:
-    case SpvOpImageSampleProjDrefImplicitLod:
-    case SpvOpImageSampleProjDrefExplicitLod:
-    case SpvOpImageGather:
-    case SpvOpImageDrefGather:
-    case SpvOpImage:
-    case SpvOpImageQueryLod:
-    case SpvOpImageSparseSampleImplicitLod:
-    case SpvOpImageSparseSampleExplicitLod:
-    case SpvOpImageSparseSampleDrefImplicitLod:
-    case SpvOpImageSparseSampleDrefExplicitLod:
-    case SpvOpImageSparseGather:
-    case SpvOpImageSparseDrefGather:
-    case SpvOpCopyObject:
+    case spv::Op::OpSampledImage:
+    case spv::Op::OpImageSampleImplicitLod:
+    case spv::Op::OpImageSampleExplicitLod:
+    case spv::Op::OpImageSampleDrefImplicitLod:
+    case spv::Op::OpImageSampleDrefExplicitLod:
+    case spv::Op::OpImageSampleProjImplicitLod:
+    case spv::Op::OpImageSampleProjExplicitLod:
+    case spv::Op::OpImageSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSampleProjDrefExplicitLod:
+    case spv::Op::OpImageGather:
+    case spv::Op::OpImageDrefGather:
+    case spv::Op::OpImage:
+    case spv::Op::OpImageQueryLod:
+    case spv::Op::OpImageSparseSampleImplicitLod:
+    case spv::Op::OpImageSparseSampleExplicitLod:
+    case spv::Op::OpImageSparseSampleDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleDrefExplicitLod:
+    case spv::Op::OpImageSparseGather:
+    case spv::Op::OpImageSparseDrefGather:
+    case spv::Op::OpCopyObject:
       return true;
-    case SpvOpStore:
-      if (_.HasCapability(SpvCapabilityBindlessTextureNV)) return true;
+    case spv::Op::OpStore:
+      if (_.HasCapability(spv::Capability::BindlessTextureNV)) return true;
       return false;
     default:
       return false;
@@ -960,13 +970,13 @@
 
 spv_result_t ValidateSampledImage(ValidationState_t& _,
                                   const Instruction* inst) {
-  if (_.GetIdOpcode(inst->type_id()) != SpvOpTypeSampledImage) {
+  if (_.GetIdOpcode(inst->type_id()) != spv::Op::OpTypeSampledImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Result Type to be OpTypeSampledImage.";
   }
 
   const uint32_t image_type = _.GetOperandTypeId(inst, 2);
-  if (_.GetIdOpcode(image_type) != SpvOpTypeImage) {
+  if (_.GetIdOpcode(image_type) != spv::Op::OpTypeImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Image to be of type OpTypeImage.";
   }
@@ -994,12 +1004,12 @@
     }
   }
 
-  if (info.dim == SpvDimSubpassData) {
+  if (info.dim == spv::Dim::SubpassData) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Image 'Dim' parameter to be not SubpassData.";
   }
 
-  if (_.GetIdOpcode(_.GetOperandTypeId(inst, 3)) != SpvOpTypeSampler) {
+  if (_.GetIdOpcode(_.GetOperandTypeId(inst, 3)) != spv::Op::OpTypeSampler) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Sampler to be of type OpTypeSampler";
   }
@@ -1027,12 +1037,13 @@
                << _.getIdName(consumer_instr->id()) << ".";
       }
 
-      if (consumer_opcode == SpvOpPhi || consumer_opcode == SpvOpSelect) {
+      if (consumer_opcode == spv::Op::OpPhi ||
+          consumer_opcode == spv::Op::OpSelect) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << "Result <id> from OpSampledImage instruction must not appear "
                   "as "
                   "operands of Op"
-               << spvOpcodeString(static_cast<SpvOp>(consumer_opcode)) << "."
+               << spvOpcodeString(static_cast<spv::Op>(consumer_opcode)) << "."
                << " Found result <id> " << _.getIdName(inst->id())
                << " as an operand of <id> " << _.getIdName(consumer_instr->id())
                << ".";
@@ -1042,7 +1053,7 @@
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << "Result <id> from OpSampledImage instruction must not appear "
                   "as operand for Op"
-               << spvOpcodeString(static_cast<SpvOp>(consumer_opcode))
+               << spvOpcodeString(static_cast<spv::Op>(consumer_opcode))
                << ", since it is not specified as taking an "
                << "OpTypeSampledImage."
                << " Found result <id> " << _.getIdName(inst->id())
@@ -1057,13 +1068,13 @@
 spv_result_t ValidateImageTexelPointer(ValidationState_t& _,
                                        const Instruction* inst) {
   const auto result_type = _.FindDef(inst->type_id());
-  if (result_type->opcode() != SpvOpTypePointer) {
+  if (result_type->opcode() != spv::Op::OpTypePointer) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Result Type to be OpTypePointer";
   }
 
-  const auto storage_class = result_type->GetOperandAs<uint32_t>(1);
-  if (storage_class != SpvStorageClassImage) {
+  const auto storage_class = result_type->GetOperandAs<spv::StorageClass>(1);
+  if (storage_class != spv::StorageClass::Image) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Result Type to be OpTypePointer whose Storage Class "
               "operand is Image";
@@ -1071,21 +1082,21 @@
 
   const auto ptr_type = result_type->GetOperandAs<uint32_t>(2);
   const auto ptr_opcode = _.GetIdOpcode(ptr_type);
-  if (ptr_opcode != SpvOpTypeInt && ptr_opcode != SpvOpTypeFloat &&
-      ptr_opcode != SpvOpTypeVoid) {
+  if (ptr_opcode != spv::Op::OpTypeInt && ptr_opcode != spv::Op::OpTypeFloat &&
+      ptr_opcode != spv::Op::OpTypeVoid) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Result Type to be OpTypePointer whose Type operand "
               "must be a scalar numerical type or OpTypeVoid";
   }
 
   const auto image_ptr = _.FindDef(_.GetOperandTypeId(inst, 2));
-  if (!image_ptr || image_ptr->opcode() != SpvOpTypePointer) {
+  if (!image_ptr || image_ptr->opcode() != spv::Op::OpTypePointer) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Image to be OpTypePointer";
   }
 
   const auto image_type = image_ptr->GetOperandAs<uint32_t>(2);
-  if (_.GetIdOpcode(image_type) != SpvOpTypeImage) {
+  if (_.GetIdOpcode(image_type) != spv::Op::OpTypeImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Image to be OpTypePointer with Type OpTypeImage";
   }
@@ -1102,7 +1113,7 @@
               "pointed to by Result Type";
   }
 
-  if (info.dim == SpvDimSubpassData) {
+  if (info.dim == spv::Dim::SubpassData) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Image Dim SubpassData cannot be used with OpImageTexelPointer";
   }
@@ -1118,11 +1129,11 @@
     expected_coord_size = GetPlaneCoordSize(info);
   } else if (info.arrayed == 1) {
     switch (info.dim) {
-      case SpvDim1D:
+      case spv::Dim::Dim1D:
         expected_coord_size = 2;
         break;
-      case SpvDimCube:
-      case SpvDim2D:
+      case spv::Dim::Cube:
+      case spv::Dim::Dim2D:
         expected_coord_size = 3;
         break;
       default:
@@ -1157,11 +1168,11 @@
   }
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    if ((info.format != SpvImageFormatR64i) &&
-        (info.format != SpvImageFormatR64ui) &&
-        (info.format != SpvImageFormatR32f) &&
-        (info.format != SpvImageFormatR32i) &&
-        (info.format != SpvImageFormatR32ui)) {
+    if ((info.format != spv::ImageFormat::R64i) &&
+        (info.format != spv::ImageFormat::R64ui) &&
+        (info.format != spv::ImageFormat::R32f) &&
+        (info.format != spv::ImageFormat::R32i) &&
+        (info.format != spv::ImageFormat::R32ui)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << _.VkErrorID(4658)
              << "Expected the Image Format in Image to be R64i, R64ui, R32f, "
@@ -1173,7 +1184,7 @@
 }
 
 spv_result_t ValidateImageLod(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   uint32_t actual_result_type = 0;
   if (spv_result_t error = GetActualResultType(_, inst, &actual_result_type)) {
     return error;
@@ -1193,7 +1204,7 @@
   }
 
   const uint32_t image_type = _.GetOperandTypeId(inst, 2);
-  if (_.GetIdOpcode(image_type) != SpvOpTypeSampledImage) {
+  if (_.GetIdOpcode(image_type) != spv::Op::OpTypeSampledImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Sampled Image to be of type OpTypeSampledImage";
   }
@@ -1216,7 +1227,7 @@
            << "Sampling operation is invalid for multisample image";
   }
 
-  if (_.GetIdOpcode(info.sampled_type) != SpvOpTypeVoid) {
+  if (_.GetIdOpcode(info.sampled_type) != spv::Op::OpTypeVoid) {
     const uint32_t texel_component_type =
         _.GetComponentType(actual_result_type);
     if (texel_component_type != info.sampled_type) {
@@ -1227,9 +1238,9 @@
   }
 
   const uint32_t coord_type = _.GetOperandTypeId(inst, 3);
-  if ((opcode == SpvOpImageSampleExplicitLod ||
-       opcode == SpvOpImageSparseSampleExplicitLod) &&
-      _.HasCapability(SpvCapabilityKernel)) {
+  if ((opcode == spv::Op::OpImageSampleExplicitLod ||
+       opcode == spv::Op::OpImageSparseSampleExplicitLod) &&
+      _.HasCapability(spv::Capability::Kernel)) {
     if (!_.IsFloatScalarOrVectorType(coord_type) &&
         !_.IsIntScalarOrVectorType(coord_type)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -1252,9 +1263,9 @@
 
   const uint32_t mask = inst->words().size() <= 5 ? 0 : inst->word(5);
 
-  if (mask & SpvImageOperandsConstOffsetMask) {
+  if (mask & uint32_t(spv::ImageOperandsMask::ConstOffset)) {
     if (spvIsOpenCLEnv(_.context()->target_env)) {
-      if (opcode == SpvOpImageSampleExplicitLod) {
+      if (opcode == spv::Op::OpImageSampleExplicitLod) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "ConstOffset image operand not allowed "
                << "in the OpenCL environment.";
@@ -1279,7 +1290,7 @@
   }
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    if (info.dim == SpvDim3D) {
+    if (info.dim == spv::Dim::Dim3D) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << _.VkErrorID(4777)
              << "In Vulkan, OpImage*Dref* instructions must not use images "
@@ -1292,7 +1303,7 @@
 
 spv_result_t ValidateImageDrefLod(ValidationState_t& _,
                                   const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   uint32_t actual_result_type = 0;
   if (spv_result_t error = GetActualResultType(_, inst, &actual_result_type)) {
     return error;
@@ -1306,7 +1317,7 @@
   }
 
   const uint32_t image_type = _.GetOperandTypeId(inst, 2);
-  if (_.GetIdOpcode(image_type) != SpvOpTypeSampledImage) {
+  if (_.GetIdOpcode(image_type) != spv::Op::OpTypeSampledImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Sampled Image to be of type OpTypeSampledImage";
   }
@@ -1364,7 +1375,7 @@
     return error;
   }
 
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   if (!_.IsIntVectorType(actual_result_type) &&
       !_.IsFloatVectorType(actual_result_type)) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -1379,7 +1390,7 @@
   }
 
   const uint32_t image_type = _.GetOperandTypeId(inst, 2);
-  if (_.GetIdOpcode(image_type) != SpvOpTypeImage) {
+  if (_.GetIdOpcode(image_type) != spv::Op::OpTypeImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Image to be of type OpTypeImage";
   }
@@ -1390,7 +1401,7 @@
            << "Corrupt image type definition";
   }
 
-  if (_.GetIdOpcode(info.sampled_type) != SpvOpTypeVoid) {
+  if (_.GetIdOpcode(info.sampled_type) != spv::Op::OpTypeVoid) {
     const uint32_t result_component_type =
         _.GetComponentType(actual_result_type);
     if (result_component_type != info.sampled_type) {
@@ -1400,7 +1411,7 @@
     }
   }
 
-  if (info.dim == SpvDimCube) {
+  if (info.dim == spv::Dim::Cube) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Image 'Dim' cannot be Cube";
   }
 
@@ -1436,7 +1447,7 @@
   if (spv_result_t error = GetActualResultType(_, inst, &actual_result_type))
     return error;
 
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   if (!_.IsIntVectorType(actual_result_type) &&
       !_.IsFloatVectorType(actual_result_type)) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -1451,7 +1462,7 @@
   }
 
   const uint32_t image_type = _.GetOperandTypeId(inst, 2);
-  if (_.GetIdOpcode(image_type) != SpvOpTypeSampledImage) {
+  if (_.GetIdOpcode(image_type) != spv::Op::OpTypeSampledImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Sampled Image to be of type OpTypeSampledImage";
   }
@@ -1470,8 +1481,9 @@
            << "Gather operation is invalid for multisample image";
   }
 
-  if (opcode == SpvOpImageDrefGather || opcode == SpvOpImageSparseDrefGather ||
-      _.GetIdOpcode(info.sampled_type) != SpvOpTypeVoid) {
+  if (opcode == spv::Op::OpImageDrefGather ||
+      opcode == spv::Op::OpImageSparseDrefGather ||
+      _.GetIdOpcode(info.sampled_type) != spv::Op::OpTypeVoid) {
     const uint32_t result_component_type =
         _.GetComponentType(actual_result_type);
     if (result_component_type != info.sampled_type) {
@@ -1481,8 +1493,8 @@
     }
   }
 
-  if (info.dim != SpvDim2D && info.dim != SpvDimCube &&
-      info.dim != SpvDimRect) {
+  if (info.dim != spv::Dim::Dim2D && info.dim != spv::Dim::Cube &&
+      info.dim != spv::Dim::Rect) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << _.VkErrorID(4777)
            << "Expected Image 'Dim' to be 2D, Cube, or Rect";
@@ -1502,7 +1514,8 @@
            << " components, but given only " << actual_coord_size;
   }
 
-  if (opcode == SpvOpImageGather || opcode == SpvOpImageSparseGather) {
+  if (opcode == spv::Op::OpImageGather ||
+      opcode == spv::Op::OpImageSparseGather) {
     const uint32_t component = inst->GetOperandAs<uint32_t>(4);
     const uint32_t component_index_type = _.GetTypeId(component);
     if (!_.IsIntScalarType(component_index_type) ||
@@ -1519,8 +1532,8 @@
       }
     }
   } else {
-    assert(opcode == SpvOpImageDrefGather ||
-           opcode == SpvOpImageSparseDrefGather);
+    assert(opcode == spv::Op::OpImageDrefGather ||
+           opcode == spv::Op::OpImageSparseDrefGather);
     if (spv_result_t result = ValidateImageDref(_, inst, info)) return result;
   }
 
@@ -1532,7 +1545,7 @@
 }
 
 spv_result_t ValidateImageRead(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   uint32_t actual_result_type = 0;
   if (spv_result_t error = GetActualResultType(_, inst, &actual_result_type)) {
     return error;
@@ -1557,7 +1570,7 @@
   }  // Check OpenCL below, after we get the image info.
 
   const uint32_t image_type = _.GetOperandTypeId(inst, 2);
-  if (_.GetIdOpcode(image_type) != SpvOpTypeImage) {
+  if (_.GetIdOpcode(image_type) != spv::Op::OpTypeImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Image to be of type OpTypeImage";
   }
@@ -1591,27 +1604,27 @@
     }
 
     const uint32_t mask = inst->words().size() <= 5 ? 0 : inst->word(5);
-    if (mask & SpvImageOperandsConstOffsetMask) {
+    if (mask & uint32_t(spv::ImageOperandsMask::ConstOffset)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "ConstOffset image operand not allowed "
              << "in the OpenCL environment.";
     }
   }
 
-  if (info.dim == SpvDimSubpassData) {
-    if (opcode == SpvOpImageSparseRead) {
+  if (info.dim == spv::Dim::SubpassData) {
+    if (opcode == spv::Op::OpImageSparseRead) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image Dim SubpassData cannot be used with ImageSparseRead";
     }
 
     _.function(inst->function()->id())
         ->RegisterExecutionModelLimitation(
-            SpvExecutionModelFragment,
+            spv::ExecutionModel::Fragment,
             std::string("Dim SubpassData requires Fragment execution model: ") +
                 spvOpcodeString(opcode));
   }
 
-  if (_.GetIdOpcode(info.sampled_type) != SpvOpTypeVoid) {
+  if (_.GetIdOpcode(info.sampled_type) != spv::Op::OpTypeVoid) {
     const uint32_t result_component_type =
         _.GetComponentType(actual_result_type);
     if (result_component_type != info.sampled_type) {
@@ -1639,8 +1652,9 @@
   }
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    if (info.format == SpvImageFormatUnknown && info.dim != SpvDimSubpassData &&
-        !_.HasCapability(SpvCapabilityStorageImageReadWithoutFormat)) {
+    if (info.format == spv::ImageFormat::Unknown &&
+        info.dim != spv::Dim::SubpassData &&
+        !_.HasCapability(spv::Capability::StorageImageReadWithoutFormat)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Capability StorageImageReadWithoutFormat is required to "
              << "read storage image";
@@ -1656,7 +1670,7 @@
 
 spv_result_t ValidateImageWrite(ValidationState_t& _, const Instruction* inst) {
   const uint32_t image_type = _.GetOperandTypeId(inst, 0);
-  if (_.GetIdOpcode(image_type) != SpvOpTypeImage) {
+  if (_.GetIdOpcode(image_type) != spv::Op::OpTypeImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Image to be of type OpTypeImage";
   }
@@ -1667,7 +1681,7 @@
            << "Corrupt image type definition";
   }
 
-  if (info.dim == SpvDimSubpassData) {
+  if (info.dim == spv::Dim::SubpassData) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Image 'Dim' cannot be SubpassData";
   }
@@ -1697,7 +1711,7 @@
            << "Expected Texel to be int or float vector or scalar";
   }
 
-  if (_.GetIdOpcode(info.sampled_type) != SpvOpTypeVoid) {
+  if (_.GetIdOpcode(info.sampled_type) != spv::Op::OpTypeVoid) {
     const uint32_t texel_component_type = _.GetComponentType(texel_type);
     if (texel_component_type != info.sampled_type) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -1707,8 +1721,9 @@
   }
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    if (info.format == SpvImageFormatUnknown && info.dim != SpvDimSubpassData &&
-        !_.HasCapability(SpvCapabilityStorageImageWriteWithoutFormat)) {
+    if (info.format == spv::ImageFormat::Unknown &&
+        info.dim != spv::Dim::SubpassData &&
+        !_.HasCapability(spv::Capability::StorageImageWriteWithoutFormat)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Capability StorageImageWriteWithoutFormat is required to "
                 "write "
@@ -1733,7 +1748,7 @@
 
 spv_result_t ValidateImage(ValidationState_t& _, const Instruction* inst) {
   const uint32_t result_type = inst->type_id();
-  if (_.GetIdOpcode(result_type) != SpvOpTypeImage) {
+  if (_.GetIdOpcode(result_type) != spv::Op::OpTypeImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Result Type to be OpTypeImage";
   }
@@ -1742,7 +1757,7 @@
   const Instruction* sampled_image_type_inst = _.FindDef(sampled_image_type);
   assert(sampled_image_type_inst);
 
-  if (sampled_image_type_inst->opcode() != SpvOpTypeSampledImage) {
+  if (sampled_image_type_inst->opcode() != spv::Op::OpTypeSampledImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Sample Image to be of type OpTypeSampleImage";
   }
@@ -1764,7 +1779,7 @@
   }
 
   const uint32_t image_type = _.GetOperandTypeId(inst, 2);
-  if (_.GetIdOpcode(image_type) != SpvOpTypeImage) {
+  if (_.GetIdOpcode(image_type) != spv::Op::OpTypeImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Image to be of type OpTypeImage";
   }
@@ -1777,14 +1792,14 @@
 
   uint32_t expected_num_components = info.arrayed;
   switch (info.dim) {
-    case SpvDim1D:
+    case spv::Dim::Dim1D:
       expected_num_components += 1;
       break;
-    case SpvDim2D:
-    case SpvDimCube:
+    case spv::Dim::Dim2D:
+    case spv::Dim::Cube:
       expected_num_components += 2;
       break;
-    case SpvDim3D:
+    case spv::Dim::Dim3D:
       expected_num_components += 3;
       break;
     default:
@@ -1830,7 +1845,7 @@
   }
 
   const uint32_t image_type = _.GetOperandTypeId(inst, 2);
-  if (_.GetIdOpcode(image_type) != SpvOpTypeImage) {
+  if (_.GetIdOpcode(image_type) != spv::Op::OpTypeImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Image to be of type OpTypeImage";
   }
@@ -1843,16 +1858,16 @@
 
   uint32_t expected_num_components = info.arrayed;
   switch (info.dim) {
-    case SpvDim1D:
-    case SpvDimBuffer:
+    case spv::Dim::Dim1D:
+    case spv::Dim::Buffer:
       expected_num_components += 1;
       break;
-    case SpvDim2D:
-    case SpvDimCube:
-    case SpvDimRect:
+    case spv::Dim::Dim2D:
+    case spv::Dim::Cube:
+    case spv::Dim::Rect:
       expected_num_components += 2;
       break;
-    case SpvDim3D:
+    case spv::Dim::Dim3D:
       expected_num_components += 3;
       break;
     default:
@@ -1860,8 +1875,8 @@
              << "Image 'Dim' must be 1D, Buffer, 2D, Cube, 3D or Rect";
   }
 
-  if (info.dim == SpvDim1D || info.dim == SpvDim2D || info.dim == SpvDim3D ||
-      info.dim == SpvDimCube) {
+  if (info.dim == spv::Dim::Dim1D || info.dim == spv::Dim::Dim2D ||
+      info.dim == spv::Dim::Dim3D || info.dim == spv::Dim::Cube) {
     if (info.multisampled != 1 && info.sampled != 0 && info.sampled != 2) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image must have either 'MS'=1 or 'Sampled'=0 or 'Sampled'=2";
@@ -1885,7 +1900,7 @@
            << "Expected Result Type to be int scalar type";
   }
 
-  if (_.GetIdOpcode(_.GetOperandTypeId(inst, 2)) != SpvOpTypeImage) {
+  if (_.GetIdOpcode(_.GetOperandTypeId(inst, 2)) != spv::Op::OpTypeImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected operand to be of type OpTypeImage";
   }
@@ -1896,9 +1911,9 @@
                                    const Instruction* inst) {
   _.function(inst->function()->id())
       ->RegisterExecutionModelLimitation(
-          [&](SpvExecutionModel model, std::string* message) {
-            if (model != SpvExecutionModelFragment &&
-                model != SpvExecutionModelGLCompute) {
+          [&](spv::ExecutionModel model, std::string* message) {
+            if (model != spv::ExecutionModel::Fragment &&
+                model != spv::ExecutionModel::GLCompute) {
               if (message) {
                 *message = std::string(
                     "OpImageQueryLod requires Fragment or GLCompute execution "
@@ -1914,10 +1929,10 @@
                               std::string* message) {
         const auto* models = state.GetExecutionModels(entry_point->id());
         const auto* modes = state.GetExecutionModes(entry_point->id());
-        if (models->find(SpvExecutionModelGLCompute) != models->end() &&
-            modes->find(SpvExecutionModeDerivativeGroupLinearNV) ==
+        if (models->find(spv::ExecutionModel::GLCompute) != models->end() &&
+            modes->find(spv::ExecutionMode::DerivativeGroupLinearNV) ==
                 modes->end() &&
-            modes->find(SpvExecutionModeDerivativeGroupQuadsNV) ==
+            modes->find(spv::ExecutionMode::DerivativeGroupQuadsNV) ==
                 modes->end()) {
           if (message) {
             *message = std::string(
@@ -1942,7 +1957,7 @@
   }
 
   const uint32_t image_type = _.GetOperandTypeId(inst, 2);
-  if (_.GetIdOpcode(image_type) != SpvOpTypeSampledImage) {
+  if (_.GetIdOpcode(image_type) != spv::Op::OpTypeSampledImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Image operand to be of type OpTypeSampledImage";
   }
@@ -1953,14 +1968,14 @@
            << "Corrupt image type definition";
   }
 
-  if (info.dim != SpvDim1D && info.dim != SpvDim2D && info.dim != SpvDim3D &&
-      info.dim != SpvDimCube) {
+  if (info.dim != spv::Dim::Dim1D && info.dim != spv::Dim::Dim2D &&
+      info.dim != spv::Dim::Dim3D && info.dim != spv::Dim::Cube) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Image 'Dim' must be 1D, 2D, 3D or Cube";
   }
 
   const uint32_t coord_type = _.GetOperandTypeId(inst, 3);
-  if (_.HasCapability(SpvCapabilityKernel)) {
+  if (_.HasCapability(spv::Capability::Kernel)) {
     if (!_.IsFloatScalarOrVectorType(coord_type) &&
         !_.IsIntScalarOrVectorType(coord_type)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -2005,7 +2020,7 @@
   }
 
   const uint32_t image_type = _.GetOperandTypeId(inst, 2);
-  if (_.GetIdOpcode(image_type) != SpvOpTypeImage) {
+  if (_.GetIdOpcode(image_type) != spv::Op::OpTypeImage) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected Image to be of type OpTypeImage";
   }
@@ -2016,10 +2031,10 @@
            << "Corrupt image type definition";
   }
 
-  const SpvOp opcode = inst->opcode();
-  if (opcode == SpvOpImageQueryLevels) {
-    if (info.dim != SpvDim1D && info.dim != SpvDim2D && info.dim != SpvDim3D &&
-        info.dim != SpvDimCube) {
+  const spv::Op opcode = inst->opcode();
+  if (opcode == spv::Op::OpImageQueryLevels) {
+    if (info.dim != spv::Dim::Dim1D && info.dim != spv::Dim::Dim2D &&
+        info.dim != spv::Dim::Dim3D && info.dim != spv::Dim::Cube) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Image 'Dim' must be 1D, 2D, 3D or Cube";
     }
@@ -2033,8 +2048,8 @@
       }
     }
   } else {
-    assert(opcode == SpvOpImageQuerySamples);
-    if (info.dim != SpvDim2D) {
+    assert(opcode == spv::Op::OpImageQuerySamples);
+    if (info.dim != spv::Dim::Dim2D) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Image 'Dim' must be 2D";
     }
 
@@ -2065,13 +2080,13 @@
 
 // Validates correctness of image instructions.
 spv_result_t ImagePass(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   if (IsImplicitLod(opcode)) {
     _.function(inst->function()->id())
-        ->RegisterExecutionModelLimitation([opcode](SpvExecutionModel model,
+        ->RegisterExecutionModelLimitation([opcode](spv::ExecutionModel model,
                                                     std::string* message) {
-          if (model != SpvExecutionModelFragment &&
-              model != SpvExecutionModelGLCompute) {
+          if (model != spv::ExecutionModel::Fragment &&
+              model != spv::ExecutionModel::GLCompute) {
             if (message) {
               *message =
                   std::string(
@@ -2090,11 +2105,11 @@
           const auto* models = state.GetExecutionModels(entry_point->id());
           const auto* modes = state.GetExecutionModes(entry_point->id());
           if (models &&
-              models->find(SpvExecutionModelGLCompute) != models->end() &&
+              models->find(spv::ExecutionModel::GLCompute) != models->end() &&
               (!modes ||
-               (modes->find(SpvExecutionModeDerivativeGroupLinearNV) ==
+               (modes->find(spv::ExecutionMode::DerivativeGroupLinearNV) ==
                     modes->end() &&
-                modes->find(SpvExecutionModeDerivativeGroupQuadsNV) ==
+                modes->find(spv::ExecutionMode::DerivativeGroupQuadsNV) ==
                     modes->end()))) {
             if (message) {
               *message =
@@ -2111,73 +2126,73 @@
   }
 
   switch (opcode) {
-    case SpvOpTypeImage:
+    case spv::Op::OpTypeImage:
       return ValidateTypeImage(_, inst);
-    case SpvOpTypeSampledImage:
+    case spv::Op::OpTypeSampledImage:
       return ValidateTypeSampledImage(_, inst);
-    case SpvOpSampledImage:
+    case spv::Op::OpSampledImage:
       return ValidateSampledImage(_, inst);
-    case SpvOpImageTexelPointer:
+    case spv::Op::OpImageTexelPointer:
       return ValidateImageTexelPointer(_, inst);
 
-    case SpvOpImageSampleImplicitLod:
-    case SpvOpImageSampleExplicitLod:
-    case SpvOpImageSampleProjImplicitLod:
-    case SpvOpImageSampleProjExplicitLod:
-    case SpvOpImageSparseSampleImplicitLod:
-    case SpvOpImageSparseSampleExplicitLod:
+    case spv::Op::OpImageSampleImplicitLod:
+    case spv::Op::OpImageSampleExplicitLod:
+    case spv::Op::OpImageSampleProjImplicitLod:
+    case spv::Op::OpImageSampleProjExplicitLod:
+    case spv::Op::OpImageSparseSampleImplicitLod:
+    case spv::Op::OpImageSparseSampleExplicitLod:
       return ValidateImageLod(_, inst);
 
-    case SpvOpImageSampleDrefImplicitLod:
-    case SpvOpImageSampleDrefExplicitLod:
-    case SpvOpImageSampleProjDrefImplicitLod:
-    case SpvOpImageSampleProjDrefExplicitLod:
-    case SpvOpImageSparseSampleDrefImplicitLod:
-    case SpvOpImageSparseSampleDrefExplicitLod:
+    case spv::Op::OpImageSampleDrefImplicitLod:
+    case spv::Op::OpImageSampleDrefExplicitLod:
+    case spv::Op::OpImageSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSampleProjDrefExplicitLod:
+    case spv::Op::OpImageSparseSampleDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleDrefExplicitLod:
       return ValidateImageDrefLod(_, inst);
 
-    case SpvOpImageFetch:
-    case SpvOpImageSparseFetch:
+    case spv::Op::OpImageFetch:
+    case spv::Op::OpImageSparseFetch:
       return ValidateImageFetch(_, inst);
 
-    case SpvOpImageGather:
-    case SpvOpImageDrefGather:
-    case SpvOpImageSparseGather:
-    case SpvOpImageSparseDrefGather:
+    case spv::Op::OpImageGather:
+    case spv::Op::OpImageDrefGather:
+    case spv::Op::OpImageSparseGather:
+    case spv::Op::OpImageSparseDrefGather:
       return ValidateImageGather(_, inst);
 
-    case SpvOpImageRead:
-    case SpvOpImageSparseRead:
+    case spv::Op::OpImageRead:
+    case spv::Op::OpImageSparseRead:
       return ValidateImageRead(_, inst);
 
-    case SpvOpImageWrite:
+    case spv::Op::OpImageWrite:
       return ValidateImageWrite(_, inst);
 
-    case SpvOpImage:
+    case spv::Op::OpImage:
       return ValidateImage(_, inst);
 
-    case SpvOpImageQueryFormat:
-    case SpvOpImageQueryOrder:
+    case spv::Op::OpImageQueryFormat:
+    case spv::Op::OpImageQueryOrder:
       return ValidateImageQueryFormatOrOrder(_, inst);
 
-    case SpvOpImageQuerySizeLod:
+    case spv::Op::OpImageQuerySizeLod:
       return ValidateImageQuerySizeLod(_, inst);
-    case SpvOpImageQuerySize:
+    case spv::Op::OpImageQuerySize:
       return ValidateImageQuerySize(_, inst);
-    case SpvOpImageQueryLod:
+    case spv::Op::OpImageQueryLod:
       return ValidateImageQueryLod(_, inst);
 
-    case SpvOpImageQueryLevels:
-    case SpvOpImageQuerySamples:
+    case spv::Op::OpImageQueryLevels:
+    case spv::Op::OpImageQuerySamples:
       return ValidateImageQueryLevelsOrSamples(_, inst);
 
-    case SpvOpImageSparseSampleProjImplicitLod:
-    case SpvOpImageSparseSampleProjExplicitLod:
-    case SpvOpImageSparseSampleProjDrefImplicitLod:
-    case SpvOpImageSparseSampleProjDrefExplicitLod:
+    case spv::Op::OpImageSparseSampleProjImplicitLod:
+    case spv::Op::OpImageSparseSampleProjExplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefExplicitLod:
       return ValidateImageSparseLod(_, inst);
 
-    case SpvOpImageSparseTexelsResident:
+    case spv::Op::OpImageSparseTexelsResident:
       return ValidateImageSparseTexelsResident(_, inst);
 
     default:
diff --git a/source/val/validate_instruction.cpp b/source/val/validate_instruction.cpp
index 767c0ce..1b7847c 100644
--- a/source/val/validate_instruction.cpp
+++ b/source/val/validate_instruction.cpp
@@ -44,13 +44,13 @@
 std::string ToString(const CapabilitySet& capabilities,
                      const AssemblyGrammar& grammar) {
   std::stringstream ss;
-  capabilities.ForEach([&grammar, &ss](SpvCapability cap) {
+  capabilities.ForEach([&grammar, &ss](spv::Capability cap) {
     spv_operand_desc desc;
-    if (SPV_SUCCESS ==
-        grammar.lookupOperand(SPV_OPERAND_TYPE_CAPABILITY, cap, &desc))
+    if (SPV_SUCCESS == grammar.lookupOperand(SPV_OPERAND_TYPE_CAPABILITY,
+                                             uint32_t(cap), &desc))
       ss << desc->name << " ";
     else
-      ss << cap << " ";
+      ss << uint32_t(cap) << " ";
   });
   return ss.str();
 }
@@ -60,18 +60,18 @@
 // the opcode may only be used if at least one of the capabilities is specified
 // by the module.
 CapabilitySet EnablingCapabilitiesForOp(const ValidationState_t& state,
-                                        SpvOp opcode) {
+                                        spv::Op opcode) {
   // Exceptions for SPV_AMD_shader_ballot
   switch (opcode) {
     // Normally these would require Group capability
-    case SpvOpGroupIAddNonUniformAMD:
-    case SpvOpGroupFAddNonUniformAMD:
-    case SpvOpGroupFMinNonUniformAMD:
-    case SpvOpGroupUMinNonUniformAMD:
-    case SpvOpGroupSMinNonUniformAMD:
-    case SpvOpGroupFMaxNonUniformAMD:
-    case SpvOpGroupUMaxNonUniformAMD:
-    case SpvOpGroupSMaxNonUniformAMD:
+    case spv::Op::OpGroupIAddNonUniformAMD:
+    case spv::Op::OpGroupFAddNonUniformAMD:
+    case spv::Op::OpGroupFMinNonUniformAMD:
+    case spv::Op::OpGroupUMinNonUniformAMD:
+    case spv::Op::OpGroupSMinNonUniformAMD:
+    case spv::Op::OpGroupFMaxNonUniformAMD:
+    case spv::Op::OpGroupUMaxNonUniformAMD:
+    case spv::Op::OpGroupSMaxNonUniformAMD:
       if (state.HasExtension(kSPV_AMD_shader_ballot)) return CapabilitySet();
       break;
     default:
@@ -151,10 +151,10 @@
   // not implemented yet.  This rule is independent of target environment.
   // See https://github.com/KhronosGroup/SPIRV-Tools/issues/365
   if (operand.type == SPV_OPERAND_TYPE_BUILT_IN) {
-    switch (word) {
-      case SpvBuiltInPointSize:
-      case SpvBuiltInClipDistance:
-      case SpvBuiltInCullDistance:
+    switch (spv::BuiltIn(word)) {
+      case spv::BuiltIn::PointSize:
+      case spv::BuiltIn::ClipDistance:
+      case spv::BuiltIn::CullDistance:
         return SPV_SUCCESS;
       default:
         break;
@@ -166,7 +166,7 @@
     }
   } else if (operand.type == SPV_OPERAND_TYPE_GROUP_OPERATION &&
              state.features().group_ops_reduce_and_scans &&
-             (word <= uint32_t(SpvGroupOperationExclusiveScan))) {
+             (word <= uint32_t(spv::GroupOperation::ExclusiveScan))) {
     // Allow certain group operations if requested.
     return SPV_SUCCESS;
   }
@@ -178,15 +178,16 @@
   if (lookup_result == SPV_SUCCESS) {
     // Allow FPRoundingMode decoration if requested.
     if (operand.type == SPV_OPERAND_TYPE_DECORATION &&
-        operand_desc->value == SpvDecorationFPRoundingMode) {
+        spv::Decoration(operand_desc->value) ==
+            spv::Decoration::FPRoundingMode) {
       if (state.features().free_fp_rounding_mode) return SPV_SUCCESS;
 
       // Vulkan API requires more capabilities on rounding mode.
       if (spvIsVulkanEnv(state.context()->target_env)) {
-        enabling_capabilities.Add(SpvCapabilityStorageUniformBufferBlock16);
-        enabling_capabilities.Add(SpvCapabilityStorageUniform16);
-        enabling_capabilities.Add(SpvCapabilityStoragePushConstant16);
-        enabling_capabilities.Add(SpvCapabilityStorageInputOutput16);
+        enabling_capabilities.Add(spv::Capability::StorageUniformBufferBlock16);
+        enabling_capabilities.Add(spv::Capability::StorageUniform16);
+        enabling_capabilities.Add(spv::Capability::StoragePushConstant16);
+        enabling_capabilities.Add(spv::Capability::StorageInputOutput16);
       }
     } else {
       enabling_capabilities = state.grammar().filterCapsAgainstTargetEnv(
@@ -197,7 +198,7 @@
     // registers a capability with the module *before* checking capabilities.
     // So in the case of an OpCapability instruction, don't bother checking
     // enablement by another capability.
-    if (inst->opcode() != SpvOpCapability) {
+    if (inst->opcode() != spv::Op::OpCapability) {
       const bool enabled_by_cap =
           state.HasAnyOfCapabilities(enabling_capabilities);
       if (!enabling_capabilities.IsEmpty() && !enabled_by_cap) {
@@ -218,14 +219,14 @@
 // is explicitly reserved in the SPIR-V core spec.  Otherwise return
 // SPV_SUCCESS.
 spv_result_t ReservedCheck(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   switch (opcode) {
     // These instructions are enabled by a capability, but should never
     // be used anyway.
-    case SpvOpImageSparseSampleProjImplicitLod:
-    case SpvOpImageSparseSampleProjExplicitLod:
-    case SpvOpImageSparseSampleProjDrefImplicitLod:
-    case SpvOpImageSparseSampleProjDrefExplicitLod: {
+    case spv::Op::OpImageSparseSampleProjImplicitLod:
+    case spv::Op::OpImageSparseSampleProjExplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefImplicitLod:
+    case spv::Op::OpImageSparseSampleProjDrefExplicitLod: {
       spv_opcode_desc inst_desc;
       _.grammar().lookupOpcode(opcode, &inst_desc);
       return _.diag(SPV_ERROR_INVALID_BINARY, inst)
@@ -241,7 +242,7 @@
 // instruction is invalid because the required capability isn't declared
 // in the module.
 spv_result_t CapabilityCheck(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   CapabilitySet opcode_caps = EnablingCapabilitiesForOp(_, opcode);
   if (!_.HasAnyOfCapabilities(opcode_caps)) {
     return _.diag(SPV_ERROR_INVALID_CAPABILITY, inst)
@@ -299,7 +300,7 @@
   // OpTerminateInvocation is special because it is enabled by Shader
   // capability, but also requires an extension and/or version check.
   const bool capability_check_is_sufficient =
-      inst->opcode() != SpvOpTerminateInvocation;
+      inst->opcode() != spv::Op::OpTerminateInvocation;
 
   if (capability_check_is_sufficient && (inst_desc->numCapabilities > 0u)) {
     // We already checked that the direct capability dependency has been
@@ -357,7 +358,7 @@
 
 // Checks that the number of OpTypeStruct members is within the limit.
 spv_result_t LimitCheckStruct(ValidationState_t& _, const Instruction* inst) {
-  if (SpvOpTypeStruct != inst->opcode()) {
+  if (spv::Op::OpTypeStruct != inst->opcode()) {
     return SPV_SUCCESS;
   }
 
@@ -382,7 +383,7 @@
   for (size_t word_i = 2; word_i < inst->words().size(); ++word_i) {
     auto member = inst->word(word_i);
     auto memberTypeInstr = _.FindDef(member);
-    if (memberTypeInstr && SpvOpTypeStruct == memberTypeInstr->opcode()) {
+    if (memberTypeInstr && spv::Op::OpTypeStruct == memberTypeInstr->opcode()) {
       max_member_depth = std::max(
           max_member_depth, _.struct_nesting_depth(memberTypeInstr->id()));
     }
@@ -402,7 +403,7 @@
 // Checks that the number of (literal, label) pairs in OpSwitch is within
 // the limit.
 spv_result_t LimitCheckSwitch(ValidationState_t& _, const Instruction* inst) {
-  if (SpvOpSwitch == inst->opcode()) {
+  if (spv::Op::OpSwitch == inst->opcode()) {
     // The instruction syntax is as follows:
     // OpSwitch <selector ID> <Default ID> literal label literal label ...
     // literal,label pairs come after the first 2 operands.
@@ -422,8 +423,8 @@
 // Ensure the number of variables of the given class does not exceed the
 // limit.
 spv_result_t LimitCheckNumVars(ValidationState_t& _, const uint32_t var_id,
-                               const SpvStorageClass storage_class) {
-  if (SpvStorageClassFunction == storage_class) {
+                               const spv::StorageClass storage_class) {
+  if (spv::StorageClass::Function == storage_class) {
     _.registerLocalVariable(var_id);
     const uint32_t num_local_vars_limit =
         _.options()->universal_limits_.max_local_variables;
@@ -462,29 +463,29 @@
 }  // namespace
 
 spv_result_t InstructionPass(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
-  if (opcode == SpvOpExtension) {
+  const spv::Op opcode = inst->opcode();
+  if (opcode == spv::Op::OpExtension) {
     CheckIfKnownExtension(_, inst);
-  } else if (opcode == SpvOpCapability) {
-    _.RegisterCapability(inst->GetOperandAs<SpvCapability>(0));
-  } else if (opcode == SpvOpMemoryModel) {
+  } else if (opcode == spv::Op::OpCapability) {
+    _.RegisterCapability(inst->GetOperandAs<spv::Capability>(0));
+  } else if (opcode == spv::Op::OpMemoryModel) {
     if (_.has_memory_model_specified()) {
       return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
              << "OpMemoryModel should only be provided once.";
     }
-    _.set_addressing_model(inst->GetOperandAs<SpvAddressingModel>(0));
-    _.set_memory_model(inst->GetOperandAs<SpvMemoryModel>(1));
-  } else if (opcode == SpvOpExecutionMode) {
+    _.set_addressing_model(inst->GetOperandAs<spv::AddressingModel>(0));
+    _.set_memory_model(inst->GetOperandAs<spv::MemoryModel>(1));
+  } else if (opcode == spv::Op::OpExecutionMode) {
     const uint32_t entry_point = inst->word(1);
     _.RegisterExecutionModeForEntryPoint(entry_point,
-                                         SpvExecutionMode(inst->word(2)));
-  } else if (opcode == SpvOpVariable) {
-    const auto storage_class = inst->GetOperandAs<SpvStorageClass>(2);
+                                         spv::ExecutionMode(inst->word(2)));
+  } else if (opcode == spv::Op::OpVariable) {
+    const auto storage_class = inst->GetOperandAs<spv::StorageClass>(2);
     if (auto error = LimitCheckNumVars(_, inst->id(), storage_class)) {
       return error;
     }
-  } else if (opcode == SpvOpSamplerImageAddressingModeNV) {
-    if (!_.HasCapability(SpvCapabilityBindlessTextureNV)) {
+  } else if (opcode == spv::Op::OpSamplerImageAddressingModeNV) {
+    if (!_.HasCapability(spv::Capability::BindlessTextureNV)) {
       return _.diag(SPV_ERROR_MISSING_EXTENSION, inst)
              << "OpSamplerImageAddressingModeNV supported only with extension "
                 "SPV_NV_bindless_texture";
diff --git a/source/val/validate_interfaces.cpp b/source/val/validate_interfaces.cpp
index 7f2d648..00a5999 100644
--- a/source/val/validate_interfaces.cpp
+++ b/source/val/validate_interfaces.cpp
@@ -35,12 +35,15 @@
 bool is_interface_variable(const Instruction* inst, bool is_spv_1_4) {
   if (is_spv_1_4) {
     // Starting in SPIR-V 1.4, all global variables are interface variables.
-    return inst->opcode() == SpvOpVariable &&
-           inst->word(3u) != SpvStorageClassFunction;
+    return inst->opcode() == spv::Op::OpVariable &&
+           inst->GetOperandAs<spv::StorageClass>(2u) !=
+               spv::StorageClass::Function;
   } else {
-    return inst->opcode() == SpvOpVariable &&
-           (inst->word(3u) == SpvStorageClassInput ||
-            inst->word(3u) == SpvStorageClassOutput);
+    return inst->opcode() == spv::Op::OpVariable &&
+           (inst->GetOperandAs<spv::StorageClass>(2u) ==
+                spv::StorageClass::Input ||
+            inst->GetOperandAs<spv::StorageClass>(2u) ==
+                spv::StorageClass::Output);
   }
 }
 
@@ -114,29 +117,30 @@
                                   uint32_t* num_locations) {
   *num_locations = 0;
   switch (type->opcode()) {
-    case SpvOpTypeInt:
-    case SpvOpTypeFloat:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeFloat:
       // Scalars always consume a single location.
       *num_locations = 1;
       break;
-    case SpvOpTypeVector:
+    case spv::Op::OpTypeVector:
       // 3- and 4-component 64-bit vectors consume two locations.
-      if ((_.ContainsSizedIntOrFloatType(type->id(), SpvOpTypeInt, 64) ||
-           _.ContainsSizedIntOrFloatType(type->id(), SpvOpTypeFloat, 64)) &&
+      if ((_.ContainsSizedIntOrFloatType(type->id(), spv::Op::OpTypeInt, 64) ||
+           _.ContainsSizedIntOrFloatType(type->id(), spv::Op::OpTypeFloat,
+                                         64)) &&
           (type->GetOperandAs<uint32_t>(2) > 2)) {
         *num_locations = 2;
       } else {
         *num_locations = 1;
       }
       break;
-    case SpvOpTypeMatrix:
+    case spv::Op::OpTypeMatrix:
       // Matrices consume locations equal to the underlying vector type for
       // each column.
       NumConsumedLocations(_, _.FindDef(type->GetOperandAs<uint32_t>(1)),
                            num_locations);
       *num_locations *= type->GetOperandAs<uint32_t>(2);
       break;
-    case SpvOpTypeArray: {
+    case spv::Op::OpTypeArray: {
       // Arrays consume locations equal to the underlying type times the number
       // of elements in the vector.
       NumConsumedLocations(_, _.FindDef(type->GetOperandAs<uint32_t>(1)),
@@ -150,9 +154,9 @@
       if (is_int && is_const) *num_locations *= value;
       break;
     }
-    case SpvOpTypeStruct: {
+    case spv::Op::OpTypeStruct: {
       // Members cannot have location decorations at this point.
-      if (_.HasDecoration(type->id(), SpvDecorationLocation)) {
+      if (_.HasDecoration(type->id(), spv::Decoration::Location)) {
         return _.diag(SPV_ERROR_INVALID_DATA, type)
                << _.VkErrorID(4918) << "Members cannot be assigned a location";
       }
@@ -182,8 +186,8 @@
 uint32_t NumConsumedComponents(ValidationState_t& _, const Instruction* type) {
   uint32_t num_components = 0;
   switch (type->opcode()) {
-    case SpvOpTypeInt:
-    case SpvOpTypeFloat:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeFloat:
       // 64-bit types consume two components.
       if (type->GetOperandAs<uint32_t>(1) == 64) {
         num_components = 2;
@@ -191,7 +195,7 @@
         num_components = 1;
       }
       break;
-    case SpvOpTypeVector:
+    case spv::Op::OpTypeVector:
       // Vectors consume components equal to the underlying type's consumption
       // times the number of elements in the vector. Note that 3- and 4-element
       // vectors cannot have a component decoration (i.e. assumed to be zero).
@@ -199,7 +203,7 @@
           NumConsumedComponents(_, _.FindDef(type->GetOperandAs<uint32_t>(1)));
       num_components *= type->GetOperandAs<uint32_t>(2);
       break;
-    case SpvOpTypeArray:
+    case spv::Op::OpTypeArray:
       // Skip the array.
       return NumConsumedComponents(_,
                                    _.FindDef(type->GetOperandAs<uint32_t>(1)));
@@ -218,10 +222,10 @@
     ValidationState_t& _, const Instruction* entry_point,
     const Instruction* variable, std::unordered_set<uint32_t>* locations,
     std::unordered_set<uint32_t>* output_index1_locations) {
-  const bool is_fragment = entry_point->GetOperandAs<SpvExecutionModel>(0) ==
-                           SpvExecutionModelFragment;
+  const bool is_fragment = entry_point->GetOperandAs<spv::ExecutionModel>(0) ==
+                           spv::ExecutionModel::Fragment;
   const bool is_output =
-      variable->GetOperandAs<SpvStorageClass>(2) == SpvStorageClassOutput;
+      variable->GetOperandAs<spv::StorageClass>(2) == spv::StorageClass::Output;
   auto ptr_type_id = variable->GetOperandAs<uint32_t>(0);
   auto ptr_type = _.FindDef(ptr_type_id);
   auto type_id = ptr_type->GetOperandAs<uint32_t>(2);
@@ -240,21 +244,21 @@
   bool has_per_task_nv = false;
   bool has_per_vertex_khr = false;
   for (auto& dec : _.id_decorations(variable->id())) {
-    if (dec.dec_type() == SpvDecorationLocation) {
+    if (dec.dec_type() == spv::Decoration::Location) {
       if (has_location && dec.params()[0] != location) {
         return _.diag(SPV_ERROR_INVALID_DATA, variable)
                << "Variable has conflicting location decorations";
       }
       has_location = true;
       location = dec.params()[0];
-    } else if (dec.dec_type() == SpvDecorationComponent) {
+    } else if (dec.dec_type() == spv::Decoration::Component) {
       if (has_component && dec.params()[0] != component) {
         return _.diag(SPV_ERROR_INVALID_DATA, variable)
                << "Variable has conflicting component decorations";
       }
       has_component = true;
       component = dec.params()[0];
-    } else if (dec.dec_type() == SpvDecorationIndex) {
+    } else if (dec.dec_type() == spv::Decoration::Index) {
       if (!is_output || !is_fragment) {
         return _.diag(SPV_ERROR_INVALID_DATA, variable)
                << "Index can only be applied to Fragment output variables";
@@ -265,22 +269,22 @@
       }
       has_index = true;
       index = dec.params()[0];
-    } else if (dec.dec_type() == SpvDecorationBuiltIn) {
+    } else if (dec.dec_type() == spv::Decoration::BuiltIn) {
       // Don't check built-ins.
       return SPV_SUCCESS;
-    } else if (dec.dec_type() == SpvDecorationPatch) {
+    } else if (dec.dec_type() == spv::Decoration::Patch) {
       has_patch = true;
-    } else if (dec.dec_type() == SpvDecorationPerTaskNV) {
+    } else if (dec.dec_type() == spv::Decoration::PerTaskNV) {
       has_per_task_nv = true;
-    } else if (dec.dec_type() == SpvDecorationPerVertexKHR) {
+    } else if (dec.dec_type() == spv::Decoration::PerVertexKHR) {
       if (!is_fragment) {
         return _.diag(SPV_ERROR_INVALID_DATA, variable)
                << _.VkErrorID(6777)
                << "PerVertexKHR can only be applied to Fragment Execution "
                   "Models";
       }
-      if (type->opcode() != SpvOpTypeArray &&
-          type->opcode() != SpvOpTypeRuntimeArray) {
+      if (type->opcode() != spv::Op::OpTypeArray &&
+          type->opcode() != spv::Op::OpTypeRuntimeArray) {
         return _.diag(SPV_ERROR_INVALID_DATA, variable)
                << _.VkErrorID(6778)
                << "PerVertexKHR must be declared as arrays";
@@ -293,28 +297,28 @@
   // tessellation control, evaluation and geometry per-vertex inputs have a
   // layer of arraying that is not included in interface matching.
   bool is_arrayed = false;
-  switch (entry_point->GetOperandAs<SpvExecutionModel>(0)) {
-    case SpvExecutionModelTessellationControl:
+  switch (entry_point->GetOperandAs<spv::ExecutionModel>(0)) {
+    case spv::ExecutionModel::TessellationControl:
       if (!has_patch) {
         is_arrayed = true;
       }
       break;
-    case SpvExecutionModelTessellationEvaluation:
+    case spv::ExecutionModel::TessellationEvaluation:
       if (!is_output && !has_patch) {
         is_arrayed = true;
       }
       break;
-    case SpvExecutionModelGeometry:
+    case spv::ExecutionModel::Geometry:
       if (!is_output) {
         is_arrayed = true;
       }
       break;
-    case SpvExecutionModelFragment:
+    case spv::ExecutionModel::Fragment:
       if (!is_output && has_per_vertex_khr) {
         is_arrayed = true;
       }
       break;
-    case SpvExecutionModelMeshNV:
+    case spv::ExecutionModel::MeshNV:
       if (is_output && !has_per_task_nv) {
         is_arrayed = true;
       }
@@ -324,21 +328,21 @@
   }
 
   // Unpack arrayness.
-  if (is_arrayed && (type->opcode() == SpvOpTypeArray ||
-                     type->opcode() == SpvOpTypeRuntimeArray)) {
+  if (is_arrayed && (type->opcode() == spv::Op::OpTypeArray ||
+                     type->opcode() == spv::Op::OpTypeRuntimeArray)) {
     type_id = type->GetOperandAs<uint32_t>(1);
     type = _.FindDef(type_id);
   }
 
-  if (type->opcode() == SpvOpTypeStruct) {
+  if (type->opcode() == spv::Op::OpTypeStruct) {
     // Don't check built-ins.
-    if (_.HasDecoration(type_id, SpvDecorationBuiltIn)) return SPV_SUCCESS;
+    if (_.HasDecoration(type_id, spv::Decoration::BuiltIn)) return SPV_SUCCESS;
   }
 
   // Only block-decorated structs don't need a location on the variable.
-  const bool is_block = _.HasDecoration(type_id, SpvDecorationBlock);
+  const bool is_block = _.HasDecoration(type_id, spv::Decoration::Block);
   if (!has_location && !is_block) {
-    const auto vuid = (type->opcode() == SpvOpTypeStruct) ? 4917 : 4916;
+    const auto vuid = (type->opcode() == spv::Op::OpTypeStruct) ? 4917 : 4916;
     return _.diag(SPV_ERROR_INVALID_DATA, variable)
            << _.VkErrorID(vuid) << "Variable must be decorated with a location";
   }
@@ -351,7 +355,7 @@
     uint32_t array_size = 1;
     // If the variable is still arrayed, mark the locations/components per
     // index.
-    if (type->opcode() == SpvOpTypeArray) {
+    if (type->opcode() == spv::Op::OpTypeArray) {
       // Determine the array size if possible and get the element type.
       std::tie(is_int, is_const, array_size) =
           _.EvalInt32IfConst(type->GetOperandAs<uint32_t>(2));
@@ -399,7 +403,7 @@
     std::unordered_map<uint32_t, uint32_t> member_locations;
     std::unordered_map<uint32_t, uint32_t> member_components;
     for (auto& dec : _.id_decorations(type_id)) {
-      if (dec.dec_type() == SpvDecorationLocation) {
+      if (dec.dec_type() == spv::Decoration::Location) {
         auto where = member_locations.find(dec.struct_member_index());
         if (where == member_locations.end()) {
           member_locations[dec.struct_member_index()] = dec.params()[0];
@@ -408,7 +412,7 @@
                  << "Member index " << dec.struct_member_index()
                  << " has conflicting location assignments";
         }
-      } else if (dec.dec_type() == SpvDecorationComponent) {
+      } else if (dec.dec_type() == spv::Decoration::Component) {
         auto where = member_components.find(dec.struct_member_index());
         if (where == member_components.end()) {
           member_components[dec.struct_member_index()] = dec.params()[0];
@@ -447,7 +451,7 @@
         continue;
       }
 
-      if (member->opcode() == SpvOpTypeArray && num_components >= 1 &&
+      if (member->opcode() == spv::Op::OpTypeArray && num_components >= 1 &&
           num_components < 4) {
         // When an array has an element that takes less than a location in
         // size, calculate the used locations in a strided manner.
@@ -492,12 +496,12 @@
   // TODO(dneto): SPV_NV_ray_tracing also uses locations on interface variables,
   // in other shader stages. Similarly, the *provisional* version of
   // SPV_KHR_ray_tracing did as well, but not the final version.
-  switch (entry_point->GetOperandAs<SpvExecutionModel>(0)) {
-    case SpvExecutionModelVertex:
-    case SpvExecutionModelTessellationControl:
-    case SpvExecutionModelTessellationEvaluation:
-    case SpvExecutionModelGeometry:
-    case SpvExecutionModelFragment:
+  switch (entry_point->GetOperandAs<spv::ExecutionModel>(0)) {
+    case spv::ExecutionModel::Vertex:
+    case spv::ExecutionModel::TessellationControl:
+    case spv::ExecutionModel::TessellationEvaluation:
+    case spv::ExecutionModel::Geometry:
+    case spv::ExecutionModel::Fragment:
       break;
     default:
       return SPV_SUCCESS;
@@ -511,9 +515,9 @@
   for (uint32_t i = 3; i < entry_point->operands().size(); ++i) {
     auto interface_id = entry_point->GetOperandAs<uint32_t>(i);
     auto interface_var = _.FindDef(interface_id);
-    auto storage_class = interface_var->GetOperandAs<SpvStorageClass>(2);
-    if (storage_class != SpvStorageClassInput &&
-        storage_class != SpvStorageClassOutput) {
+    auto storage_class = interface_var->GetOperandAs<spv::StorageClass>(2);
+    if (storage_class != spv::StorageClass::Input &&
+        storage_class != spv::StorageClass::Output) {
       continue;
     }
     if (!seen.insert(interface_id).second) {
@@ -522,7 +526,7 @@
       continue;
     }
 
-    auto locations = (storage_class == SpvStorageClassInput)
+    auto locations = (storage_class == spv::StorageClass::Input)
                          ? &input_locations
                          : &output_locations_index0;
     if (auto error = GetLocationsForVariable(
@@ -547,12 +551,12 @@
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
     for (auto& inst : _.ordered_instructions()) {
-      if (inst.opcode() == SpvOpEntryPoint) {
+      if (inst.opcode() == spv::Op::OpEntryPoint) {
         if (auto error = ValidateLocations(_, &inst)) {
           return error;
         }
       }
-      if (inst.opcode() == SpvOpTypeVoid) break;
+      if (inst.opcode() == spv::Op::OpTypeVoid) break;
     }
   }
 
diff --git a/source/val/validate_layout.cpp b/source/val/validate_layout.cpp
index 6f95135..238dd9b 100644
--- a/source/val/validate_layout.cpp
+++ b/source/val/validate_layout.cpp
@@ -35,9 +35,9 @@
 // is part of the current layout section. If it is not then the next sections is
 // checked.
 spv_result_t ModuleScopedInstructions(ValidationState_t& _,
-                                      const Instruction* inst, SpvOp opcode) {
+                                      const Instruction* inst, spv::Op opcode) {
   switch (opcode) {
-    case SpvOpExtInst:
+    case spv::Op::OpExtInst:
       if (spvExtInstIsDebugInfo(inst->ext_inst_type())) {
         const uint32_t ext_inst_index = inst->word(4);
         bool local_debug_info = false;
@@ -131,7 +131,7 @@
 
     switch (_.current_layout_section()) {
       case kLayoutMemoryModel:
-        if (opcode != SpvOpMemoryModel) {
+        if (opcode != spv::Op::OpMemoryModel) {
           return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
                  << spvOpcodeString(opcode)
                  << " cannot appear before the memory model instruction";
@@ -154,7 +154,8 @@
 // inside of another function. This stage ends when the first label is
 // encountered inside of a function.
 spv_result_t FunctionScopedInstructions(ValidationState_t& _,
-                                        const Instruction* inst, SpvOp opcode) {
+                                        const Instruction* inst,
+                                        spv::Op opcode) {
   // Make sure we advance into the function definitions when we hit
   // non-function declaration instructions.
   if (_.current_layout_section() == kLayoutFunctionDeclarations &&
@@ -171,12 +172,12 @@
 
   if (_.IsOpcodeInCurrentLayoutSection(opcode)) {
     switch (opcode) {
-      case SpvOpFunction: {
+      case spv::Op::OpFunction: {
         if (_.in_function_body()) {
           return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
                  << "Cannot declare a function in a function body";
         }
-        auto control_mask = inst->GetOperandAs<SpvFunctionControlMask>(2);
+        auto control_mask = inst->GetOperandAs<spv::FunctionControlMask>(2);
         if (auto error =
                 _.RegisterFunction(inst->id(), inst->type_id(), control_mask,
                                    inst->GetOperandAs<uint32_t>(3)))
@@ -188,7 +189,7 @@
         }
       } break;
 
-      case SpvOpFunctionParameter:
+      case spv::Op::OpFunctionParameter:
         if (_.in_function_body() == false) {
           return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
                  << "Function parameter instructions must be in a "
@@ -204,7 +205,7 @@
           return error;
         break;
 
-      case SpvOpFunctionEnd:
+      case spv::Op::OpFunctionEnd:
         if (_.in_function_body() == false) {
           return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
                  << "Function end instructions must be in a function body";
@@ -227,10 +228,10 @@
         if (auto error = _.RegisterFunctionEnd()) return error;
         break;
 
-      case SpvOpLine:
-      case SpvOpNoLine:
+      case spv::Op::OpLine:
+      case spv::Op::OpNoLine:
         break;
-      case SpvOpLabel:
+      case spv::Op::OpLabel:
         // If the label is encountered then the current function is a
         // definition so set the function to a declaration and update the
         // module section
@@ -244,7 +245,7 @@
         }
         break;
 
-      case SpvOpExtInst:
+      case spv::Op::OpExtInst:
         if (spvExtInstIsDebugInfo(inst->ext_inst_type())) {
           const uint32_t ext_inst_index = inst->word(4);
           bool local_debug_info = false;
@@ -356,7 +357,7 @@
 // NOTE: This function does not handle CFG related validation
 // Performs logical layout validation. See Section 2.4
 spv_result_t ModuleLayoutPass(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
 
   switch (_.current_layout_section()) {
     case kLayoutCapabilities:
diff --git a/source/val/validate_logicals.cpp b/source/val/validate_logicals.cpp
index ec1e207..dd66ce9 100644
--- a/source/val/validate_logicals.cpp
+++ b/source/val/validate_logicals.cpp
@@ -26,12 +26,12 @@
 
 // Validates correctness of logical instructions.
 spv_result_t LogicalsPass(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   const uint32_t result_type = inst->type_id();
 
   switch (opcode) {
-    case SpvOpAny:
-    case SpvOpAll: {
+    case spv::Op::OpAny:
+    case spv::Op::OpAll: {
       if (!_.IsBoolScalarType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected bool scalar type as Result Type: "
@@ -46,11 +46,11 @@
       break;
     }
 
-    case SpvOpIsNan:
-    case SpvOpIsInf:
-    case SpvOpIsFinite:
-    case SpvOpIsNormal:
-    case SpvOpSignBitSet: {
+    case spv::Op::OpIsNan:
+    case spv::Op::OpIsInf:
+    case spv::Op::OpIsFinite:
+    case spv::Op::OpIsNormal:
+    case spv::Op::OpSignBitSet: {
       if (!_.IsBoolScalarType(result_type) && !_.IsBoolVectorType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected bool scalar or vector type as Result Type: "
@@ -72,21 +72,21 @@
       break;
     }
 
-    case SpvOpFOrdEqual:
-    case SpvOpFUnordEqual:
-    case SpvOpFOrdNotEqual:
-    case SpvOpFUnordNotEqual:
-    case SpvOpFOrdLessThan:
-    case SpvOpFUnordLessThan:
-    case SpvOpFOrdGreaterThan:
-    case SpvOpFUnordGreaterThan:
-    case SpvOpFOrdLessThanEqual:
-    case SpvOpFUnordLessThanEqual:
-    case SpvOpFOrdGreaterThanEqual:
-    case SpvOpFUnordGreaterThanEqual:
-    case SpvOpLessOrGreater:
-    case SpvOpOrdered:
-    case SpvOpUnordered: {
+    case spv::Op::OpFOrdEqual:
+    case spv::Op::OpFUnordEqual:
+    case spv::Op::OpFOrdNotEqual:
+    case spv::Op::OpFUnordNotEqual:
+    case spv::Op::OpFOrdLessThan:
+    case spv::Op::OpFUnordLessThan:
+    case spv::Op::OpFOrdGreaterThan:
+    case spv::Op::OpFUnordGreaterThan:
+    case spv::Op::OpFOrdLessThanEqual:
+    case spv::Op::OpFUnordLessThanEqual:
+    case spv::Op::OpFOrdGreaterThanEqual:
+    case spv::Op::OpFUnordGreaterThanEqual:
+    case spv::Op::OpLessOrGreater:
+    case spv::Op::OpOrdered:
+    case spv::Op::OpUnordered: {
       if (!_.IsBoolScalarType(result_type) && !_.IsBoolVectorType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected bool scalar or vector type as Result Type: "
@@ -113,10 +113,10 @@
       break;
     }
 
-    case SpvOpLogicalEqual:
-    case SpvOpLogicalNotEqual:
-    case SpvOpLogicalOr:
-    case SpvOpLogicalAnd: {
+    case spv::Op::OpLogicalEqual:
+    case spv::Op::OpLogicalNotEqual:
+    case spv::Op::OpLogicalOr:
+    case spv::Op::OpLogicalAnd: {
       if (!_.IsBoolScalarType(result_type) && !_.IsBoolVectorType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected bool scalar or vector type as Result Type: "
@@ -131,7 +131,7 @@
       break;
     }
 
-    case SpvOpLogicalNot: {
+    case spv::Op::OpLogicalNot: {
       if (!_.IsBoolScalarType(result_type) && !_.IsBoolVectorType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected bool scalar or vector type as Result Type: "
@@ -145,7 +145,7 @@
       break;
     }
 
-    case SpvOpSelect: {
+    case spv::Op::OpSelect: {
       uint32_t dimension = 1;
       {
         const Instruction* type_inst = _.FindDef(result_type);
@@ -159,10 +159,10 @@
                  << " type as Result Type: " << spvOpcodeString(opcode);
         };
 
-        const SpvOp type_opcode = type_inst->opcode();
+        const spv::Op type_opcode = type_inst->opcode();
         switch (type_opcode) {
-          case SpvOpTypePointer: {
-            if (_.addressing_model() == SpvAddressingModelLogical &&
+          case spv::Op::OpTypePointer: {
+            if (_.addressing_model() == spv::AddressingModel::Logical &&
                 !_.features().variable_pointers)
               return _.diag(SPV_ERROR_INVALID_DATA, inst)
                      << "Using pointers with OpSelect requires capability "
@@ -170,31 +170,31 @@
             break;
           }
 
-          case SpvOpTypeSampledImage:
-          case SpvOpTypeImage:
-          case SpvOpTypeSampler: {
-            if (!_.HasCapability(SpvCapabilityBindlessTextureNV))
+          case spv::Op::OpTypeSampledImage:
+          case spv::Op::OpTypeImage:
+          case spv::Op::OpTypeSampler: {
+            if (!_.HasCapability(spv::Capability::BindlessTextureNV))
               return _.diag(SPV_ERROR_INVALID_DATA, inst)
                      << "Using image/sampler with OpSelect requires capability "
                      << "BindlessTextureNV";
             break;
           }
 
-          case SpvOpTypeVector: {
+          case spv::Op::OpTypeVector: {
             dimension = type_inst->word(3);
             break;
           }
 
-          case SpvOpTypeBool:
-          case SpvOpTypeInt:
-          case SpvOpTypeFloat: {
+          case spv::Op::OpTypeBool:
+          case spv::Op::OpTypeInt:
+          case spv::Op::OpTypeFloat: {
             break;
           }
 
           // Not RuntimeArray because of other rules.
-          case SpvOpTypeArray:
-          case SpvOpTypeMatrix:
-          case SpvOpTypeStruct: {
+          case spv::Op::OpTypeArray:
+          case spv::Op::OpTypeMatrix:
+          case spv::Op::OpTypeStruct: {
             if (!composites) return fail();
             break;
           }
@@ -235,16 +235,16 @@
       }
     }
 
-    case SpvOpIEqual:
-    case SpvOpINotEqual:
-    case SpvOpUGreaterThan:
-    case SpvOpUGreaterThanEqual:
-    case SpvOpULessThan:
-    case SpvOpULessThanEqual:
-    case SpvOpSGreaterThan:
-    case SpvOpSGreaterThanEqual:
-    case SpvOpSLessThan:
-    case SpvOpSLessThanEqual: {
+    case spv::Op::OpIEqual:
+    case spv::Op::OpINotEqual:
+    case spv::Op::OpUGreaterThan:
+    case spv::Op::OpUGreaterThanEqual:
+    case spv::Op::OpULessThan:
+    case spv::Op::OpULessThanEqual:
+    case spv::Op::OpSGreaterThan:
+    case spv::Op::OpSGreaterThanEqual:
+    case spv::Op::OpSLessThan:
+    case spv::Op::OpSLessThanEqual: {
       if (!_.IsBoolScalarType(result_type) && !_.IsBoolVectorType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected bool scalar or vector type as Result Type: "
diff --git a/source/val/validate_memory.cpp b/source/val/validate_memory.cpp
index 09fd2b6..80c9e87 100644
--- a/source/val/validate_memory.cpp
+++ b/source/val/validate_memory.cpp
@@ -39,13 +39,13 @@
                                  const std::set<Decoration>&);
 
 bool IsAllowedTypeOrArrayOfSame(ValidationState_t& _, const Instruction* type,
-                                std::initializer_list<uint32_t> allowed) {
+                                std::initializer_list<spv::Op> allowed) {
   if (std::find(allowed.begin(), allowed.end(), type->opcode()) !=
       allowed.end()) {
     return true;
   }
-  if (type->opcode() == SpvOpTypeArray ||
-      type->opcode() == SpvOpTypeRuntimeArray) {
+  if (type->opcode() == spv::Op::OpTypeArray ||
+      type->opcode() == spv::Op::OpTypeRuntimeArray) {
     auto elem_type = _.FindDef(type->word(2));
     return std::find(allowed.begin(), allowed.end(), elem_type->opcode()) !=
            allowed.end();
@@ -57,10 +57,10 @@
 // validator can tell, have the exact same data layout.
 bool AreLayoutCompatibleStructs(ValidationState_t& _, const Instruction* type1,
                                 const Instruction* type2) {
-  if (type1->opcode() != SpvOpTypeStruct) {
+  if (type1->opcode() != spv::Op::OpTypeStruct) {
     return false;
   }
-  if (type2->opcode() != SpvOpTypeStruct) {
+  if (type2->opcode() != spv::Op::OpTypeStruct) {
     return false;
   }
 
@@ -74,9 +74,9 @@
 // be OpTypeStruct instructions.
 bool HaveLayoutCompatibleMembers(ValidationState_t& _, const Instruction* type1,
                                  const Instruction* type2) {
-  assert(type1->opcode() == SpvOpTypeStruct &&
+  assert(type1->opcode() == spv::Op::OpTypeStruct &&
          "type1 must be an OpTypeStruct instruction.");
-  assert(type2->opcode() == SpvOpTypeStruct &&
+  assert(type2->opcode() == spv::Op::OpTypeStruct &&
          "type2 must be an OpTypeStruct instruction.");
   const auto& type1_operands = type1->operands();
   const auto& type2_operands = type2->operands();
@@ -101,9 +101,9 @@
 // OpTypeStruct instructions.
 bool HaveSameLayoutDecorations(ValidationState_t& _, const Instruction* type1,
                                const Instruction* type2) {
-  assert(type1->opcode() == SpvOpTypeStruct &&
+  assert(type1->opcode() == spv::Op::OpTypeStruct &&
          "type1 must be an OpTypeStruct instruction.");
-  assert(type2->opcode() == SpvOpTypeStruct &&
+  assert(type2->opcode() == spv::Op::OpTypeStruct &&
          "type2 must be an OpTypeStruct instruction.");
   const std::set<Decoration>& type1_decorations = _.id_decorations(type1->id());
   const std::set<Decoration>& type2_decorations = _.id_decorations(type2->id());
@@ -130,11 +130,11 @@
     // type1_decoration.  Therefore, it cannot lead to a conflict.
     for (const Decoration& decoration : type1_decorations) {
       switch (decoration.dec_type()) {
-        case SpvDecorationOffset: {
+        case spv::Decoration::Offset: {
           // Since these affect the layout of the struct, they must be present
           // in both structs.
           auto compare = [&decoration](const Decoration& rhs) {
-            if (rhs.dec_type() != SpvDecorationOffset) return false;
+            if (rhs.dec_type() != spv::Decoration::Offset) return false;
             return decoration.struct_member_index() ==
                    rhs.struct_member_index();
           };
@@ -163,7 +163,7 @@
                          bool skip_builtin) {
   if (skip_builtin) {
     for (const Decoration& decoration : _.id_decorations(storage->id())) {
-      if (decoration.dec_type() == SpvDecorationBuiltIn) return false;
+      if (decoration.dec_type() == spv::Decoration::BuiltIn) return false;
     }
   }
 
@@ -172,16 +172,16 @@
   Instruction* elem_type;
 
   switch (storage->opcode()) {
-    case SpvOpTypeBool:
+    case spv::Op::OpTypeBool:
       return true;
-    case SpvOpTypeVector:
-    case SpvOpTypeMatrix:
-    case SpvOpTypeArray:
-    case SpvOpTypeRuntimeArray:
+    case spv::Op::OpTypeVector:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeArray:
+    case spv::Op::OpTypeRuntimeArray:
       elem_type_id = storage->GetOperandAs<uint32_t>(elem_type_index);
       elem_type = _.FindDef(elem_type_id);
       return ContainsInvalidBool(_, elem_type, skip_builtin);
-    case SpvOpTypeStruct:
+    case spv::Op::OpTypeStruct:
       for (size_t member_type_index = 1;
            member_type_index < storage->operands().size();
            ++member_type_index) {
@@ -203,14 +203,14 @@
   Instruction* elem_type;
 
   switch (storage->opcode()) {
-    case SpvOpTypeCooperativeMatrixNV:
+    case spv::Op::OpTypeCooperativeMatrixNV:
       return true;
-    case SpvOpTypeArray:
-    case SpvOpTypeRuntimeArray:
+    case spv::Op::OpTypeArray:
+    case spv::Op::OpTypeRuntimeArray:
       elem_type_id = storage->GetOperandAs<uint32_t>(elem_type_index);
       elem_type = _.FindDef(elem_type_id);
       return ContainsCooperativeMatrix(_, elem_type);
-    case SpvOpTypeStruct:
+    case spv::Op::OpTypeStruct:
       for (size_t member_type_index = 1;
            member_type_index < storage->operands().size();
            ++member_type_index) {
@@ -226,33 +226,33 @@
   return false;
 }
 
-std::pair<SpvStorageClass, SpvStorageClass> GetStorageClass(
+std::pair<spv::StorageClass, spv::StorageClass> GetStorageClass(
     ValidationState_t& _, const Instruction* inst) {
-  SpvStorageClass dst_sc = SpvStorageClassMax;
-  SpvStorageClass src_sc = SpvStorageClassMax;
+  spv::StorageClass dst_sc = spv::StorageClass::Max;
+  spv::StorageClass src_sc = spv::StorageClass::Max;
   switch (inst->opcode()) {
-    case SpvOpCooperativeMatrixLoadNV:
-    case SpvOpLoad: {
+    case spv::Op::OpCooperativeMatrixLoadNV:
+    case spv::Op::OpLoad: {
       auto load_pointer = _.FindDef(inst->GetOperandAs<uint32_t>(2));
       auto load_pointer_type = _.FindDef(load_pointer->type_id());
-      dst_sc = load_pointer_type->GetOperandAs<SpvStorageClass>(1);
+      dst_sc = load_pointer_type->GetOperandAs<spv::StorageClass>(1);
       break;
     }
-    case SpvOpCooperativeMatrixStoreNV:
-    case SpvOpStore: {
+    case spv::Op::OpCooperativeMatrixStoreNV:
+    case spv::Op::OpStore: {
       auto store_pointer = _.FindDef(inst->GetOperandAs<uint32_t>(0));
       auto store_pointer_type = _.FindDef(store_pointer->type_id());
-      dst_sc = store_pointer_type->GetOperandAs<SpvStorageClass>(1);
+      dst_sc = store_pointer_type->GetOperandAs<spv::StorageClass>(1);
       break;
     }
-    case SpvOpCopyMemory:
-    case SpvOpCopyMemorySized: {
+    case spv::Op::OpCopyMemory:
+    case spv::Op::OpCopyMemorySized: {
       auto dst = _.FindDef(inst->GetOperandAs<uint32_t>(0));
       auto dst_type = _.FindDef(dst->type_id());
-      dst_sc = dst_type->GetOperandAs<SpvStorageClass>(1);
+      dst_sc = dst_type->GetOperandAs<spv::StorageClass>(1);
       auto src = _.FindDef(inst->GetOperandAs<uint32_t>(1));
       auto src_type = _.FindDef(src->type_id());
-      src_sc = src_type->GetOperandAs<SpvStorageClass>(1);
+      src_sc = src_type->GetOperandAs<spv::StorageClass>(1);
       break;
     }
     default:
@@ -266,9 +266,9 @@
 // argument and its implied operands.
 int MemoryAccessNumWords(uint32_t mask) {
   int result = 1;  // Count the mask
-  if (mask & SpvMemoryAccessAlignedMask) ++result;
-  if (mask & SpvMemoryAccessMakePointerAvailableKHRMask) ++result;
-  if (mask & SpvMemoryAccessMakePointerVisibleKHRMask) ++result;
+  if (mask & uint32_t(spv::MemoryAccessMask::Aligned)) ++result;
+  if (mask & uint32_t(spv::MemoryAccessMask::MakePointerAvailableKHR)) ++result;
+  if (mask & uint32_t(spv::MemoryAccessMask::MakePointerVisibleKHR)) ++result;
   return result;
 }
 
@@ -279,8 +279,8 @@
 // OpCooperativeMatrixStoreNV.
 uint32_t GetMakeAvailableScope(const Instruction* inst, uint32_t mask,
                                uint32_t mask_index) {
-  assert(mask & SpvMemoryAccessMakePointerAvailableKHRMask);
-  uint32_t this_bit = uint32_t(SpvMemoryAccessMakePointerAvailableKHRMask);
+  assert(mask & uint32_t(spv::MemoryAccessMask::MakePointerAvailableKHR));
+  uint32_t this_bit = uint32_t(spv::MemoryAccessMask::MakePointerAvailableKHR);
   uint32_t index =
       mask_index - 1 + MemoryAccessNumWords(mask & (this_bit | (this_bit - 1)));
   return inst->GetOperandAs<uint32_t>(index);
@@ -291,8 +291,8 @@
 // OpCooperativeMatrixStoreNV.
 uint32_t GetMakeVisibleScope(const Instruction* inst, uint32_t mask,
                              uint32_t mask_index) {
-  assert(mask & SpvMemoryAccessMakePointerVisibleKHRMask);
-  uint32_t this_bit = uint32_t(SpvMemoryAccessMakePointerVisibleKHRMask);
+  assert(mask & uint32_t(spv::MemoryAccessMask::MakePointerVisibleKHR));
+  uint32_t this_bit = uint32_t(spv::MemoryAccessMask::MakePointerVisibleKHR);
   uint32_t index =
       mask_index - 1 + MemoryAccessNumWords(mask & (this_bit | (this_bit - 1)));
   return inst->GetOperandAs<uint32_t>(index);
@@ -303,19 +303,19 @@
        ++member_index) {
     const auto member_id = inst->GetOperandAs<uint32_t>(member_index);
     const auto member_type = _.FindDef(member_id);
-    if (member_type->opcode() == SpvOpTypeRuntimeArray) return true;
+    if (member_type->opcode() == spv::Op::OpTypeRuntimeArray) return true;
   }
   return false;
 }
 
 spv_result_t CheckMemoryAccess(ValidationState_t& _, const Instruction* inst,
                                uint32_t index) {
-  SpvStorageClass dst_sc, src_sc;
+  spv::StorageClass dst_sc, src_sc;
   std::tie(dst_sc, src_sc) = GetStorageClass(_, inst);
   if (inst->operands().size() <= index) {
     // Cases where lack of some operand is invalid
-    if (src_sc == SpvStorageClassPhysicalStorageBuffer ||
-        dst_sc == SpvStorageClassPhysicalStorageBuffer) {
+    if (src_sc == spv::StorageClass::PhysicalStorageBuffer ||
+        dst_sc == spv::StorageClass::PhysicalStorageBuffer) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << _.VkErrorID(4708)
              << "Memory accesses with PhysicalStorageBuffer must use Aligned.";
@@ -324,14 +324,14 @@
   }
 
   const uint32_t mask = inst->GetOperandAs<uint32_t>(index);
-  if (mask & SpvMemoryAccessMakePointerAvailableKHRMask) {
-    if (inst->opcode() == SpvOpLoad ||
-        inst->opcode() == SpvOpCooperativeMatrixLoadNV) {
+  if (mask & uint32_t(spv::MemoryAccessMask::MakePointerAvailableKHR)) {
+    if (inst->opcode() == spv::Op::OpLoad ||
+        inst->opcode() == spv::Op::OpCooperativeMatrixLoadNV) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "MakePointerAvailableKHR cannot be used with OpLoad.";
     }
 
-    if (!(mask & SpvMemoryAccessNonPrivatePointerKHRMask)) {
+    if (!(mask & uint32_t(spv::MemoryAccessMask::NonPrivatePointerKHR))) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "NonPrivatePointerKHR must be specified if "
                 "MakePointerAvailableKHR is specified.";
@@ -343,14 +343,14 @@
       return error;
   }
 
-  if (mask & SpvMemoryAccessMakePointerVisibleKHRMask) {
-    if (inst->opcode() == SpvOpStore ||
-        inst->opcode() == SpvOpCooperativeMatrixStoreNV) {
+  if (mask & uint32_t(spv::MemoryAccessMask::MakePointerVisibleKHR)) {
+    if (inst->opcode() == spv::Op::OpStore ||
+        inst->opcode() == spv::Op::OpCooperativeMatrixStoreNV) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "MakePointerVisibleKHR cannot be used with OpStore.";
     }
 
-    if (!(mask & SpvMemoryAccessNonPrivatePointerKHRMask)) {
+    if (!(mask & uint32_t(spv::MemoryAccessMask::NonPrivatePointerKHR))) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "NonPrivatePointerKHR must be specified if "
              << "MakePointerVisibleKHR is specified.";
@@ -361,24 +361,27 @@
     if (auto error = ValidateMemoryScope(_, inst, visible_scope)) return error;
   }
 
-  if (mask & SpvMemoryAccessNonPrivatePointerKHRMask) {
-    if (dst_sc != SpvStorageClassUniform &&
-        dst_sc != SpvStorageClassWorkgroup &&
-        dst_sc != SpvStorageClassCrossWorkgroup &&
-        dst_sc != SpvStorageClassGeneric && dst_sc != SpvStorageClassImage &&
-        dst_sc != SpvStorageClassStorageBuffer &&
-        dst_sc != SpvStorageClassPhysicalStorageBuffer) {
+  if (mask & uint32_t(spv::MemoryAccessMask::NonPrivatePointerKHR)) {
+    if (dst_sc != spv::StorageClass::Uniform &&
+        dst_sc != spv::StorageClass::Workgroup &&
+        dst_sc != spv::StorageClass::CrossWorkgroup &&
+        dst_sc != spv::StorageClass::Generic &&
+        dst_sc != spv::StorageClass::Image &&
+        dst_sc != spv::StorageClass::StorageBuffer &&
+        dst_sc != spv::StorageClass::PhysicalStorageBuffer) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "NonPrivatePointerKHR requires a pointer in Uniform, "
              << "Workgroup, CrossWorkgroup, Generic, Image or StorageBuffer "
              << "storage classes.";
     }
-    if (src_sc != SpvStorageClassMax && src_sc != SpvStorageClassUniform &&
-        src_sc != SpvStorageClassWorkgroup &&
-        src_sc != SpvStorageClassCrossWorkgroup &&
-        src_sc != SpvStorageClassGeneric && src_sc != SpvStorageClassImage &&
-        src_sc != SpvStorageClassStorageBuffer &&
-        src_sc != SpvStorageClassPhysicalStorageBuffer) {
+    if (src_sc != spv::StorageClass::Max &&
+        src_sc != spv::StorageClass::Uniform &&
+        src_sc != spv::StorageClass::Workgroup &&
+        src_sc != spv::StorageClass::CrossWorkgroup &&
+        src_sc != spv::StorageClass::Generic &&
+        src_sc != spv::StorageClass::Image &&
+        src_sc != spv::StorageClass::StorageBuffer &&
+        src_sc != spv::StorageClass::PhysicalStorageBuffer) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "NonPrivatePointerKHR requires a pointer in Uniform, "
              << "Workgroup, CrossWorkgroup, Generic, Image or StorageBuffer "
@@ -386,9 +389,9 @@
     }
   }
 
-  if (!(mask & SpvMemoryAccessAlignedMask)) {
-    if (src_sc == SpvStorageClassPhysicalStorageBuffer ||
-        dst_sc == SpvStorageClassPhysicalStorageBuffer) {
+  if (!(mask & uint32_t(spv::MemoryAccessMask::Aligned))) {
+    if (src_sc == spv::StorageClass::PhysicalStorageBuffer ||
+        dst_sc == spv::StorageClass::PhysicalStorageBuffer) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << _.VkErrorID(4708)
              << "Memory accesses with PhysicalStorageBuffer must use Aligned.";
@@ -400,7 +403,7 @@
 
 spv_result_t ValidateVariable(ValidationState_t& _, const Instruction* inst) {
   auto result_type = _.FindDef(inst->type_id());
-  if (!result_type || result_type->opcode() != SpvOpTypePointer) {
+  if (!result_type || result_type->opcode() != spv::Op::OpTypePointer) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "OpVariable Result Type <id> " << _.getIdName(inst->type_id())
            << " is not a pointer type.";
@@ -416,9 +419,9 @@
     const auto initializer_id = inst->GetOperandAs<uint32_t>(initializer_index);
     const auto initializer = _.FindDef(initializer_id);
     const auto is_module_scope_var =
-        initializer && (initializer->opcode() == SpvOpVariable) &&
-        (initializer->GetOperandAs<SpvStorageClass>(storage_class_index) !=
-         SpvStorageClassFunction);
+        initializer && (initializer->opcode() == spv::Op::OpVariable) &&
+        (initializer->GetOperandAs<spv::StorageClass>(storage_class_index) !=
+         spv::StorageClass::Function);
     const auto is_constant =
         initializer && spvOpcodeIsConstant(initializer->opcode());
     if (!initializer || !(is_constant || is_module_scope_var)) {
@@ -433,23 +436,24 @@
     }
   }
 
-  auto storage_class = inst->GetOperandAs<SpvStorageClass>(storage_class_index);
-  if (storage_class != SpvStorageClassWorkgroup &&
-      storage_class != SpvStorageClassCrossWorkgroup &&
-      storage_class != SpvStorageClassPrivate &&
-      storage_class != SpvStorageClassFunction &&
-      storage_class != SpvStorageClassRayPayloadKHR &&
-      storage_class != SpvStorageClassIncomingRayPayloadKHR &&
-      storage_class != SpvStorageClassHitAttributeKHR &&
-      storage_class != SpvStorageClassCallableDataKHR &&
-      storage_class != SpvStorageClassIncomingCallableDataKHR &&
-      storage_class != SpvStorageClassTaskPayloadWorkgroupEXT) {
-    bool storage_input_or_output = storage_class == SpvStorageClassInput ||
-                                   storage_class == SpvStorageClassOutput;
+  auto storage_class =
+      inst->GetOperandAs<spv::StorageClass>(storage_class_index);
+  if (storage_class != spv::StorageClass::Workgroup &&
+      storage_class != spv::StorageClass::CrossWorkgroup &&
+      storage_class != spv::StorageClass::Private &&
+      storage_class != spv::StorageClass::Function &&
+      storage_class != spv::StorageClass::RayPayloadKHR &&
+      storage_class != spv::StorageClass::IncomingRayPayloadKHR &&
+      storage_class != spv::StorageClass::HitAttributeKHR &&
+      storage_class != spv::StorageClass::CallableDataKHR &&
+      storage_class != spv::StorageClass::IncomingCallableDataKHR &&
+      storage_class != spv::StorageClass::TaskPayloadWorkgroupEXT) {
+    bool storage_input_or_output = storage_class == spv::StorageClass::Input ||
+                                   storage_class == spv::StorageClass::Output;
     bool builtin = false;
     if (storage_input_or_output) {
       for (const Decoration& decoration : _.id_decorations(inst->id())) {
-        if (decoration.dec_type() == SpvDecorationBuiltIn) {
+        if (decoration.dec_type() == spv::Decoration::BuiltIn) {
           builtin = true;
           break;
         }
@@ -482,18 +486,18 @@
            << "Invalid storage class for target environment";
   }
 
-  if (storage_class == SpvStorageClassGeneric) {
+  if (storage_class == spv::StorageClass::Generic) {
     return _.diag(SPV_ERROR_INVALID_BINARY, inst)
            << "OpVariable storage class cannot be Generic";
   }
 
-  if (inst->function() && storage_class != SpvStorageClassFunction) {
+  if (inst->function() && storage_class != spv::StorageClass::Function) {
     return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
            << "Variables must have a function[7] storage class inside"
               " of a function";
   }
 
-  if (!inst->function() && storage_class == SpvStorageClassFunction) {
+  if (!inst->function() && storage_class == spv::StorageClass::Function) {
     return _.diag(SPV_ERROR_INVALID_LAYOUT, inst)
            << "Variables can not have a function[7] storage class "
               "outside of a function";
@@ -503,7 +507,7 @@
   // storage class.
   const auto result_storage_class_index = 1;
   const auto result_storage_class =
-      result_type->GetOperandAs<uint32_t>(result_storage_class_index);
+      result_type->GetOperandAs<spv::StorageClass>(result_storage_class_index);
   if (storage_class != result_storage_class) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "From SPIR-V spec, section 3.32.8 on OpVariable:\n"
@@ -513,16 +517,16 @@
 
   // Variable pointer related restrictions.
   const auto pointee = _.FindDef(result_type->word(3));
-  if (_.addressing_model() == SpvAddressingModelLogical &&
+  if (_.addressing_model() == spv::AddressingModel::Logical &&
       !_.options()->relax_logical_pointer) {
     // VariablePointersStorageBuffer is implied by VariablePointers.
-    if (pointee->opcode() == SpvOpTypePointer) {
-      if (!_.HasCapability(SpvCapabilityVariablePointersStorageBuffer)) {
+    if (pointee->opcode() == spv::Op::OpTypePointer) {
+      if (!_.HasCapability(spv::Capability::VariablePointersStorageBuffer)) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << "In Logical addressing, variables may not allocate a pointer "
                << "type";
-      } else if (storage_class != SpvStorageClassFunction &&
-                 storage_class != SpvStorageClassPrivate) {
+      } else if (storage_class != spv::StorageClass::Function &&
+                 storage_class != spv::StorageClass::Private) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << "In Logical addressing with variable pointers, variables "
                << "that allocate pointers must be in Function or Private "
@@ -534,8 +538,8 @@
   if (spvIsVulkanEnv(_.context()->target_env)) {
     // Vulkan Push Constant Interface section: Check type of PushConstant
     // variables.
-    if (storage_class == SpvStorageClassPushConstant) {
-      if (pointee->opcode() != SpvOpTypeStruct) {
+    if (storage_class == spv::StorageClass::PushConstant) {
+      if (pointee->opcode() != spv::Op::OpTypeStruct) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << _.VkErrorID(6808) << "PushConstant OpVariable <id> "
                << _.getIdName(inst->id()) << " has illegal type.\n"
@@ -546,11 +550,12 @@
 
     // Vulkan Descriptor Set Interface: Check type of UniformConstant and
     // Uniform variables.
-    if (storage_class == SpvStorageClassUniformConstant) {
+    if (storage_class == spv::StorageClass::UniformConstant) {
       if (!IsAllowedTypeOrArrayOfSame(
               _, pointee,
-              {SpvOpTypeImage, SpvOpTypeSampler, SpvOpTypeSampledImage,
-               SpvOpTypeAccelerationStructureKHR})) {
+              {spv::Op::OpTypeImage, spv::Op::OpTypeSampler,
+               spv::Op::OpTypeSampledImage,
+               spv::Op::OpTypeAccelerationStructureKHR})) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << _.VkErrorID(4655) << "UniformConstant OpVariable <id> "
                << _.getIdName(inst->id()) << " has illegal type.\n"
@@ -562,8 +567,8 @@
       }
     }
 
-    if (storage_class == SpvStorageClassUniform) {
-      if (!IsAllowedTypeOrArrayOfSame(_, pointee, {SpvOpTypeStruct})) {
+    if (storage_class == spv::StorageClass::Uniform) {
+      if (!IsAllowedTypeOrArrayOfSame(_, pointee, {spv::Op::OpTypeStruct})) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << _.VkErrorID(6807) << "Uniform OpVariable <id> "
                << _.getIdName(inst->id()) << " has illegal type.\n"
@@ -575,8 +580,8 @@
       }
     }
 
-    if (storage_class == SpvStorageClassStorageBuffer) {
-      if (!IsAllowedTypeOrArrayOfSame(_, pointee, {SpvOpTypeStruct})) {
+    if (storage_class == spv::StorageClass::StorageBuffer) {
+      if (!IsAllowedTypeOrArrayOfSame(_, pointee, {spv::Op::OpTypeStruct})) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << _.VkErrorID(6807) << "StorageBuffer OpVariable <id> "
                << _.getIdName(inst->id()) << " has illegal type.\n"
@@ -589,9 +594,9 @@
     }
 
     // Check for invalid use of Invariant
-    if (storage_class != SpvStorageClassInput &&
-        storage_class != SpvStorageClassOutput) {
-      if (_.HasDecoration(inst->id(), SpvDecorationInvariant)) {
+    if (storage_class != spv::StorageClass::Input &&
+        storage_class != spv::StorageClass::Output) {
+      if (_.HasDecoration(inst->id(), spv::Decoration::Invariant)) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << _.VkErrorID(4677)
                << "Variable decorated with Invariant must only be identified "
@@ -599,8 +604,8 @@
                   "environment.";
       }
       // Need to check if only the members in a struct are decorated
-      if (value_type && value_type->opcode() == SpvOpTypeStruct) {
-        if (_.HasDecoration(value_id, SpvDecorationInvariant)) {
+      if (value_type && value_type->opcode() == spv::Op::OpTypeStruct) {
+        if (_.HasDecoration(value_id, spv::Decoration::Invariant)) {
           return _.diag(SPV_ERROR_INVALID_ID, inst)
                  << _.VkErrorID(4677)
                  << "Variable struct member decorated with Invariant must only "
@@ -612,10 +617,10 @@
 
     // Initializers in Vulkan are only allowed in some storage clases
     if (inst->operands().size() > 3) {
-      if (storage_class == SpvStorageClassWorkgroup) {
+      if (storage_class == spv::StorageClass::Workgroup) {
         auto init_id = inst->GetOperandAs<uint32_t>(3);
         auto init = _.FindDef(init_id);
-        if (init->opcode() != SpvOpConstantNull) {
+        if (init->opcode() != spv::Op::OpConstantNull) {
           return _.diag(SPV_ERROR_INVALID_ID, inst)
                  << _.VkErrorID(4734) << "OpVariable, <id> "
                  << _.getIdName(inst->id())
@@ -623,9 +628,9 @@
                     "Workgroup "
                     "storage class";
         }
-      } else if (storage_class != SpvStorageClassOutput &&
-                 storage_class != SpvStorageClassPrivate &&
-                 storage_class != SpvStorageClassFunction) {
+      } else if (storage_class != spv::StorageClass::Output &&
+                 storage_class != spv::StorageClass::Private &&
+                 storage_class != spv::StorageClass::Function) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << _.VkErrorID(4651) << "OpVariable, <id> "
                << _.getIdName(inst->id())
@@ -641,35 +646,35 @@
   }
 
   if (inst->operands().size() > 3) {
-    if (storage_class == SpvStorageClassTaskPayloadWorkgroupEXT) {
+    if (storage_class == spv::StorageClass::TaskPayloadWorkgroupEXT) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "OpVariable, <id> " << _.getIdName(inst->id())
              << ", initializer are not allowed for TaskPayloadWorkgroupEXT";
     }
-    if (storage_class == SpvStorageClassInput) {
+    if (storage_class == spv::StorageClass::Input) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "OpVariable, <id> " << _.getIdName(inst->id())
              << ", initializer are not allowed for Input";
     }
   }
 
-  if (storage_class == SpvStorageClassPhysicalStorageBuffer) {
+  if (storage_class == spv::StorageClass::PhysicalStorageBuffer) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "PhysicalStorageBuffer must not be used with OpVariable.";
   }
 
   auto pointee_base = pointee;
-  while (pointee_base->opcode() == SpvOpTypeArray) {
+  while (pointee_base->opcode() == spv::Op::OpTypeArray) {
     pointee_base = _.FindDef(pointee_base->GetOperandAs<uint32_t>(1u));
   }
-  if (pointee_base->opcode() == SpvOpTypePointer) {
-    if (pointee_base->GetOperandAs<uint32_t>(1u) ==
-        SpvStorageClassPhysicalStorageBuffer) {
+  if (pointee_base->opcode() == spv::Op::OpTypePointer) {
+    if (pointee_base->GetOperandAs<spv::StorageClass>(1u) ==
+        spv::StorageClass::PhysicalStorageBuffer) {
       // check for AliasedPointer/RestrictPointer
       bool foundAliased =
-          _.HasDecoration(inst->id(), SpvDecorationAliasedPointer);
+          _.HasDecoration(inst->id(), spv::Decoration::AliasedPointer);
       bool foundRestrict =
-          _.HasDecoration(inst->id(), SpvDecorationRestrictPointer);
+          _.HasDecoration(inst->id(), spv::Decoration::RestrictPointer);
       if (!foundAliased && !foundRestrict) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << "OpVariable " << inst->id()
@@ -690,8 +695,8 @@
     // OpTypeRuntimeArray should only ever be in a container like OpTypeStruct,
     // so should never appear as a bare variable.
     // Unless the module has the RuntimeDescriptorArrayEXT capability.
-    if (value_type && value_type->opcode() == SpvOpTypeRuntimeArray) {
-      if (!_.HasCapability(SpvCapabilityRuntimeDescriptorArrayEXT)) {
+    if (value_type && value_type->opcode() == spv::Op::OpTypeRuntimeArray) {
+      if (!_.HasCapability(spv::Capability::RuntimeDescriptorArrayEXT)) {
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << _.VkErrorID(4680) << "OpVariable, <id> "
                << _.getIdName(inst->id())
@@ -702,9 +707,9 @@
       } else {
         // A bare variable OpTypeRuntimeArray is allowed in this context, but
         // still need to check the storage class.
-        if (storage_class != SpvStorageClassStorageBuffer &&
-            storage_class != SpvStorageClassUniform &&
-            storage_class != SpvStorageClassUniformConstant) {
+        if (storage_class != spv::StorageClass::StorageBuffer &&
+            storage_class != spv::StorageClass::Uniform &&
+            storage_class != spv::StorageClass::UniformConstant) {
           return _.diag(SPV_ERROR_INVALID_ID, inst)
                  << _.VkErrorID(4680)
                  << "For Vulkan with RuntimeDescriptorArrayEXT, a variable "
@@ -718,11 +723,11 @@
     // must either have the storage class StorageBuffer and be decorated
     // with Block, or it must be in the Uniform storage class and be decorated
     // as BufferBlock.
-    if (value_type && value_type->opcode() == SpvOpTypeStruct) {
+    if (value_type && value_type->opcode() == spv::Op::OpTypeStruct) {
       if (DoesStructContainRTA(_, value_type)) {
-        if (storage_class == SpvStorageClassStorageBuffer ||
-            storage_class == SpvStorageClassPhysicalStorageBuffer) {
-          if (!_.HasDecoration(value_id, SpvDecorationBlock)) {
+        if (storage_class == spv::StorageClass::StorageBuffer ||
+            storage_class == spv::StorageClass::PhysicalStorageBuffer) {
+          if (!_.HasDecoration(value_id, spv::Decoration::Block)) {
             return _.diag(SPV_ERROR_INVALID_ID, inst)
                    << _.VkErrorID(4680)
                    << "For Vulkan, an OpTypeStruct variable containing an "
@@ -730,8 +735,8 @@
                    << "has storage class StorageBuffer or "
                       "PhysicalStorageBuffer.";
           }
-        } else if (storage_class == SpvStorageClassUniform) {
-          if (!_.HasDecoration(value_id, SpvDecorationBufferBlock)) {
+        } else if (storage_class == spv::StorageClass::Uniform) {
+          if (!_.HasDecoration(value_id, spv::Decoration::BufferBlock)) {
             return _.diag(SPV_ERROR_INVALID_ID, inst)
                    << _.VkErrorID(4680)
                    << "For Vulkan, an OpTypeStruct variable containing an "
@@ -750,8 +755,8 @@
   }
 
   // Cooperative matrix types can only be allocated in Function or Private
-  if ((storage_class != SpvStorageClassFunction &&
-       storage_class != SpvStorageClassPrivate) &&
+  if ((storage_class != spv::StorageClass::Function &&
+       storage_class != spv::StorageClass::Private) &&
       ContainsCooperativeMatrix(_, pointee)) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Cooperative matrix types (or types containing them) can only be "
@@ -760,57 +765,59 @@
               "parameters";
   }
 
-  if (_.HasCapability(SpvCapabilityShader)) {
+  if (_.HasCapability(spv::Capability::Shader)) {
     // Don't allow variables containing 16-bit elements without the appropriate
     // capabilities.
-    if ((!_.HasCapability(SpvCapabilityInt16) &&
-         _.ContainsSizedIntOrFloatType(value_id, SpvOpTypeInt, 16)) ||
-        (!_.HasCapability(SpvCapabilityFloat16) &&
-         _.ContainsSizedIntOrFloatType(value_id, SpvOpTypeFloat, 16))) {
+    if ((!_.HasCapability(spv::Capability::Int16) &&
+         _.ContainsSizedIntOrFloatType(value_id, spv::Op::OpTypeInt, 16)) ||
+        (!_.HasCapability(spv::Capability::Float16) &&
+         _.ContainsSizedIntOrFloatType(value_id, spv::Op::OpTypeFloat, 16))) {
       auto underlying_type = value_type;
-      while (underlying_type->opcode() == SpvOpTypePointer) {
-        storage_class = underlying_type->GetOperandAs<SpvStorageClass>(1u);
+      while (underlying_type->opcode() == spv::Op::OpTypePointer) {
+        storage_class = underlying_type->GetOperandAs<spv::StorageClass>(1u);
         underlying_type =
             _.FindDef(underlying_type->GetOperandAs<uint32_t>(2u));
       }
       bool storage_class_ok = true;
       std::string sc_name = _.grammar().lookupOperandName(
-          SPV_OPERAND_TYPE_STORAGE_CLASS, storage_class);
+          SPV_OPERAND_TYPE_STORAGE_CLASS, uint32_t(storage_class));
       switch (storage_class) {
-        case SpvStorageClassStorageBuffer:
-        case SpvStorageClassPhysicalStorageBuffer:
-          if (!_.HasCapability(SpvCapabilityStorageBuffer16BitAccess)) {
+        case spv::StorageClass::StorageBuffer:
+        case spv::StorageClass::PhysicalStorageBuffer:
+          if (!_.HasCapability(spv::Capability::StorageBuffer16BitAccess)) {
             storage_class_ok = false;
           }
           break;
-        case SpvStorageClassUniform:
+        case spv::StorageClass::Uniform:
           if (!_.HasCapability(
-                  SpvCapabilityUniformAndStorageBuffer16BitAccess)) {
-            if (underlying_type->opcode() == SpvOpTypeArray ||
-                underlying_type->opcode() == SpvOpTypeRuntimeArray) {
+                  spv::Capability::UniformAndStorageBuffer16BitAccess)) {
+            if (underlying_type->opcode() == spv::Op::OpTypeArray ||
+                underlying_type->opcode() == spv::Op::OpTypeRuntimeArray) {
               underlying_type =
                   _.FindDef(underlying_type->GetOperandAs<uint32_t>(1u));
             }
-            if (!_.HasCapability(SpvCapabilityStorageBuffer16BitAccess) ||
+            if (!_.HasCapability(spv::Capability::StorageBuffer16BitAccess) ||
                 !_.HasDecoration(underlying_type->id(),
-                                 SpvDecorationBufferBlock)) {
+                                 spv::Decoration::BufferBlock)) {
               storage_class_ok = false;
             }
           }
           break;
-        case SpvStorageClassPushConstant:
-          if (!_.HasCapability(SpvCapabilityStoragePushConstant16)) {
+        case spv::StorageClass::PushConstant:
+          if (!_.HasCapability(spv::Capability::StoragePushConstant16)) {
             storage_class_ok = false;
           }
           break;
-        case SpvStorageClassInput:
-        case SpvStorageClassOutput:
-          if (!_.HasCapability(SpvCapabilityStorageInputOutput16)) {
+        case spv::StorageClass::Input:
+        case spv::StorageClass::Output:
+          if (!_.HasCapability(spv::Capability::StorageInputOutput16)) {
             storage_class_ok = false;
           }
           break;
-        case SpvStorageClassWorkgroup:
-          if (!_.HasCapability(SpvCapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR)) {
+        case spv::StorageClass::Workgroup:
+          if (!_.HasCapability(
+                  spv::Capability::
+                      WorkgroupMemoryExplicitLayout16BitAccessKHR)) {
             storage_class_ok = false;
           }
           break;
@@ -827,46 +834,48 @@
     }
     // Don't allow variables containing 8-bit elements without the appropriate
     // capabilities.
-    if (!_.HasCapability(SpvCapabilityInt8) &&
-        _.ContainsSizedIntOrFloatType(value_id, SpvOpTypeInt, 8)) {
+    if (!_.HasCapability(spv::Capability::Int8) &&
+        _.ContainsSizedIntOrFloatType(value_id, spv::Op::OpTypeInt, 8)) {
       auto underlying_type = value_type;
-      while (underlying_type->opcode() == SpvOpTypePointer) {
-        storage_class = underlying_type->GetOperandAs<SpvStorageClass>(1u);
+      while (underlying_type->opcode() == spv::Op::OpTypePointer) {
+        storage_class = underlying_type->GetOperandAs<spv::StorageClass>(1u);
         underlying_type =
             _.FindDef(underlying_type->GetOperandAs<uint32_t>(2u));
       }
       bool storage_class_ok = true;
       std::string sc_name = _.grammar().lookupOperandName(
-          SPV_OPERAND_TYPE_STORAGE_CLASS, storage_class);
+          SPV_OPERAND_TYPE_STORAGE_CLASS, uint32_t(storage_class));
       switch (storage_class) {
-        case SpvStorageClassStorageBuffer:
-        case SpvStorageClassPhysicalStorageBuffer:
-          if (!_.HasCapability(SpvCapabilityStorageBuffer8BitAccess)) {
+        case spv::StorageClass::StorageBuffer:
+        case spv::StorageClass::PhysicalStorageBuffer:
+          if (!_.HasCapability(spv::Capability::StorageBuffer8BitAccess)) {
             storage_class_ok = false;
           }
           break;
-        case SpvStorageClassUniform:
+        case spv::StorageClass::Uniform:
           if (!_.HasCapability(
-                  SpvCapabilityUniformAndStorageBuffer8BitAccess)) {
-            if (underlying_type->opcode() == SpvOpTypeArray ||
-                underlying_type->opcode() == SpvOpTypeRuntimeArray) {
+                  spv::Capability::UniformAndStorageBuffer8BitAccess)) {
+            if (underlying_type->opcode() == spv::Op::OpTypeArray ||
+                underlying_type->opcode() == spv::Op::OpTypeRuntimeArray) {
               underlying_type =
                   _.FindDef(underlying_type->GetOperandAs<uint32_t>(1u));
             }
-            if (!_.HasCapability(SpvCapabilityStorageBuffer8BitAccess) ||
+            if (!_.HasCapability(spv::Capability::StorageBuffer8BitAccess) ||
                 !_.HasDecoration(underlying_type->id(),
-                                 SpvDecorationBufferBlock)) {
+                                 spv::Decoration::BufferBlock)) {
               storage_class_ok = false;
             }
           }
           break;
-        case SpvStorageClassPushConstant:
-          if (!_.HasCapability(SpvCapabilityStoragePushConstant8)) {
+        case spv::StorageClass::PushConstant:
+          if (!_.HasCapability(spv::Capability::StoragePushConstant8)) {
             storage_class_ok = false;
           }
           break;
-        case SpvStorageClassWorkgroup:
-          if (!_.HasCapability(SpvCapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR)) {
+        case spv::StorageClass::Workgroup:
+          if (!_.HasCapability(
+                  spv::Capability::
+                      WorkgroupMemoryExplicitLayout8BitAccessKHR)) {
             storage_class_ok = false;
           }
           break;
@@ -898,7 +907,7 @@
   const auto pointer_id = inst->GetOperandAs<uint32_t>(pointer_index);
   const auto pointer = _.FindDef(pointer_id);
   if (!pointer ||
-      ((_.addressing_model() == SpvAddressingModelLogical) &&
+      ((_.addressing_model() == spv::AddressingModel::Logical) &&
        ((!_.features().variable_pointers &&
          !spvOpcodeReturnsLogicalPointer(pointer->opcode())) ||
         (_.features().variable_pointers &&
@@ -909,14 +918,14 @@
   }
 
   const auto pointer_type = _.FindDef(pointer->type_id());
-  if (!pointer_type || pointer_type->opcode() != SpvOpTypePointer) {
+  if (!pointer_type || pointer_type->opcode() != spv::Op::OpTypePointer) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "OpLoad type for pointer <id> " << _.getIdName(pointer_id)
            << " is not a pointer type.";
   }
 
   uint32_t pointee_data_type;
-  uint32_t storage_class;
+  spv::StorageClass storage_class;
   if (!_.GetPointerTypeInfo(pointer_type->id(), &pointee_data_type,
                             &storage_class) ||
       result_type->id() != pointee_data_type) {
@@ -934,13 +943,13 @@
 
   if (auto error = CheckMemoryAccess(_, inst, 3)) return error;
 
-  if (_.HasCapability(SpvCapabilityShader) &&
+  if (_.HasCapability(spv::Capability::Shader) &&
       _.ContainsLimitedUseIntOrFloatType(inst->type_id()) &&
-      result_type->opcode() != SpvOpTypePointer) {
-    if (result_type->opcode() != SpvOpTypeInt &&
-        result_type->opcode() != SpvOpTypeFloat &&
-        result_type->opcode() != SpvOpTypeVector &&
-        result_type->opcode() != SpvOpTypeMatrix) {
+      result_type->opcode() != spv::Op::OpTypePointer) {
+    if (result_type->opcode() != spv::Op::OpTypeInt &&
+        result_type->opcode() != spv::Op::OpTypeFloat &&
+        result_type->opcode() != spv::Op::OpTypeVector &&
+        result_type->opcode() != spv::Op::OpTypeMatrix) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "8- or 16-bit loads must be a scalar, vector or matrix type";
     }
@@ -954,7 +963,7 @@
   const auto pointer_id = inst->GetOperandAs<uint32_t>(pointer_index);
   const auto pointer = _.FindDef(pointer_id);
   if (!pointer ||
-      (_.addressing_model() == SpvAddressingModelLogical &&
+      (_.addressing_model() == spv::AddressingModel::Logical &&
        ((!_.features().variable_pointers &&
          !spvOpcodeReturnsLogicalPointer(pointer->opcode())) ||
         (_.features().variable_pointers &&
@@ -964,14 +973,14 @@
            << " is not a logical pointer.";
   }
   const auto pointer_type = _.FindDef(pointer->type_id());
-  if (!pointer_type || pointer_type->opcode() != SpvOpTypePointer) {
+  if (!pointer_type || pointer_type->opcode() != spv::Op::OpTypePointer) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "OpStore type for pointer <id> " << _.getIdName(pointer_id)
            << " is not a pointer type.";
   }
   const auto type_id = pointer_type->GetOperandAs<uint32_t>(2);
   const auto type = _.FindDef(type_id);
-  if (!type || SpvOpTypeVoid == type->opcode()) {
+  if (!type || spv::Op::OpTypeVoid == type->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "OpStore Pointer <id> " << _.getIdName(pointer_id)
            << "s type is void.";
@@ -980,29 +989,29 @@
   // validate storage class
   {
     uint32_t data_type;
-    uint32_t storage_class;
+    spv::StorageClass storage_class;
     if (!_.GetPointerTypeInfo(pointer_type->id(), &data_type, &storage_class)) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "OpStore Pointer <id> " << _.getIdName(pointer_id)
              << " is not pointer type";
     }
 
-    if (storage_class == SpvStorageClassUniformConstant ||
-        storage_class == SpvStorageClassInput ||
-        storage_class == SpvStorageClassPushConstant) {
+    if (storage_class == spv::StorageClass::UniformConstant ||
+        storage_class == spv::StorageClass::Input ||
+        storage_class == spv::StorageClass::PushConstant) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "OpStore Pointer <id> " << _.getIdName(pointer_id)
              << " storage class is read-only";
-    } else if (storage_class == SpvStorageClassShaderRecordBufferKHR) {
+    } else if (storage_class == spv::StorageClass::ShaderRecordBufferKHR) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "ShaderRecordBufferKHR Storage Class variables are read only";
-    } else if (storage_class == SpvStorageClassHitAttributeKHR) {
+    } else if (storage_class == spv::StorageClass::HitAttributeKHR) {
       std::string errorVUID = _.VkErrorID(4703);
       _.function(inst->function()->id())
           ->RegisterExecutionModelLimitation(
-              [errorVUID](SpvExecutionModel model, std::string* message) {
-                if (model == SpvExecutionModelAnyHitKHR ||
-                    model == SpvExecutionModelClosestHitKHR) {
+              [errorVUID](spv::ExecutionModel model, std::string* message) {
+                if (model == spv::ExecutionModel::AnyHitKHR ||
+                    model == spv::ExecutionModel::ClosestHitKHR) {
                   if (message) {
                     *message =
                         errorVUID +
@@ -1016,18 +1025,18 @@
     }
 
     if (spvIsVulkanEnv(_.context()->target_env) &&
-        storage_class == SpvStorageClassUniform) {
+        storage_class == spv::StorageClass::Uniform) {
       auto base_ptr = _.TracePointer(pointer);
-      if (base_ptr->opcode() == SpvOpVariable) {
+      if (base_ptr->opcode() == spv::Op::OpVariable) {
         // If it's not a variable a different check should catch the problem.
         auto base_type = _.FindDef(base_ptr->GetOperandAs<uint32_t>(0));
         // Get the pointed-to type.
         base_type = _.FindDef(base_type->GetOperandAs<uint32_t>(2u));
-        if (base_type->opcode() == SpvOpTypeArray ||
-            base_type->opcode() == SpvOpTypeRuntimeArray) {
+        if (base_type->opcode() == spv::Op::OpTypeArray ||
+            base_type->opcode() == spv::Op::OpTypeRuntimeArray) {
           base_type = _.FindDef(base_type->GetOperandAs<uint32_t>(1u));
         }
-        if (_.HasDecoration(base_type->id(), SpvDecorationBlock)) {
+        if (_.HasDecoration(base_type->id(), spv::Decoration::Block)) {
           return _.diag(SPV_ERROR_INVALID_ID, inst)
                  << _.VkErrorID(6925)
                  << "In the Vulkan environment, cannot store to Uniform Blocks";
@@ -1045,15 +1054,16 @@
            << " is not an object.";
   }
   const auto object_type = _.FindDef(object->type_id());
-  if (!object_type || SpvOpTypeVoid == object_type->opcode()) {
+  if (!object_type || spv::Op::OpTypeVoid == object_type->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "OpStore Object <id> " << _.getIdName(object_id)
            << "s type is void.";
   }
 
   if (type->id() != object_type->id()) {
-    if (!_.options()->relax_struct_store || type->opcode() != SpvOpTypeStruct ||
-        object_type->opcode() != SpvOpTypeStruct) {
+    if (!_.options()->relax_struct_store ||
+        type->opcode() != spv::Op::OpTypeStruct ||
+        object_type->opcode() != spv::Op::OpTypeStruct) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "OpStore Pointer <id> " << _.getIdName(pointer_id)
              << "s type does not match Object <id> "
@@ -1071,13 +1081,13 @@
 
   if (auto error = CheckMemoryAccess(_, inst, 2)) return error;
 
-  if (_.HasCapability(SpvCapabilityShader) &&
+  if (_.HasCapability(spv::Capability::Shader) &&
       _.ContainsLimitedUseIntOrFloatType(inst->type_id()) &&
-      object_type->opcode() != SpvOpTypePointer) {
-    if (object_type->opcode() != SpvOpTypeInt &&
-        object_type->opcode() != SpvOpTypeFloat &&
-        object_type->opcode() != SpvOpTypeVector &&
-        object_type->opcode() != SpvOpTypeMatrix) {
+      object_type->opcode() != spv::Op::OpTypePointer) {
+    if (object_type->opcode() != spv::Op::OpTypeInt &&
+        object_type->opcode() != spv::Op::OpTypeFloat &&
+        object_type->opcode() != spv::Op::OpTypeVector &&
+        object_type->opcode() != spv::Op::OpTypeMatrix) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "8- or 16-bit stores must be a scalar, vector or matrix type";
     }
@@ -1088,9 +1098,10 @@
 
 spv_result_t ValidateCopyMemoryMemoryAccess(ValidationState_t& _,
                                             const Instruction* inst) {
-  assert(inst->opcode() == SpvOpCopyMemory ||
-         inst->opcode() == SpvOpCopyMemorySized);
-  const uint32_t first_access_index = inst->opcode() == SpvOpCopyMemory ? 2 : 3;
+  assert(inst->opcode() == spv::Op::OpCopyMemory ||
+         inst->opcode() == spv::Op::OpCopyMemorySized);
+  const uint32_t first_access_index =
+      inst->opcode() == spv::Op::OpCopyMemory ? 2 : 3;
   if (inst->operands().size() > first_access_index) {
     if (auto error = CheckMemoryAccess(_, inst, first_access_index))
       return error;
@@ -1108,21 +1119,23 @@
         //  make-visible.
         //  - the second is the source (read) access and it can't have
         //  make-available.
-        if (first_access & SpvMemoryAccessMakePointerVisibleKHRMask) {
+        if (first_access &
+            uint32_t(spv::MemoryAccessMask::MakePointerVisibleKHR)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << "Target memory access must not include "
                     "MakePointerVisibleKHR";
         }
         const auto second_access =
             inst->GetOperandAs<uint32_t>(second_access_index);
-        if (second_access & SpvMemoryAccessMakePointerAvailableKHRMask) {
+        if (second_access &
+            uint32_t(spv::MemoryAccessMask::MakePointerAvailableKHR)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << "Source memory access must not include "
                     "MakePointerAvailableKHR";
         }
       } else {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
-               << spvOpcodeString(static_cast<SpvOp>(inst->opcode()))
+               << spvOpcodeString(static_cast<spv::Op>(inst->opcode()))
                << " with two memory access operands requires SPIR-V 1.4 or "
                   "later";
       }
@@ -1152,7 +1165,7 @@
 
   const auto target_pointer_type = _.FindDef(target->type_id());
   if (!target_pointer_type ||
-      target_pointer_type->opcode() != SpvOpTypePointer) {
+      target_pointer_type->opcode() != spv::Op::OpTypePointer) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Target operand <id> " << _.getIdName(target_id)
            << " is not a pointer.";
@@ -1160,16 +1173,16 @@
 
   const auto source_pointer_type = _.FindDef(source->type_id());
   if (!source_pointer_type ||
-      source_pointer_type->opcode() != SpvOpTypePointer) {
+      source_pointer_type->opcode() != spv::Op::OpTypePointer) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Source operand <id> " << _.getIdName(source_id)
            << " is not a pointer.";
   }
 
-  if (inst->opcode() == SpvOpCopyMemory) {
+  if (inst->opcode() == spv::Op::OpCopyMemory) {
     const auto target_type =
         _.FindDef(target_pointer_type->GetOperandAs<uint32_t>(2));
-    if (!target_type || target_type->opcode() == SpvOpTypeVoid) {
+    if (!target_type || target_type->opcode() == spv::Op::OpTypeVoid) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "Target operand <id> " << _.getIdName(target_id)
              << " cannot be a void pointer.";
@@ -1177,7 +1190,7 @@
 
     const auto source_type =
         _.FindDef(source_pointer_type->GetOperandAs<uint32_t>(2));
-    if (!source_type || source_type->opcode() == SpvOpTypeVoid) {
+    if (!source_type || source_type->opcode() == spv::Op::OpTypeVoid) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "Source operand <id> " << _.getIdName(source_id)
              << " cannot be a void pointer.";
@@ -1207,11 +1220,11 @@
 
     bool is_zero = true;
     switch (size->opcode()) {
-      case SpvOpConstantNull:
+      case spv::Op::OpConstantNull:
         return _.diag(SPV_ERROR_INVALID_ID, inst)
                << "Size operand <id> " << _.getIdName(size_id)
                << " cannot be a constant zero.";
-      case SpvOpConstant:
+      case spv::Op::OpConstant:
         if (size_type->word(3) == 1 &&
             size->word(size->words().size() - 1) & 0x80000000) {
           return _.diag(SPV_ERROR_INVALID_ID, inst)
@@ -1236,10 +1249,10 @@
 
   // Get past the pointers to avoid checking a pointer copy.
   auto sub_type = _.FindDef(target_pointer_type->GetOperandAs<uint32_t>(2));
-  while (sub_type->opcode() == SpvOpTypePointer) {
+  while (sub_type->opcode() == spv::Op::OpTypePointer) {
     sub_type = _.FindDef(sub_type->GetOperandAs<uint32_t>(2));
   }
-  if (_.HasCapability(SpvCapabilityShader) &&
+  if (_.HasCapability(spv::Capability::Shader) &&
       _.ContainsLimitedUseIntOrFloatType(sub_type->id())) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Cannot copy memory of objects containing 8- or 16-bit types";
@@ -1251,15 +1264,16 @@
 spv_result_t ValidateAccessChain(ValidationState_t& _,
                                  const Instruction* inst) {
   std::string instr_name =
-      "Op" + std::string(spvOpcodeString(static_cast<SpvOp>(inst->opcode())));
+      "Op" + std::string(spvOpcodeString(static_cast<spv::Op>(inst->opcode())));
 
   // The result type must be OpTypePointer.
   auto result_type = _.FindDef(inst->type_id());
-  if (SpvOpTypePointer != result_type->opcode()) {
+  if (spv::Op::OpTypePointer != result_type->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "The Result Type of " << instr_name << " <id> "
            << _.getIdName(inst->id()) << " must be OpTypePointer. Found Op"
-           << spvOpcodeString(static_cast<SpvOp>(result_type->opcode())) << ".";
+           << spvOpcodeString(static_cast<spv::Op>(result_type->opcode()))
+           << ".";
   }
 
   // Result type is a pointer. Find out what it's pointing to.
@@ -1272,7 +1286,7 @@
   const auto base_id = inst->GetOperandAs<uint32_t>(base_index);
   const auto base = _.FindDef(base_id);
   const auto base_type = _.FindDef(base->type_id());
-  if (!base_type || SpvOpTypePointer != base_type->opcode()) {
+  if (!base_type || spv::Op::OpTypePointer != base_type->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "The Base <id> " << _.getIdName(base_id) << " in " << instr_name
            << " instruction must be a pointer.";
@@ -1296,8 +1310,8 @@
   // The number of indexes passed to OpAccessChain may not exceed 255
   // The instruction includes 4 words + N words (for N indexes)
   size_t num_indexes = inst->words().size() - 4;
-  if (inst->opcode() == SpvOpPtrAccessChain ||
-      inst->opcode() == SpvOpInBoundsPtrAccessChain) {
+  if (inst->opcode() == spv::Op::OpPtrAccessChain ||
+      inst->opcode() == spv::Op::OpInBoundsPtrAccessChain) {
     // In pointer access chains, the element operand is required, but not
     // counted as an index.
     --num_indexes;
@@ -1317,8 +1331,8 @@
   // on. Once any non-composite type is reached, there must be no remaining
   // (unused) indexes.
   auto starting_index = 4;
-  if (inst->opcode() == SpvOpPtrAccessChain ||
-      inst->opcode() == SpvOpInBoundsPtrAccessChain) {
+  if (inst->opcode() == spv::Op::OpPtrAccessChain ||
+      inst->opcode() == spv::Op::OpInBoundsPtrAccessChain) {
     ++starting_index;
   }
   for (size_t i = starting_index; i < inst->words().size(); ++i) {
@@ -1327,26 +1341,26 @@
     auto cur_word_instr = _.FindDef(cur_word);
     // The index must be a scalar integer type (See OpAccessChain in the Spec.)
     auto index_type = _.FindDef(cur_word_instr->type_id());
-    if (!index_type || SpvOpTypeInt != index_type->opcode()) {
+    if (!index_type || spv::Op::OpTypeInt != index_type->opcode()) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "Indexes passed to " << instr_name
              << " must be of type integer.";
     }
     switch (type_pointee->opcode()) {
-      case SpvOpTypeMatrix:
-      case SpvOpTypeVector:
-      case SpvOpTypeCooperativeMatrixNV:
-      case SpvOpTypeArray:
-      case SpvOpTypeRuntimeArray: {
-        // In OpTypeMatrix, OpTypeVector, SpvOpTypeCooperativeMatrixNV,
+      case spv::Op::OpTypeMatrix:
+      case spv::Op::OpTypeVector:
+      case spv::Op::OpTypeCooperativeMatrixNV:
+      case spv::Op::OpTypeArray:
+      case spv::Op::OpTypeRuntimeArray: {
+        // In OpTypeMatrix, OpTypeVector, spv::Op::OpTypeCooperativeMatrixNV,
         // OpTypeArray, and OpTypeRuntimeArray, word 2 is the Element Type.
         type_pointee = _.FindDef(type_pointee->word(2));
         break;
       }
-      case SpvOpTypeStruct: {
+      case spv::Op::OpTypeStruct: {
         // In case of structures, there is an additional constraint on the
         // index: the index must be an OpConstant.
-        if (SpvOpConstant != cur_word_instr->opcode()) {
+        if (spv::Op::OpConstant != cur_word_instr->opcode()) {
           return _.diag(SPV_ERROR_INVALID_ID, cur_word_instr)
                  << "The <id> passed to " << instr_name
                  << " to index into a "
@@ -1390,11 +1404,12 @@
   if (type_pointee->id() != result_type_pointee->id()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << instr_name << " result type (Op"
-           << spvOpcodeString(static_cast<SpvOp>(result_type_pointee->opcode()))
+           << spvOpcodeString(
+                  static_cast<spv::Op>(result_type_pointee->opcode()))
            << ") does not match the type that results from indexing into the "
               "base "
               "<id> (Op"
-           << spvOpcodeString(static_cast<SpvOp>(type_pointee->opcode()))
+           << spvOpcodeString(static_cast<spv::Op>(type_pointee->opcode()))
            << ").";
   }
 
@@ -1403,7 +1418,7 @@
 
 spv_result_t ValidatePtrAccessChain(ValidationState_t& _,
                                     const Instruction* inst) {
-  if (_.addressing_model() == SpvAddressingModelLogical) {
+  if (_.addressing_model() == spv::AddressingModel::Logical) {
     if (!_.features().variable_pointers) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Generating variable pointers requires capability "
@@ -1417,30 +1432,31 @@
   const auto base_id = inst->GetOperandAs<uint32_t>(2);
   const auto base = _.FindDef(base_id);
   const auto base_type = _.FindDef(base->type_id());
-  const auto base_type_storage_class = base_type->word(2);
+  const auto base_type_storage_class =
+      base_type->GetOperandAs<spv::StorageClass>(1);
 
-  if (_.HasCapability(SpvCapabilityShader) &&
-      (base_type_storage_class == SpvStorageClassUniform ||
-       base_type_storage_class == SpvStorageClassStorageBuffer ||
-       base_type_storage_class == SpvStorageClassPhysicalStorageBuffer ||
-       base_type_storage_class == SpvStorageClassPushConstant ||
-       (_.HasCapability(SpvCapabilityWorkgroupMemoryExplicitLayoutKHR) &&
-        base_type_storage_class == SpvStorageClassWorkgroup)) &&
-      !_.HasDecoration(base_type->id(), SpvDecorationArrayStride)) {
+  if (_.HasCapability(spv::Capability::Shader) &&
+      (base_type_storage_class == spv::StorageClass::Uniform ||
+       base_type_storage_class == spv::StorageClass::StorageBuffer ||
+       base_type_storage_class == spv::StorageClass::PhysicalStorageBuffer ||
+       base_type_storage_class == spv::StorageClass::PushConstant ||
+       (_.HasCapability(spv::Capability::WorkgroupMemoryExplicitLayoutKHR) &&
+        base_type_storage_class == spv::StorageClass::Workgroup)) &&
+      !_.HasDecoration(base_type->id(), spv::Decoration::ArrayStride)) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "OpPtrAccessChain must have a Base whose type is decorated "
               "with ArrayStride";
   }
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    if (base_type_storage_class == SpvStorageClassWorkgroup) {
-      if (!_.HasCapability(SpvCapabilityVariablePointers)) {
+    if (base_type_storage_class == spv::StorageClass::Workgroup) {
+      if (!_.HasCapability(spv::Capability::VariablePointers)) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << _.VkErrorID(7651)
                << "OpPtrAccessChain Base operand pointing to Workgroup "
                   "storage class must use VariablePointers capability";
       }
-    } else if (base_type_storage_class == SpvStorageClassStorageBuffer) {
+    } else if (base_type_storage_class == spv::StorageClass::StorageBuffer) {
       if (!_.features().variable_pointers) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << _.VkErrorID(7652)
@@ -1449,7 +1465,7 @@
                   "VariablePointersStorageBuffer capability";
       }
     } else if (base_type_storage_class !=
-               SpvStorageClassPhysicalStorageBuffer) {
+               spv::StorageClass::PhysicalStorageBuffer) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << _.VkErrorID(7650)
              << "OpPtrAccessChain Base operand must point to Workgroup, "
@@ -1463,11 +1479,11 @@
 spv_result_t ValidateArrayLength(ValidationState_t& state,
                                  const Instruction* inst) {
   std::string instr_name =
-      "Op" + std::string(spvOpcodeString(static_cast<SpvOp>(inst->opcode())));
+      "Op" + std::string(spvOpcodeString(static_cast<spv::Op>(inst->opcode())));
 
   // Result type must be a 32-bit unsigned int.
   auto result_type = state.FindDef(inst->type_id());
-  if (result_type->opcode() != SpvOpTypeInt ||
+  if (result_type->opcode() != spv::Op::OpTypeInt ||
       result_type->GetOperandAs<uint32_t>(1) != 32 ||
       result_type->GetOperandAs<uint32_t>(2) != 0) {
     return state.diag(SPV_ERROR_INVALID_ID, inst)
@@ -1480,7 +1496,7 @@
   // last element is a runtime array.
   auto pointer = state.FindDef(inst->GetOperandAs<uint32_t>(2));
   auto pointer_type = state.FindDef(pointer->type_id());
-  if (pointer_type->opcode() != SpvOpTypePointer) {
+  if (pointer_type->opcode() != spv::Op::OpTypePointer) {
     return state.diag(SPV_ERROR_INVALID_ID, inst)
            << "The Structure's type in " << instr_name << " <id> "
            << state.getIdName(inst->id())
@@ -1488,7 +1504,7 @@
   }
 
   auto structure_type = state.FindDef(pointer_type->GetOperandAs<uint32_t>(2));
-  if (structure_type->opcode() != SpvOpTypeStruct) {
+  if (structure_type->opcode() != spv::Op::OpTypeStruct) {
     return state.diag(SPV_ERROR_INVALID_ID, inst)
            << "The Structure's type in " << instr_name << " <id> "
            << state.getIdName(inst->id())
@@ -1498,7 +1514,7 @@
   auto num_of_members = structure_type->operands().size() - 1;
   auto last_member =
       state.FindDef(structure_type->GetOperandAs<uint32_t>(num_of_members));
-  if (last_member->opcode() != SpvOpTypeRuntimeArray) {
+  if (last_member->opcode() != spv::Op::OpTypeRuntimeArray) {
     return state.diag(SPV_ERROR_INVALID_ID, inst)
            << "The Structure's last member in " << instr_name << " <id> "
            << state.getIdName(inst->id()) << " must be an OpTypeRuntimeArray.";
@@ -1518,11 +1534,11 @@
 spv_result_t ValidateCooperativeMatrixLengthNV(ValidationState_t& state,
                                                const Instruction* inst) {
   std::string instr_name =
-      "Op" + std::string(spvOpcodeString(static_cast<SpvOp>(inst->opcode())));
+      "Op" + std::string(spvOpcodeString(static_cast<spv::Op>(inst->opcode())));
 
   // Result type must be a 32-bit unsigned int.
   auto result_type = state.FindDef(inst->type_id());
-  if (result_type->opcode() != SpvOpTypeInt ||
+  if (result_type->opcode() != spv::Op::OpTypeInt ||
       result_type->GetOperandAs<uint32_t>(1) != 32 ||
       result_type->GetOperandAs<uint32_t>(2) != 0) {
     return state.diag(SPV_ERROR_INVALID_ID, inst)
@@ -1533,7 +1549,7 @@
 
   auto type_id = inst->GetOperandAs<uint32_t>(2);
   auto type = state.FindDef(type_id);
-  if (type->opcode() != SpvOpTypeCooperativeMatrixNV) {
+  if (type->opcode() != spv::Op::OpTypeCooperativeMatrixNV) {
     return state.diag(SPV_ERROR_INVALID_ID, inst)
            << "The type in " << instr_name << " <id> "
            << state.getIdName(type_id) << " must be OpTypeCooperativeMatrixNV.";
@@ -1545,35 +1561,35 @@
                                                   const Instruction* inst) {
   uint32_t type_id;
   const char* opname;
-  if (inst->opcode() == SpvOpCooperativeMatrixLoadNV) {
+  if (inst->opcode() == spv::Op::OpCooperativeMatrixLoadNV) {
     type_id = inst->type_id();
-    opname = "SpvOpCooperativeMatrixLoadNV";
+    opname = "spv::Op::OpCooperativeMatrixLoadNV";
   } else {
     // get Object operand's type
     type_id = _.FindDef(inst->GetOperandAs<uint32_t>(1))->type_id();
-    opname = "SpvOpCooperativeMatrixStoreNV";
+    opname = "spv::Op::OpCooperativeMatrixStoreNV";
   }
 
   auto matrix_type = _.FindDef(type_id);
 
-  if (matrix_type->opcode() != SpvOpTypeCooperativeMatrixNV) {
-    if (inst->opcode() == SpvOpCooperativeMatrixLoadNV) {
+  if (matrix_type->opcode() != spv::Op::OpTypeCooperativeMatrixNV) {
+    if (inst->opcode() == spv::Op::OpCooperativeMatrixLoadNV) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << "SpvOpCooperativeMatrixLoadNV Result Type <id> "
+             << "spv::Op::OpCooperativeMatrixLoadNV Result Type <id> "
              << _.getIdName(type_id) << " is not a cooperative matrix type.";
     } else {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
-             << "SpvOpCooperativeMatrixStoreNV Object type <id> "
+             << "spv::Op::OpCooperativeMatrixStoreNV Object type <id> "
              << _.getIdName(type_id) << " is not a cooperative matrix type.";
     }
   }
 
   const auto pointer_index =
-      (inst->opcode() == SpvOpCooperativeMatrixLoadNV) ? 2u : 0u;
+      (inst->opcode() == spv::Op::OpCooperativeMatrixLoadNV) ? 2u : 0u;
   const auto pointer_id = inst->GetOperandAs<uint32_t>(pointer_index);
   const auto pointer = _.FindDef(pointer_id);
   if (!pointer ||
-      ((_.addressing_model() == SpvAddressingModelLogical) &&
+      ((_.addressing_model() == spv::AddressingModel::Logical) &&
        ((!_.features().variable_pointers &&
          !spvOpcodeReturnsLogicalPointer(pointer->opcode())) ||
         (_.features().variable_pointers &&
@@ -1585,7 +1601,7 @@
 
   const auto pointer_type_id = pointer->type_id();
   const auto pointer_type = _.FindDef(pointer_type_id);
-  if (!pointer_type || pointer_type->opcode() != SpvOpTypePointer) {
+  if (!pointer_type || pointer_type->opcode() != spv::Op::OpTypePointer) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << opname << " type for pointer <id> " << _.getIdName(pointer_id)
            << " is not a pointer type.";
@@ -1593,11 +1609,11 @@
 
   const auto storage_class_index = 1u;
   const auto storage_class =
-      pointer_type->GetOperandAs<uint32_t>(storage_class_index);
+      pointer_type->GetOperandAs<spv::StorageClass>(storage_class_index);
 
-  if (storage_class != SpvStorageClassWorkgroup &&
-      storage_class != SpvStorageClassStorageBuffer &&
-      storage_class != SpvStorageClassPhysicalStorageBuffer) {
+  if (storage_class != spv::StorageClass::Workgroup &&
+      storage_class != spv::StorageClass::StorageBuffer &&
+      storage_class != spv::StorageClass::PhysicalStorageBuffer) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << opname << " storage class for pointer type <id> "
            << _.getIdName(pointer_type_id)
@@ -1614,7 +1630,7 @@
   }
 
   const auto stride_index =
-      (inst->opcode() == SpvOpCooperativeMatrixLoadNV) ? 3u : 2u;
+      (inst->opcode() == spv::Op::OpCooperativeMatrixLoadNV) ? 3u : 2u;
   const auto stride_id = inst->GetOperandAs<uint32_t>(stride_index);
   const auto stride = _.FindDef(stride_id);
   if (!stride || !_.IsIntScalarType(stride->type_id())) {
@@ -1624,7 +1640,7 @@
   }
 
   const auto colmajor_index =
-      (inst->opcode() == SpvOpCooperativeMatrixLoadNV) ? 4u : 3u;
+      (inst->opcode() == spv::Op::OpCooperativeMatrixLoadNV) ? 4u : 3u;
   const auto colmajor_id = inst->GetOperandAs<uint32_t>(colmajor_index);
   const auto colmajor = _.FindDef(colmajor_id);
   if (!colmajor || !_.IsBoolScalarType(colmajor->type_id()) ||
@@ -1636,7 +1652,7 @@
   }
 
   const auto memory_access_index =
-      (inst->opcode() == SpvOpCooperativeMatrixLoadNV) ? 5u : 4u;
+      (inst->opcode() == spv::Op::OpCooperativeMatrixLoadNV) ? 5u : 4u;
   if (inst->operands().size() > memory_access_index) {
     if (auto error = CheckMemoryAccess(_, inst, memory_access_index))
       return error;
@@ -1647,7 +1663,7 @@
 
 spv_result_t ValidatePtrComparison(ValidationState_t& _,
                                    const Instruction* inst) {
-  if (_.addressing_model() == SpvAddressingModelLogical &&
+  if (_.addressing_model() == spv::AddressingModel::Logical &&
       !_.features().variable_pointers) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Instruction cannot for logical addressing model be used without "
@@ -1655,13 +1671,13 @@
   }
 
   const auto result_type = _.FindDef(inst->type_id());
-  if (inst->opcode() == SpvOpPtrDiff) {
-    if (!result_type || result_type->opcode() != SpvOpTypeInt) {
+  if (inst->opcode() == spv::Op::OpPtrDiff) {
+    if (!result_type || result_type->opcode() != spv::Op::OpTypeInt) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "Result Type must be an integer scalar";
     }
   } else {
-    if (!result_type || result_type->opcode() != SpvOpTypeBool) {
+    if (!result_type || result_type->opcode() != spv::Op::OpTypeBool) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "Result Type must be OpTypeBool";
     }
@@ -1674,25 +1690,26 @@
            << "The types of Operand 1 and Operand 2 must match";
   }
   const auto op1_type = _.FindDef(op1->type_id());
-  if (!op1_type || op1_type->opcode() != SpvOpTypePointer) {
+  if (!op1_type || op1_type->opcode() != spv::Op::OpTypePointer) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Operand type must be a pointer";
   }
 
-  SpvStorageClass sc = op1_type->GetOperandAs<SpvStorageClass>(1u);
-  if (_.addressing_model() == SpvAddressingModelLogical) {
-    if (sc != SpvStorageClassWorkgroup && sc != SpvStorageClassStorageBuffer) {
+  spv::StorageClass sc = op1_type->GetOperandAs<spv::StorageClass>(1u);
+  if (_.addressing_model() == spv::AddressingModel::Logical) {
+    if (sc != spv::StorageClass::Workgroup &&
+        sc != spv::StorageClass::StorageBuffer) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "Invalid pointer storage class";
     }
 
-    if (sc == SpvStorageClassWorkgroup &&
-        !_.HasCapability(SpvCapabilityVariablePointers)) {
+    if (sc == spv::StorageClass::Workgroup &&
+        !_.HasCapability(spv::Capability::VariablePointers)) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "Workgroup storage class pointer requires VariablePointers "
                 "capability to be specified";
     }
-  } else if (sc == SpvStorageClassPhysicalStorageBuffer) {
+  } else if (sc == spv::StorageClass::PhysicalStorageBuffer) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Cannot use a pointer in the PhysicalStorageBuffer storage class";
   }
@@ -1704,45 +1721,45 @@
 
 spv_result_t MemoryPass(ValidationState_t& _, const Instruction* inst) {
   switch (inst->opcode()) {
-    case SpvOpVariable:
+    case spv::Op::OpVariable:
       if (auto error = ValidateVariable(_, inst)) return error;
       break;
-    case SpvOpLoad:
+    case spv::Op::OpLoad:
       if (auto error = ValidateLoad(_, inst)) return error;
       break;
-    case SpvOpStore:
+    case spv::Op::OpStore:
       if (auto error = ValidateStore(_, inst)) return error;
       break;
-    case SpvOpCopyMemory:
-    case SpvOpCopyMemorySized:
+    case spv::Op::OpCopyMemory:
+    case spv::Op::OpCopyMemorySized:
       if (auto error = ValidateCopyMemory(_, inst)) return error;
       break;
-    case SpvOpPtrAccessChain:
+    case spv::Op::OpPtrAccessChain:
       if (auto error = ValidatePtrAccessChain(_, inst)) return error;
       break;
-    case SpvOpAccessChain:
-    case SpvOpInBoundsAccessChain:
-    case SpvOpInBoundsPtrAccessChain:
+    case spv::Op::OpAccessChain:
+    case spv::Op::OpInBoundsAccessChain:
+    case spv::Op::OpInBoundsPtrAccessChain:
       if (auto error = ValidateAccessChain(_, inst)) return error;
       break;
-    case SpvOpArrayLength:
+    case spv::Op::OpArrayLength:
       if (auto error = ValidateArrayLength(_, inst)) return error;
       break;
-    case SpvOpCooperativeMatrixLoadNV:
-    case SpvOpCooperativeMatrixStoreNV:
+    case spv::Op::OpCooperativeMatrixLoadNV:
+    case spv::Op::OpCooperativeMatrixStoreNV:
       if (auto error = ValidateCooperativeMatrixLoadStoreNV(_, inst))
         return error;
       break;
-    case SpvOpCooperativeMatrixLengthNV:
+    case spv::Op::OpCooperativeMatrixLengthNV:
       if (auto error = ValidateCooperativeMatrixLengthNV(_, inst)) return error;
       break;
-    case SpvOpPtrEqual:
-    case SpvOpPtrNotEqual:
-    case SpvOpPtrDiff:
+    case spv::Op::OpPtrEqual:
+    case spv::Op::OpPtrNotEqual:
+    case spv::Op::OpPtrDiff:
       if (auto error = ValidatePtrComparison(_, inst)) return error;
       break;
-    case SpvOpImageTexelPointer:
-    case SpvOpGenericPtrMemSemantics:
+    case spv::Op::OpImageTexelPointer:
+    case spv::Op::OpGenericPtrMemSemantics:
     default:
       break;
   }
diff --git a/source/val/validate_memory_semantics.cpp b/source/val/validate_memory_semantics.cpp
index d918931..748b238 100644
--- a/source/val/validate_memory_semantics.cpp
+++ b/source/val/validate_memory_semantics.cpp
@@ -27,7 +27,7 @@
                                      const Instruction* inst,
                                      uint32_t operand_index,
                                      uint32_t memory_scope) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   const auto id = inst->GetOperandAs<const uint32_t>(operand_index);
   bool is_int32 = false, is_const_int32 = false;
   uint32_t value = 0;
@@ -40,15 +40,15 @@
   }
 
   if (!is_const_int32) {
-    if (_.HasCapability(SpvCapabilityShader) &&
-        !_.HasCapability(SpvCapabilityCooperativeMatrixNV)) {
+    if (_.HasCapability(spv::Capability::Shader) &&
+        !_.HasCapability(spv::Capability::CooperativeMatrixNV)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Memory Semantics ids must be OpConstant when Shader "
                 "capability is present";
     }
 
-    if (_.HasCapability(SpvCapabilityShader) &&
-        _.HasCapability(SpvCapabilityCooperativeMatrixNV) &&
+    if (_.HasCapability(spv::Capability::Shader) &&
+        _.HasCapability(spv::Capability::CooperativeMatrixNV) &&
         !spvOpcodeIsConstant(_.GetIdOpcode(id))) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Memory Semantics must be a constant instruction when "
@@ -58,9 +58,10 @@
   }
 
   const size_t num_memory_order_set_bits = spvtools::utils::CountSetBits(
-      value & (SpvMemorySemanticsAcquireMask | SpvMemorySemanticsReleaseMask |
-               SpvMemorySemanticsAcquireReleaseMask |
-               SpvMemorySemanticsSequentiallyConsistentMask));
+      value & uint32_t(spv::MemorySemanticsMask::Acquire |
+                       spv::MemorySemanticsMask::Release |
+                       spv::MemorySemanticsMask::AcquireRelease |
+                       spv::MemorySemanticsMask::SequentiallyConsistent));
 
   if (num_memory_order_set_bits > 1) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -71,40 +72,40 @@
               "SequentiallyConsistent";
   }
 
-  if (_.memory_model() == SpvMemoryModelVulkanKHR &&
-      value & SpvMemorySemanticsSequentiallyConsistentMask) {
+  if (_.memory_model() == spv::MemoryModel::VulkanKHR &&
+      value & uint32_t(spv::MemorySemanticsMask::SequentiallyConsistent)) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "SequentiallyConsistent memory "
               "semantics cannot be used with "
               "the VulkanKHR memory model.";
   }
 
-  if (value & SpvMemorySemanticsMakeAvailableKHRMask &&
-      !_.HasCapability(SpvCapabilityVulkanMemoryModelKHR)) {
+  if (value & uint32_t(spv::MemorySemanticsMask::MakeAvailableKHR) &&
+      !_.HasCapability(spv::Capability::VulkanMemoryModelKHR)) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << spvOpcodeString(opcode)
            << ": Memory Semantics MakeAvailableKHR requires capability "
            << "VulkanMemoryModelKHR";
   }
 
-  if (value & SpvMemorySemanticsMakeVisibleKHRMask &&
-      !_.HasCapability(SpvCapabilityVulkanMemoryModelKHR)) {
+  if (value & uint32_t(spv::MemorySemanticsMask::MakeVisibleKHR) &&
+      !_.HasCapability(spv::Capability::VulkanMemoryModelKHR)) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << spvOpcodeString(opcode)
            << ": Memory Semantics MakeVisibleKHR requires capability "
            << "VulkanMemoryModelKHR";
   }
 
-  if (value & SpvMemorySemanticsOutputMemoryKHRMask &&
-      !_.HasCapability(SpvCapabilityVulkanMemoryModelKHR)) {
+  if (value & uint32_t(spv::MemorySemanticsMask::OutputMemoryKHR) &&
+      !_.HasCapability(spv::Capability::VulkanMemoryModelKHR)) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << spvOpcodeString(opcode)
            << ": Memory Semantics OutputMemoryKHR requires capability "
            << "VulkanMemoryModelKHR";
   }
 
-  if (value & SpvMemorySemanticsVolatileMask) {
-    if (!_.HasCapability(SpvCapabilityVulkanMemoryModelKHR)) {
+  if (value & uint32_t(spv::MemorySemanticsMask::Volatile)) {
+    if (!_.HasCapability(spv::Capability::VulkanMemoryModelKHR)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << spvOpcodeString(opcode)
              << ": Memory Semantics Volatile requires capability "
@@ -118,26 +119,27 @@
     }
   }
 
-  if (value & SpvMemorySemanticsUniformMemoryMask &&
-      !_.HasCapability(SpvCapabilityShader)) {
+  if (value & uint32_t(spv::MemorySemanticsMask::UniformMemory) &&
+      !_.HasCapability(spv::Capability::Shader)) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << spvOpcodeString(opcode)
            << ": Memory Semantics UniformMemory requires capability Shader";
   }
 
-  // Checking for SpvCapabilityAtomicStorage is intentionally not done here. See
-  // https://github.com/KhronosGroup/glslang/issues/1618 for the reasoning why.
+  // Checking for spv::Capability::AtomicStorage is intentionally not done here.
+  // See https://github.com/KhronosGroup/glslang/issues/1618 for the reasoning
+  // why.
 
-  if (value & (SpvMemorySemanticsMakeAvailableKHRMask |
-               SpvMemorySemanticsMakeVisibleKHRMask)) {
+  if (value & uint32_t(spv::MemorySemanticsMask::MakeAvailableKHR |
+                       spv::MemorySemanticsMask::MakeVisibleKHR)) {
     const bool includes_storage_class =
-        value & (SpvMemorySemanticsUniformMemoryMask |
-                 SpvMemorySemanticsSubgroupMemoryMask |
-                 SpvMemorySemanticsWorkgroupMemoryMask |
-                 SpvMemorySemanticsCrossWorkgroupMemoryMask |
-                 SpvMemorySemanticsAtomicCounterMemoryMask |
-                 SpvMemorySemanticsImageMemoryMask |
-                 SpvMemorySemanticsOutputMemoryKHRMask);
+        value & uint32_t(spv::MemorySemanticsMask::UniformMemory |
+                         spv::MemorySemanticsMask::SubgroupMemory |
+                         spv::MemorySemanticsMask::WorkgroupMemory |
+                         spv::MemorySemanticsMask::CrossWorkgroupMemory |
+                         spv::MemorySemanticsMask::AtomicCounterMemory |
+                         spv::MemorySemanticsMask::ImageMemory |
+                         spv::MemorySemanticsMask::OutputMemoryKHR);
 
     if (!includes_storage_class) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -146,18 +148,18 @@
     }
   }
 
-  if (value & SpvMemorySemanticsMakeVisibleKHRMask &&
-      !(value & (SpvMemorySemanticsAcquireMask |
-                 SpvMemorySemanticsAcquireReleaseMask))) {
+  if (value & uint32_t(spv::MemorySemanticsMask::MakeVisibleKHR) &&
+      !(value & uint32_t(spv::MemorySemanticsMask::Acquire |
+                         spv::MemorySemanticsMask::AcquireRelease))) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << spvOpcodeString(opcode)
            << ": MakeVisibleKHR Memory Semantics also requires either Acquire "
               "or AcquireRelease Memory Semantics";
   }
 
-  if (value & SpvMemorySemanticsMakeAvailableKHRMask &&
-      !(value & (SpvMemorySemanticsReleaseMask |
-                 SpvMemorySemanticsAcquireReleaseMask))) {
+  if (value & uint32_t(spv::MemorySemanticsMask::MakeAvailableKHR) &&
+      !(value & uint32_t(spv::MemorySemanticsMask::Release |
+                         spv::MemorySemanticsMask::AcquireRelease))) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << spvOpcodeString(opcode)
            << ": MakeAvailableKHR Memory Semantics also requires either "
@@ -166,12 +168,12 @@
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
     const bool includes_storage_class =
-        value & (SpvMemorySemanticsUniformMemoryMask |
-                 SpvMemorySemanticsWorkgroupMemoryMask |
-                 SpvMemorySemanticsImageMemoryMask |
-                 SpvMemorySemanticsOutputMemoryKHRMask);
+        value & uint32_t(spv::MemorySemanticsMask::UniformMemory |
+                         spv::MemorySemanticsMask::WorkgroupMemory |
+                         spv::MemorySemanticsMask::ImageMemory |
+                         spv::MemorySemanticsMask::OutputMemoryKHR);
 
-    if (opcode == SpvOpMemoryBarrier && !num_memory_order_set_bits) {
+    if (opcode == spv::Op::OpMemoryBarrier && !num_memory_order_set_bits) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << _.VkErrorID(4732) << spvOpcodeString(opcode)
              << ": Vulkan specification requires Memory Semantics to have "
@@ -179,13 +181,15 @@
                 "of the following bits set: Acquire, Release, "
                 "AcquireRelease "
                 "or SequentiallyConsistent";
-    } else if (opcode != SpvOpMemoryBarrier && num_memory_order_set_bits) {
+    } else if (opcode != spv::Op::OpMemoryBarrier &&
+               num_memory_order_set_bits) {
       // should leave only atomics and control barriers for Vulkan env
       bool memory_is_int32 = false, memory_is_const_int32 = false;
       uint32_t memory_value = 0;
       std::tie(memory_is_int32, memory_is_const_int32, memory_value) =
           _.EvalInt32IfConst(memory_scope);
-      if (memory_is_int32 && memory_value == SpvScopeInvocation) {
+      if (memory_is_int32 &&
+          spv::Scope(memory_value) == spv::Scope::Invocation) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << _.VkErrorID(4641) << spvOpcodeString(opcode)
                << ": Vulkan specification requires Memory Semantics to be None "
@@ -193,7 +197,7 @@
       }
     }
 
-    if (opcode == SpvOpMemoryBarrier && !includes_storage_class) {
+    if (opcode == spv::Op::OpMemoryBarrier && !includes_storage_class) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << _.VkErrorID(4733) << spvOpcodeString(opcode)
              << ": expected Memory Semantics to include a Vulkan-supported "
@@ -202,7 +206,7 @@
 
 #if 0
     // TODO(atgoo@github.com): this check fails Vulkan CTS, reenable once fixed.
-    if (opcode == SpvOpControlBarrier && value && !includes_storage_class) {
+    if (opcode == spv::Op::OpControlBarrier && value && !includes_storage_class) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << spvOpcodeString(opcode)
              << ": expected Memory Semantics to include a Vulkan-supported "
@@ -211,18 +215,18 @@
 #endif
   }
 
-  if (opcode == SpvOpAtomicFlagClear &&
-      (value & SpvMemorySemanticsAcquireMask ||
-       value & SpvMemorySemanticsAcquireReleaseMask)) {
+  if (opcode == spv::Op::OpAtomicFlagClear &&
+      (value & uint32_t(spv::MemorySemanticsMask::Acquire) ||
+       value & uint32_t(spv::MemorySemanticsMask::AcquireRelease))) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Memory Semantics Acquire and AcquireRelease cannot be used "
               "with "
            << spvOpcodeString(opcode);
   }
 
-  if (opcode == SpvOpAtomicCompareExchange && operand_index == 5 &&
-      (value & SpvMemorySemanticsReleaseMask ||
-       value & SpvMemorySemanticsAcquireReleaseMask)) {
+  if (opcode == spv::Op::OpAtomicCompareExchange && operand_index == 5 &&
+      (value & uint32_t(spv::MemorySemanticsMask::Release) ||
+       value & uint32_t(spv::MemorySemanticsMask::AcquireRelease))) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << spvOpcodeString(opcode)
            << ": Memory Semantics Release and AcquireRelease cannot be "
@@ -231,20 +235,20 @@
   }
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    if (opcode == SpvOpAtomicLoad &&
-        (value & SpvMemorySemanticsReleaseMask ||
-         value & SpvMemorySemanticsAcquireReleaseMask ||
-         value & SpvMemorySemanticsSequentiallyConsistentMask)) {
+    if (opcode == spv::Op::OpAtomicLoad &&
+        (value & uint32_t(spv::MemorySemanticsMask::Release) ||
+         value & uint32_t(spv::MemorySemanticsMask::AcquireRelease) ||
+         value & uint32_t(spv::MemorySemanticsMask::SequentiallyConsistent))) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << _.VkErrorID(4731)
              << "Vulkan spec disallows OpAtomicLoad with Memory Semantics "
                 "Release, AcquireRelease and SequentiallyConsistent";
     }
 
-    if (opcode == SpvOpAtomicStore &&
-        (value & SpvMemorySemanticsAcquireMask ||
-         value & SpvMemorySemanticsAcquireReleaseMask ||
-         value & SpvMemorySemanticsSequentiallyConsistentMask)) {
+    if (opcode == spv::Op::OpAtomicStore &&
+        (value & uint32_t(spv::MemorySemanticsMask::Acquire) ||
+         value & uint32_t(spv::MemorySemanticsMask::AcquireRelease) ||
+         value & uint32_t(spv::MemorySemanticsMask::SequentiallyConsistent))) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << _.VkErrorID(4730)
              << "Vulkan spec disallows OpAtomicStore with Memory Semantics "
diff --git a/source/val/validate_mesh_shading.cpp b/source/val/validate_mesh_shading.cpp
index a7f0726..e569e25 100644
--- a/source/val/validate_mesh_shading.cpp
+++ b/source/val/validate_mesh_shading.cpp
@@ -23,13 +23,13 @@
 namespace val {
 
 spv_result_t MeshShadingPass(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   switch (opcode) {
-    case SpvOpEmitMeshTasksEXT: {
+    case spv::Op::OpEmitMeshTasksEXT: {
       _.function(inst->function()->id())
           ->RegisterExecutionModelLimitation(
-              [](SpvExecutionModel model, std::string* message) {
-                if (model != SpvExecutionModelTaskEXT) {
+              [](spv::ExecutionModel model, std::string* message) {
+                if (model != spv::ExecutionModel::TaskEXT) {
                   if (message) {
                     *message =
                         "OpEmitMeshTasksEXT requires TaskEXT execution model";
@@ -62,12 +62,12 @@
 
       if (inst->operands().size() == 4) {
         const auto payload = _.FindDef(inst->GetOperandAs<uint32_t>(3));
-        if (payload->opcode() != SpvOpVariable) {
+        if (payload->opcode() != spv::Op::OpVariable) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << "Payload must be the result of a OpVariable";
         }
-        if (SpvStorageClass(payload->GetOperandAs<uint32_t>(2)) !=
-            SpvStorageClassTaskPayloadWorkgroupEXT) {
+        if (payload->GetOperandAs<spv::StorageClass>(2) !=
+            spv::StorageClass::TaskPayloadWorkgroupEXT) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << "Payload OpVariable must have a storage class of "
                     "TaskPayloadWorkgroupEXT";
@@ -76,11 +76,11 @@
       break;
     }
 
-    case SpvOpSetMeshOutputsEXT: {
+    case spv::Op::OpSetMeshOutputsEXT: {
       _.function(inst->function()->id())
           ->RegisterExecutionModelLimitation(
-              [](SpvExecutionModel model, std::string* message) {
-                if (model != SpvExecutionModelMeshEXT) {
+              [](spv::ExecutionModel model, std::string* message) {
+                if (model != spv::ExecutionModel::MeshEXT) {
                   if (message) {
                     *message =
                         "OpSetMeshOutputsEXT requires MeshEXT execution model";
@@ -107,7 +107,7 @@
       break;
     }
 
-    case SpvOpWritePackedPrimitiveIndices4x8NV: {
+    case spv::Op::OpWritePackedPrimitiveIndices4x8NV: {
       // No validation rules (for the moment).
       break;
     }
diff --git a/source/val/validate_misc.cpp b/source/val/validate_misc.cpp
index 5acc21e..d71fd2d 100644
--- a/source/val/validate_misc.cpp
+++ b/source/val/validate_misc.cpp
@@ -30,7 +30,7 @@
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Cannot create undefined values with void type";
   }
-  if (_.HasCapability(SpvCapabilityShader) &&
+  if (_.HasCapability(spv::Capability::Shader) &&
       _.ContainsLimitedUseIntOrFloatType(inst->type_id()) &&
       !_.IsPointerType(inst->type_id())) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
@@ -50,7 +50,8 @@
   bool is_int32 = false, is_const_int32 = false;
   uint32_t value = 0;
   std::tie(is_int32, is_const_int32, value) = _.EvalInt32IfConst(scope);
-  if (is_const_int32 && value != SpvScopeSubgroup && value != SpvScopeDevice) {
+  if (is_const_int32 && spv::Scope(value) != spv::Scope::Subgroup &&
+      spv::Scope(value) != spv::Scope::Device) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << _.VkErrorID(4652) << "Scope must be Subgroup or Device";
   }
@@ -104,18 +105,18 @@
 
 spv_result_t MiscPass(ValidationState_t& _, const Instruction* inst) {
   switch (inst->opcode()) {
-    case SpvOpUndef:
+    case spv::Op::OpUndef:
       if (auto error = ValidateUndef(_, inst)) return error;
       break;
     default:
       break;
   }
   switch (inst->opcode()) {
-    case SpvOpBeginInvocationInterlockEXT:
-    case SpvOpEndInvocationInterlockEXT:
+    case spv::Op::OpBeginInvocationInterlockEXT:
+    case spv::Op::OpEndInvocationInterlockEXT:
       _.function(inst->function()->id())
           ->RegisterExecutionModelLimitation(
-              SpvExecutionModelFragment,
+              spv::ExecutionModel::Fragment,
               "OpBeginInvocationInterlockEXT/OpEndInvocationInterlockEXT "
               "require Fragment execution model");
 
@@ -126,14 +127,14 @@
             const auto* execution_modes =
                 state.GetExecutionModes(entry_point->id());
 
-            auto find_interlock = [](const SpvExecutionMode& mode) {
+            auto find_interlock = [](const spv::ExecutionMode& mode) {
               switch (mode) {
-                case SpvExecutionModePixelInterlockOrderedEXT:
-                case SpvExecutionModePixelInterlockUnorderedEXT:
-                case SpvExecutionModeSampleInterlockOrderedEXT:
-                case SpvExecutionModeSampleInterlockUnorderedEXT:
-                case SpvExecutionModeShadingRateInterlockOrderedEXT:
-                case SpvExecutionModeShadingRateInterlockUnorderedEXT:
+                case spv::ExecutionMode::PixelInterlockOrderedEXT:
+                case spv::ExecutionMode::PixelInterlockUnorderedEXT:
+                case spv::ExecutionMode::SampleInterlockOrderedEXT:
+                case spv::ExecutionMode::SampleInterlockUnorderedEXT:
+                case spv::ExecutionMode::ShadingRateInterlockOrderedEXT:
+                case spv::ExecutionMode::ShadingRateInterlockUnorderedEXT:
                   return true;
                 default:
                   return false;
@@ -156,18 +157,18 @@
             return true;
           });
       break;
-    case SpvOpDemoteToHelperInvocationEXT:
+    case spv::Op::OpDemoteToHelperInvocationEXT:
       _.function(inst->function()->id())
           ->RegisterExecutionModelLimitation(
-              SpvExecutionModelFragment,
+              spv::ExecutionModel::Fragment,
               "OpDemoteToHelperInvocationEXT requires Fragment execution "
               "model");
       break;
-    case SpvOpIsHelperInvocationEXT: {
+    case spv::Op::OpIsHelperInvocationEXT: {
       const uint32_t result_type = inst->type_id();
       _.function(inst->function()->id())
           ->RegisterExecutionModelLimitation(
-              SpvExecutionModelFragment,
+              spv::ExecutionModel::Fragment,
               "OpIsHelperInvocationEXT requires Fragment execution model");
       if (!_.IsBoolScalarType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -175,17 +176,17 @@
                << spvOpcodeString(inst->opcode());
       break;
     }
-    case SpvOpReadClockKHR:
+    case spv::Op::OpReadClockKHR:
       if (auto error = ValidateShaderClock(_, inst)) {
         return error;
       }
       break;
-    case SpvOpAssumeTrueKHR:
+    case spv::Op::OpAssumeTrueKHR:
       if (auto error = ValidateAssumeTrue(_, inst)) {
         return error;
       }
       break;
-    case SpvOpExpectKHR:
+    case spv::Op::OpExpectKHR:
       if (auto error = ValidateExpect(_, inst)) {
         return error;
       }
diff --git a/source/val/validate_mode_setting.cpp b/source/val/validate_mode_setting.cpp
index 672192b..dfa4646 100644
--- a/source/val/validate_mode_setting.cpp
+++ b/source/val/validate_mode_setting.cpp
@@ -27,16 +27,16 @@
 spv_result_t ValidateEntryPoint(ValidationState_t& _, const Instruction* inst) {
   const auto entry_point_id = inst->GetOperandAs<uint32_t>(1);
   auto entry_point = _.FindDef(entry_point_id);
-  if (!entry_point || SpvOpFunction != entry_point->opcode()) {
+  if (!entry_point || spv::Op::OpFunction != entry_point->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "OpEntryPoint Entry Point <id> " << _.getIdName(entry_point_id)
            << " is not a function.";
   }
 
   // Only check the shader execution models
-  const SpvExecutionModel execution_model =
-      inst->GetOperandAs<SpvExecutionModel>(0);
-  if (execution_model != SpvExecutionModelKernel) {
+  const spv::ExecutionModel execution_model =
+      inst->GetOperandAs<spv::ExecutionModel>(0);
+  if (execution_model != spv::ExecutionModel::Kernel) {
     const auto entry_point_type_id = entry_point->GetOperandAs<uint32_t>(3);
     const auto entry_point_type = _.FindDef(entry_point_type_id);
     if (!entry_point_type || 3 != entry_point_type->words().size()) {
@@ -48,7 +48,7 @@
   }
 
   auto return_type = _.FindDef(entry_point->type_id());
-  if (!return_type || SpvOpTypeVoid != return_type->opcode()) {
+  if (!return_type || spv::Op::OpTypeVoid != return_type->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << _.VkErrorID(4633) << "OpEntryPoint Entry Point <id> "
            << _.getIdName(entry_point_id)
@@ -56,31 +56,31 @@
   }
 
   const auto* execution_modes = _.GetExecutionModes(entry_point_id);
-  if (_.HasCapability(SpvCapabilityShader)) {
+  if (_.HasCapability(spv::Capability::Shader)) {
     switch (execution_model) {
-      case SpvExecutionModelFragment:
+      case spv::ExecutionModel::Fragment:
         if (execution_modes &&
-            execution_modes->count(SpvExecutionModeOriginUpperLeft) &&
-            execution_modes->count(SpvExecutionModeOriginLowerLeft)) {
+            execution_modes->count(spv::ExecutionMode::OriginUpperLeft) &&
+            execution_modes->count(spv::ExecutionMode::OriginLowerLeft)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << "Fragment execution model entry points can only specify "
                     "one of OriginUpperLeft or OriginLowerLeft execution "
                     "modes.";
         }
         if (!execution_modes ||
-            (!execution_modes->count(SpvExecutionModeOriginUpperLeft) &&
-             !execution_modes->count(SpvExecutionModeOriginLowerLeft))) {
+            (!execution_modes->count(spv::ExecutionMode::OriginUpperLeft) &&
+             !execution_modes->count(spv::ExecutionMode::OriginLowerLeft))) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << "Fragment execution model entry points require either an "
                     "OriginUpperLeft or OriginLowerLeft execution mode.";
         }
         if (execution_modes &&
             1 < std::count_if(execution_modes->begin(), execution_modes->end(),
-                              [](const SpvExecutionMode& mode) {
+                              [](const spv::ExecutionMode& mode) {
                                 switch (mode) {
-                                  case SpvExecutionModeDepthGreater:
-                                  case SpvExecutionModeDepthLess:
-                                  case SpvExecutionModeDepthUnchanged:
+                                  case spv::ExecutionMode::DepthGreater:
+                                  case spv::ExecutionMode::DepthLess:
+                                  case spv::ExecutionMode::DepthUnchanged:
                                     return true;
                                   default:
                                     return false;
@@ -94,14 +94,15 @@
         if (execution_modes &&
             1 < std::count_if(
                     execution_modes->begin(), execution_modes->end(),
-                    [](const SpvExecutionMode& mode) {
+                    [](const spv::ExecutionMode& mode) {
                       switch (mode) {
-                        case SpvExecutionModePixelInterlockOrderedEXT:
-                        case SpvExecutionModePixelInterlockUnorderedEXT:
-                        case SpvExecutionModeSampleInterlockOrderedEXT:
-                        case SpvExecutionModeSampleInterlockUnorderedEXT:
-                        case SpvExecutionModeShadingRateInterlockOrderedEXT:
-                        case SpvExecutionModeShadingRateInterlockUnorderedEXT:
+                        case spv::ExecutionMode::PixelInterlockOrderedEXT:
+                        case spv::ExecutionMode::PixelInterlockUnorderedEXT:
+                        case spv::ExecutionMode::SampleInterlockOrderedEXT:
+                        case spv::ExecutionMode::SampleInterlockUnorderedEXT:
+                        case spv::ExecutionMode::ShadingRateInterlockOrderedEXT:
+                        case spv::ExecutionMode::
+                            ShadingRateInterlockUnorderedEXT:
                           return true;
                         default:
                           return false;
@@ -114,11 +115,11 @@
         if (execution_modes &&
             1 < std::count_if(
                     execution_modes->begin(), execution_modes->end(),
-                    [](const SpvExecutionMode& mode) {
+                    [](const spv::ExecutionMode& mode) {
                       switch (mode) {
-                        case SpvExecutionModeStencilRefUnchangedFrontAMD:
-                        case SpvExecutionModeStencilRefLessFrontAMD:
-                        case SpvExecutionModeStencilRefGreaterFrontAMD:
+                        case spv::ExecutionMode::StencilRefUnchangedFrontAMD:
+                        case spv::ExecutionMode::StencilRefLessFrontAMD:
+                        case spv::ExecutionMode::StencilRefGreaterFrontAMD:
                           return true;
                         default:
                           return false;
@@ -133,11 +134,11 @@
         if (execution_modes &&
             1 < std::count_if(
                     execution_modes->begin(), execution_modes->end(),
-                    [](const SpvExecutionMode& mode) {
+                    [](const spv::ExecutionMode& mode) {
                       switch (mode) {
-                        case SpvExecutionModeStencilRefUnchangedBackAMD:
-                        case SpvExecutionModeStencilRefLessBackAMD:
-                        case SpvExecutionModeStencilRefGreaterBackAMD:
+                        case spv::ExecutionMode::StencilRefUnchangedBackAMD:
+                        case spv::ExecutionMode::StencilRefLessBackAMD:
+                        case spv::ExecutionMode::StencilRefGreaterBackAMD:
                           return true;
                         default:
                           return false;
@@ -150,20 +151,21 @@
                     "execution modes.";
         }
         break;
-      case SpvExecutionModelTessellationControl:
-      case SpvExecutionModelTessellationEvaluation:
+      case spv::ExecutionModel::TessellationControl:
+      case spv::ExecutionModel::TessellationEvaluation:
         if (execution_modes &&
-            1 < std::count_if(execution_modes->begin(), execution_modes->end(),
-                              [](const SpvExecutionMode& mode) {
-                                switch (mode) {
-                                  case SpvExecutionModeSpacingEqual:
-                                  case SpvExecutionModeSpacingFractionalEven:
-                                  case SpvExecutionModeSpacingFractionalOdd:
-                                    return true;
-                                  default:
-                                    return false;
-                                }
-                              })) {
+            1 < std::count_if(
+                    execution_modes->begin(), execution_modes->end(),
+                    [](const spv::ExecutionMode& mode) {
+                      switch (mode) {
+                        case spv::ExecutionMode::SpacingEqual:
+                        case spv::ExecutionMode::SpacingFractionalEven:
+                        case spv::ExecutionMode::SpacingFractionalOdd:
+                          return true;
+                        default:
+                          return false;
+                      }
+                    })) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << "Tessellation execution model entry points can specify at "
                     "most one of SpacingEqual, SpacingFractionalOdd or "
@@ -171,11 +173,11 @@
         }
         if (execution_modes &&
             1 < std::count_if(execution_modes->begin(), execution_modes->end(),
-                              [](const SpvExecutionMode& mode) {
+                              [](const spv::ExecutionMode& mode) {
                                 switch (mode) {
-                                  case SpvExecutionModeTriangles:
-                                  case SpvExecutionModeQuads:
-                                  case SpvExecutionModeIsolines:
+                                  case spv::ExecutionMode::Triangles:
+                                  case spv::ExecutionMode::Quads:
+                                  case spv::ExecutionMode::Isolines:
                                     return true;
                                   default:
                                     return false;
@@ -187,10 +189,10 @@
         }
         if (execution_modes &&
             1 < std::count_if(execution_modes->begin(), execution_modes->end(),
-                              [](const SpvExecutionMode& mode) {
+                              [](const spv::ExecutionMode& mode) {
                                 switch (mode) {
-                                  case SpvExecutionModeVertexOrderCw:
-                                  case SpvExecutionModeVertexOrderCcw:
+                                  case spv::ExecutionMode::VertexOrderCw:
+                                  case spv::ExecutionMode::VertexOrderCcw:
                                     return true;
                                   default:
                                     return false;
@@ -202,21 +204,22 @@
                     "modes.";
         }
         break;
-      case SpvExecutionModelGeometry:
+      case spv::ExecutionModel::Geometry:
         if (!execution_modes ||
-            1 != std::count_if(execution_modes->begin(), execution_modes->end(),
-                               [](const SpvExecutionMode& mode) {
-                                 switch (mode) {
-                                   case SpvExecutionModeInputPoints:
-                                   case SpvExecutionModeInputLines:
-                                   case SpvExecutionModeInputLinesAdjacency:
-                                   case SpvExecutionModeTriangles:
-                                   case SpvExecutionModeInputTrianglesAdjacency:
-                                     return true;
-                                   default:
-                                     return false;
-                                 }
-                               })) {
+            1 != std::count_if(
+                     execution_modes->begin(), execution_modes->end(),
+                     [](const spv::ExecutionMode& mode) {
+                       switch (mode) {
+                         case spv::ExecutionMode::InputPoints:
+                         case spv::ExecutionMode::InputLines:
+                         case spv::ExecutionMode::InputLinesAdjacency:
+                         case spv::ExecutionMode::Triangles:
+                         case spv::ExecutionMode::InputTrianglesAdjacency:
+                           return true;
+                         default:
+                           return false;
+                       }
+                     })) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << "Geometry execution model entry points must specify "
                     "exactly one of InputPoints, InputLines, "
@@ -225,11 +228,11 @@
         }
         if (!execution_modes ||
             1 != std::count_if(execution_modes->begin(), execution_modes->end(),
-                               [](const SpvExecutionMode& mode) {
+                               [](const spv::ExecutionMode& mode) {
                                  switch (mode) {
-                                   case SpvExecutionModeOutputPoints:
-                                   case SpvExecutionModeOutputLineStrip:
-                                   case SpvExecutionModeOutputTriangleStrip:
+                                   case spv::ExecutionMode::OutputPoints:
+                                   case spv::ExecutionMode::OutputLineStrip:
+                                   case spv::ExecutionMode::OutputTriangleStrip:
                                      return true;
                                    default:
                                      return false;
@@ -241,14 +244,14 @@
                     "OutputTriangleStrip execution modes.";
         }
         break;
-      case SpvExecutionModelMeshEXT:
+      case spv::ExecutionModel::MeshEXT:
         if (!execution_modes ||
             1 != std::count_if(execution_modes->begin(), execution_modes->end(),
-                               [](const SpvExecutionMode& mode) {
+                               [](const spv::ExecutionMode& mode) {
                                  switch (mode) {
-                                   case SpvExecutionModeOutputPoints:
-                                   case SpvExecutionModeOutputLinesEXT:
-                                   case SpvExecutionModeOutputTrianglesEXT:
+                                   case spv::ExecutionMode::OutputPoints:
+                                   case spv::ExecutionMode::OutputLinesEXT:
+                                   case spv::ExecutionMode::OutputTrianglesEXT:
                                      return true;
                                    default:
                                      return false;
@@ -260,10 +263,10 @@
                     "OutputTrianglesEXT Execution Modes.";
         } else if (2 != std::count_if(
                             execution_modes->begin(), execution_modes->end(),
-                            [](const SpvExecutionMode& mode) {
+                            [](const spv::ExecutionMode& mode) {
                               switch (mode) {
-                                case SpvExecutionModeOutputPrimitivesEXT:
-                                case SpvExecutionModeOutputVertices:
+                                case spv::ExecutionMode::OutputPrimitivesEXT:
+                                case spv::ExecutionMode::OutputVertices:
                                   return true;
                                 default:
                                   return false;
@@ -281,23 +284,25 @@
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
     switch (execution_model) {
-      case SpvExecutionModelGLCompute:
+      case spv::ExecutionModel::GLCompute:
         if (!execution_modes ||
-            !execution_modes->count(SpvExecutionModeLocalSize)) {
+            !execution_modes->count(spv::ExecutionMode::LocalSize)) {
           bool ok = false;
           for (auto& i : _.ordered_instructions()) {
-            if (i.opcode() == SpvOpDecorate) {
+            if (i.opcode() == spv::Op::OpDecorate) {
               if (i.operands().size() > 2) {
-                if (i.GetOperandAs<SpvDecoration>(1) == SpvDecorationBuiltIn &&
-                    i.GetOperandAs<SpvBuiltIn>(2) == SpvBuiltInWorkgroupSize) {
+                if (i.GetOperandAs<spv::Decoration>(1) ==
+                        spv::Decoration::BuiltIn &&
+                    i.GetOperandAs<spv::BuiltIn>(2) ==
+                        spv::BuiltIn::WorkgroupSize) {
                   ok = true;
                   break;
                 }
               }
             }
-            if (i.opcode() == SpvOpExecutionModeId) {
-              const auto mode = i.GetOperandAs<SpvExecutionMode>(1);
-              if (mode == SpvExecutionModeLocalSizeId) {
+            if (i.opcode() == spv::Op::OpExecutionModeId) {
+              const auto mode = i.GetOperandAs<spv::ExecutionMode>(1);
+              if (mode == spv::ExecutionMode::LocalSizeId) {
                 ok = true;
                 break;
               }
@@ -333,15 +338,15 @@
               "operand of an OpEntryPoint.";
   }
 
-  const auto mode = inst->GetOperandAs<SpvExecutionMode>(1);
-  if (inst->opcode() == SpvOpExecutionModeId) {
+  const auto mode = inst->GetOperandAs<spv::ExecutionMode>(1);
+  if (inst->opcode() == spv::Op::OpExecutionModeId) {
     size_t operand_count = inst->operands().size();
     for (size_t i = 2; i < operand_count; ++i) {
       const auto operand_id = inst->GetOperandAs<uint32_t>(2);
       const auto* operand_inst = _.FindDef(operand_id);
-      if (mode == SpvExecutionModeSubgroupsPerWorkgroupId ||
-          mode == SpvExecutionModeLocalSizeHintId ||
-          mode == SpvExecutionModeLocalSizeId) {
+      if (mode == spv::ExecutionMode::SubgroupsPerWorkgroupId ||
+          mode == spv::ExecutionMode::LocalSizeHintId ||
+          mode == spv::ExecutionMode::LocalSizeId) {
         if (!spvOpcodeIsConstant(operand_inst->opcode())) {
           return _.diag(SPV_ERROR_INVALID_ID, inst)
                  << "For OpExecutionModeId all Extra Operand ids must be "
@@ -355,9 +360,9 @@
                   "operands.";
       }
     }
-  } else if (mode == SpvExecutionModeSubgroupsPerWorkgroupId ||
-             mode == SpvExecutionModeLocalSizeHintId ||
-             mode == SpvExecutionModeLocalSizeId) {
+  } else if (mode == spv::ExecutionMode::SubgroupsPerWorkgroupId ||
+             mode == spv::ExecutionMode::LocalSizeHintId ||
+             mode == spv::ExecutionMode::LocalSizeId) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "OpExecutionMode is only valid when the Mode operand is an "
               "execution mode that takes no Extra Operands, or takes Extra "
@@ -366,39 +371,39 @@
 
   const auto* models = _.GetExecutionModels(entry_point_id);
   switch (mode) {
-    case SpvExecutionModeInvocations:
-    case SpvExecutionModeInputPoints:
-    case SpvExecutionModeInputLines:
-    case SpvExecutionModeInputLinesAdjacency:
-    case SpvExecutionModeInputTrianglesAdjacency:
-    case SpvExecutionModeOutputLineStrip:
-    case SpvExecutionModeOutputTriangleStrip:
+    case spv::ExecutionMode::Invocations:
+    case spv::ExecutionMode::InputPoints:
+    case spv::ExecutionMode::InputLines:
+    case spv::ExecutionMode::InputLinesAdjacency:
+    case spv::ExecutionMode::InputTrianglesAdjacency:
+    case spv::ExecutionMode::OutputLineStrip:
+    case spv::ExecutionMode::OutputTriangleStrip:
       if (!std::all_of(models->begin(), models->end(),
-                       [](const SpvExecutionModel& model) {
-                         return model == SpvExecutionModelGeometry;
+                       [](const spv::ExecutionModel& model) {
+                         return model == spv::ExecutionModel::Geometry;
                        })) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Execution mode can only be used with the Geometry execution "
                   "model.";
       }
       break;
-    case SpvExecutionModeOutputPoints:
-      if (!std::all_of(models->begin(), models->end(),
-                       [&_](const SpvExecutionModel& model) {
-                         switch (model) {
-                           case SpvExecutionModelGeometry:
-                             return true;
-                           case SpvExecutionModelMeshNV:
-                             return _.HasCapability(SpvCapabilityMeshShadingNV);
-                           case SpvExecutionModelMeshEXT:
-                             return _.HasCapability(
-                                 SpvCapabilityMeshShadingEXT);
-                           default:
-                             return false;
-                         }
-                       })) {
-        if (_.HasCapability(SpvCapabilityMeshShadingNV) ||
-            _.HasCapability(SpvCapabilityMeshShadingEXT)) {
+    case spv::ExecutionMode::OutputPoints:
+      if (!std::all_of(
+              models->begin(), models->end(),
+              [&_](const spv::ExecutionModel& model) {
+                switch (model) {
+                  case spv::ExecutionModel::Geometry:
+                    return true;
+                  case spv::ExecutionModel::MeshNV:
+                    return _.HasCapability(spv::Capability::MeshShadingNV);
+                  case spv::ExecutionModel::MeshEXT:
+                    return _.HasCapability(spv::Capability::MeshShadingEXT);
+                  default:
+                    return false;
+                }
+              })) {
+        if (_.HasCapability(spv::Capability::MeshShadingNV) ||
+            _.HasCapability(spv::Capability::MeshShadingEXT)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << "Execution mode can only be used with the Geometry "
                     "MeshNV or MeshEXT execution model.";
@@ -410,32 +415,32 @@
         }
       }
       break;
-    case SpvExecutionModeSpacingEqual:
-    case SpvExecutionModeSpacingFractionalEven:
-    case SpvExecutionModeSpacingFractionalOdd:
-    case SpvExecutionModeVertexOrderCw:
-    case SpvExecutionModeVertexOrderCcw:
-    case SpvExecutionModePointMode:
-    case SpvExecutionModeQuads:
-    case SpvExecutionModeIsolines:
+    case spv::ExecutionMode::SpacingEqual:
+    case spv::ExecutionMode::SpacingFractionalEven:
+    case spv::ExecutionMode::SpacingFractionalOdd:
+    case spv::ExecutionMode::VertexOrderCw:
+    case spv::ExecutionMode::VertexOrderCcw:
+    case spv::ExecutionMode::PointMode:
+    case spv::ExecutionMode::Quads:
+    case spv::ExecutionMode::Isolines:
       if (!std::all_of(
               models->begin(), models->end(),
-              [](const SpvExecutionModel& model) {
-                return (model == SpvExecutionModelTessellationControl) ||
-                       (model == SpvExecutionModelTessellationEvaluation);
+              [](const spv::ExecutionModel& model) {
+                return (model == spv::ExecutionModel::TessellationControl) ||
+                       (model == spv::ExecutionModel::TessellationEvaluation);
               })) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Execution mode can only be used with a tessellation "
                   "execution model.";
       }
       break;
-    case SpvExecutionModeTriangles:
+    case spv::ExecutionMode::Triangles:
       if (!std::all_of(models->begin(), models->end(),
-                       [](const SpvExecutionModel& model) {
+                       [](const spv::ExecutionModel& model) {
                          switch (model) {
-                           case SpvExecutionModelGeometry:
-                           case SpvExecutionModelTessellationControl:
-                           case SpvExecutionModelTessellationEvaluation:
+                           case spv::ExecutionModel::Geometry:
+                           case spv::ExecutionModel::TessellationControl:
+                           case spv::ExecutionModel::TessellationEvaluation:
                              return true;
                            default:
                              return false;
@@ -446,25 +451,25 @@
                   "tessellation execution model.";
       }
       break;
-    case SpvExecutionModeOutputVertices:
-      if (!std::all_of(models->begin(), models->end(),
-                       [&_](const SpvExecutionModel& model) {
-                         switch (model) {
-                           case SpvExecutionModelGeometry:
-                           case SpvExecutionModelTessellationControl:
-                           case SpvExecutionModelTessellationEvaluation:
-                             return true;
-                           case SpvExecutionModelMeshNV:
-                             return _.HasCapability(SpvCapabilityMeshShadingNV);
-                           case SpvExecutionModelMeshEXT:
-                             return _.HasCapability(
-                                 SpvCapabilityMeshShadingEXT);
-                           default:
-                             return false;
-                         }
-                       })) {
-        if (_.HasCapability(SpvCapabilityMeshShadingNV) ||
-            _.HasCapability(SpvCapabilityMeshShadingEXT)) {
+    case spv::ExecutionMode::OutputVertices:
+      if (!std::all_of(
+              models->begin(), models->end(),
+              [&_](const spv::ExecutionModel& model) {
+                switch (model) {
+                  case spv::ExecutionModel::Geometry:
+                  case spv::ExecutionModel::TessellationControl:
+                  case spv::ExecutionModel::TessellationEvaluation:
+                    return true;
+                  case spv::ExecutionModel::MeshNV:
+                    return _.HasCapability(spv::Capability::MeshShadingNV);
+                  case spv::ExecutionModel::MeshEXT:
+                    return _.HasCapability(spv::Capability::MeshShadingEXT);
+                  default:
+                    return false;
+                }
+              })) {
+        if (_.HasCapability(spv::Capability::MeshShadingNV) ||
+            _.HasCapability(spv::Capability::MeshShadingEXT)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << "Execution mode can only be used with a Geometry, "
                     "tessellation, MeshNV or MeshEXT execution model.";
@@ -475,13 +480,13 @@
         }
       }
       break;
-    case SpvExecutionModeOutputLinesEXT:
-    case SpvExecutionModeOutputTrianglesEXT:
-    case SpvExecutionModeOutputPrimitivesEXT:
+    case spv::ExecutionMode::OutputLinesEXT:
+    case spv::ExecutionMode::OutputTrianglesEXT:
+    case spv::ExecutionMode::OutputPrimitivesEXT:
       if (!std::all_of(models->begin(), models->end(),
-                       [](const SpvExecutionModel& model) {
-                         return (model == SpvExecutionModelMeshEXT ||
-                                 model == SpvExecutionModelMeshNV);
+                       [](const spv::ExecutionModel& model) {
+                         return (model == spv::ExecutionModel::MeshEXT ||
+                                 model == spv::ExecutionModel::MeshNV);
                        })) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Execution mode can only be used with the MeshEXT or MeshNV "
@@ -489,74 +494,74 @@
                   "model.";
       }
       break;
-    case SpvExecutionModePixelCenterInteger:
-    case SpvExecutionModeOriginUpperLeft:
-    case SpvExecutionModeOriginLowerLeft:
-    case SpvExecutionModeEarlyFragmentTests:
-    case SpvExecutionModeDepthReplacing:
-    case SpvExecutionModeDepthGreater:
-    case SpvExecutionModeDepthLess:
-    case SpvExecutionModeDepthUnchanged:
-    case SpvExecutionModePixelInterlockOrderedEXT:
-    case SpvExecutionModePixelInterlockUnorderedEXT:
-    case SpvExecutionModeSampleInterlockOrderedEXT:
-    case SpvExecutionModeSampleInterlockUnorderedEXT:
-    case SpvExecutionModeShadingRateInterlockOrderedEXT:
-    case SpvExecutionModeShadingRateInterlockUnorderedEXT:
-    case SpvExecutionModeEarlyAndLateFragmentTestsAMD:
-    case SpvExecutionModeStencilRefUnchangedFrontAMD:
-    case SpvExecutionModeStencilRefGreaterFrontAMD:
-    case SpvExecutionModeStencilRefLessFrontAMD:
-    case SpvExecutionModeStencilRefUnchangedBackAMD:
-    case SpvExecutionModeStencilRefGreaterBackAMD:
-    case SpvExecutionModeStencilRefLessBackAMD:
+    case spv::ExecutionMode::PixelCenterInteger:
+    case spv::ExecutionMode::OriginUpperLeft:
+    case spv::ExecutionMode::OriginLowerLeft:
+    case spv::ExecutionMode::EarlyFragmentTests:
+    case spv::ExecutionMode::DepthReplacing:
+    case spv::ExecutionMode::DepthGreater:
+    case spv::ExecutionMode::DepthLess:
+    case spv::ExecutionMode::DepthUnchanged:
+    case spv::ExecutionMode::PixelInterlockOrderedEXT:
+    case spv::ExecutionMode::PixelInterlockUnorderedEXT:
+    case spv::ExecutionMode::SampleInterlockOrderedEXT:
+    case spv::ExecutionMode::SampleInterlockUnorderedEXT:
+    case spv::ExecutionMode::ShadingRateInterlockOrderedEXT:
+    case spv::ExecutionMode::ShadingRateInterlockUnorderedEXT:
+    case spv::ExecutionMode::EarlyAndLateFragmentTestsAMD:
+    case spv::ExecutionMode::StencilRefUnchangedFrontAMD:
+    case spv::ExecutionMode::StencilRefGreaterFrontAMD:
+    case spv::ExecutionMode::StencilRefLessFrontAMD:
+    case spv::ExecutionMode::StencilRefUnchangedBackAMD:
+    case spv::ExecutionMode::StencilRefGreaterBackAMD:
+    case spv::ExecutionMode::StencilRefLessBackAMD:
       if (!std::all_of(models->begin(), models->end(),
-                       [](const SpvExecutionModel& model) {
-                         return model == SpvExecutionModelFragment;
+                       [](const spv::ExecutionModel& model) {
+                         return model == spv::ExecutionModel::Fragment;
                        })) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Execution mode can only be used with the Fragment execution "
                   "model.";
       }
       break;
-    case SpvExecutionModeLocalSizeHint:
-    case SpvExecutionModeVecTypeHint:
-    case SpvExecutionModeContractionOff:
-    case SpvExecutionModeLocalSizeHintId:
+    case spv::ExecutionMode::LocalSizeHint:
+    case spv::ExecutionMode::VecTypeHint:
+    case spv::ExecutionMode::ContractionOff:
+    case spv::ExecutionMode::LocalSizeHintId:
       if (!std::all_of(models->begin(), models->end(),
-                       [](const SpvExecutionModel& model) {
-                         return model == SpvExecutionModelKernel;
+                       [](const spv::ExecutionModel& model) {
+                         return model == spv::ExecutionModel::Kernel;
                        })) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Execution mode can only be used with the Kernel execution "
                   "model.";
       }
       break;
-    case SpvExecutionModeLocalSize:
-    case SpvExecutionModeLocalSizeId:
-      if (mode == SpvExecutionModeLocalSizeId && !_.IsLocalSizeIdAllowed())
+    case spv::ExecutionMode::LocalSize:
+    case spv::ExecutionMode::LocalSizeId:
+      if (mode == spv::ExecutionMode::LocalSizeId && !_.IsLocalSizeIdAllowed())
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "LocalSizeId mode is not allowed by the current environment.";
 
-      if (!std::all_of(models->begin(), models->end(),
-                       [&_](const SpvExecutionModel& model) {
-                         switch (model) {
-                           case SpvExecutionModelKernel:
-                           case SpvExecutionModelGLCompute:
-                             return true;
-                           case SpvExecutionModelTaskNV:
-                           case SpvExecutionModelMeshNV:
-                             return _.HasCapability(SpvCapabilityMeshShadingNV);
-                           case SpvExecutionModelTaskEXT:
-                           case SpvExecutionModelMeshEXT:
-                             return _.HasCapability(
-                                 SpvCapabilityMeshShadingEXT);
-                           default:
-                             return false;
-                         }
-                       })) {
-        if (_.HasCapability(SpvCapabilityMeshShadingNV) ||
-            _.HasCapability(SpvCapabilityMeshShadingEXT)) {
+      if (!std::all_of(
+              models->begin(), models->end(),
+              [&_](const spv::ExecutionModel& model) {
+                switch (model) {
+                  case spv::ExecutionModel::Kernel:
+                  case spv::ExecutionModel::GLCompute:
+                    return true;
+                  case spv::ExecutionModel::TaskNV:
+                  case spv::ExecutionModel::MeshNV:
+                    return _.HasCapability(spv::Capability::MeshShadingNV);
+                  case spv::ExecutionModel::TaskEXT:
+                  case spv::ExecutionModel::MeshEXT:
+                    return _.HasCapability(spv::Capability::MeshShadingEXT);
+                  default:
+                    return false;
+                }
+              })) {
+        if (_.HasCapability(spv::Capability::MeshShadingNV) ||
+            _.HasCapability(spv::Capability::MeshShadingEXT)) {
           return _.diag(SPV_ERROR_INVALID_DATA, inst)
                  << "Execution mode can only be used with a Kernel, GLCompute, "
                     "MeshNV, MeshEXT, TaskNV or TaskEXT execution model.";
@@ -572,13 +577,13 @@
   }
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    if (mode == SpvExecutionModeOriginLowerLeft) {
+    if (mode == spv::ExecutionMode::OriginLowerLeft) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << _.VkErrorID(4653)
              << "In the Vulkan environment, the OriginLowerLeft execution mode "
                 "must not be used.";
     }
-    if (mode == SpvExecutionModePixelCenterInteger) {
+    if (mode == spv::ExecutionMode::PixelCenterInteger) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << _.VkErrorID(4654)
              << "In the Vulkan environment, the PixelCenterInteger execution "
@@ -593,29 +598,30 @@
                                  const Instruction* inst) {
   // Already produced an error if multiple memory model instructions are
   // present.
-  if (_.memory_model() != SpvMemoryModelVulkanKHR &&
-      _.HasCapability(SpvCapabilityVulkanMemoryModelKHR)) {
+  if (_.memory_model() != spv::MemoryModel::VulkanKHR &&
+      _.HasCapability(spv::Capability::VulkanMemoryModelKHR)) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "VulkanMemoryModelKHR capability must only be specified if "
               "the VulkanKHR memory model is used.";
   }
 
   if (spvIsOpenCLEnv(_.context()->target_env)) {
-    if ((_.addressing_model() != SpvAddressingModelPhysical32) &&
-        (_.addressing_model() != SpvAddressingModelPhysical64)) {
+    if ((_.addressing_model() != spv::AddressingModel::Physical32) &&
+        (_.addressing_model() != spv::AddressingModel::Physical64)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Addressing model must be Physical32 or Physical64 "
              << "in the OpenCL environment.";
     }
-    if (_.memory_model() != SpvMemoryModelOpenCL) {
+    if (_.memory_model() != spv::MemoryModel::OpenCL) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Memory model must be OpenCL in the OpenCL environment.";
     }
   }
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    if ((_.addressing_model() != SpvAddressingModelLogical) &&
-        (_.addressing_model() != SpvAddressingModelPhysicalStorageBuffer64)) {
+    if ((_.addressing_model() != spv::AddressingModel::Logical) &&
+        (_.addressing_model() !=
+         spv::AddressingModel::PhysicalStorageBuffer64)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << _.VkErrorID(4635)
              << "Addressing model must be Logical or PhysicalStorageBuffer64 "
@@ -629,14 +635,14 @@
 
 spv_result_t ModeSettingPass(ValidationState_t& _, const Instruction* inst) {
   switch (inst->opcode()) {
-    case SpvOpEntryPoint:
+    case spv::Op::OpEntryPoint:
       if (auto error = ValidateEntryPoint(_, inst)) return error;
       break;
-    case SpvOpExecutionMode:
-    case SpvOpExecutionModeId:
+    case spv::Op::OpExecutionMode:
+    case spv::Op::OpExecutionModeId:
       if (auto error = ValidateExecutionMode(_, inst)) return error;
       break;
-    case SpvOpMemoryModel:
+    case spv::Op::OpMemoryModel:
       if (auto error = ValidateMemoryModel(_, inst)) return error;
       break;
     default:
diff --git a/source/val/validate_non_uniform.cpp b/source/val/validate_non_uniform.cpp
index 6d4f8a2..5c5e9bd 100644
--- a/source/val/validate_non_uniform.cpp
+++ b/source/val/validate_non_uniform.cpp
@@ -48,11 +48,11 @@
                                                    "of integer type scalar";
   }
 
-  const auto group = inst->GetOperandAs<uint32_t>(3);
+  const auto group = inst->GetOperandAs<spv::GroupOperation>(3);
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    if ((group != SpvGroupOperationReduce) &&
-        (group != SpvGroupOperationInclusiveScan) &&
-        (group != SpvGroupOperationExclusiveScan)) {
+    if ((group != spv::GroupOperation::Reduce) &&
+        (group != spv::GroupOperation::InclusiveScan) &&
+        (group != spv::GroupOperation::ExclusiveScan)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << _.VkErrorID(4685)
              << "In Vulkan: The OpGroupNonUniformBallotBitCount group "
@@ -120,7 +120,7 @@
 
 // Validates correctness of non-uniform group instructions.
 spv_result_t NonUniformPass(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
 
   if (spvOpcodeIsNonUniformGroupOperation(opcode)) {
     const uint32_t execution_scope = inst->word(3);
@@ -130,9 +130,9 @@
   }
 
   switch (opcode) {
-    case SpvOpGroupNonUniformBallotBitCount:
+    case spv::Op::OpGroupNonUniformBallotBitCount:
       return ValidateGroupNonUniformBallotBitCount(_, inst);
-    case SpvOpGroupNonUniformRotateKHR:
+    case spv::Op::OpGroupNonUniformRotateKHR:
       return ValidateGroupNonUniformRotateKHR(_, inst);
     default:
       break;
diff --git a/source/val/validate_primitives.cpp b/source/val/validate_primitives.cpp
index 7d11f2e..5e598c3 100644
--- a/source/val/validate_primitives.cpp
+++ b/source/val/validate_primitives.cpp
@@ -28,16 +28,16 @@
 
 // Validates correctness of primitive instructions.
 spv_result_t PrimitivesPass(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
 
   switch (opcode) {
-    case SpvOpEmitVertex:
-    case SpvOpEndPrimitive:
-    case SpvOpEmitStreamVertex:
-    case SpvOpEndStreamPrimitive:
+    case spv::Op::OpEmitVertex:
+    case spv::Op::OpEndPrimitive:
+    case spv::Op::OpEmitStreamVertex:
+    case spv::Op::OpEndStreamPrimitive:
       _.function(inst->function()->id())
           ->RegisterExecutionModelLimitation(
-              SpvExecutionModelGeometry,
+              spv::ExecutionModel::Geometry,
               std::string(spvOpcodeString(opcode)) +
                   " instructions require Geometry execution model");
       break;
@@ -46,8 +46,8 @@
   }
 
   switch (opcode) {
-    case SpvOpEmitStreamVertex:
-    case SpvOpEndStreamPrimitive: {
+    case spv::Op::OpEmitStreamVertex:
+    case spv::Op::OpEndStreamPrimitive: {
       const uint32_t stream_id = inst->word(1);
       const uint32_t stream_type = _.GetTypeId(stream_id);
       if (!_.IsIntScalarType(stream_type)) {
@@ -56,7 +56,7 @@
                << ": expected Stream to be int scalar";
       }
 
-      const SpvOp stream_opcode = _.GetIdOpcode(stream_id);
+      const spv::Op stream_opcode = _.GetIdOpcode(stream_id);
       if (!spvOpcodeIsConstant(stream_opcode)) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << spvOpcodeString(opcode)
diff --git a/source/val/validate_ray_query.cpp b/source/val/validate_ray_query.cpp
index b553449..9b67fc9 100644
--- a/source/val/validate_ray_query.cpp
+++ b/source/val/validate_ray_query.cpp
@@ -29,19 +29,19 @@
   const uint32_t ray_query_id = inst->GetOperandAs<uint32_t>(ray_query_index);
   auto variable = _.FindDef(ray_query_id);
   const auto var_opcode = variable->opcode();
-  if (!variable ||
-      (var_opcode != SpvOpVariable && var_opcode != SpvOpFunctionParameter &&
-       var_opcode != SpvOpAccessChain)) {
+  if (!variable || (var_opcode != spv::Op::OpVariable &&
+                    var_opcode != spv::Op::OpFunctionParameter &&
+                    var_opcode != spv::Op::OpAccessChain)) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Ray Query must be a memory object declaration";
   }
   auto pointer = _.FindDef(variable->GetOperandAs<uint32_t>(0));
-  if (!pointer || pointer->opcode() != SpvOpTypePointer) {
+  if (!pointer || pointer->opcode() != spv::Op::OpTypePointer) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Ray Query must be a pointer";
   }
   auto type = _.FindDef(pointer->GetOperandAs<uint32_t>(2));
-  if (!type || type->opcode() != SpvOpTypeRayQueryKHR) {
+  if (!type || type->opcode() != spv::Op::OpTypeRayQueryKHR) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Ray Query must be a pointer to OpTypeRayQueryKHR";
   }
@@ -54,7 +54,7 @@
   const uint32_t intersection_id =
       inst->GetOperandAs<uint32_t>(intersection_index);
   const uint32_t intersection_type = _.GetTypeId(intersection_id);
-  const SpvOp intersection_opcode = _.GetIdOpcode(intersection_id);
+  const spv::Op intersection_opcode = _.GetIdOpcode(intersection_id);
   if (!_.IsIntScalarType(intersection_type) ||
       _.GetBitWidth(intersection_type) != 32 ||
       !spvOpcodeIsConstant(intersection_opcode)) {
@@ -68,15 +68,15 @@
 }  // namespace
 
 spv_result_t RayQueryPass(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   const uint32_t result_type = inst->type_id();
 
   switch (opcode) {
-    case SpvOpRayQueryInitializeKHR: {
+    case spv::Op::OpRayQueryInitializeKHR: {
       if (auto error = ValidateRayQueryPointer(_, inst, 0)) return error;
 
       if (_.GetIdOpcode(_.GetOperandTypeId(inst, 1)) !=
-          SpvOpTypeAccelerationStructureKHR) {
+          spv::Op::OpTypeAccelerationStructureKHR) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected Acceleration Structure to be of type "
                   "OpTypeAccelerationStructureKHR";
@@ -123,13 +123,13 @@
       break;
     }
 
-    case SpvOpRayQueryTerminateKHR:
-    case SpvOpRayQueryConfirmIntersectionKHR: {
+    case spv::Op::OpRayQueryTerminateKHR:
+    case spv::Op::OpRayQueryConfirmIntersectionKHR: {
       if (auto error = ValidateRayQueryPointer(_, inst, 0)) return error;
       break;
     }
 
-    case SpvOpRayQueryGenerateIntersectionKHR: {
+    case spv::Op::OpRayQueryGenerateIntersectionKHR: {
       if (auto error = ValidateRayQueryPointer(_, inst, 0)) return error;
 
       const uint32_t hit_t_id = _.GetOperandTypeId(inst, 1);
@@ -141,9 +141,9 @@
       break;
     }
 
-    case SpvOpRayQueryGetIntersectionFrontFaceKHR:
-    case SpvOpRayQueryProceedKHR:
-    case SpvOpRayQueryGetIntersectionCandidateAABBOpaqueKHR: {
+    case spv::Op::OpRayQueryGetIntersectionFrontFaceKHR:
+    case spv::Op::OpRayQueryProceedKHR:
+    case spv::Op::OpRayQueryGetIntersectionCandidateAABBOpaqueKHR: {
       if (auto error = ValidateRayQueryPointer(_, inst, 2)) return error;
 
       if (!_.IsBoolScalarType(result_type)) {
@@ -151,15 +151,15 @@
                << "expected Result Type to be bool scalar type";
       }
 
-      if (opcode == SpvOpRayQueryGetIntersectionFrontFaceKHR) {
+      if (opcode == spv::Op::OpRayQueryGetIntersectionFrontFaceKHR) {
         if (auto error = ValidateIntersectionId(_, inst, 3)) return error;
       }
 
       break;
     }
 
-    case SpvOpRayQueryGetIntersectionTKHR:
-    case SpvOpRayQueryGetRayTMinKHR: {
+    case spv::Op::OpRayQueryGetIntersectionTKHR:
+    case spv::Op::OpRayQueryGetRayTMinKHR: {
       if (auto error = ValidateRayQueryPointer(_, inst, 2)) return error;
 
       if (!_.IsFloatScalarType(result_type) ||
@@ -168,20 +168,21 @@
                << "expected Result Type to be 32-bit float scalar type";
       }
 
-      if (opcode == SpvOpRayQueryGetIntersectionTKHR) {
+      if (opcode == spv::Op::OpRayQueryGetIntersectionTKHR) {
         if (auto error = ValidateIntersectionId(_, inst, 3)) return error;
       }
 
       break;
     }
 
-    case SpvOpRayQueryGetIntersectionTypeKHR:
-    case SpvOpRayQueryGetIntersectionInstanceCustomIndexKHR:
-    case SpvOpRayQueryGetIntersectionInstanceIdKHR:
-    case SpvOpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR:
-    case SpvOpRayQueryGetIntersectionGeometryIndexKHR:
-    case SpvOpRayQueryGetIntersectionPrimitiveIndexKHR:
-    case SpvOpRayQueryGetRayFlagsKHR: {
+    case spv::Op::OpRayQueryGetIntersectionTypeKHR:
+    case spv::Op::OpRayQueryGetIntersectionInstanceCustomIndexKHR:
+    case spv::Op::OpRayQueryGetIntersectionInstanceIdKHR:
+    case spv::Op::
+        OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR:
+    case spv::Op::OpRayQueryGetIntersectionGeometryIndexKHR:
+    case spv::Op::OpRayQueryGetIntersectionPrimitiveIndexKHR:
+    case spv::Op::OpRayQueryGetRayFlagsKHR: {
       if (auto error = ValidateRayQueryPointer(_, inst, 2)) return error;
 
       if (!_.IsIntScalarType(result_type) || _.GetBitWidth(result_type) != 32) {
@@ -189,17 +190,17 @@
                << "expected Result Type to be 32-bit int scalar type";
       }
 
-      if (opcode != SpvOpRayQueryGetRayFlagsKHR) {
+      if (opcode != spv::Op::OpRayQueryGetRayFlagsKHR) {
         if (auto error = ValidateIntersectionId(_, inst, 3)) return error;
       }
 
       break;
     }
 
-    case SpvOpRayQueryGetIntersectionObjectRayDirectionKHR:
-    case SpvOpRayQueryGetIntersectionObjectRayOriginKHR:
-    case SpvOpRayQueryGetWorldRayDirectionKHR:
-    case SpvOpRayQueryGetWorldRayOriginKHR: {
+    case spv::Op::OpRayQueryGetIntersectionObjectRayDirectionKHR:
+    case spv::Op::OpRayQueryGetIntersectionObjectRayOriginKHR:
+    case spv::Op::OpRayQueryGetWorldRayDirectionKHR:
+    case spv::Op::OpRayQueryGetWorldRayOriginKHR: {
       if (auto error = ValidateRayQueryPointer(_, inst, 2)) return error;
 
       if (!_.IsFloatVectorType(result_type) ||
@@ -210,15 +211,15 @@
                   "vector type";
       }
 
-      if (opcode == SpvOpRayQueryGetIntersectionObjectRayDirectionKHR ||
-          opcode == SpvOpRayQueryGetIntersectionObjectRayOriginKHR) {
+      if (opcode == spv::Op::OpRayQueryGetIntersectionObjectRayDirectionKHR ||
+          opcode == spv::Op::OpRayQueryGetIntersectionObjectRayOriginKHR) {
         if (auto error = ValidateIntersectionId(_, inst, 3)) return error;
       }
 
       break;
     }
 
-    case SpvOpRayQueryGetIntersectionBarycentricsKHR: {
+    case spv::Op::OpRayQueryGetIntersectionBarycentricsKHR: {
       if (auto error = ValidateRayQueryPointer(_, inst, 2)) return error;
       if (auto error = ValidateIntersectionId(_, inst, 3)) return error;
 
@@ -233,8 +234,8 @@
       break;
     }
 
-    case SpvOpRayQueryGetIntersectionObjectToWorldKHR:
-    case SpvOpRayQueryGetIntersectionWorldToObjectKHR: {
+    case spv::Op::OpRayQueryGetIntersectionObjectToWorldKHR:
+    case spv::Op::OpRayQueryGetIntersectionWorldToObjectKHR: {
       if (auto error = ValidateRayQueryPointer(_, inst, 2)) return error;
       if (auto error = ValidateIntersectionId(_, inst, 3)) return error;
 
diff --git a/source/val/validate_ray_tracing.cpp b/source/val/validate_ray_tracing.cpp
index 5b5c8da..f74e9d4 100644
--- a/source/val/validate_ray_tracing.cpp
+++ b/source/val/validate_ray_tracing.cpp
@@ -23,17 +23,17 @@
 namespace val {
 
 spv_result_t RayTracingPass(ValidationState_t& _, const Instruction* inst) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   const uint32_t result_type = inst->type_id();
 
   switch (opcode) {
-    case SpvOpTraceRayKHR: {
+    case spv::Op::OpTraceRayKHR: {
       _.function(inst->function()->id())
           ->RegisterExecutionModelLimitation(
-              [](SpvExecutionModel model, std::string* message) {
-                if (model != SpvExecutionModelRayGenerationKHR &&
-                    model != SpvExecutionModelClosestHitKHR &&
-                    model != SpvExecutionModelMissKHR) {
+              [](spv::ExecutionModel model, std::string* message) {
+                if (model != spv::ExecutionModel::RayGenerationKHR &&
+                    model != spv::ExecutionModel::ClosestHitKHR &&
+                    model != spv::ExecutionModel::MissKHR) {
                   if (message) {
                     *message =
                         "OpTraceRayKHR requires RayGenerationKHR, "
@@ -45,7 +45,7 @@
               });
 
       if (_.GetIdOpcode(_.GetOperandTypeId(inst, 0)) !=
-          SpvOpTypeAccelerationStructureKHR) {
+          spv::Op::OpTypeAccelerationStructureKHR) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected Acceleration Structure to be of type "
                   "OpTypeAccelerationStructureKHR";
@@ -109,13 +109,13 @@
       }
 
       const Instruction* payload = _.FindDef(inst->GetOperandAs<uint32_t>(10));
-      if (payload->opcode() != SpvOpVariable) {
+      if (payload->opcode() != spv::Op::OpVariable) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Payload must be the result of a OpVariable";
-      } else if (payload->GetOperandAs<uint32_t>(2) !=
-                     SpvStorageClassRayPayloadKHR &&
-                 payload->GetOperandAs<uint32_t>(2) !=
-                     SpvStorageClassIncomingRayPayloadKHR) {
+      } else if (payload->GetOperandAs<spv::StorageClass>(2) !=
+                     spv::StorageClass::RayPayloadKHR &&
+                 payload->GetOperandAs<spv::StorageClass>(2) !=
+                     spv::StorageClass::IncomingRayPayloadKHR) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Payload must have storage class RayPayloadKHR or "
                   "IncomingRayPayloadKHR";
@@ -123,11 +123,11 @@
       break;
     }
 
-    case SpvOpReportIntersectionKHR: {
+    case spv::Op::OpReportIntersectionKHR: {
       _.function(inst->function()->id())
           ->RegisterExecutionModelLimitation(
-              [](SpvExecutionModel model, std::string* message) {
-                if (model != SpvExecutionModelIntersectionKHR) {
+              [](spv::ExecutionModel model, std::string* message) {
+                if (model != spv::ExecutionModel::IntersectionKHR) {
                   if (message) {
                     *message =
                         "OpReportIntersectionKHR requires IntersectionKHR "
@@ -158,14 +158,14 @@
       break;
     }
 
-    case SpvOpExecuteCallableKHR: {
+    case spv::Op::OpExecuteCallableKHR: {
       _.function(inst->function()->id())
-          ->RegisterExecutionModelLimitation([](SpvExecutionModel model,
+          ->RegisterExecutionModelLimitation([](spv::ExecutionModel model,
                                                 std::string* message) {
-            if (model != SpvExecutionModelRayGenerationKHR &&
-                model != SpvExecutionModelClosestHitKHR &&
-                model != SpvExecutionModelMissKHR &&
-                model != SpvExecutionModelCallableKHR) {
+            if (model != spv::ExecutionModel::RayGenerationKHR &&
+                model != spv::ExecutionModel::ClosestHitKHR &&
+                model != spv::ExecutionModel::MissKHR &&
+                model != spv::ExecutionModel::CallableKHR) {
               if (message) {
                 *message =
                     "OpExecuteCallableKHR requires RayGenerationKHR, "
@@ -184,13 +184,13 @@
       }
 
       const auto callable_data = _.FindDef(inst->GetOperandAs<uint32_t>(1));
-      if (callable_data->opcode() != SpvOpVariable) {
+      if (callable_data->opcode() != spv::Op::OpVariable) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Callable Data must be the result of a OpVariable";
-      } else if (callable_data->GetOperandAs<uint32_t>(2) !=
-                     SpvStorageClassCallableDataKHR &&
-                 callable_data->GetOperandAs<uint32_t>(2) !=
-                     SpvStorageClassIncomingCallableDataKHR) {
+      } else if (callable_data->GetOperandAs<spv::StorageClass>(2) !=
+                     spv::StorageClass::CallableDataKHR &&
+                 callable_data->GetOperandAs<spv::StorageClass>(2) !=
+                     spv::StorageClass::IncomingCallableDataKHR) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Callable Data must have storage class CallableDataKHR or "
                   "IncomingCallableDataKHR";
diff --git a/source/val/validate_scopes.cpp b/source/val/validate_scopes.cpp
index e978180..fa1dad9 100644
--- a/source/val/validate_scopes.cpp
+++ b/source/val/validate_scopes.cpp
@@ -25,16 +25,16 @@
 bool IsValidScope(uint32_t scope) {
   // Deliberately avoid a default case so we have to update the list when the
   // scopes list changes.
-  switch (static_cast<SpvScope>(scope)) {
-    case SpvScopeCrossDevice:
-    case SpvScopeDevice:
-    case SpvScopeWorkgroup:
-    case SpvScopeSubgroup:
-    case SpvScopeInvocation:
-    case SpvScopeQueueFamilyKHR:
-    case SpvScopeShaderCallKHR:
+  switch (static_cast<spv::Scope>(scope)) {
+    case spv::Scope::CrossDevice:
+    case spv::Scope::Device:
+    case spv::Scope::Workgroup:
+    case spv::Scope::Subgroup:
+    case spv::Scope::Invocation:
+    case spv::Scope::QueueFamilyKHR:
+    case spv::Scope::ShaderCallKHR:
       return true;
-    case SpvScopeMax:
+    case spv::Scope::Max:
       break;
   }
   return false;
@@ -42,7 +42,7 @@
 
 spv_result_t ValidateScope(ValidationState_t& _, const Instruction* inst,
                            uint32_t scope) {
-  SpvOp opcode = inst->opcode();
+  spv::Op opcode = inst->opcode();
   bool is_int32 = false, is_const_int32 = false;
   uint32_t value = 0;
   std::tie(is_int32, is_const_int32, value) = _.EvalInt32IfConst(scope);
@@ -53,14 +53,14 @@
   }
 
   if (!is_const_int32) {
-    if (_.HasCapability(SpvCapabilityShader) &&
-        !_.HasCapability(SpvCapabilityCooperativeMatrixNV)) {
+    if (_.HasCapability(spv::Capability::Shader) &&
+        !_.HasCapability(spv::Capability::CooperativeMatrixNV)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Scope ids must be OpConstant when Shader capability is "
              << "present";
     }
-    if (_.HasCapability(SpvCapabilityShader) &&
-        _.HasCapability(SpvCapabilityCooperativeMatrixNV) &&
+    if (_.HasCapability(spv::Capability::Shader) &&
+        _.HasCapability(spv::Capability::CooperativeMatrixNV) &&
         !spvOpcodeIsConstant(_.GetIdOpcode(scope))) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << "Scope ids must be constant or specialization constant when "
@@ -78,10 +78,10 @@
 
 spv_result_t ValidateExecutionScope(ValidationState_t& _,
                                     const Instruction* inst, uint32_t scope) {
-  SpvOp opcode = inst->opcode();
+  spv::Op opcode = inst->opcode();
   bool is_int32 = false, is_const_int32 = false;
-  uint32_t value = 0;
-  std::tie(is_int32, is_const_int32, value) = _.EvalInt32IfConst(scope);
+  uint32_t tmp_value = 0;
+  std::tie(is_int32, is_const_int32, tmp_value) = _.EvalInt32IfConst(scope);
 
   if (auto error = ValidateScope(_, inst, scope)) {
     return error;
@@ -91,13 +91,15 @@
     return SPV_SUCCESS;
   }
 
+  spv::Scope value = spv::Scope(tmp_value);
+
   // Vulkan specific rules
   if (spvIsVulkanEnv(_.context()->target_env)) {
     // Vulkan 1.1 specific rules
     if (_.context()->target_env != SPV_ENV_VULKAN_1_0) {
       // Scope for Non Uniform Group Operations must be limited to Subgroup
       if (spvOpcodeIsNonUniformGroupOperation(opcode) &&
-          value != SpvScopeSubgroup) {
+          value != spv::Scope::Subgroup) {
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << _.VkErrorID(4642) << spvOpcodeString(opcode)
                << ": in Vulkan environment Execution scope is limited to "
@@ -107,21 +109,21 @@
 
     // OpControlBarrier must only use Subgroup execution scope for a subset of
     // execution models.
-    if (opcode == SpvOpControlBarrier && value != SpvScopeSubgroup) {
+    if (opcode == spv::Op::OpControlBarrier && value != spv::Scope::Subgroup) {
       std::string errorVUID = _.VkErrorID(4682);
       _.function(inst->function()->id())
           ->RegisterExecutionModelLimitation([errorVUID](
-                                                 SpvExecutionModel model,
+                                                 spv::ExecutionModel model,
                                                  std::string* message) {
-            if (model == SpvExecutionModelFragment ||
-                model == SpvExecutionModelVertex ||
-                model == SpvExecutionModelGeometry ||
-                model == SpvExecutionModelTessellationEvaluation ||
-                model == SpvExecutionModelRayGenerationKHR ||
-                model == SpvExecutionModelIntersectionKHR ||
-                model == SpvExecutionModelAnyHitKHR ||
-                model == SpvExecutionModelClosestHitKHR ||
-                model == SpvExecutionModelMissKHR) {
+            if (model == spv::ExecutionModel::Fragment ||
+                model == spv::ExecutionModel::Vertex ||
+                model == spv::ExecutionModel::Geometry ||
+                model == spv::ExecutionModel::TessellationEvaluation ||
+                model == spv::ExecutionModel::RayGenerationKHR ||
+                model == spv::ExecutionModel::IntersectionKHR ||
+                model == spv::ExecutionModel::AnyHitKHR ||
+                model == spv::ExecutionModel::ClosestHitKHR ||
+                model == spv::ExecutionModel::MissKHR) {
               if (message) {
                 *message =
                     errorVUID +
@@ -137,17 +139,17 @@
     }
 
     // Only subset of execution models support Workgroup.
-    if (value == SpvScopeWorkgroup) {
+    if (value == spv::Scope::Workgroup) {
       std::string errorVUID = _.VkErrorID(4637);
       _.function(inst->function()->id())
           ->RegisterExecutionModelLimitation(
-              [errorVUID](SpvExecutionModel model, std::string* message) {
-                if (model != SpvExecutionModelTaskNV &&
-                    model != SpvExecutionModelMeshNV &&
-                    model != SpvExecutionModelTaskEXT &&
-                    model != SpvExecutionModelMeshEXT &&
-                    model != SpvExecutionModelTessellationControl &&
-                    model != SpvExecutionModelGLCompute) {
+              [errorVUID](spv::ExecutionModel model, std::string* message) {
+                if (model != spv::ExecutionModel::TaskNV &&
+                    model != spv::ExecutionModel::MeshNV &&
+                    model != spv::ExecutionModel::TaskEXT &&
+                    model != spv::ExecutionModel::MeshEXT &&
+                    model != spv::ExecutionModel::TessellationControl &&
+                    model != spv::ExecutionModel::GLCompute) {
                   if (message) {
                     *message =
                         errorVUID +
@@ -163,7 +165,7 @@
 
     // Vulkan generic rules
     // Scope for execution must be limited to Workgroup or Subgroup
-    if (value != SpvScopeWorkgroup && value != SpvScopeSubgroup) {
+    if (value != spv::Scope::Workgroup && value != spv::Scope::Subgroup) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << _.VkErrorID(4636) << spvOpcodeString(opcode)
              << ": in Vulkan environment Execution Scope is limited to "
@@ -177,7 +179,7 @@
   // Scope for execution must be limited to Workgroup or Subgroup for
   // non-uniform operations
   if (spvOpcodeIsNonUniformGroupOperation(opcode) &&
-      value != SpvScopeSubgroup && value != SpvScopeWorkgroup) {
+      value != spv::Scope::Subgroup && value != spv::Scope::Workgroup) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << spvOpcodeString(opcode)
            << ": Execution scope is limited to Subgroup or Workgroup";
@@ -188,10 +190,10 @@
 
 spv_result_t ValidateMemoryScope(ValidationState_t& _, const Instruction* inst,
                                  uint32_t scope) {
-  const SpvOp opcode = inst->opcode();
+  const spv::Op opcode = inst->opcode();
   bool is_int32 = false, is_const_int32 = false;
-  uint32_t value = 0;
-  std::tie(is_int32, is_const_int32, value) = _.EvalInt32IfConst(scope);
+  uint32_t tmp_value = 0;
+  std::tie(is_int32, is_const_int32, tmp_value) = _.EvalInt32IfConst(scope);
 
   if (auto error = ValidateScope(_, inst, scope)) {
     return error;
@@ -201,8 +203,10 @@
     return SPV_SUCCESS;
   }
 
-  if (value == SpvScopeQueueFamilyKHR) {
-    if (_.HasCapability(SpvCapabilityVulkanMemoryModelKHR)) {
+  spv::Scope value = spv::Scope(tmp_value);
+
+  if (value == spv::Scope::QueueFamilyKHR) {
+    if (_.HasCapability(spv::Capability::VulkanMemoryModelKHR)) {
       return SPV_SUCCESS;
     } else {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -212,9 +216,9 @@
     }
   }
 
-  if (value == SpvScopeDevice &&
-      _.HasCapability(SpvCapabilityVulkanMemoryModelKHR) &&
-      !_.HasCapability(SpvCapabilityVulkanMemoryModelDeviceScopeKHR)) {
+  if (value == spv::Scope::Device &&
+      _.HasCapability(spv::Capability::VulkanMemoryModelKHR) &&
+      !_.HasCapability(spv::Capability::VulkanMemoryModelDeviceScopeKHR)) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Use of device scope with VulkanKHR memory model requires the "
            << "VulkanMemoryModelDeviceScopeKHR capability";
@@ -222,18 +226,19 @@
 
   // Vulkan Specific rules
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    if (value != SpvScopeDevice && value != SpvScopeWorkgroup &&
-        value != SpvScopeSubgroup && value != SpvScopeInvocation &&
-        value != SpvScopeShaderCallKHR && value != SpvScopeQueueFamily) {
+    if (value != spv::Scope::Device && value != spv::Scope::Workgroup &&
+        value != spv::Scope::Subgroup && value != spv::Scope::Invocation &&
+        value != spv::Scope::ShaderCallKHR &&
+        value != spv::Scope::QueueFamily) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << _.VkErrorID(4638) << spvOpcodeString(opcode)
              << ": in Vulkan environment Memory Scope is limited to Device, "
                 "QueueFamily, Workgroup, ShaderCallKHR, Subgroup, or "
                 "Invocation";
     } else if (_.context()->target_env == SPV_ENV_VULKAN_1_0 &&
-               value == SpvScopeSubgroup &&
-               !_.HasCapability(SpvCapabilitySubgroupBallotKHR) &&
-               !_.HasCapability(SpvCapabilitySubgroupVoteKHR)) {
+               value == spv::Scope::Subgroup &&
+               !_.HasCapability(spv::Capability::SubgroupBallotKHR) &&
+               !_.HasCapability(spv::Capability::SubgroupVoteKHR)) {
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
              << _.VkErrorID(6997) << spvOpcodeString(opcode)
              << ": in Vulkan 1.0 environment Memory Scope is can not be "
@@ -241,17 +246,17 @@
                 "declared";
     }
 
-    if (value == SpvScopeShaderCallKHR) {
+    if (value == spv::Scope::ShaderCallKHR) {
       std::string errorVUID = _.VkErrorID(4640);
       _.function(inst->function()->id())
           ->RegisterExecutionModelLimitation(
-              [errorVUID](SpvExecutionModel model, std::string* message) {
-                if (model != SpvExecutionModelRayGenerationKHR &&
-                    model != SpvExecutionModelIntersectionKHR &&
-                    model != SpvExecutionModelAnyHitKHR &&
-                    model != SpvExecutionModelClosestHitKHR &&
-                    model != SpvExecutionModelMissKHR &&
-                    model != SpvExecutionModelCallableKHR) {
+              [errorVUID](spv::ExecutionModel model, std::string* message) {
+                if (model != spv::ExecutionModel::RayGenerationKHR &&
+                    model != spv::ExecutionModel::IntersectionKHR &&
+                    model != spv::ExecutionModel::AnyHitKHR &&
+                    model != spv::ExecutionModel::ClosestHitKHR &&
+                    model != spv::ExecutionModel::MissKHR &&
+                    model != spv::ExecutionModel::CallableKHR) {
                   if (message) {
                     *message =
                         errorVUID +
@@ -264,17 +269,17 @@
               });
     }
 
-    if (value == SpvScopeWorkgroup) {
+    if (value == spv::Scope::Workgroup) {
       std::string errorVUID = _.VkErrorID(7321);
       _.function(inst->function()->id())
           ->RegisterExecutionModelLimitation(
-              [errorVUID](SpvExecutionModel model, std::string* message) {
-                if (model != SpvExecutionModelGLCompute &&
-                    model != SpvExecutionModelTessellationControl &&
-                    model != SpvExecutionModelTaskNV &&
-                    model != SpvExecutionModelMeshNV &&
-                    model != SpvExecutionModelTaskEXT &&
-                    model != SpvExecutionModelMeshEXT) {
+              [errorVUID](spv::ExecutionModel model, std::string* message) {
+                if (model != spv::ExecutionModel::GLCompute &&
+                    model != spv::ExecutionModel::TessellationControl &&
+                    model != spv::ExecutionModel::TaskNV &&
+                    model != spv::ExecutionModel::MeshNV &&
+                    model != spv::ExecutionModel::TaskEXT &&
+                    model != spv::ExecutionModel::MeshEXT) {
                   if (message) {
                     *message = errorVUID +
                                "Workgroup Memory Scope is limited to MeshNV, "
@@ -286,12 +291,12 @@
                 return true;
               });
 
-      if (_.memory_model() == SpvMemoryModelGLSL450) {
+      if (_.memory_model() == spv::MemoryModel::GLSL450) {
         errorVUID = _.VkErrorID(7320);
         _.function(inst->function()->id())
             ->RegisterExecutionModelLimitation(
-                [errorVUID](SpvExecutionModel model, std::string* message) {
-                  if (model == SpvExecutionModelTessellationControl) {
+                [errorVUID](spv::ExecutionModel model, std::string* message) {
+                  if (model == spv::ExecutionModel::TessellationControl) {
                     if (message) {
                       *message =
                           errorVUID +
diff --git a/source/val/validate_small_type_uses.cpp b/source/val/validate_small_type_uses.cpp
index 9db82e7..69f61ee 100644
--- a/source/val/validate_small_type_uses.cpp
+++ b/source/val/validate_small_type_uses.cpp
@@ -22,7 +22,7 @@
 
 spv_result_t ValidateSmallTypeUses(ValidationState_t& _,
                                    const Instruction* inst) {
-  if (!_.HasCapability(SpvCapabilityShader) || inst->type_id() == 0 ||
+  if (!_.HasCapability(spv::Capability::Shader) || inst->type_id() == 0 ||
       !_.ContainsLimitedUseIntOrFloatType(inst->type_id())) {
     return SPV_SUCCESS;
   }
@@ -36,13 +36,13 @@
   for (auto use : inst->uses()) {
     const auto* user = use.first;
     switch (user->opcode()) {
-      case SpvOpDecorate:
-      case SpvOpDecorateId:
-      case SpvOpCopyObject:
-      case SpvOpStore:
-      case SpvOpFConvert:
-      case SpvOpUConvert:
-      case SpvOpSConvert:
+      case spv::Op::OpDecorate:
+      case spv::Op::OpDecorateId:
+      case spv::Op::OpCopyObject:
+      case spv::Op::OpStore:
+      case spv::Op::OpFConvert:
+      case spv::Op::OpUConvert:
+      case spv::Op::OpSConvert:
         break;
       default:
         return _.diag(SPV_ERROR_INVALID_ID, user)
diff --git a/source/val/validate_type.cpp b/source/val/validate_type.cpp
index 6b0881c..e7adab8 100644
--- a/source/val/validate_type.cpp
+++ b/source/val/validate_type.cpp
@@ -19,7 +19,6 @@
 #include "source/val/instruction.h"
 #include "source/val/validate.h"
 #include "source/val/validation_state.h"
-#include "spirv/unified1/spirv.h"
 
 namespace spvtools {
 namespace val {
@@ -50,8 +49,8 @@
     return SPV_SUCCESS;
 
   const auto opcode = inst->opcode();
-  if (opcode != SpvOpTypeArray && opcode != SpvOpTypeRuntimeArray &&
-      opcode != SpvOpTypeStruct && opcode != SpvOpTypePointer &&
+  if (opcode != spv::Op::OpTypeArray && opcode != spv::Op::OpTypeRuntimeArray &&
+      opcode != spv::Op::OpTypeStruct && opcode != spv::Op::OpTypePointer &&
       !_.RegisterUniqueTypeDeclaration(inst)) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
            << "Duplicate non-aggregate type declarations are not allowed. "
@@ -84,7 +83,7 @@
              << "Using a 16-bit integer type requires the Int16 capability,"
                 " or an extension that explicitly enables 16-bit integers.";
     } else if (num_bits == 64) {
-      if (_.HasCapability(SpvCapabilityInt64)) {
+      if (_.HasCapability(spv::Capability::Int64)) {
         return SPV_SUCCESS;
       }
       return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -105,7 +104,8 @@
 
   // SPIR-V Spec 2.16.3: Validation Rules for Kernel Capabilities: The
   // Signedness in OpTypeInt must always be 0.
-  if (SpvOpTypeInt == inst->opcode() && _.HasCapability(SpvCapabilityKernel) &&
+  if (spv::Op::OpTypeInt == inst->opcode() &&
+      _.HasCapability(spv::Capability::Kernel) &&
       inst->GetOperandAs<uint32_t>(2) != 0u) {
     return _.diag(SPV_ERROR_INVALID_BINARY, inst)
            << "The Signedness in OpTypeInt "
@@ -135,7 +135,7 @@
               " or an extension that explicitly enables 16-bit floating point.";
   }
   if (num_bits == 64) {
-    if (_.HasCapability(SpvCapabilityFloat64)) {
+    if (_.HasCapability(spv::Capability::Float64)) {
       return SPV_SUCCESS;
     }
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -163,7 +163,7 @@
   if (num_components == 2 || num_components == 3 || num_components == 4) {
     return SPV_SUCCESS;
   } else if (num_components == 8 || num_components == 16) {
-    if (_.HasCapability(SpvCapabilityVector16)) {
+    if (_.HasCapability(spv::Capability::Vector16)) {
       return SPV_SUCCESS;
     }
     return _.diag(SPV_ERROR_INVALID_DATA, inst)
@@ -183,7 +183,7 @@
   const auto column_type_index = 1;
   const auto column_type_id = inst->GetOperandAs<uint32_t>(column_type_index);
   const auto column_type = _.FindDef(column_type_id);
-  if (!column_type || SpvOpTypeVector != column_type->opcode()) {
+  if (!column_type || spv::Op::OpTypeVector != column_type->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Columns in a matrix must be of type vector.";
   }
@@ -192,7 +192,7 @@
   // Operand 1 is the <id> of the type of data in the vector.
   const auto comp_type_id = column_type->GetOperandAs<uint32_t>(1);
   auto comp_type_instruction = _.FindDef(comp_type_id);
-  if (comp_type_instruction->opcode() != SpvOpTypeFloat) {
+  if (comp_type_instruction->opcode() != spv::Op::OpTypeFloat) {
     return _.diag(SPV_ERROR_INVALID_DATA, inst) << "Matrix types can only be "
                                                    "parameterized with "
                                                    "floating-point types.";
@@ -219,14 +219,14 @@
            << " is not a type.";
   }
 
-  if (element_type->opcode() == SpvOpTypeVoid) {
+  if (element_type->opcode() == spv::Op::OpTypeVoid) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "OpTypeArray Element Type <id> " << _.getIdName(element_type_id)
            << " is a void type.";
   }
 
   if (spvIsVulkanEnv(_.context()->target_env) &&
-      element_type->opcode() == SpvOpTypeRuntimeArray) {
+      element_type->opcode() == spv::Op::OpTypeRuntimeArray) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << _.VkErrorID(4680) << "OpTypeArray Element Type <id> "
            << _.getIdName(element_type_id) << " is not valid in "
@@ -246,15 +246,15 @@
   const auto const_inst = length->words();
   const auto const_result_type_index = 1;
   const auto const_result_type = _.FindDef(const_inst[const_result_type_index]);
-  if (!const_result_type || SpvOpTypeInt != const_result_type->opcode()) {
+  if (!const_result_type || spv::Op::OpTypeInt != const_result_type->opcode()) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "OpTypeArray Length <id> " << _.getIdName(length_id)
            << " is not a constant integer type.";
   }
 
   switch (length->opcode()) {
-    case SpvOpSpecConstant:
-    case SpvOpConstant: {
+    case spv::Op::OpSpecConstant:
+    case spv::Op::OpConstant: {
       auto& type_words = const_result_type->words();
       const bool is_signed = type_words[3] > 0;
       const uint32_t width = type_words[2];
@@ -265,11 +265,11 @@
                << " default value must be at least 1: found " << ivalue;
       }
     } break;
-    case SpvOpConstantNull:
+    case spv::Op::OpConstantNull:
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "OpTypeArray Length <id> " << _.getIdName(length_id)
              << " default value must be at least 1.";
-    case SpvOpSpecConstantOp:
+    case spv::Op::OpSpecConstantOp:
       // Assume it's OK, rather than try to evaluate the operation.
       break;
     default:
@@ -289,14 +289,14 @@
            << " is not a type.";
   }
 
-  if (element_type->opcode() == SpvOpTypeVoid) {
+  if (element_type->opcode() == spv::Op::OpTypeVoid) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "OpTypeRuntimeArray Element Type <id> " << _.getIdName(element_id)
            << " is a void type.";
   }
 
   if (spvIsVulkanEnv(_.context()->target_env) &&
-      element_type->opcode() == SpvOpTypeRuntimeArray) {
+      element_type->opcode() == spv::Op::OpTypeRuntimeArray) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << _.VkErrorID(4680) << "OpTypeRuntimeArray Element Type <id> "
            << _.getIdName(element_id) << " is not valid in "
@@ -322,11 +322,11 @@
              << "OpTypeStruct Member Type <id> " << _.getIdName(member_type_id)
              << " is not a type.";
     }
-    if (member_type->opcode() == SpvOpTypeVoid) {
+    if (member_type->opcode() == spv::Op::OpTypeVoid) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "Structures cannot contain a void type.";
     }
-    if (SpvOpTypeStruct == member_type->opcode() &&
+    if (spv::Op::OpTypeStruct == member_type->opcode() &&
         _.IsStructTypeWithBuiltInMember(member_type_id)) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "Structure <id> " << _.getIdName(member_type_id)
@@ -339,7 +339,7 @@
     }
 
     if (spvIsVulkanEnv(_.context()->target_env) &&
-        member_type->opcode() == SpvOpTypeRuntimeArray) {
+        member_type->opcode() == spv::Op::OpTypeRuntimeArray) {
       const bool is_last_member =
           member_type_index == inst->operands().size() - 1;
       if (!is_last_member) {
@@ -357,9 +357,10 @@
   for (size_t word_i = 2; word_i < inst->words().size(); ++word_i) {
     auto member = inst->word(word_i);
     auto memberTypeInstr = _.FindDef(member);
-    if (memberTypeInstr && SpvOpTypeStruct == memberTypeInstr->opcode()) {
-      if (_.HasDecoration(memberTypeInstr->id(), SpvDecorationBlock) ||
-          _.HasDecoration(memberTypeInstr->id(), SpvDecorationBufferBlock) ||
+    if (memberTypeInstr && spv::Op::OpTypeStruct == memberTypeInstr->opcode()) {
+      if (_.HasDecoration(memberTypeInstr->id(), spv::Decoration::Block) ||
+          _.HasDecoration(memberTypeInstr->id(),
+                          spv::Decoration::BufferBlock) ||
           _.GetHasNestedBlockOrBufferBlockStruct(memberTypeInstr->id()))
         has_nested_blockOrBufferBlock_struct = true;
     }
@@ -368,8 +369,8 @@
   _.SetHasNestedBlockOrBufferBlockStruct(inst->id(),
                                          has_nested_blockOrBufferBlock_struct);
   if (_.GetHasNestedBlockOrBufferBlockStruct(inst->id()) &&
-      (_.HasDecoration(inst->id(), SpvDecorationBufferBlock) ||
-       _.HasDecoration(inst->id(), SpvDecorationBlock))) {
+      (_.HasDecoration(inst->id(), spv::Decoration::BufferBlock) ||
+       _.HasDecoration(inst->id(), spv::Decoration::Block))) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "rules: A Block or BufferBlock cannot be nested within another "
               "Block or BufferBlock. ";
@@ -377,7 +378,7 @@
 
   std::unordered_set<uint32_t> built_in_members;
   for (auto decoration : _.id_decorations(struct_id)) {
-    if (decoration.dec_type() == SpvDecorationBuiltIn &&
+    if (decoration.dec_type() == spv::Decoration::BuiltIn &&
         decoration.struct_member_index() != Decoration::kInvalidMember) {
       built_in_members.insert(decoration.struct_member_index());
     }
@@ -398,9 +399,9 @@
 
   const auto isOpaqueType = [&_](const Instruction* opaque_inst) {
     auto opcode = opaque_inst->opcode();
-    if (_.HasCapability(SpvCapabilityBindlessTextureNV) &&
-        (opcode == SpvOpTypeImage || opcode == SpvOpTypeSampler ||
-         opcode == SpvOpTypeSampledImage)) {
+    if (_.HasCapability(spv::Capability::BindlessTextureNV) &&
+        (opcode == spv::Op::OpTypeImage || opcode == spv::Op::OpTypeSampler ||
+         opcode == spv::Op::OpTypeSampledImage)) {
       return false;
     } else if (spvOpcodeIsBaseOpaqueType(opcode)) {
       return true;
@@ -430,15 +431,15 @@
            << " is not a type.";
   }
   // See if this points to a storage image.
-  const auto storage_class = inst->GetOperandAs<SpvStorageClass>(1);
-  if (storage_class == SpvStorageClassUniformConstant) {
+  const auto storage_class = inst->GetOperandAs<spv::StorageClass>(1);
+  if (storage_class == spv::StorageClass::UniformConstant) {
     // Unpack an optional level of arraying.
-    if (type->opcode() == SpvOpTypeArray ||
-        type->opcode() == SpvOpTypeRuntimeArray) {
+    if (type->opcode() == spv::Op::OpTypeArray ||
+        type->opcode() == spv::Op::OpTypeRuntimeArray) {
       type_id = type->GetOperandAs<uint32_t>(1);
       type = _.FindDef(type_id);
     }
-    if (type->opcode() == SpvOpTypeImage) {
+    if (type->opcode() == spv::Op::OpTypeImage) {
       const auto sampled = type->GetOperandAs<uint32_t>(6);
       // 2 indicates this image is known to be be used without a sampler, i.e.
       // a storage image.
@@ -475,7 +476,7 @@
              << " is not a type.";
     }
 
-    if (param_type->opcode() == SpvOpTypeVoid) {
+    if (param_type->opcode() == spv::Op::OpTypeVoid) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << "OpTypeFunction Parameter Type <id> " << _.getIdName(param_id)
              << " cannot be OpTypeVoid.";
@@ -495,8 +496,9 @@
   // decoration instruction.
   for (auto& pair : inst->uses()) {
     const auto* use = pair.first;
-    if (use->opcode() != SpvOpFunction && !spvOpcodeIsDebug(use->opcode()) &&
-        !use->IsNonSemantic() && !spvOpcodeIsDecoration(use->opcode())) {
+    if (use->opcode() != spv::Op::OpFunction &&
+        !spvOpcodeIsDebug(use->opcode()) && !use->IsNonSemantic() &&
+        !spvOpcodeIsDecoration(use->opcode())) {
       return _.diag(SPV_ERROR_INVALID_ID, use)
              << "Invalid use of function type result id "
              << _.getIdName(inst->id()) << ".";
@@ -510,13 +512,13 @@
                                         const Instruction* inst) {
   const auto pointer_type_id = inst->GetOperandAs<uint32_t>(0);
   const auto pointer_type_inst = _.FindDef(pointer_type_id);
-  if (pointer_type_inst->opcode() != SpvOpTypePointer) {
+  if (pointer_type_inst->opcode() != spv::Op::OpTypePointer) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Pointer type in OpTypeForwardPointer is not a pointer type.";
   }
 
-  const auto storage_class = inst->GetOperandAs<SpvStorageClass>(1);
-  if (storage_class != pointer_type_inst->GetOperandAs<uint32_t>(1)) {
+  const auto storage_class = inst->GetOperandAs<spv::StorageClass>(1);
+  if (storage_class != pointer_type_inst->GetOperandAs<spv::StorageClass>(1)) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Storage class in OpTypeForwardPointer does not match the "
            << "pointer definition.";
@@ -524,13 +526,13 @@
 
   const auto pointee_type_id = pointer_type_inst->GetOperandAs<uint32_t>(2);
   const auto pointee_type = _.FindDef(pointee_type_id);
-  if (!pointee_type || pointee_type->opcode() != SpvOpTypeStruct) {
+  if (!pointee_type || pointee_type->opcode() != spv::Op::OpTypeStruct) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "Forward pointers must point to a structure";
   }
 
   if (spvIsVulkanEnv(_.context()->target_env)) {
-    if (storage_class != SpvStorageClassPhysicalStorageBuffer) {
+    if (storage_class != spv::StorageClass::PhysicalStorageBuffer) {
       return _.diag(SPV_ERROR_INVALID_ID, inst)
              << _.VkErrorID(4711)
              << "In Vulkan, OpTypeForwardPointer must have "
@@ -547,8 +549,8 @@
   const auto component_type_id =
       inst->GetOperandAs<uint32_t>(component_type_index);
   const auto component_type = _.FindDef(component_type_id);
-  if (!component_type || (SpvOpTypeFloat != component_type->opcode() &&
-                          SpvOpTypeInt != component_type->opcode())) {
+  if (!component_type || (spv::Op::OpTypeFloat != component_type->opcode() &&
+                          spv::Op::OpTypeInt != component_type->opcode())) {
     return _.diag(SPV_ERROR_INVALID_ID, inst)
            << "OpTypeCooperativeMatrixNV Component Type <id> "
            << _.getIdName(component_type_id)
@@ -591,44 +593,44 @@
 
 spv_result_t TypePass(ValidationState_t& _, const Instruction* inst) {
   if (!spvOpcodeGeneratesType(inst->opcode()) &&
-      inst->opcode() != SpvOpTypeForwardPointer) {
+      inst->opcode() != spv::Op::OpTypeForwardPointer) {
     return SPV_SUCCESS;
   }
 
   if (auto error = ValidateUniqueness(_, inst)) return error;
 
   switch (inst->opcode()) {
-    case SpvOpTypeInt:
+    case spv::Op::OpTypeInt:
       if (auto error = ValidateTypeInt(_, inst)) return error;
       break;
-    case SpvOpTypeFloat:
+    case spv::Op::OpTypeFloat:
       if (auto error = ValidateTypeFloat(_, inst)) return error;
       break;
-    case SpvOpTypeVector:
+    case spv::Op::OpTypeVector:
       if (auto error = ValidateTypeVector(_, inst)) return error;
       break;
-    case SpvOpTypeMatrix:
+    case spv::Op::OpTypeMatrix:
       if (auto error = ValidateTypeMatrix(_, inst)) return error;
       break;
-    case SpvOpTypeArray:
+    case spv::Op::OpTypeArray:
       if (auto error = ValidateTypeArray(_, inst)) return error;
       break;
-    case SpvOpTypeRuntimeArray:
+    case spv::Op::OpTypeRuntimeArray:
       if (auto error = ValidateTypeRuntimeArray(_, inst)) return error;
       break;
-    case SpvOpTypeStruct:
+    case spv::Op::OpTypeStruct:
       if (auto error = ValidateTypeStruct(_, inst)) return error;
       break;
-    case SpvOpTypePointer:
+    case spv::Op::OpTypePointer:
       if (auto error = ValidateTypePointer(_, inst)) return error;
       break;
-    case SpvOpTypeFunction:
+    case spv::Op::OpTypeFunction:
       if (auto error = ValidateTypeFunction(_, inst)) return error;
       break;
-    case SpvOpTypeForwardPointer:
+    case spv::Op::OpTypeForwardPointer:
       if (auto error = ValidateTypeForwardPointer(_, inst)) return error;
       break;
-    case SpvOpTypeCooperativeMatrixNV:
+    case spv::Op::OpTypeCooperativeMatrixNV:
       if (auto error = ValidateTypeCooperativeMatrixNV(_, inst)) return error;
       break;
     default:
diff --git a/source/val/validation_state.cpp b/source/val/validation_state.cpp
index 64a0a1a..bb33fb5 100644
--- a/source/val/validation_state.cpp
+++ b/source/val/validation_state.cpp
@@ -31,66 +31,66 @@
 namespace {
 
 ModuleLayoutSection InstructionLayoutSection(
-    ModuleLayoutSection current_section, SpvOp op) {
+    ModuleLayoutSection current_section, spv::Op op) {
   // See Section 2.4
   if (spvOpcodeGeneratesType(op) || spvOpcodeIsConstant(op))
     return kLayoutTypes;
 
   switch (op) {
-    case SpvOpCapability:
+    case spv::Op::OpCapability:
       return kLayoutCapabilities;
-    case SpvOpExtension:
+    case spv::Op::OpExtension:
       return kLayoutExtensions;
-    case SpvOpExtInstImport:
+    case spv::Op::OpExtInstImport:
       return kLayoutExtInstImport;
-    case SpvOpMemoryModel:
+    case spv::Op::OpMemoryModel:
       return kLayoutMemoryModel;
-    case SpvOpEntryPoint:
+    case spv::Op::OpEntryPoint:
       return kLayoutEntryPoint;
-    case SpvOpExecutionMode:
-    case SpvOpExecutionModeId:
+    case spv::Op::OpExecutionMode:
+    case spv::Op::OpExecutionModeId:
       return kLayoutExecutionMode;
-    case SpvOpSourceContinued:
-    case SpvOpSource:
-    case SpvOpSourceExtension:
-    case SpvOpString:
+    case spv::Op::OpSourceContinued:
+    case spv::Op::OpSource:
+    case spv::Op::OpSourceExtension:
+    case spv::Op::OpString:
       return kLayoutDebug1;
-    case SpvOpName:
-    case SpvOpMemberName:
+    case spv::Op::OpName:
+    case spv::Op::OpMemberName:
       return kLayoutDebug2;
-    case SpvOpModuleProcessed:
+    case spv::Op::OpModuleProcessed:
       return kLayoutDebug3;
-    case SpvOpDecorate:
-    case SpvOpMemberDecorate:
-    case SpvOpGroupDecorate:
-    case SpvOpGroupMemberDecorate:
-    case SpvOpDecorationGroup:
-    case SpvOpDecorateId:
-    case SpvOpDecorateStringGOOGLE:
-    case SpvOpMemberDecorateStringGOOGLE:
+    case spv::Op::OpDecorate:
+    case spv::Op::OpMemberDecorate:
+    case spv::Op::OpGroupDecorate:
+    case spv::Op::OpGroupMemberDecorate:
+    case spv::Op::OpDecorationGroup:
+    case spv::Op::OpDecorateId:
+    case spv::Op::OpDecorateStringGOOGLE:
+    case spv::Op::OpMemberDecorateStringGOOGLE:
       return kLayoutAnnotations;
-    case SpvOpTypeForwardPointer:
+    case spv::Op::OpTypeForwardPointer:
       return kLayoutTypes;
-    case SpvOpVariable:
+    case spv::Op::OpVariable:
       if (current_section == kLayoutTypes) return kLayoutTypes;
       return kLayoutFunctionDefinitions;
-    case SpvOpExtInst:
-      // SpvOpExtInst is only allowed in types section for certain extended
-      // instruction sets. This will be checked separately.
+    case spv::Op::OpExtInst:
+      // spv::Op::OpExtInst is only allowed in types section for certain
+      // extended instruction sets. This will be checked separately.
       if (current_section == kLayoutTypes) return kLayoutTypes;
       return kLayoutFunctionDefinitions;
-    case SpvOpLine:
-    case SpvOpNoLine:
-    case SpvOpUndef:
+    case spv::Op::OpLine:
+    case spv::Op::OpNoLine:
+    case spv::Op::OpUndef:
       if (current_section == kLayoutTypes) return kLayoutTypes;
       return kLayoutFunctionDefinitions;
-    case SpvOpFunction:
-    case SpvOpFunctionParameter:
-    case SpvOpFunctionEnd:
+    case spv::Op::OpFunction:
+    case spv::Op::OpFunctionParameter:
+    case spv::Op::OpFunctionEnd:
       if (current_section == kLayoutFunctionDeclarations)
         return kLayoutFunctionDeclarations;
       return kLayoutFunctionDefinitions;
-    case SpvOpSamplerImageAddressingModeNV:
+    case spv::Op::OpSamplerImageAddressingModeNV:
       return kLayoutSamplerImageAddressMode;
     default:
       break;
@@ -98,7 +98,7 @@
   return kLayoutFunctionDefinitions;
 }
 
-bool IsInstructionInLayoutSection(ModuleLayoutSection layout, SpvOp op) {
+bool IsInstructionInLayoutSection(ModuleLayoutSection layout, spv::Op op) {
   return layout == InstructionLayoutSection(layout, op);
 }
 
@@ -106,7 +106,9 @@
 spv_result_t CountInstructions(void* user_data,
                                const spv_parsed_instruction_t* inst) {
   ValidationState_t& _ = *(reinterpret_cast<ValidationState_t*>(user_data));
-  if (inst->opcode == SpvOpFunction) _.increment_total_functions();
+  if (spv::Op(inst->opcode) == spv::Op::OpFunction) {
+    _.increment_total_functions();
+  }
   _.increment_total_instructions();
 
   return SPV_SUCCESS;
@@ -160,8 +162,8 @@
       struct_nesting_depth_(),
       struct_has_nested_blockorbufferblock_struct_(),
       grammar_(ctx),
-      addressing_model_(SpvAddressingModelMax),
-      memory_model_(SpvMemoryModelMax),
+      addressing_model_(spv::AddressingModel::Max),
+      memory_model_(spv::MemoryModel::Max),
       pointer_size_and_alignment_(0),
       sampler_image_addressing_mode_(0),
       in_function_(false),
@@ -290,13 +292,13 @@
   }
 }
 
-bool ValidationState_t::IsOpcodeInPreviousLayoutSection(SpvOp op) {
+bool ValidationState_t::IsOpcodeInPreviousLayoutSection(spv::Op op) {
   ModuleLayoutSection section =
       InstructionLayoutSection(current_layout_section_, op);
   return section < current_layout_section_;
 }
 
-bool ValidationState_t::IsOpcodeInCurrentLayoutSection(SpvOp op) {
+bool ValidationState_t::IsOpcodeInCurrentLayoutSection(spv::Op op) {
   return IsInstructionInLayoutSection(current_layout_section_, op);
 }
 
@@ -353,7 +355,7 @@
          module_functions_.back().current_block() != nullptr;
 }
 
-void ValidationState_t::RegisterCapability(SpvCapability cap) {
+void ValidationState_t::RegisterCapability(spv::Capability cap) {
   // Avoid redundant work.  Otherwise the recursion could induce work
   // quadrdatic in the capability dependency depth. (Ok, not much, but
   // it's something.)
@@ -361,51 +363,51 @@
 
   module_capabilities_.Add(cap);
   spv_operand_desc desc;
-  if (SPV_SUCCESS ==
-      grammar_.lookupOperand(SPV_OPERAND_TYPE_CAPABILITY, cap, &desc)) {
+  if (SPV_SUCCESS == grammar_.lookupOperand(SPV_OPERAND_TYPE_CAPABILITY,
+                                            uint32_t(cap), &desc)) {
     CapabilitySet(desc->numCapabilities, desc->capabilities)
-        .ForEach([this](SpvCapability c) { RegisterCapability(c); });
+        .ForEach([this](spv::Capability c) { RegisterCapability(c); });
   }
 
   switch (cap) {
-    case SpvCapabilityKernel:
+    case spv::Capability::Kernel:
       features_.group_ops_reduce_and_scans = true;
       break;
-    case SpvCapabilityInt8:
+    case spv::Capability::Int8:
       features_.use_int8_type = true;
       features_.declare_int8_type = true;
       break;
-    case SpvCapabilityStorageBuffer8BitAccess:
-    case SpvCapabilityUniformAndStorageBuffer8BitAccess:
-    case SpvCapabilityStoragePushConstant8:
-    case SpvCapabilityWorkgroupMemoryExplicitLayout8BitAccessKHR:
+    case spv::Capability::StorageBuffer8BitAccess:
+    case spv::Capability::UniformAndStorageBuffer8BitAccess:
+    case spv::Capability::StoragePushConstant8:
+    case spv::Capability::WorkgroupMemoryExplicitLayout8BitAccessKHR:
       features_.declare_int8_type = true;
       break;
-    case SpvCapabilityInt16:
+    case spv::Capability::Int16:
       features_.declare_int16_type = true;
       break;
-    case SpvCapabilityFloat16:
-    case SpvCapabilityFloat16Buffer:
+    case spv::Capability::Float16:
+    case spv::Capability::Float16Buffer:
       features_.declare_float16_type = true;
       break;
-    case SpvCapabilityStorageUniformBufferBlock16:
-    case SpvCapabilityStorageUniform16:
-    case SpvCapabilityStoragePushConstant16:
-    case SpvCapabilityStorageInputOutput16:
-    case SpvCapabilityWorkgroupMemoryExplicitLayout16BitAccessKHR:
+    case spv::Capability::StorageUniformBufferBlock16:
+    case spv::Capability::StorageUniform16:
+    case spv::Capability::StoragePushConstant16:
+    case spv::Capability::StorageInputOutput16:
+    case spv::Capability::WorkgroupMemoryExplicitLayout16BitAccessKHR:
       features_.declare_int16_type = true;
       features_.declare_float16_type = true;
       features_.free_fp_rounding_mode = true;
       break;
-    case SpvCapabilityVariablePointers:
-    case SpvCapabilityVariablePointersStorageBuffer:
+    case spv::Capability::VariablePointers:
+    case spv::Capability::VariablePointersStorageBuffer:
       features_.variable_pointers = true;
       break;
     default:
       // TODO(dneto): For now don't validate SPV_NV_ray_tracing, which uses
-      // capability SpvCapabilityRayTracingNV.
-      // SpvCapabilityRayTracingProvisionalKHR would need the same treatment.
-      // One of the differences going from SPV_KHR_ray_tracing from
+      // capability spv::Capability::RayTracingNV.
+      // spv::Capability::RayTracingProvisionalKHR would need the same
+      // treatment. One of the differences going from SPV_KHR_ray_tracing from
       // provisional to final spec was the provisional spec uses Locations
       // for variables in certain storage classes, just like the
       // SPV_NV_ray_tracing extension.  So it mimics the NVIDIA extension.
@@ -454,30 +456,32 @@
   return module_extensions_.HasAnyOf(extensions);
 }
 
-void ValidationState_t::set_addressing_model(SpvAddressingModel am) {
+void ValidationState_t::set_addressing_model(spv::AddressingModel am) {
   addressing_model_ = am;
   switch (am) {
-    case SpvAddressingModelPhysical32:
+    case spv::AddressingModel::Physical32:
       pointer_size_and_alignment_ = 4;
       break;
     default:
     // fall through
-    case SpvAddressingModelPhysical64:
-    case SpvAddressingModelPhysicalStorageBuffer64:
+    case spv::AddressingModel::Physical64:
+    case spv::AddressingModel::PhysicalStorageBuffer64:
       pointer_size_and_alignment_ = 8;
       break;
   }
 }
 
-SpvAddressingModel ValidationState_t::addressing_model() const {
+spv::AddressingModel ValidationState_t::addressing_model() const {
   return addressing_model_;
 }
 
-void ValidationState_t::set_memory_model(SpvMemoryModel mm) {
+void ValidationState_t::set_memory_model(spv::MemoryModel mm) {
   memory_model_ = mm;
 }
 
-SpvMemoryModel ValidationState_t::memory_model() const { return memory_model_; }
+spv::MemoryModel ValidationState_t::memory_model() const {
+  return memory_model_;
+}
 
 void ValidationState_t::set_samplerimage_variable_address_mode(
     uint32_t bit_width) {
@@ -489,8 +493,8 @@
 }
 
 spv_result_t ValidationState_t::RegisterFunction(
-    uint32_t id, uint32_t ret_type_id, SpvFunctionControlMask function_control,
-    uint32_t function_type_id) {
+    uint32_t id, uint32_t ret_type_id,
+    spv::FunctionControlMask function_control, uint32_t function_type_id) {
   assert(in_function_body() == false &&
          "RegisterFunction can only be called when parsing the binary outside "
          "of another function");
@@ -526,24 +530,24 @@
 // Improves diagnostic messages by collecting names of IDs
 void ValidationState_t::RegisterDebugInstruction(const Instruction* inst) {
   switch (inst->opcode()) {
-    case SpvOpName: {
+    case spv::Op::OpName: {
       const auto target = inst->GetOperandAs<uint32_t>(0);
       const std::string str = inst->GetOperandAs<std::string>(1);
       AssignNameToId(target, str);
       break;
     }
-    case SpvOpMemberName: {
+    case spv::Op::OpMemberName: {
       const auto target = inst->GetOperandAs<uint32_t>(0);
       const std::string str = inst->GetOperandAs<std::string>(2);
       AssignNameToId(target, str);
       break;
     }
-    case SpvOpSourceContinued:
-    case SpvOpSource:
-    case SpvOpSourceExtension:
-    case SpvOpString:
-    case SpvOpLine:
-    case SpvOpNoLine:
+    case spv::Op::OpSourceContinued:
+    case spv::Op::OpSource:
+    case spv::Op::OpSourceExtension:
+    case spv::Op::OpString:
+    case spv::Op::OpLine:
+    case spv::Op::OpNoLine:
     default:
       break;
   }
@@ -567,7 +571,7 @@
       // should be recorded. The validator will ensure that all usages of an
       // OpTypeSampledImage and its definition are in the same basic block.
       if ((SPV_OPERAND_TYPE_ID == operand.type) &&
-          (SpvOpSampledImage == operand_inst->opcode())) {
+          (spv::Op::OpSampledImage == operand_inst->opcode())) {
         RegisterSampledImageConsumer(operand_word, inst);
       }
 
@@ -577,12 +581,12 @@
       // Instead just need to register storage class usage for consumers in a
       // function block.
       if (inst->function()) {
-        if (operand_inst->opcode() == SpvOpTypePointer) {
+        if (operand_inst->opcode() == spv::Op::OpTypePointer) {
           RegisterStorageClassConsumer(
-              operand_inst->GetOperandAs<SpvStorageClass>(1), inst);
-        } else if (operand_inst->opcode() == SpvOpVariable) {
+              operand_inst->GetOperandAs<spv::StorageClass>(1), inst);
+        } else if (operand_inst->opcode() == spv::Op::OpVariable) {
           RegisterStorageClassConsumer(
-              operand_inst->GetOperandAs<SpvStorageClass>(2), inst);
+              operand_inst->GetOperandAs<spv::StorageClass>(2), inst);
         }
       }
     }
@@ -605,21 +609,21 @@
 }
 
 void ValidationState_t::RegisterStorageClassConsumer(
-    SpvStorageClass storage_class, Instruction* consumer) {
+    spv::StorageClass storage_class, Instruction* consumer) {
   if (spvIsVulkanEnv(context()->target_env)) {
-    if (storage_class == SpvStorageClassOutput) {
+    if (storage_class == spv::StorageClass::Output) {
       std::string errorVUID = VkErrorID(4644);
       function(consumer->function()->id())
           ->RegisterExecutionModelLimitation([errorVUID](
-                                                 SpvExecutionModel model,
+                                                 spv::ExecutionModel model,
                                                  std::string* message) {
-            if (model == SpvExecutionModelGLCompute ||
-                model == SpvExecutionModelRayGenerationKHR ||
-                model == SpvExecutionModelIntersectionKHR ||
-                model == SpvExecutionModelAnyHitKHR ||
-                model == SpvExecutionModelClosestHitKHR ||
-                model == SpvExecutionModelMissKHR ||
-                model == SpvExecutionModelCallableKHR) {
+            if (model == spv::ExecutionModel::GLCompute ||
+                model == spv::ExecutionModel::RayGenerationKHR ||
+                model == spv::ExecutionModel::IntersectionKHR ||
+                model == spv::ExecutionModel::AnyHitKHR ||
+                model == spv::ExecutionModel::ClosestHitKHR ||
+                model == spv::ExecutionModel::MissKHR ||
+                model == spv::ExecutionModel::CallableKHR) {
               if (message) {
                 *message =
                     errorVUID +
@@ -634,17 +638,17 @@
           });
     }
 
-    if (storage_class == SpvStorageClassWorkgroup) {
+    if (storage_class == spv::StorageClass::Workgroup) {
       std::string errorVUID = VkErrorID(4645);
       function(consumer->function()->id())
           ->RegisterExecutionModelLimitation([errorVUID](
-                                                 SpvExecutionModel model,
+                                                 spv::ExecutionModel model,
                                                  std::string* message) {
-            if (model != SpvExecutionModelGLCompute &&
-                model != SpvExecutionModelTaskNV &&
-                model != SpvExecutionModelMeshNV &&
-                model != SpvExecutionModelTaskEXT &&
-                model != SpvExecutionModelMeshEXT) {
+            if (model != spv::ExecutionModel::GLCompute &&
+                model != spv::ExecutionModel::TaskNV &&
+                model != spv::ExecutionModel::MeshNV &&
+                model != spv::ExecutionModel::TaskEXT &&
+                model != spv::ExecutionModel::MeshEXT) {
               if (message) {
                 *message =
                     errorVUID +
@@ -658,15 +662,16 @@
     }
   }
 
-  if (storage_class == SpvStorageClassCallableDataKHR) {
+  if (storage_class == spv::StorageClass::CallableDataKHR) {
     std::string errorVUID = VkErrorID(4704);
     function(consumer->function()->id())
-        ->RegisterExecutionModelLimitation([errorVUID](SpvExecutionModel model,
-                                                       std::string* message) {
-          if (model != SpvExecutionModelRayGenerationKHR &&
-              model != SpvExecutionModelClosestHitKHR &&
-              model != SpvExecutionModelCallableKHR &&
-              model != SpvExecutionModelMissKHR) {
+        ->RegisterExecutionModelLimitation([errorVUID](
+                                               spv::ExecutionModel model,
+                                               std::string* message) {
+          if (model != spv::ExecutionModel::RayGenerationKHR &&
+              model != spv::ExecutionModel::ClosestHitKHR &&
+              model != spv::ExecutionModel::CallableKHR &&
+              model != spv::ExecutionModel::MissKHR) {
             if (message) {
               *message = errorVUID +
                          "CallableDataKHR Storage Class is limited to "
@@ -677,12 +682,13 @@
           }
           return true;
         });
-  } else if (storage_class == SpvStorageClassIncomingCallableDataKHR) {
+  } else if (storage_class == spv::StorageClass::IncomingCallableDataKHR) {
     std::string errorVUID = VkErrorID(4705);
     function(consumer->function()->id())
-        ->RegisterExecutionModelLimitation([errorVUID](SpvExecutionModel model,
-                                                       std::string* message) {
-          if (model != SpvExecutionModelCallableKHR) {
+        ->RegisterExecutionModelLimitation([errorVUID](
+                                               spv::ExecutionModel model,
+                                               std::string* message) {
+          if (model != spv::ExecutionModel::CallableKHR) {
             if (message) {
               *message = errorVUID +
                          "IncomingCallableDataKHR Storage Class is limited to "
@@ -692,14 +698,15 @@
           }
           return true;
         });
-  } else if (storage_class == SpvStorageClassRayPayloadKHR) {
+  } else if (storage_class == spv::StorageClass::RayPayloadKHR) {
     std::string errorVUID = VkErrorID(4698);
     function(consumer->function()->id())
-        ->RegisterExecutionModelLimitation([errorVUID](SpvExecutionModel model,
-                                                       std::string* message) {
-          if (model != SpvExecutionModelRayGenerationKHR &&
-              model != SpvExecutionModelClosestHitKHR &&
-              model != SpvExecutionModelMissKHR) {
+        ->RegisterExecutionModelLimitation([errorVUID](
+                                               spv::ExecutionModel model,
+                                               std::string* message) {
+          if (model != spv::ExecutionModel::RayGenerationKHR &&
+              model != spv::ExecutionModel::ClosestHitKHR &&
+              model != spv::ExecutionModel::MissKHR) {
             if (message) {
               *message =
                   errorVUID +
@@ -710,14 +717,14 @@
           }
           return true;
         });
-  } else if (storage_class == SpvStorageClassHitAttributeKHR) {
+  } else if (storage_class == spv::StorageClass::HitAttributeKHR) {
     std::string errorVUID = VkErrorID(4701);
     function(consumer->function()->id())
         ->RegisterExecutionModelLimitation(
-            [errorVUID](SpvExecutionModel model, std::string* message) {
-              if (model != SpvExecutionModelIntersectionKHR &&
-                  model != SpvExecutionModelAnyHitKHR &&
-                  model != SpvExecutionModelClosestHitKHR) {
+            [errorVUID](spv::ExecutionModel model, std::string* message) {
+              if (model != spv::ExecutionModel::IntersectionKHR &&
+                  model != spv::ExecutionModel::AnyHitKHR &&
+                  model != spv::ExecutionModel::ClosestHitKHR) {
                 if (message) {
                   *message = errorVUID +
                              "HitAttributeKHR Storage Class is limited to "
@@ -728,14 +735,14 @@
               }
               return true;
             });
-  } else if (storage_class == SpvStorageClassIncomingRayPayloadKHR) {
+  } else if (storage_class == spv::StorageClass::IncomingRayPayloadKHR) {
     std::string errorVUID = VkErrorID(4699);
     function(consumer->function()->id())
         ->RegisterExecutionModelLimitation(
-            [errorVUID](SpvExecutionModel model, std::string* message) {
-              if (model != SpvExecutionModelAnyHitKHR &&
-                  model != SpvExecutionModelClosestHitKHR &&
-                  model != SpvExecutionModelMissKHR) {
+            [errorVUID](spv::ExecutionModel model, std::string* message) {
+              if (model != spv::ExecutionModel::AnyHitKHR &&
+                  model != spv::ExecutionModel::ClosestHitKHR &&
+                  model != spv::ExecutionModel::MissKHR) {
                 if (message) {
                   *message =
                       errorVUID +
@@ -746,17 +753,17 @@
               }
               return true;
             });
-  } else if (storage_class == SpvStorageClassShaderRecordBufferKHR) {
+  } else if (storage_class == spv::StorageClass::ShaderRecordBufferKHR) {
     std::string errorVUID = VkErrorID(7119);
     function(consumer->function()->id())
         ->RegisterExecutionModelLimitation(
-            [errorVUID](SpvExecutionModel model, std::string* message) {
-              if (model != SpvExecutionModelRayGenerationKHR &&
-                  model != SpvExecutionModelIntersectionKHR &&
-                  model != SpvExecutionModelAnyHitKHR &&
-                  model != SpvExecutionModelClosestHitKHR &&
-                  model != SpvExecutionModelCallableKHR &&
-                  model != SpvExecutionModelMissKHR) {
+            [errorVUID](spv::ExecutionModel model, std::string* message) {
+              if (model != spv::ExecutionModel::RayGenerationKHR &&
+                  model != spv::ExecutionModel::IntersectionKHR &&
+                  model != spv::ExecutionModel::AnyHitKHR &&
+                  model != spv::ExecutionModel::ClosestHitKHR &&
+                  model != spv::ExecutionModel::CallableKHR &&
+                  model != spv::ExecutionModel::MissKHR) {
                 if (message) {
                   *message =
                       errorVUID +
@@ -768,12 +775,12 @@
               }
               return true;
             });
-  } else if (storage_class == SpvStorageClassTaskPayloadWorkgroupEXT) {
+  } else if (storage_class == spv::StorageClass::TaskPayloadWorkgroupEXT) {
     function(consumer->function()->id())
         ->RegisterExecutionModelLimitation(
-            [](SpvExecutionModel model, std::string* message) {
-              if (model != SpvExecutionModelTaskEXT &&
-                  model != SpvExecutionModelMeshEXT) {
+            [](spv::ExecutionModel model, std::string* message) {
+              if (model != spv::ExecutionModel::TaskEXT &&
+                  model != spv::ExecutionModel::MeshEXT) {
                 if (message) {
                   *message =
                       "TaskPayloadWorkgroupEXT Storage Class is limited to "
@@ -814,9 +821,9 @@
   return inst ? inst->type_id() : 0;
 }
 
-SpvOp ValidationState_t::GetIdOpcode(uint32_t id) const {
+spv::Op ValidationState_t::GetIdOpcode(uint32_t id) const {
   const Instruction* inst = FindDef(id);
-  return inst ? inst->opcode() : SpvOpNop;
+  return inst ? inst->opcode() : spv::Op::OpNop;
 }
 
 uint32_t ValidationState_t::GetComponentType(uint32_t id) const {
@@ -824,18 +831,18 @@
   assert(inst);
 
   switch (inst->opcode()) {
-    case SpvOpTypeFloat:
-    case SpvOpTypeInt:
-    case SpvOpTypeBool:
+    case spv::Op::OpTypeFloat:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeBool:
       return id;
 
-    case SpvOpTypeVector:
+    case spv::Op::OpTypeVector:
       return inst->word(2);
 
-    case SpvOpTypeMatrix:
+    case spv::Op::OpTypeMatrix:
       return GetComponentType(inst->word(2));
 
-    case SpvOpTypeCooperativeMatrixNV:
+    case spv::Op::OpTypeCooperativeMatrixNV:
       return inst->word(2);
 
     default:
@@ -853,16 +860,16 @@
   assert(inst);
 
   switch (inst->opcode()) {
-    case SpvOpTypeFloat:
-    case SpvOpTypeInt:
-    case SpvOpTypeBool:
+    case spv::Op::OpTypeFloat:
+    case spv::Op::OpTypeInt:
+    case spv::Op::OpTypeBool:
       return 1;
 
-    case SpvOpTypeVector:
-    case SpvOpTypeMatrix:
+    case spv::Op::OpTypeVector:
+    case spv::Op::OpTypeMatrix:
       return inst->word(3);
 
-    case SpvOpTypeCooperativeMatrixNV:
+    case spv::Op::OpTypeCooperativeMatrixNV:
       // Actual dimension isn't known, return 0
       return 0;
 
@@ -881,10 +888,11 @@
   const Instruction* inst = FindDef(component_type_id);
   assert(inst);
 
-  if (inst->opcode() == SpvOpTypeFloat || inst->opcode() == SpvOpTypeInt)
+  if (inst->opcode() == spv::Op::OpTypeFloat ||
+      inst->opcode() == spv::Op::OpTypeInt)
     return inst->word(2);
 
-  if (inst->opcode() == SpvOpTypeBool) return 1;
+  if (inst->opcode() == spv::Op::OpTypeBool) return 1;
 
   assert(0);
   return 0;
@@ -892,12 +900,12 @@
 
 bool ValidationState_t::IsVoidType(uint32_t id) const {
   const Instruction* inst = FindDef(id);
-  return inst && inst->opcode() == SpvOpTypeVoid;
+  return inst && inst->opcode() == spv::Op::OpTypeVoid;
 }
 
 bool ValidationState_t::IsFloatScalarType(uint32_t id) const {
   const Instruction* inst = FindDef(id);
-  return inst && inst->opcode() == SpvOpTypeFloat;
+  return inst && inst->opcode() == spv::Op::OpTypeFloat;
 }
 
 bool ValidationState_t::IsFloatVectorType(uint32_t id) const {
@@ -906,7 +914,7 @@
     return false;
   }
 
-  if (inst->opcode() == SpvOpTypeVector) {
+  if (inst->opcode() == spv::Op::OpTypeVector) {
     return IsFloatScalarType(GetComponentType(id));
   }
 
@@ -919,11 +927,11 @@
     return false;
   }
 
-  if (inst->opcode() == SpvOpTypeFloat) {
+  if (inst->opcode() == spv::Op::OpTypeFloat) {
     return true;
   }
 
-  if (inst->opcode() == SpvOpTypeVector) {
+  if (inst->opcode() == spv::Op::OpTypeVector) {
     return IsFloatScalarType(GetComponentType(id));
   }
 
@@ -932,7 +940,7 @@
 
 bool ValidationState_t::IsIntScalarType(uint32_t id) const {
   const Instruction* inst = FindDef(id);
-  return inst && inst->opcode() == SpvOpTypeInt;
+  return inst && inst->opcode() == spv::Op::OpTypeInt;
 }
 
 bool ValidationState_t::IsIntVectorType(uint32_t id) const {
@@ -941,7 +949,7 @@
     return false;
   }
 
-  if (inst->opcode() == SpvOpTypeVector) {
+  if (inst->opcode() == spv::Op::OpTypeVector) {
     return IsIntScalarType(GetComponentType(id));
   }
 
@@ -954,11 +962,11 @@
     return false;
   }
 
-  if (inst->opcode() == SpvOpTypeInt) {
+  if (inst->opcode() == spv::Op::OpTypeInt) {
     return true;
   }
 
-  if (inst->opcode() == SpvOpTypeVector) {
+  if (inst->opcode() == spv::Op::OpTypeVector) {
     return IsIntScalarType(GetComponentType(id));
   }
 
@@ -967,7 +975,7 @@
 
 bool ValidationState_t::IsUnsignedIntScalarType(uint32_t id) const {
   const Instruction* inst = FindDef(id);
-  return inst && inst->opcode() == SpvOpTypeInt && inst->word(3) == 0;
+  return inst && inst->opcode() == spv::Op::OpTypeInt && inst->word(3) == 0;
 }
 
 bool ValidationState_t::IsUnsignedIntVectorType(uint32_t id) const {
@@ -976,7 +984,7 @@
     return false;
   }
 
-  if (inst->opcode() == SpvOpTypeVector) {
+  if (inst->opcode() == spv::Op::OpTypeVector) {
     return IsUnsignedIntScalarType(GetComponentType(id));
   }
 
@@ -985,7 +993,7 @@
 
 bool ValidationState_t::IsSignedIntScalarType(uint32_t id) const {
   const Instruction* inst = FindDef(id);
-  return inst && inst->opcode() == SpvOpTypeInt && inst->word(3) == 1;
+  return inst && inst->opcode() == spv::Op::OpTypeInt && inst->word(3) == 1;
 }
 
 bool ValidationState_t::IsSignedIntVectorType(uint32_t id) const {
@@ -994,7 +1002,7 @@
     return false;
   }
 
-  if (inst->opcode() == SpvOpTypeVector) {
+  if (inst->opcode() == spv::Op::OpTypeVector) {
     return IsSignedIntScalarType(GetComponentType(id));
   }
 
@@ -1003,7 +1011,7 @@
 
 bool ValidationState_t::IsBoolScalarType(uint32_t id) const {
   const Instruction* inst = FindDef(id);
-  return inst && inst->opcode() == SpvOpTypeBool;
+  return inst && inst->opcode() == spv::Op::OpTypeBool;
 }
 
 bool ValidationState_t::IsBoolVectorType(uint32_t id) const {
@@ -1012,7 +1020,7 @@
     return false;
   }
 
-  if (inst->opcode() == SpvOpTypeVector) {
+  if (inst->opcode() == spv::Op::OpTypeVector) {
     return IsBoolScalarType(GetComponentType(id));
   }
 
@@ -1025,11 +1033,11 @@
     return false;
   }
 
-  if (inst->opcode() == SpvOpTypeBool) {
+  if (inst->opcode() == spv::Op::OpTypeBool) {
     return true;
   }
 
-  if (inst->opcode() == SpvOpTypeVector) {
+  if (inst->opcode() == spv::Op::OpTypeVector) {
     return IsBoolScalarType(GetComponentType(id));
   }
 
@@ -1042,7 +1050,7 @@
     return false;
   }
 
-  if (inst->opcode() == SpvOpTypeMatrix) {
+  if (inst->opcode() == spv::Op::OpTypeMatrix) {
     return IsFloatScalarType(GetComponentType(id));
   }
 
@@ -1057,13 +1065,13 @@
 
   const Instruction* mat_inst = FindDef(id);
   assert(mat_inst);
-  if (mat_inst->opcode() != SpvOpTypeMatrix) return false;
+  if (mat_inst->opcode() != spv::Op::OpTypeMatrix) return false;
 
   const uint32_t vec_type = mat_inst->word(2);
   const Instruction* vec_inst = FindDef(vec_type);
   assert(vec_inst);
 
-  if (vec_inst->opcode() != SpvOpTypeVector) {
+  if (vec_inst->opcode() != spv::Op::OpTypeVector) {
     assert(0);
     return false;
   }
@@ -1083,7 +1091,7 @@
 
   const Instruction* inst = FindDef(struct_type_id);
   assert(inst);
-  if (inst->opcode() != SpvOpTypeStruct) return false;
+  if (inst->opcode() != spv::Op::OpTypeStruct) return false;
 
   *member_types =
       std::vector<uint32_t>(inst->words().cbegin() + 2, inst->words().cend());
@@ -1095,30 +1103,31 @@
 
 bool ValidationState_t::IsPointerType(uint32_t id) const {
   const Instruction* inst = FindDef(id);
-  return inst && inst->opcode() == SpvOpTypePointer;
+  return inst && inst->opcode() == spv::Op::OpTypePointer;
 }
 
-bool ValidationState_t::GetPointerTypeInfo(uint32_t id, uint32_t* data_type,
-                                           uint32_t* storage_class) const {
+bool ValidationState_t::GetPointerTypeInfo(
+    uint32_t id, uint32_t* data_type, spv::StorageClass* storage_class) const {
+  *storage_class = spv::StorageClass::Max;
   if (!id) return false;
 
   const Instruction* inst = FindDef(id);
   assert(inst);
-  if (inst->opcode() != SpvOpTypePointer) return false;
+  if (inst->opcode() != spv::Op::OpTypePointer) return false;
 
-  *storage_class = inst->word(2);
+  *storage_class = spv::StorageClass(inst->word(2));
   *data_type = inst->word(3);
   return true;
 }
 
 bool ValidationState_t::IsAccelerationStructureType(uint32_t id) const {
   const Instruction* inst = FindDef(id);
-  return inst && inst->opcode() == SpvOpTypeAccelerationStructureKHR;
+  return inst && inst->opcode() == spv::Op::OpTypeAccelerationStructureKHR;
 }
 
 bool ValidationState_t::IsCooperativeMatrixType(uint32_t id) const {
   const Instruction* inst = FindDef(id);
-  return inst && inst->opcode() == SpvOpTypeCooperativeMatrixNV;
+  return inst && inst->opcode() == spv::Op::OpTypeCooperativeMatrixNV;
 }
 
 bool ValidationState_t::IsFloatCooperativeMatrixType(uint32_t id) const {
@@ -1148,8 +1157,8 @@
   const auto m1_type = FindDef(m1);
   const auto m2_type = FindDef(m2);
 
-  if (m1_type->opcode() != SpvOpTypeCooperativeMatrixNV ||
-      m2_type->opcode() != SpvOpTypeCooperativeMatrixNV) {
+  if (m1_type->opcode() != spv::Op::OpTypeCooperativeMatrixNV ||
+      m2_type->opcode() != spv::Op::OpTypeCooperativeMatrixNV) {
     return diag(SPV_ERROR_INVALID_DATA, inst)
            << "Expected cooperative matrix types";
   }
@@ -1214,7 +1223,8 @@
     return false;
   }
 
-  if (inst->opcode() != SpvOpConstant && inst->opcode() != SpvOpSpecConstant)
+  if (inst->opcode() != spv::Op::OpConstant &&
+      inst->opcode() != spv::Op::OpSpecConstant)
     return false;
 
   if (!IsIntScalarType(inst->type_id())) return false;
@@ -1246,7 +1256,7 @@
     return std::make_tuple(true, false, 0);
   }
 
-  if (inst->opcode() == SpvOpConstantNull) {
+  if (inst->opcode() == spv::Op::OpConstantNull) {
     return std::make_tuple(true, true, 0);
   }
 
@@ -1380,7 +1390,7 @@
     }
   }
 
-  if (lhs->opcode() == SpvOpTypeArray) {
+  if (lhs->opcode() == spv::Op::OpTypeArray) {
     // Size operands must match.
     if (lhs->GetOperandAs<uint32_t>(2u) != rhs->GetOperandAs<uint32_t>(2u)) {
       return false;
@@ -1399,7 +1409,7 @@
       return false;
     }
     return LogicallyMatch(lhs_ele, rhs_ele, check_decorations);
-  } else if (lhs->opcode() == SpvOpTypeStruct) {
+  } else if (lhs->opcode() == spv::Op::OpTypeStruct) {
     // Number of elements must match.
     if (lhs->operands().size() != rhs->operands().size()) {
       return false;
@@ -1437,11 +1447,11 @@
 const Instruction* ValidationState_t::TracePointer(
     const Instruction* inst) const {
   auto base_ptr = inst;
-  while (base_ptr->opcode() == SpvOpAccessChain ||
-         base_ptr->opcode() == SpvOpInBoundsAccessChain ||
-         base_ptr->opcode() == SpvOpPtrAccessChain ||
-         base_ptr->opcode() == SpvOpInBoundsPtrAccessChain ||
-         base_ptr->opcode() == SpvOpCopyObject) {
+  while (base_ptr->opcode() == spv::Op::OpAccessChain ||
+         base_ptr->opcode() == spv::Op::OpInBoundsAccessChain ||
+         base_ptr->opcode() == spv::Op::OpPtrAccessChain ||
+         base_ptr->opcode() == spv::Op::OpInBoundsPtrAccessChain ||
+         base_ptr->opcode() == spv::Op::OpCopyObject) {
     base_ptr = FindDef(base_ptr->GetOperandAs<uint32_t>(2u));
   }
   return base_ptr;
@@ -1456,25 +1466,25 @@
   if (f(inst)) return true;
 
   switch (inst->opcode()) {
-    case SpvOpTypeArray:
-    case SpvOpTypeRuntimeArray:
-    case SpvOpTypeVector:
-    case SpvOpTypeMatrix:
-    case SpvOpTypeImage:
-    case SpvOpTypeSampledImage:
-    case SpvOpTypeCooperativeMatrixNV:
+    case spv::Op::OpTypeArray:
+    case spv::Op::OpTypeRuntimeArray:
+    case spv::Op::OpTypeVector:
+    case spv::Op::OpTypeMatrix:
+    case spv::Op::OpTypeImage:
+    case spv::Op::OpTypeSampledImage:
+    case spv::Op::OpTypeCooperativeMatrixNV:
       return ContainsType(inst->GetOperandAs<uint32_t>(1u), f,
                           traverse_all_types);
-    case SpvOpTypePointer:
+    case spv::Op::OpTypePointer:
       if (IsForwardPointer(id)) return false;
       if (traverse_all_types) {
         return ContainsType(inst->GetOperandAs<uint32_t>(2u), f,
                             traverse_all_types);
       }
       break;
-    case SpvOpTypeFunction:
-    case SpvOpTypeStruct:
-      if (inst->opcode() == SpvOpTypeFunction && !traverse_all_types) {
+    case spv::Op::OpTypeFunction:
+    case spv::Op::OpTypeStruct:
+      if (inst->opcode() == spv::Op::OpTypeFunction && !traverse_all_types) {
         return false;
       }
       for (uint32_t i = 1; i < inst->operands().size(); ++i) {
@@ -1491,9 +1501,9 @@
   return false;
 }
 
-bool ValidationState_t::ContainsSizedIntOrFloatType(uint32_t id, SpvOp type,
+bool ValidationState_t::ContainsSizedIntOrFloatType(uint32_t id, spv::Op type,
                                                     uint32_t width) const {
-  if (type != SpvOpTypeInt && type != SpvOpTypeFloat) return false;
+  if (type != spv::Op::OpTypeInt && type != spv::Op::OpTypeFloat) return false;
 
   const auto f = [type, width](const Instruction* inst) {
     if (inst->opcode() == type) {
@@ -1505,12 +1515,12 @@
 }
 
 bool ValidationState_t::ContainsLimitedUseIntOrFloatType(uint32_t id) const {
-  if ((!HasCapability(SpvCapabilityInt16) &&
-       ContainsSizedIntOrFloatType(id, SpvOpTypeInt, 16)) ||
-      (!HasCapability(SpvCapabilityInt8) &&
-       ContainsSizedIntOrFloatType(id, SpvOpTypeInt, 8)) ||
-      (!HasCapability(SpvCapabilityFloat16) &&
-       ContainsSizedIntOrFloatType(id, SpvOpTypeFloat, 16))) {
+  if ((!HasCapability(spv::Capability::Int16) &&
+       ContainsSizedIntOrFloatType(id, spv::Op::OpTypeInt, 16)) ||
+      (!HasCapability(spv::Capability::Int8) &&
+       ContainsSizedIntOrFloatType(id, spv::Op::OpTypeInt, 8)) ||
+      (!HasCapability(spv::Capability::Float16) &&
+       ContainsSizedIntOrFloatType(id, spv::Op::OpTypeFloat, 16))) {
     return true;
   }
   return false;
@@ -1518,33 +1528,33 @@
 
 bool ValidationState_t::ContainsRuntimeArray(uint32_t id) const {
   const auto f = [](const Instruction* inst) {
-    return inst->opcode() == SpvOpTypeRuntimeArray;
+    return inst->opcode() == spv::Op::OpTypeRuntimeArray;
   };
   return ContainsType(id, f, /* traverse_all_types = */ false);
 }
 
 bool ValidationState_t::IsValidStorageClass(
-    SpvStorageClass storage_class) const {
+    spv::StorageClass storage_class) const {
   if (spvIsVulkanEnv(context()->target_env)) {
     switch (storage_class) {
-      case SpvStorageClassUniformConstant:
-      case SpvStorageClassUniform:
-      case SpvStorageClassStorageBuffer:
-      case SpvStorageClassInput:
-      case SpvStorageClassOutput:
-      case SpvStorageClassImage:
-      case SpvStorageClassWorkgroup:
-      case SpvStorageClassPrivate:
-      case SpvStorageClassFunction:
-      case SpvStorageClassPushConstant:
-      case SpvStorageClassPhysicalStorageBuffer:
-      case SpvStorageClassRayPayloadKHR:
-      case SpvStorageClassIncomingRayPayloadKHR:
-      case SpvStorageClassHitAttributeKHR:
-      case SpvStorageClassCallableDataKHR:
-      case SpvStorageClassIncomingCallableDataKHR:
-      case SpvStorageClassShaderRecordBufferKHR:
-      case SpvStorageClassTaskPayloadWorkgroupEXT:
+      case spv::StorageClass::UniformConstant:
+      case spv::StorageClass::Uniform:
+      case spv::StorageClass::StorageBuffer:
+      case spv::StorageClass::Input:
+      case spv::StorageClass::Output:
+      case spv::StorageClass::Image:
+      case spv::StorageClass::Workgroup:
+      case spv::StorageClass::Private:
+      case spv::StorageClass::Function:
+      case spv::StorageClass::PushConstant:
+      case spv::StorageClass::PhysicalStorageBuffer:
+      case spv::StorageClass::RayPayloadKHR:
+      case spv::StorageClass::IncomingRayPayloadKHR:
+      case spv::StorageClass::HitAttributeKHR:
+      case spv::StorageClass::CallableDataKHR:
+      case spv::StorageClass::IncomingCallableDataKHR:
+      case spv::StorageClass::ShaderRecordBufferKHR:
+      case spv::StorageClass::TaskPayloadWorkgroupEXT:
         return true;
       default:
         return false;
diff --git a/source/val/validation_state.h b/source/val/validation_state.h
index 1b599ff..4d5ac00 100644
--- a/source/val/validation_state.h
+++ b/source/val/validation_state.h
@@ -185,10 +185,10 @@
   void ProgressToNextLayoutSectionOrder();
 
   /// Determines if the op instruction is in a previous layout section
-  bool IsOpcodeInPreviousLayoutSection(SpvOp op);
+  bool IsOpcodeInPreviousLayoutSection(spv::Op op);
 
   /// Determines if the op instruction is part of the current section
-  bool IsOpcodeInCurrentLayoutSection(SpvOp op);
+  bool IsOpcodeInCurrentLayoutSection(spv::Op op);
 
   DiagnosticStream diag(spv_result_t error_code, const Instruction* inst);
 
@@ -217,7 +217,8 @@
   };
 
   /// Registers |id| as an entry point with |execution_model| and |interfaces|.
-  void RegisterEntryPoint(const uint32_t id, SpvExecutionModel execution_model,
+  void RegisterEntryPoint(const uint32_t id,
+                          spv::ExecutionModel execution_model,
                           EntryPointDescription&& desc) {
     entry_points_.push_back(id);
     entry_point_to_execution_models_[id].insert(execution_model);
@@ -235,7 +236,7 @@
 
   /// Registers execution mode for the given entry point.
   void RegisterExecutionModeForEntryPoint(uint32_t entry_point,
-                                          SpvExecutionMode execution_mode) {
+                                          spv::ExecutionMode execution_mode) {
     entry_point_to_execution_modes_[entry_point].insert(execution_mode);
   }
 
@@ -247,7 +248,7 @@
 
   /// Returns Execution Models for the given Entry Point.
   /// Returns nullptr if none found (would trigger assertion).
-  const std::set<SpvExecutionModel>* GetExecutionModels(
+  const std::set<spv::ExecutionModel>* GetExecutionModels(
       uint32_t entry_point) const {
     const auto it = entry_point_to_execution_models_.find(entry_point);
     if (it == entry_point_to_execution_models_.end()) {
@@ -259,7 +260,7 @@
 
   /// Returns Execution Modes for the given Entry Point.
   /// Returns nullptr if none found.
-  const std::set<SpvExecutionMode>* GetExecutionModes(
+  const std::set<spv::ExecutionMode>* GetExecutionModes(
       uint32_t entry_point) const {
     const auto it = entry_point_to_execution_modes_.find(entry_point);
     if (it == entry_point_to_execution_modes_.end()) {
@@ -300,7 +301,7 @@
     return (id_to_function_.find(id) != id_to_function_.end());
   }
   /// Registers the capability and its dependent capabilities
-  void RegisterCapability(SpvCapability cap);
+  void RegisterCapability(spv::Capability cap);
 
   /// Registers the extension.
   void RegisterExtension(Extension ext);
@@ -308,14 +309,14 @@
   /// Registers the function in the module. Subsequent instructions will be
   /// called against this function
   spv_result_t RegisterFunction(uint32_t id, uint32_t ret_type_id,
-                                SpvFunctionControlMask function_control,
+                                spv::FunctionControlMask function_control,
                                 uint32_t function_type_id);
 
   /// Register a function end instruction
   spv_result_t RegisterFunctionEnd();
 
   /// Returns true if the capability is enabled in the module.
-  bool HasCapability(SpvCapability cap) const {
+  bool HasCapability(spv::Capability cap) const {
     return module_capabilities_.Contains(cap);
   }
 
@@ -339,16 +340,16 @@
   bool HasAnyOfExtensions(const ExtensionSet& extensions) const;
 
   /// Sets the addressing model of this module (logical/physical).
-  void set_addressing_model(SpvAddressingModel am);
+  void set_addressing_model(spv::AddressingModel am);
 
   /// Returns true if the OpMemoryModel was found.
   bool has_memory_model_specified() const {
-    return addressing_model_ != SpvAddressingModelMax &&
-           memory_model_ != SpvMemoryModelMax;
+    return addressing_model_ != spv::AddressingModel::Max &&
+           memory_model_ != spv::MemoryModel::Max;
   }
 
   /// Returns the addressing model of this module, or Logical if uninitialized.
-  SpvAddressingModel addressing_model() const;
+  spv::AddressingModel addressing_model() const;
 
   /// Returns the addressing model of this module, or Logical if uninitialized.
   uint32_t pointer_size_and_alignment() const {
@@ -356,10 +357,10 @@
   }
 
   /// Sets the memory model of this module.
-  void set_memory_model(SpvMemoryModel mm);
+  void set_memory_model(spv::MemoryModel mm);
 
   /// Returns the memory model of this module, or Simple if uninitialized.
-  SpvMemoryModel memory_model() const;
+  spv::MemoryModel memory_model() const;
 
   /// Sets the bit width for sampler/image type variables. If not set, they are
   /// considered opaque
@@ -432,8 +433,8 @@
 
     // The decorations are sorted by member_index, so this look up will give the
     // exact range of decorations for this member index.
-    Decoration min_decoration((SpvDecoration)0, {}, member_index);
-    Decoration max_decoration(SpvDecorationMax, {}, member_index);
+    Decoration min_decoration((spv::Decoration)0, {}, member_index);
+    Decoration max_decoration(spv::Decoration::Max, {}, member_index);
 
     FieldDecorationsIter result;
     result.begin = decorations.lower_bound(min_decoration);
@@ -449,7 +450,7 @@
 
   /// Returns true if the given id <id> has the given decoration <dec>,
   /// otherwise returns false.
-  bool HasDecoration(uint32_t id, SpvDecoration dec) {
+  bool HasDecoration(uint32_t id, spv::Decoration dec) {
     const auto& decorations = id_decorations_.find(id);
     if (decorations == id_decorations_.end()) return false;
 
@@ -485,7 +486,7 @@
                                     Instruction* consumer);
 
   // Record a function's storage class consumer instruction
-  void RegisterStorageClassConsumer(SpvStorageClass storage_class,
+  void RegisterStorageClassConsumer(spv::StorageClass storage_class,
                                     Instruction* consumer);
 
   /// Returns the set of Global Variables.
@@ -616,7 +617,7 @@
 
   // Returns true if |id| is a type id that contains |type| (or integer or
   // floating point type) of |width| bits.
-  bool ContainsSizedIntOrFloatType(uint32_t id, SpvOp type,
+  bool ContainsSizedIntOrFloatType(uint32_t id, spv::Op type,
                                    uint32_t width) const;
   // Returns true if |id| is a type id that contains a 8- or 16-bit int or
   // 16-bit float that is not generally enabled for use.
@@ -642,7 +643,7 @@
 
   // Returns opcode of the instruction which issued the id or OpNop if the
   // instruction is not registered.
-  SpvOp GetIdOpcode(uint32_t id) const;
+  spv::Op GetIdOpcode(uint32_t id) const;
 
   // Returns type_id for given id operand if it has a type or zero otherwise.
   // |operand_index| is expected to be pointing towards an operand which is an
@@ -652,7 +653,7 @@
 
   // Provides information on pointer type. Returns false iff not pointer type.
   bool GetPointerTypeInfo(uint32_t id, uint32_t* data_type,
-                          uint32_t* storage_class) const;
+                          spv::StorageClass* storage_class) const;
 
   // Is the ID the type of a pointer to a uniform block: Block-decorated struct
   // in uniform storage class? The result is only valid after internal method
@@ -732,6 +733,9 @@
     }
     return std::string(desc->name);
   }
+  std::string SpvDecorationString(spv::Decoration decoration) {
+    return SpvDecorationString(uint32_t(decoration));
+  }
 
   // Returns whether type m1 and type m2 are cooperative matrices with
   // the same "shape" (matching scope, rows, cols). If any are specialization
@@ -764,7 +768,7 @@
   const Instruction* TracePointer(const Instruction* inst) const;
 
   // Validates the storage class for the target environment.
-  bool IsValidStorageClass(SpvStorageClass storage_class) const;
+  bool IsValidStorageClass(spv::StorageClass storage_class) const;
 
   // Takes a Vulkan Valid Usage ID (VUID) as |id| and optional |reference| and
   // will return a non-empty string only if ID is known and targeting Vulkan.
@@ -883,8 +887,8 @@
 
   AssemblyGrammar grammar_;
 
-  SpvAddressingModel addressing_model_;
-  SpvMemoryModel memory_model_;
+  spv::AddressingModel addressing_model_;
+  spv::MemoryModel memory_model_;
   // pointer size derived from addressing model. Assumes all storage classes
   // have the same pointer size (for physical pointer types).
   uint32_t pointer_size_and_alignment_;
@@ -905,11 +909,11 @@
   /// Mapping entry point -> execution models. It is presumed that the same
   /// function could theoretically be used as 'main' by multiple OpEntryPoint
   /// instructions.
-  std::unordered_map<uint32_t, std::set<SpvExecutionModel>>
+  std::unordered_map<uint32_t, std::set<spv::ExecutionModel>>
       entry_point_to_execution_models_;
 
   /// Mapping entry point -> execution modes.
-  std::unordered_map<uint32_t, std::set<SpvExecutionMode>>
+  std::unordered_map<uint32_t, std::set<spv::ExecutionMode>>
       entry_point_to_execution_modes_;
 
   /// Mapping function -> array of entry points inside this
diff --git a/test/binary_header_get_test.cpp b/test/binary_header_get_test.cpp
index f94f0c1..aca09b0 100644
--- a/test/binary_header_get_test.cpp
+++ b/test/binary_header_get_test.cpp
@@ -23,8 +23,8 @@
   BinaryHeaderGet() { memset(code, 0, sizeof(code)); }
 
   virtual void SetUp() {
-    code[0] = SpvMagicNumber;
-    code[1] = SpvVersion;
+    code[0] = static_cast<uint32_t>(spv::MagicNumber);
+    code[1] = static_cast<uint32_t>(spv::Version);
     code[2] = SPV_GENERATOR_CODEPLAY;
     code[3] = 1;  // NOTE: Bound
     code[4] = 0;  // NOTE: Schema; reserved
@@ -50,7 +50,7 @@
   spv_header_t header;
   ASSERT_EQ(SPV_SUCCESS, spvBinaryHeaderGet(&const_bin, endian, &header));
 
-  ASSERT_EQ(static_cast<uint32_t>(SpvMagicNumber), header.magic);
+  ASSERT_EQ(static_cast<uint32_t>(spv::MagicNumber), header.magic);
   // Expect SPIRV-Headers updated to SPIR-V 1.6.
   ASSERT_EQ(0x00010600u, header.version);
   ASSERT_EQ(static_cast<uint32_t>(SPV_GENERATOR_CODEPLAY), header.generator);
diff --git a/test/binary_parse_test.cpp b/test/binary_parse_test.cpp
index f0810a3..4c699c1 100644
--- a/test/binary_parse_test.cpp
+++ b/test/binary_parse_test.cpp
@@ -54,14 +54,14 @@
 struct ParsedInstruction {
   explicit ParsedInstruction(const spv_parsed_instruction_t& inst)
       : words(inst.words, inst.words + inst.num_words),
-        opcode(static_cast<SpvOp>(inst.opcode)),
+        opcode(static_cast<spv::Op>(inst.opcode)),
         ext_inst_type(inst.ext_inst_type),
         type_id(inst.type_id),
         result_id(inst.result_id),
         operands(inst.operands, inst.operands + inst.num_operands) {}
 
   std::vector<uint32_t> words;
-  SpvOp opcode;
+  spv::Op opcode;
   spv_ext_inst_type_t ext_inst_type;
   uint32_t type_id;
   uint32_t result_id;
@@ -127,14 +127,14 @@
 // The SPIR-V module header words for the Khronos Assembler generator,
 // for a module with an ID bound of 1.
 const uint32_t kHeaderForBound1[] = {
-    SpvMagicNumber, SpvVersion,
+    spv::MagicNumber, spv::Version,
     SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS_ASSEMBLER, 0), 1 /*bound*/,
     0 /*schema*/};
 
 // Returns the expected SPIR-V module header words for the Khronos
 // Assembler generator, and with a given Id bound.
 std::vector<uint32_t> ExpectedHeaderForBound(uint32_t bound) {
-  return {SpvMagicNumber, 0x10000,
+  return {spv::MagicNumber, 0x10000,
           SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS_ASSEMBLER, 0), bound, 0};
 }
 
@@ -162,13 +162,13 @@
 // Returns a ParsedInstruction for an OpTypeVoid instruction that would
 // generate the given result Id.
 ParsedInstruction MakeParsedVoidTypeInstruction(uint32_t result_id) {
-  const auto void_inst = MakeInstruction(SpvOpTypeVoid, {result_id});
+  const auto void_inst = MakeInstruction(spv::Op::OpTypeVoid, {result_id});
   const auto void_operands = std::vector<spv_parsed_operand_t>{
       MakeSimpleOperand(1, SPV_OPERAND_TYPE_RESULT_ID)};
   const spv_parsed_instruction_t parsed_void_inst = {
       void_inst.data(),
       static_cast<uint16_t>(void_inst.size()),
-      SpvOpTypeVoid,
+      uint16_t(spv::Op::OpTypeVoid),
       SPV_EXT_INST_TYPE_NONE,
       0,  // type id
       result_id,
@@ -180,14 +180,14 @@
 // Returns a ParsedInstruction for an OpTypeInt instruction that generates
 // the given result Id for a 32-bit signed integer scalar type.
 ParsedInstruction MakeParsedInt32TypeInstruction(uint32_t result_id) {
-  const auto i32_inst = MakeInstruction(SpvOpTypeInt, {result_id, 32, 1});
+  const auto i32_inst = MakeInstruction(spv::Op::OpTypeInt, {result_id, 32, 1});
   const auto i32_operands = std::vector<spv_parsed_operand_t>{
       MakeSimpleOperand(1, SPV_OPERAND_TYPE_RESULT_ID),
       MakeLiteralNumberOperand(2), MakeLiteralNumberOperand(3)};
   spv_parsed_instruction_t parsed_i32_inst = {
       i32_inst.data(),
       static_cast<uint16_t>(i32_inst.size()),
-      SpvOpTypeInt,
+      uint16_t(spv::Op::OpTypeInt),
       SPV_EXT_INST_TYPE_NONE,
       0,  // type id
       result_id,
@@ -216,12 +216,12 @@
 
 // Adds an EXPECT_CALL to client_->Header() with appropriate parameters,
 // including bound.  Returns the EXPECT_CALL result.
-#define EXPECT_HEADER(bound)                                                   \
-  EXPECT_CALL(                                                                 \
-      client_,                                                                 \
-      Header(AnyOf(SPV_ENDIANNESS_LITTLE, SPV_ENDIANNESS_BIG), SpvMagicNumber, \
-             0x10000, SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS_ASSEMBLER, 0),  \
-             bound, 0 /*reserved*/))
+#define EXPECT_HEADER(bound)                                                 \
+  EXPECT_CALL(client_,                                                       \
+              Header(AnyOf(SPV_ENDIANNESS_LITTLE, SPV_ENDIANNESS_BIG),       \
+                     spv::MagicNumber, 0x10000,                              \
+                     SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS_ASSEMBLER, 0), \
+                     bound, 0 /*reserved*/))
 
 static const bool kSwapEndians[] = {false, true};
 
@@ -481,19 +481,20 @@
     const std::string str =
         "the future is already here, it's just not evenly distributed";
     const auto str_words = MakeVector(str);
-    const auto instruction = MakeInstruction(SpvOpName, {99}, str_words);
+    const auto instruction = MakeInstruction(spv::Op::OpName, {99}, str_words);
     const auto words = Concatenate({ExpectedHeaderForBound(100), instruction});
     InSequence calls_expected_in_specific_order;
     EXPECT_HEADER(100).WillOnce(Return(SPV_SUCCESS));
     const auto operands = std::vector<spv_parsed_operand_t>{
         MakeSimpleOperand(1, SPV_OPERAND_TYPE_ID),
         MakeLiteralStringOperand(2, static_cast<uint16_t>(str_words.size()))};
-    EXPECT_CALL(client_, Instruction(ParsedInstruction(spv_parsed_instruction_t{
-                             instruction.data(),
-                             static_cast<uint16_t>(instruction.size()),
-                             SpvOpName, SPV_EXT_INST_TYPE_NONE, 0 /*type id*/,
-                             0 /* No result id for OpName*/, operands.data(),
-                             static_cast<uint16_t>(operands.size())})))
+    EXPECT_CALL(
+        client_,
+        Instruction(ParsedInstruction(spv_parsed_instruction_t{
+            instruction.data(), static_cast<uint16_t>(instruction.size()),
+            uint16_t(spv::Op::OpName), SPV_EXT_INST_TYPE_NONE, 0 /*type id*/,
+            0 /* No result id for OpName*/, operands.data(),
+            static_cast<uint16_t>(operands.size())})))
         .WillOnce(Return(SPV_SUCCESS));
     Parse(words, SPV_SUCCESS, endian_swap);
     EXPECT_EQ(nullptr, diagnostic_);
@@ -518,13 +519,13 @@
       MakeSimpleOperand(5, SPV_OPERAND_TYPE_ID),  // Id of the argument
   };
   const auto instruction = MakeInstruction(
-      SpvOpExtInst,
+      spv::Op::OpExtInst,
       {2, 3, 1, static_cast<uint32_t>(OpenCLLIB::Entrypoints::Sqrt), 4});
   EXPECT_CALL(client_,
               Instruction(ParsedInstruction(spv_parsed_instruction_t{
                   instruction.data(), static_cast<uint16_t>(instruction.size()),
-                  SpvOpExtInst, SPV_EXT_INST_TYPE_OPENCL_STD, 2 /*type id*/,
-                  3 /*result id*/, operands.data(),
+                  uint16_t(spv::Op::OpExtInst), SPV_EXT_INST_TYPE_OPENCL_STD,
+                  2 /*type id*/, 3 /*result id*/, operands.data(),
                   static_cast<uint16_t>(operands.size())})))
       .WillOnce(Return(SPV_SUCCESS));
   // Since we are actually checking the output, don't test the
@@ -593,36 +594,38 @@
 INSTANTIATE_TEST_SUITE_P(
     BinaryParseDiagnostic, BinaryParseWordVectorDiagnosticTest,
     ::testing::ValuesIn(std::vector<WordVectorDiagnosticCase>{
-        {Concatenate({ExpectedHeaderForBound(1), {spvOpcodeMake(0, SpvOpNop)}}),
+        {Concatenate({ExpectedHeaderForBound(1),
+                      {spvOpcodeMake(0, spv::Op::OpNop)}}),
          "Invalid instruction word count: 0"},
         {Concatenate(
              {ExpectedHeaderForBound(1),
-              {spvOpcodeMake(1, static_cast<SpvOp>(
+              {spvOpcodeMake(1, static_cast<spv::Op>(
                                     std::numeric_limits<uint16_t>::max()))}}),
          "Invalid opcode: 65535"},
         {Concatenate({ExpectedHeaderForBound(1),
-                      MakeInstruction(SpvOpNop, {42})}),
+                      MakeInstruction(spv::Op::OpNop, {42})}),
          "Invalid instruction OpNop starting at word 5: expected "
          "no more operands after 1 words, but stated word count is 2."},
         // Supply several more unexpected words.
         {Concatenate({ExpectedHeaderForBound(1),
-                      MakeInstruction(SpvOpNop, {42, 43, 44, 45, 46, 47})}),
+                      MakeInstruction(spv::Op::OpNop,
+                                      {42, 43, 44, 45, 46, 47})}),
          "Invalid instruction OpNop starting at word 5: expected "
          "no more operands after 1 words, but stated word count is 7."},
         {Concatenate({ExpectedHeaderForBound(1),
-                      MakeInstruction(SpvOpTypeVoid, {1, 2})}),
+                      MakeInstruction(spv::Op::OpTypeVoid, {1, 2})}),
          "Invalid instruction OpTypeVoid starting at word 5: expected "
          "no more operands after 2 words, but stated word count is 3."},
         {Concatenate({ExpectedHeaderForBound(1),
-                      MakeInstruction(SpvOpTypeVoid, {1, 2, 5, 9, 10})}),
+                      MakeInstruction(spv::Op::OpTypeVoid, {1, 2, 5, 9, 10})}),
          "Invalid instruction OpTypeVoid starting at word 5: expected "
          "no more operands after 2 words, but stated word count is 6."},
         {Concatenate({ExpectedHeaderForBound(1),
-                      MakeInstruction(SpvOpTypeInt, {1, 32, 1, 9})}),
+                      MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1, 9})}),
          "Invalid instruction OpTypeInt starting at word 5: expected "
          "no more operands after 4 words, but stated word count is 5."},
         {Concatenate({ExpectedHeaderForBound(1),
-                      MakeInstruction(SpvOpTypeInt, {1})}),
+                      MakeInstruction(spv::Op::OpTypeInt, {1})}),
          "End of input reached while decoding OpTypeInt starting at word 5:"
          " expected more operands after 2 words."},
 
@@ -630,7 +633,7 @@
 
         // Detect a missing single word operand.
         {Concatenate({ExpectedHeaderForBound(1),
-                      {spvOpcodeMake(2, SpvOpTypeStruct)}}),
+                      {spvOpcodeMake(2, spv::Op::OpTypeStruct)}}),
          "End of input reached while decoding OpTypeStruct starting at word"
          " 5: missing result ID operand at word offset 1."},
         // Detect this a missing a multi-word operand to OpConstant.
@@ -639,29 +642,29 @@
         //    %1 = OpTypeInt 64 0
         //    %2 = OpConstant %1 <missing>
         {Concatenate({ExpectedHeaderForBound(3),
-                      {MakeInstruction(SpvOpTypeInt, {1, 64, 0})},
-                      {spvOpcodeMake(5, SpvOpConstant), 1, 2}}),
+                      {MakeInstruction(spv::Op::OpTypeInt, {1, 64, 0})},
+                      {spvOpcodeMake(5, spv::Op::OpConstant), 1, 2}}),
          "End of input reached while decoding OpConstant starting at word"
          " 9: missing possibly multi-word literal number operand at word "
          "offset 3."},
         // Detect when we provide only one word from the 64-bit literal,
         // and again lie about the number of words in the instruction.
         {Concatenate({ExpectedHeaderForBound(3),
-                      {MakeInstruction(SpvOpTypeInt, {1, 64, 0})},
-                      {spvOpcodeMake(5, SpvOpConstant), 1, 2, 42}}),
+                      {MakeInstruction(spv::Op::OpTypeInt, {1, 64, 0})},
+                      {spvOpcodeMake(5, spv::Op::OpConstant), 1, 2, 42}}),
          "End of input reached while decoding OpConstant starting at word"
          " 9: truncated possibly multi-word literal number operand at word "
          "offset 3."},
         // Detect when a required string operand is missing.
         // Also, lie about the length of the instruction.
         {Concatenate({ExpectedHeaderForBound(3),
-                      {spvOpcodeMake(3, SpvOpString), 1}}),
+                      {spvOpcodeMake(3, spv::Op::OpString), 1}}),
          "End of input reached while decoding OpString starting at word"
          " 5: missing literal string operand at word offset 2."},
         // Detect when a required string operand is truncated: it's missing
         // a null terminator.  Catching the error avoids a buffer overrun.
         {Concatenate({ExpectedHeaderForBound(3),
-                      {spvOpcodeMake(4, SpvOpString), 1, 0x41414141,
+                      {spvOpcodeMake(4, spv::Op::OpString), 1, 0x41414141,
                        0x41414141}}),
          "End of input reached while decoding OpString starting at word"
          " 5: truncated literal string operand at word offset 2."},
@@ -669,9 +672,9 @@
         // a null terminator.  Catching the error avoids a buffer overrun.
         // (It is valid for an optional string operand to be absent.)
         {Concatenate({ExpectedHeaderForBound(3),
-                      {spvOpcodeMake(6, SpvOpSource),
-                       static_cast<uint32_t>(SpvSourceLanguageOpenCL_C), 210,
-                       1 /* file id */,
+                      {spvOpcodeMake(6, spv::Op::OpSource),
+                       static_cast<uint32_t>(spv::SourceLanguage::OpenCL_C),
+                       210, 1 /* file id */,
                        /*start of string*/ 0x41414141, 0x41414141}}),
          "End of input reached while decoding OpSource starting at word"
          " 5: truncated literal string operand at word offset 4."},
@@ -681,19 +684,19 @@
         // In this case the instruction word count is too small, where
         // it would truncate a multi-word operand to OpConstant.
         {Concatenate({ExpectedHeaderForBound(3),
-                      {MakeInstruction(SpvOpTypeInt, {1, 64, 0})},
-                      {spvOpcodeMake(4, SpvOpConstant), 1, 2, 44, 44}}),
+                      {MakeInstruction(spv::Op::OpTypeInt, {1, 64, 0})},
+                      {spvOpcodeMake(4, spv::Op::OpConstant), 1, 2, 44, 44}}),
          "Invalid word count: OpConstant starting at word 9 says it has 4"
          " words, but found 5 words instead."},
         // Word count is to small, where it would truncate a literal string.
         {Concatenate({ExpectedHeaderForBound(2),
-                      {spvOpcodeMake(3, SpvOpString), 1, 0x41414141, 0}}),
+                      {spvOpcodeMake(3, spv::Op::OpString), 1, 0x41414141, 0}}),
          "Invalid word count: OpString starting at word 5 says it has 3"
          " words, but found 4 words instead."},
         // Word count is too large.  The string terminates before the last
         // word.
         {Concatenate({ExpectedHeaderForBound(2),
-                      {spvOpcodeMake(4, SpvOpString), 1 /* result id */},
+                      {spvOpcodeMake(4, spv::Op::OpString), 1 /* result id */},
                       MakeVector("abc"),
                       {0 /* this word does not belong*/}}),
          "Invalid instruction OpString starting at word 5: expected no more"
@@ -701,111 +704,116 @@
         // Word count is too large.  There are too many words after the string
         // literal.  A linkage attribute decoration is the only case in SPIR-V
         // where a string operand is followed by another operand.
-        {Concatenate({ExpectedHeaderForBound(2),
-                      {spvOpcodeMake(6, SpvOpDecorate), 1 /* target id */,
-                       static_cast<uint32_t>(SpvDecorationLinkageAttributes)},
-                      MakeVector("abc"),
-                      {static_cast<uint32_t>(SpvLinkageTypeImport),
-                       0 /* does not belong */}}),
+        {Concatenate(
+             {ExpectedHeaderForBound(2),
+              {spvOpcodeMake(6, spv::Op::OpDecorate), 1 /* target id */,
+               static_cast<uint32_t>(spv::Decoration::LinkageAttributes)},
+              MakeVector("abc"),
+              {static_cast<uint32_t>(spv::LinkageType::Import),
+               0 /* does not belong */}}),
          "Invalid instruction OpDecorate starting at word 5: expected no more"
          " operands after 5 words, but stated word count is 6."},
         // Like the previous case, but with 5 extra words.
-        {Concatenate({ExpectedHeaderForBound(2),
-                      {spvOpcodeMake(10, SpvOpDecorate), 1 /* target id */,
-                       static_cast<uint32_t>(SpvDecorationLinkageAttributes)},
-                      MakeVector("abc"),
-                      {static_cast<uint32_t>(SpvLinkageTypeImport),
-                       /* don't belong */ 0, 1, 2, 3, 4}}),
+        {Concatenate(
+             {ExpectedHeaderForBound(2),
+              {spvOpcodeMake(10, spv::Op::OpDecorate), 1 /* target id */,
+               static_cast<uint32_t>(spv::Decoration::LinkageAttributes)},
+              MakeVector("abc"),
+              {static_cast<uint32_t>(spv::LinkageType::Import),
+               /* don't belong */ 0, 1, 2, 3, 4}}),
          "Invalid instruction OpDecorate starting at word 5: expected no more"
          " operands after 5 words, but stated word count is 10."},
         // Like the previous two cases, but with OpMemberDecorate.
-        {Concatenate({ExpectedHeaderForBound(2),
-                      {spvOpcodeMake(7, SpvOpMemberDecorate), 1 /* target id */,
-                       42 /* member index */,
-                       static_cast<uint32_t>(SpvDecorationLinkageAttributes)},
-                      MakeVector("abc"),
-                      {static_cast<uint32_t>(SpvLinkageTypeImport),
-                       0 /* does not belong */}}),
+        {Concatenate(
+             {ExpectedHeaderForBound(2),
+              {spvOpcodeMake(7, spv::Op::OpMemberDecorate), 1 /* target id */,
+               42 /* member index */,
+               static_cast<uint32_t>(spv::Decoration::LinkageAttributes)},
+              MakeVector("abc"),
+              {static_cast<uint32_t>(spv::LinkageType::Import),
+               0 /* does not belong */}}),
          "Invalid instruction OpMemberDecorate starting at word 5: expected no"
          " more operands after 6 words, but stated word count is 7."},
-        {Concatenate({ExpectedHeaderForBound(2),
-                      {spvOpcodeMake(11, SpvOpMemberDecorate),
-                       1 /* target id */, 42 /* member index */,
-                       static_cast<uint32_t>(SpvDecorationLinkageAttributes)},
-                      MakeVector("abc"),
-                      {static_cast<uint32_t>(SpvLinkageTypeImport),
-                       /* don't belong */ 0, 1, 2, 3, 4}}),
+        {Concatenate(
+             {ExpectedHeaderForBound(2),
+              {spvOpcodeMake(11, spv::Op::OpMemberDecorate), 1 /* target id */,
+               42 /* member index */,
+               static_cast<uint32_t>(spv::Decoration::LinkageAttributes)},
+              MakeVector("abc"),
+              {static_cast<uint32_t>(spv::LinkageType::Import),
+               /* don't belong */ 0, 1, 2, 3, 4}}),
          "Invalid instruction OpMemberDecorate starting at word 5: expected no"
          " more operands after 6 words, but stated word count is 11."},
         // Word count is too large.  There should be no more words
         // after the RelaxedPrecision decoration.
         {Concatenate({ExpectedHeaderForBound(2),
-                      {spvOpcodeMake(4, SpvOpDecorate), 1 /* target id */,
-                       static_cast<uint32_t>(SpvDecorationRelaxedPrecision),
+                      {spvOpcodeMake(4, spv::Op::OpDecorate), 1 /* target id */,
+                       static_cast<uint32_t>(spv::Decoration::RelaxedPrecision),
                        0 /* does not belong */}}),
          "Invalid instruction OpDecorate starting at word 5: expected no"
          " more operands after 3 words, but stated word count is 4."},
         // Word count is too large.  There should be only one word after
         // the SpecId decoration enum word.
         {Concatenate({ExpectedHeaderForBound(2),
-                      {spvOpcodeMake(5, SpvOpDecorate), 1 /* target id */,
-                       static_cast<uint32_t>(SpvDecorationSpecId),
+                      {spvOpcodeMake(5, spv::Op::OpDecorate), 1 /* target id */,
+                       static_cast<uint32_t>(spv::Decoration::SpecId),
                        42 /* the spec id */, 0 /* does not belong */}}),
          "Invalid instruction OpDecorate starting at word 5: expected no"
          " more operands after 4 words, but stated word count is 5."},
         {Concatenate({ExpectedHeaderForBound(2),
-                      {spvOpcodeMake(2, SpvOpTypeVoid), 0}}),
+                      {spvOpcodeMake(2, spv::Op::OpTypeVoid), 0}}),
          "Error: Result Id is 0"},
         {Concatenate({
              ExpectedHeaderForBound(2),
-             {spvOpcodeMake(2, SpvOpTypeVoid), 1},
-             {spvOpcodeMake(2, SpvOpTypeBool), 1},
+             {spvOpcodeMake(2, spv::Op::OpTypeVoid), 1},
+             {spvOpcodeMake(2, spv::Op::OpTypeBool), 1},
          }),
          "Id 1 is defined more than once"},
         {Concatenate({ExpectedHeaderForBound(3),
-                      MakeInstruction(SpvOpExtInst, {2, 3, 100, 4, 5})}),
+                      MakeInstruction(spv::Op::OpExtInst, {2, 3, 100, 4, 5})}),
          "OpExtInst set Id 100 does not reference an OpExtInstImport result "
          "Id"},
         {Concatenate({ExpectedHeaderForBound(101),
-                      MakeInstruction(SpvOpExtInstImport, {100},
+                      MakeInstruction(spv::Op::OpExtInstImport, {100},
                                       MakeVector("OpenCL.std")),
                       // OpenCL cos is #14
-                      MakeInstruction(SpvOpExtInst, {2, 3, 100, 14, 5, 999})}),
+                      MakeInstruction(spv::Op::OpExtInst,
+                                      {2, 3, 100, 14, 5, 999})}),
          "Invalid instruction OpExtInst starting at word 10: expected no "
          "more operands after 6 words, but stated word count is 7."},
         // In this case, the OpSwitch selector refers to an invalid ID.
         {Concatenate({ExpectedHeaderForBound(3),
-                      MakeInstruction(SpvOpSwitch, {1, 2, 42, 3})}),
+                      MakeInstruction(spv::Op::OpSwitch, {1, 2, 42, 3})}),
          "Invalid OpSwitch: selector id 1 has no type"},
         // In this case, the OpSwitch selector refers to an ID that has
         // no type.
         {Concatenate({ExpectedHeaderForBound(3),
-                      MakeInstruction(SpvOpLabel, {1}),
-                      MakeInstruction(SpvOpSwitch, {1, 2, 42, 3})}),
+                      MakeInstruction(spv::Op::OpLabel, {1}),
+                      MakeInstruction(spv::Op::OpSwitch, {1, 2, 42, 3})}),
          "Invalid OpSwitch: selector id 1 has no type"},
         {Concatenate({ExpectedHeaderForBound(3),
-                      MakeInstruction(SpvOpTypeInt, {1, 32, 0}),
-                      MakeInstruction(SpvOpSwitch, {1, 3, 42, 3})}),
+                      MakeInstruction(spv::Op::OpTypeInt, {1, 32, 0}),
+                      MakeInstruction(spv::Op::OpSwitch, {1, 3, 42, 3})}),
          "Invalid OpSwitch: selector id 1 is a type, not a value"},
         {Concatenate({ExpectedHeaderForBound(3),
-                      MakeInstruction(SpvOpTypeFloat, {1, 32}),
-                      MakeInstruction(SpvOpConstant, {1, 2, 0x78f00000}),
-                      MakeInstruction(SpvOpSwitch, {2, 3, 42, 3})}),
+                      MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
+                      MakeInstruction(spv::Op::OpConstant, {1, 2, 0x78f00000}),
+                      MakeInstruction(spv::Op::OpSwitch, {2, 3, 42, 3})}),
          "Invalid OpSwitch: selector id 2 is not a scalar integer"},
         {Concatenate({ExpectedHeaderForBound(3),
-                      MakeInstruction(SpvOpExtInstImport, {1},
+                      MakeInstruction(spv::Op::OpExtInstImport, {1},
                                       MakeVector("invalid-import"))}),
          "Invalid extended instruction import 'invalid-import'"},
         {Concatenate({
              ExpectedHeaderForBound(3),
-             MakeInstruction(SpvOpTypeInt, {1, 32, 0}),
-             MakeInstruction(SpvOpConstant, {2, 2, 42}),
+             MakeInstruction(spv::Op::OpTypeInt, {1, 32, 0}),
+             MakeInstruction(spv::Op::OpConstant, {2, 2, 42}),
          }),
          "Type Id 2 is not a type"},
         {Concatenate({
              ExpectedHeaderForBound(3),
-             MakeInstruction(SpvOpTypeBool, {1}),
-             MakeInstruction(SpvOpConstant, {1, 2, 42}),
+             MakeInstruction(spv::Op::OpTypeBool, {1}),
+             MakeInstruction(spv::Op::OpConstant, {1, 2, 42}),
          }),
          "Type Id 1 is not a scalar numeric type"},
     }));
diff --git a/test/binary_to_text_test.cpp b/test/binary_to_text_test.cpp
index 44705f2..85d5bd1 100644
--- a/test/binary_to_text_test.cpp
+++ b/test/binary_to_text_test.cpp
@@ -185,43 +185,43 @@
 INSTANTIATE_TEST_SUITE_P(
     InvalidIds, BinaryToTextFail,
     ::testing::ValuesIn(std::vector<FailedDecodeCase>{
-        {"", spvtest::MakeInstruction(SpvOpTypeVoid, {0}),
+        {"", spvtest::MakeInstruction(spv::Op::OpTypeVoid, {0}),
          "Error: Result Id is 0"},
-        {"", spvtest::MakeInstruction(SpvOpConstant, {0, 1, 42}),
+        {"", spvtest::MakeInstruction(spv::Op::OpConstant, {0, 1, 42}),
          "Error: Type Id is 0"},
-        {"%1 = OpTypeVoid", spvtest::MakeInstruction(SpvOpTypeVoid, {1}),
+        {"%1 = OpTypeVoid", spvtest::MakeInstruction(spv::Op::OpTypeVoid, {1}),
          "Id 1 is defined more than once"},
         {"%1 = OpTypeVoid\n"
          "%2 = OpNot %1 %foo",
-         spvtest::MakeInstruction(SpvOpNot, {1, 2, 3}),
+         spvtest::MakeInstruction(spv::Op::OpNot, {1, 2, 3}),
          "Id 2 is defined more than once"},
         {"%1 = OpTypeVoid\n"
          "%2 = OpNot %1 %foo",
-         spvtest::MakeInstruction(SpvOpNot, {1, 1, 3}),
+         spvtest::MakeInstruction(spv::Op::OpNot, {1, 1, 3}),
          "Id 1 is defined more than once"},
         // The following are the two failure cases for
         // Parser::setNumericTypeInfoForType.
-        {"", spvtest::MakeInstruction(SpvOpConstant, {500, 1, 42}),
+        {"", spvtest::MakeInstruction(spv::Op::OpConstant, {500, 1, 42}),
          "Type Id 500 is not a type"},
         {"%1 = OpTypeInt 32 0\n"
          "%2 = OpTypeVector %1 4",
-         spvtest::MakeInstruction(SpvOpConstant, {2, 3, 999}),
+         spvtest::MakeInstruction(spv::Op::OpConstant, {2, 3, 999}),
          "Type Id 2 is not a scalar numeric type"},
     }));
 
 INSTANTIATE_TEST_SUITE_P(
     InvalidIdsCheckedDuringLiteralCaseParsing, BinaryToTextFail,
     ::testing::ValuesIn(std::vector<FailedDecodeCase>{
-        {"", spvtest::MakeInstruction(SpvOpSwitch, {1, 2, 3, 4}),
+        {"", spvtest::MakeInstruction(spv::Op::OpSwitch, {1, 2, 3, 4}),
          "Invalid OpSwitch: selector id 1 has no type"},
         {"%1 = OpTypeVoid\n",
-         spvtest::MakeInstruction(SpvOpSwitch, {1, 2, 3, 4}),
+         spvtest::MakeInstruction(spv::Op::OpSwitch, {1, 2, 3, 4}),
          "Invalid OpSwitch: selector id 1 is a type, not a value"},
         {"%1 = OpConstantTrue !500",
-         spvtest::MakeInstruction(SpvOpSwitch, {1, 2, 3, 4}),
+         spvtest::MakeInstruction(spv::Op::OpSwitch, {1, 2, 3, 4}),
          "Type Id 500 is not a type"},
         {"%1 = OpTypeFloat 32\n%2 = OpConstant %1 1.5",
-         spvtest::MakeInstruction(SpvOpSwitch, {2, 3, 4, 5}),
+         spvtest::MakeInstruction(spv::Op::OpSwitch, {2, 3, 4, 5}),
          "Invalid OpSwitch: selector id 2 is not a scalar integer"},
     }));
 
diff --git a/test/comment_test.cpp b/test/comment_test.cpp
index 49f8df6..5cc9b1d 100644
--- a/test/comment_test.cpp
+++ b/test/comment_test.cpp
@@ -40,10 +40,10 @@
 
   EXPECT_THAT(
       CompiledInstructions(input),
-      Eq(Concatenate({MakeInstruction(SpvOpMemoryModel,
-                                      {uint32_t(SpvAddressingModelLogical),
-                                       uint32_t(SpvMemoryModelSimple)}),
-                      MakeInstruction(SpvOpExtInstImport, {1},
+      Eq(Concatenate({MakeInstruction(spv::Op::OpMemoryModel,
+                                      {uint32_t(spv::AddressingModel::Logical),
+                                       uint32_t(spv::MemoryModel::Simple)}),
+                      MakeInstruction(spv::Op::OpExtInstImport, {1},
                                       MakeVector("GLSL.std.450"))})));
 }
 
diff --git a/test/cpp_interface_test.cpp b/test/cpp_interface_test.cpp
index 4cab4df..5d11698 100644
--- a/test/cpp_interface_test.cpp
+++ b/test/cpp_interface_test.cpp
@@ -19,7 +19,7 @@
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include "spirv-tools/optimizer.hpp"
-#include "spirv/1.1/spirv.h"
+#include "spirv/unified1/spirv.hpp11"
 
 namespace spvtools {
 namespace {
@@ -47,7 +47,7 @@
   std::vector<uint32_t> binary;
   EXPECT_TRUE(t.Assemble(input_text, &binary));
   EXPECT_TRUE(binary.size() > 5u);
-  EXPECT_EQ(SpvMagicNumber, binary[0]);
+  EXPECT_EQ(spv::MagicNumber, binary[0]);
   EXPECT_EQ(kExpectedSpvVersion, binary[1]);
 
   // This cannot pass validation since %1 is not defined.
@@ -74,7 +74,7 @@
   EXPECT_TRUE(t.Assemble("", &binary));
   // We only have the header.
   EXPECT_EQ(5u, binary.size());
-  EXPECT_EQ(SpvMagicNumber, binary[0]);
+  EXPECT_EQ(spv::MagicNumber, binary[0]);
   EXPECT_EQ(kExpectedSpvVersion, binary[1]);
 }
 
@@ -85,21 +85,21 @@
     std::vector<uint32_t> binary;
     EXPECT_TRUE(t.Assemble(input_text, &binary));
     EXPECT_TRUE(binary.size() > 5u);
-    EXPECT_EQ(SpvMagicNumber, binary[0]);
+    EXPECT_EQ(spv::MagicNumber, binary[0]);
     EXPECT_EQ(kExpectedSpvVersion, binary[1]);
   }
   {
     std::vector<uint32_t> binary;
     EXPECT_TRUE(t.Assemble(input_text.data(), input_text.size(), &binary));
     EXPECT_TRUE(binary.size() > 5u);
-    EXPECT_EQ(SpvMagicNumber, binary[0]);
+    EXPECT_EQ(spv::MagicNumber, binary[0]);
     EXPECT_EQ(kExpectedSpvVersion, binary[1]);
   }
   {  // Ignore the last newline.
     std::vector<uint32_t> binary;
     EXPECT_TRUE(t.Assemble(input_text.data(), input_text.size() - 1, &binary));
     EXPECT_TRUE(binary.size() > 5u);
-    EXPECT_EQ(SpvMagicNumber, binary[0]);
+    EXPECT_EQ(spv::MagicNumber, binary[0]);
     EXPECT_EQ(kExpectedSpvVersion, binary[1]);
   }
 }
diff --git a/test/diff/diff_test.cpp b/test/diff/diff_test.cpp
index 5b11d0e..3b63c69 100644
--- a/test/diff/diff_test.cpp
+++ b/test/diff/diff_test.cpp
@@ -195,14 +195,14 @@
 
   // Differentiate them in the header.
   const spvtools::opt::ModuleHeader src_header = {
-      SpvMagicNumber,
+      spv::MagicNumber,
       SPV_SPIRV_VERSION_WORD(1, 3),
       SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS_ASSEMBLER, 3),
       src->module()->IdBound(),
       src->module()->schema(),
   };
   const spvtools::opt::ModuleHeader dst_header = {
-      SpvMagicNumber,
+      spv::MagicNumber,
       SPV_SPIRV_VERSION_WORD(1, 2),
       SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS_GLSLANG, 10),
       dst->module()->IdBound(),
diff --git a/test/enum_set_test.cpp b/test/enum_set_test.cpp
index 047d642..1f72715 100644
--- a/test/enum_set_test.cpp
+++ b/test/enum_set_test.cpp
@@ -179,60 +179,60 @@
 }
 
 TEST(CapabilitySet, ConstructSingleMemberMatrix) {
-  CapabilitySet s(SpvCapabilityMatrix);
-  EXPECT_TRUE(s.Contains(SpvCapabilityMatrix));
-  EXPECT_FALSE(s.Contains(SpvCapabilityShader));
-  EXPECT_FALSE(s.Contains(static_cast<SpvCapability>(1000)));
+  CapabilitySet s(spv::Capability::Matrix);
+  EXPECT_TRUE(s.Contains(spv::Capability::Matrix));
+  EXPECT_FALSE(s.Contains(spv::Capability::Shader));
+  EXPECT_FALSE(s.Contains(static_cast<spv::Capability>(1000)));
 }
 
 TEST(CapabilitySet, ConstructSingleMemberMaxInMask) {
-  CapabilitySet s(static_cast<SpvCapability>(63));
-  EXPECT_FALSE(s.Contains(SpvCapabilityMatrix));
-  EXPECT_FALSE(s.Contains(SpvCapabilityShader));
-  EXPECT_TRUE(s.Contains(static_cast<SpvCapability>(63)));
-  EXPECT_FALSE(s.Contains(static_cast<SpvCapability>(64)));
-  EXPECT_FALSE(s.Contains(static_cast<SpvCapability>(1000)));
+  CapabilitySet s(static_cast<spv::Capability>(63));
+  EXPECT_FALSE(s.Contains(spv::Capability::Matrix));
+  EXPECT_FALSE(s.Contains(spv::Capability::Shader));
+  EXPECT_TRUE(s.Contains(static_cast<spv::Capability>(63)));
+  EXPECT_FALSE(s.Contains(static_cast<spv::Capability>(64)));
+  EXPECT_FALSE(s.Contains(static_cast<spv::Capability>(1000)));
 }
 
 TEST(CapabilitySet, ConstructSingleMemberMinOverflow) {
   // Check the first one that forces overflow beyond the mask.
-  CapabilitySet s(static_cast<SpvCapability>(64));
-  EXPECT_FALSE(s.Contains(SpvCapabilityMatrix));
-  EXPECT_FALSE(s.Contains(SpvCapabilityShader));
-  EXPECT_FALSE(s.Contains(static_cast<SpvCapability>(63)));
-  EXPECT_TRUE(s.Contains(static_cast<SpvCapability>(64)));
-  EXPECT_FALSE(s.Contains(static_cast<SpvCapability>(1000)));
+  CapabilitySet s(static_cast<spv::Capability>(64));
+  EXPECT_FALSE(s.Contains(spv::Capability::Matrix));
+  EXPECT_FALSE(s.Contains(spv::Capability::Shader));
+  EXPECT_FALSE(s.Contains(static_cast<spv::Capability>(63)));
+  EXPECT_TRUE(s.Contains(static_cast<spv::Capability>(64)));
+  EXPECT_FALSE(s.Contains(static_cast<spv::Capability>(1000)));
 }
 
 TEST(CapabilitySet, ConstructSingleMemberMaxOverflow) {
   // Check the max 32-bit signed int.
-  CapabilitySet s(static_cast<SpvCapability>(0x7fffffffu));
-  EXPECT_FALSE(s.Contains(SpvCapabilityMatrix));
-  EXPECT_FALSE(s.Contains(SpvCapabilityShader));
-  EXPECT_FALSE(s.Contains(static_cast<SpvCapability>(1000)));
-  EXPECT_TRUE(s.Contains(static_cast<SpvCapability>(0x7fffffffu)));
+  CapabilitySet s(static_cast<spv::Capability>(0x7fffffffu));
+  EXPECT_FALSE(s.Contains(spv::Capability::Matrix));
+  EXPECT_FALSE(s.Contains(spv::Capability::Shader));
+  EXPECT_FALSE(s.Contains(static_cast<spv::Capability>(1000)));
+  EXPECT_TRUE(s.Contains(static_cast<spv::Capability>(0x7fffffffu)));
 }
 
 TEST(CapabilitySet, AddEnum) {
-  CapabilitySet s(SpvCapabilityShader);
-  s.Add(SpvCapabilityKernel);
-  s.Add(static_cast<SpvCapability>(42));
-  EXPECT_FALSE(s.Contains(SpvCapabilityMatrix));
-  EXPECT_TRUE(s.Contains(SpvCapabilityShader));
-  EXPECT_TRUE(s.Contains(SpvCapabilityKernel));
-  EXPECT_TRUE(s.Contains(static_cast<SpvCapability>(42)));
+  CapabilitySet s(spv::Capability::Shader);
+  s.Add(spv::Capability::Kernel);
+  s.Add(static_cast<spv::Capability>(42));
+  EXPECT_FALSE(s.Contains(spv::Capability::Matrix));
+  EXPECT_TRUE(s.Contains(spv::Capability::Shader));
+  EXPECT_TRUE(s.Contains(spv::Capability::Kernel));
+  EXPECT_TRUE(s.Contains(static_cast<spv::Capability>(42)));
 }
 
 TEST(CapabilitySet, InitializerListEmpty) {
   CapabilitySet s{};
   for (uint32_t i = 0; i < 1000; i++) {
-    EXPECT_FALSE(s.Contains(static_cast<SpvCapability>(i)));
+    EXPECT_FALSE(s.Contains(static_cast<spv::Capability>(i)));
   }
 }
 
 struct ForEachCase {
   CapabilitySet capabilities;
-  std::vector<SpvCapability> expected;
+  std::vector<spv::Capability> expected;
 };
 
 using CapabilitySetForEachTest = ::testing::TestWithParam<ForEachCase>;
@@ -253,7 +253,7 @@
   EXPECT_THAT(ElementsIn(moved), Eq(GetParam().expected));
 
   // The moved-from set is empty.
-  EXPECT_THAT(ElementsIn(copy), Eq(std::vector<SpvCapability>{}));
+  EXPECT_THAT(ElementsIn(copy), Eq(std::vector<spv::Capability>{}));
 }
 
 TEST_P(CapabilitySetForEachTest, OperatorEquals) {
@@ -267,24 +267,25 @@
   EXPECT_THAT(ElementsIn(assigned), Eq(GetParam().expected));
 }
 
-INSTANTIATE_TEST_SUITE_P(Samples, CapabilitySetForEachTest,
-                         ValuesIn(std::vector<ForEachCase>{
-                             {{}, {}},
-                             {{SpvCapabilityMatrix}, {SpvCapabilityMatrix}},
-                             {{SpvCapabilityKernel, SpvCapabilityShader},
-                              {SpvCapabilityShader, SpvCapabilityKernel}},
-                             {{static_cast<SpvCapability>(999)},
-                              {static_cast<SpvCapability>(999)}},
-                             {{static_cast<SpvCapability>(0x7fffffff)},
-                              {static_cast<SpvCapability>(0x7fffffff)}},
-                             // Mixture and out of order
-                             {{static_cast<SpvCapability>(0x7fffffff),
-                               static_cast<SpvCapability>(100),
-                               SpvCapabilityShader, SpvCapabilityMatrix},
-                              {SpvCapabilityMatrix, SpvCapabilityShader,
-                               static_cast<SpvCapability>(100),
-                               static_cast<SpvCapability>(0x7fffffff)}},
-                         }));
+INSTANTIATE_TEST_SUITE_P(
+    Samples, CapabilitySetForEachTest,
+    ValuesIn(std::vector<ForEachCase>{
+        {{}, {}},
+        {{spv::Capability::Matrix}, {spv::Capability::Matrix}},
+        {{spv::Capability::Kernel, spv::Capability::Shader},
+         {spv::Capability::Shader, spv::Capability::Kernel}},
+        {{static_cast<spv::Capability>(999)},
+         {static_cast<spv::Capability>(999)}},
+        {{static_cast<spv::Capability>(0x7fffffff)},
+         {static_cast<spv::Capability>(0x7fffffff)}},
+        // Mixture and out of order
+        {{static_cast<spv::Capability>(0x7fffffff),
+          static_cast<spv::Capability>(100), spv::Capability::Shader,
+          spv::Capability::Matrix},
+         {spv::Capability::Matrix, spv::Capability::Shader,
+          static_cast<spv::Capability>(100),
+          static_cast<spv::Capability>(0x7fffffff)}},
+    }));
 
 }  // namespace
 }  // namespace spvtools
diff --git a/test/enum_string_mapping_test.cpp b/test/enum_string_mapping_test.cpp
index 52aa653..01dede7 100644
--- a/test/enum_string_mapping_test.cpp
+++ b/test/enum_string_mapping_test.cpp
@@ -34,7 +34,7 @@
     ::testing::TestWithParam<std::pair<Extension, std::string>>;
 using UnknownExtensionTest = ::testing::TestWithParam<std::string>;
 using CapabilityTest =
-    ::testing::TestWithParam<std::pair<SpvCapability, std::string>>;
+    ::testing::TestWithParam<std::pair<spv::Capability, std::string>>;
 
 TEST_P(ExtensionTest, TestExtensionFromString) {
   const std::pair<Extension, std::string>& param = GetParam();
@@ -59,8 +59,8 @@
 }
 
 TEST_P(CapabilityTest, TestCapabilityToString) {
-  const std::pair<SpvCapability, std::string>& param = GetParam();
-  const SpvCapability capability = param.first;
+  const std::pair<spv::Capability, std::string>& param = GetParam();
+  const spv::Capability capability = param.first;
   const std::string capability_str = param.second;
   const std::string result_str = CapabilityToString(capability);
   EXPECT_EQ(capability_str, result_str);
@@ -99,104 +99,105 @@
 
 INSTANTIATE_TEST_SUITE_P(
     AllCapabilities, CapabilityTest,
-    ValuesIn(std::vector<std::pair<SpvCapability, std::string>>(
-        {{SpvCapabilityMatrix, "Matrix"},
-         {SpvCapabilityShader, "Shader"},
-         {SpvCapabilityGeometry, "Geometry"},
-         {SpvCapabilityTessellation, "Tessellation"},
-         {SpvCapabilityAddresses, "Addresses"},
-         {SpvCapabilityLinkage, "Linkage"},
-         {SpvCapabilityKernel, "Kernel"},
-         {SpvCapabilityVector16, "Vector16"},
-         {SpvCapabilityFloat16Buffer, "Float16Buffer"},
-         {SpvCapabilityFloat16, "Float16"},
-         {SpvCapabilityFloat64, "Float64"},
-         {SpvCapabilityInt64, "Int64"},
-         {SpvCapabilityInt64Atomics, "Int64Atomics"},
-         {SpvCapabilityImageBasic, "ImageBasic"},
-         {SpvCapabilityImageReadWrite, "ImageReadWrite"},
-         {SpvCapabilityImageMipmap, "ImageMipmap"},
-         {SpvCapabilityPipes, "Pipes"},
-         {SpvCapabilityGroups, "Groups"},
-         {SpvCapabilityDeviceEnqueue, "DeviceEnqueue"},
-         {SpvCapabilityLiteralSampler, "LiteralSampler"},
-         {SpvCapabilityAtomicStorage, "AtomicStorage"},
-         {SpvCapabilityInt16, "Int16"},
-         {SpvCapabilityTessellationPointSize, "TessellationPointSize"},
-         {SpvCapabilityGeometryPointSize, "GeometryPointSize"},
-         {SpvCapabilityImageGatherExtended, "ImageGatherExtended"},
-         {SpvCapabilityStorageImageMultisample, "StorageImageMultisample"},
-         {SpvCapabilityUniformBufferArrayDynamicIndexing,
+    ValuesIn(std::vector<std::pair<spv::Capability, std::string>>(
+        {{spv::Capability::Matrix, "Matrix"},
+         {spv::Capability::Shader, "Shader"},
+         {spv::Capability::Geometry, "Geometry"},
+         {spv::Capability::Tessellation, "Tessellation"},
+         {spv::Capability::Addresses, "Addresses"},
+         {spv::Capability::Linkage, "Linkage"},
+         {spv::Capability::Kernel, "Kernel"},
+         {spv::Capability::Vector16, "Vector16"},
+         {spv::Capability::Float16Buffer, "Float16Buffer"},
+         {spv::Capability::Float16, "Float16"},
+         {spv::Capability::Float64, "Float64"},
+         {spv::Capability::Int64, "Int64"},
+         {spv::Capability::Int64Atomics, "Int64Atomics"},
+         {spv::Capability::ImageBasic, "ImageBasic"},
+         {spv::Capability::ImageReadWrite, "ImageReadWrite"},
+         {spv::Capability::ImageMipmap, "ImageMipmap"},
+         {spv::Capability::Pipes, "Pipes"},
+         {spv::Capability::Groups, "Groups"},
+         {spv::Capability::DeviceEnqueue, "DeviceEnqueue"},
+         {spv::Capability::LiteralSampler, "LiteralSampler"},
+         {spv::Capability::AtomicStorage, "AtomicStorage"},
+         {spv::Capability::Int16, "Int16"},
+         {spv::Capability::TessellationPointSize, "TessellationPointSize"},
+         {spv::Capability::GeometryPointSize, "GeometryPointSize"},
+         {spv::Capability::ImageGatherExtended, "ImageGatherExtended"},
+         {spv::Capability::StorageImageMultisample, "StorageImageMultisample"},
+         {spv::Capability::UniformBufferArrayDynamicIndexing,
           "UniformBufferArrayDynamicIndexing"},
-         {SpvCapabilitySampledImageArrayDynamicIndexing,
+         {spv::Capability::SampledImageArrayDynamicIndexing,
           "SampledImageArrayDynamicIndexing"},
-         {SpvCapabilityStorageBufferArrayDynamicIndexing,
+         {spv::Capability::StorageBufferArrayDynamicIndexing,
           "StorageBufferArrayDynamicIndexing"},
-         {SpvCapabilityStorageImageArrayDynamicIndexing,
+         {spv::Capability::StorageImageArrayDynamicIndexing,
           "StorageImageArrayDynamicIndexing"},
-         {SpvCapabilityClipDistance, "ClipDistance"},
-         {SpvCapabilityCullDistance, "CullDistance"},
-         {SpvCapabilityImageCubeArray, "ImageCubeArray"},
-         {SpvCapabilitySampleRateShading, "SampleRateShading"},
-         {SpvCapabilityImageRect, "ImageRect"},
-         {SpvCapabilitySampledRect, "SampledRect"},
-         {SpvCapabilityGenericPointer, "GenericPointer"},
-         {SpvCapabilityInt8, "Int8"},
-         {SpvCapabilityInputAttachment, "InputAttachment"},
-         {SpvCapabilitySparseResidency, "SparseResidency"},
-         {SpvCapabilityMinLod, "MinLod"},
-         {SpvCapabilitySampled1D, "Sampled1D"},
-         {SpvCapabilityImage1D, "Image1D"},
-         {SpvCapabilitySampledCubeArray, "SampledCubeArray"},
-         {SpvCapabilitySampledBuffer, "SampledBuffer"},
-         {SpvCapabilityImageBuffer, "ImageBuffer"},
-         {SpvCapabilityImageMSArray, "ImageMSArray"},
-         {SpvCapabilityStorageImageExtendedFormats,
+         {spv::Capability::ClipDistance, "ClipDistance"},
+         {spv::Capability::CullDistance, "CullDistance"},
+         {spv::Capability::ImageCubeArray, "ImageCubeArray"},
+         {spv::Capability::SampleRateShading, "SampleRateShading"},
+         {spv::Capability::ImageRect, "ImageRect"},
+         {spv::Capability::SampledRect, "SampledRect"},
+         {spv::Capability::GenericPointer, "GenericPointer"},
+         {spv::Capability::Int8, "Int8"},
+         {spv::Capability::InputAttachment, "InputAttachment"},
+         {spv::Capability::SparseResidency, "SparseResidency"},
+         {spv::Capability::MinLod, "MinLod"},
+         {spv::Capability::Sampled1D, "Sampled1D"},
+         {spv::Capability::Image1D, "Image1D"},
+         {spv::Capability::SampledCubeArray, "SampledCubeArray"},
+         {spv::Capability::SampledBuffer, "SampledBuffer"},
+         {spv::Capability::ImageBuffer, "ImageBuffer"},
+         {spv::Capability::ImageMSArray, "ImageMSArray"},
+         {spv::Capability::StorageImageExtendedFormats,
           "StorageImageExtendedFormats"},
-         {SpvCapabilityImageQuery, "ImageQuery"},
-         {SpvCapabilityDerivativeControl, "DerivativeControl"},
-         {SpvCapabilityInterpolationFunction, "InterpolationFunction"},
-         {SpvCapabilityTransformFeedback, "TransformFeedback"},
-         {SpvCapabilityGeometryStreams, "GeometryStreams"},
-         {SpvCapabilityStorageImageReadWithoutFormat,
+         {spv::Capability::ImageQuery, "ImageQuery"},
+         {spv::Capability::DerivativeControl, "DerivativeControl"},
+         {spv::Capability::InterpolationFunction, "InterpolationFunction"},
+         {spv::Capability::TransformFeedback, "TransformFeedback"},
+         {spv::Capability::GeometryStreams, "GeometryStreams"},
+         {spv::Capability::StorageImageReadWithoutFormat,
           "StorageImageReadWithoutFormat"},
-         {SpvCapabilityStorageImageWriteWithoutFormat,
+         {spv::Capability::StorageImageWriteWithoutFormat,
           "StorageImageWriteWithoutFormat"},
-         {SpvCapabilityMultiViewport, "MultiViewport"},
-         {SpvCapabilitySubgroupDispatch, "SubgroupDispatch"},
-         {SpvCapabilityNamedBarrier, "NamedBarrier"},
-         {SpvCapabilityPipeStorage, "PipeStorage"},
-         {SpvCapabilitySubgroupBallotKHR, "SubgroupBallotKHR"},
-         {SpvCapabilityDrawParameters, "DrawParameters"},
-         {SpvCapabilitySubgroupVoteKHR, "SubgroupVoteKHR"},
-         {SpvCapabilityStorageBuffer16BitAccess, "StorageBuffer16BitAccess"},
-         {SpvCapabilityStorageUniformBufferBlock16,
+         {spv::Capability::MultiViewport, "MultiViewport"},
+         {spv::Capability::SubgroupDispatch, "SubgroupDispatch"},
+         {spv::Capability::NamedBarrier, "NamedBarrier"},
+         {spv::Capability::PipeStorage, "PipeStorage"},
+         {spv::Capability::SubgroupBallotKHR, "SubgroupBallotKHR"},
+         {spv::Capability::DrawParameters, "DrawParameters"},
+         {spv::Capability::SubgroupVoteKHR, "SubgroupVoteKHR"},
+         {spv::Capability::StorageBuffer16BitAccess,
+          "StorageBuffer16BitAccess"},
+         {spv::Capability::StorageUniformBufferBlock16,
           "StorageBuffer16BitAccess"},  // Preferred name
-         {SpvCapabilityUniformAndStorageBuffer16BitAccess,
+         {spv::Capability::UniformAndStorageBuffer16BitAccess,
           "UniformAndStorageBuffer16BitAccess"},
-         {SpvCapabilityStorageUniform16,
+         {spv::Capability::StorageUniform16,
           "UniformAndStorageBuffer16BitAccess"},  // Preferred name
-         {SpvCapabilityStoragePushConstant16, "StoragePushConstant16"},
-         {SpvCapabilityStorageInputOutput16, "StorageInputOutput16"},
-         {SpvCapabilityDeviceGroup, "DeviceGroup"},
-         {SpvCapabilityAtomicFloat32AddEXT, "AtomicFloat32AddEXT"},
-         {SpvCapabilityAtomicFloat64AddEXT, "AtomicFloat64AddEXT"},
-         {SpvCapabilityAtomicFloat32MinMaxEXT, "AtomicFloat32MinMaxEXT"},
-         {SpvCapabilityAtomicFloat64MinMaxEXT, "AtomicFloat64MinMaxEXT"},
-         {SpvCapabilityMultiView, "MultiView"},
-         {SpvCapabilityInt64ImageEXT, "Int64ImageEXT"},
-         {SpvCapabilitySampleMaskOverrideCoverageNV,
+         {spv::Capability::StoragePushConstant16, "StoragePushConstant16"},
+         {spv::Capability::StorageInputOutput16, "StorageInputOutput16"},
+         {spv::Capability::DeviceGroup, "DeviceGroup"},
+         {spv::Capability::AtomicFloat32AddEXT, "AtomicFloat32AddEXT"},
+         {spv::Capability::AtomicFloat64AddEXT, "AtomicFloat64AddEXT"},
+         {spv::Capability::AtomicFloat32MinMaxEXT, "AtomicFloat32MinMaxEXT"},
+         {spv::Capability::AtomicFloat64MinMaxEXT, "AtomicFloat64MinMaxEXT"},
+         {spv::Capability::MultiView, "MultiView"},
+         {spv::Capability::Int64ImageEXT, "Int64ImageEXT"},
+         {spv::Capability::SampleMaskOverrideCoverageNV,
           "SampleMaskOverrideCoverageNV"},
-         {SpvCapabilityGeometryShaderPassthroughNV,
+         {spv::Capability::GeometryShaderPassthroughNV,
           "GeometryShaderPassthroughNV"},
          // The next two are different names for the same token.
-         {SpvCapabilityShaderViewportIndexLayerNV,
+         {spv::Capability::ShaderViewportIndexLayerNV,
           "ShaderViewportIndexLayerEXT"},
-         {SpvCapabilityShaderViewportIndexLayerEXT,
+         {spv::Capability::ShaderViewportIndexLayerEXT,
           "ShaderViewportIndexLayerEXT"},
-         {SpvCapabilityShaderViewportMaskNV, "ShaderViewportMaskNV"},
-         {SpvCapabilityShaderStereoViewNV, "ShaderStereoViewNV"},
-         {SpvCapabilityPerViewAttributesNV, "PerViewAttributesNV"}})));
+         {spv::Capability::ShaderViewportMaskNV, "ShaderViewportMaskNV"},
+         {spv::Capability::ShaderStereoViewNV, "ShaderStereoViewNV"},
+         {spv::Capability::PerViewAttributesNV, "PerViewAttributesNV"}})));
 
 }  // namespace
 }  // namespace spvtools
diff --git a/test/ext_inst.cldebug100_test.cpp b/test/ext_inst.cldebug100_test.cpp
index 0bbdd3a..cfc68e8 100644
--- a/test/ext_inst.cldebug100_test.cpp
+++ b/test/ext_inst.cldebug100_test.cpp
@@ -18,7 +18,6 @@
 #include "OpenCLDebugInfo100.h"
 #include "gmock/gmock.h"
 #include "source/util/string_utils.h"
-#include "spirv/unified1/spirv.h"
 #include "test/test_fixture.h"
 #include "test/unit_spirv.h"
 
@@ -158,12 +157,13 @@
       GetParam().name + GetParam().operands + "\n";
   // First make sure it assembles correctly.
   std::cout << input << std::endl;
-  EXPECT_THAT(CompiledInstructions(input),
-              Eq(Concatenate(
-                  {MakeInstruction(SpvOpExtInstImport, {1},
-                                   MakeVector("OpenCL.DebugInfo.100")),
-                   MakeInstruction(SpvOpExtInst, {2, 3, 1, GetParam().opcode},
-                                   GetParam().expected_operands)})))
+  EXPECT_THAT(
+      CompiledInstructions(input),
+      Eq(Concatenate(
+          {MakeInstruction(spv::Op::OpExtInstImport, {1},
+                           MakeVector("OpenCL.DebugInfo.100")),
+           MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, GetParam().opcode},
+                           GetParam().expected_operands)})))
       << input;
   // Now check the round trip through the disassembler.
   EXPECT_THAT(EncodeAndDecodeSuccessfully(input), input) << input;
@@ -297,7 +297,7 @@
   {                                                         \
     uint32_t(OpenCLDebugInfo100Debug##Enum), EPREFIX #Enum, \
         " %4 " #S0 " " Fstr, {                              \
-      4, uint32_t(SpvStorageClass##S0), Fnum                \
+      4, uint32_t(spv::StorageClass::S0), Fnum              \
     }                                                       \
   }
 
@@ -313,7 +313,7 @@
   {                                                         \
     uint32_t(OpenCLDebugInfo100Debug##Enum), EPREFIX #Enum, \
         " " #L0 " " #L1 " %4 " RawEnumName, {               \
-      L0, L1, 4, RawEnumValue                               \
+      L0, L1, 4, (uint32_t)RawEnumValue                     \
     }                                                       \
   }
 
@@ -574,7 +574,7 @@
 INSTANTIATE_TEST_SUITE_P(
     OpenCLDebugInfo100DebugCompilationUnit, ExtInstCLDebugInfo100RoundTripTest,
     ::testing::ValuesIn(std::vector<InstructionCase>({
-        CASE_LLIe(CompilationUnit, 100, 42, "HLSL", SpvSourceLanguageHLSL),
+        CASE_LLIe(CompilationUnit, 100, 42, "HLSL", spv::SourceLanguage::HLSL),
     })));
 
 INSTANTIATE_TEST_SUITE_P(
@@ -612,14 +612,14 @@
   const std::string input = prefix + "FlagIsPublic\n";
   const std::string expected = prefix + "FlagIsProtected|FlagIsPrivate\n";
   // First make sure it assembles correctly.
-  EXPECT_THAT(
-      CompiledInstructions(input),
-      Eq(Concatenate(
-          {MakeInstruction(SpvOpExtInstImport, {1}, MakeVector("DebugInfo")),
-           MakeInstruction(SpvOpExtInst,
-                           {2, 3, 1, OpenCLDebugInfo100DebugTypePointer, 4,
-                            uint32_t(SpvStorageClassPrivate),
-                            OpenCLDebugInfo100FlagIsPublic})})))
+  EXPECT_THAT(CompiledInstructions(input),
+              Eq(Concatenate(
+                  {MakeInstruction(spv::Op::OpExtInstImport, {1},
+                                   MakeVector("DebugInfo")),
+                   MakeInstruction(spv::Op::OpExtInst,
+                                   {2, 3, 1, OpenCLDebugInfo100DebugTypePointer,
+                                    4, uint32_t(spv::StorageClass::Private),
+                                    OpenCLDebugInfo100FlagIsPublic})})))
       << input;
   // Now check the round trip through the disassembler.
   EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(expected)) << input;
diff --git a/test/ext_inst.debuginfo_test.cpp b/test/ext_inst.debuginfo_test.cpp
index 9090c24..5ccbde6 100644
--- a/test/ext_inst.debuginfo_test.cpp
+++ b/test/ext_inst.debuginfo_test.cpp
@@ -52,12 +52,12 @@
       "%3 = OpExtInst %2 %1 " +
       GetParam().name + GetParam().operands + "\n";
   // First make sure it assembles correctly.
-  EXPECT_THAT(
-      CompiledInstructions(input),
-      Eq(Concatenate(
-          {MakeInstruction(SpvOpExtInstImport, {1}, MakeVector("DebugInfo")),
-           MakeInstruction(SpvOpExtInst, {2, 3, 1, GetParam().opcode},
-                           GetParam().expected_operands)})))
+  EXPECT_THAT(CompiledInstructions(input),
+              Eq(Concatenate({MakeInstruction(spv::Op::OpExtInstImport, {1},
+                                              MakeVector("DebugInfo")),
+                              MakeInstruction(spv::Op::OpExtInst,
+                                              {2, 3, 1, GetParam().opcode},
+                                              GetParam().expected_operands)})))
       << input;
   // Now check the round trip through the disassembler.
   EXPECT_THAT(EncodeAndDecodeSuccessfully(input), input) << input;
@@ -156,7 +156,7 @@
 #define CASE_ISF(Enum, S0, Fstr, Fnum)                                    \
   {                                                                       \
     uint32_t(DebugInfoDebug##Enum), "Debug" #Enum, " %4 " #S0 " " Fstr, { \
-      4, uint32_t(SpvStorageClass##S0), Fnum                              \
+      4, uint32_t(spv::StorageClass::S0), Fnum                            \
     }                                                                     \
   }
 
@@ -408,11 +408,12 @@
   // First make sure it assembles correctly.
   EXPECT_THAT(
       CompiledInstructions(input),
-      Eq(Concatenate(
-          {MakeInstruction(SpvOpExtInstImport, {1}, MakeVector("DebugInfo")),
-           MakeInstruction(SpvOpExtInst, {2, 3, 1, DebugInfoDebugTypePointer, 4,
-                                          uint32_t(SpvStorageClassPrivate),
-                                          DebugInfoFlagIsPublic})})))
+      Eq(Concatenate({MakeInstruction(spv::Op::OpExtInstImport, {1},
+                                      MakeVector("DebugInfo")),
+                      MakeInstruction(spv::Op::OpExtInst,
+                                      {2, 3, 1, DebugInfoDebugTypePointer, 4,
+                                       uint32_t(spv::StorageClass::Private),
+                                       DebugInfoFlagIsPublic})})))
       << input;
   // Now check the round trip through the disassembler.
   EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(expected)) << input;
diff --git a/test/ext_inst.opencl_test.cpp b/test/ext_inst.opencl_test.cpp
index d80a9bd..51c2b01 100644
--- a/test/ext_inst.opencl_test.cpp
+++ b/test/ext_inst.opencl_test.cpp
@@ -47,12 +47,12 @@
       "%3 = OpExtInst %2 %1 " +
       GetParam().name + " " + GetParam().operands + "\n";
   // First make sure it assembles correctly.
-  EXPECT_THAT(
-      CompiledInstructions(input),
-      Eq(Concatenate(
-          {MakeInstruction(SpvOpExtInstImport, {1}, MakeVector("OpenCL.std")),
-           MakeInstruction(SpvOpExtInst, {2, 3, 1, GetParam().opcode},
-                           GetParam().expected_operands)})))
+  EXPECT_THAT(CompiledInstructions(input),
+              Eq(Concatenate({MakeInstruction(spv::Op::OpExtInstImport, {1},
+                                              MakeVector("OpenCL.std")),
+                              MakeInstruction(spv::Op::OpExtInst,
+                                              {2, 3, 1, GetParam().opcode},
+                                              GetParam().expected_operands)})))
       << input;
   // Now check the round trip through the disassembler.
   EXPECT_THAT(EncodeAndDecodeSuccessfully(input), input) << input;
@@ -85,7 +85,7 @@
 #define CASE3Round(Enum, Name, Mode)                                    \
   {                                                                     \
     uint32_t(OpenCLLIB::Entrypoints::Enum), #Name, "%4 %5 %6 " #Mode, { \
-      4, 5, 6, uint32_t(SpvFPRoundingMode##Mode)                        \
+      4, 5, 6, uint32_t(spv::FPRoundingMode::Mode)                      \
     }                                                                   \
   }
 
diff --git a/test/fuzz/available_instructions_test.cpp b/test/fuzz/available_instructions_test.cpp
index dc8a3b5..bbe524a 100644
--- a/test/fuzz/available_instructions_test.cpp
+++ b/test/fuzz/available_instructions_test.cpp
@@ -176,41 +176,41 @@
       auto available = all_instructions.GetAvailableBeforeInstruction(i1);
       ASSERT_FALSE(available.empty());
       ASSERT_EQ(30, available.size());
-      ASSERT_EQ(SpvOpTypeVoid, available[0]->opcode());
-      ASSERT_EQ(SpvOpVariable, available[15]->opcode());
+      ASSERT_EQ(spv::Op::OpTypeVoid, available[0]->opcode());
+      ASSERT_EQ(spv::Op::OpVariable, available[15]->opcode());
     }
     {
       auto available = all_instructions.GetAvailableBeforeInstruction(i2);
       ASSERT_FALSE(available.empty());
       ASSERT_EQ(46, available.size());
-      ASSERT_EQ(SpvOpTypeVoid, available[0]->opcode());
-      ASSERT_EQ(SpvOpTypePointer, available[3]->opcode());
-      ASSERT_EQ(SpvOpVariable, available[15]->opcode());
-      ASSERT_EQ(SpvOpFunctionCall, available[40]->opcode());
-      ASSERT_EQ(SpvOpStore, available[45]->opcode());
+      ASSERT_EQ(spv::Op::OpTypeVoid, available[0]->opcode());
+      ASSERT_EQ(spv::Op::OpTypePointer, available[3]->opcode());
+      ASSERT_EQ(spv::Op::OpVariable, available[15]->opcode());
+      ASSERT_EQ(spv::Op::OpFunctionCall, available[40]->opcode());
+      ASSERT_EQ(spv::Op::OpStore, available[45]->opcode());
     }
     {
       auto available = all_instructions.GetAvailableBeforeInstruction(i3);
       ASSERT_FALSE(available.empty());
       ASSERT_EQ(45, available.size());
-      ASSERT_EQ(SpvOpTypeVoid, available[0]->opcode());
-      ASSERT_EQ(SpvOpTypePointer, available[3]->opcode());
-      ASSERT_EQ(SpvOpVariable, available[15]->opcode());
-      ASSERT_EQ(SpvOpFunctionCall, available[40]->opcode());
-      ASSERT_EQ(SpvOpBranchConditional, available[44]->opcode());
+      ASSERT_EQ(spv::Op::OpTypeVoid, available[0]->opcode());
+      ASSERT_EQ(spv::Op::OpTypePointer, available[3]->opcode());
+      ASSERT_EQ(spv::Op::OpVariable, available[15]->opcode());
+      ASSERT_EQ(spv::Op::OpFunctionCall, available[40]->opcode());
+      ASSERT_EQ(spv::Op::OpBranchConditional, available[44]->opcode());
     }
     {
       auto available = all_instructions.GetAvailableBeforeInstruction(i6);
       ASSERT_FALSE(available.empty());
       ASSERT_EQ(33, available.size());
-      ASSERT_EQ(SpvOpTypeVoid, available[0]->opcode());
-      ASSERT_EQ(SpvOpTypeFloat, available[4]->opcode());
-      ASSERT_EQ(SpvOpTypePointer, available[8]->opcode());
-      ASSERT_EQ(SpvOpConstantComposite, available[12]->opcode());
-      ASSERT_EQ(SpvOpConstant, available[16]->opcode());
-      ASSERT_EQ(SpvOpFunctionParameter, available[30]->opcode());
-      ASSERT_EQ(SpvOpFunctionParameter, available[31]->opcode());
-      ASSERT_EQ(SpvOpVariable, available[32]->opcode());
+      ASSERT_EQ(spv::Op::OpTypeVoid, available[0]->opcode());
+      ASSERT_EQ(spv::Op::OpTypeFloat, available[4]->opcode());
+      ASSERT_EQ(spv::Op::OpTypePointer, available[8]->opcode());
+      ASSERT_EQ(spv::Op::OpConstantComposite, available[12]->opcode());
+      ASSERT_EQ(spv::Op::OpConstant, available[16]->opcode());
+      ASSERT_EQ(spv::Op::OpFunctionParameter, available[30]->opcode());
+      ASSERT_EQ(spv::Op::OpFunctionParameter, available[31]->opcode());
+      ASSERT_EQ(spv::Op::OpVariable, available[32]->opcode());
     }
   }
   {
@@ -225,51 +225,51 @@
       auto available = vector_instructions.GetAvailableBeforeInstruction(i4);
       ASSERT_FALSE(available.empty());
       ASSERT_EQ(3, available.size());
-      ASSERT_EQ(SpvOpConstantComposite, available[0]->opcode());
-      ASSERT_EQ(SpvOpConstantComposite, available[1]->opcode());
-      ASSERT_EQ(SpvOpCopyObject, available[2]->opcode());
+      ASSERT_EQ(spv::Op::OpConstantComposite, available[0]->opcode());
+      ASSERT_EQ(spv::Op::OpConstantComposite, available[1]->opcode());
+      ASSERT_EQ(spv::Op::OpCopyObject, available[2]->opcode());
     }
     {
       auto available = vector_instructions.GetAvailableBeforeInstruction(i5);
       ASSERT_FALSE(available.empty());
       ASSERT_EQ(3, available.size());
-      ASSERT_EQ(SpvOpConstantComposite, available[0]->opcode());
-      ASSERT_EQ(SpvOpConstantComposite, available[1]->opcode());
-      ASSERT_EQ(SpvOpCopyObject, available[2]->opcode());
+      ASSERT_EQ(spv::Op::OpConstantComposite, available[0]->opcode());
+      ASSERT_EQ(spv::Op::OpConstantComposite, available[1]->opcode());
+      ASSERT_EQ(spv::Op::OpCopyObject, available[2]->opcode());
     }
     {
       auto available = vector_instructions.GetAvailableBeforeInstruction(i6);
       ASSERT_FALSE(available.empty());
       ASSERT_EQ(2, available.size());
-      ASSERT_EQ(SpvOpConstantComposite, available[0]->opcode());
-      ASSERT_EQ(SpvOpConstantComposite, available[1]->opcode());
+      ASSERT_EQ(spv::Op::OpConstantComposite, available[0]->opcode());
+      ASSERT_EQ(spv::Op::OpConstantComposite, available[1]->opcode());
     }
   }
   {
     AvailableInstructions integer_add_instructions(
         context.get(), [](opt::IRContext*, opt::Instruction* inst) -> bool {
-          return inst->opcode() == SpvOpIAdd;
+          return inst->opcode() == spv::Op::OpIAdd;
         });
     {
       auto available =
           integer_add_instructions.GetAvailableBeforeInstruction(i7);
       ASSERT_FALSE(available.empty());
       ASSERT_EQ(1, available.size());
-      ASSERT_EQ(SpvOpIAdd, available[0]->opcode());
+      ASSERT_EQ(spv::Op::OpIAdd, available[0]->opcode());
     }
     {
       auto available =
           integer_add_instructions.GetAvailableBeforeInstruction(i8);
       ASSERT_FALSE(available.empty());
       ASSERT_EQ(1, available.size());
-      ASSERT_EQ(SpvOpIAdd, available[0]->opcode());
+      ASSERT_EQ(spv::Op::OpIAdd, available[0]->opcode());
     }
     {
       auto available =
           integer_add_instructions.GetAvailableBeforeInstruction(i9);
       ASSERT_FALSE(available.empty());
       ASSERT_EQ(1, available.size());
-      ASSERT_EQ(SpvOpIAdd, available[0]->opcode());
+      ASSERT_EQ(spv::Op::OpIAdd, available[0]->opcode());
     }
   }
 }
diff --git a/test/fuzz/data_synonym_transformation_test.cpp b/test/fuzz/data_synonym_transformation_test.cpp
index 7e93f29..3ba8093 100644
--- a/test/fuzz/data_synonym_transformation_test.cpp
+++ b/test/fuzz/data_synonym_transformation_test.cpp
@@ -146,12 +146,12 @@
 
   // Replace %12 with %100[0] in '%25 = OpAccessChain %24 %20 %12'
   auto instruction_descriptor_1 =
-      MakeInstructionDescriptor(25, SpvOpAccessChain, 0);
+      MakeInstructionDescriptor(25, spv::Op::OpAccessChain, 0);
   auto good_extract_1 =
       TransformationCompositeExtract(instruction_descriptor_1, 102, 100, {0});
   // Bad: id already in use
   auto bad_extract_1 = TransformationCompositeExtract(
-      MakeInstructionDescriptor(25, SpvOpAccessChain, 0), 25, 100, {0});
+      MakeInstructionDescriptor(25, spv::Op::OpAccessChain, 0), 25, 100, {0});
   ASSERT_TRUE(
       good_extract_1.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
@@ -166,7 +166,8 @@
                                                kConsoleMessageConsumer));
 
   // Replace %13 with %100[1] in 'OpStore %15 %13'
-  auto instruction_descriptor_2 = MakeInstructionDescriptor(100, SpvOpStore, 0);
+  auto instruction_descriptor_2 =
+      MakeInstructionDescriptor(100, spv::Op::OpStore, 0);
   auto good_extract_2 =
       TransformationCompositeExtract(instruction_descriptor_2, 103, 100, {1});
   // No bad example provided here.
@@ -183,7 +184,7 @@
 
   // Replace %22 with %100[2] in '%23 = OpConvertSToF %16 %22'
   auto instruction_descriptor_3 =
-      MakeInstructionDescriptor(23, SpvOpConvertSToF, 0);
+      MakeInstructionDescriptor(23, spv::Op::OpConvertSToF, 0);
   auto good_extract_3 =
       TransformationCompositeExtract(instruction_descriptor_3, 104, 100, {2});
   ASSERT_TRUE(
@@ -203,12 +204,13 @@
                                                kConsoleMessageConsumer));
 
   // Replace %28 with %101[0] in 'OpStore %33 %28'
-  auto instruction_descriptor_4 = MakeInstructionDescriptor(33, SpvOpStore, 0);
+  auto instruction_descriptor_4 =
+      MakeInstructionDescriptor(33, spv::Op::OpStore, 0);
   auto good_extract_4 =
       TransformationCompositeExtract(instruction_descriptor_4, 105, 101, {0});
   // Bad: instruction descriptor does not identify an appropriate instruction
   auto bad_extract_4 = TransformationCompositeExtract(
-      MakeInstructionDescriptor(33, SpvOpCopyObject, 0), 105, 101, {0});
+      MakeInstructionDescriptor(33, spv::Op::OpCopyObject, 0), 105, 101, {0});
   ASSERT_TRUE(
       good_extract_4.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
@@ -224,7 +226,7 @@
 
   // Replace %23 with %101[1] in '%50 = OpCopyObject %16 %23'
   auto instruction_descriptor_5 =
-      MakeInstructionDescriptor(50, SpvOpCopyObject, 0);
+      MakeInstructionDescriptor(50, spv::Op::OpCopyObject, 0);
   auto good_extract_5 =
       TransformationCompositeExtract(instruction_descriptor_5, 106, 101, {1});
   ASSERT_TRUE(
@@ -244,7 +246,8 @@
                                                kConsoleMessageConsumer));
 
   // Replace %32 with %101[2] in 'OpStore %33 %32'
-  auto instruction_descriptor_6 = MakeInstructionDescriptor(33, SpvOpStore, 1);
+  auto instruction_descriptor_6 =
+      MakeInstructionDescriptor(33, spv::Op::OpStore, 1);
   auto good_extract_6 =
       TransformationCompositeExtract(instruction_descriptor_6, 107, 101, {2});
   // Bad: id 1001 does not exist
@@ -265,7 +268,7 @@
 
   // Replace %23 with %101[3] in '%51 = OpCopyObject %16 %23'
   auto instruction_descriptor_7 =
-      MakeInstructionDescriptor(51, SpvOpCopyObject, 0);
+      MakeInstructionDescriptor(51, spv::Op::OpCopyObject, 0);
   auto good_extract_7 =
       TransformationCompositeExtract(instruction_descriptor_7, 108, 101, {3});
   ASSERT_TRUE(
@@ -431,7 +434,8 @@
       MakeSynonymFact(50, {}, 100, {2}));
 
   // Replace %23 with %100[0] in '%26 = OpFAdd %7 %23 %25'
-  auto instruction_descriptor_1 = MakeInstructionDescriptor(26, SpvOpFAdd, 0);
+  auto instruction_descriptor_1 =
+      MakeInstructionDescriptor(26, spv::Op::OpFAdd, 0);
   auto extract_1 =
       TransformationCompositeExtract(instruction_descriptor_1, 101, 100, {0});
   ASSERT_TRUE(extract_1.IsApplicable(context.get(), transformation_context));
@@ -445,7 +449,8 @@
                                                kConsoleMessageConsumer));
 
   // Replace %25 with %100[1] in '%26 = OpFAdd %7 %23 %25'
-  auto instruction_descriptor_2 = MakeInstructionDescriptor(26, SpvOpFAdd, 0);
+  auto instruction_descriptor_2 =
+      MakeInstructionDescriptor(26, spv::Op::OpFAdd, 0);
   auto extract_2 =
       TransformationCompositeExtract(instruction_descriptor_2, 102, 100, {1});
   ASSERT_TRUE(extract_2.IsApplicable(context.get(), transformation_context));
@@ -611,7 +616,7 @@
 
   // Replace %45 with %100[1] in '%46 = OpCompositeConstruct %32 %35 %45'
   auto instruction_descriptor_1 =
-      MakeInstructionDescriptor(46, SpvOpCompositeConstruct, 0);
+      MakeInstructionDescriptor(46, spv::Op::OpCompositeConstruct, 0);
   auto extract_1 =
       TransformationCompositeExtract(instruction_descriptor_1, 201, 100, {1});
   ASSERT_TRUE(extract_1.IsApplicable(context.get(), transformation_context));
@@ -627,7 +632,7 @@
   // Replace second occurrence of %27 with %101[0] in '%28 =
   // OpCompositeConstruct %8 %27 %27'
   auto instruction_descriptor_2 =
-      MakeInstructionDescriptor(28, SpvOpCompositeConstruct, 0);
+      MakeInstructionDescriptor(28, spv::Op::OpCompositeConstruct, 0);
   auto extract_2 =
       TransformationCompositeExtract(instruction_descriptor_2, 202, 101, {0});
   ASSERT_TRUE(extract_2.IsApplicable(context.get(), transformation_context));
@@ -642,7 +647,7 @@
 
   // Replace %36 with %101[1] in '%45 = OpCompositeConstruct %31 %36 %41 %44'
   auto instruction_descriptor_3 =
-      MakeInstructionDescriptor(45, SpvOpCompositeConstruct, 0);
+      MakeInstructionDescriptor(45, spv::Op::OpCompositeConstruct, 0);
   auto extract_3 =
       TransformationCompositeExtract(instruction_descriptor_3, 203, 101, {1});
   ASSERT_TRUE(extract_3.IsApplicable(context.get(), transformation_context));
@@ -658,7 +663,7 @@
   // Replace first occurrence of %27 with %101[2] in '%28 = OpCompositeConstruct
   // %8 %27 %27'
   auto instruction_descriptor_4 =
-      MakeInstructionDescriptor(28, SpvOpCompositeConstruct, 0);
+      MakeInstructionDescriptor(28, spv::Op::OpCompositeConstruct, 0);
   auto extract_4 =
       TransformationCompositeExtract(instruction_descriptor_4, 204, 101, {2});
   ASSERT_TRUE(extract_4.IsApplicable(context.get(), transformation_context));
@@ -672,7 +677,8 @@
                                                kConsoleMessageConsumer));
 
   // Replace %22 with %102[0] in 'OpStore %23 %22'
-  auto instruction_descriptor_5 = MakeInstructionDescriptor(23, SpvOpStore, 0);
+  auto instruction_descriptor_5 =
+      MakeInstructionDescriptor(23, spv::Op::OpStore, 0);
   auto extract_5 =
       TransformationCompositeExtract(instruction_descriptor_5, 205, 102, {0});
   ASSERT_TRUE(extract_5.IsApplicable(context.get(), transformation_context));
@@ -931,7 +937,7 @@
 
   // Replace %20 with %100[0:2] in '%80 = OpCopyObject %16 %20'
   auto instruction_descriptor_1 =
-      MakeInstructionDescriptor(80, SpvOpCopyObject, 0);
+      MakeInstructionDescriptor(80, spv::Op::OpCopyObject, 0);
   auto shuffle_1 = TransformationVectorShuffle(instruction_descriptor_1, 200,
                                                100, 100, {0, 1, 2});
   ASSERT_TRUE(shuffle_1.IsApplicable(context.get(), transformation_context));
@@ -948,7 +954,7 @@
 
   // Replace %54 with %100[3] in '%56 = OpFOrdNotEqual %30 %54 %55'
   auto instruction_descriptor_2 =
-      MakeInstructionDescriptor(56, SpvOpFOrdNotEqual, 0);
+      MakeInstructionDescriptor(56, spv::Op::OpFOrdNotEqual, 0);
   auto extract_2 =
       TransformationCompositeExtract(instruction_descriptor_2, 201, 100, {3});
 
@@ -963,7 +969,8 @@
                                                kConsoleMessageConsumer));
 
   // Replace %15 with %101[0:1] in 'OpStore %12 %15'
-  auto instruction_descriptor_3 = MakeInstructionDescriptor(64, SpvOpStore, 0);
+  auto instruction_descriptor_3 =
+      MakeInstructionDescriptor(64, spv::Op::OpStore, 0);
   auto shuffle_3 = TransformationVectorShuffle(instruction_descriptor_3, 202,
                                                101, 101, {0, 1});
   ASSERT_TRUE(shuffle_3.IsApplicable(context.get(), transformation_context));
@@ -980,7 +987,7 @@
 
   // Replace %19 with %101[2:3] in '%81 = OpVectorShuffle %16 %19 %19 0 0 1'
   auto instruction_descriptor_4 =
-      MakeInstructionDescriptor(81, SpvOpVectorShuffle, 0);
+      MakeInstructionDescriptor(81, spv::Op::OpVectorShuffle, 0);
   auto shuffle_4 = TransformationVectorShuffle(instruction_descriptor_4, 203,
                                                101, 101, {2, 3});
   ASSERT_TRUE(shuffle_4.IsApplicable(context.get(), transformation_context));
@@ -998,7 +1005,7 @@
   // Replace %27 with %102[0] in '%82 = OpCompositeConstruct %21 %26 %27 %28
   // %25'
   auto instruction_descriptor_5 =
-      MakeInstructionDescriptor(82, SpvOpCompositeConstruct, 0);
+      MakeInstructionDescriptor(82, spv::Op::OpCompositeConstruct, 0);
   auto extract_5 =
       TransformationCompositeExtract(instruction_descriptor_5, 204, 102, {0});
 
@@ -1014,7 +1021,7 @@
 
   // Replace %15 with %102[1:2] in '%83 = OpCopyObject %10 %15'
   auto instruction_descriptor_6 =
-      MakeInstructionDescriptor(83, SpvOpCopyObject, 0);
+      MakeInstructionDescriptor(83, spv::Op::OpCopyObject, 0);
   auto shuffle_6 = TransformationVectorShuffle(instruction_descriptor_6, 205,
                                                102, 102, {1, 2});
   ASSERT_TRUE(shuffle_6.IsApplicable(context.get(), transformation_context));
@@ -1031,7 +1038,7 @@
 
   // Replace %33 with %103[0] in '%86 = OpCopyObject %30 %33'
   auto instruction_descriptor_7 =
-      MakeInstructionDescriptor(86, SpvOpCopyObject, 0);
+      MakeInstructionDescriptor(86, spv::Op::OpCopyObject, 0);
   auto extract_7 =
       TransformationCompositeExtract(instruction_descriptor_7, 206, 103, {0});
   ASSERT_TRUE(extract_7.IsApplicable(context.get(), transformation_context));
@@ -1046,7 +1053,7 @@
 
   // Replace %47 with %103[1:3] in '%84 = OpCopyObject %39 %47'
   auto instruction_descriptor_8 =
-      MakeInstructionDescriptor(84, SpvOpCopyObject, 0);
+      MakeInstructionDescriptor(84, spv::Op::OpCopyObject, 0);
   auto shuffle_8 = TransformationVectorShuffle(instruction_descriptor_8, 207,
                                                103, 103, {1, 2, 3});
   ASSERT_TRUE(shuffle_8.IsApplicable(context.get(), transformation_context));
@@ -1063,7 +1070,7 @@
 
   // Replace %42 with %104[0] in '%85 = OpCopyObject %30 %42'
   auto instruction_descriptor_9 =
-      MakeInstructionDescriptor(85, SpvOpCopyObject, 0);
+      MakeInstructionDescriptor(85, spv::Op::OpCopyObject, 0);
   auto extract_9 =
       TransformationCompositeExtract(instruction_descriptor_9, 208, 104, {0});
   ASSERT_TRUE(extract_9.IsApplicable(context.get(), transformation_context));
@@ -1078,7 +1085,7 @@
 
   // Replace %45 with %104[1] in '%63 = OpLogicalOr %30 %45 %46'
   auto instruction_descriptor_10 =
-      MakeInstructionDescriptor(63, SpvOpLogicalOr, 0);
+      MakeInstructionDescriptor(63, spv::Op::OpLogicalOr, 0);
   auto extract_10 =
       TransformationCompositeExtract(instruction_descriptor_10, 209, 104, {1});
   ASSERT_TRUE(extract_10.IsApplicable(context.get(), transformation_context));
@@ -1092,7 +1099,8 @@
                                                kConsoleMessageConsumer));
 
   // Replace %38 with %105[0:1] in 'OpStore %36 %38'
-  auto instruction_descriptor_11 = MakeInstructionDescriptor(85, SpvOpStore, 0);
+  auto instruction_descriptor_11 =
+      MakeInstructionDescriptor(85, spv::Op::OpStore, 0);
   auto shuffle_11 = TransformationVectorShuffle(instruction_descriptor_11, 210,
                                                 105, 105, {0, 1});
   ASSERT_TRUE(shuffle_11.IsApplicable(context.get(), transformation_context));
@@ -1109,7 +1117,7 @@
 
   // Replace %46 with %105[2] in '%62 = OpLogicalAnd %30 %45 %46'
   auto instruction_descriptor_12 =
-      MakeInstructionDescriptor(62, SpvOpLogicalAnd, 0);
+      MakeInstructionDescriptor(62, spv::Op::OpLogicalAnd, 0);
   auto extract_12 =
       TransformationCompositeExtract(instruction_descriptor_12, 211, 105, {2});
   ASSERT_TRUE(extract_12.IsApplicable(context.get(), transformation_context));
diff --git a/test/fuzz/fact_manager/constant_uniform_facts_test.cpp b/test/fuzz/fact_manager/constant_uniform_facts_test.cpp
index 4d80f0a..b267e3d 100644
--- a/test/fuzz/fact_manager/constant_uniform_facts_test.cpp
+++ b/test/fuzz/fact_manager/constant_uniform_facts_test.cpp
@@ -366,41 +366,41 @@
   opt::Instruction::OperandList operands = {
       {SPV_OPERAND_TYPE_LITERAL_INTEGER, {1}}};
   context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-      context.get(), SpvOpConstant, type_int32_id, 50, operands));
+      context.get(), spv::Op::OpConstant, type_int32_id, 50, operands));
   operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_int32_min[0]}}};
   context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-      context.get(), SpvOpConstant, type_int32_id, 51, operands));
+      context.get(), spv::Op::OpConstant, type_int32_id, 51, operands));
   operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_int64_max[0]}},
               {SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_int64_max[1]}}};
   context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-      context.get(), SpvOpConstant, type_int64_id, 52, operands));
+      context.get(), spv::Op::OpConstant, type_int64_id, 52, operands));
   operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {1}}};
   context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-      context.get(), SpvOpConstant, type_uint32_id, 53, operands));
+      context.get(), spv::Op::OpConstant, type_uint32_id, 53, operands));
   operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_uint64_1[0]}},
               {SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_uint64_1[1]}}};
   context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-      context.get(), SpvOpConstant, type_uint64_id, 54, operands));
+      context.get(), spv::Op::OpConstant, type_uint64_id, 54, operands));
   operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_uint64_max[0]}},
               {SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_uint64_max[1]}}};
   context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-      context.get(), SpvOpConstant, type_uint64_id, 55, operands));
+      context.get(), spv::Op::OpConstant, type_uint64_id, 55, operands));
   operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_float_10[0]}}};
   context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-      context.get(), SpvOpConstant, type_float_id, 56, operands));
+      context.get(), spv::Op::OpConstant, type_float_id, 56, operands));
   operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_double_10[0]}},
               {SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_double_10[1]}}};
   context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-      context.get(), SpvOpConstant, type_double_id, 57, operands));
+      context.get(), spv::Op::OpConstant, type_double_id, 57, operands));
   operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_double_20[0]}},
               {SPV_OPERAND_TYPE_LITERAL_INTEGER, {buffer_double_20[1]}}};
   context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-      context.get(), SpvOpConstant, type_double_id, 58, operands));
+      context.get(), spv::Op::OpConstant, type_double_id, 58, operands));
 
   // A duplicate of the constant with id 59.
   operands = {{SPV_OPERAND_TYPE_LITERAL_INTEGER, {1}}};
   context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-      context.get(), SpvOpConstant, type_int32_id, 59, operands));
+      context.get(), spv::Op::OpConstant, type_int32_id, 59, operands));
 
   context->InvalidateAnalysesExceptFor(opt::IRContext::Analysis::kAnalysisNone);
 
diff --git a/test/fuzz/fact_manager/data_synonym_and_id_equation_facts_test.cpp b/test/fuzz/fact_manager/data_synonym_and_id_equation_facts_test.cpp
index 689d2e7..c3b47a4 100644
--- a/test/fuzz/fact_manager/data_synonym_and_id_equation_facts_test.cpp
+++ b/test/fuzz/fact_manager/data_synonym_and_id_equation_facts_test.cpp
@@ -136,15 +136,15 @@
   FactManager fact_manager(context.get());
 
   // Add equation facts
-  fact_manager.AddFactIdEquation(24, SpvOpConvertSToF, {15});
-  fact_manager.AddFactIdEquation(25, SpvOpConvertSToF, {16});
-  fact_manager.AddFactIdEquation(26, SpvOpConvertUToF, {17});
-  fact_manager.AddFactIdEquation(27, SpvOpConvertSToF, {18});
-  fact_manager.AddFactIdEquation(28, SpvOpConvertUToF, {19});
-  fact_manager.AddFactIdEquation(29, SpvOpConvertUToF, {20});
-  fact_manager.AddFactIdEquation(30, SpvOpConvertSToF, {21});
-  fact_manager.AddFactIdEquation(31, SpvOpConvertUToF, {22});
-  fact_manager.AddFactIdEquation(32, SpvOpConvertUToF, {23});
+  fact_manager.AddFactIdEquation(24, spv::Op::OpConvertSToF, {15});
+  fact_manager.AddFactIdEquation(25, spv::Op::OpConvertSToF, {16});
+  fact_manager.AddFactIdEquation(26, spv::Op::OpConvertUToF, {17});
+  fact_manager.AddFactIdEquation(27, spv::Op::OpConvertSToF, {18});
+  fact_manager.AddFactIdEquation(28, spv::Op::OpConvertUToF, {19});
+  fact_manager.AddFactIdEquation(29, spv::Op::OpConvertUToF, {20});
+  fact_manager.AddFactIdEquation(30, spv::Op::OpConvertSToF, {21});
+  fact_manager.AddFactIdEquation(31, spv::Op::OpConvertUToF, {22});
+  fact_manager.AddFactIdEquation(32, spv::Op::OpConvertUToF, {23});
 
   fact_manager.AddFactDataSynonym(MakeDataDescriptor(15, {}),
                                   MakeDataDescriptor(16, {}));
@@ -212,7 +212,7 @@
 
   // Add required facts.
   transformation_context.GetFactManager()->AddFactIdEquation(
-      14, SpvOpConvertSToF, {9});
+      14, spv::Op::OpConvertSToF, {9});
   transformation_context.GetFactManager()->AddFactDataSynonym(
       MakeDataDescriptor(14, {}), MakeDataDescriptor(17, {}));
 
@@ -232,7 +232,7 @@
 
   // Add another equation.
   transformation_context.GetFactManager()->AddFactIdEquation(
-      15, SpvOpConvertSToF, {9});
+      15, spv::Op::OpConvertSToF, {9});
 
   // Check that two ids are synonymous even though one of them doesn't exist in
   // the module (%17).
@@ -249,7 +249,7 @@
   ASSERT_TRUE(context->KillDef(15));
 
   transformation_context.GetFactManager()->AddFactIdEquation(
-      18, SpvOpConvertSToF, {9});
+      18, spv::Op::OpConvertSToF, {9});
 
   CheckConsistencyOfSynonymFacts(context.get(), transformation_context);
 
@@ -294,8 +294,8 @@
                                   MakeDataDescriptor(7, {}));
   fact_manager.AddFactDataSynonym(MakeDataDescriptor(16, {}),
                                   MakeDataDescriptor(14, {}));
-  fact_manager.AddFactIdEquation(14, SpvOpLogicalNot, {7});
-  fact_manager.AddFactIdEquation(17, SpvOpLogicalNot, {16});
+  fact_manager.AddFactIdEquation(14, spv::Op::OpLogicalNot, {7});
+  fact_manager.AddFactIdEquation(17, spv::Op::OpLogicalNot, {16});
 
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(15, {}),
                                         MakeDataDescriptor(7, {})));
@@ -336,8 +336,8 @@
 
   FactManager fact_manager(context.get());
 
-  fact_manager.AddFactIdEquation(14, SpvOpSNegate, {7});
-  fact_manager.AddFactIdEquation(15, SpvOpSNegate, {14});
+  fact_manager.AddFactIdEquation(14, spv::Op::OpSNegate, {7});
+  fact_manager.AddFactIdEquation(15, spv::Op::OpSNegate, {14});
 
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(7, {}),
                                         MakeDataDescriptor(15, {})));
@@ -380,19 +380,19 @@
 
   FactManager fact_manager(context.get());
 
-  fact_manager.AddFactIdEquation(14, SpvOpIAdd, {15, 16});
+  fact_manager.AddFactIdEquation(14, spv::Op::OpIAdd, {15, 16});
   fact_manager.AddFactDataSynonym(MakeDataDescriptor(17, {}),
                                   MakeDataDescriptor(15, {}));
   fact_manager.AddFactDataSynonym(MakeDataDescriptor(18, {}),
                                   MakeDataDescriptor(16, {}));
-  fact_manager.AddFactIdEquation(19, SpvOpISub, {14, 18});
-  fact_manager.AddFactIdEquation(20, SpvOpISub, {14, 17});
+  fact_manager.AddFactIdEquation(19, spv::Op::OpISub, {14, 18});
+  fact_manager.AddFactIdEquation(20, spv::Op::OpISub, {14, 17});
   fact_manager.AddFactDataSynonym(MakeDataDescriptor(21, {}),
                                   MakeDataDescriptor(14, {}));
-  fact_manager.AddFactIdEquation(22, SpvOpISub, {16, 21});
+  fact_manager.AddFactIdEquation(22, spv::Op::OpISub, {16, 21});
   fact_manager.AddFactDataSynonym(MakeDataDescriptor(23, {}),
                                   MakeDataDescriptor(22, {}));
-  fact_manager.AddFactIdEquation(24, SpvOpSNegate, {23});
+  fact_manager.AddFactIdEquation(24, spv::Op::OpSNegate, {23});
 
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(19, {}),
                                         MakeDataDescriptor(15, {})));
@@ -438,31 +438,31 @@
 
   FactManager fact_manager(context.get());
 
-  fact_manager.AddFactIdEquation(14, SpvOpISub, {15, 16});
-  fact_manager.AddFactIdEquation(17, SpvOpIAdd, {14, 16});
+  fact_manager.AddFactIdEquation(14, spv::Op::OpISub, {15, 16});
+  fact_manager.AddFactIdEquation(17, spv::Op::OpIAdd, {14, 16});
 
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(17, {}),
                                         MakeDataDescriptor(15, {})));
 
-  fact_manager.AddFactIdEquation(18, SpvOpIAdd, {16, 14});
+  fact_manager.AddFactIdEquation(18, spv::Op::OpIAdd, {16, 14});
 
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(18, {}),
                                         MakeDataDescriptor(15, {})));
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(17, {}),
                                         MakeDataDescriptor(18, {})));
 
-  fact_manager.AddFactIdEquation(19, SpvOpISub, {14, 15});
-  fact_manager.AddFactIdEquation(20, SpvOpSNegate, {19});
+  fact_manager.AddFactIdEquation(19, spv::Op::OpISub, {14, 15});
+  fact_manager.AddFactIdEquation(20, spv::Op::OpSNegate, {19});
 
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(20, {}),
                                         MakeDataDescriptor(16, {})));
 
-  fact_manager.AddFactIdEquation(21, SpvOpISub, {14, 19});
+  fact_manager.AddFactIdEquation(21, spv::Op::OpISub, {14, 19});
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(21, {}),
                                         MakeDataDescriptor(15, {})));
 
-  fact_manager.AddFactIdEquation(22, SpvOpISub, {14, 18});
-  fact_manager.AddFactIdEquation(23, SpvOpSNegate, {22});
+  fact_manager.AddFactIdEquation(22, spv::Op::OpISub, {14, 18});
+  fact_manager.AddFactIdEquation(23, spv::Op::OpSNegate, {22});
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(23, {}),
                                         MakeDataDescriptor(16, {})));
 }
@@ -525,31 +525,31 @@
   fact_manager.AddFactDataSynonym(MakeDataDescriptor(22, {}),
                                   MakeDataDescriptor(23, {}));
 
-  fact_manager.AddFactIdEquation(25, SpvOpConvertUToF, {16});
-  fact_manager.AddFactIdEquation(26, SpvOpConvertUToF, {17});
+  fact_manager.AddFactIdEquation(25, spv::Op::OpConvertUToF, {16});
+  fact_manager.AddFactIdEquation(26, spv::Op::OpConvertUToF, {17});
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(25, {}),
                                         MakeDataDescriptor(26, {})));
 
-  fact_manager.AddFactIdEquation(27, SpvOpConvertSToF, {20});
-  fact_manager.AddFactIdEquation(28, SpvOpConvertUToF, {21});
+  fact_manager.AddFactIdEquation(27, spv::Op::OpConvertSToF, {20});
+  fact_manager.AddFactIdEquation(28, spv::Op::OpConvertUToF, {21});
   ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(27, {}),
                                          MakeDataDescriptor(28, {})));
 
-  fact_manager.AddFactIdEquation(29, SpvOpConvertSToF, {18});
-  fact_manager.AddFactIdEquation(30, SpvOpConvertUToF, {19});
+  fact_manager.AddFactIdEquation(29, spv::Op::OpConvertSToF, {18});
+  fact_manager.AddFactIdEquation(30, spv::Op::OpConvertUToF, {19});
   ASSERT_FALSE(fact_manager.IsSynonymous(MakeDataDescriptor(29, {}),
                                          MakeDataDescriptor(30, {})));
 
-  fact_manager.AddFactIdEquation(31, SpvOpConvertSToF, {22});
-  fact_manager.AddFactIdEquation(32, SpvOpConvertSToF, {23});
+  fact_manager.AddFactIdEquation(31, spv::Op::OpConvertSToF, {22});
+  fact_manager.AddFactIdEquation(32, spv::Op::OpConvertSToF, {23});
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(31, {}),
                                         MakeDataDescriptor(32, {})));
 
-  fact_manager.AddFactIdEquation(33, SpvOpConvertUToF, {17});
+  fact_manager.AddFactIdEquation(33, spv::Op::OpConvertUToF, {17});
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(33, {}),
                                         MakeDataDescriptor(26, {})));
 
-  fact_manager.AddFactIdEquation(34, SpvOpConvertSToF, {23});
+  fact_manager.AddFactIdEquation(34, spv::Op::OpConvertSToF, {23});
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(32, {}),
                                         MakeDataDescriptor(34, {})));
 }
@@ -605,7 +605,7 @@
 
   uint32_t lhs_id = 30;
   for (uint32_t rhs_id : {6, 6, 7, 7, 19, 19, 20, 20, 21, 21, 22, 22}) {
-    fact_manager.AddFactIdEquation(lhs_id, SpvOpBitcast, {rhs_id});
+    fact_manager.AddFactIdEquation(lhs_id, spv::Op::OpBitcast, {rhs_id});
     ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(lhs_id, {}),
                                           MakeDataDescriptor(rhs_id, {})));
     ++lhs_id;
@@ -651,37 +651,37 @@
 
   FactManager fact_manager(context.get());
 
-  fact_manager.AddFactIdEquation(14, SpvOpISub, {15, 16});
+  fact_manager.AddFactIdEquation(14, spv::Op::OpISub, {15, 16});
   fact_manager.AddFactDataSynonym(MakeDataDescriptor(114, {}),
                                   MakeDataDescriptor(14, {}));
-  fact_manager.AddFactIdEquation(17, SpvOpIAdd, {114, 16});
+  fact_manager.AddFactIdEquation(17, spv::Op::OpIAdd, {114, 16});
 
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(17, {}),
                                         MakeDataDescriptor(15, {})));
 
-  fact_manager.AddFactIdEquation(18, SpvOpIAdd, {16, 114});
+  fact_manager.AddFactIdEquation(18, spv::Op::OpIAdd, {16, 114});
 
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(18, {}),
                                         MakeDataDescriptor(15, {})));
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(17, {}),
                                         MakeDataDescriptor(18, {})));
 
-  fact_manager.AddFactIdEquation(19, SpvOpISub, {14, 15});
+  fact_manager.AddFactIdEquation(19, spv::Op::OpISub, {14, 15});
   fact_manager.AddFactDataSynonym(MakeDataDescriptor(119, {}),
                                   MakeDataDescriptor(19, {}));
-  fact_manager.AddFactIdEquation(20, SpvOpSNegate, {119});
+  fact_manager.AddFactIdEquation(20, spv::Op::OpSNegate, {119});
 
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(20, {}),
                                         MakeDataDescriptor(16, {})));
 
-  fact_manager.AddFactIdEquation(21, SpvOpISub, {14, 19});
+  fact_manager.AddFactIdEquation(21, spv::Op::OpISub, {14, 19});
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(21, {}),
                                         MakeDataDescriptor(15, {})));
 
-  fact_manager.AddFactIdEquation(22, SpvOpISub, {14, 18});
+  fact_manager.AddFactIdEquation(22, spv::Op::OpISub, {14, 18});
   fact_manager.AddFactDataSynonym(MakeDataDescriptor(22, {}),
                                   MakeDataDescriptor(220, {}));
-  fact_manager.AddFactIdEquation(23, SpvOpSNegate, {220});
+  fact_manager.AddFactIdEquation(23, spv::Op::OpSNegate, {220});
   ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(23, {}),
                                         MakeDataDescriptor(16, {})));
 }
diff --git a/test/fuzz/fuzzer_pass_donate_modules_test.cpp b/test/fuzz/fuzzer_pass_donate_modules_test.cpp
index fe8e671..81687ac 100644
--- a/test/fuzz/fuzzer_pass_donate_modules_test.cpp
+++ b/test/fuzz/fuzzer_pass_donate_modules_test.cpp
@@ -2025,9 +2025,9 @@
                                       &transformation_sequence, false, {});
 
   ASSERT_TRUE(donor_context->get_feature_mgr()->HasCapability(
-      SpvCapabilityVariablePointersStorageBuffer));
+      spv::Capability::VariablePointersStorageBuffer));
   ASSERT_FALSE(recipient_context->get_feature_mgr()->HasCapability(
-      SpvCapabilityVariablePointersStorageBuffer));
+      spv::Capability::VariablePointersStorageBuffer));
 
   fuzzer_pass.DonateSingleModule(donor_context.get(), false);
 
@@ -2040,12 +2040,12 @@
   // have different OpCapability instructions but the same capabilities. In our
   // example, VariablePointers implicitly declares
   // VariablePointersStorageBuffer. Thus, two modules must be compatible.
-  recipient_context->AddCapability(SpvCapabilityVariablePointers);
+  recipient_context->AddCapability(spv::Capability::VariablePointers);
 
   ASSERT_TRUE(donor_context->get_feature_mgr()->HasCapability(
-      SpvCapabilityVariablePointersStorageBuffer));
+      spv::Capability::VariablePointersStorageBuffer));
   ASSERT_TRUE(recipient_context->get_feature_mgr()->HasCapability(
-      SpvCapabilityVariablePointersStorageBuffer));
+      spv::Capability::VariablePointersStorageBuffer));
 
   fuzzer_pass.DonateSingleModule(donor_context.get(), false);
 
diff --git a/test/fuzz/fuzzerutil_test.cpp b/test/fuzz/fuzzerutil_test.cpp
index 1286d38..6555336 100644
--- a/test/fuzz/fuzzerutil_test.cpp
+++ b/test/fuzz/fuzzerutil_test.cpp
@@ -939,9 +939,9 @@
                                                kConsoleMessageConsumer));
 
   opt::IRContext* ir_context = context.get();
-  auto private_storage_class = SpvStorageClassPrivate;
-  auto function_storage_class = SpvStorageClassFunction;
-  auto input_storage_class = SpvStorageClassInput;
+  auto private_storage_class = spv::StorageClass::Private;
+  auto function_storage_class = spv::StorageClass::Function;
+  auto input_storage_class = spv::StorageClass::Input;
 
   // A valid pointer must have the correct |pointee_type_id| and |storageClass|.
   // A function type pointer with id = 9 and pointee type id 8 should be found.
@@ -1610,196 +1610,206 @@
 
   // OpAtomicLoad
 #ifndef NDEBUG
-  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicLoad, 0,
-                                              int_type, uint_type),
-               "Signedness check should not occur on a pointer operand.");
-#endif
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicLoad, 1,
-                                             int_type, uint_type));
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicLoad, 2,
-                                             int_type, uint_type));
-
-  // OpAtomicExchange
-#ifndef NDEBUG
-  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(
-                   context.get(), SpvOpAtomicExchange, 0, int_type, uint_type),
-               "Signedness check should not occur on a pointer operand.");
-#endif
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicExchange,
-                                             1, int_type, uint_type));
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicExchange,
-                                             2, int_type, uint_type));
-  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
-      context.get(), SpvOpAtomicExchange, 3, int_type, uint_type));
-
-  // OpAtomicStore
-#ifndef NDEBUG
-  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicStore,
-                                              0, int_type, uint_type),
-               "Signedness check should not occur on a pointer operand.");
-#endif
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicStore, 1,
-                                             int_type, uint_type));
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicStore, 2,
-                                             int_type, uint_type));
-  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicStore,
-                                              3, int_type, uint_type));
-
-  // OpAtomicCompareExchange
-#ifndef NDEBUG
   ASSERT_DEATH(
-      fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicCompareExchange,
-                                     0, int_type, uint_type),
-      "Signedness check should not occur on a pointer operand.");
-#endif
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
-      context.get(), SpvOpAtomicCompareExchange, 1, int_type, uint_type));
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
-      context.get(), SpvOpAtomicCompareExchange, 2, int_type, uint_type));
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
-      context.get(), SpvOpAtomicCompareExchange, 3, int_type, uint_type));
-  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
-      context.get(), SpvOpAtomicCompareExchange, 4, int_type, uint_type));
-
-  // OpAtomicIIncrement
-#ifndef NDEBUG
-  ASSERT_DEATH(
-      fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicIIncrement, 0,
+      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicLoad, 0,
                                      int_type, uint_type),
       "Signedness check should not occur on a pointer operand.");
 #endif
   ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
-      context.get(), SpvOpAtomicIIncrement, 1, int_type, uint_type));
+      context.get(), spv::Op::OpAtomicLoad, 1, int_type, uint_type));
   ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
-      context.get(), SpvOpAtomicIIncrement, 2, int_type, uint_type));
+      context.get(), spv::Op::OpAtomicLoad, 2, int_type, uint_type));
 
-// OpAtomicIDecrement
+  // OpAtomicExchange
 #ifndef NDEBUG
-  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicStore,
+  ASSERT_DEATH(
+      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicExchange,
+                                     0, int_type, uint_type),
+      "Signedness check should not occur on a pointer operand.");
+#endif
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicExchange, 1, int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicExchange, 2, int_type, uint_type));
+  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicExchange, 3, int_type, uint_type));
+
+  // OpAtomicStore
+#ifndef NDEBUG
+  ASSERT_DEATH(
+      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicStore, 0,
+                                     int_type, uint_type),
+      "Signedness check should not occur on a pointer operand.");
+#endif
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicStore, 1, int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicStore, 2, int_type, uint_type));
+  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicStore, 3, int_type, uint_type));
+
+  // OpAtomicCompareExchange
+#ifndef NDEBUG
+  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(context.get(),
+                                              spv::Op::OpAtomicCompareExchange,
                                               0, int_type, uint_type),
                "Signedness check should not occur on a pointer operand.");
 #endif
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicStore, 1,
-                                             int_type, uint_type));
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicStore, 2,
-                                             int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicCompareExchange, 1, int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicCompareExchange, 2, int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicCompareExchange, 3, int_type, uint_type));
+  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicCompareExchange, 4, int_type, uint_type));
+
+  // OpAtomicIIncrement
+#ifndef NDEBUG
+  ASSERT_DEATH(
+      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicIIncrement,
+                                     0, int_type, uint_type),
+      "Signedness check should not occur on a pointer operand.");
+#endif
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicIIncrement, 1, int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicIIncrement, 2, int_type, uint_type));
+
+// OpAtomicIDecrement
+#ifndef NDEBUG
+  ASSERT_DEATH(
+      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicStore, 0,
+                                     int_type, uint_type),
+      "Signedness check should not occur on a pointer operand.");
+#endif
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicStore, 1, int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicStore, 2, int_type, uint_type));
 
 // OpAtomicIAdd
 #ifndef NDEBUG
-  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicIAdd, 0,
-                                              int_type, uint_type),
-               "Signedness check should not occur on a pointer operand.");
+  ASSERT_DEATH(
+      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicIAdd, 0,
+                                     int_type, uint_type),
+      "Signedness check should not occur on a pointer operand.");
 #endif
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicIAdd, 1,
-                                             int_type, uint_type));
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicIAdd, 2,
-                                             int_type, uint_type));
-  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicIAdd, 3,
-                                              int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicIAdd, 1, int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicIAdd, 2, int_type, uint_type));
+  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicIAdd, 3, int_type, uint_type));
 
 // OpAtomicISub
 #ifndef NDEBUG
-  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicISub, 0,
-                                              int_type, uint_type),
-               "Signedness check should not occur on a pointer operand.");
+  ASSERT_DEATH(
+      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicISub, 0,
+                                     int_type, uint_type),
+      "Signedness check should not occur on a pointer operand.");
 #endif
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicISub, 1,
-                                             int_type, uint_type));
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicISub, 2,
-                                             int_type, uint_type));
-  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicISub, 3,
-                                              int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicISub, 1, int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicISub, 2, int_type, uint_type));
+  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicISub, 3, int_type, uint_type));
 
 // OpAtomicSMin
 #ifndef NDEBUG
-  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicSMin, 0,
-                                              int_type, uint_type),
-               "Signedness check should not occur on a pointer operand.");
+  ASSERT_DEATH(
+      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicSMin, 0,
+                                     int_type, uint_type),
+      "Signedness check should not occur on a pointer operand.");
 #endif
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicSMin, 1,
-                                             int_type, uint_type));
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicSMin, 2,
-                                             int_type, uint_type));
-  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicSMin, 3,
-                                              int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicSMin, 1, int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicSMin, 2, int_type, uint_type));
+  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicSMin, 3, int_type, uint_type));
 
 // OpAtomicUMin
 #ifndef NDEBUG
-  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicUMin, 0,
-                                              int_type, uint_type),
-               "Signedness check should not occur on a pointer operand.");
+  ASSERT_DEATH(
+      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicUMin, 0,
+                                     int_type, uint_type),
+      "Signedness check should not occur on a pointer operand.");
 #endif
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicUMin, 1,
-                                             int_type, uint_type));
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicUMin, 2,
-                                             int_type, uint_type));
-  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicUMin, 3,
-                                              int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicUMin, 1, int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicUMin, 2, int_type, uint_type));
+  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicUMin, 3, int_type, uint_type));
 
 // OpAtomicSMax
 #ifndef NDEBUG
-  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicSMax, 0,
-                                              int_type, uint_type),
-               "Signedness check should not occur on a pointer operand.");
+  ASSERT_DEATH(
+      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicSMax, 0,
+                                     int_type, uint_type),
+      "Signedness check should not occur on a pointer operand.");
 #endif
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicSMax, 1,
-                                             int_type, uint_type));
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicSMax, 2,
-                                             int_type, uint_type));
-  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicSMax, 3,
-                                              int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicSMax, 1, int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicSMax, 2, int_type, uint_type));
+  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicSMax, 3, int_type, uint_type));
 
 // OpAtomicUMax
 #ifndef NDEBUG
-  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicUMax, 0,
-                                              int_type, uint_type),
-               "Signedness check should not occur on a pointer operand.");
+  ASSERT_DEATH(
+      fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicUMax, 0,
+                                     int_type, uint_type),
+      "Signedness check should not occur on a pointer operand.");
 #endif
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicUMax, 1,
-                                             int_type, uint_type));
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicUMax, 2,
-                                             int_type, uint_type));
-  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicUMax, 3,
-                                              int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicUMax, 1, int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicUMax, 2, int_type, uint_type));
+  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicUMax, 3, int_type, uint_type));
 
 // OpAtomicAnd
 #ifndef NDEBUG
-  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicAnd, 0,
-                                              int_type, uint_type),
+  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(
+                   context.get(), spv::Op::OpAtomicAnd, 0, int_type, uint_type),
                "Signedness check should not occur on a pointer operand.");
 #endif
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicAnd, 1,
-                                             int_type, uint_type));
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicAnd, 2,
-                                             int_type, uint_type));
-  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicAnd, 3,
-                                              int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicAnd, 1, int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicAnd, 2, int_type, uint_type));
+  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicAnd, 3, int_type, uint_type));
 
 // OpAtomicOr
 #ifndef NDEBUG
-  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicOr, 0,
-                                              int_type, uint_type),
+  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(
+                   context.get(), spv::Op::OpAtomicOr, 0, int_type, uint_type),
                "Signedness check should not occur on a pointer operand.");
 #endif
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicOr, 1,
-                                             int_type, uint_type));
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicOr, 2,
-                                             int_type, uint_type));
-  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicOr, 3,
-                                              int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicOr,
+                                             1, int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), spv::Op::OpAtomicOr,
+                                             2, int_type, uint_type));
+  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicOr, 3, int_type, uint_type));
 
 // OpAtomicXor
 #ifndef NDEBUG
-  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicXor, 0,
-                                              int_type, uint_type),
+  ASSERT_DEATH(fuzzerutil::TypesAreCompatible(
+                   context.get(), spv::Op::OpAtomicXor, 0, int_type, uint_type),
                "Signedness check should not occur on a pointer operand.");
 #endif
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicXor, 1,
-                                             int_type, uint_type));
-  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicXor, 2,
-                                             int_type, uint_type));
-  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(context.get(), SpvOpAtomicXor, 3,
-                                              int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicXor, 1, int_type, uint_type));
+  ASSERT_TRUE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicXor, 2, int_type, uint_type));
+  ASSERT_FALSE(fuzzerutil::TypesAreCompatible(
+      context.get(), spv::Op::OpAtomicXor, 3, int_type, uint_type));
 }
 
 }  // namespace
diff --git a/test/fuzz/replayer_test.cpp b/test/fuzz/replayer_test.cpp
index 151f263..b87d4f8 100644
--- a/test/fuzz/replayer_test.cpp
+++ b/test/fuzz/replayer_test.cpp
@@ -90,8 +90,8 @@
   protobufs::TransformationSequence transformations;
   for (uint32_t id = 12; id <= 22; id++) {
     *transformations.add_transformation() =
-        TransformationSplitBlock(MakeInstructionDescriptor(id, SpvOpLoad, 0),
-                                 id + 100)
+        TransformationSplitBlock(
+            MakeInstructionDescriptor(id, spv::Op::OpLoad, 0), id + 100)
             .ToMessage();
   }
 
@@ -335,7 +335,7 @@
   *transformations.add_transformation() =
       TransformationAddConstantScalar(100, 8, {42}, true).ToMessage();
   *transformations.add_transformation() =
-      TransformationAddGlobalVariable(101, 50, SpvStorageClassPrivate, 100,
+      TransformationAddGlobalVariable(101, 50, spv::StorageClass::Private, 100,
                                       true)
           .ToMessage();
   *transformations.add_transformation() =
@@ -345,7 +345,7 @@
           11,
           protobufs::TransformationAddSynonym::SynonymType::
               TransformationAddSynonym_SynonymType_COPY_OBJECT,
-          104, MakeInstructionDescriptor(12, SpvOpFunctionCall, 0))
+          104, MakeInstructionDescriptor(12, spv::Op::OpFunctionCall, 0))
           .ToMessage();
 
   // Full replay
@@ -455,7 +455,8 @@
   *transformations.add_transformation() =
       TransformationFlattenConditionalBranch(5, true, 0, 0, 0, {}).ToMessage();
   *transformations.add_transformation() =
-      TransformationAddGlobalVariable(101, 50, SpvStorageClassPrivate, 11, true)
+      TransformationAddGlobalVariable(101, 50, spv::StorageClass::Private, 11,
+                                      true)
           .ToMessage();
 
   protobufs::FactSequence empty_facts;
diff --git a/test/fuzz/shrinker_test.cpp b/test/fuzz/shrinker_test.cpp
index 942de29..699730c 100644
--- a/test/fuzz/shrinker_test.cpp
+++ b/test/fuzz/shrinker_test.cpp
@@ -186,9 +186,9 @@
     for (auto& function : *temp_ir_context->module()) {
       for (auto& block : function) {
         for (auto& inst : block) {
-          if (inst.opcode() == SpvOpNot) {
+          if (inst.opcode() == spv::Op::OpNot) {
             found_op_not = true;
-          } else if (inst.opcode() == SpvOpFunctionCall) {
+          } else if (inst.opcode() == spv::Op::OpFunctionCall) {
             op_call_count++;
           }
         }
@@ -221,21 +221,21 @@
         for (auto& inst : block) {
           switch (counter) {
             case 0:
-              ASSERT_EQ(SpvOpVariable, inst.opcode());
+              ASSERT_EQ(spv::Op::OpVariable, inst.opcode());
               ASSERT_EQ(11, inst.result_id());
               break;
             case 1:
-              ASSERT_EQ(SpvOpStore, inst.opcode());
+              ASSERT_EQ(spv::Op::OpStore, inst.opcode());
               break;
             case 2:
-              ASSERT_EQ(SpvOpLoad, inst.opcode());
+              ASSERT_EQ(spv::Op::OpLoad, inst.opcode());
               ASSERT_EQ(12, inst.result_id());
               break;
             case 3:
-              ASSERT_EQ(SpvOpStore, inst.opcode());
+              ASSERT_EQ(spv::Op::OpStore, inst.opcode());
               break;
             case 4:
-              ASSERT_EQ(SpvOpReturn, inst.opcode());
+              ASSERT_EQ(spv::Op::OpReturn, inst.opcode());
               break;
             default:
               FAIL();
@@ -250,11 +250,11 @@
         first_block = false;
         for (auto& inst : block) {
           switch (inst.opcode()) {
-            case SpvOpVariable:
-            case SpvOpNot:
-            case SpvOpReturn:
-            case SpvOpReturnValue:
-            case SpvOpFunctionCall:
+            case spv::Op::OpVariable:
+            case spv::Op::OpNot:
+            case spv::Op::OpReturn:
+            case spv::Op::OpReturnValue:
+            case spv::Op::OpFunctionCall:
               // These are the only instructions we expect to see.
               break;
             default:
@@ -362,7 +362,7 @@
     uint32_t copy_object_count = 0;
     temp_ir_context->module()->ForEachInst(
         [&copy_object_count](opt::Instruction* inst) {
-          if (inst->opcode() == SpvOpCopyObject) {
+          if (inst->opcode() == spv::Op::OpCopyObject) {
             copy_object_count++;
           }
         });
diff --git a/test/fuzz/transformation_access_chain_test.cpp b/test/fuzz/transformation_access_chain_test.cpp
index bddcf5f..fa19aa5 100644
--- a/test/fuzz/transformation_access_chain_test.cpp
+++ b/test/fuzz/transformation_access_chain_test.cpp
@@ -129,7 +129,7 @@
 
   // Check the case where the index type is not a 32-bit integer.
   TransformationAccessChain invalid_index_example1(
-      101, 28, {29}, MakeInstructionDescriptor(42, SpvOpReturn, 0));
+      101, 28, {29}, MakeInstructionDescriptor(42, spv::Op::OpReturn, 0));
 
   // Since the index  is not a 32-bit integer type but a 32-bit float type,
   // ValidIndexComposite should return false and thus the transformation is not
@@ -138,86 +138,95 @@
                                                    transformation_context));
 
   // Bad: id is not fresh
-  ASSERT_FALSE(TransformationAccessChain(
-                   43, 43, {80}, MakeInstructionDescriptor(24, SpvOpLoad, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAccessChain(
+          43, 43, {80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer id does not exist
-  ASSERT_FALSE(TransformationAccessChain(
-                   100, 1000, {80}, MakeInstructionDescriptor(24, SpvOpLoad, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAccessChain(
+          100, 1000, {80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer id is not a type
-  ASSERT_FALSE(TransformationAccessChain(
-                   100, 5, {80}, MakeInstructionDescriptor(24, SpvOpLoad, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAccessChain(
+          100, 5, {80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer id is not a pointer
-  ASSERT_FALSE(TransformationAccessChain(
-                   100, 23, {80}, MakeInstructionDescriptor(24, SpvOpLoad, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAccessChain(
+          100, 23, {80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   // Bad: index id does not exist
-  ASSERT_FALSE(TransformationAccessChain(
-                   100, 43, {1000}, MakeInstructionDescriptor(24, SpvOpLoad, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAccessChain(
+          100, 43, {1000}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   // Bad: index id is not a constant and the pointer refers to a struct
-  ASSERT_FALSE(TransformationAccessChain(
-                   100, 43, {24}, MakeInstructionDescriptor(25, SpvOpIAdd, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAccessChain(
+          100, 43, {24}, MakeInstructionDescriptor(25, spv::Op::OpIAdd, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   // Bad: too many indices
-  ASSERT_FALSE(
-      TransformationAccessChain(100, 43, {80, 80, 80},
-                                MakeInstructionDescriptor(24, SpvOpLoad, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAccessChain(
+                   100, 43, {80, 80, 80},
+                   MakeInstructionDescriptor(24, spv::Op::OpLoad, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: index id is out of bounds when accessing a struct
   ASSERT_FALSE(
-      TransformationAccessChain(100, 43, {83, 80},
-                                MakeInstructionDescriptor(24, SpvOpLoad, 0))
+      TransformationAccessChain(
+          100, 43, {83, 80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0))
           .IsApplicable(context.get(), transformation_context));
 
   // Bad: attempt to insert before variable
-  ASSERT_FALSE(TransformationAccessChain(
-                   100, 34, {}, MakeInstructionDescriptor(36, SpvOpVariable, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAccessChain(
+          100, 34, {}, MakeInstructionDescriptor(36, spv::Op::OpVariable, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   // Bad: OpTypeBool must be present in the module to clamp an index
   ASSERT_FALSE(
-      TransformationAccessChain(100, 36, {80, 81},
-                                MakeInstructionDescriptor(37, SpvOpStore, 0))
+      TransformationAccessChain(
+          100, 36, {80, 81}, MakeInstructionDescriptor(37, spv::Op::OpStore, 0))
           .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer not available
-  ASSERT_FALSE(
-      TransformationAccessChain(
-          100, 43, {80}, MakeInstructionDescriptor(21, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAccessChain(
+                   100, 43, {80},
+                   MakeInstructionDescriptor(21, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: instruction descriptor does not identify anything
-  ASSERT_FALSE(TransformationAccessChain(
-                   100, 43, {80}, MakeInstructionDescriptor(24, SpvOpLoad, 100))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAccessChain(
+          100, 43, {80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 100))
+          .IsApplicable(context.get(), transformation_context));
 
 #ifndef NDEBUG
   // Bad: pointer is null
   ASSERT_DEATH(
-      TransformationAccessChain(100, 46, {80},
-                                MakeInstructionDescriptor(24, SpvOpLoad, 0))
+      TransformationAccessChain(
+          100, 46, {80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0))
           .IsApplicable(context.get(), transformation_context),
       "Access chains should not be created from null/undefined pointers");
 #endif
 
   // Bad: pointer to result type does not exist
-  ASSERT_FALSE(TransformationAccessChain(
-                   100, 52, {0}, MakeInstructionDescriptor(24, SpvOpLoad, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAccessChain(
+          100, 52, {0}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   {
     TransformationAccessChain transformation(
-        100, 43, {80}, MakeInstructionDescriptor(24, SpvOpLoad, 0));
+        100, 43, {80}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -230,7 +239,7 @@
 
   {
     TransformationAccessChain transformation(
-        101, 28, {81}, MakeInstructionDescriptor(42, SpvOpReturn, 0));
+        101, 28, {81}, MakeInstructionDescriptor(42, spv::Op::OpReturn, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -243,7 +252,7 @@
 
   {
     TransformationAccessChain transformation(
-        102, 44, {}, MakeInstructionDescriptor(44, SpvOpStore, 0));
+        102, 44, {}, MakeInstructionDescriptor(44, spv::Op::OpStore, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -256,7 +265,8 @@
 
   {
     TransformationAccessChain transformation(
-        103, 13, {80}, MakeInstructionDescriptor(21, SpvOpAccessChain, 0));
+        103, 13, {80},
+        MakeInstructionDescriptor(21, spv::Op::OpAccessChain, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -269,7 +279,7 @@
 
   {
     TransformationAccessChain transformation(
-        104, 34, {}, MakeInstructionDescriptor(44, SpvOpStore, 1));
+        104, 34, {}, MakeInstructionDescriptor(44, spv::Op::OpStore, 1));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -282,7 +292,7 @@
 
   {
     TransformationAccessChain transformation(
-        105, 38, {}, MakeInstructionDescriptor(40, SpvOpFunctionCall, 0));
+        105, 38, {}, MakeInstructionDescriptor(40, spv::Op::OpFunctionCall, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -295,7 +305,7 @@
 
   {
     TransformationAccessChain transformation(
-        106, 14, {}, MakeInstructionDescriptor(24, SpvOpLoad, 0));
+        106, 14, {}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -309,7 +319,7 @@
     // Check the case where the access chain's base pointer has the irrelevant
     // pointee fact; the resulting access chain should inherit this fact.
     TransformationAccessChain transformation(
-        107, 54, {}, MakeInstructionDescriptor(24, SpvOpLoad, 0));
+        107, 54, {}, MakeInstructionDescriptor(24, spv::Op::OpLoad, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -440,9 +450,10 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   // Bad: %9 is a pointer to a struct, but %20 is not a constant.
-  ASSERT_FALSE(TransformationAccessChain(
-                   100, 9, {20}, MakeInstructionDescriptor(9, SpvOpReturn, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAccessChain(
+          100, 9, {20}, MakeInstructionDescriptor(9, spv::Op::OpReturn, 0))
+          .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationAccessChainTest, IsomorphicStructs) {
@@ -478,7 +489,7 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   {
     TransformationAccessChain transformation(
-        100, 11, {}, MakeInstructionDescriptor(5, SpvOpReturn, 0));
+        100, 11, {}, MakeInstructionDescriptor(5, spv::Op::OpReturn, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -488,7 +499,7 @@
   }
   {
     TransformationAccessChain transformation(
-        101, 12, {}, MakeInstructionDescriptor(5, SpvOpReturn, 0));
+        101, 12, {}, MakeInstructionDescriptor(5, spv::Op::OpReturn, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -587,51 +598,56 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   // Bad: no ids given for clamping
-  ASSERT_FALSE(TransformationAccessChain(
-                   100, 29, {17}, MakeInstructionDescriptor(36, SpvOpLoad, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAccessChain(
+          100, 29, {17}, MakeInstructionDescriptor(36, spv::Op::OpLoad, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   // Bad: an id given for clamping is not fresh
   ASSERT_FALSE(TransformationAccessChain(
-                   100, 29, {17}, MakeInstructionDescriptor(36, SpvOpLoad, 0),
+                   100, 29, {17},
+                   MakeInstructionDescriptor(36, spv::Op::OpLoad, 0),
                    {{46, 201}})
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: an id given for clamping is not fresh
   ASSERT_FALSE(TransformationAccessChain(
-                   100, 29, {17}, MakeInstructionDescriptor(36, SpvOpLoad, 0),
+                   100, 29, {17},
+                   MakeInstructionDescriptor(36, spv::Op::OpLoad, 0),
                    {{200, 46}})
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: an id given for clamping is the same as the id for the access chain
   ASSERT_FALSE(TransformationAccessChain(
-                   100, 29, {17}, MakeInstructionDescriptor(36, SpvOpLoad, 0),
+                   100, 29, {17},
+                   MakeInstructionDescriptor(36, spv::Op::OpLoad, 0),
                    {{100, 201}})
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: the fresh ids given are not distinct
   ASSERT_FALSE(TransformationAccessChain(
-                   100, 29, {17}, MakeInstructionDescriptor(36, SpvOpLoad, 0),
+                   100, 29, {17},
+                   MakeInstructionDescriptor(36, spv::Op::OpLoad, 0),
                    {{200, 200}})
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: not enough ids given for clamping (2 pairs needed)
-  ASSERT_FALSE(
-      TransformationAccessChain(104, 34, {45, 10, 46},
-                                MakeInstructionDescriptor(46, SpvOpReturn, 0),
-                                {{208, 209}, {209, 211}})
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAccessChain(
+                   104, 34, {45, 10, 46},
+                   MakeInstructionDescriptor(46, spv::Op::OpReturn, 0),
+                   {{208, 209}, {209, 211}})
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: the fresh ids given are not distinct
-  ASSERT_FALSE(
-      TransformationAccessChain(104, 34, {45, 10, 46},
-                                MakeInstructionDescriptor(46, SpvOpReturn, 0),
-                                {{208, 209}, {209, 211}})
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAccessChain(
+                   104, 34, {45, 10, 46},
+                   MakeInstructionDescriptor(46, spv::Op::OpReturn, 0),
+                   {{208, 209}, {209, 211}})
+                   .IsApplicable(context.get(), transformation_context));
 
   {
     TransformationAccessChain transformation(
-        100, 29, {17}, MakeInstructionDescriptor(36, SpvOpLoad, 0),
+        100, 29, {17}, MakeInstructionDescriptor(36, spv::Op::OpLoad, 0),
         {{200, 201}});
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
@@ -643,7 +659,7 @@
 
   {
     TransformationAccessChain transformation(
-        101, 29, {36}, MakeInstructionDescriptor(38, SpvOpLoad, 0),
+        101, 29, {36}, MakeInstructionDescriptor(38, spv::Op::OpLoad, 0),
         {{202, 203}});
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
@@ -655,7 +671,7 @@
 
   {
     TransformationAccessChain transformation(
-        102, 32, {10, 40}, MakeInstructionDescriptor(42, SpvOpLoad, 0),
+        102, 32, {10, 40}, MakeInstructionDescriptor(42, spv::Op::OpLoad, 0),
         {{204, 205}});
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
@@ -667,7 +683,7 @@
 
   {
     TransformationAccessChain transformation(
-        103, 34, {11}, MakeInstructionDescriptor(45, SpvOpLoad, 0),
+        103, 34, {11}, MakeInstructionDescriptor(45, spv::Op::OpLoad, 0),
         {{206, 207}});
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
@@ -679,7 +695,8 @@
 
   {
     TransformationAccessChain transformation(
-        104, 34, {45, 10, 46}, MakeInstructionDescriptor(46, SpvOpReturn, 0),
+        104, 34, {45, 10, 46},
+        MakeInstructionDescriptor(46, spv::Op::OpReturn, 0),
         {{208, 209}, {210, 211}});
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
diff --git a/test/fuzz/transformation_add_constant_boolean_test.cpp b/test/fuzz/transformation_add_constant_boolean_test.cpp
index bd8d91c..bb8817e 100644
--- a/test/fuzz/transformation_add_constant_boolean_test.cpp
+++ b/test/fuzz/transformation_add_constant_boolean_test.cpp
@@ -72,7 +72,8 @@
   ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(7));
   ASSERT_EQ(nullptr, context->get_constant_mgr()->FindDeclaredConstant(7));
   ApplyAndCheckFreshIds(add_true, context.get(), &transformation_context);
-  ASSERT_EQ(SpvOpConstantTrue, context->get_def_use_mgr()->GetDef(7)->opcode());
+  ASSERT_EQ(spv::Op::OpConstantTrue,
+            context->get_def_use_mgr()->GetDef(7)->opcode());
   ASSERT_TRUE(context->get_constant_mgr()
                   ->FindDeclaredConstant(7)
                   ->AsBoolConstant()
diff --git a/test/fuzz/transformation_add_constant_composite_test.cpp b/test/fuzz/transformation_add_constant_composite_test.cpp
index e5cbeec..193aa0a 100644
--- a/test/fuzz/transformation_add_constant_composite_test.cpp
+++ b/test/fuzz/transformation_add_constant_composite_test.cpp
@@ -91,7 +91,7 @@
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
-    ASSERT_EQ(SpvOpConstantComposite,
+    ASSERT_EQ(spv::Op::OpConstantComposite,
               context->get_def_use_mgr()->GetDef(100)->opcode());
     ASSERT_EQ(0.0F, context->get_constant_mgr()
                         ->FindDeclaredConstant(100)
diff --git a/test/fuzz/transformation_add_constant_null_test.cpp b/test/fuzz/transformation_add_constant_null_test.cpp
index 1553e9f..44e92f8 100644
--- a/test/fuzz/transformation_add_constant_null_test.cpp
+++ b/test/fuzz/transformation_add_constant_null_test.cpp
@@ -87,7 +87,7 @@
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
-    ASSERT_EQ(SpvOpConstantNull,
+    ASSERT_EQ(spv::Op::OpConstantNull,
               context->get_def_use_mgr()->GetDef(100)->opcode());
     ASSERT_EQ(
         0.0F,
diff --git a/test/fuzz/transformation_add_constant_scalar_test.cpp b/test/fuzz/transformation_add_constant_scalar_test.cpp
index 00c0541..8c742a4 100644
--- a/test/fuzz/transformation_add_constant_scalar_test.cpp
+++ b/test/fuzz/transformation_add_constant_scalar_test.cpp
@@ -179,7 +179,8 @@
   ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(19));
   ASSERT_EQ(nullptr, context->get_constant_mgr()->FindDeclaredConstant(19));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
-  ASSERT_EQ(SpvOpConstant, context->get_def_use_mgr()->GetDef(19)->opcode());
+  ASSERT_EQ(spv::Op::OpConstant,
+            context->get_def_use_mgr()->GetDef(19)->opcode());
   ASSERT_EQ(4, context->get_constant_mgr()->FindDeclaredConstant(19)->GetU32());
   auto* constant_instruction = context->get_def_use_mgr()->GetDef(19);
   EXPECT_EQ(constant_instruction->NumInOperands(), 1);
diff --git a/test/fuzz/transformation_add_copy_memory_test.cpp b/test/fuzz/transformation_add_copy_memory_test.cpp
index ff8ac72..29a936c 100644
--- a/test/fuzz/transformation_add_copy_memory_test.cpp
+++ b/test/fuzz/transformation_add_copy_memory_test.cpp
@@ -148,89 +148,89 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // Target id is not fresh (59).
   ASSERT_FALSE(TransformationAddCopyMemory(
-                   MakeInstructionDescriptor(27, SpvOpFunctionCall, 0), 59, 19,
-                   SpvStorageClassPrivate, 20)
+                   MakeInstructionDescriptor(27, spv::Op::OpFunctionCall, 0),
+                   59, 19, spv::StorageClass::Private, 20)
                    .IsApplicable(context.get(), transformation_context));
 
   // Instruction descriptor is invalid (id 90 is undefined).
   ASSERT_FALSE(TransformationAddCopyMemory(
-                   MakeInstructionDescriptor(90, SpvOpVariable, 0), 90, 19,
-                   SpvStorageClassPrivate, 20)
+                   MakeInstructionDescriptor(90, spv::Op::OpVariable, 0), 90,
+                   19, spv::StorageClass::Private, 20)
                    .IsApplicable(context.get(), transformation_context));
 
   // Cannot insert OpCopyMemory before OpPhi.
-  ASSERT_FALSE(
-      TransformationAddCopyMemory(MakeInstructionDescriptor(75, SpvOpPhi, 0),
-                                  90, 19, SpvStorageClassPrivate, 20)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAddCopyMemory(
+                   MakeInstructionDescriptor(75, spv::Op::OpPhi, 0), 90, 19,
+                   spv::StorageClass::Private, 20)
+                   .IsApplicable(context.get(), transformation_context));
 
   // Source instruction is invalid.
   ASSERT_FALSE(TransformationAddCopyMemory(
-                   MakeInstructionDescriptor(27, SpvOpFunctionCall, 0), 90, 76,
-                   SpvStorageClassPrivate, 0)
+                   MakeInstructionDescriptor(27, spv::Op::OpFunctionCall, 0),
+                   90, 76, spv::StorageClass::Private, 0)
                    .IsApplicable(context.get(), transformation_context));
 
   // Source instruction's type doesn't exist.
   ASSERT_FALSE(TransformationAddCopyMemory(
-                   MakeInstructionDescriptor(27, SpvOpFunctionCall, 0), 90, 5,
-                   SpvStorageClassPrivate, 0)
+                   MakeInstructionDescriptor(27, spv::Op::OpFunctionCall, 0),
+                   90, 5, spv::StorageClass::Private, 0)
                    .IsApplicable(context.get(), transformation_context));
 
   // Source instruction's type is invalid.
-  ASSERT_FALSE(
-      TransformationAddCopyMemory(MakeInstructionDescriptor(41, SpvOpLoad, 0),
-                                  90, 40, SpvStorageClassPrivate, 0)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAddCopyMemory(
+                   MakeInstructionDescriptor(41, spv::Op::OpLoad, 0), 90, 40,
+                   spv::StorageClass::Private, 0)
+                   .IsApplicable(context.get(), transformation_context));
 
   // Source instruction is OpConstantNull.
-  ASSERT_FALSE(
-      TransformationAddCopyMemory(MakeInstructionDescriptor(41, SpvOpLoad, 0),
-                                  90, 88, SpvStorageClassPrivate, 0)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAddCopyMemory(
+                   MakeInstructionDescriptor(41, spv::Op::OpLoad, 0), 90, 88,
+                   spv::StorageClass::Private, 0)
+                   .IsApplicable(context.get(), transformation_context));
 
   // Storage class is invalid.
   ASSERT_FALSE(TransformationAddCopyMemory(
-                   MakeInstructionDescriptor(27, SpvOpFunctionCall, 0), 90, 19,
-                   SpvStorageClassWorkgroup, 20)
+                   MakeInstructionDescriptor(27, spv::Op::OpFunctionCall, 0),
+                   90, 19, spv::StorageClass::Workgroup, 20)
                    .IsApplicable(context.get(), transformation_context));
 
   // Initializer is 0.
   ASSERT_FALSE(TransformationAddCopyMemory(
-                   MakeInstructionDescriptor(27, SpvOpFunctionCall, 0), 90, 19,
-                   SpvStorageClassPrivate, 0)
+                   MakeInstructionDescriptor(27, spv::Op::OpFunctionCall, 0),
+                   90, 19, spv::StorageClass::Private, 0)
                    .IsApplicable(context.get(), transformation_context));
 
   // Initializer has wrong type.
   ASSERT_FALSE(TransformationAddCopyMemory(
-                   MakeInstructionDescriptor(27, SpvOpFunctionCall, 0), 90, 19,
-                   SpvStorageClassPrivate, 25)
+                   MakeInstructionDescriptor(27, spv::Op::OpFunctionCall, 0),
+                   90, 19, spv::StorageClass::Private, 25)
                    .IsApplicable(context.get(), transformation_context));
 
   // Source and target instructions are in different functions.
-  ASSERT_FALSE(
-      TransformationAddCopyMemory(MakeInstructionDescriptor(13, SpvOpLoad, 0),
-                                  90, 19, SpvStorageClassPrivate, 20)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAddCopyMemory(
+                   MakeInstructionDescriptor(13, spv::Op::OpLoad, 0), 90, 19,
+                   spv::StorageClass::Private, 20)
+                   .IsApplicable(context.get(), transformation_context));
 
   // Source instruction doesn't dominate the target instruction.
   ASSERT_FALSE(TransformationAddCopyMemory(
-                   MakeInstructionDescriptor(77, SpvOpLogicalEqual, 0), 90, 89,
-                   SpvStorageClassPrivate, 20)
+                   MakeInstructionDescriptor(77, spv::Op::OpLogicalEqual, 0),
+                   90, 89, spv::StorageClass::Private, 20)
                    .IsApplicable(context.get(), transformation_context));
 
   // Source and target instructions are the same.
   ASSERT_FALSE(TransformationAddCopyMemory(
-                   MakeInstructionDescriptor(19, SpvOpVariable, 0), 90, 19,
-                   SpvStorageClassPrivate, 20)
+                   MakeInstructionDescriptor(19, spv::Op::OpVariable, 0), 90,
+                   19, spv::StorageClass::Private, 20)
                    .IsApplicable(context.get(), transformation_context));
 
   // Correct transformations.
   uint32_t fresh_id = 90;
-  auto descriptor = MakeInstructionDescriptor(27, SpvOpFunctionCall, 0);
+  auto descriptor = MakeInstructionDescriptor(27, spv::Op::OpFunctionCall, 0);
   std::vector<uint32_t> source_ids = {19, 23, 26, 30, 35, 39, 68, 86};
   std::vector<uint32_t> initializers = {20, 24, 25, 25, 36, 84, 85, 20};
-  std::vector<SpvStorageClass> storage_classes = {SpvStorageClassPrivate,
-                                                  SpvStorageClassFunction};
+  std::vector<spv::StorageClass> storage_classes = {
+      spv::StorageClass::Private, spv::StorageClass::Function};
   for (size_t i = 0, n = source_ids.size(); i < n; ++i) {
     TransformationAddCopyMemory transformation(
         descriptor, fresh_id, source_ids[i],
@@ -420,10 +420,10 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  ASSERT_FALSE(
-      TransformationAddCopyMemory(MakeInstructionDescriptor(5, SpvOpReturn, 0),
-                                  100, 9, SpvStorageClassPrivate, 50)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAddCopyMemory(
+                   MakeInstructionDescriptor(5, spv::Op::OpReturn, 0), 100, 9,
+                   spv::StorageClass::Private, 50)
+                   .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationAddCopyMemoryTest, DisallowBlockDecoration) {
@@ -466,12 +466,12 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  ASSERT_FALSE(
-      TransformationAddCopyMemory(MakeInstructionDescriptor(5, SpvOpReturn, 0),
-                                  100, 9, SpvStorageClassPrivate, 50)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAddCopyMemory(
+                   MakeInstructionDescriptor(5, spv::Op::OpReturn, 0), 100, 9,
+                   spv::StorageClass::Private, 50)
+                   .IsApplicable(context.get(), transformation_context));
 }
 
 }  // namespace
 }  // namespace fuzz
-}  // namespace spvtools
\ No newline at end of file
+}  // namespace spvtools
diff --git a/test/fuzz/transformation_add_early_terminator_wrapper_test.cpp b/test/fuzz/transformation_add_early_terminator_wrapper_test.cpp
index 8239e21..8cb04a9 100644
--- a/test/fuzz/transformation_add_early_terminator_wrapper_test.cpp
+++ b/test/fuzz/transformation_add_early_terminator_wrapper_test.cpp
@@ -40,8 +40,9 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
 
-  ASSERT_FALSE(TransformationAddEarlyTerminatorWrapper(100, 101, SpvOpKill)
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAddEarlyTerminatorWrapper(100, 101, spv::Op::OpKill)
+          .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationAddEarlyTerminatorWrapperTest, NoVoidFunctionType) {
@@ -63,8 +64,9 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
 
-  ASSERT_FALSE(TransformationAddEarlyTerminatorWrapper(100, 101, SpvOpKill)
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAddEarlyTerminatorWrapper(100, 101, spv::Op::OpKill)
+          .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationAddEarlyTerminatorWrapperTest, BasicTest) {
@@ -93,25 +95,27 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
 
-  ASSERT_FALSE(TransformationAddEarlyTerminatorWrapper(2, 101, SpvOpKill)
+  ASSERT_FALSE(TransformationAddEarlyTerminatorWrapper(2, 101, spv::Op::OpKill)
                    .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(TransformationAddEarlyTerminatorWrapper(100, 4, SpvOpKill)
+  ASSERT_FALSE(TransformationAddEarlyTerminatorWrapper(100, 4, spv::Op::OpKill)
                    .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(TransformationAddEarlyTerminatorWrapper(100, 100, SpvOpKill)
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAddEarlyTerminatorWrapper(100, 100, spv::Op::OpKill)
+          .IsApplicable(context.get(), transformation_context));
 
 #ifndef NDEBUG
-  ASSERT_DEATH(TransformationAddEarlyTerminatorWrapper(100, 101, SpvOpReturn)
-                   .IsApplicable(context.get(), transformation_context),
-               "Invalid opcode.");
+  ASSERT_DEATH(
+      TransformationAddEarlyTerminatorWrapper(100, 101, spv::Op::OpReturn)
+          .IsApplicable(context.get(), transformation_context),
+      "Invalid opcode.");
 #endif
 
   auto transformation1 =
-      TransformationAddEarlyTerminatorWrapper(100, 101, SpvOpKill);
+      TransformationAddEarlyTerminatorWrapper(100, 101, spv::Op::OpKill);
   auto transformation2 =
-      TransformationAddEarlyTerminatorWrapper(102, 103, SpvOpUnreachable);
+      TransformationAddEarlyTerminatorWrapper(102, 103, spv::Op::OpUnreachable);
   auto transformation3 = TransformationAddEarlyTerminatorWrapper(
-      104, 105, SpvOpTerminateInvocation);
+      104, 105, spv::Op::OpTerminateInvocation);
 
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
diff --git a/test/fuzz/transformation_add_function_test.cpp b/test/fuzz/transformation_add_function_test.cpp
index d55fb93..65ae2f2 100644
--- a/test/fuzz/transformation_add_function_test.cpp
+++ b/test/fuzz/transformation_add_function_test.cpp
@@ -84,7 +84,7 @@
                            &found_non_irrelevant_parameter](
                               opt::Instruction* inst) {
       if (context->get_def_use_mgr()->GetDef(inst->type_id())->opcode() ==
-              SpvOpTypePointer &&
+              spv::Op::OpTypePointer &&
           !transformation_context.GetFactManager()->PointeeValueIsIrrelevant(
               inst->result_id())) {
         found_non_irrelevant_parameter = true;
@@ -96,7 +96,7 @@
     }
     // Look through the instructions in the function's first block.
     for (auto& inst : *function.begin()) {
-      if (inst.opcode() != SpvOpVariable) {
+      if (inst.opcode() != spv::Op::OpVariable) {
         // We have found a non-variable instruction; this means we have gotten
         // past all variables, so we are done.
         return true;
@@ -154,73 +154,84 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   TransformationAddFunction transformation1(std::vector<protobufs::Instruction>(
-      {MakeInstructionMessage(
-           SpvOpFunction, 8, 13,
-           {{SPV_OPERAND_TYPE_FUNCTION_CONTROL, {SpvFunctionControlMaskNone}},
-            {SPV_OPERAND_TYPE_ID, {10}}}),
-       MakeInstructionMessage(SpvOpFunctionParameter, 7, 11, {}),
-       MakeInstructionMessage(SpvOpFunctionParameter, 9, 12, {}),
-       MakeInstructionMessage(SpvOpLabel, 0, 14, {}),
+      {MakeInstructionMessage(spv::Op::OpFunction, 8, 13,
+                              {{SPV_OPERAND_TYPE_FUNCTION_CONTROL,
+                                {uint32_t(spv::FunctionControlMask::MaskNone)}},
+                               {SPV_OPERAND_TYPE_ID, {10}}}),
+       MakeInstructionMessage(spv::Op::OpFunctionParameter, 7, 11, {}),
+       MakeInstructionMessage(spv::Op::OpFunctionParameter, 9, 12, {}),
+       MakeInstructionMessage(spv::Op::OpLabel, 0, 14, {}),
+       MakeInstructionMessage(spv::Op::OpVariable, 9, 17,
+                              {{SPV_OPERAND_TYPE_STORAGE_CLASS,
+                                {uint32_t(spv::StorageClass::Function)}}}),
+       MakeInstructionMessage(spv::Op::OpVariable, 7, 19,
+                              {{SPV_OPERAND_TYPE_STORAGE_CLASS,
+                                {uint32_t(spv::StorageClass::Function)}}}),
        MakeInstructionMessage(
-           SpvOpVariable, 9, 17,
-           {{SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}}}),
-       MakeInstructionMessage(
-           SpvOpVariable, 7, 19,
-           {{SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}}}),
-       MakeInstructionMessage(
-           SpvOpStore, 0, 0,
+           spv::Op::OpStore, 0, 0,
            {{SPV_OPERAND_TYPE_ID, {17}}, {SPV_OPERAND_TYPE_ID, {18}}}),
        MakeInstructionMessage(
-           SpvOpStore, 0, 0,
+           spv::Op::OpStore, 0, 0,
            {{SPV_OPERAND_TYPE_ID, {19}}, {SPV_OPERAND_TYPE_ID, {20}}}),
-       MakeInstructionMessage(SpvOpBranch, 0, 0, {{SPV_OPERAND_TYPE_ID, {21}}}),
-       MakeInstructionMessage(SpvOpLabel, 0, 21, {}),
+       MakeInstructionMessage(spv::Op::OpBranch, 0, 0,
+                              {{SPV_OPERAND_TYPE_ID, {21}}}),
+       MakeInstructionMessage(spv::Op::OpLabel, 0, 21, {}),
+       MakeInstructionMessage(spv::Op::OpLoopMerge, 0, 0,
+                              {{SPV_OPERAND_TYPE_ID, {23}},
+                               {SPV_OPERAND_TYPE_ID, {24}},
+                               {SPV_OPERAND_TYPE_LOOP_CONTROL,
+                                {uint32_t(spv::LoopControlMask::MaskNone)}}}),
+       MakeInstructionMessage(spv::Op::OpBranch, 0, 0,
+                              {{SPV_OPERAND_TYPE_ID, {25}}}),
+       MakeInstructionMessage(spv::Op::OpLabel, 0, 25, {}),
+       MakeInstructionMessage(spv::Op::OpLoad, 6, 26,
+                              {{SPV_OPERAND_TYPE_ID, {19}}}),
+       MakeInstructionMessage(spv::Op::OpLoad, 6, 27,
+                              {{SPV_OPERAND_TYPE_ID, {11}}}),
        MakeInstructionMessage(
-           SpvOpLoopMerge, 0, 0,
-           {{SPV_OPERAND_TYPE_ID, {23}},
-            {SPV_OPERAND_TYPE_ID, {24}},
-            {SPV_OPERAND_TYPE_LOOP_CONTROL, {SpvLoopControlMaskNone}}}),
-       MakeInstructionMessage(SpvOpBranch, 0, 0, {{SPV_OPERAND_TYPE_ID, {25}}}),
-       MakeInstructionMessage(SpvOpLabel, 0, 25, {}),
-       MakeInstructionMessage(SpvOpLoad, 6, 26, {{SPV_OPERAND_TYPE_ID, {19}}}),
-       MakeInstructionMessage(SpvOpLoad, 6, 27, {{SPV_OPERAND_TYPE_ID, {11}}}),
-       MakeInstructionMessage(
-           SpvOpSLessThan, 28, 29,
+           spv::Op::OpSLessThan, 28, 29,
            {{SPV_OPERAND_TYPE_ID, {26}}, {SPV_OPERAND_TYPE_ID, {27}}}),
-       MakeInstructionMessage(SpvOpBranchConditional, 0, 0,
+       MakeInstructionMessage(spv::Op::OpBranchConditional, 0, 0,
                               {{SPV_OPERAND_TYPE_ID, {29}},
                                {SPV_OPERAND_TYPE_ID, {22}},
                                {SPV_OPERAND_TYPE_ID, {23}}}),
-       MakeInstructionMessage(SpvOpLabel, 0, 22, {}),
-       MakeInstructionMessage(SpvOpLoad, 8, 30, {{SPV_OPERAND_TYPE_ID, {12}}}),
-       MakeInstructionMessage(SpvOpLoad, 6, 31, {{SPV_OPERAND_TYPE_ID, {19}}}),
-       MakeInstructionMessage(SpvOpConvertSToF, 8, 32,
+       MakeInstructionMessage(spv::Op::OpLabel, 0, 22, {}),
+       MakeInstructionMessage(spv::Op::OpLoad, 8, 30,
+                              {{SPV_OPERAND_TYPE_ID, {12}}}),
+       MakeInstructionMessage(spv::Op::OpLoad, 6, 31,
+                              {{SPV_OPERAND_TYPE_ID, {19}}}),
+       MakeInstructionMessage(spv::Op::OpConvertSToF, 8, 32,
                               {{SPV_OPERAND_TYPE_ID, {31}}}),
        MakeInstructionMessage(
-           SpvOpFMul, 8, 33,
+           spv::Op::OpFMul, 8, 33,
            {{SPV_OPERAND_TYPE_ID, {30}}, {SPV_OPERAND_TYPE_ID, {32}}}),
-       MakeInstructionMessage(SpvOpLoad, 8, 34, {{SPV_OPERAND_TYPE_ID, {17}}}),
+       MakeInstructionMessage(spv::Op::OpLoad, 8, 34,
+                              {{SPV_OPERAND_TYPE_ID, {17}}}),
        MakeInstructionMessage(
-           SpvOpFAdd, 8, 35,
+           spv::Op::OpFAdd, 8, 35,
            {{SPV_OPERAND_TYPE_ID, {34}}, {SPV_OPERAND_TYPE_ID, {33}}}),
        MakeInstructionMessage(
-           SpvOpStore, 0, 0,
+           spv::Op::OpStore, 0, 0,
            {{SPV_OPERAND_TYPE_ID, {17}}, {SPV_OPERAND_TYPE_ID, {35}}}),
-       MakeInstructionMessage(SpvOpBranch, 0, 0, {{SPV_OPERAND_TYPE_ID, {24}}}),
-       MakeInstructionMessage(SpvOpLabel, 0, 24, {}),
-       MakeInstructionMessage(SpvOpLoad, 6, 36, {{SPV_OPERAND_TYPE_ID, {19}}}),
+       MakeInstructionMessage(spv::Op::OpBranch, 0, 0,
+                              {{SPV_OPERAND_TYPE_ID, {24}}}),
+       MakeInstructionMessage(spv::Op::OpLabel, 0, 24, {}),
+       MakeInstructionMessage(spv::Op::OpLoad, 6, 36,
+                              {{SPV_OPERAND_TYPE_ID, {19}}}),
        MakeInstructionMessage(
-           SpvOpIAdd, 6, 38,
+           spv::Op::OpIAdd, 6, 38,
            {{SPV_OPERAND_TYPE_ID, {36}}, {SPV_OPERAND_TYPE_ID, {37}}}),
        MakeInstructionMessage(
-           SpvOpStore, 0, 0,
+           spv::Op::OpStore, 0, 0,
            {{SPV_OPERAND_TYPE_ID, {19}}, {SPV_OPERAND_TYPE_ID, {38}}}),
-       MakeInstructionMessage(SpvOpBranch, 0, 0, {{SPV_OPERAND_TYPE_ID, {21}}}),
-       MakeInstructionMessage(SpvOpLabel, 0, 23, {}),
-       MakeInstructionMessage(SpvOpLoad, 8, 39, {{SPV_OPERAND_TYPE_ID, {17}}}),
-       MakeInstructionMessage(SpvOpReturnValue, 0, 0,
+       MakeInstructionMessage(spv::Op::OpBranch, 0, 0,
+                              {{SPV_OPERAND_TYPE_ID, {21}}}),
+       MakeInstructionMessage(spv::Op::OpLabel, 0, 23, {}),
+       MakeInstructionMessage(spv::Op::OpLoad, 8, 39,
+                              {{SPV_OPERAND_TYPE_ID, {17}}}),
+       MakeInstructionMessage(spv::Op::OpReturnValue, 0, 0,
                               {{SPV_OPERAND_TYPE_ID, {39}}}),
-       MakeInstructionMessage(SpvOpFunctionEnd, 0, 0, {})}));
+       MakeInstructionMessage(spv::Op::OpFunctionEnd, 0, 0, {})}));
 
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
@@ -299,51 +310,51 @@
   ASSERT_TRUE(transformation_context.GetFactManager()->BlockIsDead(25));
 
   TransformationAddFunction transformation2(std::vector<protobufs::Instruction>(
-      {MakeInstructionMessage(
-           SpvOpFunction, 2, 15,
-           {{SPV_OPERAND_TYPE_FUNCTION_CONTROL, {SpvFunctionControlMaskNone}},
-            {SPV_OPERAND_TYPE_ID, {3}}}),
-       MakeInstructionMessage(SpvOpLabel, 0, 16, {}),
+      {MakeInstructionMessage(spv::Op::OpFunction, 2, 15,
+                              {{SPV_OPERAND_TYPE_FUNCTION_CONTROL,
+                                {uint32_t(spv::FunctionControlMask::MaskNone)}},
+                               {SPV_OPERAND_TYPE_ID, {3}}}),
+       MakeInstructionMessage(spv::Op::OpLabel, 0, 16, {}),
+       MakeInstructionMessage(spv::Op::OpVariable, 7, 44,
+                              {{SPV_OPERAND_TYPE_STORAGE_CLASS,
+                                {uint32_t(spv::StorageClass::Function)}}}),
+       MakeInstructionMessage(spv::Op::OpVariable, 9, 45,
+                              {{SPV_OPERAND_TYPE_STORAGE_CLASS,
+                                {uint32_t(spv::StorageClass::Function)}}}),
+       MakeInstructionMessage(spv::Op::OpVariable, 7, 48,
+                              {{SPV_OPERAND_TYPE_STORAGE_CLASS,
+                                {uint32_t(spv::StorageClass::Function)}}}),
+       MakeInstructionMessage(spv::Op::OpVariable, 9, 49,
+                              {{SPV_OPERAND_TYPE_STORAGE_CLASS,
+                                {uint32_t(spv::StorageClass::Function)}}}),
        MakeInstructionMessage(
-           SpvOpVariable, 7, 44,
-           {{SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}}}),
-       MakeInstructionMessage(
-           SpvOpVariable, 9, 45,
-           {{SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}}}),
-       MakeInstructionMessage(
-           SpvOpVariable, 7, 48,
-           {{SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}}}),
-       MakeInstructionMessage(
-           SpvOpVariable, 9, 49,
-           {{SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}}}),
-       MakeInstructionMessage(
-           SpvOpStore, 0, 0,
+           spv::Op::OpStore, 0, 0,
            {{SPV_OPERAND_TYPE_ID, {44}}, {SPV_OPERAND_TYPE_ID, {20}}}),
        MakeInstructionMessage(
-           SpvOpStore, 0, 0,
+           spv::Op::OpStore, 0, 0,
            {{SPV_OPERAND_TYPE_ID, {45}}, {SPV_OPERAND_TYPE_ID, {18}}}),
-       MakeInstructionMessage(SpvOpFunctionCall, 8, 46,
+       MakeInstructionMessage(spv::Op::OpFunctionCall, 8, 46,
                               {{SPV_OPERAND_TYPE_ID, {13}},
                                {SPV_OPERAND_TYPE_ID, {44}},
                                {SPV_OPERAND_TYPE_ID, {45}}}),
        MakeInstructionMessage(
-           SpvOpStore, 0, 0,
+           spv::Op::OpStore, 0, 0,
            {{SPV_OPERAND_TYPE_ID, {48}}, {SPV_OPERAND_TYPE_ID, {37}}}),
        MakeInstructionMessage(
-           SpvOpStore, 0, 0,
+           spv::Op::OpStore, 0, 0,
            {{SPV_OPERAND_TYPE_ID, {49}}, {SPV_OPERAND_TYPE_ID, {47}}}),
-       MakeInstructionMessage(SpvOpFunctionCall, 8, 50,
+       MakeInstructionMessage(spv::Op::OpFunctionCall, 8, 50,
                               {{SPV_OPERAND_TYPE_ID, {13}},
                                {SPV_OPERAND_TYPE_ID, {48}},
                                {SPV_OPERAND_TYPE_ID, {49}}}),
        MakeInstructionMessage(
-           SpvOpFAdd, 8, 51,
+           spv::Op::OpFAdd, 8, 51,
            {{SPV_OPERAND_TYPE_ID, {46}}, {SPV_OPERAND_TYPE_ID, {50}}}),
        MakeInstructionMessage(
-           SpvOpStore, 0, 0,
+           spv::Op::OpStore, 0, 0,
            {{SPV_OPERAND_TYPE_ID, {43}}, {SPV_OPERAND_TYPE_ID, {51}}}),
-       MakeInstructionMessage(SpvOpReturn, 0, 0, {}),
-       MakeInstructionMessage(SpvOpFunctionEnd, 0, 0, {})}));
+       MakeInstructionMessage(spv::Op::OpReturn, 0, 0, {}),
+       MakeInstructionMessage(spv::Op::OpFunctionEnd, 0, 0, {})}));
 
   ASSERT_TRUE(
       transformation2.IsApplicable(context.get(), transformation_context));
@@ -513,45 +524,46 @@
   ASSERT_FALSE(
       TransformationAddFunction(
           std::vector<protobufs::Instruction>(
-              {MakeInstructionMessage(SpvOpFunctionParameter, 7, 11, {}),
-               MakeInstructionMessage(SpvOpFunctionParameter, 9, 12, {}),
-               MakeInstructionMessage(SpvOpLabel, 0, 14, {})}))
+              {MakeInstructionMessage(spv::Op::OpFunctionParameter, 7, 11, {}),
+               MakeInstructionMessage(spv::Op::OpFunctionParameter, 9, 12, {}),
+               MakeInstructionMessage(spv::Op::OpLabel, 0, 14, {})}))
           .IsApplicable(context.get(), transformation_context));
 
   // No OpLabel
   ASSERT_FALSE(
       TransformationAddFunction(
           std::vector<protobufs::Instruction>(
-              {MakeInstructionMessage(SpvOpFunction, 8, 13,
-                                      {{SPV_OPERAND_TYPE_FUNCTION_CONTROL,
-                                        {SpvFunctionControlMaskNone}},
-                                       {SPV_OPERAND_TYPE_ID, {10}}}),
-               MakeInstructionMessage(SpvOpReturnValue, 0, 0,
+              {MakeInstructionMessage(
+                   spv::Op::OpFunction, 8, 13,
+                   {{SPV_OPERAND_TYPE_FUNCTION_CONTROL,
+                     {uint32_t(spv::FunctionControlMask::MaskNone)}},
+                    {SPV_OPERAND_TYPE_ID, {10}}}),
+               MakeInstructionMessage(spv::Op::OpReturnValue, 0, 0,
                                       {{SPV_OPERAND_TYPE_ID, {39}}}),
-               MakeInstructionMessage(SpvOpFunctionEnd, 0, 0, {})}))
+               MakeInstructionMessage(spv::Op::OpFunctionEnd, 0, 0, {})}))
           .IsApplicable(context.get(), transformation_context));
 
   // Abrupt end of instructions
   ASSERT_FALSE(TransformationAddFunction(
                    std::vector<protobufs::Instruction>({MakeInstructionMessage(
-                       SpvOpFunction, 8, 13,
+                       spv::Op::OpFunction, 8, 13,
                        {{SPV_OPERAND_TYPE_FUNCTION_CONTROL,
-                         {SpvFunctionControlMaskNone}},
+                         {uint32_t(spv::FunctionControlMask::MaskNone)}},
                         {SPV_OPERAND_TYPE_ID, {10}}})}))
                    .IsApplicable(context.get(), transformation_context));
 
   // No function end
-  ASSERT_FALSE(
-      TransformationAddFunction(
-          std::vector<protobufs::Instruction>(
-              {MakeInstructionMessage(SpvOpFunction, 8, 13,
-                                      {{SPV_OPERAND_TYPE_FUNCTION_CONTROL,
-                                        {SpvFunctionControlMaskNone}},
-                                       {SPV_OPERAND_TYPE_ID, {10}}}),
-               MakeInstructionMessage(SpvOpLabel, 0, 14, {}),
-               MakeInstructionMessage(SpvOpReturnValue, 0, 0,
-                                      {{SPV_OPERAND_TYPE_ID, {39}}})}))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAddFunction(
+                   std::vector<protobufs::Instruction>(
+                       {MakeInstructionMessage(
+                            spv::Op::OpFunction, 8, 13,
+                            {{SPV_OPERAND_TYPE_FUNCTION_CONTROL,
+                              {uint32_t(spv::FunctionControlMask::MaskNone)}},
+                             {SPV_OPERAND_TYPE_ID, {10}}}),
+                        MakeInstructionMessage(spv::Op::OpLabel, 0, 14, {}),
+                        MakeInstructionMessage(spv::Op::OpReturnValue, 0, 0,
+                                               {{SPV_OPERAND_TYPE_ID, {39}}})}))
+                   .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationAddFunctionTest, LoopLimiters) {
@@ -581,61 +593,69 @@
   const auto consumer = nullptr;
 
   std::vector<protobufs::Instruction> instructions;
-  instructions.push_back(MakeInstructionMessage(
-      SpvOpFunction, 2, 30,
-      {{SPV_OPERAND_TYPE_FUNCTION_CONTROL, {SpvFunctionControlMaskNone}},
-       {SPV_OPERAND_TYPE_TYPE_ID, {3}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 31, {}));
   instructions.push_back(
-      MakeInstructionMessage(SpvOpBranch, 0, 0, {{SPV_OPERAND_TYPE_ID, {20}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 20, {}));
-  instructions.push_back(MakeInstructionMessage(
-      SpvOpLoopMerge, 0, 0,
-      {{SPV_OPERAND_TYPE_ID, {21}},
-       {SPV_OPERAND_TYPE_ID, {22}},
-       {SPV_OPERAND_TYPE_LOOP_CONTROL, {SpvLoopControlMaskNone}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpBranchConditional, 0, 0,
+      MakeInstructionMessage(spv::Op::OpFunction, 2, 30,
+                             {{SPV_OPERAND_TYPE_FUNCTION_CONTROL,
+                               {uint32_t(spv::FunctionControlMask::MaskNone)}},
+                              {SPV_OPERAND_TYPE_TYPE_ID, {3}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 31, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpBranch, 0, 0,
+                                                {{SPV_OPERAND_TYPE_ID, {20}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 20, {}));
+  instructions.push_back(
+      MakeInstructionMessage(spv::Op::OpLoopMerge, 0, 0,
+                             {{SPV_OPERAND_TYPE_ID, {21}},
+                              {SPV_OPERAND_TYPE_ID, {22}},
+                              {SPV_OPERAND_TYPE_LOOP_CONTROL,
+                               {uint32_t(spv::LoopControlMask::MaskNone)}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpBranchConditional, 0,
+                                                0,
                                                 {{SPV_OPERAND_TYPE_ID, {12}},
                                                  {SPV_OPERAND_TYPE_ID, {23}},
                                                  {SPV_OPERAND_TYPE_ID, {21}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 23, {}));
-  instructions.push_back(MakeInstructionMessage(
-      SpvOpLoopMerge, 0, 0,
-      {{SPV_OPERAND_TYPE_ID, {25}},
-       {SPV_OPERAND_TYPE_ID, {26}},
-       {SPV_OPERAND_TYPE_LOOP_CONTROL, {SpvLoopControlMaskNone}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 23, {}));
   instructions.push_back(
-      MakeInstructionMessage(SpvOpBranch, 0, 0, {{SPV_OPERAND_TYPE_ID, {28}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 28, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpBranchConditional, 0, 0,
+      MakeInstructionMessage(spv::Op::OpLoopMerge, 0, 0,
+                             {{SPV_OPERAND_TYPE_ID, {25}},
+                              {SPV_OPERAND_TYPE_ID, {26}},
+                              {SPV_OPERAND_TYPE_LOOP_CONTROL,
+                               {uint32_t(spv::LoopControlMask::MaskNone)}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpBranch, 0, 0,
+                                                {{SPV_OPERAND_TYPE_ID, {28}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 28, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpBranchConditional, 0,
+                                                0,
                                                 {{SPV_OPERAND_TYPE_ID, {12}},
                                                  {SPV_OPERAND_TYPE_ID, {26}},
                                                  {SPV_OPERAND_TYPE_ID, {25}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 26, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 26, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpBranch, 0, 0,
+                                                {{SPV_OPERAND_TYPE_ID, {23}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 25, {}));
   instructions.push_back(
-      MakeInstructionMessage(SpvOpBranch, 0, 0, {{SPV_OPERAND_TYPE_ID, {23}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 25, {}));
-  instructions.push_back(MakeInstructionMessage(
-      SpvOpLoopMerge, 0, 0,
-      {{SPV_OPERAND_TYPE_ID, {24}},
-       {SPV_OPERAND_TYPE_ID, {27}},
-       {SPV_OPERAND_TYPE_LOOP_CONTROL, {SpvLoopControlMaskNone}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpBranchConditional, 0, 0,
+      MakeInstructionMessage(spv::Op::OpLoopMerge, 0, 0,
+                             {{SPV_OPERAND_TYPE_ID, {24}},
+                              {SPV_OPERAND_TYPE_ID, {27}},
+                              {SPV_OPERAND_TYPE_LOOP_CONTROL,
+                               {uint32_t(spv::LoopControlMask::MaskNone)}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpBranchConditional, 0,
+                                                0,
                                                 {{SPV_OPERAND_TYPE_ID, {12}},
                                                  {SPV_OPERAND_TYPE_ID, {24}},
                                                  {SPV_OPERAND_TYPE_ID, {27}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 27, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 27, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpBranch, 0, 0,
+                                                {{SPV_OPERAND_TYPE_ID, {25}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 24, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpBranch, 0, 0,
+                                                {{SPV_OPERAND_TYPE_ID, {22}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 22, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpBranch, 0, 0,
+                                                {{SPV_OPERAND_TYPE_ID, {20}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 21, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpReturn, 0, 0, {}));
   instructions.push_back(
-      MakeInstructionMessage(SpvOpBranch, 0, 0, {{SPV_OPERAND_TYPE_ID, {25}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 24, {}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpBranch, 0, 0, {{SPV_OPERAND_TYPE_ID, {22}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 22, {}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpBranch, 0, 0, {{SPV_OPERAND_TYPE_ID, {20}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 21, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpReturn, 0, 0, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpFunctionEnd, 0, 0, {}));
+      MakeInstructionMessage(spv::Op::OpFunctionEnd, 0, 0, {}));
 
   spvtools::ValidatorOptions validator_options;
 
@@ -837,31 +857,36 @@
 
   std::vector<protobufs::Instruction> instructions;
 
-  instructions.push_back(MakeInstructionMessage(
-      SpvOpFunction, 2, 10,
-      {{SPV_OPERAND_TYPE_FUNCTION_CONTROL, {SpvFunctionControlMaskNone}},
-       {SPV_OPERAND_TYPE_TYPE_ID, {8}}}));
   instructions.push_back(
-      MakeInstructionMessage(SpvOpFunctionParameter, 7, 9, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 11, {}));
+      MakeInstructionMessage(spv::Op::OpFunction, 2, 10,
+                             {{SPV_OPERAND_TYPE_FUNCTION_CONTROL,
+                               {uint32_t(spv::FunctionControlMask::MaskNone)}},
+                              {SPV_OPERAND_TYPE_TYPE_ID, {8}}}));
   instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 6, 12, {{SPV_OPERAND_TYPE_ID, {9}}}));
+      MakeInstructionMessage(spv::Op::OpFunctionParameter, 7, 9, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 11, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 6, 12,
+                                                {{SPV_OPERAND_TYPE_ID, {9}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpIEqual, 14, 15,
+      spv::Op::OpIEqual, 14, 15,
       {{SPV_OPERAND_TYPE_ID, {12}}, {SPV_OPERAND_TYPE_ID, {13}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpSelectionMerge, 0, 0,
+      spv::Op::OpSelectionMerge, 0, 0,
       {{SPV_OPERAND_TYPE_ID, {17}},
-       {SPV_OPERAND_TYPE_SELECTION_CONTROL, {SpvSelectionControlMaskNone}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpBranchConditional, 0, 0,
+       {SPV_OPERAND_TYPE_SELECTION_CONTROL,
+        {uint32_t(spv::SelectionControlMask::MaskNone)}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpBranchConditional, 0,
+                                                0,
                                                 {{SPV_OPERAND_TYPE_ID, {15}},
                                                  {SPV_OPERAND_TYPE_ID, {16}},
                                                  {SPV_OPERAND_TYPE_ID, {17}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 16, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpUnreachable, 0, 0, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 17, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpKill, 0, 0, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpFunctionEnd, 0, 0, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 16, {}));
+  instructions.push_back(
+      MakeInstructionMessage(spv::Op::OpUnreachable, 0, 0, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 17, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpKill, 0, 0, {}));
+  instructions.push_back(
+      MakeInstructionMessage(spv::Op::OpFunctionEnd, 0, 0, {}));
 
   spvtools::ValidatorOptions validator_options;
 
@@ -996,31 +1021,36 @@
 
   std::vector<protobufs::Instruction> instructions;
 
-  instructions.push_back(MakeInstructionMessage(
-      SpvOpFunction, 6, 10,
-      {{SPV_OPERAND_TYPE_FUNCTION_CONTROL, {SpvFunctionControlMaskNone}},
-       {SPV_OPERAND_TYPE_TYPE_ID, {50}}}));
   instructions.push_back(
-      MakeInstructionMessage(SpvOpFunctionParameter, 7, 9, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 11, {}));
+      MakeInstructionMessage(spv::Op::OpFunction, 6, 10,
+                             {{SPV_OPERAND_TYPE_FUNCTION_CONTROL,
+                               {uint32_t(spv::FunctionControlMask::MaskNone)}},
+                              {SPV_OPERAND_TYPE_TYPE_ID, {50}}}));
   instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 6, 12, {{SPV_OPERAND_TYPE_ID, {9}}}));
+      MakeInstructionMessage(spv::Op::OpFunctionParameter, 7, 9, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 11, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 6, 12,
+                                                {{SPV_OPERAND_TYPE_ID, {9}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpIEqual, 14, 15,
+      spv::Op::OpIEqual, 14, 15,
       {{SPV_OPERAND_TYPE_ID, {12}}, {SPV_OPERAND_TYPE_ID, {13}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpSelectionMerge, 0, 0,
+      spv::Op::OpSelectionMerge, 0, 0,
       {{SPV_OPERAND_TYPE_ID, {17}},
-       {SPV_OPERAND_TYPE_SELECTION_CONTROL, {SpvSelectionControlMaskNone}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpBranchConditional, 0, 0,
+       {SPV_OPERAND_TYPE_SELECTION_CONTROL,
+        {uint32_t(spv::SelectionControlMask::MaskNone)}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpBranchConditional, 0,
+                                                0,
                                                 {{SPV_OPERAND_TYPE_ID, {15}},
                                                  {SPV_OPERAND_TYPE_ID, {16}},
                                                  {SPV_OPERAND_TYPE_ID, {17}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 16, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpUnreachable, 0, 0, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 17, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpKill, 0, 0, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpFunctionEnd, 0, 0, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 16, {}));
+  instructions.push_back(
+      MakeInstructionMessage(spv::Op::OpUnreachable, 0, 0, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 17, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpKill, 0, 0, {}));
+  instructions.push_back(
+      MakeInstructionMessage(spv::Op::OpFunctionEnd, 0, 0, {}));
 
   spvtools::ValidatorOptions validator_options;
 
@@ -1189,129 +1219,133 @@
 
   std::vector<protobufs::Instruction> instructions;
 
-  instructions.push_back(MakeInstructionMessage(
-      SpvOpFunction, 2, 12,
-      {{SPV_OPERAND_TYPE_FUNCTION_CONTROL, {SpvFunctionControlMaskNone}},
-       {SPV_OPERAND_TYPE_TYPE_ID, {8}}}));
   instructions.push_back(
-      MakeInstructionMessage(SpvOpFunctionParameter, 7, 9, {}));
+      MakeInstructionMessage(spv::Op::OpFunction, 2, 12,
+                             {{SPV_OPERAND_TYPE_FUNCTION_CONTROL,
+                               {uint32_t(spv::FunctionControlMask::MaskNone)}},
+                              {SPV_OPERAND_TYPE_TYPE_ID, {8}}}));
   instructions.push_back(
-      MakeInstructionMessage(SpvOpFunctionParameter, 102, 10, {}));
+      MakeInstructionMessage(spv::Op::OpFunctionParameter, 7, 9, {}));
   instructions.push_back(
-      MakeInstructionMessage(SpvOpFunctionParameter, 7, 11, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 13, {}));
+      MakeInstructionMessage(spv::Op::OpFunctionParameter, 102, 10, {}));
+  instructions.push_back(
+      MakeInstructionMessage(spv::Op::OpFunctionParameter, 7, 11, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 13, {}));
 
-  instructions.push_back(MakeInstructionMessage(
-      SpvOpVariable, 7, 14,
-      {{SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}}}));
-  instructions.push_back(MakeInstructionMessage(
-      SpvOpVariable, 26, 27,
-      {{SPV_OPERAND_TYPE_STORAGE_CLASS, {SpvStorageClassFunction}}}));
   instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 6, 22, {{SPV_OPERAND_TYPE_ID, {11}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpAccessChain, 23, 24,
+      MakeInstructionMessage(spv::Op::OpVariable, 7, 14,
+                             {{SPV_OPERAND_TYPE_STORAGE_CLASS,
+                               {uint32_t(spv::StorageClass::Function)}}}));
+  instructions.push_back(
+      MakeInstructionMessage(spv::Op::OpVariable, 26, 27,
+                             {{SPV_OPERAND_TYPE_STORAGE_CLASS,
+                               {uint32_t(spv::StorageClass::Function)}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 6, 22,
+                                                {{SPV_OPERAND_TYPE_ID, {11}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpAccessChain, 23, 24,
                                                 {{SPV_OPERAND_TYPE_ID, {20}},
                                                  {SPV_OPERAND_TYPE_ID, {21}},
                                                  {SPV_OPERAND_TYPE_ID, {22}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 6, 25, {{SPV_OPERAND_TYPE_ID, {24}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 6, 25,
+                                                {{SPV_OPERAND_TYPE_ID, {24}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpStore, 0, 0,
+      spv::Op::OpStore, 0, 0,
       {{SPV_OPERAND_TYPE_ID, {14}}, {SPV_OPERAND_TYPE_ID, {25}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 15, 28, {{SPV_OPERAND_TYPE_ID, {10}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 15, 28,
+                                                {{SPV_OPERAND_TYPE_ID, {10}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpAccessChain, 29, 30,
+      spv::Op::OpAccessChain, 29, 30,
       {{SPV_OPERAND_TYPE_ID, {20}}, {SPV_OPERAND_TYPE_ID, {28}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 17, 31, {{SPV_OPERAND_TYPE_ID, {30}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 17, 31,
+                                                {{SPV_OPERAND_TYPE_ID, {30}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpStore, 0, 0,
+      spv::Op::OpStore, 0, 0,
       {{SPV_OPERAND_TYPE_ID, {27}}, {SPV_OPERAND_TYPE_ID, {31}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 6, 32, {{SPV_OPERAND_TYPE_ID, {9}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 6, 32,
+                                                {{SPV_OPERAND_TYPE_ID, {9}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpInBoundsAccessChain, 7, 34,
+      spv::Op::OpInBoundsAccessChain, 7, 34,
       {{SPV_OPERAND_TYPE_ID, {27}}, {SPV_OPERAND_TYPE_ID, {32}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpStore, 0, 0,
+      spv::Op::OpStore, 0, 0,
       {{SPV_OPERAND_TYPE_ID, {34}}, {SPV_OPERAND_TYPE_ID, {33}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 6, 39, {{SPV_OPERAND_TYPE_ID, {9}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 6, 39,
+                                                {{SPV_OPERAND_TYPE_ID, {9}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpAccessChain, 23, 40,
+      spv::Op::OpAccessChain, 23, 40,
       {{SPV_OPERAND_TYPE_ID, {38}}, {SPV_OPERAND_TYPE_ID, {33}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 6, 41, {{SPV_OPERAND_TYPE_ID, {40}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 6, 41,
+                                                {{SPV_OPERAND_TYPE_ID, {40}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpInBoundsAccessChain, 23, 42,
+      spv::Op::OpInBoundsAccessChain, 23, 42,
       {{SPV_OPERAND_TYPE_ID, {38}}, {SPV_OPERAND_TYPE_ID, {39}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpStore, 0, 0,
+      spv::Op::OpStore, 0, 0,
       {{SPV_OPERAND_TYPE_ID, {42}}, {SPV_OPERAND_TYPE_ID, {41}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 15, 43, {{SPV_OPERAND_TYPE_ID, {10}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 6, 44, {{SPV_OPERAND_TYPE_ID, {11}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 6, 45, {{SPV_OPERAND_TYPE_ID, {9}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 15, 46, {{SPV_OPERAND_TYPE_ID, {10}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 15, 43,
+                                                {{SPV_OPERAND_TYPE_ID, {10}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 6, 44,
+                                                {{SPV_OPERAND_TYPE_ID, {11}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 6, 45,
+                                                {{SPV_OPERAND_TYPE_ID, {9}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 15, 46,
+                                                {{SPV_OPERAND_TYPE_ID, {10}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpIAdd, 6, 47,
+      spv::Op::OpIAdd, 6, 47,
       {{SPV_OPERAND_TYPE_ID, {45}}, {SPV_OPERAND_TYPE_ID, {46}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpAccessChain, 23, 48,
+      spv::Op::OpAccessChain, 23, 48,
       {{SPV_OPERAND_TYPE_ID, {38}}, {SPV_OPERAND_TYPE_ID, {47}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 6, 49, {{SPV_OPERAND_TYPE_ID, {48}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpInBoundsAccessChain, 23,
-                                                50,
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 6, 49,
+                                                {{SPV_OPERAND_TYPE_ID, {48}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpInBoundsAccessChain,
+                                                23, 50,
                                                 {{SPV_OPERAND_TYPE_ID, {20}},
                                                  {SPV_OPERAND_TYPE_ID, {43}},
                                                  {SPV_OPERAND_TYPE_ID, {44}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 6, 51, {{SPV_OPERAND_TYPE_ID, {50}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 6, 51,
+                                                {{SPV_OPERAND_TYPE_ID, {50}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpIAdd, 6, 52,
+      spv::Op::OpIAdd, 6, 52,
       {{SPV_OPERAND_TYPE_ID, {51}}, {SPV_OPERAND_TYPE_ID, {49}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpAccessChain, 23, 53,
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpAccessChain, 23, 53,
                                                 {{SPV_OPERAND_TYPE_ID, {20}},
                                                  {SPV_OPERAND_TYPE_ID, {43}},
                                                  {SPV_OPERAND_TYPE_ID, {44}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpStore, 0, 0,
+      spv::Op::OpStore, 0, 0,
       {{SPV_OPERAND_TYPE_ID, {53}}, {SPV_OPERAND_TYPE_ID, {52}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 15, 58, {{SPV_OPERAND_TYPE_ID, {10}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 6, 63, {{SPV_OPERAND_TYPE_ID, {11}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpAccessChain, 64, 65,
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 15, 58,
+                                                {{SPV_OPERAND_TYPE_ID, {10}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 6, 63,
+                                                {{SPV_OPERAND_TYPE_ID, {11}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpAccessChain, 64, 65,
                                                 {{SPV_OPERAND_TYPE_ID, {62}},
                                                  {SPV_OPERAND_TYPE_ID, {21}},
                                                  {SPV_OPERAND_TYPE_ID, {63}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpAccessChain, 64, 101,
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpAccessChain, 64, 101,
                                                 {{SPV_OPERAND_TYPE_ID, {62}},
                                                  {SPV_OPERAND_TYPE_ID, {45}},
                                                  {SPV_OPERAND_TYPE_ID, {46}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 54, 66, {{SPV_OPERAND_TYPE_ID, {65}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 54, 66,
+                                                {{SPV_OPERAND_TYPE_ID, {65}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpAccessChain, 64, 67,
+      spv::Op::OpAccessChain, 64, 67,
       {{SPV_OPERAND_TYPE_ID, {57}}, {SPV_OPERAND_TYPE_ID, {58}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpStore, 0, 0,
+      spv::Op::OpStore, 0, 0,
       {{SPV_OPERAND_TYPE_ID, {67}}, {SPV_OPERAND_TYPE_ID, {66}}}));
-  instructions.push_back(
-      MakeInstructionMessage(SpvOpLoad, 6, 68, {{SPV_OPERAND_TYPE_ID, {9}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLoad, 6, 68,
+                                                {{SPV_OPERAND_TYPE_ID, {9}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpInBoundsAccessChain, 64, 70,
+      spv::Op::OpInBoundsAccessChain, 64, 70,
       {{SPV_OPERAND_TYPE_ID, {57}}, {SPV_OPERAND_TYPE_ID, {68}}}));
   instructions.push_back(MakeInstructionMessage(
-      SpvOpStore, 0, 0,
+      spv::Op::OpStore, 0, 0,
       {{SPV_OPERAND_TYPE_ID, {70}}, {SPV_OPERAND_TYPE_ID, {69}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpReturn, 0, 0, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpFunctionEnd, 0, 0, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpReturn, 0, 0, {}));
+  instructions.push_back(
+      MakeInstructionMessage(spv::Op::OpFunctionEnd, 0, 0, {}));
 
   spvtools::ValidatorOptions validator_options;
 
@@ -1634,15 +1668,17 @@
 
   std::vector<protobufs::Instruction> instructions;
 
-  instructions.push_back(MakeInstructionMessage(
-      SpvOpFunction, 2, 8,
-      {{SPV_OPERAND_TYPE_FUNCTION_CONTROL, {SpvFunctionControlMaskNone}},
-       {SPV_OPERAND_TYPE_TYPE_ID, {3}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 9, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpFunctionCall, 2, 11,
+  instructions.push_back(
+      MakeInstructionMessage(spv::Op::OpFunction, 2, 8,
+                             {{SPV_OPERAND_TYPE_FUNCTION_CONTROL,
+                               {uint32_t(spv::FunctionControlMask::MaskNone)}},
+                              {SPV_OPERAND_TYPE_TYPE_ID, {3}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 9, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpFunctionCall, 2, 11,
                                                 {{SPV_OPERAND_TYPE_ID, {6}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpReturn, 0, 0, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpFunctionEnd, 0, 0, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpReturn, 0, 0, {}));
+  instructions.push_back(
+      MakeInstructionMessage(spv::Op::OpFunctionEnd, 0, 0, {}));
 
   spvtools::ValidatorOptions validator_options;
 
@@ -1738,15 +1774,17 @@
 
   std::vector<protobufs::Instruction> instructions;
 
-  instructions.push_back(MakeInstructionMessage(
-      SpvOpFunction, 2, 8,
-      {{SPV_OPERAND_TYPE_FUNCTION_CONTROL, {SpvFunctionControlMaskNone}},
-       {SPV_OPERAND_TYPE_TYPE_ID, {3}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpLabel, 0, 9, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpFunctionCall, 2, 11,
+  instructions.push_back(
+      MakeInstructionMessage(spv::Op::OpFunction, 2, 8,
+                             {{SPV_OPERAND_TYPE_FUNCTION_CONTROL,
+                               {uint32_t(spv::FunctionControlMask::MaskNone)}},
+                              {SPV_OPERAND_TYPE_TYPE_ID, {3}}}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpLabel, 0, 9, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpFunctionCall, 2, 11,
                                                 {{SPV_OPERAND_TYPE_ID, {6}}}));
-  instructions.push_back(MakeInstructionMessage(SpvOpReturn, 0, 0, {}));
-  instructions.push_back(MakeInstructionMessage(SpvOpFunctionEnd, 0, 0, {}));
+  instructions.push_back(MakeInstructionMessage(spv::Op::OpReturn, 0, 0, {}));
+  instructions.push_back(
+      MakeInstructionMessage(spv::Op::OpFunctionEnd, 0, 0, {}));
 
   spvtools::ValidatorOptions validator_options;
 
diff --git a/test/fuzz/transformation_add_global_undef_test.cpp b/test/fuzz/transformation_add_global_undef_test.cpp
index 03b9157..b87970f 100644
--- a/test/fuzz/transformation_add_global_undef_test.cpp
+++ b/test/fuzz/transformation_add_global_undef_test.cpp
@@ -71,7 +71,8 @@
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
-    ASSERT_EQ(SpvOpUndef, context->get_def_use_mgr()->GetDef(100)->opcode());
+    ASSERT_EQ(spv::Op::OpUndef,
+              context->get_def_use_mgr()->GetDef(100)->opcode());
   }
 
   TransformationAddGlobalUndef transformations[] = {
diff --git a/test/fuzz/transformation_add_global_variable_test.cpp b/test/fuzz/transformation_add_global_variable_test.cpp
index 9531ade..fc452df 100644
--- a/test/fuzz/transformation_add_global_variable_test.cpp
+++ b/test/fuzz/transformation_add_global_variable_test.cpp
@@ -66,94 +66,95 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   // Id already in use
-  ASSERT_FALSE(
-      TransformationAddGlobalVariable(4, 10, SpvStorageClassPrivate, 0, true)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAddGlobalVariable(
+                   4, 10, spv::StorageClass::Private, 0, true)
+                   .IsApplicable(context.get(), transformation_context));
   // %1 is not a type
-  ASSERT_FALSE(
-      TransformationAddGlobalVariable(100, 1, SpvStorageClassPrivate, 0, false)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAddGlobalVariable(
+                   100, 1, spv::StorageClass::Private, 0, false)
+                   .IsApplicable(context.get(), transformation_context));
 
   // %7 is not a pointer type
-  ASSERT_FALSE(
-      TransformationAddGlobalVariable(100, 7, SpvStorageClassPrivate, 0, true)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAddGlobalVariable(
+                   100, 7, spv::StorageClass::Private, 0, true)
+                   .IsApplicable(context.get(), transformation_context));
 
   // %9 does not have Private storage class
-  ASSERT_FALSE(
-      TransformationAddGlobalVariable(100, 9, SpvStorageClassPrivate, 0, false)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAddGlobalVariable(
+                   100, 9, spv::StorageClass::Private, 0, false)
+                   .IsApplicable(context.get(), transformation_context));
 
   // %15 does not have Private storage class
-  ASSERT_FALSE(
-      TransformationAddGlobalVariable(100, 15, SpvStorageClassPrivate, 0, true)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAddGlobalVariable(
+                   100, 15, spv::StorageClass::Private, 0, true)
+                   .IsApplicable(context.get(), transformation_context));
 
   // %10 is a pointer to float, while %16 is an int constant
-  ASSERT_FALSE(TransformationAddGlobalVariable(100, 10, SpvStorageClassPrivate,
-                                               16, false)
+  ASSERT_FALSE(TransformationAddGlobalVariable(
+                   100, 10, spv::StorageClass::Private, 16, false)
                    .IsApplicable(context.get(), transformation_context));
 
   // %10 is a Private pointer to float, while %15 is a variable with type
   // Uniform float pointer
-  ASSERT_FALSE(
-      TransformationAddGlobalVariable(100, 10, SpvStorageClassPrivate, 15, true)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAddGlobalVariable(
+                   100, 10, spv::StorageClass::Private, 15, true)
+                   .IsApplicable(context.get(), transformation_context));
 
   // %12 is a Private pointer to int, while %10 is a variable with type
   // Private float pointer
-  ASSERT_FALSE(TransformationAddGlobalVariable(100, 12, SpvStorageClassPrivate,
-                                               10, false)
+  ASSERT_FALSE(TransformationAddGlobalVariable(
+                   100, 12, spv::StorageClass::Private, 10, false)
                    .IsApplicable(context.get(), transformation_context));
 
   // %10 is pointer-to-float, and %14 has type pointer-to-float; that's not OK
   // since the initializer's type should be the *pointee* type.
-  ASSERT_FALSE(
-      TransformationAddGlobalVariable(104, 10, SpvStorageClassPrivate, 14, true)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationAddGlobalVariable(
+                   104, 10, spv::StorageClass::Private, 14, true)
+                   .IsApplicable(context.get(), transformation_context));
 
   // This would work in principle, but logical addressing does not allow
   // a pointer to a pointer.
-  ASSERT_FALSE(TransformationAddGlobalVariable(104, 17, SpvStorageClassPrivate,
-                                               14, false)
+  ASSERT_FALSE(TransformationAddGlobalVariable(
+                   104, 17, spv::StorageClass::Private, 14, false)
                    .IsApplicable(context.get(), transformation_context));
 
   {
     // %100 = OpVariable %12 Private
     ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(100));
     TransformationAddGlobalVariable transformation(
-        100, 12, SpvStorageClassPrivate, 16, true);
+        100, 12, spv::StorageClass::Private, 16, true);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
-    ASSERT_EQ(SpvOpVariable, context->get_def_use_mgr()->GetDef(100)->opcode());
+    ASSERT_EQ(spv::Op::OpVariable,
+              context->get_def_use_mgr()->GetDef(100)->opcode());
     ASSERT_EQ(
-        SpvStorageClassPrivate,
-        static_cast<SpvStorageClass>(
+        spv::StorageClass::Private,
+        static_cast<spv::StorageClass>(
             context->get_def_use_mgr()->GetDef(100)->GetSingleWordInOperand(
                 0)));
   }
 
   TransformationAddGlobalVariable transformations[] = {
       // %101 = OpVariable %10 Private
-      TransformationAddGlobalVariable(101, 10, SpvStorageClassPrivate, 40,
+      TransformationAddGlobalVariable(101, 10, spv::StorageClass::Private, 40,
                                       false),
 
       // %102 = OpVariable %13 Private
-      TransformationAddGlobalVariable(102, 13, SpvStorageClassPrivate, 41,
+      TransformationAddGlobalVariable(102, 13, spv::StorageClass::Private, 41,
                                       true),
 
       // %103 = OpVariable %12 Private %16
-      TransformationAddGlobalVariable(103, 12, SpvStorageClassPrivate, 16,
+      TransformationAddGlobalVariable(103, 12, spv::StorageClass::Private, 16,
                                       false),
 
       // %104 = OpVariable %19 Private %21
-      TransformationAddGlobalVariable(104, 19, SpvStorageClassPrivate, 21,
+      TransformationAddGlobalVariable(104, 19, spv::StorageClass::Private, 21,
                                       true),
 
       // %105 = OpVariable %19 Private %22
-      TransformationAddGlobalVariable(105, 19, SpvStorageClassPrivate, 22,
+      TransformationAddGlobalVariable(105, 19, spv::StorageClass::Private, 22,
                                       false)};
 
   for (auto& transformation : transformations) {
@@ -269,15 +270,15 @@
         MakeUnique<FactManager>(context.get()), validator_options);
     TransformationAddGlobalVariable transformations[] = {
         // %100 = OpVariable %12 Private
-        TransformationAddGlobalVariable(100, 12, SpvStorageClassPrivate, 16,
+        TransformationAddGlobalVariable(100, 12, spv::StorageClass::Private, 16,
                                         true),
 
         // %101 = OpVariable %12 Private %16
-        TransformationAddGlobalVariable(101, 12, SpvStorageClassPrivate, 16,
+        TransformationAddGlobalVariable(101, 12, spv::StorageClass::Private, 16,
                                         false),
 
         // %102 = OpVariable %19 Private %21
-        TransformationAddGlobalVariable(102, 19, SpvStorageClassPrivate, 21,
+        TransformationAddGlobalVariable(102, 19, spv::StorageClass::Private, 21,
                                         true)};
 
     for (auto& transformation : transformations) {
@@ -388,15 +389,15 @@
         MakeUnique<FactManager>(context.get()), validator_options);
     TransformationAddGlobalVariable transformations[] = {
         // %100 = OpVariable %12 Private
-        TransformationAddGlobalVariable(100, 12, SpvStorageClassPrivate, 16,
+        TransformationAddGlobalVariable(100, 12, spv::StorageClass::Private, 16,
                                         true),
 
         // %101 = OpVariable %12 Private %16
-        TransformationAddGlobalVariable(101, 12, SpvStorageClassPrivate, 16,
+        TransformationAddGlobalVariable(101, 12, spv::StorageClass::Private, 16,
                                         false),
 
         // %102 = OpVariable %19 Private %21
-        TransformationAddGlobalVariable(102, 19, SpvStorageClassPrivate, 21,
+        TransformationAddGlobalVariable(102, 19, spv::StorageClass::Private, 21,
                                         true)};
 
     for (auto& transformation : transformations) {
@@ -486,7 +487,8 @@
       MakeUnique<FactManager>(context.get()), validator_options);
 #ifndef NDEBUG
   ASSERT_DEATH(
-      TransformationAddGlobalVariable(8, 7, SpvStorageClassWorkgroup, 50, true)
+      TransformationAddGlobalVariable(8, 7, spv::StorageClass::Workgroup, 50,
+                                      true)
           .IsApplicable(context.get(), transformation_context),
       "By construction this transformation should not have an.*initializer "
       "when Workgroup storage class is used");
@@ -494,10 +496,11 @@
 
   TransformationAddGlobalVariable transformations[] = {
       // %8 = OpVariable %7 Workgroup
-      TransformationAddGlobalVariable(8, 7, SpvStorageClassWorkgroup, 0, true),
+      TransformationAddGlobalVariable(8, 7, spv::StorageClass::Workgroup, 0,
+                                      true),
 
       // %10 = OpVariable %7 Workgroup
-      TransformationAddGlobalVariable(10, 7, SpvStorageClassWorkgroup, 0,
+      TransformationAddGlobalVariable(10, 7, spv::StorageClass::Workgroup, 0,
                                       false)};
 
   for (auto& transformation : transformations) {
diff --git a/test/fuzz/transformation_add_image_sample_unused_components_test.cpp b/test/fuzz/transformation_add_image_sample_unused_components_test.cpp
index 072378c..7047544 100644
--- a/test/fuzz/transformation_add_image_sample_unused_components_test.cpp
+++ b/test/fuzz/transformation_add_image_sample_unused_components_test.cpp
@@ -73,14 +73,14 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // Tests applicable image instruction.
   auto instruction_descriptor =
-      MakeInstructionDescriptor(25, SpvOpImageSampleImplicitLod, 0);
+      MakeInstructionDescriptor(25, spv::Op::OpImageSampleImplicitLod, 0);
   auto transformation =
       TransformationAddImageSampleUnusedComponents(23, instruction_descriptor);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   instruction_descriptor =
-      MakeInstructionDescriptor(26, SpvOpImageSampleExplicitLod, 0);
+      MakeInstructionDescriptor(26, spv::Op::OpImageSampleExplicitLod, 0);
   transformation =
       TransformationAddImageSampleUnusedComponents(24, instruction_descriptor);
   ASSERT_TRUE(
@@ -88,27 +88,27 @@
 
   // Tests undefined image instructions.
   instruction_descriptor =
-      MakeInstructionDescriptor(27, SpvOpImageSampleImplicitLod, 0);
+      MakeInstructionDescriptor(27, spv::Op::OpImageSampleImplicitLod, 0);
   transformation =
       TransformationAddImageSampleUnusedComponents(23, instruction_descriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   instruction_descriptor =
-      MakeInstructionDescriptor(28, SpvOpImageSampleExplicitLod, 0);
+      MakeInstructionDescriptor(28, spv::Op::OpImageSampleExplicitLod, 0);
   transformation =
       TransformationAddImageSampleUnusedComponents(23, instruction_descriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   // Tests non-image instructions.
-  instruction_descriptor = MakeInstructionDescriptor(19, SpvOpLabel, 0);
+  instruction_descriptor = MakeInstructionDescriptor(19, spv::Op::OpLabel, 0);
   transformation =
       TransformationAddImageSampleUnusedComponents(24, instruction_descriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instruction_descriptor = MakeInstructionDescriptor(20, SpvOpLoad, 0);
+  instruction_descriptor = MakeInstructionDescriptor(20, spv::Op::OpLoad, 0);
   transformation =
       TransformationAddImageSampleUnusedComponents(24, instruction_descriptor);
   ASSERT_FALSE(
@@ -116,7 +116,7 @@
 
   // Tests coordinate operand being a vec4.
   instruction_descriptor =
-      MakeInstructionDescriptor(27, SpvOpImageSampleExplicitLod, 0);
+      MakeInstructionDescriptor(27, spv::Op::OpImageSampleExplicitLod, 0);
   transformation =
       TransformationAddImageSampleUnusedComponents(22, instruction_descriptor);
   ASSERT_FALSE(
@@ -124,7 +124,7 @@
 
   // Tests undefined coordinate with unused operands.
   instruction_descriptor =
-      MakeInstructionDescriptor(25, SpvOpImageSampleImplicitLod, 0);
+      MakeInstructionDescriptor(25, spv::Op::OpImageSampleImplicitLod, 0);
   transformation =
       TransformationAddImageSampleUnusedComponents(27, instruction_descriptor);
   ASSERT_FALSE(
@@ -133,7 +133,7 @@
   // Tests coordinate with unused operands being a non-OpCompositeConstruct
   // instruction.
   instruction_descriptor =
-      MakeInstructionDescriptor(25, SpvOpImageSampleImplicitLod, 0);
+      MakeInstructionDescriptor(25, spv::Op::OpImageSampleImplicitLod, 0);
   transformation =
       TransformationAddImageSampleUnusedComponents(21, instruction_descriptor);
   ASSERT_FALSE(
@@ -142,7 +142,7 @@
   // Tests the first OpCompositeConstruct constituent not being the original
   // coordinate.
   instruction_descriptor =
-      MakeInstructionDescriptor(25, SpvOpImageSampleImplicitLod, 0);
+      MakeInstructionDescriptor(25, spv::Op::OpImageSampleImplicitLod, 0);
   transformation =
       TransformationAddImageSampleUnusedComponents(22, instruction_descriptor);
   ASSERT_FALSE(
@@ -198,13 +198,13 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   auto instruction_descriptor =
-      MakeInstructionDescriptor(25, SpvOpImageSampleImplicitLod, 0);
+      MakeInstructionDescriptor(25, spv::Op::OpImageSampleImplicitLod, 0);
   auto transformation =
       TransformationAddImageSampleUnusedComponents(23, instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instruction_descriptor =
-      MakeInstructionDescriptor(26, SpvOpImageSampleExplicitLod, 0);
+      MakeInstructionDescriptor(26, spv::Op::OpImageSampleExplicitLod, 0);
   transformation =
       TransformationAddImageSampleUnusedComponents(24, instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
diff --git a/test/fuzz/transformation_add_local_variable_test.cpp b/test/fuzz/transformation_add_local_variable_test.cpp
index de88573..2af8597 100644
--- a/test/fuzz/transformation_add_local_variable_test.cpp
+++ b/test/fuzz/transformation_add_local_variable_test.cpp
@@ -104,7 +104,8 @@
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
-    ASSERT_EQ(SpvOpVariable, context->get_def_use_mgr()->GetDef(105)->opcode());
+    ASSERT_EQ(spv::Op::OpVariable,
+              context->get_def_use_mgr()->GetDef(105)->opcode());
     ASSERT_EQ(5, context->get_instr_block(105)->id());
   }
 
diff --git a/test/fuzz/transformation_add_opphi_synonym_test.cpp b/test/fuzz/transformation_add_opphi_synonym_test.cpp
index 3501f8e..4aca30c 100644
--- a/test/fuzz/transformation_add_opphi_synonym_test.cpp
+++ b/test/fuzz/transformation_add_opphi_synonym_test.cpp
@@ -366,7 +366,7 @@
 
   // Remove the VariablePointers capability.
   context.get()->get_feature_mgr()->RemoveCapability(
-      SpvCapabilityVariablePointers);
+      spv::Capability::VariablePointers);
 
   // The VariablePointers capability is required to add an OpPhi instruction of
   // pointer type.
@@ -375,7 +375,7 @@
 
   // Add the VariablePointers capability back.
   context.get()->get_feature_mgr()->AddCapability(
-      SpvCapabilityVariablePointers);
+      spv::Capability::VariablePointers);
 
   // If the ids have pointer type, the storage class must be Workgroup or
   // StorageBuffer, but it is Function in this case.
diff --git a/test/fuzz/transformation_add_synonym_test.cpp b/test/fuzz/transformation_add_synonym_test.cpp
index ffcf1c9..385590e 100644
--- a/test/fuzz/transformation_add_synonym_test.cpp
+++ b/test/fuzz/transformation_add_synonym_test.cpp
@@ -77,7 +77,7 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   transformation_context.GetFactManager()->AddFactIdIsIrrelevant(24);
 
-  auto insert_before = MakeInstructionDescriptor(22, SpvOpReturn, 0);
+  auto insert_before = MakeInstructionDescriptor(22, spv::Op::OpReturn, 0);
 
 #ifndef NDEBUG
   ASSERT_DEATH(
@@ -126,34 +126,34 @@
                      .IsApplicable(context.get(), transformation_context));
 
     // |insert_before| is invalid.
-    ASSERT_FALSE(
-        TransformationAddSynonym(9, synonym_type, 40,
-                                 MakeInstructionDescriptor(25, SpvOpStore, 0))
-            .IsApplicable(context.get(), transformation_context));
-
-    // Can't insert before |insert_before|.
-    ASSERT_FALSE(
-        TransformationAddSynonym(9, synonym_type, 40,
-                                 MakeInstructionDescriptor(5, SpvOpLabel, 0))
-            .IsApplicable(context.get(), transformation_context));
     ASSERT_FALSE(TransformationAddSynonym(
                      9, synonym_type, 40,
-                     MakeInstructionDescriptor(22, SpvOpVariable, 0))
+                     MakeInstructionDescriptor(25, spv::Op::OpStore, 0))
+                     .IsApplicable(context.get(), transformation_context));
+
+    // Can't insert before |insert_before|.
+    ASSERT_FALSE(TransformationAddSynonym(
+                     9, synonym_type, 40,
+                     MakeInstructionDescriptor(5, spv::Op::OpLabel, 0))
                      .IsApplicable(context.get(), transformation_context));
     ASSERT_FALSE(TransformationAddSynonym(
                      9, synonym_type, 40,
-                     MakeInstructionDescriptor(25, SpvOpFunctionEnd, 0))
+                     MakeInstructionDescriptor(22, spv::Op::OpVariable, 0))
+                     .IsApplicable(context.get(), transformation_context));
+    ASSERT_FALSE(TransformationAddSynonym(
+                     9, synonym_type, 40,
+                     MakeInstructionDescriptor(25, spv::Op::OpFunctionEnd, 0))
                      .IsApplicable(context.get(), transformation_context));
 
     // Domination rules are not satisfied.
-    ASSERT_FALSE(
-        TransformationAddSynonym(27, synonym_type, 40,
-                                 MakeInstructionDescriptor(27, SpvOpLoad, 0))
-            .IsApplicable(context.get(), transformation_context));
-    ASSERT_FALSE(
-        TransformationAddSynonym(27, synonym_type, 40,
-                                 MakeInstructionDescriptor(22, SpvOpStore, 1))
-            .IsApplicable(context.get(), transformation_context));
+    ASSERT_FALSE(TransformationAddSynonym(
+                     27, synonym_type, 40,
+                     MakeInstructionDescriptor(27, spv::Op::OpLoad, 0))
+                     .IsApplicable(context.get(), transformation_context));
+    ASSERT_FALSE(TransformationAddSynonym(
+                     27, synonym_type, 40,
+                     MakeInstructionDescriptor(22, spv::Op::OpStore, 1))
+                     .IsApplicable(context.get(), transformation_context));
   }
 }
 
@@ -212,7 +212,7 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto insert_before = MakeInstructionDescriptor(5, SpvOpReturn, 0);
+  auto insert_before = MakeInstructionDescriptor(5, spv::Op::OpReturn, 0);
 
   uint32_t fresh_id = 50;
   for (auto synonym_type : {protobufs::TransformationAddSynonym::ADD_ZERO,
@@ -374,7 +374,7 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto insert_before = MakeInstructionDescriptor(5, SpvOpReturn, 0);
+  auto insert_before = MakeInstructionDescriptor(5, spv::Op::OpReturn, 0);
 
   uint32_t fresh_id = 50;
   for (auto synonym_type : {protobufs::TransformationAddSynonym::LOGICAL_AND,
@@ -467,7 +467,7 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto insert_before = MakeInstructionDescriptor(5, SpvOpReturn, 0);
+  auto insert_before = MakeInstructionDescriptor(5, spv::Op::OpReturn, 0);
   const auto synonym_type = protobufs::TransformationAddSynonym::LOGICAL_AND;
 
   // Required constant is not present in the module.
@@ -505,7 +505,7 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto insert_before = MakeInstructionDescriptor(5, SpvOpReturn, 0);
+  auto insert_before = MakeInstructionDescriptor(5, spv::Op::OpReturn, 0);
   const auto synonym_type = protobufs::TransformationAddSynonym::LOGICAL_OR;
 
   // Required constant is not present in the module.
@@ -563,7 +563,7 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto insert_before = MakeInstructionDescriptor(5, SpvOpReturn, 0);
+  auto insert_before = MakeInstructionDescriptor(5, spv::Op::OpReturn, 0);
   const auto synonym_type = protobufs::TransformationAddSynonym::COPY_OBJECT;
 
   ASSERT_FALSE(
@@ -666,7 +666,7 @@
   {
     TransformationAddSynonym copy_true(
         7, protobufs::TransformationAddSynonym::COPY_OBJECT, 100,
-        MakeInstructionDescriptor(5, SpvOpReturn, 0));
+        MakeInstructionDescriptor(5, spv::Op::OpReturn, 0));
     ASSERT_TRUE(copy_true.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(copy_true, context.get(), &transformation_context);
 
@@ -687,7 +687,7 @@
   {
     TransformationAddSynonym copy_false(
         8, protobufs::TransformationAddSynonym::COPY_OBJECT, 101,
-        MakeInstructionDescriptor(100, SpvOpReturn, 0));
+        MakeInstructionDescriptor(100, spv::Op::OpReturn, 0));
     ASSERT_TRUE(copy_false.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(copy_false, context.get(), &transformation_context);
     std::vector<uint32_t> ids_for_which_synonyms_are_known =
@@ -707,7 +707,7 @@
   {
     TransformationAddSynonym copy_false_again(
         101, protobufs::TransformationAddSynonym::COPY_OBJECT, 102,
-        MakeInstructionDescriptor(5, SpvOpReturn, 0));
+        MakeInstructionDescriptor(5, spv::Op::OpReturn, 0));
     ASSERT_TRUE(
         copy_false_again.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(copy_false_again, context.get(),
@@ -730,7 +730,7 @@
   {
     TransformationAddSynonym copy_true_again(
         7, protobufs::TransformationAddSynonym::COPY_OBJECT, 103,
-        MakeInstructionDescriptor(102, SpvOpReturn, 0));
+        MakeInstructionDescriptor(102, spv::Op::OpReturn, 0));
     ASSERT_TRUE(
         copy_true_again.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(copy_true_again, context.get(),
@@ -970,128 +970,133 @@
   // Inapplicable because %18 is decorated.
   ASSERT_FALSE(TransformationAddSynonym(
                    18, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                   MakeInstructionDescriptor(21, SpvOpAccessChain, 0))
+                   MakeInstructionDescriptor(21, spv::Op::OpAccessChain, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because %77 is decorated.
   ASSERT_FALSE(TransformationAddSynonym(
                    77, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                   MakeInstructionDescriptor(77, SpvOpBranch, 0))
+                   MakeInstructionDescriptor(77, spv::Op::OpBranch, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because %80 is decorated.
   ASSERT_FALSE(TransformationAddSynonym(
                    80, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                   MakeInstructionDescriptor(77, SpvOpIAdd, 0))
+                   MakeInstructionDescriptor(77, spv::Op::OpIAdd, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because %84 is not available at the requested point
-  ASSERT_FALSE(TransformationAddSynonym(
-                   84, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                   MakeInstructionDescriptor(32, SpvOpCompositeExtract, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAddSynonym(
+          84, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
+          MakeInstructionDescriptor(32, spv::Op::OpCompositeExtract, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   // Fine because %84 is available at the requested point
-  ASSERT_TRUE(TransformationAddSynonym(
-                  84, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                  MakeInstructionDescriptor(32, SpvOpCompositeConstruct, 0))
-                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(
+      TransformationAddSynonym(
+          84, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
+          MakeInstructionDescriptor(32, spv::Op::OpCompositeConstruct, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because id %9 is already in use
-  ASSERT_FALSE(TransformationAddSynonym(
-                   84, protobufs::TransformationAddSynonym::COPY_OBJECT, 9,
-                   MakeInstructionDescriptor(32, SpvOpCompositeConstruct, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAddSynonym(
+          84, protobufs::TransformationAddSynonym::COPY_OBJECT, 9,
+          MakeInstructionDescriptor(32, spv::Op::OpCompositeConstruct, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because the requested point does not exist
   ASSERT_FALSE(TransformationAddSynonym(
                    84, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                   MakeInstructionDescriptor(86, SpvOpReturn, 2))
+                   MakeInstructionDescriptor(86, spv::Op::OpReturn, 2))
                    .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because %9 is not in a function
   ASSERT_FALSE(TransformationAddSynonym(
                    9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                   MakeInstructionDescriptor(9, SpvOpTypeInt, 0))
+                   MakeInstructionDescriptor(9, spv::Op::OpTypeInt, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because the insert point is right before, or inside, a chunk
   // of OpPhis
   ASSERT_FALSE(TransformationAddSynonym(
                    9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                   MakeInstructionDescriptor(30, SpvOpPhi, 0))
+                   MakeInstructionDescriptor(30, spv::Op::OpPhi, 0))
                    .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationAddSynonym(
                    9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                   MakeInstructionDescriptor(99, SpvOpPhi, 1))
+                   MakeInstructionDescriptor(99, spv::Op::OpPhi, 1))
                    .IsApplicable(context.get(), transformation_context));
 
   // OK, because the insert point is just after a chunk of OpPhis.
   ASSERT_TRUE(TransformationAddSynonym(
                   9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                  MakeInstructionDescriptor(96, SpvOpAccessChain, 0))
+                  MakeInstructionDescriptor(96, spv::Op::OpAccessChain, 0))
+                  .IsApplicable(context.get(), transformation_context));
+
+  // Inapplicable because the insert point is right after an OpSelectionMerge
+  ASSERT_FALSE(
+      TransformationAddSynonym(
+          9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
+          MakeInstructionDescriptor(58, spv::Op::OpBranchConditional, 0))
+          .IsApplicable(context.get(), transformation_context));
+
+  // OK, because the insert point is right before the OpSelectionMerge
+  ASSERT_TRUE(TransformationAddSynonym(
+                  9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
+                  MakeInstructionDescriptor(58, spv::Op::OpSelectionMerge, 0))
                   .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because the insert point is right after an OpSelectionMerge
   ASSERT_FALSE(TransformationAddSynonym(
                    9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                   MakeInstructionDescriptor(58, SpvOpBranchConditional, 0))
+                   MakeInstructionDescriptor(43, spv::Op::OpSwitch, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // OK, because the insert point is right before the OpSelectionMerge
   ASSERT_TRUE(TransformationAddSynonym(
                   9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                  MakeInstructionDescriptor(58, SpvOpSelectionMerge, 0))
-                  .IsApplicable(context.get(), transformation_context));
-
-  // Inapplicable because the insert point is right after an OpSelectionMerge
-  ASSERT_FALSE(TransformationAddSynonym(
-                   9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                   MakeInstructionDescriptor(43, SpvOpSwitch, 0))
-                   .IsApplicable(context.get(), transformation_context));
-
-  // OK, because the insert point is right before the OpSelectionMerge
-  ASSERT_TRUE(TransformationAddSynonym(
-                  9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                  MakeInstructionDescriptor(43, SpvOpSelectionMerge, 0))
+                  MakeInstructionDescriptor(43, spv::Op::OpSelectionMerge, 0))
                   .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because the insert point is right after an OpLoopMerge
-  ASSERT_FALSE(TransformationAddSynonym(
-                   9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                   MakeInstructionDescriptor(40, SpvOpBranchConditional, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationAddSynonym(
+          9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
+          MakeInstructionDescriptor(40, spv::Op::OpBranchConditional, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   // OK, because the insert point is right before the OpLoopMerge
   ASSERT_TRUE(TransformationAddSynonym(
                   9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                  MakeInstructionDescriptor(40, SpvOpLoopMerge, 0))
+                  MakeInstructionDescriptor(40, spv::Op::OpLoopMerge, 0))
                   .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because id %300 does not exist
   ASSERT_FALSE(TransformationAddSynonym(
                    300, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                   MakeInstructionDescriptor(40, SpvOpLoopMerge, 0))
+                   MakeInstructionDescriptor(40, spv::Op::OpLoopMerge, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // Inapplicable because the following instruction is OpVariable
   ASSERT_FALSE(TransformationAddSynonym(
                    9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                   MakeInstructionDescriptor(180, SpvOpVariable, 0))
+                   MakeInstructionDescriptor(180, spv::Op::OpVariable, 0))
                    .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationAddSynonym(
                    9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                   MakeInstructionDescriptor(181, SpvOpVariable, 0))
+                   MakeInstructionDescriptor(181, spv::Op::OpVariable, 0))
                    .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationAddSynonym(
                    9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                   MakeInstructionDescriptor(182, SpvOpVariable, 0))
+                   MakeInstructionDescriptor(182, spv::Op::OpVariable, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // OK, because this is just past the group of OpVariable instructions.
   ASSERT_TRUE(TransformationAddSynonym(
                   9, protobufs::TransformationAddSynonym::COPY_OBJECT, 200,
-                  MakeInstructionDescriptor(182, SpvOpAccessChain, 0))
+                  MakeInstructionDescriptor(182, spv::Op::OpAccessChain, 0))
                   .IsApplicable(context.get(), transformation_context));
 }
 
@@ -1163,25 +1168,25 @@
   std::vector<TransformationAddSynonym> transformations = {
       TransformationAddSynonym(
           19, protobufs::TransformationAddSynonym::COPY_OBJECT, 100,
-          MakeInstructionDescriptor(22, SpvOpStore, 0)),
+          MakeInstructionDescriptor(22, spv::Op::OpStore, 0)),
       TransformationAddSynonym(
           22, protobufs::TransformationAddSynonym::COPY_OBJECT, 101,
-          MakeInstructionDescriptor(22, SpvOpCopyObject, 0)),
+          MakeInstructionDescriptor(22, spv::Op::OpCopyObject, 0)),
       TransformationAddSynonym(
           12, protobufs::TransformationAddSynonym::COPY_OBJECT, 102,
-          MakeInstructionDescriptor(22, SpvOpCopyObject, 0)),
+          MakeInstructionDescriptor(22, spv::Op::OpCopyObject, 0)),
       TransformationAddSynonym(
           11, protobufs::TransformationAddSynonym::COPY_OBJECT, 103,
-          MakeInstructionDescriptor(22, SpvOpCopyObject, 0)),
+          MakeInstructionDescriptor(22, spv::Op::OpCopyObject, 0)),
       TransformationAddSynonym(
           16, protobufs::TransformationAddSynonym::COPY_OBJECT, 104,
-          MakeInstructionDescriptor(22, SpvOpCopyObject, 0)),
+          MakeInstructionDescriptor(22, spv::Op::OpCopyObject, 0)),
       TransformationAddSynonym(
           8, protobufs::TransformationAddSynonym::COPY_OBJECT, 105,
-          MakeInstructionDescriptor(22, SpvOpCopyObject, 0)),
+          MakeInstructionDescriptor(22, spv::Op::OpCopyObject, 0)),
       TransformationAddSynonym(
           17, protobufs::TransformationAddSynonym::COPY_OBJECT, 106,
-          MakeInstructionDescriptor(22, SpvOpCopyObject, 0))};
+          MakeInstructionDescriptor(22, spv::Op::OpCopyObject, 0))};
 
   for (auto& transformation : transformations) {
     ASSERT_TRUE(
@@ -1273,7 +1278,7 @@
   // Illegal to copy null.
   ASSERT_FALSE(TransformationAddSynonym(
                    8, protobufs::TransformationAddSynonym::COPY_OBJECT, 100,
-                   MakeInstructionDescriptor(5, SpvOpReturn, 0))
+                   MakeInstructionDescriptor(5, spv::Op::OpReturn, 0))
                    .IsApplicable(context.get(), transformation_context));
 }
 
@@ -1312,13 +1317,13 @@
 
   TransformationAddSynonym transformation1(
       8, protobufs::TransformationAddSynonym::COPY_OBJECT, 100,
-      MakeInstructionDescriptor(9, SpvOpReturn, 0));
+      MakeInstructionDescriptor(9, spv::Op::OpReturn, 0));
   TransformationAddSynonym transformation2(
       9, protobufs::TransformationAddSynonym::COPY_OBJECT, 101,
-      MakeInstructionDescriptor(9, SpvOpReturn, 0));
+      MakeInstructionDescriptor(9, spv::Op::OpReturn, 0));
   TransformationAddSynonym transformation3(
       100, protobufs::TransformationAddSynonym::COPY_OBJECT, 102,
-      MakeInstructionDescriptor(9, SpvOpReturn, 0));
+      MakeInstructionDescriptor(9, spv::Op::OpReturn, 0));
 
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
@@ -1397,7 +1402,7 @@
   ASSERT_FALSE(
       TransformationAddSynonym(
           216, protobufs::TransformationAddSynonym::COPY_OBJECT, 500,
-          MakeInstructionDescriptor(217, SpvOpImageSampleImplicitLod, 0))
+          MakeInstructionDescriptor(217, spv::Op::OpImageSampleImplicitLod, 0))
           .IsApplicable(context.get(), transformation_context));
 }
 
@@ -1434,7 +1439,7 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   ASSERT_FALSE(TransformationAddSynonym(
                    8, protobufs::TransformationAddSynonym::COPY_OBJECT, 500,
-                   MakeInstructionDescriptor(8, SpvOpReturn, 0))
+                   MakeInstructionDescriptor(8, spv::Op::OpReturn, 0))
                    .IsApplicable(context.get(), transformation_context));
 }
 
@@ -1475,7 +1480,7 @@
 
   transformation_context.GetFactManager()->AddFactBlockIsDead(9);
 
-  auto insert_before = MakeInstructionDescriptor(9, SpvOpBranch, 0);
+  auto insert_before = MakeInstructionDescriptor(9, spv::Op::OpBranch, 0);
 
   ASSERT_FALSE(TransformationAddSynonym(
                    7, protobufs::TransformationAddSynonym::COPY_OBJECT, 100,
diff --git a/test/fuzz/transformation_add_type_array_test.cpp b/test/fuzz/transformation_add_type_array_test.cpp
index 2ef8200..ab480fb 100644
--- a/test/fuzz/transformation_add_type_array_test.cpp
+++ b/test/fuzz/transformation_add_type_array_test.cpp
@@ -99,7 +99,7 @@
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
-    ASSERT_EQ(SpvOpTypeArray,
+    ASSERT_EQ(spv::Op::OpTypeArray,
               context->get_def_use_mgr()->GetDef(100)->opcode());
     ASSERT_NE(nullptr, context->get_type_mgr()->GetType(100)->AsArray());
   }
@@ -113,7 +113,7 @@
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
-    ASSERT_EQ(SpvOpTypeArray,
+    ASSERT_EQ(spv::Op::OpTypeArray,
               context->get_def_use_mgr()->GetDef(100)->opcode());
     ASSERT_NE(nullptr, context->get_type_mgr()->GetType(100)->AsArray());
   }
diff --git a/test/fuzz/transformation_add_type_boolean_test.cpp b/test/fuzz/transformation_add_type_boolean_test.cpp
index a8e657b..388d4f6 100644
--- a/test/fuzz/transformation_add_type_boolean_test.cpp
+++ b/test/fuzz/transformation_add_type_boolean_test.cpp
@@ -57,7 +57,8 @@
   ASSERT_TRUE(
       add_type_bool.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(add_type_bool, context.get(), &transformation_context);
-  ASSERT_EQ(SpvOpTypeBool, context->get_def_use_mgr()->GetDef(100)->opcode());
+  ASSERT_EQ(spv::Op::OpTypeBool,
+            context->get_def_use_mgr()->GetDef(100)->opcode());
   ASSERT_NE(nullptr, context->get_type_mgr()->GetType(100)->AsBool());
   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
                                                kConsoleMessageConsumer));
diff --git a/test/fuzz/transformation_add_type_float_test.cpp b/test/fuzz/transformation_add_type_float_test.cpp
index 9275bec..75f3788 100644
--- a/test/fuzz/transformation_add_type_float_test.cpp
+++ b/test/fuzz/transformation_add_type_float_test.cpp
@@ -74,7 +74,7 @@
 
   // By default, SPIR-V does not support 64-bit float types.
   // Below we add such capability, so the test should now pass.
-  context.get()->get_feature_mgr()->AddCapability(SpvCapabilityFloat64);
+  context.get()->get_feature_mgr()->AddCapability(spv::Capability::Float64);
   ASSERT_TRUE(TransformationAddTypeFloat(7, 64).IsApplicable(
       context.get(), transformation_context));
 
@@ -120,7 +120,8 @@
   ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(6));
   ASSERT_EQ(nullptr, context->get_type_mgr()->GetType(6));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
-  ASSERT_EQ(SpvOpTypeFloat, context->get_def_use_mgr()->GetDef(6)->opcode());
+  ASSERT_EQ(spv::Op::OpTypeFloat,
+            context->get_def_use_mgr()->GetDef(6)->opcode());
   ASSERT_NE(nullptr, context->get_type_mgr()->GetType(6)->AsFloat());
 
   // Adds 32-bit float type.
@@ -128,7 +129,8 @@
   ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(7));
   ASSERT_EQ(nullptr, context->get_type_mgr()->GetType(7));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
-  ASSERT_EQ(SpvOpTypeFloat, context->get_def_use_mgr()->GetDef(7)->opcode());
+  ASSERT_EQ(spv::Op::OpTypeFloat,
+            context->get_def_use_mgr()->GetDef(7)->opcode());
   ASSERT_NE(nullptr, context->get_type_mgr()->GetType(7)->AsFloat());
 
   // Adds 64-bit float type.
@@ -136,7 +138,8 @@
   ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(8));
   ASSERT_EQ(nullptr, context->get_type_mgr()->GetType(8));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
-  ASSERT_EQ(SpvOpTypeFloat, context->get_def_use_mgr()->GetDef(8)->opcode());
+  ASSERT_EQ(spv::Op::OpTypeFloat,
+            context->get_def_use_mgr()->GetDef(8)->opcode());
   ASSERT_NE(nullptr, context->get_type_mgr()->GetType(8)->AsFloat());
 
   std::string variant_shader = R"(
diff --git a/test/fuzz/transformation_add_type_int_test.cpp b/test/fuzz/transformation_add_type_int_test.cpp
index 4cbfed0..b41d420 100644
--- a/test/fuzz/transformation_add_type_int_test.cpp
+++ b/test/fuzz/transformation_add_type_int_test.cpp
@@ -88,13 +88,13 @@
 
   // By default SPIR-V does not support 16-bit integers.
   // Below we add such capability, so the test should now be successful.
-  context.get()->get_feature_mgr()->AddCapability(SpvCapabilityInt16);
+  context.get()->get_feature_mgr()->AddCapability(spv::Capability::Int16);
   ASSERT_TRUE(TransformationAddTypeInt(7, 16, true)
                   .IsApplicable(context.get(), transformation_context));
 
   // By default SPIR-V does not support 64-bit integers.
   // Below we add such capability, so the test should now pass.
-  context.get()->get_feature_mgr()->AddCapability(SpvCapabilityInt64);
+  context.get()->get_feature_mgr()->AddCapability(spv::Capability::Int64);
   ASSERT_TRUE(TransformationAddTypeInt(7, 64, true)
                   .IsApplicable(context.get(), transformation_context));
 
@@ -147,7 +147,8 @@
   ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(6));
   ASSERT_EQ(nullptr, context->get_type_mgr()->GetType(6));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
-  ASSERT_EQ(SpvOpTypeInt, context->get_def_use_mgr()->GetDef(6)->opcode());
+  ASSERT_EQ(spv::Op::OpTypeInt,
+            context->get_def_use_mgr()->GetDef(6)->opcode());
   ASSERT_NE(nullptr, context->get_type_mgr()->GetType(6)->AsInteger());
 
   // Adds signed 16-bit integer type.
diff --git a/test/fuzz/transformation_add_type_matrix_test.cpp b/test/fuzz/transformation_add_type_matrix_test.cpp
index df0111e..9b10dbd 100644
--- a/test/fuzz/transformation_add_type_matrix_test.cpp
+++ b/test/fuzz/transformation_add_type_matrix_test.cpp
@@ -72,7 +72,7 @@
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
-    ASSERT_EQ(SpvOpTypeMatrix,
+    ASSERT_EQ(spv::Op::OpTypeMatrix,
               context->get_def_use_mgr()->GetDef(100)->opcode());
     ASSERT_NE(nullptr, context->get_type_mgr()->GetType(100)->AsMatrix());
   }
diff --git a/test/fuzz/transformation_add_type_pointer_test.cpp b/test/fuzz/transformation_add_type_pointer_test.cpp
index b9072e3..5e25f0e 100644
--- a/test/fuzz/transformation_add_type_pointer_test.cpp
+++ b/test/fuzz/transformation_add_type_pointer_test.cpp
@@ -103,28 +103,28 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   auto bad_type_id_does_not_exist =
-      TransformationAddTypePointer(100, SpvStorageClassFunction, 101);
+      TransformationAddTypePointer(100, spv::StorageClass::Function, 101);
   auto bad_type_id_is_not_type =
-      TransformationAddTypePointer(100, SpvStorageClassFunction, 23);
+      TransformationAddTypePointer(100, spv::StorageClass::Function, 23);
   auto bad_result_id_is_not_fresh =
-      TransformationAddTypePointer(17, SpvStorageClassFunction, 21);
+      TransformationAddTypePointer(17, spv::StorageClass::Function, 21);
 
   auto good_new_private_pointer_to_t =
-      TransformationAddTypePointer(101, SpvStorageClassPrivate, 7);
+      TransformationAddTypePointer(101, spv::StorageClass::Private, 7);
   auto good_new_uniform_pointer_to_t =
-      TransformationAddTypePointer(102, SpvStorageClassUniform, 7);
+      TransformationAddTypePointer(102, spv::StorageClass::Uniform, 7);
   auto good_another_function_pointer_to_s =
-      TransformationAddTypePointer(103, SpvStorageClassFunction, 8);
+      TransformationAddTypePointer(103, spv::StorageClass::Function, 8);
   auto good_new_uniform_pointer_to_s =
-      TransformationAddTypePointer(104, SpvStorageClassUniform, 8);
+      TransformationAddTypePointer(104, spv::StorageClass::Uniform, 8);
   auto good_another_private_pointer_to_float =
-      TransformationAddTypePointer(105, SpvStorageClassPrivate, 21);
+      TransformationAddTypePointer(105, spv::StorageClass::Private, 21);
   auto good_new_private_pointer_to_private_pointer_to_float =
-      TransformationAddTypePointer(106, SpvStorageClassPrivate, 105);
+      TransformationAddTypePointer(106, spv::StorageClass::Private, 105);
   auto good_new_uniform_pointer_to_vec2 =
-      TransformationAddTypePointer(107, SpvStorageClassUniform, 24);
+      TransformationAddTypePointer(107, spv::StorageClass::Uniform, 24);
   auto good_new_private_pointer_to_uniform_pointer_to_vec2 =
-      TransformationAddTypePointer(108, SpvStorageClassPrivate, 107);
+      TransformationAddTypePointer(108, spv::StorageClass::Private, 107);
 
   ASSERT_FALSE(bad_type_id_does_not_exist.IsApplicable(context.get(),
                                                        transformation_context));
@@ -143,7 +143,7 @@
                           &transformation_context);
     ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
         context.get(), validator_options, kConsoleMessageConsumer));
-    ASSERT_EQ(SpvOpTypePointer,
+    ASSERT_EQ(spv::Op::OpTypePointer,
               context->get_def_use_mgr()->GetDef(101)->opcode());
     ASSERT_NE(nullptr, context->get_type_mgr()->GetType(101)->AsPointer());
   }
diff --git a/test/fuzz/transformation_add_type_struct_test.cpp b/test/fuzz/transformation_add_type_struct_test.cpp
index 7fb91ab..1440b4a 100644
--- a/test/fuzz/transformation_add_type_struct_test.cpp
+++ b/test/fuzz/transformation_add_type_struct_test.cpp
@@ -72,7 +72,7 @@
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
-    ASSERT_EQ(SpvOpTypeStruct,
+    ASSERT_EQ(spv::Op::OpTypeStruct,
               context->get_def_use_mgr()->GetDef(100)->opcode());
     ASSERT_NE(nullptr, context->get_type_mgr()->GetType(100)->AsStruct());
   }
diff --git a/test/fuzz/transformation_add_type_vector_test.cpp b/test/fuzz/transformation_add_type_vector_test.cpp
index 755bc4a..b39c1c9 100644
--- a/test/fuzz/transformation_add_type_vector_test.cpp
+++ b/test/fuzz/transformation_add_type_vector_test.cpp
@@ -66,7 +66,7 @@
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
-    ASSERT_EQ(SpvOpTypeVector,
+    ASSERT_EQ(spv::Op::OpTypeVector,
               context->get_def_use_mgr()->GetDef(100)->opcode());
     ASSERT_NE(nullptr, context->get_type_mgr()->GetType(100)->AsVector());
   }
diff --git a/test/fuzz/transformation_adjust_branch_weights_test.cpp b/test/fuzz/transformation_adjust_branch_weights_test.cpp
index 5984a3e..2b532bf 100644
--- a/test/fuzz/transformation_adjust_branch_weights_test.cpp
+++ b/test/fuzz/transformation_adjust_branch_weights_test.cpp
@@ -108,7 +108,7 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // Tests OpBranchConditional instruction with weights.
   auto instruction_descriptor =
-      MakeInstructionDescriptor(33, SpvOpBranchConditional, 0);
+      MakeInstructionDescriptor(33, spv::Op::OpBranchConditional, 0);
   auto transformation =
       TransformationAdjustBranchWeights(instruction_descriptor, {0, 1});
   ASSERT_TRUE(
@@ -116,7 +116,7 @@
 
   // Tests the two branch weights equal to 0.
   instruction_descriptor =
-      MakeInstructionDescriptor(33, SpvOpBranchConditional, 0);
+      MakeInstructionDescriptor(33, spv::Op::OpBranchConditional, 0);
   transformation =
       TransformationAdjustBranchWeights(instruction_descriptor, {0, 0});
 #ifndef NDEBUG
@@ -127,14 +127,14 @@
 
   // Tests 32-bit unsigned integer overflow.
   instruction_descriptor =
-      MakeInstructionDescriptor(33, SpvOpBranchConditional, 0);
+      MakeInstructionDescriptor(33, spv::Op::OpBranchConditional, 0);
   transformation = TransformationAdjustBranchWeights(instruction_descriptor,
                                                      {UINT32_MAX, 0});
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   instruction_descriptor =
-      MakeInstructionDescriptor(33, SpvOpBranchConditional, 0);
+      MakeInstructionDescriptor(33, spv::Op::OpBranchConditional, 0);
   transformation = TransformationAdjustBranchWeights(instruction_descriptor,
                                                      {1, UINT32_MAX});
 #ifndef NDEBUG
@@ -145,26 +145,26 @@
 
   // Tests OpBranchConditional instruction with no weights.
   instruction_descriptor =
-      MakeInstructionDescriptor(21, SpvOpBranchConditional, 0);
+      MakeInstructionDescriptor(21, spv::Op::OpBranchConditional, 0);
   transformation =
       TransformationAdjustBranchWeights(instruction_descriptor, {0, 1});
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   // Tests non-OpBranchConditional instructions.
-  instruction_descriptor = MakeInstructionDescriptor(2, SpvOpTypeVoid, 0);
+  instruction_descriptor = MakeInstructionDescriptor(2, spv::Op::OpTypeVoid, 0);
   transformation =
       TransformationAdjustBranchWeights(instruction_descriptor, {5, 6});
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instruction_descriptor = MakeInstructionDescriptor(20, SpvOpLabel, 0);
+  instruction_descriptor = MakeInstructionDescriptor(20, spv::Op::OpLabel, 0);
   transformation =
       TransformationAdjustBranchWeights(instruction_descriptor, {1, 2});
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instruction_descriptor = MakeInstructionDescriptor(49, SpvOpIAdd, 0);
+  instruction_descriptor = MakeInstructionDescriptor(49, spv::Op::OpIAdd, 0);
   transformation =
       TransformationAdjustBranchWeights(instruction_descriptor, {1, 2});
   ASSERT_FALSE(
@@ -255,13 +255,13 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   auto instruction_descriptor =
-      MakeInstructionDescriptor(33, SpvOpBranchConditional, 0);
+      MakeInstructionDescriptor(33, spv::Op::OpBranchConditional, 0);
   auto transformation =
       TransformationAdjustBranchWeights(instruction_descriptor, {5, 6});
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instruction_descriptor =
-      MakeInstructionDescriptor(21, SpvOpBranchConditional, 0);
+      MakeInstructionDescriptor(21, spv::Op::OpBranchConditional, 0);
   transformation =
       TransformationAdjustBranchWeights(instruction_descriptor, {7, 8});
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
diff --git a/test/fuzz/transformation_composite_construct_test.cpp b/test/fuzz/transformation_composite_construct_test.cpp
index 3c5f731..c4eef87 100644
--- a/test/fuzz/transformation_composite_construct_test.cpp
+++ b/test/fuzz/transformation_composite_construct_test.cpp
@@ -136,16 +136,17 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // Make a vec2[3]
   TransformationCompositeConstruct make_vec2_array_length_3(
-      37, {41, 45, 27}, MakeInstructionDescriptor(46, SpvOpAccessChain, 0),
-      200);
+      37, {41, 45, 27},
+      MakeInstructionDescriptor(46, spv::Op::OpAccessChain, 0), 200);
   // Bad: there are too many components
   TransformationCompositeConstruct make_vec2_array_length_3_bad(
-      37, {41, 45, 27, 27}, MakeInstructionDescriptor(46, SpvOpAccessChain, 0),
-      200);
+      37, {41, 45, 27, 27},
+      MakeInstructionDescriptor(46, spv::Op::OpAccessChain, 0), 200);
   // The first component does not correspond to an instruction with a result
   // type so this check should return false.
   TransformationCompositeConstruct make_vec2_array_length_3_nores(
-      37, {2, 45, 27}, MakeInstructionDescriptor(46, SpvOpAccessChain, 0), 200);
+      37, {2, 45, 27}, MakeInstructionDescriptor(46, spv::Op::OpAccessChain, 0),
+      200);
   ASSERT_TRUE(make_vec2_array_length_3.IsApplicable(context.get(),
                                                     transformation_context));
   ASSERT_FALSE(make_vec2_array_length_3_bad.IsApplicable(
@@ -159,7 +160,7 @@
   uint32_t num_uses_of_27_before = context->get_def_use_mgr()->NumUses(27);
   ApplyAndCheckFreshIds(make_vec2_array_length_3, context.get(),
                         &transformation_context);
-  ASSERT_EQ(SpvOpCompositeConstruct,
+  ASSERT_EQ(spv::Op::OpCompositeConstruct,
             context->get_def_use_mgr()->GetDef(200)->opcode());
   ASSERT_EQ(34, context->get_instr_block(200)->id());
   ASSERT_EQ(num_uses_of_41_before + 1, context->get_def_use_mgr()->NumUses(41));
@@ -176,10 +177,10 @@
 
   // Make a float[2]
   TransformationCompositeConstruct make_float_array_length_2(
-      9, {24, 40}, MakeInstructionDescriptor(71, SpvOpStore, 0), 201);
+      9, {24, 40}, MakeInstructionDescriptor(71, spv::Op::OpStore, 0), 201);
   // Bad: %41 does not have type float
   TransformationCompositeConstruct make_float_array_length_2_bad(
-      9, {41, 40}, MakeInstructionDescriptor(71, SpvOpStore, 0), 201);
+      9, {41, 40}, MakeInstructionDescriptor(71, spv::Op::OpStore, 0), 201);
   ASSERT_TRUE(make_float_array_length_2.IsApplicable(context.get(),
                                                      transformation_context));
   ASSERT_FALSE(make_float_array_length_2_bad.IsApplicable(
@@ -195,12 +196,12 @@
 
   // Make a bool[3]
   TransformationCompositeConstruct make_bool_array_length_3(
-      47, {33, 50, 50}, MakeInstructionDescriptor(33, SpvOpSelectionMerge, 0),
-      202);
+      47, {33, 50, 50},
+      MakeInstructionDescriptor(33, spv::Op::OpSelectionMerge, 0), 202);
   // Bad: %54 is not available at the desired program point.
   TransformationCompositeConstruct make_bool_array_length_3_bad(
-      47, {33, 54, 50}, MakeInstructionDescriptor(33, SpvOpSelectionMerge, 0),
-      202);
+      47, {33, 54, 50},
+      MakeInstructionDescriptor(33, spv::Op::OpSelectionMerge, 0), 202);
   ASSERT_TRUE(make_bool_array_length_3.IsApplicable(context.get(),
                                                     transformation_context));
   ASSERT_FALSE(make_bool_array_length_3_bad.IsApplicable(
@@ -218,10 +219,10 @@
 
   // make a uvec3[2][2]
   TransformationCompositeConstruct make_uvec3_array_length_2_2(
-      58, {69, 100}, MakeInstructionDescriptor(64, SpvOpStore, 0), 203);
+      58, {69, 100}, MakeInstructionDescriptor(64, spv::Op::OpStore, 0), 203);
   // Bad: Skip count 100 is too large.
   TransformationCompositeConstruct make_uvec3_array_length_2_2_bad(
-      58, {33, 54}, MakeInstructionDescriptor(64, SpvOpStore, 100), 203);
+      58, {33, 54}, MakeInstructionDescriptor(64, spv::Op::OpStore, 100), 203);
   ASSERT_TRUE(make_uvec3_array_length_2_2.IsApplicable(context.get(),
                                                        transformation_context));
   ASSERT_FALSE(make_uvec3_array_length_2_2_bad.IsApplicable(
@@ -425,14 +426,17 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // make a mat3x4
   TransformationCompositeConstruct make_mat34(
-      32, {25, 28, 31}, MakeInstructionDescriptor(31, SpvOpReturn, 0), 200);
+      32, {25, 28, 31}, MakeInstructionDescriptor(31, spv::Op::OpReturn, 0),
+      200);
   // Bad: %35 is mat4x3, not mat3x4.
   TransformationCompositeConstruct make_mat34_bad(
-      35, {25, 28, 31}, MakeInstructionDescriptor(31, SpvOpReturn, 0), 200);
+      35, {25, 28, 31}, MakeInstructionDescriptor(31, spv::Op::OpReturn, 0),
+      200);
   // The first component does not correspond to an instruction with a result
   // type so this check should return false.
   TransformationCompositeConstruct make_mat34_nores(
-      32, {2, 28, 31}, MakeInstructionDescriptor(31, SpvOpReturn, 0), 200);
+      32, {2, 28, 31}, MakeInstructionDescriptor(31, spv::Op::OpReturn, 0),
+      200);
   ASSERT_TRUE(make_mat34.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_mat34_bad.IsApplicable(context.get(), transformation_context));
@@ -450,10 +454,12 @@
 
   // make a mat4x3
   TransformationCompositeConstruct make_mat43(
-      35, {11, 13, 16, 100}, MakeInstructionDescriptor(31, SpvOpStore, 0), 201);
+      35, {11, 13, 16, 100}, MakeInstructionDescriptor(31, spv::Op::OpStore, 0),
+      201);
   // Bad: %25 does not match the matrix's column type.
   TransformationCompositeConstruct make_mat43_bad(
-      35, {25, 13, 16, 100}, MakeInstructionDescriptor(31, SpvOpStore, 0), 201);
+      35, {25, 13, 16, 100}, MakeInstructionDescriptor(31, spv::Op::OpStore, 0),
+      201);
   ASSERT_TRUE(make_mat43.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_mat43_bad.IsApplicable(context.get(), transformation_context));
@@ -644,14 +650,16 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // make an Inner
   TransformationCompositeConstruct make_inner(
-      9, {25, 19}, MakeInstructionDescriptor(57, SpvOpAccessChain, 0), 200);
+      9, {25, 19}, MakeInstructionDescriptor(57, spv::Op::OpAccessChain, 0),
+      200);
   // Bad: Too few fields to make the struct.
   TransformationCompositeConstruct make_inner_bad(
-      9, {25}, MakeInstructionDescriptor(57, SpvOpAccessChain, 0), 200);
+      9, {25}, MakeInstructionDescriptor(57, spv::Op::OpAccessChain, 0), 200);
   // The first component does not correspond to an instruction with a result
   // type so this check should return false.
   TransformationCompositeConstruct make_inner_nores(
-      9, {2, 19}, MakeInstructionDescriptor(57, SpvOpAccessChain, 0), 200);
+      9, {2, 19}, MakeInstructionDescriptor(57, spv::Op::OpAccessChain, 0),
+      200);
   ASSERT_TRUE(make_inner.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_inner_bad.IsApplicable(context.get(), transformation_context));
@@ -667,12 +675,12 @@
 
   // make an Outer
   TransformationCompositeConstruct make_outer(
-      33, {46, 200, 56}, MakeInstructionDescriptor(200, SpvOpAccessChain, 0),
-      201);
+      33, {46, 200, 56},
+      MakeInstructionDescriptor(200, spv::Op::OpAccessChain, 0), 201);
   // Bad: %200 is not available at the desired program point.
   TransformationCompositeConstruct make_outer_bad(
       33, {46, 200, 56},
-      MakeInstructionDescriptor(200, SpvOpCompositeConstruct, 0), 201);
+      MakeInstructionDescriptor(200, spv::Op::OpCompositeConstruct, 0), 201);
   ASSERT_TRUE(make_outer.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_outer_bad.IsApplicable(context.get(), transformation_context));
@@ -973,10 +981,10 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   TransformationCompositeConstruct make_vec2(
-      7, {17, 11}, MakeInstructionDescriptor(100, SpvOpStore, 0), 200);
+      7, {17, 11}, MakeInstructionDescriptor(100, spv::Op::OpStore, 0), 200);
   // Bad: not enough data for a vec2
   TransformationCompositeConstruct make_vec2_bad(
-      7, {11}, MakeInstructionDescriptor(100, SpvOpStore, 0), 200);
+      7, {11}, MakeInstructionDescriptor(100, spv::Op::OpStore, 0), 200);
   ASSERT_TRUE(make_vec2.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_vec2_bad.IsApplicable(context.get(), transformation_context));
@@ -989,12 +997,12 @@
       MakeDataDescriptor(11, {}), MakeDataDescriptor(200, {1})));
 
   TransformationCompositeConstruct make_vec3(
-      25, {12, 32}, MakeInstructionDescriptor(35, SpvOpCompositeConstruct, 0),
-      201);
+      25, {12, 32},
+      MakeInstructionDescriptor(35, spv::Op::OpCompositeConstruct, 0), 201);
   // Bad: too much data for a vec3
   TransformationCompositeConstruct make_vec3_bad(
       25, {12, 32, 32},
-      MakeInstructionDescriptor(35, SpvOpCompositeConstruct, 0), 201);
+      MakeInstructionDescriptor(35, spv::Op::OpCompositeConstruct, 0), 201);
   ASSERT_TRUE(make_vec3.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_vec3_bad.IsApplicable(context.get(), transformation_context));
@@ -1009,12 +1017,12 @@
       MakeDataDescriptor(32, {}), MakeDataDescriptor(201, {2})));
 
   TransformationCompositeConstruct make_vec4(
-      44, {32, 32, 10, 11}, MakeInstructionDescriptor(75, SpvOpAccessChain, 0),
-      202);
+      44, {32, 32, 10, 11},
+      MakeInstructionDescriptor(75, spv::Op::OpAccessChain, 0), 202);
   // Bad: id 48 is not available at the insertion points
   TransformationCompositeConstruct make_vec4_bad(
-      44, {48, 32, 10, 11}, MakeInstructionDescriptor(75, SpvOpAccessChain, 0),
-      202);
+      44, {48, 32, 10, 11},
+      MakeInstructionDescriptor(75, spv::Op::OpAccessChain, 0), 202);
   ASSERT_TRUE(make_vec4.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_vec4_bad.IsApplicable(context.get(), transformation_context));
@@ -1031,10 +1039,10 @@
       MakeDataDescriptor(11, {}), MakeDataDescriptor(202, {3})));
 
   TransformationCompositeConstruct make_ivec2(
-      51, {126, 120}, MakeInstructionDescriptor(128, SpvOpLoad, 0), 203);
+      51, {126, 120}, MakeInstructionDescriptor(128, spv::Op::OpLoad, 0), 203);
   // Bad: if 128 is not available at the instruction that defines 128
   TransformationCompositeConstruct make_ivec2_bad(
-      51, {128, 120}, MakeInstructionDescriptor(128, SpvOpLoad, 0), 203);
+      51, {128, 120}, MakeInstructionDescriptor(128, spv::Op::OpLoad, 0), 203);
   ASSERT_TRUE(make_ivec2.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_ivec2_bad.IsApplicable(context.get(), transformation_context));
@@ -1047,12 +1055,12 @@
       MakeDataDescriptor(120, {}), MakeDataDescriptor(203, {1})));
 
   TransformationCompositeConstruct make_ivec3(
-      114, {56, 117, 56}, MakeInstructionDescriptor(66, SpvOpAccessChain, 0),
-      204);
+      114, {56, 117, 56},
+      MakeInstructionDescriptor(66, spv::Op::OpAccessChain, 0), 204);
   // Bad because 1300 is not an id
   TransformationCompositeConstruct make_ivec3_bad(
-      114, {56, 117, 1300}, MakeInstructionDescriptor(66, SpvOpAccessChain, 0),
-      204);
+      114, {56, 117, 1300},
+      MakeInstructionDescriptor(66, spv::Op::OpAccessChain, 0), 204);
   ASSERT_TRUE(make_ivec3.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_ivec3_bad.IsApplicable(context.get(), transformation_context));
@@ -1067,12 +1075,12 @@
       MakeDataDescriptor(56, {}), MakeDataDescriptor(204, {2})));
 
   TransformationCompositeConstruct make_ivec4(
-      122, {56, 117, 117, 117}, MakeInstructionDescriptor(66, SpvOpIAdd, 0),
-      205);
+      122, {56, 117, 117, 117},
+      MakeInstructionDescriptor(66, spv::Op::OpIAdd, 0), 205);
   // Bad because 86 is the wrong type.
   TransformationCompositeConstruct make_ivec4_bad(
-      86, {56, 117, 117, 117}, MakeInstructionDescriptor(66, SpvOpIAdd, 0),
-      205);
+      86, {56, 117, 117, 117},
+      MakeInstructionDescriptor(66, spv::Op::OpIAdd, 0), 205);
   ASSERT_TRUE(make_ivec4.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_ivec4_bad.IsApplicable(context.get(), transformation_context));
@@ -1089,9 +1097,11 @@
       MakeDataDescriptor(117, {}), MakeDataDescriptor(205, {3})));
 
   TransformationCompositeConstruct make_uvec2(
-      86, {18, 38}, MakeInstructionDescriptor(133, SpvOpAccessChain, 0), 206);
+      86, {18, 38}, MakeInstructionDescriptor(133, spv::Op::OpAccessChain, 0),
+      206);
   TransformationCompositeConstruct make_uvec2_bad(
-      86, {18, 38}, MakeInstructionDescriptor(133, SpvOpAccessChain, 200), 206);
+      86, {18, 38}, MakeInstructionDescriptor(133, spv::Op::OpAccessChain, 200),
+      206);
   ASSERT_TRUE(make_uvec2.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_uvec2_bad.IsApplicable(context.get(), transformation_context));
@@ -1104,10 +1114,12 @@
       MakeDataDescriptor(38, {}), MakeDataDescriptor(206, {1})));
 
   TransformationCompositeConstruct make_uvec3(
-      59, {14, 18, 136}, MakeInstructionDescriptor(137, SpvOpReturn, 0), 207);
+      59, {14, 18, 136}, MakeInstructionDescriptor(137, spv::Op::OpReturn, 0),
+      207);
   // Bad because 1300 is not an id
   TransformationCompositeConstruct make_uvec3_bad(
-      59, {14, 18, 1300}, MakeInstructionDescriptor(137, SpvOpReturn, 0), 207);
+      59, {14, 18, 1300}, MakeInstructionDescriptor(137, spv::Op::OpReturn, 0),
+      207);
   ASSERT_TRUE(make_uvec3.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_uvec3_bad.IsApplicable(context.get(), transformation_context));
@@ -1123,11 +1135,11 @@
 
   TransformationCompositeConstruct make_uvec4(
       131, {14, 18, 136, 136},
-      MakeInstructionDescriptor(137, SpvOpAccessChain, 0), 208);
+      MakeInstructionDescriptor(137, spv::Op::OpAccessChain, 0), 208);
   // Bad because 86 is the wrong type.
   TransformationCompositeConstruct make_uvec4_bad(
       86, {14, 18, 136, 136},
-      MakeInstructionDescriptor(137, SpvOpAccessChain, 0), 208);
+      MakeInstructionDescriptor(137, spv::Op::OpAccessChain, 0), 208);
   ASSERT_TRUE(make_uvec4.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_uvec4_bad.IsApplicable(context.get(), transformation_context));
@@ -1149,7 +1161,7 @@
           111,
           41,
       },
-      MakeInstructionDescriptor(75, SpvOpAccessChain, 0), 209);
+      MakeInstructionDescriptor(75, spv::Op::OpAccessChain, 0), 209);
   // Bad because 0 is not a valid base instruction id
   TransformationCompositeConstruct make_bvec2_bad(
       102,
@@ -1157,7 +1169,7 @@
           111,
           41,
       },
-      MakeInstructionDescriptor(0, SpvOpExtInstImport, 0), 209);
+      MakeInstructionDescriptor(0, spv::Op::OpExtInstImport, 0), 209);
   ASSERT_TRUE(make_bvec2.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_bvec2_bad.IsApplicable(context.get(), transformation_context));
@@ -1170,10 +1182,10 @@
       MakeDataDescriptor(41, {}), MakeDataDescriptor(209, {1})));
 
   TransformationCompositeConstruct make_bvec3(
-      93, {108, 73}, MakeInstructionDescriptor(108, SpvOpStore, 0), 210);
+      93, {108, 73}, MakeInstructionDescriptor(108, spv::Op::OpStore, 0), 210);
   // Bad because there are too many components for a bvec3
   TransformationCompositeConstruct make_bvec3_bad(
-      93, {108, 108}, MakeInstructionDescriptor(108, SpvOpStore, 0), 210);
+      93, {108, 108}, MakeInstructionDescriptor(108, spv::Op::OpStore, 0), 210);
   ASSERT_TRUE(make_bvec3.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_bvec3_bad.IsApplicable(context.get(), transformation_context));
@@ -1188,10 +1200,11 @@
       MakeDataDescriptor(73, {}), MakeDataDescriptor(210, {2})));
 
   TransformationCompositeConstruct make_bvec4(
-      70, {108, 108}, MakeInstructionDescriptor(108, SpvOpBranch, 0), 211);
+      70, {108, 108}, MakeInstructionDescriptor(108, spv::Op::OpBranch, 0),
+      211);
   // Bad because 21 is a type, not a result id
   TransformationCompositeConstruct make_bvec4_bad(
-      70, {21, 108}, MakeInstructionDescriptor(108, SpvOpBranch, 0), 211);
+      70, {21, 108}, MakeInstructionDescriptor(108, spv::Op::OpBranch, 0), 211);
   ASSERT_TRUE(make_bvec4.IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       make_bvec4_bad.IsApplicable(context.get(), transformation_context));
@@ -1477,7 +1490,8 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   TransformationCompositeConstruct transformation(
-      32, {25, 28, 31}, MakeInstructionDescriptor(31, SpvOpReturn, 0), 200);
+      32, {25, 28, 31}, MakeInstructionDescriptor(31, spv::Op::OpReturn, 0),
+      200);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
@@ -1562,7 +1576,8 @@
   transformation_context.GetFactManager()->AddFactIdIsIrrelevant(25);
 
   TransformationCompositeConstruct transformation(
-      32, {25, 28, 31}, MakeInstructionDescriptor(31, SpvOpReturn, 0), 200);
+      32, {25, 28, 31}, MakeInstructionDescriptor(31, spv::Op::OpReturn, 0),
+      200);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
@@ -1618,7 +1633,7 @@
   transformation_context.GetFactManager()->AddFactBlockIsDead(15);
 
   TransformationCompositeConstruct transformation(
-      7, {10, 11}, MakeInstructionDescriptor(15, SpvOpBranch, 0), 100);
+      7, {10, 11}, MakeInstructionDescriptor(15, spv::Op::OpBranch, 0), 100);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
@@ -1660,7 +1675,7 @@
   transformation_context.GetFactManager()->AddFactIdIsIrrelevant(8);
 
   TransformationCompositeConstruct transformation(
-      7, {8, 9, 10}, MakeInstructionDescriptor(5, SpvOpReturn, 0), 100);
+      7, {8, 9, 10}, MakeInstructionDescriptor(5, spv::Op::OpReturn, 0), 100);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
@@ -1707,7 +1722,7 @@
   transformation_context.GetFactManager()->AddFactIdIsIrrelevant(10);
 
   TransformationCompositeConstruct transformation(
-      8, {10, 9}, MakeInstructionDescriptor(5, SpvOpReturn, 0), 100);
+      8, {10, 9}, MakeInstructionDescriptor(5, spv::Op::OpReturn, 0), 100);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
diff --git a/test/fuzz/transformation_composite_extract_test.cpp b/test/fuzz/transformation_composite_extract_test.cpp
index 1df5591..d468e41 100644
--- a/test/fuzz/transformation_composite_extract_test.cpp
+++ b/test/fuzz/transformation_composite_extract_test.cpp
@@ -102,47 +102,49 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   // Instruction does not exist.
-  ASSERT_FALSE(TransformationCompositeExtract(
-                   MakeInstructionDescriptor(36, SpvOpIAdd, 0), 200, 101, {0})
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationCompositeExtract(
+          MakeInstructionDescriptor(36, spv::Op::OpIAdd, 0), 200, 101, {0})
+          .IsApplicable(context.get(), transformation_context));
 
   // Id for composite is not a composite.
   ASSERT_FALSE(
       TransformationCompositeExtract(
-          MakeInstructionDescriptor(37, SpvOpAccessChain, 0), 200, 32, {})
+          MakeInstructionDescriptor(37, spv::Op::OpAccessChain, 0), 200, 32, {})
           .IsApplicable(context.get(), transformation_context));
 
   // Composite does not dominate instruction being inserted before.
-  ASSERT_FALSE(
-      TransformationCompositeExtract(
-          MakeInstructionDescriptor(37, SpvOpAccessChain, 0), 200, 101, {0})
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationCompositeExtract(
+                   MakeInstructionDescriptor(37, spv::Op::OpAccessChain, 0),
+                   200, 101, {0})
+                   .IsApplicable(context.get(), transformation_context));
 
   // Too many indices for extraction from struct composite.
-  ASSERT_FALSE(
-      TransformationCompositeExtract(
-          MakeInstructionDescriptor(24, SpvOpAccessChain, 0), 200, 101, {0, 0})
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationCompositeExtract(
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0),
+                   200, 101, {0, 0})
+                   .IsApplicable(context.get(), transformation_context));
 
   // Too many indices for extraction from struct composite.
-  ASSERT_FALSE(
-      TransformationCompositeExtract(
-          MakeInstructionDescriptor(13, SpvOpIEqual, 0), 200, 104, {0, 0, 0})
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationCompositeExtract(
+                   MakeInstructionDescriptor(13, spv::Op::OpIEqual, 0), 200,
+                   104, {0, 0, 0})
+                   .IsApplicable(context.get(), transformation_context));
 
   // Out of bounds index for extraction from struct composite.
   ASSERT_FALSE(
       TransformationCompositeExtract(
-          MakeInstructionDescriptor(13, SpvOpIEqual, 0), 200, 104, {0, 3})
+          MakeInstructionDescriptor(13, spv::Op::OpIEqual, 0), 200, 104, {0, 3})
           .IsApplicable(context.get(), transformation_context));
 
   // Result id already used.
-  ASSERT_FALSE(TransformationCompositeExtract(
-                   MakeInstructionDescriptor(35, SpvOpFAdd, 0), 80, 103, {0})
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationCompositeExtract(
+          MakeInstructionDescriptor(35, spv::Op::OpFAdd, 0), 80, 103, {0})
+          .IsApplicable(context.get(), transformation_context));
 
   TransformationCompositeExtract transformation_1(
-      MakeInstructionDescriptor(36, SpvOpConvertFToS, 0), 201, 100, {2});
+      MakeInstructionDescriptor(36, spv::Op::OpConvertFToS, 0), 201, 100, {2});
   ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(201));
   ASSERT_EQ(nullptr, context->get_instr_block(201));
   uint32_t num_uses_of_100_before = context->get_def_use_mgr()->NumUses(100);
@@ -150,7 +152,7 @@
       transformation_1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation_1, context.get(),
                         &transformation_context);
-  ASSERT_EQ(SpvOpCompositeExtract,
+  ASSERT_EQ(spv::Op::OpCompositeExtract,
             context->get_def_use_mgr()->GetDef(201)->opcode());
   ASSERT_EQ(15, context->get_instr_block(201)->id());
   ASSERT_EQ(num_uses_of_100_before + 1,
@@ -159,7 +161,8 @@
                                                kConsoleMessageConsumer));
 
   TransformationCompositeExtract transformation_2(
-      MakeInstructionDescriptor(37, SpvOpAccessChain, 0), 202, 104, {0, 2});
+      MakeInstructionDescriptor(37, spv::Op::OpAccessChain, 0), 202, 104,
+      {0, 2});
   ASSERT_TRUE(
       transformation_2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation_2, context.get(),
@@ -168,7 +171,7 @@
                                                kConsoleMessageConsumer));
 
   TransformationCompositeExtract transformation_3(
-      MakeInstructionDescriptor(29, SpvOpAccessChain, 0), 203, 104, {0});
+      MakeInstructionDescriptor(29, spv::Op::OpAccessChain, 0), 203, 104, {0});
   ASSERT_TRUE(
       transformation_3.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation_3, context.get(),
@@ -177,7 +180,7 @@
                                                kConsoleMessageConsumer));
 
   TransformationCompositeExtract transformation_4(
-      MakeInstructionDescriptor(24, SpvOpStore, 0), 204, 101, {0});
+      MakeInstructionDescriptor(24, spv::Op::OpStore, 0), 204, 101, {0});
   ASSERT_TRUE(
       transformation_4.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation_4, context.get(),
@@ -186,7 +189,7 @@
                                                kConsoleMessageConsumer));
 
   TransformationCompositeExtract transformation_5(
-      MakeInstructionDescriptor(29, SpvOpBranch, 0), 205, 102, {2});
+      MakeInstructionDescriptor(29, spv::Op::OpBranch, 0), 205, 102, {2});
   ASSERT_TRUE(
       transformation_5.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation_5, context.get(),
@@ -195,7 +198,7 @@
                                                kConsoleMessageConsumer));
 
   TransformationCompositeExtract transformation_6(
-      MakeInstructionDescriptor(37, SpvOpReturn, 0), 206, 103, {1});
+      MakeInstructionDescriptor(37, spv::Op::OpReturn, 0), 206, 103, {1});
   ASSERT_TRUE(
       transformation_6.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation_6, context.get(),
@@ -378,45 +381,50 @@
   // Cannot insert before the OpVariables of a function.
   ASSERT_FALSE(
       TransformationCompositeExtract(
-          MakeInstructionDescriptor(101, SpvOpVariable, 0), 200, 14, {0})
+          MakeInstructionDescriptor(101, spv::Op::OpVariable, 0), 200, 14, {0})
           .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationCompositeExtract(
-          MakeInstructionDescriptor(101, SpvOpVariable, 1), 200, 14, {1})
+          MakeInstructionDescriptor(101, spv::Op::OpVariable, 1), 200, 14, {1})
           .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationCompositeExtract(
-          MakeInstructionDescriptor(102, SpvOpVariable, 0), 200, 14, {1})
+          MakeInstructionDescriptor(102, spv::Op::OpVariable, 0), 200, 14, {1})
           .IsApplicable(context.get(), transformation_context));
   // OK to insert right after the OpVariables.
-  ASSERT_FALSE(TransformationCompositeExtract(
-                   MakeInstructionDescriptor(102, SpvOpBranch, 1), 200, 14, {1})
-                   .IsApplicable(context.get(), transformation_context));
-
-  // Cannot insert before the OpPhis of a block.
-  ASSERT_FALSE(TransformationCompositeExtract(
-                   MakeInstructionDescriptor(60, SpvOpPhi, 0), 200, 14, {2})
-                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(TransformationCompositeExtract(
-                   MakeInstructionDescriptor(59, SpvOpPhi, 0), 200, 14, {3})
-                   .IsApplicable(context.get(), transformation_context));
-  // OK to insert after the OpPhis.
-  ASSERT_TRUE(
+  ASSERT_FALSE(
       TransformationCompositeExtract(
-          MakeInstructionDescriptor(59, SpvOpAccessChain, 0), 200, 14, {3})
+          MakeInstructionDescriptor(102, spv::Op::OpBranch, 1), 200, 14, {1})
           .IsApplicable(context.get(), transformation_context));
 
+  // Cannot insert before the OpPhis of a block.
+  ASSERT_FALSE(
+      TransformationCompositeExtract(
+          MakeInstructionDescriptor(60, spv::Op::OpPhi, 0), 200, 14, {2})
+          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationCompositeExtract(
+          MakeInstructionDescriptor(59, spv::Op::OpPhi, 0), 200, 14, {3})
+          .IsApplicable(context.get(), transformation_context));
+  // OK to insert after the OpPhis.
+  ASSERT_TRUE(TransformationCompositeExtract(
+                  MakeInstructionDescriptor(59, spv::Op::OpAccessChain, 0), 200,
+                  14, {3})
+                  .IsApplicable(context.get(), transformation_context));
+
   // Cannot insert before OpLoopMerge
-  ASSERT_FALSE(TransformationCompositeExtract(
-                   MakeInstructionDescriptor(33, SpvOpBranchConditional, 0),
-                   200, 14, {3})
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationCompositeExtract(
+          MakeInstructionDescriptor(33, spv::Op::OpBranchConditional, 0), 200,
+          14, {3})
+          .IsApplicable(context.get(), transformation_context));
 
   // Cannot insert before OpSelectionMerge
-  ASSERT_FALSE(TransformationCompositeExtract(
-                   MakeInstructionDescriptor(21, SpvOpBranchConditional, 0),
-                   200, 14, {2})
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationCompositeExtract(
+          MakeInstructionDescriptor(21, spv::Op::OpBranchConditional, 0), 200,
+          14, {2})
+          .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationCompositeExtractTest, AddSynonymsForRelevantIds) {
@@ -498,7 +506,7 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   TransformationCompositeExtract transformation(
-      MakeInstructionDescriptor(36, SpvOpConvertFToS, 0), 201, 100, {2});
+      MakeInstructionDescriptor(36, spv::Op::OpConvertFToS, 0), 201, 100, {2});
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
@@ -586,7 +594,7 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   transformation_context.GetFactManager()->AddFactIdIsIrrelevant(100);
   TransformationCompositeExtract transformation(
-      MakeInstructionDescriptor(36, SpvOpConvertFToS, 0), 201, 100, {2});
+      MakeInstructionDescriptor(36, spv::Op::OpConvertFToS, 0), 201, 100, {2});
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
@@ -635,7 +643,7 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   transformation_context.GetFactManager()->AddFactBlockIsDead(15);
   TransformationCompositeExtract transformation(
-      MakeInstructionDescriptor(15, SpvOpBranch, 0), 100, 12, {0});
+      MakeInstructionDescriptor(15, spv::Op::OpBranch, 0), 100, 12, {0});
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
diff --git a/test/fuzz/transformation_composite_insert_test.cpp b/test/fuzz/transformation_composite_insert_test.cpp
index 3b6f34d..e61c0fa 100644
--- a/test/fuzz/transformation_composite_insert_test.cpp
+++ b/test/fuzz/transformation_composite_insert_test.cpp
@@ -103,65 +103,69 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // Bad: |fresh_id| is not fresh.
   auto transformation_bad_1 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(29, SpvOpStore, 0), 20, 29, 11, {1, 0, 0});
+      MakeInstructionDescriptor(29, spv::Op::OpStore, 0), 20, 29, 11,
+      {1, 0, 0});
   ASSERT_FALSE(
       transformation_bad_1.IsApplicable(context.get(), transformation_context));
 
   // Bad: |composite_id| does not refer to a existing instruction.
   auto transformation_bad_2 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(29, SpvOpStore, 0), 50, 40, 11, {1, 0, 0});
+      MakeInstructionDescriptor(29, spv::Op::OpStore, 0), 50, 40, 11,
+      {1, 0, 0});
   ASSERT_FALSE(
       transformation_bad_2.IsApplicable(context.get(), transformation_context));
 
   // Bad: |composite_id| does not refer to a composite value.
   auto transformation_bad_3 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(29, SpvOpStore, 0), 50, 9, 11, {1, 0, 0});
+      MakeInstructionDescriptor(29, spv::Op::OpStore, 0), 50, 9, 11, {1, 0, 0});
   ASSERT_FALSE(
       transformation_bad_3.IsApplicable(context.get(), transformation_context));
 
   // Bad: |object_id| does not refer to a defined instruction.
   auto transformation_bad_4 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(29, SpvOpStore, 0), 50, 29, 40, {1, 0, 0});
+      MakeInstructionDescriptor(29, spv::Op::OpStore, 0), 50, 29, 40,
+      {1, 0, 0});
   ASSERT_FALSE(
       transformation_bad_4.IsApplicable(context.get(), transformation_context));
 
   // Bad: |object_id| cannot refer to a pointer.
   auto transformation_bad_5 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(29, SpvOpStore, 0), 50, 29, 8, {1, 0, 0});
+      MakeInstructionDescriptor(29, spv::Op::OpStore, 0), 50, 29, 8, {1, 0, 0});
   ASSERT_FALSE(
       transformation_bad_5.IsApplicable(context.get(), transformation_context));
 
   // Bad: |index| is not a correct index.
   auto transformation_bad_6 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(29, SpvOpStore, 0), 50, 29, 11, {2, 0, 0});
+      MakeInstructionDescriptor(29, spv::Op::OpStore, 0), 50, 29, 11,
+      {2, 0, 0});
   ASSERT_FALSE(
       transformation_bad_6.IsApplicable(context.get(), transformation_context));
 
   // Bad: Type id of the object to be inserted and the type id of the
   // component at |index| are not the same.
   auto transformation_bad_7 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(29, SpvOpStore, 0), 50, 29, 11, {1, 0});
+      MakeInstructionDescriptor(29, spv::Op::OpStore, 0), 50, 29, 11, {1, 0});
   ASSERT_FALSE(
       transformation_bad_7.IsApplicable(context.get(), transformation_context));
 
   // Bad: |instruction_to_insert_before| does not refer to a defined
   // instruction.
   auto transformation_bad_8 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(29, SpvOpIMul, 0), 50, 29, 11, {1, 0, 0});
+      MakeInstructionDescriptor(29, spv::Op::OpIMul, 0), 50, 29, 11, {1, 0, 0});
   ASSERT_FALSE(
       transformation_bad_8.IsApplicable(context.get(), transformation_context));
 
   // Bad: OpCompositeInsert cannot be inserted before OpBranchConditional with
   // OpSelectionMerge above it.
   auto transformation_bad_9 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(29, SpvOpBranchConditional, 0), 50, 29, 11,
-      {1, 0, 0});
+      MakeInstructionDescriptor(29, spv::Op::OpBranchConditional, 0), 50, 29,
+      11, {1, 0, 0});
   ASSERT_FALSE(
       transformation_bad_9.IsApplicable(context.get(), transformation_context));
 
   // Bad: |composite_id| does not have a type_id.
   auto transformation_bad_10 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(29, SpvOpStore, 0), 50, 1, 11, {1, 0, 0});
+      MakeInstructionDescriptor(29, spv::Op::OpStore, 0), 50, 1, 11, {1, 0, 0});
   ASSERT_FALSE(transformation_bad_10.IsApplicable(context.get(),
                                                   transformation_context));
 }
@@ -222,14 +226,14 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // Bad: The composite with |composite_id| cannot be empty.
   auto transformation_bad_1 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(64, SpvOpStore, 0), 50, 61, 62, {1});
+      MakeInstructionDescriptor(64, spv::Op::OpStore, 0), 50, 61, 62, {1});
   ASSERT_FALSE(
       transformation_bad_1.IsApplicable(context.get(), transformation_context));
 
   // Good: It is possible to insert into a composite an element which is an
   // empty composite.
   auto transformation_good_1 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(64, SpvOpStore, 0), 50, 64, 62, {1});
+      MakeInstructionDescriptor(64, spv::Op::OpStore, 0), 50, 64, 62, {1});
   ASSERT_TRUE(transformation_good_1.IsApplicable(context.get(),
                                                  transformation_context));
   ApplyAndCheckFreshIds(transformation_good_1, context.get(),
@@ -368,7 +372,8 @@
   transformation_context.GetFactManager()->AddFactIdIsIrrelevant(30);
 
   auto transformation_good_1 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(30, SpvOpStore, 0), 50, 30, 11, {1, 0, 0});
+      MakeInstructionDescriptor(30, spv::Op::OpStore, 0), 50, 30, 11,
+      {1, 0, 0});
   ASSERT_TRUE(transformation_good_1.IsApplicable(context.get(),
                                                  transformation_context));
   ApplyAndCheckFreshIds(transformation_good_1, context.get(),
@@ -473,7 +478,8 @@
   transformation_context.GetFactManager()->AddFactIdIsIrrelevant(11);
 
   auto transformation_good_1 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(30, SpvOpStore, 0), 50, 30, 11, {1, 0, 0});
+      MakeInstructionDescriptor(30, spv::Op::OpStore, 0), 50, 30, 11,
+      {1, 0, 0});
   ASSERT_TRUE(transformation_good_1.IsApplicable(context.get(),
                                                  transformation_context));
   ApplyAndCheckFreshIds(transformation_good_1, context.get(),
@@ -580,7 +586,8 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   auto transformation_good_1 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(30, SpvOpStore, 0), 50, 30, 11, {1, 0, 0});
+      MakeInstructionDescriptor(30, spv::Op::OpStore, 0), 50, 30, 11,
+      {1, 0, 0});
   ASSERT_TRUE(transformation_good_1.IsApplicable(context.get(),
                                                  transformation_context));
   ApplyAndCheckFreshIds(transformation_good_1, context.get(),
@@ -609,7 +616,8 @@
       MakeDataDescriptor(30, {1, 0, 0}), MakeDataDescriptor(50, {1, 0, 0})));
 
   auto transformation_good_2 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(50, SpvOpStore, 0), 51, 50, 11, {0, 1, 1});
+      MakeInstructionDescriptor(50, spv::Op::OpStore, 0), 51, 50, 11,
+      {0, 1, 1});
   ASSERT_TRUE(transformation_good_2.IsApplicable(context.get(),
                                                  transformation_context));
   ApplyAndCheckFreshIds(transformation_good_2, context.get(),
@@ -787,30 +795,30 @@
   // Bad: The object with |object_id| is not available at
   // |instruction_to_insert_before|.
   auto transformation_bad_1 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(31, SpvOpIMul, 0), 50, 27, 60, {1});
+      MakeInstructionDescriptor(31, spv::Op::OpIMul, 0), 50, 27, 60, {1});
   ASSERT_FALSE(
       transformation_bad_1.IsApplicable(context.get(), transformation_context));
 
   // Bad: The composite with |composite_id| is not available at
   // |instruction_to_insert_before|.
   auto transformation_bad_2 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(31, SpvOpIMul, 0), 50, 61, 21, {1});
+      MakeInstructionDescriptor(31, spv::Op::OpIMul, 0), 50, 61, 21, {1});
   ASSERT_FALSE(
       transformation_bad_2.IsApplicable(context.get(), transformation_context));
 
   // Bad: The |instruction_to_insert_before| is the composite itself and is
   // available.
   auto transformation_bad_3 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(61, SpvOpCompositeConstruct, 0), 50, 61, 21,
-      {1});
+      MakeInstructionDescriptor(61, spv::Op::OpCompositeConstruct, 0), 50, 61,
+      21, {1});
   ASSERT_FALSE(
       transformation_bad_3.IsApplicable(context.get(), transformation_context));
 
   // Bad: The |instruction_to_insert_before| is the object itself and is not
   // available.
   auto transformation_bad_4 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(60, SpvOpCompositeConstruct, 0), 50, 27, 60,
-      {1});
+      MakeInstructionDescriptor(60, spv::Op::OpCompositeConstruct, 0), 50, 27,
+      60, {1});
   ASSERT_FALSE(
       transformation_bad_4.IsApplicable(context.get(), transformation_context));
 }
@@ -863,7 +871,8 @@
 
   // Leads to synonyms - nothing is irrelevant.
   auto transformation1 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(13, SpvOpSelectionMerge, 0), 100, 9, 17, {0});
+      MakeInstructionDescriptor(13, spv::Op::OpSelectionMerge, 0), 100, 9, 17,
+      {0});
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation1, context.get(),
@@ -876,7 +885,8 @@
   // Because %16 is irrelevant, we don't get a synonym with the component to
   // which it has been inserted (but we do for the other component).
   auto transformation2 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(13, SpvOpSelectionMerge, 0), 101, 9, 16, {0});
+      MakeInstructionDescriptor(13, spv::Op::OpSelectionMerge, 0), 101, 9, 16,
+      {0});
   ASSERT_TRUE(
       transformation2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation2, context.get(),
@@ -889,7 +899,8 @@
   // Because %18 is irrelevant we only get a synonym for the component into
   // which insertion has taken place.
   auto transformation3 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(13, SpvOpSelectionMerge, 0), 102, 18, 17, {0});
+      MakeInstructionDescriptor(13, spv::Op::OpSelectionMerge, 0), 102, 18, 17,
+      {0});
   ASSERT_TRUE(
       transformation3.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation3, context.get(),
@@ -901,7 +912,7 @@
 
   // Does not lead to synonyms as block %14 is dead.
   auto transformation4 = TransformationCompositeInsert(
-      MakeInstructionDescriptor(14, SpvOpBranch, 0), 103, 9, 17, {0});
+      MakeInstructionDescriptor(14, spv::Op::OpBranch, 0), 103, 9, 17, {0});
   ASSERT_TRUE(
       transformation4.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation4, context.get(),
diff --git a/test/fuzz/transformation_equation_instruction_test.cpp b/test/fuzz/transformation_equation_instruction_test.cpp
index 5b5033d..3653fca 100644
--- a/test/fuzz/transformation_equation_instruction_test.cpp
+++ b/test/fuzz/transformation_equation_instruction_test.cpp
@@ -54,65 +54,66 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   protobufs::InstructionDescriptor return_instruction =
-      MakeInstructionDescriptor(13, SpvOpReturn, 0);
+      MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   // Bad: id already in use.
-  ASSERT_FALSE(TransformationEquationInstruction(7, SpvOpSNegate, {7},
+  ASSERT_FALSE(TransformationEquationInstruction(7, spv::Op::OpSNegate, {7},
                                                  return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: identified instruction does not exist.
-  ASSERT_FALSE(
-      TransformationEquationInstruction(
-          14, SpvOpSNegate, {7}, MakeInstructionDescriptor(13, SpvOpLoad, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationEquationInstruction(
+                   14, spv::Op::OpSNegate, {7},
+                   MakeInstructionDescriptor(13, spv::Op::OpLoad, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: id 100 does not exist
-  ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpSNegate, {100},
+  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpSNegate, {100},
                                                  return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: id 20 is an OpUndef
-  ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpSNegate, {20},
+  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpSNegate, {20},
                                                  return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: id 30 is not available right before its definition
   ASSERT_FALSE(TransformationEquationInstruction(
-                   14, SpvOpSNegate, {30},
-                   MakeInstructionDescriptor(30, SpvOpCopyObject, 0))
+                   14, spv::Op::OpSNegate, {30},
+                   MakeInstructionDescriptor(30, spv::Op::OpCopyObject, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: too many arguments to OpSNegate.
-  ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpSNegate, {7, 7},
+  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpSNegate, {7, 7},
                                                  return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: 40 is a type id.
-  ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpSNegate, {40},
+  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpSNegate, {40},
                                                  return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: wrong type of argument to OpSNegate.
-  ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpSNegate, {41},
+  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpSNegate, {41},
                                                  return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 
   auto transformation1 = TransformationEquationInstruction(
-      14, SpvOpSNegate, {7}, return_instruction);
+      14, spv::Op::OpSNegate, {7}, return_instruction);
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(14));
   ASSERT_EQ(nullptr, context->get_instr_block(14));
   ApplyAndCheckFreshIds(transformation1, context.get(),
                         &transformation_context);
-  ASSERT_EQ(SpvOpSNegate, context->get_def_use_mgr()->GetDef(14)->opcode());
+  ASSERT_EQ(spv::Op::OpSNegate,
+            context->get_def_use_mgr()->GetDef(14)->opcode());
   ASSERT_EQ(13, context->get_instr_block(14)->id());
   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
                                                kConsoleMessageConsumer));
 
   auto transformation2 = TransformationEquationInstruction(
-      15, SpvOpSNegate, {14}, return_instruction);
+      15, spv::Op::OpSNegate, {14}, return_instruction);
   ASSERT_TRUE(
       transformation2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation2, context.get(),
@@ -178,25 +179,25 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   protobufs::InstructionDescriptor return_instruction =
-      MakeInstructionDescriptor(13, SpvOpReturn, 0);
+      MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   // Bad: too few arguments to OpLogicalNot.
-  ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpLogicalNot, {},
+  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpLogicalNot, {},
                                                  return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: 6 is a type id.
-  ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpLogicalNot, {6},
+  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpLogicalNot, {6},
                                                  return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: wrong type of argument to OpLogicalNot.
-  ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpLogicalNot, {21},
-                                                 return_instruction)
+  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpLogicalNot,
+                                                 {21}, return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 
   auto transformation1 = TransformationEquationInstruction(
-      14, SpvOpLogicalNot, {7}, return_instruction);
+      14, spv::Op::OpLogicalNot, {7}, return_instruction);
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation1, context.get(),
@@ -205,7 +206,7 @@
                                                kConsoleMessageConsumer));
 
   auto transformation2 = TransformationEquationInstruction(
-      15, SpvOpLogicalNot, {14}, return_instruction);
+      15, spv::Op::OpLogicalNot, {14}, return_instruction);
   ASSERT_TRUE(
       transformation2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation2, context.get(),
@@ -272,31 +273,31 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   protobufs::InstructionDescriptor return_instruction =
-      MakeInstructionDescriptor(13, SpvOpReturn, 0);
+      MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   // Bad: too many arguments to OpIAdd.
-  ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpIAdd, {15, 16, 16},
-                                                 return_instruction)
+  ASSERT_FALSE(TransformationEquationInstruction(
+                   14, spv::Op::OpIAdd, {15, 16, 16}, return_instruction)
                    .IsApplicable(context.get(), transformation_context));
   // Bad: boolean argument to OpIAdd.
-  ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpIAdd, {15, 32},
+  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpIAdd, {15, 32},
                                                  return_instruction)
                    .IsApplicable(context.get(), transformation_context));
   // Bad: type as argument to OpIAdd.
-  ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpIAdd, {33, 16},
+  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpIAdd, {33, 16},
                                                  return_instruction)
                    .IsApplicable(context.get(), transformation_context));
   // Bad: arguments of mismatched widths
-  ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpIAdd, {15, 31},
+  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpIAdd, {15, 31},
                                                  return_instruction)
                    .IsApplicable(context.get(), transformation_context));
   // Bad: arguments of mismatched widths
-  ASSERT_FALSE(TransformationEquationInstruction(14, SpvOpIAdd, {31, 15},
+  ASSERT_FALSE(TransformationEquationInstruction(14, spv::Op::OpIAdd, {31, 15},
                                                  return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 
   auto transformation1 = TransformationEquationInstruction(
-      14, SpvOpIAdd, {15, 16}, return_instruction);
+      14, spv::Op::OpIAdd, {15, 16}, return_instruction);
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation1, context.get(),
@@ -305,7 +306,7 @@
                                                kConsoleMessageConsumer));
 
   auto transformation2 = TransformationEquationInstruction(
-      19, SpvOpISub, {14, 16}, return_instruction);
+      19, spv::Op::OpISub, {14, 16}, return_instruction);
   ASSERT_TRUE(
       transformation2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation2, context.get(),
@@ -316,7 +317,7 @@
       MakeDataDescriptor(15, {}), MakeDataDescriptor(19, {})));
 
   auto transformation3 = TransformationEquationInstruction(
-      20, SpvOpISub, {14, 15}, return_instruction);
+      20, spv::Op::OpISub, {14, 15}, return_instruction);
   ASSERT_TRUE(
       transformation3.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation3, context.get(),
@@ -327,7 +328,7 @@
       MakeDataDescriptor(20, {}), MakeDataDescriptor(16, {})));
 
   auto transformation4 = TransformationEquationInstruction(
-      22, SpvOpISub, {16, 14}, return_instruction);
+      22, spv::Op::OpISub, {16, 14}, return_instruction);
   ASSERT_TRUE(
       transformation4.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation4, context.get(),
@@ -336,7 +337,7 @@
                                                kConsoleMessageConsumer));
 
   auto transformation5 = TransformationEquationInstruction(
-      24, SpvOpSNegate, {22}, return_instruction);
+      24, spv::Op::OpSNegate, {22}, return_instruction);
   ASSERT_TRUE(
       transformation5.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation5, context.get(),
@@ -404,10 +405,10 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   protobufs::InstructionDescriptor return_instruction =
-      MakeInstructionDescriptor(13, SpvOpReturn, 0);
+      MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   auto transformation1 = TransformationEquationInstruction(
-      14, SpvOpISub, {15, 16}, return_instruction);
+      14, spv::Op::OpISub, {15, 16}, return_instruction);
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation1, context.get(),
@@ -416,7 +417,7 @@
                                                kConsoleMessageConsumer));
 
   auto transformation2 = TransformationEquationInstruction(
-      17, SpvOpIAdd, {14, 16}, return_instruction);
+      17, spv::Op::OpIAdd, {14, 16}, return_instruction);
   ASSERT_TRUE(
       transformation2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation2, context.get(),
@@ -427,7 +428,7 @@
       MakeDataDescriptor(17, {}), MakeDataDescriptor(15, {})));
 
   auto transformation3 = TransformationEquationInstruction(
-      18, SpvOpIAdd, {16, 14}, return_instruction);
+      18, spv::Op::OpIAdd, {16, 14}, return_instruction);
   ASSERT_TRUE(
       transformation3.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation3, context.get(),
@@ -440,7 +441,7 @@
       MakeDataDescriptor(18, {}), MakeDataDescriptor(15, {})));
 
   auto transformation4 = TransformationEquationInstruction(
-      19, SpvOpISub, {14, 15}, return_instruction);
+      19, spv::Op::OpISub, {14, 15}, return_instruction);
   ASSERT_TRUE(
       transformation4.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation4, context.get(),
@@ -449,7 +450,7 @@
                                                kConsoleMessageConsumer));
 
   auto transformation5 = TransformationEquationInstruction(
-      20, SpvOpSNegate, {19}, return_instruction);
+      20, spv::Op::OpSNegate, {19}, return_instruction);
   ASSERT_TRUE(
       transformation5.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation5, context.get(),
@@ -460,7 +461,7 @@
       MakeDataDescriptor(20, {}), MakeDataDescriptor(16, {})));
 
   auto transformation6 = TransformationEquationInstruction(
-      21, SpvOpISub, {14, 19}, return_instruction);
+      21, spv::Op::OpISub, {14, 19}, return_instruction);
   ASSERT_TRUE(
       transformation6.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation6, context.get(),
@@ -471,7 +472,7 @@
       MakeDataDescriptor(21, {}), MakeDataDescriptor(15, {})));
 
   auto transformation7 = TransformationEquationInstruction(
-      22, SpvOpISub, {14, 18}, return_instruction);
+      22, spv::Op::OpISub, {14, 18}, return_instruction);
   ASSERT_TRUE(
       transformation7.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation7, context.get(),
@@ -480,7 +481,7 @@
                                                kConsoleMessageConsumer));
 
   auto transformation8 = TransformationEquationInstruction(
-      23, SpvOpSNegate, {22}, return_instruction);
+      23, spv::Op::OpSNegate, {22}, return_instruction);
   ASSERT_TRUE(
       transformation8.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation8, context.get(),
@@ -559,51 +560,51 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto insert_before = MakeInstructionDescriptor(13, SpvOpReturn, 0);
+  auto insert_before = MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   // Too many operands.
-  ASSERT_FALSE(TransformationEquationInstruction(50, SpvOpBitcast, {15, 16},
-                                                 insert_before)
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast,
+                                                 {15, 16}, insert_before)
                    .IsApplicable(context.get(), transformation_context));
 
   // Too few operands.
-  ASSERT_FALSE(
-      TransformationEquationInstruction(50, SpvOpBitcast, {}, insert_before)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {},
+                                                 insert_before)
+                   .IsApplicable(context.get(), transformation_context));
 
   // Operand's id is invalid.
-  ASSERT_FALSE(
-      TransformationEquationInstruction(50, SpvOpBitcast, {50}, insert_before)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {50},
+                                                 insert_before)
+                   .IsApplicable(context.get(), transformation_context));
 
   // Operand's type is invalid
-  ASSERT_FALSE(
-      TransformationEquationInstruction(50, SpvOpBitcast, {13}, insert_before)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {13},
+                                                 insert_before)
+                   .IsApplicable(context.get(), transformation_context));
 
   // Operand must be a scalar or a vector of numerical type.
 #ifndef NDEBUG
-  ASSERT_DEATH(
-      TransformationEquationInstruction(50, SpvOpBitcast, {23}, insert_before)
-          .IsApplicable(context.get(), transformation_context),
-      "Operand is not a scalar or a vector of numerical type");
-  ASSERT_DEATH(
-      TransformationEquationInstruction(50, SpvOpBitcast, {24}, insert_before)
-          .IsApplicable(context.get(), transformation_context),
-      "Only vectors of numerical components are supported");
+  ASSERT_DEATH(TransformationEquationInstruction(50, spv::Op::OpBitcast, {23},
+                                                 insert_before)
+                   .IsApplicable(context.get(), transformation_context),
+               "Operand is not a scalar or a vector of numerical type");
+  ASSERT_DEATH(TransformationEquationInstruction(50, spv::Op::OpBitcast, {24},
+                                                 insert_before)
+                   .IsApplicable(context.get(), transformation_context),
+               "Only vectors of numerical components are supported");
 #else
-  ASSERT_FALSE(
-      TransformationEquationInstruction(50, SpvOpBitcast, {23}, insert_before)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationEquationInstruction(50, SpvOpBitcast, {24}, insert_before)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {23},
+                                                 insert_before)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {24},
+                                                 insert_before)
+                   .IsApplicable(context.get(), transformation_context));
 #endif
 
   for (uint32_t operand_id = 15, fresh_id = 50; operand_id <= 20;
        ++operand_id, ++fresh_id) {
     TransformationEquationInstruction transformation(
-        fresh_id, SpvOpBitcast, {operand_id}, insert_before);
+        fresh_id, spv::Op::OpBitcast, {operand_id}, insert_before);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -683,23 +684,23 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto insert_before = MakeInstructionDescriptor(13, SpvOpReturn, 0);
+  auto insert_before = MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   // Scalar floating-point type does not exist.
-  ASSERT_FALSE(
-      TransformationEquationInstruction(50, SpvOpBitcast, {15}, insert_before)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationEquationInstruction(50, SpvOpBitcast, {16}, insert_before)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {15},
+                                                 insert_before)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {16},
+                                                 insert_before)
+                   .IsApplicable(context.get(), transformation_context));
 
   // Vector of floating-point components does not exist.
-  ASSERT_FALSE(
-      TransformationEquationInstruction(50, SpvOpBitcast, {18}, insert_before)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationEquationInstruction(50, SpvOpBitcast, {19}, insert_before)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {18},
+                                                 insert_before)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {19},
+                                                 insert_before)
+                   .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationEquationInstructionTest, BitcastResultTypeIntDoesNotExist1) {
@@ -730,17 +731,17 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto insert_before = MakeInstructionDescriptor(13, SpvOpReturn, 0);
+  auto insert_before = MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   // Scalar integral type does not exist.
-  ASSERT_FALSE(
-      TransformationEquationInstruction(50, SpvOpBitcast, {17}, insert_before)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {17},
+                                                 insert_before)
+                   .IsApplicable(context.get(), transformation_context));
 
   // Vector of integral components does not exist.
-  ASSERT_FALSE(
-      TransformationEquationInstruction(50, SpvOpBitcast, {20}, insert_before)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpBitcast, {20},
+                                                 insert_before)
+                   .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationEquationInstructionTest, BitcastResultTypeIntDoesNotExist2) {
@@ -773,19 +774,19 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto insert_before = MakeInstructionDescriptor(13, SpvOpReturn, 0);
+  auto insert_before = MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   {
-    TransformationEquationInstruction transformation(50, SpvOpBitcast, {17},
-                                                     insert_before);
+    TransformationEquationInstruction transformation(50, spv::Op::OpBitcast,
+                                                     {17}, insert_before);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
   }
   {
-    TransformationEquationInstruction transformation(51, SpvOpBitcast, {20},
-                                                     insert_before);
+    TransformationEquationInstruction transformation(51, spv::Op::OpBitcast,
+                                                     {20}, insert_before);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -848,19 +849,19 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto insert_before = MakeInstructionDescriptor(13, SpvOpReturn, 0);
+  auto insert_before = MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   {
-    TransformationEquationInstruction transformation(50, SpvOpBitcast, {17},
-                                                     insert_before);
+    TransformationEquationInstruction transformation(50, spv::Op::OpBitcast,
+                                                     {17}, insert_before);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
   }
   {
-    TransformationEquationInstruction transformation(51, SpvOpBitcast, {20},
-                                                     insert_before);
+    TransformationEquationInstruction transformation(51, spv::Op::OpBitcast,
+                                                     {20}, insert_before);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -922,20 +923,20 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto insert_before = MakeInstructionDescriptor(13, SpvOpReturn, 0);
+  auto insert_before = MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   {
-    TransformationEquationInstruction transformation(50, SpvOpBitcast, {17},
-                                                     insert_before);
+    TransformationEquationInstruction transformation(50, spv::Op::OpBitcast,
+                                                     {17}, insert_before);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
   }
 
-  ASSERT_FALSE(
-      TransformationEquationInstruction(51, SpvOpBitcast, {20}, insert_before)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationEquationInstruction(51, spv::Op::OpBitcast, {20},
+                                                 insert_before)
+                   .IsApplicable(context.get(), transformation_context));
 
   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
                                                kConsoleMessageConsumer));
@@ -993,20 +994,20 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto insert_before = MakeInstructionDescriptor(13, SpvOpReturn, 0);
+  auto insert_before = MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   {
-    TransformationEquationInstruction transformation(50, SpvOpBitcast, {17},
-                                                     insert_before);
+    TransformationEquationInstruction transformation(50, spv::Op::OpBitcast,
+                                                     {17}, insert_before);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
   }
 
-  ASSERT_FALSE(
-      TransformationEquationInstruction(51, SpvOpBitcast, {20}, insert_before)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationEquationInstruction(51, spv::Op::OpBitcast, {20},
+                                                 insert_before)
+                   .IsApplicable(context.get(), transformation_context));
 
   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
                                                kConsoleMessageConsumer));
@@ -1066,19 +1067,19 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto insert_before = MakeInstructionDescriptor(13, SpvOpReturn, 0);
+  auto insert_before = MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   {
-    TransformationEquationInstruction transformation(50, SpvOpBitcast, {17},
-                                                     insert_before);
+    TransformationEquationInstruction transformation(50, spv::Op::OpBitcast,
+                                                     {17}, insert_before);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
   }
   {
-    TransformationEquationInstruction transformation(51, SpvOpBitcast, {20},
-                                                     insert_before);
+    TransformationEquationInstruction transformation(51, spv::Op::OpBitcast,
+                                                     {20}, insert_before);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -1146,19 +1147,19 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto insert_before = MakeInstructionDescriptor(13, SpvOpReturn, 0);
+  auto insert_before = MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   {
-    TransformationEquationInstruction transformation(50, SpvOpBitcast, {17},
-                                                     insert_before);
+    TransformationEquationInstruction transformation(50, spv::Op::OpBitcast,
+                                                     {17}, insert_before);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
   }
   {
-    TransformationEquationInstruction transformation(51, SpvOpBitcast, {20},
-                                                     insert_before);
+    TransformationEquationInstruction transformation(51, spv::Op::OpBitcast,
+                                                     {20}, insert_before);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -1222,10 +1223,10 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   protobufs::InstructionDescriptor return_instruction =
-      MakeInstructionDescriptor(13, SpvOpReturn, 0);
+      MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   auto transformation1 = TransformationEquationInstruction(
-      522, SpvOpISub, {113, 113}, return_instruction);
+      522, spv::Op::OpISub, {113, 113}, return_instruction);
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation1, context.get(),
@@ -1234,7 +1235,7 @@
                                                kConsoleMessageConsumer));
 
   auto transformation2 = TransformationEquationInstruction(
-      570, SpvOpIAdd, {522, 113}, return_instruction);
+      570, spv::Op::OpIAdd, {522, 113}, return_instruction);
   ASSERT_TRUE(
       transformation2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation2, context.get(),
@@ -1294,10 +1295,10 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   protobufs::InstructionDescriptor return_instruction =
-      MakeInstructionDescriptor(13, SpvOpReturn, 0);
+      MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   auto transformation1 = TransformationEquationInstruction(
-      522, SpvOpISub, {113, 113}, return_instruction);
+      522, spv::Op::OpISub, {113, 113}, return_instruction);
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation1, context.get(),
@@ -1306,7 +1307,7 @@
                                                kConsoleMessageConsumer));
 
   auto transformation2 = TransformationEquationInstruction(
-      570, SpvOpIAdd, {522, 113}, return_instruction);
+      570, spv::Op::OpIAdd, {522, 113}, return_instruction);
   ASSERT_TRUE(
       transformation2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation2, context.get(),
@@ -1380,97 +1381,97 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   protobufs::InstructionDescriptor return_instruction =
-      MakeInstructionDescriptor(13, SpvOpReturn, 0);
+      MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   // Too few instruction operands.
-  ASSERT_FALSE(TransformationEquationInstruction(50, SpvOpConvertSToF, {},
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpConvertSToF, {},
                                                  return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 
   // Too many instruction operands.
-  ASSERT_FALSE(TransformationEquationInstruction(50, SpvOpConvertSToF, {15, 16},
-                                                 return_instruction)
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpConvertSToF,
+                                                 {15, 16}, return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 
   // Operand has no type id.
-  ASSERT_FALSE(TransformationEquationInstruction(50, SpvOpConvertSToF, {7},
-                                                 return_instruction)
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpConvertSToF,
+                                                 {7}, return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 
   // OpConvertSToF and OpConvertUToF require an operand to have scalar or vector
   // of integral components type.
-  ASSERT_FALSE(TransformationEquationInstruction(50, SpvOpConvertSToF, {17},
-                                                 return_instruction)
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpConvertSToF,
+                                                 {17}, return_instruction)
                    .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(TransformationEquationInstruction(50, SpvOpConvertSToF, {14},
-                                                 return_instruction)
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpConvertSToF,
+                                                 {14}, return_instruction)
                    .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(TransformationEquationInstruction(50, SpvOpConvertUToF, {17},
-                                                 return_instruction)
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpConvertUToF,
+                                                 {17}, return_instruction)
                    .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(TransformationEquationInstruction(50, SpvOpConvertUToF, {14},
-                                                 return_instruction)
+  ASSERT_FALSE(TransformationEquationInstruction(50, spv::Op::OpConvertUToF,
+                                                 {14}, return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 
   {
-    TransformationEquationInstruction transformation(50, SpvOpConvertSToF, {15},
-                                                     return_instruction);
+    TransformationEquationInstruction transformation(50, spv::Op::OpConvertSToF,
+                                                     {15}, return_instruction);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
   }
   {
-    TransformationEquationInstruction transformation(51, SpvOpConvertSToF, {10},
-                                                     return_instruction);
+    TransformationEquationInstruction transformation(51, spv::Op::OpConvertSToF,
+                                                     {10}, return_instruction);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
   }
   {
-    TransformationEquationInstruction transformation(52, SpvOpConvertUToF, {16},
-                                                     return_instruction);
+    TransformationEquationInstruction transformation(52, spv::Op::OpConvertUToF,
+                                                     {16}, return_instruction);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
   }
   {
-    TransformationEquationInstruction transformation(53, SpvOpConvertUToF, {11},
-                                                     return_instruction);
+    TransformationEquationInstruction transformation(53, spv::Op::OpConvertUToF,
+                                                     {11}, return_instruction);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
   }
   {
-    TransformationEquationInstruction transformation(58, SpvOpConvertSToF, {18},
-                                                     return_instruction);
+    TransformationEquationInstruction transformation(58, spv::Op::OpConvertSToF,
+                                                     {18}, return_instruction);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
   }
   {
-    TransformationEquationInstruction transformation(59, SpvOpConvertUToF, {19},
-                                                     return_instruction);
+    TransformationEquationInstruction transformation(59, spv::Op::OpConvertUToF,
+                                                     {19}, return_instruction);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
   }
   {
-    TransformationEquationInstruction transformation(60, SpvOpConvertSToF, {20},
-                                                     return_instruction);
+    TransformationEquationInstruction transformation(60, spv::Op::OpConvertSToF,
+                                                     {20}, return_instruction);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
                           &transformation_context);
   }
   {
-    TransformationEquationInstruction transformation(61, SpvOpConvertUToF, {21},
-                                                     return_instruction);
+    TransformationEquationInstruction transformation(61, spv::Op::OpConvertUToF,
+                                                     {21}, return_instruction);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -1555,22 +1556,22 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   protobufs::InstructionDescriptor return_instruction =
-      MakeInstructionDescriptor(13, SpvOpReturn, 0);
+      MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   // Scalar float type doesn't exist.
-  ASSERT_FALSE(TransformationEquationInstruction(16, SpvOpConvertUToF, {10},
-                                                 return_instruction)
+  ASSERT_FALSE(TransformationEquationInstruction(16, spv::Op::OpConvertUToF,
+                                                 {10}, return_instruction)
                    .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(TransformationEquationInstruction(16, SpvOpConvertSToF, {11},
-                                                 return_instruction)
+  ASSERT_FALSE(TransformationEquationInstruction(16, spv::Op::OpConvertSToF,
+                                                 {11}, return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 
   // Vector float type doesn't exist.
-  ASSERT_FALSE(TransformationEquationInstruction(16, SpvOpConvertUToF, {14},
-                                                 return_instruction)
+  ASSERT_FALSE(TransformationEquationInstruction(16, spv::Op::OpConvertUToF,
+                                                 {14}, return_instruction)
                    .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(TransformationEquationInstruction(16, SpvOpConvertSToF, {15},
-                                                 return_instruction)
+  ASSERT_FALSE(TransformationEquationInstruction(16, spv::Op::OpConvertSToF,
+                                                 {15}, return_instruction)
                    .IsApplicable(context.get(), transformation_context));
 }
 
@@ -1605,11 +1606,11 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto return_instruction = MakeInstructionDescriptor(13, SpvOpReturn, 0);
+  auto return_instruction = MakeInstructionDescriptor(13, spv::Op::OpReturn, 0);
 
   // Applicable.
-  TransformationEquationInstruction transformation(14, SpvOpIAdd, {15, 16},
-                                                   return_instruction);
+  TransformationEquationInstruction transformation(
+      14, spv::Op::OpIAdd, {15, 16}, return_instruction);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
 
@@ -1662,11 +1663,12 @@
   transformation_context.GetFactManager()->AddFactBlockIsDead(41);
 
   TransformationEquationInstruction transformation1(
-      14, SpvOpIAdd, {15, 16},
-      MakeInstructionDescriptor(13, SpvOpSelectionMerge, 0));
+      14, spv::Op::OpIAdd, {15, 16},
+      MakeInstructionDescriptor(13, spv::Op::OpSelectionMerge, 0));
   // No synonym is created since block is dead.
   TransformationEquationInstruction transformation2(
-      100, SpvOpISub, {14, 16}, MakeInstructionDescriptor(41, SpvOpBranch, 0));
+      100, spv::Op::OpISub, {14, 16},
+      MakeInstructionDescriptor(41, spv::Op::OpBranch, 0));
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation1, context.get(),
diff --git a/test/fuzz/transformation_flatten_conditional_branch_test.cpp b/test/fuzz/transformation_flatten_conditional_branch_test.cpp
index 800af0e..0631899 100644
--- a/test/fuzz/transformation_flatten_conditional_branch_test.cpp
+++ b/test/fuzz/transformation_flatten_conditional_branch_test.cpp
@@ -441,8 +441,8 @@
   ASSERT_DEATH(TransformationFlattenConditionalBranch(
                    31, true, 0, 0, 0,
                    {{MakeSideEffectWrapperInfo(
-                       MakeInstructionDescriptor(6, SpvOpLoad, 0), 100, 101,
-                       102, 103, 104, 14)}})
+                       MakeInstructionDescriptor(6, spv::Op::OpLoad, 0), 100,
+                       101, 102, 103, 104, 14)}})
                    .IsApplicable(context.get(), transformation_context),
                "Bad attempt to query whether overflow ids are available.");
 #endif
@@ -451,52 +451,55 @@
   ASSERT_FALSE(TransformationFlattenConditionalBranch(
                    31, true, 0, 0, 0,
                    {{MakeSideEffectWrapperInfo(
-                       MakeInstructionDescriptor(6, SpvOpLoad, 0), 100, 101,
-                       102, 103, 0, 0)}})
+                       MakeInstructionDescriptor(6, spv::Op::OpLoad, 0), 100,
+                       101, 102, 103, 0, 0)}})
                    .IsApplicable(context.get(), transformation_context));
 
   // Not all fresh ids given are distinct.
   ASSERT_FALSE(TransformationFlattenConditionalBranch(
                    31, true, 0, 0, 0,
                    {{MakeSideEffectWrapperInfo(
-                       MakeInstructionDescriptor(6, SpvOpLoad, 0), 100, 100,
-                       102, 103, 104, 0)}})
+                       MakeInstructionDescriptor(6, spv::Op::OpLoad, 0), 100,
+                       100, 102, 103, 104, 0)}})
                    .IsApplicable(context.get(), transformation_context));
 
   // %48 heads a construct containing an OpSampledImage instruction.
   ASSERT_FALSE(TransformationFlattenConditionalBranch(
                    48, true, 0, 0, 0,
                    {{MakeSideEffectWrapperInfo(
-                       MakeInstructionDescriptor(53, SpvOpLoad, 0), 100, 101,
-                       102, 103, 104, 0)}})
+                       MakeInstructionDescriptor(53, spv::Op::OpLoad, 0), 100,
+                       101, 102, 103, 104, 0)}})
                    .IsApplicable(context.get(), transformation_context));
 
   // %0 is not a valid id.
   ASSERT_FALSE(
       TransformationFlattenConditionalBranch(
           31, true, 0, 0, 0,
-          {MakeSideEffectWrapperInfo(MakeInstructionDescriptor(6, SpvOpLoad, 0),
-                                     104, 100, 101, 102, 103, 0),
+          {MakeSideEffectWrapperInfo(
+               MakeInstructionDescriptor(6, spv::Op::OpLoad, 0), 104, 100, 101,
+               102, 103, 0),
            MakeSideEffectWrapperInfo(
-               MakeInstructionDescriptor(6, SpvOpStore, 0), 106, 105)})
+               MakeInstructionDescriptor(6, spv::Op::OpStore, 0), 106, 105)})
           .IsApplicable(context.get(), transformation_context));
 
   // %17 is a float constant, while %6 has int type.
   ASSERT_FALSE(
       TransformationFlattenConditionalBranch(
           31, true, 0, 0, 0,
-          {MakeSideEffectWrapperInfo(MakeInstructionDescriptor(6, SpvOpLoad, 0),
-                                     104, 100, 101, 102, 103, 17),
+          {MakeSideEffectWrapperInfo(
+               MakeInstructionDescriptor(6, spv::Op::OpLoad, 0), 104, 100, 101,
+               102, 103, 17),
            MakeSideEffectWrapperInfo(
-               MakeInstructionDescriptor(6, SpvOpStore, 0), 106, 105)})
+               MakeInstructionDescriptor(6, spv::Op::OpStore, 0), 106, 105)})
           .IsApplicable(context.get(), transformation_context));
 
   auto transformation1 = TransformationFlattenConditionalBranch(
       31, true, 0, 0, 0,
-      {MakeSideEffectWrapperInfo(MakeInstructionDescriptor(6, SpvOpLoad, 0),
-                                 104, 100, 101, 102, 103, 70),
-       MakeSideEffectWrapperInfo(MakeInstructionDescriptor(6, SpvOpStore, 0),
-                                 106, 105)});
+      {MakeSideEffectWrapperInfo(
+           MakeInstructionDescriptor(6, spv::Op::OpLoad, 0), 104, 100, 101, 102,
+           103, 70),
+       MakeSideEffectWrapperInfo(
+           MakeInstructionDescriptor(6, spv::Op::OpStore, 0), 106, 105)});
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation1, context.get(),
@@ -514,8 +517,8 @@
 
   auto transformation2 = TransformationFlattenConditionalBranch(
       36, false, 0, 0, 0,
-      {MakeSideEffectWrapperInfo(MakeInstructionDescriptor(8, SpvOpStore, 0),
-                                 114, 113)});
+      {MakeSideEffectWrapperInfo(
+          MakeInstructionDescriptor(8, spv::Op::OpStore, 0), 114, 113)});
   ASSERT_TRUE(
       transformation2.IsApplicable(context.get(), new_transformation_context));
   ApplyAndCheckFreshIds(transformation2, context.get(),
@@ -717,7 +720,8 @@
   auto transformation1 = TransformationFlattenConditionalBranch(
       7, true, 0, 0, 0,
       {{MakeSideEffectWrapperInfo(
-          MakeInstructionDescriptor(10, SpvOpFunctionCall, 0), 100, 101)}});
+          MakeInstructionDescriptor(10, spv::Op::OpFunctionCall, 0), 100,
+          101)}});
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation1, context.get(),
@@ -729,7 +733,8 @@
       TransformationFlattenConditionalBranch(
           7, true, 0, 0, 0,
           {{MakeSideEffectWrapperInfo(
-              MakeInstructionDescriptor(14, SpvOpFunctionCall, 0), 102, 103)}})
+              MakeInstructionDescriptor(14, spv::Op::OpFunctionCall, 0), 102,
+              103)}})
           .IsApplicable(context.get(), transformation_context));
 
   // Block %16 is unreachable.
@@ -1126,10 +1131,12 @@
 
   auto transformation = TransformationFlattenConditionalBranch(
       7, true, 0, 0, 0,
-      {MakeSideEffectWrapperInfo(MakeInstructionDescriptor(522, SpvOpLoad, 0),
-                                 200, 201, 202, 203, 204, 5),
-       MakeSideEffectWrapperInfo(MakeInstructionDescriptor(466, SpvOpLoad, 0),
-                                 300, 301, 302, 303, 304, 5)});
+      {MakeSideEffectWrapperInfo(
+           MakeInstructionDescriptor(522, spv::Op::OpLoad, 0), 200, 201, 202,
+           203, 204, 5),
+       MakeSideEffectWrapperInfo(
+           MakeInstructionDescriptor(466, spv::Op::OpLoad, 0), 300, 301, 302,
+           303, 304, 5)});
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
@@ -1231,8 +1238,9 @@
 
   auto transformation = TransformationFlattenConditionalBranch(
       5, true, 0, 0, 0,
-      {MakeSideEffectWrapperInfo(MakeInstructionDescriptor(20, SpvOpLoad, 0),
-                                 100, 101, 102, 103, 104, 21)});
+      {MakeSideEffectWrapperInfo(
+          MakeInstructionDescriptor(20, spv::Op::OpLoad, 0), 100, 101, 102, 103,
+          104, 21)});
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
@@ -1299,8 +1307,8 @@
   ASSERT_FALSE(TransformationFlattenConditionalBranch(
                    28, true, 0, 0, 0,
                    {MakeSideEffectWrapperInfo(
-                       MakeInstructionDescriptor(40, SpvOpLoad, 0), 100, 101,
-                       102, 103, 104, 200)})
+                       MakeInstructionDescriptor(40, spv::Op::OpLoad, 0), 100,
+                       101, 102, 103, 104, 200)})
                    .IsApplicable(context.get(), transformation_context));
 }
 
@@ -1730,7 +1738,7 @@
   // Check that the in operands of any OpSelect instructions all have the
   // appropriate operand type.
   context->module()->ForEachInst([](opt::Instruction* inst) {
-    if (inst->opcode() == SpvOpSelect) {
+    if (inst->opcode() == spv::Op::OpSelect) {
       ASSERT_EQ(SPV_OPERAND_TYPE_ID, inst->GetInOperand(0).type);
       ASSERT_EQ(SPV_OPERAND_TYPE_ID, inst->GetInOperand(1).type);
       ASSERT_EQ(SPV_OPERAND_TYPE_ID, inst->GetInOperand(2).type);
@@ -2183,14 +2191,15 @@
 
   transformation_context.GetFactManager()->AddFactDataSynonym(
       MakeDataDescriptor(10, {}), MakeDataDescriptor(21, {}));
-  ASSERT_FALSE(TransformationFlattenConditionalBranch(
-                   12, true, 0, 0, 0,
-                   {MakeSideEffectWrapperInfo(
-                        MakeInstructionDescriptor(30, SpvOpStore, 0), 100, 101),
-                    MakeSideEffectWrapperInfo(
-                        MakeInstructionDescriptor(21, SpvOpLoad, 0), 102, 103,
-                        104, 105, 106, 80)})
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationFlattenConditionalBranch(
+          12, true, 0, 0, 0,
+          {MakeSideEffectWrapperInfo(
+               MakeInstructionDescriptor(30, spv::Op::OpStore, 0), 100, 101),
+           MakeSideEffectWrapperInfo(
+               MakeInstructionDescriptor(21, spv::Op::OpLoad, 0), 102, 103, 104,
+               105, 106, 80)})
+          .IsApplicable(context.get(), transformation_context));
 }
 
 }  // namespace
diff --git a/test/fuzz/transformation_function_call_test.cpp b/test/fuzz/transformation_function_call_test.cpp
index b27b3ca..c963e33 100644
--- a/test/fuzz/transformation_function_call_test.cpp
+++ b/test/fuzz/transformation_function_call_test.cpp
@@ -174,88 +174,91 @@
 
   // Bad transformations
   // Too many arguments
-  ASSERT_FALSE(
-      TransformationFunctionCall(100, 21, {71, 72, 71},
-                                 MakeInstructionDescriptor(59, SpvOpBranch, 0))
-          .IsApplicable(context.get(), transformation_context));
-  // Too few arguments
   ASSERT_FALSE(TransformationFunctionCall(
-                   100, 21, {71}, MakeInstructionDescriptor(59, SpvOpBranch, 0))
+                   100, 21, {71, 72, 71},
+                   MakeInstructionDescriptor(59, spv::Op::OpBranch, 0))
                    .IsApplicable(context.get(), transformation_context));
+  // Too few arguments
+  ASSERT_FALSE(
+      TransformationFunctionCall(
+          100, 21, {71}, MakeInstructionDescriptor(59, spv::Op::OpBranch, 0))
+          .IsApplicable(context.get(), transformation_context));
   // Arguments are the wrong way around (types do not match)
-  ASSERT_FALSE(
-      TransformationFunctionCall(100, 21, {72, 71},
-                                 MakeInstructionDescriptor(59, SpvOpBranch, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationFunctionCall(
+                   100, 21, {72, 71},
+                   MakeInstructionDescriptor(59, spv::Op::OpBranch, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // 21 is not an appropriate argument
-  ASSERT_FALSE(
-      TransformationFunctionCall(100, 21, {21, 72},
-                                 MakeInstructionDescriptor(59, SpvOpBranch, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationFunctionCall(
+                   100, 21, {21, 72},
+                   MakeInstructionDescriptor(59, spv::Op::OpBranch, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // 300 does not exist
-  ASSERT_FALSE(
-      TransformationFunctionCall(100, 21, {300, 72},
-                                 MakeInstructionDescriptor(59, SpvOpBranch, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationFunctionCall(
+                   100, 21, {300, 72},
+                   MakeInstructionDescriptor(59, spv::Op::OpBranch, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // 71 is not a function
-  ASSERT_FALSE(
-      TransformationFunctionCall(100, 71, {71, 72},
-                                 MakeInstructionDescriptor(59, SpvOpBranch, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationFunctionCall(
+                   100, 71, {71, 72},
+                   MakeInstructionDescriptor(59, spv::Op::OpBranch, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // 500 does not exist
-  ASSERT_FALSE(
-      TransformationFunctionCall(100, 500, {71, 72},
-                                 MakeInstructionDescriptor(59, SpvOpBranch, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationFunctionCall(
+                   100, 500, {71, 72},
+                   MakeInstructionDescriptor(59, spv::Op::OpBranch, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // Id is not fresh
   ASSERT_FALSE(
-      TransformationFunctionCall(21, 21, {71, 72},
-                                 MakeInstructionDescriptor(59, SpvOpBranch, 0))
+      TransformationFunctionCall(
+          21, 21, {71, 72}, MakeInstructionDescriptor(59, spv::Op::OpBranch, 0))
           .IsApplicable(context.get(), transformation_context));
   // Access chain as pointer parameter
-  ASSERT_FALSE(
-      TransformationFunctionCall(100, 21, {98, 72},
-                                 MakeInstructionDescriptor(59, SpvOpBranch, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationFunctionCall(
+                   100, 21, {98, 72},
+                   MakeInstructionDescriptor(59, spv::Op::OpBranch, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // Copied object as pointer parameter
-  ASSERT_FALSE(
-      TransformationFunctionCall(100, 21, {99, 72},
-                                 MakeInstructionDescriptor(59, SpvOpBranch, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationFunctionCall(
+                   100, 21, {99, 72},
+                   MakeInstructionDescriptor(59, spv::Op::OpBranch, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // Non-livesafe called from original live block
-  ASSERT_FALSE(
-      TransformationFunctionCall(
-          100, 10, {71}, MakeInstructionDescriptor(99, SpvOpSelectionMerge, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationFunctionCall(
+                   100, 10, {71},
+                   MakeInstructionDescriptor(99, spv::Op::OpSelectionMerge, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // Non-livesafe called from livesafe function
-  ASSERT_FALSE(
-      TransformationFunctionCall(
-          100, 10, {19}, MakeInstructionDescriptor(38, SpvOpConvertFToS, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationFunctionCall(
+                   100, 10, {19},
+                   MakeInstructionDescriptor(38, spv::Op::OpConvertFToS, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // Livesafe function called with pointer to non-arbitrary local variable
+  ASSERT_FALSE(TransformationFunctionCall(
+                   100, 21, {61, 72},
+                   MakeInstructionDescriptor(38, spv::Op::OpConvertFToS, 0))
+                   .IsApplicable(context.get(), transformation_context));
+  // Direct recursion
   ASSERT_FALSE(
       TransformationFunctionCall(
-          100, 21, {61, 72}, MakeInstructionDescriptor(38, SpvOpConvertFToS, 0))
+          100, 4, {}, MakeInstructionDescriptor(59, spv::Op::OpBranch, 0))
           .IsApplicable(context.get(), transformation_context));
-  // Direct recursion
-  ASSERT_FALSE(TransformationFunctionCall(
-                   100, 4, {}, MakeInstructionDescriptor(59, SpvOpBranch, 0))
-                   .IsApplicable(context.get(), transformation_context));
   // Indirect recursion
-  ASSERT_FALSE(TransformationFunctionCall(
-                   100, 24, {9}, MakeInstructionDescriptor(96, SpvOpBranch, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationFunctionCall(
+          100, 24, {9}, MakeInstructionDescriptor(96, spv::Op::OpBranch, 0))
+          .IsApplicable(context.get(), transformation_context));
   // Parameter 23 is not available at the call site
   ASSERT_FALSE(
-      TransformationFunctionCall(104, 10, {23},
-                                 MakeInstructionDescriptor(205, SpvOpBranch, 0))
+      TransformationFunctionCall(
+          104, 10, {23}, MakeInstructionDescriptor(205, spv::Op::OpBranch, 0))
           .IsApplicable(context.get(), transformation_context));
 
   // Good transformations
   {
     // Livesafe called from dead block: fine
     TransformationFunctionCall transformation(
-        100, 21, {71, 72}, MakeInstructionDescriptor(59, SpvOpBranch, 0));
+        100, 21, {71, 72}, MakeInstructionDescriptor(59, spv::Op::OpBranch, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -266,7 +269,8 @@
   {
     // Livesafe called from original live block: fine
     TransformationFunctionCall transformation(
-        101, 21, {71, 72}, MakeInstructionDescriptor(98, SpvOpAccessChain, 0));
+        101, 21, {71, 72},
+        MakeInstructionDescriptor(98, spv::Op::OpAccessChain, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -277,7 +281,7 @@
   {
     // Livesafe called from livesafe function: fine
     TransformationFunctionCall transformation(
-        102, 200, {19, 20}, MakeInstructionDescriptor(36, SpvOpLoad, 0));
+        102, 200, {19, 20}, MakeInstructionDescriptor(36, spv::Op::OpLoad, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -288,7 +292,7 @@
   {
     // Dead called from dead block in injected function: fine
     TransformationFunctionCall transformation(
-        103, 10, {23}, MakeInstructionDescriptor(45, SpvOpLoad, 0));
+        103, 10, {23}, MakeInstructionDescriptor(45, spv::Op::OpLoad, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -299,7 +303,7 @@
   {
     // Non-livesafe called from dead block in livesafe function: OK
     TransformationFunctionCall transformation(
-        104, 10, {201}, MakeInstructionDescriptor(205, SpvOpBranch, 0));
+        104, 10, {201}, MakeInstructionDescriptor(205, spv::Op::OpBranch, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -310,7 +314,7 @@
   {
     // Livesafe called from dead block with non-arbitrary parameter
     TransformationFunctionCall transformation(
-        105, 21, {62, 65}, MakeInstructionDescriptor(59, SpvOpBranch, 0));
+        105, 21, {62, 65}, MakeInstructionDescriptor(59, spv::Op::OpBranch, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -465,9 +469,10 @@
   transformation_context.GetFactManager()->AddFactBlockIsDead(11);
 
   // 4 is an entry point, so it is not legal for it to be the target of a call.
-  ASSERT_FALSE(TransformationFunctionCall(
-                   100, 4, {}, MakeInstructionDescriptor(11, SpvOpReturn, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationFunctionCall(
+          100, 4, {}, MakeInstructionDescriptor(11, spv::Op::OpReturn, 0))
+          .IsApplicable(context.get(), transformation_context));
 }
 
 }  // namespace
diff --git a/test/fuzz/transformation_load_test.cpp b/test/fuzz/transformation_load_test.cpp
index 370826e..6fde49a 100644
--- a/test/fuzz/transformation_load_test.cpp
+++ b/test/fuzz/transformation_load_test.cpp
@@ -131,67 +131,68 @@
   //  60 - null
 
   // Bad: id is not fresh
-  ASSERT_FALSE(
-      TransformationLoad(33, 33, false, 0, 0,
-                         MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   33, 33, false, 0, 0,
+                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // Bad: attempt to load from 11 from outside its function
-  ASSERT_FALSE(
-      TransformationLoad(100, 11, false, 0, 0,
-                         MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   100, 11, false, 0, 0,
+                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer is not available
-  ASSERT_FALSE(
-      TransformationLoad(100, 33, false, 0, 0,
-                         MakeInstructionDescriptor(45, SpvOpCopyObject, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   100, 33, false, 0, 0,
+                   MakeInstructionDescriptor(45, spv::Op::OpCopyObject, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: attempt to insert before OpVariable
   ASSERT_FALSE(
       TransformationLoad(100, 27, false, 0, 0,
-                         MakeInstructionDescriptor(27, SpvOpVariable, 0))
+                         MakeInstructionDescriptor(27, spv::Op::OpVariable, 0))
           .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer id does not exist
-  ASSERT_FALSE(
-      TransformationLoad(100, 1000, false, 0, 0,
-                         MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   100, 1000, false, 0, 0,
+                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer id exists but does not have a type
-  ASSERT_FALSE(
-      TransformationLoad(100, 5, false, 0, 0,
-                         MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   100, 5, false, 0, 0,
+                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer id exists and has a type, but is not a pointer
-  ASSERT_FALSE(
-      TransformationLoad(100, 24, false, 0, 0,
-                         MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   100, 24, false, 0, 0,
+                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: attempt to load from null pointer
-  ASSERT_FALSE(
-      TransformationLoad(100, 60, false, 0, 0,
-                         MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   100, 60, false, 0, 0,
+                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: %40 is not available at the program point
-  ASSERT_FALSE(TransformationLoad(100, 40, false, 0, 0,
-                                  MakeInstructionDescriptor(37, SpvOpReturn, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationLoad(100, 40, false, 0, 0,
+                         MakeInstructionDescriptor(37, spv::Op::OpReturn, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   // Bad: The described instruction does not exist
   ASSERT_FALSE(
       TransformationLoad(100, 33, false, 0, 0,
-                         MakeInstructionDescriptor(1000, SpvOpReturn, 0))
+                         MakeInstructionDescriptor(1000, spv::Op::OpReturn, 0))
           .IsApplicable(context.get(), transformation_context));
 
   {
     TransformationLoad transformation(
         100, 33, false, 0, 0,
-        MakeInstructionDescriptor(38, SpvOpAccessChain, 0));
+        MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -203,7 +204,7 @@
   {
     TransformationLoad transformation(
         101, 46, false, 0, 0,
-        MakeInstructionDescriptor(16, SpvOpReturnValue, 0));
+        MakeInstructionDescriptor(16, spv::Op::OpReturnValue, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -215,7 +216,7 @@
   {
     TransformationLoad transformation(
         102, 16, false, 0, 0,
-        MakeInstructionDescriptor(16, SpvOpReturnValue, 0));
+        MakeInstructionDescriptor(16, spv::Op::OpReturnValue, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -227,7 +228,7 @@
   {
     TransformationLoad transformation(
         103, 40, false, 0, 0,
-        MakeInstructionDescriptor(43, SpvOpAccessChain, 0));
+        MakeInstructionDescriptor(43, spv::Op::OpAccessChain, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -344,80 +345,80 @@
       MakeUnique<FactManager>(context.get()), validator_options);
 
   // Bad: id is not fresh.
-  ASSERT_FALSE(
-      TransformationLoad(14, 14, true, 15, 20,
-                         MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   14, 14, true, 15, 20,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: id 100 of memory scope instruction does not exist.
-  ASSERT_FALSE(
-      TransformationLoad(21, 14, true, 100, 20,
-                         MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   21, 14, true, 100, 20,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // Bad: id 100 of memory semantics instruction does not exist.
-  ASSERT_FALSE(
-      TransformationLoad(21, 14, true, 15, 100,
-                         MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   21, 14, true, 15, 100,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // Bad: memory scope should be |OpConstant| opcode.
-  ASSERT_FALSE(
-      TransformationLoad(21, 14, true, 5, 20,
-                         MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   21, 14, true, 5, 20,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // Bad: memory semantics should be |OpConstant| opcode.
-  ASSERT_FALSE(
-      TransformationLoad(21, 14, true, 15, 5,
-                         MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   21, 14, true, 15, 5,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: The memory scope instruction must have an Integer operand.
-  ASSERT_FALSE(
-      TransformationLoad(21, 14, true, 15, 19,
-                         MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   21, 14, true, 15, 19,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // Bad: The memory memory semantics instruction must have an Integer operand.
-  ASSERT_FALSE(
-      TransformationLoad(21, 14, true, 19, 20,
-                         MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   21, 14, true, 19, 20,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: Integer size of the memory scope must be equal to 32 bits.
-  ASSERT_FALSE(
-      TransformationLoad(21, 14, true, 17, 20,
-                         MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   21, 14, true, 17, 20,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: Integer size of memory semantics must be equal to 32 bits.
-  ASSERT_FALSE(
-      TransformationLoad(21, 14, true, 15, 17,
-                         MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   21, 14, true, 15, 17,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
-  // Bad: memory scope value must be 4 (SpvScopeInvocation).
-  ASSERT_FALSE(
-      TransformationLoad(21, 14, true, 16, 20,
-                         MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  // Bad: memory scope value must be 4 (spv::Scope::Invocation).
+  ASSERT_FALSE(TransformationLoad(
+                   21, 14, true, 16, 20,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: memory semantics value must be either:
   // 64 (SpvMemorySemanticsUniformMemoryMask)
   // 256 (SpvMemorySemanticsWorkgroupMemoryMask)
-  ASSERT_FALSE(
-      TransformationLoad(21, 14, true, 15, 16,
-                         MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   21, 14, true, 15, 16,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: The described instruction does not exist
-  ASSERT_FALSE(
-      TransformationLoad(21, 14, false, 15, 20,
-                         MakeInstructionDescriptor(150, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   21, 14, false, 15, 20,
+                   MakeInstructionDescriptor(150, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Successful transformations.
   {
     TransformationLoad transformation(
         21, 14, true, 15, 20,
-        MakeInstructionDescriptor(24, SpvOpAccessChain, 0));
+        MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -518,22 +519,22 @@
       MakeUnique<FactManager>(context.get()), validator_options);
 
   // Bad: Can't insert OpAccessChain before the id 23 of memory scope.
-  ASSERT_FALSE(
-      TransformationLoad(60, 38, true, 21, 23,
-                         MakeInstructionDescriptor(23, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   60, 38, true, 21, 23,
+                   MakeInstructionDescriptor(23, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: Can't insert OpAccessChain before the id 23 of memory semantics.
-  ASSERT_FALSE(
-      TransformationLoad(60, 38, true, 21, 23,
-                         MakeInstructionDescriptor(21, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationLoad(
+                   60, 38, true, 21, 23,
+                   MakeInstructionDescriptor(21, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Successful transformations.
   {
     TransformationLoad transformation(
         60, 38, true, 21, 23,
-        MakeInstructionDescriptor(40, SpvOpAccessChain, 0));
+        MakeInstructionDescriptor(40, spv::Op::OpAccessChain, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
diff --git a/test/fuzz/transformation_merge_function_returns_test.cpp b/test/fuzz/transformation_merge_function_returns_test.cpp
index 400d49a..dd1869f 100644
--- a/test/fuzz/transformation_merge_function_returns_test.cpp
+++ b/test/fuzz/transformation_merge_function_returns_test.cpp
@@ -1884,7 +1884,7 @@
   // Ensure that all input operands of OpBranchConditional instructions have
   // the right operand type.
   context->module()->ForEachInst([](opt::Instruction* inst) {
-    if (inst->opcode() == SpvOpBranchConditional) {
+    if (inst->opcode() == spv::Op::OpBranchConditional) {
       ASSERT_EQ(inst->GetInOperand(0).type, SPV_OPERAND_TYPE_ID);
       ASSERT_EQ(inst->GetInOperand(1).type, SPV_OPERAND_TYPE_ID);
       ASSERT_EQ(inst->GetInOperand(2).type, SPV_OPERAND_TYPE_ID);
diff --git a/test/fuzz/transformation_move_instruction_down_test.cpp b/test/fuzz/transformation_move_instruction_down_test.cpp
index 45dde7d..5ab1619 100644
--- a/test/fuzz/transformation_move_instruction_down_test.cpp
+++ b/test/fuzz/transformation_move_instruction_down_test.cpp
@@ -73,44 +73,45 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // Instruction descriptor is invalid.
   ASSERT_FALSE(TransformationMoveInstructionDown(
-                   MakeInstructionDescriptor(30, SpvOpNop, 0))
+                   MakeInstructionDescriptor(30, spv::Op::OpNop, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // Opcode is not supported.
   ASSERT_FALSE(TransformationMoveInstructionDown(
-                   MakeInstructionDescriptor(5, SpvOpLabel, 0))
+                   MakeInstructionDescriptor(5, spv::Op::OpLabel, 0))
                    .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationMoveInstructionDown(
-                   MakeInstructionDescriptor(12, SpvOpVariable, 0))
+                   MakeInstructionDescriptor(12, spv::Op::OpVariable, 0))
                    .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationMoveInstructionDown(
-                   MakeInstructionDescriptor(42, SpvOpFunctionCall, 0))
+                   MakeInstructionDescriptor(42, spv::Op::OpFunctionCall, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // Can't move the last instruction in the block.
-  ASSERT_FALSE(TransformationMoveInstructionDown(
-                   MakeInstructionDescriptor(15, SpvOpBranchConditional, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationMoveInstructionDown(
+          MakeInstructionDescriptor(15, spv::Op::OpBranchConditional, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   // Can't move the instruction if the next instruction is the last one in the
   // block.
   ASSERT_FALSE(TransformationMoveInstructionDown(
-                   MakeInstructionDescriptor(21, SpvOpIAdd, 0))
+                   MakeInstructionDescriptor(21, spv::Op::OpIAdd, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // Can't insert instruction's opcode after its successor.
   ASSERT_FALSE(TransformationMoveInstructionDown(
-                   MakeInstructionDescriptor(15, SpvOpIMul, 0))
+                   MakeInstructionDescriptor(15, spv::Op::OpIMul, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // Instruction's successor depends on the instruction.
   ASSERT_FALSE(TransformationMoveInstructionDown(
-                   MakeInstructionDescriptor(10, SpvOpIAdd, 0))
+                   MakeInstructionDescriptor(10, spv::Op::OpIAdd, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   {
     TransformationMoveInstructionDown transformation(
-        MakeInstructionDescriptor(11, SpvOpISub, 0));
+        MakeInstructionDescriptor(11, spv::Op::OpISub, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -120,7 +121,7 @@
   }
   {
     TransformationMoveInstructionDown transformation(
-        MakeInstructionDescriptor(22, SpvOpIAdd, 0));
+        MakeInstructionDescriptor(22, spv::Op::OpIAdd, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -218,17 +219,17 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // Swap memory instruction with an unsupported one.
   ASSERT_FALSE(TransformationMoveInstructionDown(
-                   MakeInstructionDescriptor(22, SpvOpLoad, 0))
+                   MakeInstructionDescriptor(22, spv::Op::OpLoad, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // Swap memory barrier with an unsupported one.
   ASSERT_FALSE(TransformationMoveInstructionDown(
-                   MakeInstructionDescriptor(23, SpvOpMemoryBarrier, 0))
+                   MakeInstructionDescriptor(23, spv::Op::OpMemoryBarrier, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // Swap simple instruction with an unsupported one.
   TransformationMoveInstructionDown transformation(
-      MakeInstructionDescriptor(8, SpvOpCopyObject, 0));
+      MakeInstructionDescriptor(8, spv::Op::OpCopyObject, 0));
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
@@ -322,21 +323,21 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // Swap two barrier instructions.
   ASSERT_FALSE(TransformationMoveInstructionDown(
-                   MakeInstructionDescriptor(21, SpvOpMemoryBarrier, 0))
+                   MakeInstructionDescriptor(21, spv::Op::OpMemoryBarrier, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // Swap barrier and memory instructions.
   ASSERT_FALSE(TransformationMoveInstructionDown(
-                   MakeInstructionDescriptor(21, SpvOpMemoryBarrier, 2))
+                   MakeInstructionDescriptor(21, spv::Op::OpMemoryBarrier, 2))
                    .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationMoveInstructionDown(
-                   MakeInstructionDescriptor(22, SpvOpLoad, 0))
+                   MakeInstructionDescriptor(22, spv::Op::OpLoad, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // Swap barrier and simple instructions.
   {
     TransformationMoveInstructionDown transformation(
-        MakeInstructionDescriptor(23, SpvOpCopyObject, 0));
+        MakeInstructionDescriptor(23, spv::Op::OpCopyObject, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -346,7 +347,7 @@
   }
   {
     TransformationMoveInstructionDown transformation(
-        MakeInstructionDescriptor(22, SpvOpMemoryBarrier, 1));
+        MakeInstructionDescriptor(22, spv::Op::OpMemoryBarrier, 1));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -406,7 +407,7 @@
   // Swap simple and barrier instructions.
   {
     TransformationMoveInstructionDown transformation(
-        MakeInstructionDescriptor(40, SpvOpCopyObject, 0));
+        MakeInstructionDescriptor(40, spv::Op::OpCopyObject, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -416,7 +417,7 @@
   }
   {
     TransformationMoveInstructionDown transformation(
-        MakeInstructionDescriptor(21, SpvOpMemoryBarrier, 0));
+        MakeInstructionDescriptor(21, spv::Op::OpMemoryBarrier, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -428,7 +429,7 @@
   // Swap simple and memory instructions.
   {
     TransformationMoveInstructionDown transformation(
-        MakeInstructionDescriptor(41, SpvOpCopyObject, 0));
+        MakeInstructionDescriptor(41, spv::Op::OpCopyObject, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -438,7 +439,7 @@
   }
   {
     TransformationMoveInstructionDown transformation(
-        MakeInstructionDescriptor(22, SpvOpLoad, 0));
+        MakeInstructionDescriptor(22, spv::Op::OpLoad, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -450,7 +451,7 @@
   // Swap two simple instructions.
   {
     TransformationMoveInstructionDown transformation(
-        MakeInstructionDescriptor(23, SpvOpCopyObject, 0));
+        MakeInstructionDescriptor(23, spv::Op::OpCopyObject, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -625,22 +626,22 @@
 
   protobufs::InstructionDescriptor invalid_swaps[] = {
       // R and RW
-      MakeInstructionDescriptor(25, SpvOpLoad, 0),
+      MakeInstructionDescriptor(25, spv::Op::OpLoad, 0),
 
       // R and W
-      MakeInstructionDescriptor(29, SpvOpLoad, 0),
+      MakeInstructionDescriptor(29, spv::Op::OpLoad, 0),
 
       // RW and RW
-      MakeInstructionDescriptor(32, SpvOpCopyMemory, 0),
-      MakeInstructionDescriptor(32, SpvOpCopyMemory, 2),
-      MakeInstructionDescriptor(32, SpvOpCopyMemory, 4),
+      MakeInstructionDescriptor(32, spv::Op::OpCopyMemory, 0),
+      MakeInstructionDescriptor(32, spv::Op::OpCopyMemory, 2),
+      MakeInstructionDescriptor(32, spv::Op::OpCopyMemory, 4),
 
       // RW and W
-      MakeInstructionDescriptor(32, SpvOpCopyMemory, 12),
-      MakeInstructionDescriptor(32, SpvOpStore, 1),
+      MakeInstructionDescriptor(32, spv::Op::OpCopyMemory, 12),
+      MakeInstructionDescriptor(32, spv::Op::OpStore, 1),
 
       // W and W
-      MakeInstructionDescriptor(32, SpvOpStore, 6),
+      MakeInstructionDescriptor(32, spv::Op::OpStore, 6),
   };
 
   for (const auto& descriptor : invalid_swaps) {
@@ -651,55 +652,55 @@
   // Valid swaps.
   protobufs::InstructionDescriptor valid_swaps[] = {
       // R and R
-      MakeInstructionDescriptor(23, SpvOpLoad, 0),
-      MakeInstructionDescriptor(24, SpvOpLoad, 0),
+      MakeInstructionDescriptor(23, spv::Op::OpLoad, 0),
+      MakeInstructionDescriptor(24, spv::Op::OpLoad, 0),
 
       // R and RW
-      MakeInstructionDescriptor(26, SpvOpLoad, 0),
-      MakeInstructionDescriptor(25, SpvOpCopyMemory, 1),
+      MakeInstructionDescriptor(26, spv::Op::OpLoad, 0),
+      MakeInstructionDescriptor(25, spv::Op::OpCopyMemory, 1),
 
-      MakeInstructionDescriptor(27, SpvOpLoad, 0),
-      MakeInstructionDescriptor(26, SpvOpCopyMemory, 1),
+      MakeInstructionDescriptor(27, spv::Op::OpLoad, 0),
+      MakeInstructionDescriptor(26, spv::Op::OpCopyMemory, 1),
 
-      MakeInstructionDescriptor(28, SpvOpLoad, 0),
-      MakeInstructionDescriptor(27, SpvOpCopyMemory, 1),
+      MakeInstructionDescriptor(28, spv::Op::OpLoad, 0),
+      MakeInstructionDescriptor(27, spv::Op::OpCopyMemory, 1),
 
       // R and W
-      MakeInstructionDescriptor(30, SpvOpLoad, 0),
-      MakeInstructionDescriptor(29, SpvOpStore, 1),
+      MakeInstructionDescriptor(30, spv::Op::OpLoad, 0),
+      MakeInstructionDescriptor(29, spv::Op::OpStore, 1),
 
-      MakeInstructionDescriptor(31, SpvOpLoad, 0),
-      MakeInstructionDescriptor(30, SpvOpStore, 1),
+      MakeInstructionDescriptor(31, spv::Op::OpLoad, 0),
+      MakeInstructionDescriptor(30, spv::Op::OpStore, 1),
 
-      MakeInstructionDescriptor(32, SpvOpLoad, 0),
-      MakeInstructionDescriptor(31, SpvOpStore, 1),
+      MakeInstructionDescriptor(32, spv::Op::OpLoad, 0),
+      MakeInstructionDescriptor(31, spv::Op::OpStore, 1),
 
       // RW and RW
-      MakeInstructionDescriptor(32, SpvOpCopyMemory, 6),
-      MakeInstructionDescriptor(32, SpvOpCopyMemory, 6),
+      MakeInstructionDescriptor(32, spv::Op::OpCopyMemory, 6),
+      MakeInstructionDescriptor(32, spv::Op::OpCopyMemory, 6),
 
-      MakeInstructionDescriptor(32, SpvOpCopyMemory, 8),
-      MakeInstructionDescriptor(32, SpvOpCopyMemory, 8),
+      MakeInstructionDescriptor(32, spv::Op::OpCopyMemory, 8),
+      MakeInstructionDescriptor(32, spv::Op::OpCopyMemory, 8),
 
-      MakeInstructionDescriptor(32, SpvOpCopyMemory, 10),
-      MakeInstructionDescriptor(32, SpvOpCopyMemory, 10),
+      MakeInstructionDescriptor(32, spv::Op::OpCopyMemory, 10),
+      MakeInstructionDescriptor(32, spv::Op::OpCopyMemory, 10),
 
       // RW and W
-      MakeInstructionDescriptor(32, SpvOpCopyMemory, 14),
-      MakeInstructionDescriptor(32, SpvOpStore, 3),
+      MakeInstructionDescriptor(32, spv::Op::OpCopyMemory, 14),
+      MakeInstructionDescriptor(32, spv::Op::OpStore, 3),
 
-      MakeInstructionDescriptor(32, SpvOpCopyMemory, 15),
-      MakeInstructionDescriptor(32, SpvOpStore, 4),
+      MakeInstructionDescriptor(32, spv::Op::OpCopyMemory, 15),
+      MakeInstructionDescriptor(32, spv::Op::OpStore, 4),
 
-      MakeInstructionDescriptor(32, SpvOpCopyMemory, 16),
-      MakeInstructionDescriptor(32, SpvOpStore, 5),
+      MakeInstructionDescriptor(32, spv::Op::OpCopyMemory, 16),
+      MakeInstructionDescriptor(32, spv::Op::OpStore, 5),
 
       // W and W
-      MakeInstructionDescriptor(32, SpvOpStore, 8),
-      MakeInstructionDescriptor(32, SpvOpStore, 8),
+      MakeInstructionDescriptor(32, spv::Op::OpStore, 8),
+      MakeInstructionDescriptor(32, spv::Op::OpStore, 8),
 
-      MakeInstructionDescriptor(32, SpvOpStore, 10),
-      MakeInstructionDescriptor(32, SpvOpStore, 10),
+      MakeInstructionDescriptor(32, spv::Op::OpStore, 10),
+      MakeInstructionDescriptor(32, spv::Op::OpStore, 10),
   };
 
   for (const auto& descriptor : valid_swaps) {
diff --git a/test/fuzz/transformation_mutate_pointer_test.cpp b/test/fuzz/transformation_mutate_pointer_test.cpp
index e869efa..e0cb615 100644
--- a/test/fuzz/transformation_mutate_pointer_test.cpp
+++ b/test/fuzz/transformation_mutate_pointer_test.cpp
@@ -86,7 +86,8 @@
   transformation_context.GetFactManager()->AddFactIdIsIrrelevant(35);
   transformation_context.GetFactManager()->AddFactIdIsIrrelevant(39);
 
-  const auto insert_before = MakeInstructionDescriptor(26, SpvOpReturn, 0);
+  const auto insert_before =
+      MakeInstructionDescriptor(26, spv::Op::OpReturn, 0);
 
   // 20 is not a fresh id.
   ASSERT_FALSE(TransformationMutatePointer(20, 20, insert_before)
@@ -94,13 +95,14 @@
 
   // |insert_before| instruction descriptor is invalid.
   ASSERT_FALSE(TransformationMutatePointer(
-                   20, 70, MakeInstructionDescriptor(26, SpvOpStore, 0))
+                   20, 70, MakeInstructionDescriptor(26, spv::Op::OpStore, 0))
                    .IsApplicable(context.get(), transformation_context));
 
   // Can't insert OpLoad before OpVariable.
-  ASSERT_FALSE(TransformationMutatePointer(
-                   20, 70, MakeInstructionDescriptor(26, SpvOpVariable, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationMutatePointer(
+          20, 70, MakeInstructionDescriptor(26, spv::Op::OpVariable, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   // |pointer_id| doesn't exist in the module.
   ASSERT_FALSE(TransformationMutatePointer(70, 70, insert_before)
@@ -131,9 +133,10 @@
                    .IsApplicable(context.get(), transformation_context));
 
   // |pointer_id| is not available before |insert_before|.
-  ASSERT_FALSE(TransformationMutatePointer(
-                   26, 70, MakeInstructionDescriptor(26, SpvOpAccessChain, 0))
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationMutatePointer(
+          26, 70, MakeInstructionDescriptor(26, spv::Op::OpAccessChain, 0))
+          .IsApplicable(context.get(), transformation_context));
 
   transformation_context.GetFactManager()->AddFactIdIsIrrelevant(40);
 
@@ -274,7 +277,8 @@
   ASSERT_FALSE(
       context->GetDominatorAnalysis(context->GetFunction(4))->IsReachable(10));
 
-  const auto insert_before = MakeInstructionDescriptor(10, SpvOpReturn, 0);
+  const auto insert_before =
+      MakeInstructionDescriptor(10, spv::Op::OpReturn, 0);
 
   // Can mutate a global variable in an unreachable block.
   TransformationMutatePointer transformation(12, 50, insert_before);
diff --git a/test/fuzz/transformation_permute_phi_operands_test.cpp b/test/fuzz/transformation_permute_phi_operands_test.cpp
index 0774dcf..320dd1d 100644
--- a/test/fuzz/transformation_permute_phi_operands_test.cpp
+++ b/test/fuzz/transformation_permute_phi_operands_test.cpp
@@ -128,11 +128,11 @@
   context->get_def_use_mgr()->ForEachUse(
       25, [&found_use_in_store, &found_use_in_add_lhs, &found_use_in_add_rhs](
               opt::Instruction* inst, uint32_t operand_index) {
-        if (inst->opcode() == SpvOpStore) {
+        if (inst->opcode() == spv::Op::OpStore) {
           ASSERT_FALSE(found_use_in_store);
           found_use_in_store = true;
         } else {
-          ASSERT_EQ(SpvOpIAdd, inst->opcode());
+          ASSERT_EQ(spv::Op::OpIAdd, inst->opcode());
           if (operand_index == 2) {
             ASSERT_FALSE(found_use_in_add_lhs);
             found_use_in_add_lhs = true;
diff --git a/test/fuzz/transformation_propagate_instruction_down_test.cpp b/test/fuzz/transformation_propagate_instruction_down_test.cpp
index 52974ca..8bedef2 100644
--- a/test/fuzz/transformation_propagate_instruction_down_test.cpp
+++ b/test/fuzz/transformation_propagate_instruction_down_test.cpp
@@ -499,13 +499,13 @@
     TransformationPropagateInstructionDown transformation(
         5, 200, {{{15, 203}, {16, 204}}});
     ASSERT_FALSE(context->get_feature_mgr()->HasCapability(
-        SpvCapabilityVariablePointersStorageBuffer));
+        spv::Capability::VariablePointersStorageBuffer));
     ASSERT_FALSE(
         transformation.IsApplicable(context.get(), transformation_context));
 
-    context->AddCapability(SpvCapabilityVariablePointers);
+    context->AddCapability(spv::Capability::VariablePointers);
     ASSERT_TRUE(context->get_feature_mgr()->HasCapability(
-        SpvCapabilityVariablePointersStorageBuffer));
+        spv::Capability::VariablePointersStorageBuffer));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
diff --git a/test/fuzz/transformation_propagate_instruction_up_test.cpp b/test/fuzz/transformation_propagate_instruction_up_test.cpp
index 8a04270..20cf4b3 100644
--- a/test/fuzz/transformation_propagate_instruction_up_test.cpp
+++ b/test/fuzz/transformation_propagate_instruction_up_test.cpp
@@ -699,7 +699,7 @@
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  context->AddCapability(SpvCapabilityVariablePointers);
+  context->AddCapability(spv::Capability::VariablePointers);
 
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
@@ -779,7 +779,7 @@
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  context->AddCapability(SpvCapabilityVariablePointersStorageBuffer);
+  context->AddCapability(spv::Capability::VariablePointersStorageBuffer);
 
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
diff --git a/test/fuzz/transformation_push_id_through_variable_test.cpp b/test/fuzz/transformation_push_id_through_variable_test.cpp
index b0fff58..0d4850d 100644
--- a/test/fuzz/transformation_push_id_through_variable_test.cpp
+++ b/test/fuzz/transformation_push_id_through_variable_test.cpp
@@ -110,9 +110,9 @@
   uint32_t value_synonym_id = 62;
   uint32_t variable_id = 63;
   uint32_t initializer_id = 23;
-  uint32_t variable_storage_class = SpvStorageClassPrivate;
+  uint32_t variable_storage_class = (uint32_t)spv::StorageClass::Private;
   auto instruction_descriptor =
-      MakeInstructionDescriptor(95, SpvOpReturnValue, 0);
+      MakeInstructionDescriptor(95, spv::Op::OpReturnValue, 0);
   auto transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -124,8 +124,9 @@
   value_synonym_id = 60;
   variable_id = 61;
   initializer_id = 80;
-  variable_storage_class = SpvStorageClassFunction;
-  instruction_descriptor = MakeInstructionDescriptor(38, SpvOpAccessChain, 0);
+  variable_storage_class = (uint32_t)spv::StorageClass::Function;
+  instruction_descriptor =
+      MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0);
   transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -137,8 +138,9 @@
   value_synonym_id = 62;
   variable_id = 63;
   initializer_id = 80;
-  variable_storage_class = SpvStorageClassFunction;
-  instruction_descriptor = MakeInstructionDescriptor(64, SpvOpAccessChain, 0);
+  variable_storage_class = (uint32_t)spv::StorageClass::Function;
+  instruction_descriptor =
+      MakeInstructionDescriptor(64, spv::Op::OpAccessChain, 0);
   transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -151,8 +153,9 @@
   value_synonym_id = 62;
   variable_id = 63;
   initializer_id = 24;
-  variable_storage_class = SpvStorageClassFunction;
-  instruction_descriptor = MakeInstructionDescriptor(27, SpvOpVariable, 0);
+  variable_storage_class = (uint32_t)spv::StorageClass::Function;
+  instruction_descriptor =
+      MakeInstructionDescriptor(27, spv::Op::OpVariable, 0);
   transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -164,8 +167,9 @@
   value_synonym_id = 62;
   variable_id = 63;
   initializer_id = 80;
-  variable_storage_class = SpvStorageClassFunction;
-  instruction_descriptor = MakeInstructionDescriptor(100, SpvOpUnreachable, 0);
+  variable_storage_class = (uint32_t)spv::StorageClass::Function;
+  instruction_descriptor =
+      MakeInstructionDescriptor(100, spv::Op::OpUnreachable, 0);
   transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -177,8 +181,9 @@
   value_synonym_id = 62;
   variable_id = 63;
   initializer_id = 23;
-  variable_storage_class = SpvStorageClassFunction;
-  instruction_descriptor = MakeInstructionDescriptor(95, SpvOpReturnValue, 0);
+  variable_storage_class = (uint32_t)spv::StorageClass::Function;
+  instruction_descriptor =
+      MakeInstructionDescriptor(95, spv::Op::OpReturnValue, 0);
   transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -190,8 +195,9 @@
   value_synonym_id = 62;
   variable_id = 63;
   initializer_id = 80;
-  variable_storage_class = SpvStorageClassPrivate;
-  instruction_descriptor = MakeInstructionDescriptor(95, SpvOpReturnValue, 0);
+  variable_storage_class = (uint32_t)spv::StorageClass::Private;
+  instruction_descriptor =
+      MakeInstructionDescriptor(95, spv::Op::OpReturnValue, 0);
   transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -203,8 +209,9 @@
   value_synonym_id = 62;
   variable_id = 63;
   initializer_id = 93;
-  variable_storage_class = SpvStorageClassInput;
-  instruction_descriptor = MakeInstructionDescriptor(95, SpvOpReturnValue, 0);
+  variable_storage_class = (uint32_t)spv::StorageClass::Input;
+  instruction_descriptor =
+      MakeInstructionDescriptor(95, spv::Op::OpReturnValue, 0);
   transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -219,8 +226,9 @@
   value_synonym_id = 62;
   variable_id = 63;
   initializer_id = 80;
-  variable_storage_class = SpvStorageClassFunction;
-  instruction_descriptor = MakeInstructionDescriptor(40, SpvOpAccessChain, 0);
+  variable_storage_class = (uint32_t)spv::StorageClass::Function;
+  instruction_descriptor =
+      MakeInstructionDescriptor(40, spv::Op::OpAccessChain, 0);
   transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -232,8 +240,9 @@
   value_synonym_id = 62;
   variable_id = 63;
   initializer_id = 95;
-  variable_storage_class = SpvStorageClassFunction;
-  instruction_descriptor = MakeInstructionDescriptor(40, SpvOpAccessChain, 0);
+  variable_storage_class = (uint32_t)spv::StorageClass::Function;
+  instruction_descriptor =
+      MakeInstructionDescriptor(40, spv::Op::OpAccessChain, 0);
   transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -245,8 +254,9 @@
   value_synonym_id = 62;
   variable_id = 63;
   initializer_id = 93;
-  variable_storage_class = SpvStorageClassFunction;
-  instruction_descriptor = MakeInstructionDescriptor(40, SpvOpAccessChain, 0);
+  variable_storage_class = (uint32_t)spv::StorageClass::Function;
+  instruction_descriptor =
+      MakeInstructionDescriptor(40, spv::Op::OpAccessChain, 0);
   transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -335,9 +345,9 @@
   uint32_t value_synonym_id = 100;
   uint32_t variable_id = 101;
   uint32_t initializer_id = 80;
-  uint32_t variable_storage_class = SpvStorageClassFunction;
+  uint32_t variable_storage_class = (uint32_t)spv::StorageClass::Function;
   auto instruction_descriptor =
-      MakeInstructionDescriptor(38, SpvOpAccessChain, 0);
+      MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0);
   auto transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -346,18 +356,18 @@
   ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(variable_id));
   ASSERT_EQ(nullptr, context->get_instr_block(variable_id));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
-  ASSERT_EQ(SpvOpLoad,
+  ASSERT_EQ(spv::Op::OpLoad,
             context->get_def_use_mgr()->GetDef(value_synonym_id)->opcode());
   ASSERT_EQ(36, context->get_instr_block(value_synonym_id)->id());
-  ASSERT_EQ(SpvOpVariable,
+  ASSERT_EQ(spv::Op::OpVariable,
             context->get_def_use_mgr()->GetDef(variable_id)->opcode());
   ASSERT_EQ(5, context->get_instr_block(variable_id)->id());
   uint32_t variable_use_count = 0;
   context->get_def_use_mgr()->ForEachUse(
       variable_id,
       [&variable_use_count](opt::Instruction* inst, uint32_t /*unused*/) {
-        ASSERT_TRUE(inst->opcode() == SpvOpLoad ||
-                    inst->opcode() == SpvOpStore);
+        ASSERT_TRUE(inst->opcode() == spv::Op::OpLoad ||
+                    inst->opcode() == spv::Op::OpStore);
         variable_use_count++;
       });
   ASSERT_EQ(2, variable_use_count);
@@ -366,8 +376,9 @@
   value_synonym_id = 102;
   variable_id = 103;
   initializer_id = 21;
-  variable_storage_class = SpvStorageClassFunction;
-  instruction_descriptor = MakeInstructionDescriptor(38, SpvOpAccessChain, 0);
+  variable_storage_class = (uint32_t)spv::StorageClass::Function;
+  instruction_descriptor =
+      MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0);
   transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -377,8 +388,9 @@
   value_synonym_id = 104;
   variable_id = 105;
   initializer_id = 80;
-  variable_storage_class = SpvStorageClassFunction;
-  instruction_descriptor = MakeInstructionDescriptor(95, SpvOpReturnValue, 0);
+  variable_storage_class = (uint32_t)spv::StorageClass::Function;
+  instruction_descriptor =
+      MakeInstructionDescriptor(95, spv::Op::OpReturnValue, 0);
   transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -388,8 +400,9 @@
   value_synonym_id = 106;
   variable_id = 107;
   initializer_id = 80;
-  variable_storage_class = SpvStorageClassFunction;
-  instruction_descriptor = MakeInstructionDescriptor(95, SpvOpReturnValue, 0);
+  variable_storage_class = (uint32_t)spv::StorageClass::Function;
+  instruction_descriptor =
+      MakeInstructionDescriptor(95, spv::Op::OpReturnValue, 0);
   transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -399,8 +412,9 @@
   value_synonym_id = 108;
   variable_id = 109;
   initializer_id = 21;
-  variable_storage_class = SpvStorageClassPrivate;
-  instruction_descriptor = MakeInstructionDescriptor(95, SpvOpReturnValue, 0);
+  variable_storage_class = (uint32_t)spv::StorageClass::Private;
+  instruction_descriptor =
+      MakeInstructionDescriptor(95, spv::Op::OpReturnValue, 0);
   transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -410,8 +424,8 @@
   value_synonym_id = 110;
   variable_id = 111;
   initializer_id = 21;
-  variable_storage_class = SpvStorageClassPrivate;
-  instruction_descriptor = MakeInstructionDescriptor(27, SpvOpStore, 0);
+  variable_storage_class = (uint32_t)spv::StorageClass::Private;
+  instruction_descriptor = MakeInstructionDescriptor(27, spv::Op::OpStore, 0);
   transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -602,9 +616,9 @@
   uint32_t value_synonym_id = 62;
   uint32_t variable_id = 63;
   uint32_t initializer_id = 23;
-  uint32_t variable_storage_class = SpvStorageClassPrivate;
+  uint32_t variable_storage_class = (uint32_t)spv::StorageClass::Private;
   auto instruction_descriptor =
-      MakeInstructionDescriptor(95, SpvOpReturnValue, 0);
+      MakeInstructionDescriptor(95, spv::Op::OpReturnValue, 0);
   auto transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -705,9 +719,9 @@
   uint32_t value_synonym_id = 62;
   uint32_t variable_id = 63;
   uint32_t initializer_id = 23;
-  uint32_t variable_storage_class = SpvStorageClassPrivate;
+  uint32_t variable_storage_class = (uint32_t)spv::StorageClass::Private;
   auto instruction_descriptor =
-      MakeInstructionDescriptor(95, SpvOpReturnValue, 0);
+      MakeInstructionDescriptor(95, spv::Op::OpReturnValue, 0);
   auto transformation = TransformationPushIdThroughVariable(
       value_id, value_synonym_id, variable_id, variable_storage_class,
       initializer_id, instruction_descriptor);
@@ -766,8 +780,8 @@
 
   transformation_context.GetFactManager()->AddFactBlockIsDead(15);
   auto transformation = TransformationPushIdThroughVariable(
-      14, 100, 101, SpvStorageClassFunction, 14,
-      MakeInstructionDescriptor(15, SpvOpBranch, 0));
+      14, 100, 101, uint32_t(spv::StorageClass::Function), 14,
+      MakeInstructionDescriptor(15, spv::Op::OpBranch, 0));
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
diff --git a/test/fuzz/transformation_replace_boolean_constant_with_constant_binary_test.cpp b/test/fuzz/transformation_replace_boolean_constant_with_constant_binary_test.cpp
index b8c2a8a..65cf3d4 100644
--- a/test/fuzz/transformation_replace_boolean_constant_with_constant_binary_test.cpp
+++ b/test/fuzz/transformation_replace_boolean_constant_with_constant_binary_test.cpp
@@ -167,34 +167,38 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   std::vector<protobufs::IdUseDescriptor> uses_of_true = {
-      MakeIdUseDescriptor(41, MakeInstructionDescriptor(44, SpvOpStore, 12), 1),
-      MakeIdUseDescriptor(41, MakeInstructionDescriptor(46, SpvOpLogicalOr, 0),
-                          0)};
+      MakeIdUseDescriptor(
+          41, MakeInstructionDescriptor(44, spv::Op::OpStore, 12), 1),
+      MakeIdUseDescriptor(
+          41, MakeInstructionDescriptor(46, spv::Op::OpLogicalOr, 0), 0)};
 
   std::vector<protobufs::IdUseDescriptor> uses_of_false = {
-      MakeIdUseDescriptor(43, MakeInstructionDescriptor(44, SpvOpStore, 13), 1),
-      MakeIdUseDescriptor(43, MakeInstructionDescriptor(48, SpvOpLogicalAnd, 0),
-                          1)};
+      MakeIdUseDescriptor(
+          43, MakeInstructionDescriptor(44, spv::Op::OpStore, 13), 1),
+      MakeIdUseDescriptor(
+          43, MakeInstructionDescriptor(48, spv::Op::OpLogicalAnd, 0), 1)};
 
   const uint32_t fresh_id = 100;
 
-  std::vector<SpvOp> fp_gt_opcodes = {
-      SpvOpFOrdGreaterThan, SpvOpFOrdGreaterThanEqual, SpvOpFUnordGreaterThan,
-      SpvOpFUnordGreaterThanEqual};
+  std::vector<spv::Op> fp_gt_opcodes = {
+      spv::Op::OpFOrdGreaterThan, spv::Op::OpFOrdGreaterThanEqual,
+      spv::Op::OpFUnordGreaterThan, spv::Op::OpFUnordGreaterThanEqual};
 
-  std::vector<SpvOp> fp_lt_opcodes = {SpvOpFOrdLessThan, SpvOpFOrdLessThanEqual,
-                                      SpvOpFUnordLessThan,
-                                      SpvOpFUnordLessThanEqual};
+  std::vector<spv::Op> fp_lt_opcodes = {
+      spv::Op::OpFOrdLessThan, spv::Op::OpFOrdLessThanEqual,
+      spv::Op::OpFUnordLessThan, spv::Op::OpFUnordLessThanEqual};
 
-  std::vector<SpvOp> int_gt_opcodes = {SpvOpSGreaterThan,
-                                       SpvOpSGreaterThanEqual};
+  std::vector<spv::Op> int_gt_opcodes = {spv::Op::OpSGreaterThan,
+                                         spv::Op::OpSGreaterThanEqual};
 
-  std::vector<SpvOp> int_lt_opcodes = {SpvOpSLessThan, SpvOpSLessThanEqual};
+  std::vector<spv::Op> int_lt_opcodes = {spv::Op::OpSLessThan,
+                                         spv::Op::OpSLessThanEqual};
 
-  std::vector<SpvOp> uint_gt_opcodes = {SpvOpUGreaterThan,
-                                        SpvOpUGreaterThanEqual};
+  std::vector<spv::Op> uint_gt_opcodes = {spv::Op::OpUGreaterThan,
+                                          spv::Op::OpUGreaterThanEqual};
 
-  std::vector<SpvOp> uint_lt_opcodes = {SpvOpULessThan, SpvOpULessThanEqual};
+  std::vector<spv::Op> uint_lt_opcodes = {spv::Op::OpULessThan,
+                                          spv::Op::OpULessThanEqual};
 
 #define CHECK_OPERATOR(USE_DESCRIPTOR, LHS_ID, RHS_ID, OPCODE, FRESH_ID) \
   ASSERT_TRUE(TransformationReplaceBooleanConstantWithConstantBinary(    \
@@ -253,41 +257,41 @@
 
   // Target id is not fresh
   ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary(
-                   uses_of_true[0], 15, 17, SpvOpFOrdLessThan, 15)
+                   uses_of_true[0], 15, 17, spv::Op::OpFOrdLessThan, 15)
                    .IsApplicable(context.get(), transformation_context));
 
   // LHS id does not exist
   ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary(
-                   uses_of_true[0], 300, 17, SpvOpFOrdLessThan, 200)
+                   uses_of_true[0], 300, 17, spv::Op::OpFOrdLessThan, 200)
                    .IsApplicable(context.get(), transformation_context));
 
   // RHS id does not exist
   ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary(
-                   uses_of_true[0], 15, 300, SpvOpFOrdLessThan, 200)
+                   uses_of_true[0], 15, 300, spv::Op::OpFOrdLessThan, 200)
                    .IsApplicable(context.get(), transformation_context));
 
   // LHS and RHS ids do not match type
   ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary(
-                   uses_of_true[0], 11, 17, SpvOpFOrdLessThan, 200)
+                   uses_of_true[0], 11, 17, spv::Op::OpFOrdLessThan, 200)
                    .IsApplicable(context.get(), transformation_context));
 
   // Opcode not appropriate
   ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary(
-                   uses_of_true[0], 15, 17, SpvOpFDiv, 200)
+                   uses_of_true[0], 15, 17, spv::Op::OpFDiv, 200)
                    .IsApplicable(context.get(), transformation_context));
 
   auto replace_true_with_double_comparison =
       TransformationReplaceBooleanConstantWithConstantBinary(
-          uses_of_true[0], 11, 9, SpvOpFUnordGreaterThan, 100);
+          uses_of_true[0], 11, 9, spv::Op::OpFUnordGreaterThan, 100);
   auto replace_true_with_uint32_comparison =
       TransformationReplaceBooleanConstantWithConstantBinary(
-          uses_of_true[1], 27, 29, SpvOpULessThanEqual, 101);
+          uses_of_true[1], 27, 29, spv::Op::OpULessThanEqual, 101);
   auto replace_false_with_float_comparison =
       TransformationReplaceBooleanConstantWithConstantBinary(
-          uses_of_false[0], 17, 15, SpvOpFOrdLessThan, 102);
+          uses_of_false[0], 17, 15, spv::Op::OpFOrdLessThan, 102);
   auto replace_false_with_sint64_comparison =
       TransformationReplaceBooleanConstantWithConstantBinary(
-          uses_of_false[1], 33, 31, SpvOpSLessThan, 103);
+          uses_of_false[1], 33, 31, spv::Op::OpSLessThan, 103);
 
   ASSERT_TRUE(replace_true_with_double_comparison.IsApplicable(
       context.get(), transformation_context));
@@ -423,13 +427,13 @@
         {SPV_OPERAND_TYPE_LITERAL_INTEGER, {words[0]}},
         {SPV_OPERAND_TYPE_LITERAL_INTEGER, {words[1]}}};
     context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-        context.get(), SpvOpConstant, 6, 200, operands));
+        context.get(), spv::Op::OpConstant, 6, 200, operands));
     fuzzerutil::UpdateModuleIdBound(context.get(), 200);
     ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
         context.get(), validator_options, kConsoleMessageConsumer));
     // The transformation is not applicable because %200 is NaN.
     ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary(
-                     uses_of_true[0], 11, 200, SpvOpFOrdLessThan, 300)
+                     uses_of_true[0], 11, 200, spv::Op::OpFOrdLessThan, 300)
                      .IsApplicable(context.get(), transformation_context));
   }
   if (std::numeric_limits<double>::has_infinity) {
@@ -440,14 +444,14 @@
         {SPV_OPERAND_TYPE_LITERAL_INTEGER, {words[0]}},
         {SPV_OPERAND_TYPE_LITERAL_INTEGER, {words[1]}}};
     context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-        context.get(), SpvOpConstant, 6, 201, operands));
+        context.get(), spv::Op::OpConstant, 6, 201, operands));
     fuzzerutil::UpdateModuleIdBound(context.get(), 201);
     ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
         context.get(), validator_options, kConsoleMessageConsumer));
     // Even though the double constant %11 is less than the infinity %201, the
     // transformation is restricted to only apply to finite values.
     ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary(
-                     uses_of_true[0], 11, 201, SpvOpFOrdLessThan, 300)
+                     uses_of_true[0], 11, 201, spv::Op::OpFOrdLessThan, 300)
                      .IsApplicable(context.get(), transformation_context));
   }
   if (std::numeric_limits<float>::has_infinity) {
@@ -459,13 +463,14 @@
     memcpy(words_negative_infinity, &negative_infinity_float, sizeof(float));
     opt::Instruction::OperandList operands_positive_infinity = {
         {SPV_OPERAND_TYPE_LITERAL_INTEGER, {words_positive_infinity[0]}}};
-    context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-        context.get(), SpvOpConstant, 12, 202, operands_positive_infinity));
+    context->module()->AddGlobalValue(
+        MakeUnique<opt::Instruction>(context.get(), spv::Op::OpConstant, 12,
+                                     202, operands_positive_infinity));
     fuzzerutil::UpdateModuleIdBound(context.get(), 202);
     opt::Instruction::OperandList operands = {
         {SPV_OPERAND_TYPE_LITERAL_INTEGER, {words_negative_infinity[0]}}};
     context->module()->AddGlobalValue(MakeUnique<opt::Instruction>(
-        context.get(), SpvOpConstant, 12, 203, operands));
+        context.get(), spv::Op::OpConstant, 12, 203, operands));
     fuzzerutil::UpdateModuleIdBound(context.get(), 203);
     ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
         context.get(), validator_options, kConsoleMessageConsumer));
@@ -473,7 +478,7 @@
     // infinity %202, the transformation is restricted to only apply to finite
     // values.
     ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary(
-                     uses_of_true[0], 203, 202, SpvOpFOrdLessThan, 300)
+                     uses_of_true[0], 203, 202, spv::Op::OpFOrdLessThan, 300)
                      .IsApplicable(context.get(), transformation_context));
   }
 }
@@ -547,14 +552,14 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   auto use_of_true_in_if = MakeIdUseDescriptor(
-      13, MakeInstructionDescriptor(10, SpvOpBranchConditional, 0), 0);
+      13, MakeInstructionDescriptor(10, spv::Op::OpBranchConditional, 0), 0);
   auto use_of_false_in_while = MakeIdUseDescriptor(
-      21, MakeInstructionDescriptor(16, SpvOpBranchConditional, 0), 0);
+      21, MakeInstructionDescriptor(16, spv::Op::OpBranchConditional, 0), 0);
 
   auto replacement_1 = TransformationReplaceBooleanConstantWithConstantBinary(
-      use_of_true_in_if, 9, 11, SpvOpSLessThan, 100);
+      use_of_true_in_if, 9, 11, spv::Op::OpSLessThan, 100);
   auto replacement_2 = TransformationReplaceBooleanConstantWithConstantBinary(
-      use_of_false_in_while, 9, 11, SpvOpSGreaterThanEqual, 101);
+      use_of_false_in_while, 9, 11, spv::Op::OpSGreaterThanEqual, 101);
 
   ASSERT_TRUE(
       replacement_1.IsApplicable(context.get(), transformation_context));
@@ -662,10 +667,11 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto instruction_descriptor = MakeInstructionDescriptor(14, SpvOpPhi, 0);
+  auto instruction_descriptor =
+      MakeInstructionDescriptor(14, spv::Op::OpPhi, 0);
   auto id_use_descriptor = MakeIdUseDescriptor(8, instruction_descriptor, 0);
   auto transformation = TransformationReplaceBooleanConstantWithConstantBinary(
-      id_use_descriptor, 6, 7, SpvOpULessThan, 15);
+      id_use_descriptor, 6, 7, spv::Op::OpULessThan, 15);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
@@ -740,11 +746,12 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  ASSERT_FALSE(TransformationReplaceBooleanConstantWithConstantBinary(
-                   MakeIdUseDescriptor(
-                       9, MakeInstructionDescriptor(50, SpvOpVariable, 0), 1),
-                   13, 15, SpvOpSLessThan, 100)
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationReplaceBooleanConstantWithConstantBinary(
+          MakeIdUseDescriptor(
+              9, MakeInstructionDescriptor(50, spv::Op::OpVariable, 0), 1),
+          13, 15, spv::Op::OpSLessThan, 100)
+          .IsApplicable(context.get(), transformation_context));
 }
 
 }  // namespace
diff --git a/test/fuzz/transformation_replace_branch_from_dead_block_with_exit_test.cpp b/test/fuzz/transformation_replace_branch_from_dead_block_with_exit_test.cpp
index 6bba14f..012e317 100644
--- a/test/fuzz/transformation_replace_branch_from_dead_block_with_exit_test.cpp
+++ b/test/fuzz/transformation_replace_branch_from_dead_block_with_exit_test.cpp
@@ -79,35 +79,37 @@
   transformation_context.GetFactManager()->AddFactBlockIsDead(20);
 
   // Bad: 4 is not a block
-  ASSERT_FALSE(TransformationReplaceBranchFromDeadBlockWithExit(4, SpvOpKill, 0)
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationReplaceBranchFromDeadBlockWithExit(4, spv::Op::OpKill, 0)
+          .IsApplicable(context.get(), transformation_context));
   // Bad: 200 does not exist
   ASSERT_FALSE(
-      TransformationReplaceBranchFromDeadBlockWithExit(200, SpvOpKill, 0)
+      TransformationReplaceBranchFromDeadBlockWithExit(200, spv::Op::OpKill, 0)
           .IsApplicable(context.get(), transformation_context));
   // Bad: 21 is not a dead block
   ASSERT_FALSE(
-      TransformationReplaceBranchFromDeadBlockWithExit(21, SpvOpKill, 0)
+      TransformationReplaceBranchFromDeadBlockWithExit(21, spv::Op::OpKill, 0)
           .IsApplicable(context.get(), transformation_context));
   // Bad: terminator of 8 is not OpBranch
-  ASSERT_FALSE(TransformationReplaceBranchFromDeadBlockWithExit(8, SpvOpKill, 0)
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationReplaceBranchFromDeadBlockWithExit(8, spv::Op::OpKill, 0)
+          .IsApplicable(context.get(), transformation_context));
   // Bad: 10's successor only has 10 as a predecessor
   ASSERT_FALSE(
-      TransformationReplaceBranchFromDeadBlockWithExit(10, SpvOpKill, 0)
+      TransformationReplaceBranchFromDeadBlockWithExit(10, spv::Op::OpKill, 0)
           .IsApplicable(context.get(), transformation_context));
 
 #ifndef NDEBUG
   ASSERT_DEATH(
-      TransformationReplaceBranchFromDeadBlockWithExit(20, SpvOpSwitch, 0)
+      TransformationReplaceBranchFromDeadBlockWithExit(20, spv::Op::OpSwitch, 0)
           .IsApplicable(context.get(), transformation_context),
       "Invalid early exit opcode.");
 #endif
 
   auto transformation1 =
-      TransformationReplaceBranchFromDeadBlockWithExit(20, SpvOpKill, 0);
+      TransformationReplaceBranchFromDeadBlockWithExit(20, spv::Op::OpKill, 0);
   auto transformation2 =
-      TransformationReplaceBranchFromDeadBlockWithExit(16, SpvOpKill, 0);
+      TransformationReplaceBranchFromDeadBlockWithExit(16, spv::Op::OpKill, 0);
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
@@ -281,48 +283,48 @@
 
   // Bad: OpKill not allowed in vertex shader
   ASSERT_FALSE(
-      TransformationReplaceBranchFromDeadBlockWithExit(201, SpvOpKill, 0)
+      TransformationReplaceBranchFromDeadBlockWithExit(201, spv::Op::OpKill, 0)
           .IsApplicable(context.get(), transformation_context));
 
   // Bad: OpReturn is not allowed in function that expects a returned value.
-  ASSERT_FALSE(
-      TransformationReplaceBranchFromDeadBlockWithExit(200, SpvOpReturn, 0)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationReplaceBranchFromDeadBlockWithExit(
+                   200, spv::Op::OpReturn, 0)
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: Return value id does not exist
   ASSERT_FALSE(TransformationReplaceBranchFromDeadBlockWithExit(
-                   201, SpvOpReturnValue, 1000)
+                   201, spv::Op::OpReturnValue, 1000)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: Return value id does not have a type
-  ASSERT_FALSE(
-      TransformationReplaceBranchFromDeadBlockWithExit(200, SpvOpReturnValue, 6)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationReplaceBranchFromDeadBlockWithExit(
+                   200, spv::Op::OpReturnValue, 6)
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: Return value id does not have the right type
   ASSERT_FALSE(TransformationReplaceBranchFromDeadBlockWithExit(
-                   201, SpvOpReturnValue, 48)
+                   201, spv::Op::OpReturnValue, 48)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: Return value id is not available
   ASSERT_FALSE(TransformationReplaceBranchFromDeadBlockWithExit(
-                   200, SpvOpReturnValue, 400)
+                   200, spv::Op::OpReturnValue, 400)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: Early exit now allowed in continue construct
-  ASSERT_FALSE(
-      TransformationReplaceBranchFromDeadBlockWithExit(101, SpvOpUnreachable, 0)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationReplaceBranchFromDeadBlockWithExit(
+                   101, spv::Op::OpUnreachable, 0)
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: Early exit now allowed in continue construct (again)
   ASSERT_FALSE(TransformationReplaceBranchFromDeadBlockWithExit(
-                   300, SpvOpReturnValue, 14)
+                   300, spv::Op::OpReturnValue, 14)
                    .IsApplicable(context.get(), transformation_context));
 
   auto transformation1 = TransformationReplaceBranchFromDeadBlockWithExit(
-      200, SpvOpUnreachable, 0);
+      200, spv::Op::OpUnreachable, 0);
   auto transformation2 = TransformationReplaceBranchFromDeadBlockWithExit(
-      201, SpvOpReturnValue, 400);
+      201, spv::Op::OpReturnValue, 400);
 
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
@@ -339,7 +341,7 @@
 
   opt::Instruction* return_value_inst =
       context->get_instr_block(201)->terminator();
-  ASSERT_EQ(SpvOpReturnValue, return_value_inst->opcode());
+  ASSERT_EQ(spv::Op::OpReturnValue, return_value_inst->opcode());
   ASSERT_EQ(SPV_OPERAND_TYPE_ID, return_value_inst->GetInOperand(0).type);
   ASSERT_EQ(400, return_value_inst->GetSingleWordInOperand(0));
 
@@ -504,9 +506,9 @@
   transformation_context.GetFactManager()->AddFactBlockIsDead(20);
 
   auto transformation1 =
-      TransformationReplaceBranchFromDeadBlockWithExit(20, SpvOpKill, 0);
+      TransformationReplaceBranchFromDeadBlockWithExit(20, spv::Op::OpKill, 0);
   auto transformation2 =
-      TransformationReplaceBranchFromDeadBlockWithExit(16, SpvOpKill, 0);
+      TransformationReplaceBranchFromDeadBlockWithExit(16, spv::Op::OpKill, 0);
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(
@@ -609,9 +611,9 @@
   transformation_context.GetFactManager()->AddFactBlockIsDead(9);
   transformation_context.GetFactManager()->AddFactBlockIsDead(11);
 
-  ASSERT_FALSE(
-      TransformationReplaceBranchFromDeadBlockWithExit(11, SpvOpUnreachable, 0)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationReplaceBranchFromDeadBlockWithExit(
+                   11, spv::Op::OpUnreachable, 0)
+                   .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationReplaceBranchFromDeadBlockWithExitTest,
@@ -658,7 +660,7 @@
   transformation_context.GetFactManager()->AddFactBlockIsDead(11);
 
   TransformationReplaceBranchFromDeadBlockWithExit transformation(
-      11, SpvOpUnreachable, 0);
+      11, spv::Op::OpUnreachable, 0);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   transformation.Apply(context.get(), &transformation_context);
@@ -741,7 +743,7 @@
   transformation_context.GetFactManager()->AddFactBlockIsDead(13);
 
   TransformationReplaceBranchFromDeadBlockWithExit transformation(
-      13, SpvOpUnreachable, 0);
+      13, spv::Op::OpUnreachable, 0);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   transformation.Apply(context.get(), &transformation_context);
@@ -823,7 +825,7 @@
   transformation_context.GetFactManager()->AddFactBlockIsDead(10);
 
   TransformationReplaceBranchFromDeadBlockWithExit transformation(
-      10, SpvOpUnreachable, 0);
+      10, spv::Op::OpUnreachable, 0);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   transformation.Apply(context.get(), &transformation_context);
diff --git a/test/fuzz/transformation_replace_constant_with_uniform_test.cpp b/test/fuzz/transformation_replace_constant_with_uniform_test.cpp
index fe76068..7c6d126 100644
--- a/test/fuzz/transformation_replace_constant_with_uniform_test.cpp
+++ b/test/fuzz/transformation_replace_constant_with_uniform_test.cpp
@@ -121,12 +121,12 @@
   ASSERT_TRUE(AddFactHelper(&transformation_context, 3, blockname_c));
 
   // The constant ids are 9, 11 and 14, for 1, 2 and 3 respectively.
-  protobufs::IdUseDescriptor use_of_9_in_store =
-      MakeIdUseDescriptor(9, MakeInstructionDescriptor(8, SpvOpStore, 0), 1);
-  protobufs::IdUseDescriptor use_of_11_in_add =
-      MakeIdUseDescriptor(11, MakeInstructionDescriptor(12, SpvOpIAdd, 0), 1);
-  protobufs::IdUseDescriptor use_of_14_in_add =
-      MakeIdUseDescriptor(14, MakeInstructionDescriptor(15, SpvOpIAdd, 0), 0);
+  protobufs::IdUseDescriptor use_of_9_in_store = MakeIdUseDescriptor(
+      9, MakeInstructionDescriptor(8, spv::Op::OpStore, 0), 1);
+  protobufs::IdUseDescriptor use_of_11_in_add = MakeIdUseDescriptor(
+      11, MakeInstructionDescriptor(12, spv::Op::OpIAdd, 0), 1);
+  protobufs::IdUseDescriptor use_of_14_in_add = MakeIdUseDescriptor(
+      14, MakeInstructionDescriptor(15, spv::Op::OpIAdd, 0), 0);
 
   // These transformations work: they match the facts.
   auto transformation_use_of_9_in_store =
@@ -172,8 +172,8 @@
 
   // The following transformation does not apply because the id descriptor is
   // not sensible.
-  protobufs::IdUseDescriptor nonsense_id_use_descriptor =
-      MakeIdUseDescriptor(9, MakeInstructionDescriptor(15, SpvOpIAdd, 0), 0);
+  protobufs::IdUseDescriptor nonsense_id_use_descriptor = MakeIdUseDescriptor(
+      9, MakeInstructionDescriptor(15, spv::Op::OpIAdd, 0), 0);
   ASSERT_FALSE(TransformationReplaceConstantWithUniform(
                    nonsense_id_use_descriptor, blockname_a, 101, 102)
                    .IsApplicable(context.get(), transformation_context));
@@ -490,14 +490,14 @@
   ASSERT_TRUE(AddFactHelper(&transformation_context, 4, blockname_4));
 
   // The constant ids are 13, 15, 17 and 20, for 1, 2, 3 and 4 respectively.
-  protobufs::IdUseDescriptor use_of_13_in_store =
-      MakeIdUseDescriptor(13, MakeInstructionDescriptor(21, SpvOpStore, 0), 1);
-  protobufs::IdUseDescriptor use_of_15_in_add =
-      MakeIdUseDescriptor(15, MakeInstructionDescriptor(16, SpvOpIAdd, 0), 1);
-  protobufs::IdUseDescriptor use_of_17_in_add =
-      MakeIdUseDescriptor(17, MakeInstructionDescriptor(19, SpvOpIAdd, 0), 0);
-  protobufs::IdUseDescriptor use_of_20_in_store =
-      MakeIdUseDescriptor(20, MakeInstructionDescriptor(19, SpvOpStore, 1), 1);
+  protobufs::IdUseDescriptor use_of_13_in_store = MakeIdUseDescriptor(
+      13, MakeInstructionDescriptor(21, spv::Op::OpStore, 0), 1);
+  protobufs::IdUseDescriptor use_of_15_in_add = MakeIdUseDescriptor(
+      15, MakeInstructionDescriptor(16, spv::Op::OpIAdd, 0), 1);
+  protobufs::IdUseDescriptor use_of_17_in_add = MakeIdUseDescriptor(
+      17, MakeInstructionDescriptor(19, spv::Op::OpIAdd, 0), 0);
+  protobufs::IdUseDescriptor use_of_20_in_store = MakeIdUseDescriptor(
+      20, MakeInstructionDescriptor(19, spv::Op::OpStore, 1), 1);
 
   // These transformations work: they match the facts.
   auto transformation_use_of_13_in_store =
@@ -726,8 +726,8 @@
   ASSERT_TRUE(AddFactHelper(&transformation_context, 0, blockname_0));
 
   // The constant id is 9 for 0.
-  protobufs::IdUseDescriptor use_of_9_in_store =
-      MakeIdUseDescriptor(9, MakeInstructionDescriptor(8, SpvOpStore, 0), 1);
+  protobufs::IdUseDescriptor use_of_9_in_store = MakeIdUseDescriptor(
+      9, MakeInstructionDescriptor(8, spv::Op::OpStore, 0), 1);
 
   // This transformation is not available because no uniform pointer to integer
   // type is present:
@@ -803,8 +803,8 @@
   ASSERT_TRUE(AddFactHelper(&transformation_context, 9, blockname_9));
 
   // The constant id is 9 for 9.
-  protobufs::IdUseDescriptor use_of_9_in_store =
-      MakeIdUseDescriptor(9, MakeInstructionDescriptor(8, SpvOpStore, 0), 1);
+  protobufs::IdUseDescriptor use_of_9_in_store = MakeIdUseDescriptor(
+      9, MakeInstructionDescriptor(8, spv::Op::OpStore, 0), 1);
 
   // This transformation is not available because no constant is present for the
   // index 1 required to index into the uniform buffer:
@@ -879,8 +879,8 @@
       AddFactHelper(&transformation_context, float_data[0], blockname_3));
 
   // The constant id is 9 for 3.0.
-  protobufs::IdUseDescriptor use_of_9_in_store =
-      MakeIdUseDescriptor(9, MakeInstructionDescriptor(8, SpvOpStore, 0), 1);
+  protobufs::IdUseDescriptor use_of_9_in_store = MakeIdUseDescriptor(
+      9, MakeInstructionDescriptor(8, spv::Op::OpStore, 0), 1);
 
   // This transformation is not available because no integer type is present to
   // allow a constant index to be expressed:
@@ -966,10 +966,10 @@
   ASSERT_TRUE(AddFactHelper(&transformation_context, 10, blockname_10));
 
   // The constant ids for 9 and 10 are 9 and 11 respectively
-  protobufs::IdUseDescriptor use_of_9_in_store =
-      MakeIdUseDescriptor(9, MakeInstructionDescriptor(10, SpvOpStore, 0), 1);
-  protobufs::IdUseDescriptor use_of_11_in_store =
-      MakeIdUseDescriptor(11, MakeInstructionDescriptor(10, SpvOpStore, 1), 1);
+  protobufs::IdUseDescriptor use_of_9_in_store = MakeIdUseDescriptor(
+      9, MakeInstructionDescriptor(10, spv::Op::OpStore, 0), 1);
+  protobufs::IdUseDescriptor use_of_11_in_store = MakeIdUseDescriptor(
+      11, MakeInstructionDescriptor(10, spv::Op::OpStore, 1), 1);
 
   // These are right:
   ASSERT_TRUE(TransformationReplaceConstantWithUniform(use_of_9_in_store,
@@ -1251,57 +1251,73 @@
   std::vector<TransformationReplaceConstantWithUniform> transformations;
 
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(18, MakeInstructionDescriptor(20, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          18, MakeInstructionDescriptor(20, spv::Op::OpStore, 0), 1),
       uniform_f_a_4, 200, 201));
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(22, MakeInstructionDescriptor(23, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          22, MakeInstructionDescriptor(23, spv::Op::OpStore, 0), 1),
       uniform_f_a_3, 202, 203));
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(25, MakeInstructionDescriptor(26, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          25, MakeInstructionDescriptor(26, spv::Op::OpStore, 0), 1),
       uniform_f_a_2, 204, 205));
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(28, MakeInstructionDescriptor(29, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          28, MakeInstructionDescriptor(29, spv::Op::OpStore, 0), 1),
       uniform_f_a_1, 206, 207));
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(31, MakeInstructionDescriptor(32, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          31, MakeInstructionDescriptor(32, spv::Op::OpStore, 0), 1),
       uniform_f_a_0, 208, 209));
 
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(30, MakeInstructionDescriptor(35, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          30, MakeInstructionDescriptor(35, spv::Op::OpStore, 0), 1),
       uniform_f_b_w, 210, 211));
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(27, MakeInstructionDescriptor(37, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          27, MakeInstructionDescriptor(37, spv::Op::OpStore, 0), 1),
       uniform_f_b_z, 212, 213));
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(24, MakeInstructionDescriptor(39, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          24, MakeInstructionDescriptor(39, spv::Op::OpStore, 0), 1),
       uniform_f_b_y, 214, 215));
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(21, MakeInstructionDescriptor(41, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          21, MakeInstructionDescriptor(41, spv::Op::OpStore, 0), 1),
       uniform_f_b_x, 216, 217));
 
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(44, MakeInstructionDescriptor(45, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          44, MakeInstructionDescriptor(45, spv::Op::OpStore, 0), 1),
       uniform_f_c_z, 220, 221));
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(46, MakeInstructionDescriptor(47, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          46, MakeInstructionDescriptor(47, spv::Op::OpStore, 0), 1),
       uniform_f_c_y, 222, 223));
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(48, MakeInstructionDescriptor(49, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          48, MakeInstructionDescriptor(49, spv::Op::OpStore, 0), 1),
       uniform_f_c_x, 224, 225));
 
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(50, MakeInstructionDescriptor(52, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          50, MakeInstructionDescriptor(52, spv::Op::OpStore, 0), 1),
       uniform_f_d, 226, 227));
 
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(53, MakeInstructionDescriptor(54, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          53, MakeInstructionDescriptor(54, spv::Op::OpStore, 0), 1),
       uniform_h_x, 228, 229));
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(55, MakeInstructionDescriptor(56, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          55, MakeInstructionDescriptor(56, spv::Op::OpStore, 0), 1),
       uniform_h_y, 230, 231));
 
   transformations.emplace_back(TransformationReplaceConstantWithUniform(
-      MakeIdUseDescriptor(42, MakeInstructionDescriptor(43, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          42, MakeInstructionDescriptor(43, spv::Op::OpStore, 0), 1),
       uniform_g, 218, 219));
 
   for (auto& transformation : transformations) {
@@ -1520,11 +1536,12 @@
 
   ASSERT_TRUE(AddFactHelper(&transformation_context, 0, blockname_a));
 
-  ASSERT_FALSE(TransformationReplaceConstantWithUniform(
-                   MakeIdUseDescriptor(
-                       50, MakeInstructionDescriptor(8, SpvOpVariable, 0), 1),
-                   blockname_a, 100, 101)
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationReplaceConstantWithUniform(
+          MakeIdUseDescriptor(
+              50, MakeInstructionDescriptor(8, spv::Op::OpVariable, 0), 1),
+          blockname_a, 100, 101)
+          .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationReplaceConstantWithUniformTest, ReplaceOpPhiOperand) {
@@ -1579,7 +1596,8 @@
 
   {
     TransformationReplaceConstantWithUniform transformation(
-        MakeIdUseDescriptor(7, MakeInstructionDescriptor(23, SpvOpPhi, 0), 0),
+        MakeIdUseDescriptor(7, MakeInstructionDescriptor(23, spv::Op::OpPhi, 0),
+                            0),
         int_descriptor, 50, 51);
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
diff --git a/test/fuzz/transformation_replace_copy_memory_with_load_store_test.cpp b/test/fuzz/transformation_replace_copy_memory_with_load_store_test.cpp
index bcd04af..689cf19 100644
--- a/test/fuzz/transformation_replace_copy_memory_with_load_store_test.cpp
+++ b/test/fuzz/transformation_replace_copy_memory_with_load_store_test.cpp
@@ -75,11 +75,11 @@
                                                kConsoleMessageConsumer));
 
   auto instruction_descriptor_invalid_1 =
-      MakeInstructionDescriptor(5, SpvOpStore, 0);
+      MakeInstructionDescriptor(5, spv::Op::OpStore, 0);
   auto instruction_descriptor_valid_1 =
-      MakeInstructionDescriptor(5, SpvOpCopyMemory, 0);
+      MakeInstructionDescriptor(5, spv::Op::OpCopyMemory, 0);
   auto instruction_descriptor_valid_2 =
-      MakeInstructionDescriptor(5, SpvOpCopyMemory, 0);
+      MakeInstructionDescriptor(5, spv::Op::OpCopyMemory, 0);
 
   // Invalid: |source_id| is not a fresh id.
   auto transformation_invalid_1 = TransformationReplaceCopyMemoryWithLoadStore(
diff --git a/test/fuzz/transformation_replace_copy_object_with_store_load_test.cpp b/test/fuzz/transformation_replace_copy_object_with_store_load_test.cpp
index fa8c068..368e208 100644
--- a/test/fuzz/transformation_replace_copy_object_with_store_load_test.cpp
+++ b/test/fuzz/transformation_replace_copy_object_with_store_load_test.cpp
@@ -88,44 +88,45 @@
 
   // Invalid: fresh_variable_id=10 is not fresh.
   auto transformation_invalid_1 = TransformationReplaceCopyObjectWithStoreLoad(
-      27, 10, SpvStorageClassFunction, 9);
+      27, 10, (uint32_t)spv::StorageClass::Function, 9);
   ASSERT_FALSE(transformation_invalid_1.IsApplicable(context.get(),
                                                      transformation_context));
 
   // Invalid: copy_object_result_id=26 is not a CopyObject instruction.
   auto transformation_invalid_2 = TransformationReplaceCopyObjectWithStoreLoad(
-      26, 30, SpvStorageClassFunction, 9);
+      26, 30, (uint32_t)spv::StorageClass::Function, 9);
   ASSERT_FALSE(transformation_invalid_2.IsApplicable(context.get(),
                                                      transformation_context));
 
   // Invalid: copy_object_result_id=40 is of type pointer.
   auto transformation_invalid_3 = TransformationReplaceCopyObjectWithStoreLoad(
-      40, 30, SpvStorageClassFunction, 9);
+      40, 30, (uint32_t)spv::StorageClass::Function, 9);
   ASSERT_FALSE(transformation_invalid_3.IsApplicable(context.get(),
                                                      transformation_context));
 
   // Invalid: Pointer type instruction in this storage class pointing to the
   // value type is not defined.
   auto transformation_invalid_4 = TransformationReplaceCopyObjectWithStoreLoad(
-      40, 30, SpvStorageClassPrivate, 9);
+      40, 30, (uint32_t)spv::StorageClass::Private, 9);
   ASSERT_FALSE(transformation_invalid_4.IsApplicable(context.get(),
                                                      transformation_context));
 
   // Invalid: initializer_id=15 has the wrong type relative to the OpCopyObject
   // instruction.
   auto transformation_invalid_5 = TransformationReplaceCopyObjectWithStoreLoad(
-      27, 30, SpvStorageClassFunction, 15);
+      27, 30, (uint32_t)spv::StorageClass::Function, 15);
   ASSERT_FALSE(transformation_invalid_5.IsApplicable(context.get(),
                                                      transformation_context));
 
-  // Invalid: SpvStorageClassUniform is not applicable to the transformation.
+  // Invalid: spv::StorageClass::Uniform is not applicable to the
+  // transformation.
   auto transformation_invalid_6 = TransformationReplaceCopyObjectWithStoreLoad(
-      27, 30, SpvStorageClassUniform, 9);
+      27, 30, (uint32_t)spv::StorageClass::Uniform, 9);
   ASSERT_FALSE(transformation_invalid_6.IsApplicable(context.get(),
                                                      transformation_context));
 
   auto transformation_valid_1 = TransformationReplaceCopyObjectWithStoreLoad(
-      27, 30, SpvStorageClassFunction, 9);
+      27, 30, (uint32_t)spv::StorageClass::Function, 9);
   ASSERT_TRUE(transformation_valid_1.IsApplicable(context.get(),
                                                   transformation_context));
   ApplyAndCheckFreshIds(transformation_valid_1, context.get(),
@@ -134,7 +135,7 @@
                                                kConsoleMessageConsumer));
 
   auto transformation_valid_2 = TransformationReplaceCopyObjectWithStoreLoad(
-      28, 32, SpvStorageClassPrivate, 15);
+      28, 32, (uint32_t)spv::StorageClass::Private, 15);
   ASSERT_TRUE(transformation_valid_2.IsApplicable(context.get(),
                                                   transformation_context));
   ApplyAndCheckFreshIds(transformation_valid_2, context.get(),
@@ -244,7 +245,7 @@
   transformation_context.GetFactManager()->AddFactIdIsIrrelevant(11);
 
   auto transformation_1 = TransformationReplaceCopyObjectWithStoreLoad(
-      50, 100, SpvStorageClassFunction, 10);
+      50, 100, (uint32_t)spv::StorageClass::Function, 10);
   ASSERT_TRUE(
       transformation_1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation_1, context.get(),
@@ -253,7 +254,7 @@
       MakeDataDescriptor(100, {}), MakeDataDescriptor(50, {})));
 
   auto transformation_2 = TransformationReplaceCopyObjectWithStoreLoad(
-      51, 101, SpvStorageClassFunction, 10);
+      51, 101, (uint32_t)spv::StorageClass::Function, 10);
   ASSERT_TRUE(
       transformation_2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation_2, context.get(),
diff --git a/test/fuzz/transformation_replace_id_with_synonym_test.cpp b/test/fuzz/transformation_replace_id_with_synonym_test.cpp
index b33dd48..bd27c29 100644
--- a/test/fuzz/transformation_replace_id_with_synonym_test.cpp
+++ b/test/fuzz/transformation_replace_id_with_synonym_test.cpp
@@ -230,7 +230,8 @@
   // %202 cannot replace %15 as in-operand 0 of %300, since %202 does not
   // dominate %300.
   auto synonym_does_not_dominate_use = TransformationReplaceIdWithSynonym(
-      MakeIdUseDescriptor(15, MakeInstructionDescriptor(300, SpvOpIAdd, 0), 0),
+      MakeIdUseDescriptor(
+          15, MakeInstructionDescriptor(300, spv::Op::OpIAdd, 0), 0),
       202);
   ASSERT_FALSE(synonym_does_not_dominate_use.IsApplicable(
       context.get(), transformation_context));
@@ -239,8 +240,8 @@
   // incoming value for block %72, and %202 does not dominate %72.
   auto synonym_does_not_dominate_use_op_phi =
       TransformationReplaceIdWithSynonym(
-          MakeIdUseDescriptor(15, MakeInstructionDescriptor(301, SpvOpPhi, 0),
-                              2),
+          MakeIdUseDescriptor(
+              15, MakeInstructionDescriptor(301, spv::Op::OpPhi, 0), 2),
           202);
   ASSERT_FALSE(synonym_does_not_dominate_use_op_phi.IsApplicable(
       context.get(), transformation_context));
@@ -248,14 +249,15 @@
   // %200 is not a synonym for %84
   auto id_in_use_is_not_synonymous = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          84, MakeInstructionDescriptor(67, SpvOpSGreaterThan, 0), 0),
+          84, MakeInstructionDescriptor(67, spv::Op::OpSGreaterThan, 0), 0),
       200);
   ASSERT_FALSE(id_in_use_is_not_synonymous.IsApplicable(
       context.get(), transformation_context));
 
   // %86 is not a synonym for anything (and in particular not for %74)
   auto id_has_no_synonyms = TransformationReplaceIdWithSynonym(
-      MakeIdUseDescriptor(86, MakeInstructionDescriptor(84, SpvOpPhi, 0), 2),
+      MakeIdUseDescriptor(86, MakeInstructionDescriptor(84, spv::Op::OpPhi, 0),
+                          2),
       74);
   ASSERT_FALSE(
       id_has_no_synonyms.IsApplicable(context.get(), transformation_context));
@@ -264,7 +266,7 @@
   auto synonym_use_is_in_synonym_definition =
       TransformationReplaceIdWithSynonym(
           MakeIdUseDescriptor(
-              84, MakeInstructionDescriptor(207, SpvOpCopyObject, 0), 0),
+              84, MakeInstructionDescriptor(207, spv::Op::OpCopyObject, 0), 0),
           207);
   ASSERT_FALSE(synonym_use_is_in_synonym_definition.IsApplicable(
       context.get(), transformation_context));
@@ -273,7 +275,7 @@
   // definition of %207)
   auto bad_id_use_descriptor = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          84, MakeInstructionDescriptor(200, SpvOpCopyObject, 0), 0),
+          84, MakeInstructionDescriptor(200, spv::Op::OpCopyObject, 0), 0),
       207);
   ASSERT_FALSE(bad_id_use_descriptor.IsApplicable(context.get(),
                                                   transformation_context));
@@ -282,7 +284,7 @@
   // non-constant index.
   auto bad_access_chain = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          12, MakeInstructionDescriptor(14, SpvOpAccessChain, 0), 1),
+          12, MakeInstructionDescriptor(14, spv::Op::OpAccessChain, 0), 1),
       209);
   ASSERT_FALSE(
       bad_access_chain.IsApplicable(context.get(), transformation_context));
@@ -301,7 +303,8 @@
   SetUpIdSynonyms(transformation_context.GetFactManager());
 
   auto global_constant_synonym = TransformationReplaceIdWithSynonym(
-      MakeIdUseDescriptor(19, MakeInstructionDescriptor(47, SpvOpStore, 0), 1),
+      MakeIdUseDescriptor(
+          19, MakeInstructionDescriptor(47, spv::Op::OpStore, 0), 1),
       210);
   uint32_t num_uses_of_original_id_before_replacement =
       context->get_def_use_mgr()->NumUses(19);
@@ -320,7 +323,7 @@
 
   auto replace_vector_access_chain_index = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          54, MakeInstructionDescriptor(55, SpvOpAccessChain, 0), 1),
+          54, MakeInstructionDescriptor(55, spv::Op::OpAccessChain, 0), 1),
       204);
   ASSERT_TRUE(replace_vector_access_chain_index.IsApplicable(
       context.get(), transformation_context));
@@ -333,7 +336,7 @@
   // copied with something that is already a synonym.
   auto regular_replacement = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          15, MakeInstructionDescriptor(202, SpvOpCopyObject, 0), 0),
+          15, MakeInstructionDescriptor(202, spv::Op::OpCopyObject, 0), 0),
       201);
   ASSERT_TRUE(
       regular_replacement.IsApplicable(context.get(), transformation_context));
@@ -343,7 +346,8 @@
                                                kConsoleMessageConsumer));
 
   auto regular_replacement2 = TransformationReplaceIdWithSynonym(
-      MakeIdUseDescriptor(55, MakeInstructionDescriptor(203, SpvOpStore, 0), 0),
+      MakeIdUseDescriptor(
+          55, MakeInstructionDescriptor(203, spv::Op::OpStore, 0), 0),
       203);
   ASSERT_TRUE(
       regular_replacement2.IsApplicable(context.get(), transformation_context));
@@ -353,7 +357,8 @@
                                                kConsoleMessageConsumer));
 
   auto good_op_phi = TransformationReplaceIdWithSynonym(
-      MakeIdUseDescriptor(74, MakeInstructionDescriptor(86, SpvOpPhi, 0), 2),
+      MakeIdUseDescriptor(74, MakeInstructionDescriptor(86, spv::Op::OpPhi, 0),
+                          2),
       205);
   ASSERT_TRUE(good_op_phi.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(good_op_phi, context.get(), &transformation_context);
@@ -543,7 +548,8 @@
   // Replace %10 with %100 in:
   // %11 = OpLoad %6 %10
   auto replacement1 = TransformationReplaceIdWithSynonym(
-      MakeIdUseDescriptor(10, MakeInstructionDescriptor(11, SpvOpLoad, 0), 0),
+      MakeIdUseDescriptor(10, MakeInstructionDescriptor(11, spv::Op::OpLoad, 0),
+                          0),
       100);
   ASSERT_TRUE(replacement1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(replacement1, context.get(), &transformation_context);
@@ -553,7 +559,8 @@
   // Replace %8 with %101 in:
   // OpStore %8 %11
   auto replacement2 = TransformationReplaceIdWithSynonym(
-      MakeIdUseDescriptor(8, MakeInstructionDescriptor(11, SpvOpStore, 0), 0),
+      MakeIdUseDescriptor(8, MakeInstructionDescriptor(11, spv::Op::OpStore, 0),
+                          0),
       101);
   ASSERT_TRUE(replacement2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(replacement2, context.get(), &transformation_context);
@@ -563,7 +570,8 @@
   // Replace %8 with %101 in:
   // %12 = OpLoad %6 %8
   auto replacement3 = TransformationReplaceIdWithSynonym(
-      MakeIdUseDescriptor(8, MakeInstructionDescriptor(12, SpvOpLoad, 0), 0),
+      MakeIdUseDescriptor(8, MakeInstructionDescriptor(12, spv::Op::OpLoad, 0),
+                          0),
       101);
   ASSERT_TRUE(replacement3.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(replacement3, context.get(), &transformation_context);
@@ -573,7 +581,8 @@
   // Replace %10 with %100 in:
   // OpStore %10 %12
   auto replacement4 = TransformationReplaceIdWithSynonym(
-      MakeIdUseDescriptor(10, MakeInstructionDescriptor(12, SpvOpStore, 0), 0),
+      MakeIdUseDescriptor(
+          10, MakeInstructionDescriptor(12, spv::Op::OpStore, 0), 0),
       100);
   ASSERT_TRUE(replacement4.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(replacement4, context.get(), &transformation_context);
@@ -678,7 +687,7 @@
   // %16 = OpFunctionCall %2 %10 %14
   auto replacement = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          14, MakeInstructionDescriptor(16, SpvOpFunctionCall, 0), 1),
+          14, MakeInstructionDescriptor(16, spv::Op::OpFunctionCall, 0), 1),
       100);
   ASSERT_FALSE(replacement.IsApplicable(context.get(), transformation_context));
 }
@@ -871,7 +880,7 @@
   // The index %16 used for a cannot be replaced
   auto replacement1 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          16, MakeInstructionDescriptor(20, SpvOpAccessChain, 0), 1),
+          16, MakeInstructionDescriptor(20, spv::Op::OpAccessChain, 0), 1),
       100);
   ASSERT_FALSE(
       replacement1.IsApplicable(context.get(), transformation_context));
@@ -881,7 +890,7 @@
   // The index %16 used for f cannot be replaced
   auto replacement2 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          16, MakeInstructionDescriptor(39, SpvOpAccessChain, 0), 1),
+          16, MakeInstructionDescriptor(39, spv::Op::OpAccessChain, 0), 1),
       100);
   ASSERT_FALSE(
       replacement2.IsApplicable(context.get(), transformation_context));
@@ -891,7 +900,7 @@
   // The index %16 used for a cannot be replaced
   auto replacement3 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          16, MakeInstructionDescriptor(41, SpvOpAccessChain, 0), 2),
+          16, MakeInstructionDescriptor(41, spv::Op::OpAccessChain, 0), 2),
       100);
   ASSERT_FALSE(
       replacement3.IsApplicable(context.get(), transformation_context));
@@ -901,7 +910,7 @@
   // The index %16 used for 0 *can* be replaced
   auto replacement4 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          16, MakeInstructionDescriptor(52, SpvOpAccessChain, 0), 1),
+          16, MakeInstructionDescriptor(52, spv::Op::OpAccessChain, 0), 1),
       100);
   ASSERT_TRUE(replacement4.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(replacement4, context.get(), &transformation_context);
@@ -913,7 +922,7 @@
   // The index %16 used for f cannot be replaced
   auto replacement5 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          16, MakeInstructionDescriptor(52, SpvOpAccessChain, 0), 2),
+          16, MakeInstructionDescriptor(52, spv::Op::OpAccessChain, 0), 2),
       100);
   ASSERT_FALSE(
       replacement5.IsApplicable(context.get(), transformation_context));
@@ -923,7 +932,7 @@
   // The index %16 used for a cannot be replaced
   auto replacement6 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          16, MakeInstructionDescriptor(53, SpvOpAccessChain, 0), 3),
+          16, MakeInstructionDescriptor(53, spv::Op::OpAccessChain, 0), 3),
       100);
   ASSERT_FALSE(
       replacement6.IsApplicable(context.get(), transformation_context));
@@ -933,7 +942,7 @@
   // The index %16 used for 0 *can* be replaced
   auto replacement7 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          16, MakeInstructionDescriptor(53, SpvOpAccessChain, 0), 4),
+          16, MakeInstructionDescriptor(53, spv::Op::OpAccessChain, 0), 4),
       100);
   ASSERT_TRUE(replacement7.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(replacement7, context.get(), &transformation_context);
@@ -947,7 +956,7 @@
   // The index %24 used for b cannot be replaced
   auto replacement8 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          21, MakeInstructionDescriptor(24, SpvOpAccessChain, 0), 1),
+          21, MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0), 1),
       101);
   ASSERT_FALSE(
       replacement8.IsApplicable(context.get(), transformation_context));
@@ -957,7 +966,7 @@
   // The index %24 used for g cannot be replaced
   auto replacement9 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          21, MakeInstructionDescriptor(41, SpvOpAccessChain, 0), 1),
+          21, MakeInstructionDescriptor(41, spv::Op::OpAccessChain, 0), 1),
       101);
   ASSERT_FALSE(
       replacement9.IsApplicable(context.get(), transformation_context));
@@ -967,7 +976,7 @@
   // The index %24 used for 1 *can* be replaced
   auto replacement10 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          21, MakeInstructionDescriptor(41, SpvOpAccessChain, 0), 3),
+          21, MakeInstructionDescriptor(41, spv::Op::OpAccessChain, 0), 3),
       101);
   ASSERT_TRUE(
       replacement10.IsApplicable(context.get(), transformation_context));
@@ -980,7 +989,7 @@
   // The index %24 used for g cannot be replaced
   auto replacement11 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          21, MakeInstructionDescriptor(44, SpvOpAccessChain, 0), 1),
+          21, MakeInstructionDescriptor(44, spv::Op::OpAccessChain, 0), 1),
       101);
   ASSERT_FALSE(
       replacement11.IsApplicable(context.get(), transformation_context));
@@ -990,7 +999,7 @@
   // The index %24 used for b cannot be replaced
   auto replacement12 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          21, MakeInstructionDescriptor(44, SpvOpAccessChain, 0), 2),
+          21, MakeInstructionDescriptor(44, spv::Op::OpAccessChain, 0), 2),
       101);
   ASSERT_FALSE(
       replacement12.IsApplicable(context.get(), transformation_context));
@@ -1000,7 +1009,7 @@
   // The index %24 used for g cannot be replaced
   auto replacement13 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          21, MakeInstructionDescriptor(46, SpvOpAccessChain, 0), 1),
+          21, MakeInstructionDescriptor(46, spv::Op::OpAccessChain, 0), 1),
       101);
   ASSERT_FALSE(
       replacement13.IsApplicable(context.get(), transformation_context));
@@ -1010,7 +1019,7 @@
   // The index %24 used for 1 *can* be replaced
   auto replacement14 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          21, MakeInstructionDescriptor(53, SpvOpAccessChain, 0), 1),
+          21, MakeInstructionDescriptor(53, spv::Op::OpAccessChain, 0), 1),
       101);
   ASSERT_TRUE(
       replacement14.IsApplicable(context.get(), transformation_context));
@@ -1023,7 +1032,7 @@
   // The index %24 used for g cannot be replaced
   auto replacement15 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          21, MakeInstructionDescriptor(53, SpvOpAccessChain, 0), 2),
+          21, MakeInstructionDescriptor(53, spv::Op::OpAccessChain, 0), 2),
       101);
   ASSERT_FALSE(
       replacement15.IsApplicable(context.get(), transformation_context));
@@ -1033,7 +1042,7 @@
   // The index %24 used for g cannot be replaced
   auto replacement16 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          21, MakeInstructionDescriptor(56, SpvOpAccessChain, 0), 2),
+          21, MakeInstructionDescriptor(56, spv::Op::OpAccessChain, 0), 2),
       101);
   ASSERT_FALSE(
       replacement16.IsApplicable(context.get(), transformation_context));
@@ -1043,7 +1052,7 @@
   // The index %24 used for b cannot be replaced
   auto replacement17 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          21, MakeInstructionDescriptor(56, SpvOpAccessChain, 0), 3),
+          21, MakeInstructionDescriptor(56, spv::Op::OpAccessChain, 0), 3),
       101);
   ASSERT_FALSE(
       replacement17.IsApplicable(context.get(), transformation_context));
@@ -1053,7 +1062,8 @@
   // The index %24 used for g cannot be replaced
   auto replacement18 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          21, MakeInstructionDescriptor(58, SpvOpInBoundsAccessChain, 0), 2),
+          21, MakeInstructionDescriptor(58, spv::Op::OpInBoundsAccessChain, 0),
+          2),
       101);
   ASSERT_FALSE(
       replacement18.IsApplicable(context.get(), transformation_context));
@@ -1065,7 +1075,7 @@
   // The index %17 used for 2 *can* be replaced
   auto replacement19 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          17, MakeInstructionDescriptor(20, SpvOpAccessChain, 0), 2),
+          17, MakeInstructionDescriptor(20, spv::Op::OpAccessChain, 0), 2),
       102);
   ASSERT_TRUE(
       replacement19.IsApplicable(context.get(), transformation_context));
@@ -1078,7 +1088,7 @@
   // The index %17 used for c cannot be replaced
   auto replacement20 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          17, MakeInstructionDescriptor(27, SpvOpAccessChain, 0), 1),
+          17, MakeInstructionDescriptor(27, spv::Op::OpAccessChain, 0), 1),
       102);
   ASSERT_FALSE(
       replacement20.IsApplicable(context.get(), transformation_context));
@@ -1088,7 +1098,7 @@
   // The index %17 used for c cannot be replaced
   auto replacement21 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          17, MakeInstructionDescriptor(46, SpvOpAccessChain, 0), 2),
+          17, MakeInstructionDescriptor(46, spv::Op::OpAccessChain, 0), 2),
       102);
   ASSERT_FALSE(
       replacement21.IsApplicable(context.get(), transformation_context));
@@ -1098,7 +1108,7 @@
   // The index %17 used for 2 *can* be replaced
   auto replacement22 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          17, MakeInstructionDescriptor(56, SpvOpAccessChain, 0), 1),
+          17, MakeInstructionDescriptor(56, spv::Op::OpAccessChain, 0), 1),
       102);
   ASSERT_TRUE(
       replacement22.IsApplicable(context.get(), transformation_context));
@@ -1111,7 +1121,8 @@
   // The index %17 used for c cannot be replaced
   auto replacement23 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          17, MakeInstructionDescriptor(58, SpvOpInBoundsAccessChain, 0), 3),
+          17, MakeInstructionDescriptor(58, spv::Op::OpInBoundsAccessChain, 0),
+          3),
       102);
   ASSERT_FALSE(
       replacement23.IsApplicable(context.get(), transformation_context));
@@ -1123,7 +1134,8 @@
   // The index %57 used for 3 *can* be replaced
   auto replacement24 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          57, MakeInstructionDescriptor(58, SpvOpInBoundsAccessChain, 0), 1),
+          57, MakeInstructionDescriptor(58, spv::Op::OpInBoundsAccessChain, 0),
+          1),
       103);
   ASSERT_TRUE(
       replacement24.IsApplicable(context.get(), transformation_context));
@@ -1138,7 +1150,7 @@
   // The index %32 used for 17 *can* be replaced
   auto replacement25 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          32, MakeInstructionDescriptor(34, SpvOpAccessChain, 0), 1),
+          32, MakeInstructionDescriptor(34, spv::Op::OpAccessChain, 0), 1),
       106);
   ASSERT_TRUE(
       replacement25.IsApplicable(context.get(), transformation_context));
@@ -1153,7 +1165,7 @@
   // The index %43 used for 0 *can* be replaced
   auto replacement26 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          43, MakeInstructionDescriptor(44, SpvOpAccessChain, 0), 3),
+          43, MakeInstructionDescriptor(44, spv::Op::OpAccessChain, 0), 3),
       107);
   ASSERT_TRUE(
       replacement26.IsApplicable(context.get(), transformation_context));
@@ -1168,7 +1180,7 @@
   // The index %55 used for 1 *can* be replaced
   auto replacement27 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          55, MakeInstructionDescriptor(56, SpvOpAccessChain, 0), 4),
+          55, MakeInstructionDescriptor(56, spv::Op::OpAccessChain, 0), 4),
       108);
   ASSERT_TRUE(
       replacement27.IsApplicable(context.get(), transformation_context));
@@ -1182,8 +1194,8 @@
   // Corresponds to d.b[*3*]
   // The index %8 used for 3 *can* be replaced
   auto replacement28 = TransformationReplaceIdWithSynonym(
-      MakeIdUseDescriptor(8, MakeInstructionDescriptor(24, SpvOpAccessChain, 0),
-                          2),
+      MakeIdUseDescriptor(
+          8, MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0), 2),
       109);
   ASSERT_TRUE(
       replacement28.IsApplicable(context.get(), transformation_context));
@@ -1356,14 +1368,14 @@
   ASSERT_FALSE(
       TransformationReplaceIdWithSynonym(
           MakeIdUseDescriptor(
-              12, MakeInstructionDescriptor(16, SpvOpAccessChain, 0), 1),
+              12, MakeInstructionDescriptor(16, spv::Op::OpAccessChain, 0), 1),
           50)
           .IsApplicable(context.get(), transformation_context));
 
   // Fine to replace an index into a runtime array.
   auto replacement1 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          12, MakeInstructionDescriptor(16, SpvOpAccessChain, 0), 2),
+          12, MakeInstructionDescriptor(16, spv::Op::OpAccessChain, 0), 2),
       50);
   ASSERT_TRUE(replacement1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(replacement1, context.get(), &transformation_context);
@@ -1371,7 +1383,7 @@
   // Fine to replace an index into a vector inside the runtime array.
   auto replacement2 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          14, MakeInstructionDescriptor(16, SpvOpAccessChain, 0), 3),
+          14, MakeInstructionDescriptor(16, spv::Op::OpAccessChain, 0), 3),
       51);
   ASSERT_TRUE(replacement2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(replacement2, context.get(), &transformation_context);
@@ -1466,7 +1478,8 @@
   ASSERT_FALSE(
       TransformationReplaceIdWithSynonym(
           MakeIdUseDescriptor(
-              9, MakeInstructionDescriptor(20, SpvOpImageTexelPointer, 0), 2),
+              9, MakeInstructionDescriptor(20, spv::Op::OpImageTexelPointer, 0),
+              2),
           100)
           .IsApplicable(context.get(), transformation_context));
 }
@@ -1524,56 +1537,61 @@
 
   // Legal because OpSNegate always considers the integer as signed
   auto replacement1 = TransformationReplaceIdWithSynonym(
-      MakeIdUseDescriptor(10, MakeInstructionDescriptor(15, SpvOpSNegate, 0),
-                          0),
+      MakeIdUseDescriptor(
+          10, MakeInstructionDescriptor(15, spv::Op::OpSNegate, 0), 0),
       13);
   ASSERT_TRUE(replacement1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(replacement1, context.get(), &transformation_context);
 
   // Legal because OpIAdd does not care about the signedness of the operands
   auto replacement2 = TransformationReplaceIdWithSynonym(
-      MakeIdUseDescriptor(10, MakeInstructionDescriptor(16, SpvOpIAdd, 0), 0),
+      MakeIdUseDescriptor(10, MakeInstructionDescriptor(16, spv::Op::OpIAdd, 0),
+                          0),
       13);
   ASSERT_TRUE(replacement2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(replacement2, context.get(), &transformation_context);
 
   // Legal because OpSDiv does not care about the signedness of the operands
   auto replacement3 = TransformationReplaceIdWithSynonym(
-      MakeIdUseDescriptor(10, MakeInstructionDescriptor(17, SpvOpSDiv, 0), 0),
+      MakeIdUseDescriptor(10, MakeInstructionDescriptor(17, spv::Op::OpSDiv, 0),
+                          0),
       13);
   ASSERT_TRUE(replacement3.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(replacement3, context.get(), &transformation_context);
 
   // Not legal because OpUDiv requires unsigned integers
-  ASSERT_FALSE(TransformationReplaceIdWithSynonym(
-                   MakeIdUseDescriptor(
-                       13, MakeInstructionDescriptor(18, SpvOpUDiv, 0), 0),
-                   10)
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationReplaceIdWithSynonym(
+          MakeIdUseDescriptor(
+              13, MakeInstructionDescriptor(18, spv::Op::OpUDiv, 0), 0),
+          10)
+          .IsApplicable(context.get(), transformation_context));
 
   // Legal because OpSDiv does not care about the signedness of the operands
   auto replacement4 = TransformationReplaceIdWithSynonym(
-      MakeIdUseDescriptor(10, MakeInstructionDescriptor(19, SpvOpBitwiseAnd, 0),
-                          0),
+      MakeIdUseDescriptor(
+          10, MakeInstructionDescriptor(19, spv::Op::OpBitwiseAnd, 0), 0),
       13);
   ASSERT_TRUE(replacement4.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(replacement4, context.get(), &transformation_context);
 
   // Not legal because OpSelect requires both operands to have the same type as
   // the result type
-  ASSERT_FALSE(TransformationReplaceIdWithSynonym(
-                   MakeIdUseDescriptor(
-                       10, MakeInstructionDescriptor(20, SpvOpUDiv, 0), 1),
-                   13)
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationReplaceIdWithSynonym(
+          MakeIdUseDescriptor(
+              10, MakeInstructionDescriptor(20, spv::Op::OpUDiv, 0), 1),
+          13)
+          .IsApplicable(context.get(), transformation_context));
 
   // Not legal because OpStore requires the object to match the type pointed
   // to by the pointer.
-  ASSERT_FALSE(TransformationReplaceIdWithSynonym(
-                   MakeIdUseDescriptor(
-                       10, MakeInstructionDescriptor(21, SpvOpStore, 0), 1),
-                   13)
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationReplaceIdWithSynonym(
+          MakeIdUseDescriptor(
+              10, MakeInstructionDescriptor(21, spv::Op::OpStore, 0), 1),
+          13)
+          .IsApplicable(context.get(), transformation_context));
 
   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
                                                kConsoleMessageConsumer));
@@ -1668,18 +1686,20 @@
 
   // Legal because OpIAdd does not consider the signedness of the operands
   auto replacement1 = TransformationReplaceIdWithSynonym(
-      MakeIdUseDescriptor(14, MakeInstructionDescriptor(18, SpvOpIAdd, 0), 0),
+      MakeIdUseDescriptor(14, MakeInstructionDescriptor(18, spv::Op::OpIAdd, 0),
+                          0),
       15);
   ASSERT_TRUE(replacement1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(replacement1, context.get(), &transformation_context);
 
   // Not legal because OpStore requires the object to match the type pointed
   // to by the pointer.
-  ASSERT_FALSE(TransformationReplaceIdWithSynonym(
-                   MakeIdUseDescriptor(
-                       14, MakeInstructionDescriptor(18, SpvOpStore, 0), 1),
-                   15)
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationReplaceIdWithSynonym(
+          MakeIdUseDescriptor(
+              14, MakeInstructionDescriptor(18, spv::Op::OpStore, 0), 1),
+          15)
+          .IsApplicable(context.get(), transformation_context));
 
   // Add synonym fact relating %12 and %13 (equivalent integer constants with
   // different signedness).
@@ -1689,7 +1709,7 @@
   // Legal because the indices of OpAccessChain are always treated as signed
   auto replacement2 = TransformationReplaceIdWithSynonym(
       MakeIdUseDescriptor(
-          13, MakeInstructionDescriptor(19, SpvOpAccessChain, 0), 1),
+          13, MakeInstructionDescriptor(19, spv::Op::OpAccessChain, 0), 1),
       12);
   ASSERT_TRUE(replacement2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(replacement2, context.get(), &transformation_context);
diff --git a/test/fuzz/transformation_replace_irrelevant_id_test.cpp b/test/fuzz/transformation_replace_irrelevant_id_test.cpp
index c04a091..c5d6981 100644
--- a/test/fuzz/transformation_replace_irrelevant_id_test.cpp
+++ b/test/fuzz/transformation_replace_irrelevant_id_test.cpp
@@ -82,8 +82,9 @@
   SetUpIrrelevantIdFacts(transformation_context.GetFactManager());
 
   auto instruction_21_descriptor =
-      MakeInstructionDescriptor(21, SpvOpAccessChain, 0);
-  auto instruction_24_descriptor = MakeInstructionDescriptor(24, SpvOpIAdd, 0);
+      MakeInstructionDescriptor(21, spv::Op::OpAccessChain, 0);
+  auto instruction_24_descriptor =
+      MakeInstructionDescriptor(24, spv::Op::OpIAdd, 0);
 
   // %20 has not been declared as irrelevant.
   ASSERT_FALSE(TransformationReplaceIrrelevantId(
@@ -132,7 +133,8 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   SetUpIrrelevantIdFacts(transformation_context.GetFactManager());
 
-  auto instruction_24_descriptor = MakeInstructionDescriptor(24, SpvOpIAdd, 0);
+  auto instruction_24_descriptor =
+      MakeInstructionDescriptor(24, spv::Op::OpIAdd, 0);
 
   // Replace the use of %23 in %24 with %22.
   auto transformation = TransformationReplaceIrrelevantId(
@@ -229,11 +231,12 @@
 
   // We cannot replace the use of %13 in the initializer of %12 with %9 because
   // %9 is not a constant.
-  ASSERT_FALSE(TransformationReplaceIrrelevantId(
-                   MakeIdUseDescriptor(
-                       13, MakeInstructionDescriptor(12, SpvOpVariable, 0), 1),
-                   9)
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationReplaceIrrelevantId(
+          MakeIdUseDescriptor(
+              13, MakeInstructionDescriptor(12, spv::Op::OpVariable, 0), 1),
+          9)
+          .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationReplaceIrrelevantIdTest,
@@ -280,7 +283,7 @@
   ASSERT_FALSE(
       TransformationReplaceIrrelevantId(
           MakeIdUseDescriptor(
-              20, MakeInstructionDescriptor(21, SpvOpCopyObject, 0), 0),
+              20, MakeInstructionDescriptor(21, spv::Op::OpCopyObject, 0), 0),
           10)
           .IsApplicable(context.get(), transformation_context));
 }
@@ -326,7 +329,7 @@
   ASSERT_FALSE(
       TransformationReplaceIrrelevantId(
           MakeIdUseDescriptor(
-              10, MakeInstructionDescriptor(12, SpvOpAccessChain, 0), 1),
+              10, MakeInstructionDescriptor(12, spv::Op::OpAccessChain, 0), 1),
           11)
           .IsApplicable(context.get(), transformation_context));
 }
diff --git a/test/fuzz/transformation_replace_linear_algebra_instruction_test.cpp b/test/fuzz/transformation_replace_linear_algebra_instruction_test.cpp
index 8ec5552..2dedea1 100644
--- a/test/fuzz/transformation_replace_linear_algebra_instruction_test.cpp
+++ b/test/fuzz/transformation_replace_linear_algebra_instruction_test.cpp
@@ -76,54 +76,56 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   // Tests linear algebra instructions.
-  auto instruction_descriptor = MakeInstructionDescriptor(24, SpvOpDot, 0);
+  auto instruction_descriptor =
+      MakeInstructionDescriptor(24, spv::Op::OpDot, 0);
   auto transformation = TransformationReplaceLinearAlgebraInstruction(
       {33, 34, 35, 36, 37, 38}, instruction_descriptor);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   instruction_descriptor =
-      MakeInstructionDescriptor(27, SpvOpVectorTimesScalar, 0);
+      MakeInstructionDescriptor(27, spv::Op::OpVectorTimesScalar, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {33, 34, 35, 36}, instruction_descriptor);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   // Tests non-linear algebra instructions.
-  instruction_descriptor = MakeInstructionDescriptor(30, SpvOpCopyObject, 0);
+  instruction_descriptor =
+      MakeInstructionDescriptor(30, spv::Op::OpCopyObject, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {33, 34, 35, 36, 37, 38}, instruction_descriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instruction_descriptor = MakeInstructionDescriptor(31, SpvOpFAdd, 0);
+  instruction_descriptor = MakeInstructionDescriptor(31, spv::Op::OpFAdd, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {33, 34, 35, 36, 37}, instruction_descriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instruction_descriptor = MakeInstructionDescriptor(32, SpvOpFMul, 0);
+  instruction_descriptor = MakeInstructionDescriptor(32, spv::Op::OpFMul, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {33, 34, 35, 36}, instruction_descriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   // Tests number of fresh ids is different than necessary.
-  instruction_descriptor = MakeInstructionDescriptor(25, SpvOpDot, 0);
+  instruction_descriptor = MakeInstructionDescriptor(25, spv::Op::OpDot, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {33, 34, 35, 36}, instruction_descriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   instruction_descriptor =
-      MakeInstructionDescriptor(28, SpvOpVectorTimesScalar, 0);
+      MakeInstructionDescriptor(28, spv::Op::OpVectorTimesScalar, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {33, 34, 35, 36, 37, 38, 39}, instruction_descriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   // Tests non-fresh ids.
-  instruction_descriptor = MakeInstructionDescriptor(26, SpvOpDot, 0);
+  instruction_descriptor = MakeInstructionDescriptor(26, spv::Op::OpDot, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {33, 34, 5, 36, 37, 8, 39, 40, 1, 42, 3, 44, 45, 46},
       instruction_descriptor);
@@ -131,7 +133,7 @@
       transformation.IsApplicable(context.get(), transformation_context));
 
   instruction_descriptor =
-      MakeInstructionDescriptor(29, SpvOpVectorTimesScalar, 0);
+      MakeInstructionDescriptor(29, spv::Op::OpVectorTimesScalar, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {33, 34, 35, 36, 7, 38, 9, 40}, instruction_descriptor);
   ASSERT_FALSE(
@@ -249,32 +251,36 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   auto instruction_descriptor =
-      MakeInstructionDescriptor(56, SpvOpTranspose, 0);
+      MakeInstructionDescriptor(56, spv::Op::OpTranspose, 0);
   auto transformation = TransformationReplaceLinearAlgebraInstruction(
       {65, 66, 67, 68, 69, 70, 71, 72, 73, 74}, instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
-  instruction_descriptor = MakeInstructionDescriptor(57, SpvOpTranspose, 0);
+  instruction_descriptor =
+      MakeInstructionDescriptor(57, spv::Op::OpTranspose, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88},
       instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
-  instruction_descriptor = MakeInstructionDescriptor(58, SpvOpTranspose, 0);
+  instruction_descriptor =
+      MakeInstructionDescriptor(58, spv::Op::OpTranspose, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105,
        106},
       instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
-  instruction_descriptor = MakeInstructionDescriptor(59, SpvOpTranspose, 0);
+  instruction_descriptor =
+      MakeInstructionDescriptor(59, spv::Op::OpTranspose, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
        121},
       instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
-  instruction_descriptor = MakeInstructionDescriptor(60, SpvOpTranspose, 0);
+  instruction_descriptor =
+      MakeInstructionDescriptor(60, spv::Op::OpTranspose, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132,
        133, 134, 135, 136, 137, 138, 139, 140, 141, 142},
@@ -506,19 +512,19 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   auto instruction_descriptor =
-      MakeInstructionDescriptor(17, SpvOpVectorTimesScalar, 0);
+      MakeInstructionDescriptor(17, spv::Op::OpVectorTimesScalar, 0);
   auto transformation = TransformationReplaceLinearAlgebraInstruction(
       {20, 21, 22, 23}, instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instruction_descriptor =
-      MakeInstructionDescriptor(18, SpvOpVectorTimesScalar, 0);
+      MakeInstructionDescriptor(18, spv::Op::OpVectorTimesScalar, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {24, 25, 26, 27, 28, 29}, instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instruction_descriptor =
-      MakeInstructionDescriptor(19, SpvOpVectorTimesScalar, 0);
+      MakeInstructionDescriptor(19, spv::Op::OpVectorTimesScalar, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {30, 31, 32, 33, 34, 35, 36, 37}, instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
@@ -677,20 +683,20 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   auto instruction_descriptor =
-      MakeInstructionDescriptor(56, SpvOpMatrixTimesScalar, 0);
+      MakeInstructionDescriptor(56, spv::Op::OpMatrixTimesScalar, 0);
   auto transformation = TransformationReplaceLinearAlgebraInstruction(
       {65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76}, instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instruction_descriptor =
-      MakeInstructionDescriptor(57, SpvOpMatrixTimesScalar, 0);
+      MakeInstructionDescriptor(57, spv::Op::OpMatrixTimesScalar, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94},
       instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instruction_descriptor =
-      MakeInstructionDescriptor(58, SpvOpMatrixTimesScalar, 0);
+      MakeInstructionDescriptor(58, spv::Op::OpMatrixTimesScalar, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {95,  96,  97,  98,  99,  100, 101, 102, 103, 104, 105, 106,
        107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118},
@@ -964,14 +970,14 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   auto instruction_descriptor =
-      MakeInstructionDescriptor(56, SpvOpVectorTimesMatrix, 0);
+      MakeInstructionDescriptor(56, spv::Op::OpVectorTimesMatrix, 0);
   auto transformation = TransformationReplaceLinearAlgebraInstruction(
       {65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78},
       instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instruction_descriptor =
-      MakeInstructionDescriptor(57, SpvOpVectorTimesMatrix, 0);
+      MakeInstructionDescriptor(57, spv::Op::OpVectorTimesMatrix, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
        89, 90, 91, 92, 93, 94, 95, 96, 97, 98},
@@ -979,7 +985,7 @@
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instruction_descriptor =
-      MakeInstructionDescriptor(58, SpvOpVectorTimesMatrix, 0);
+      MakeInstructionDescriptor(58, spv::Op::OpVectorTimesMatrix, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {99,  100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
        112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124},
@@ -987,7 +993,7 @@
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instruction_descriptor =
-      MakeInstructionDescriptor(59, SpvOpVectorTimesMatrix, 0);
+      MakeInstructionDescriptor(59, spv::Op::OpVectorTimesMatrix, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135,
        136, 137, 138, 139, 140, 141, 142, 143, 144, 145},
@@ -1298,14 +1304,14 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   auto instruction_descriptor =
-      MakeInstructionDescriptor(56, SpvOpMatrixTimesVector, 0);
+      MakeInstructionDescriptor(56, spv::Op::OpMatrixTimesVector, 0);
   auto transformation = TransformationReplaceLinearAlgebraInstruction(
       {65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78},
       instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instruction_descriptor =
-      MakeInstructionDescriptor(57, SpvOpMatrixTimesVector, 0);
+      MakeInstructionDescriptor(57, spv::Op::OpMatrixTimesVector, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
        97},
@@ -1313,7 +1319,7 @@
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instruction_descriptor =
-      MakeInstructionDescriptor(58, SpvOpMatrixTimesVector, 0);
+      MakeInstructionDescriptor(58, spv::Op::OpMatrixTimesVector, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {98,  99,  100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
        110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121},
@@ -1321,7 +1327,7 @@
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instruction_descriptor =
-      MakeInstructionDescriptor(59, SpvOpMatrixTimesVector, 0);
+      MakeInstructionDescriptor(59, spv::Op::OpMatrixTimesVector, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132,
        133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143},
@@ -1684,7 +1690,7 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   auto instruction_descriptor =
-      MakeInstructionDescriptor(56, SpvOpMatrixTimesMatrix, 0);
+      MakeInstructionDescriptor(56, spv::Op::OpMatrixTimesMatrix, 0);
   auto transformation = TransformationReplaceLinearAlgebraInstruction(
       {83,  84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,
        97,  98,  99,  100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
@@ -1693,7 +1699,7 @@
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instruction_descriptor =
-      MakeInstructionDescriptor(57, SpvOpMatrixTimesMatrix, 0);
+      MakeInstructionDescriptor(57, spv::Op::OpMatrixTimesMatrix, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134,
        135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146,
@@ -1704,7 +1710,7 @@
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instruction_descriptor =
-      MakeInstructionDescriptor(58, SpvOpMatrixTimesMatrix, 0);
+      MakeInstructionDescriptor(58, spv::Op::OpMatrixTimesMatrix, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196,
        197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210,
@@ -2157,25 +2163,28 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   auto instruction_descriptor =
-      MakeInstructionDescriptor(47, SpvOpOuterProduct, 0);
+      MakeInstructionDescriptor(47, spv::Op::OpOuterProduct, 0);
   auto transformation = TransformationReplaceLinearAlgebraInstruction(
       {56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67}, instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
-  instruction_descriptor = MakeInstructionDescriptor(48, SpvOpOuterProduct, 0);
+  instruction_descriptor =
+      MakeInstructionDescriptor(48, spv::Op::OpOuterProduct, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85},
       instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
-  instruction_descriptor = MakeInstructionDescriptor(49, SpvOpOuterProduct, 0);
+  instruction_descriptor =
+      MakeInstructionDescriptor(49, spv::Op::OpOuterProduct, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {86, 87, 88,  89,  90,  91,  92,  93,  94,  95,  96,  97,
        98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109},
       instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
-  instruction_descriptor = MakeInstructionDescriptor(50, SpvOpOuterProduct, 0);
+  instruction_descriptor =
+      MakeInstructionDescriptor(50, spv::Op::OpOuterProduct, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123,
        124, 125},
@@ -2393,17 +2402,18 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto instruction_descriptor = MakeInstructionDescriptor(24, SpvOpDot, 0);
+  auto instruction_descriptor =
+      MakeInstructionDescriptor(24, spv::Op::OpDot, 0);
   auto transformation = TransformationReplaceLinearAlgebraInstruction(
       {27, 28, 29, 30, 31, 32}, instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
-  instruction_descriptor = MakeInstructionDescriptor(25, SpvOpDot, 0);
+  instruction_descriptor = MakeInstructionDescriptor(25, spv::Op::OpDot, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {33, 34, 35, 36, 37, 38, 39, 40, 41, 42}, instruction_descriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
-  instruction_descriptor = MakeInstructionDescriptor(26, SpvOpDot, 0);
+  instruction_descriptor = MakeInstructionDescriptor(26, spv::Op::OpDot, 0);
   transformation = TransformationReplaceLinearAlgebraInstruction(
       {43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56},
       instruction_descriptor);
diff --git a/test/fuzz/transformation_replace_load_store_with_copy_memory_test.cpp b/test/fuzz/transformation_replace_load_store_with_copy_memory_test.cpp
index bc10099..74da98b 100644
--- a/test/fuzz/transformation_replace_load_store_with_copy_memory_test.cpp
+++ b/test/fuzz/transformation_replace_load_store_with_copy_memory_test.cpp
@@ -118,29 +118,29 @@
                                                kConsoleMessageConsumer));
 
   auto bad_instruction_descriptor_1 =
-      MakeInstructionDescriptor(11, SpvOpConstant, 0);
+      MakeInstructionDescriptor(11, spv::Op::OpConstant, 0);
 
   auto load_instruction_descriptor_1 =
-      MakeInstructionDescriptor(22, SpvOpLoad, 0);
+      MakeInstructionDescriptor(22, spv::Op::OpLoad, 0);
   auto load_instruction_descriptor_2 =
-      MakeInstructionDescriptor(23, SpvOpLoad, 0);
+      MakeInstructionDescriptor(23, spv::Op::OpLoad, 0);
   auto load_instruction_descriptor_3 =
-      MakeInstructionDescriptor(24, SpvOpLoad, 0);
+      MakeInstructionDescriptor(24, spv::Op::OpLoad, 0);
   auto load_instruction_descriptor_other_block =
-      MakeInstructionDescriptor(34, SpvOpLoad, 0);
+      MakeInstructionDescriptor(34, spv::Op::OpLoad, 0);
   auto load_instruction_descriptor_unsafe =
-      MakeInstructionDescriptor(29, SpvOpLoad, 0);
+      MakeInstructionDescriptor(29, spv::Op::OpLoad, 0);
 
   auto store_instruction_descriptor_1 =
-      MakeInstructionDescriptor(22, SpvOpStore, 0);
+      MakeInstructionDescriptor(22, spv::Op::OpStore, 0);
   auto store_instruction_descriptor_2 =
-      MakeInstructionDescriptor(23, SpvOpStore, 0);
+      MakeInstructionDescriptor(23, spv::Op::OpStore, 0);
   auto store_instruction_descriptor_3 =
-      MakeInstructionDescriptor(24, SpvOpStore, 0);
+      MakeInstructionDescriptor(24, spv::Op::OpStore, 0);
   auto store_instruction_descriptor_other_block =
-      MakeInstructionDescriptor(37, SpvOpStore, 0);
+      MakeInstructionDescriptor(37, spv::Op::OpStore, 0);
   auto store_instruction_descriptor_unsafe =
-      MakeInstructionDescriptor(29, SpvOpStore, 0);
+      MakeInstructionDescriptor(29, spv::Op::OpStore, 0);
 
   // Bad: |load_instruction_descriptor| is incorrect.
   auto transformation_bad_1 = TransformationReplaceLoadStoreWithCopyMemory(
diff --git a/test/fuzz/transformation_set_function_control_test.cpp b/test/fuzz/transformation_set_function_control_test.cpp
index 85402e1..e51e24a 100644
--- a/test/fuzz/transformation_set_function_control_test.cpp
+++ b/test/fuzz/transformation_set_function_control_test.cpp
@@ -124,19 +124,22 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   // %36 is not a function
-  ASSERT_FALSE(TransformationSetFunctionControl(36, SpvFunctionControlMaskNone)
+  ASSERT_FALSE(TransformationSetFunctionControl(
+                   36, uint32_t(spv::FunctionControlMask::MaskNone))
                    .IsApplicable(context.get(), transformation_context));
   // Cannot add the Pure function control to %4 as it did not already have it
-  ASSERT_FALSE(TransformationSetFunctionControl(4, SpvFunctionControlPureMask)
+  ASSERT_FALSE(TransformationSetFunctionControl(
+                   4, uint32_t(spv::FunctionControlMask::Pure))
                    .IsApplicable(context.get(), transformation_context));
   // Cannot add the Const function control to %21 as it did not already
   // have it
-  ASSERT_FALSE(TransformationSetFunctionControl(21, SpvFunctionControlConstMask)
+  ASSERT_FALSE(TransformationSetFunctionControl(
+                   21, uint32_t(spv::FunctionControlMask::Const))
                    .IsApplicable(context.get(), transformation_context));
 
   // Set to None, removing Const
-  TransformationSetFunctionControl transformation1(11,
-                                                   SpvFunctionControlMaskNone);
+  TransformationSetFunctionControl transformation1(
+      11, uint32_t(spv::FunctionControlMask::MaskNone));
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation1, context.get(),
@@ -144,15 +147,15 @@
 
   // Set to Inline; silly to do it on an entry point, but it is allowed
   TransformationSetFunctionControl transformation2(
-      4, SpvFunctionControlInlineMask);
+      4, uint32_t(spv::FunctionControlMask::Inline));
   ASSERT_TRUE(
       transformation2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation2, context.get(),
                         &transformation_context);
 
   // Set to Pure, removing DontInline
-  TransformationSetFunctionControl transformation3(17,
-                                                   SpvFunctionControlPureMask);
+  TransformationSetFunctionControl transformation3(
+      17, uint32_t(spv::FunctionControlMask::Pure));
   ASSERT_TRUE(
       transformation3.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation3, context.get(),
@@ -160,7 +163,7 @@
 
   // Change from Inline to DontInline
   TransformationSetFunctionControl transformation4(
-      13, SpvFunctionControlDontInlineMask);
+      13, uint32_t(spv::FunctionControlMask::DontInline));
   ASSERT_TRUE(
       transformation4.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation4, context.get(),
diff --git a/test/fuzz/transformation_set_loop_control_test.cpp b/test/fuzz/transformation_set_loop_control_test.cpp
index 88b4aab..94a5b36 100644
--- a/test/fuzz/transformation_set_loop_control_test.cpp
+++ b/test/fuzz/transformation_set_loop_control_test.cpp
@@ -278,398 +278,458 @@
   // DependencyLength|MinIterations|MaxIterations|IterationMultiple|PeelCount|PartialCount
   // 2 5 90 4 7 14
 
-  ASSERT_TRUE(TransformationSetLoopControl(10, SpvLoopControlMaskNone, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  10, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(10, SpvLoopControlUnrollMask, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  10, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(10, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  10, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSetLoopControl(
-                   10, SpvLoopControlDependencyInfiniteMask, 0, 0)
+                   10, (uint32_t)spv::LoopControlMask::DependencyInfinite, 0, 0)
                    .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSetLoopControl(10, SpvLoopControlDependencyLengthMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSetLoopControl(10, SpvLoopControlMinIterationsMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSetLoopControl(10, SpvLoopControlMaxIterationsMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSetLoopControl(
-                   10, SpvLoopControlIterationMultipleMask, 0, 0)
+                   10, (uint32_t)spv::LoopControlMask::DependencyLength, 0, 0)
                    .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(10, SpvLoopControlPeelCountMask, 3, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSetLoopControl(10, SpvLoopControlPeelCountMask, 3, 3)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(10, SpvLoopControlPartialCountMask, 0, 3)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSetLoopControl(10, SpvLoopControlPartialCountMask, 3, 3)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   10, (uint32_t)spv::LoopControlMask::MinIterations, 0, 0)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   10, (uint32_t)spv::LoopControlMask::MaxIterations, 0, 0)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   10, (uint32_t)spv::LoopControlMask::IterationMultiple, 0, 0)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  10, (uint32_t)spv::LoopControlMask::PeelCount, 3, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   10, (uint32_t)spv::LoopControlMask::PeelCount, 3, 3)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  10, (uint32_t)spv::LoopControlMask::PartialCount, 0, 3)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   10, (uint32_t)spv::LoopControlMask::PartialCount, 3, 3)
+                   .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationSetLoopControl(
                   10,
-                  SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask,
+                  (uint32_t)spv::LoopControlMask::PeelCount |
+                      (uint32_t)spv::LoopControlMask::PartialCount,
                   3, 3)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(10,
-                                           SpvLoopControlUnrollMask |
-                                               SpvLoopControlPeelCountMask |
-                                               SpvLoopControlPartialCountMask,
-                                           3, 3)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  10,
+                  (uint32_t)spv::LoopControlMask::Unroll |
+                      (uint32_t)spv::LoopControlMask::PeelCount |
+                      (uint32_t)spv::LoopControlMask::PartialCount,
+                  3, 3)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(TransformationSetLoopControl(10,
-                                            SpvLoopControlDontUnrollMask |
-                                                SpvLoopControlPeelCountMask |
-                                                SpvLoopControlPartialCountMask,
-                                            3, 3)
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   10,
+                   (uint32_t)spv::LoopControlMask::DontUnroll |
+                       (uint32_t)spv::LoopControlMask::PeelCount |
+                       (uint32_t)spv::LoopControlMask::PartialCount,
+                   3, 3)
                    .IsApplicable(context.get(), transformation_context));
 
-  ASSERT_TRUE(TransformationSetLoopControl(23, SpvLoopControlMaskNone, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  23, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(23, SpvLoopControlUnrollMask, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  23, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(23, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  23, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationSetLoopControl(
                   23,
-                  SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask,
+                  (uint32_t)spv::LoopControlMask::PeelCount |
+                      (uint32_t)spv::LoopControlMask::PartialCount,
                   3, 3)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSetLoopControl(23, SpvLoopControlMaxIterationsMask, 2, 3)
-          .IsApplicable(context.get(), transformation_context));
-
-  ASSERT_TRUE(TransformationSetLoopControl(33, SpvLoopControlMaskNone, 0, 0)
-                  .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(33, SpvLoopControlUnrollMask, 0, 0)
-                  .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(33, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSetLoopControl(33, SpvLoopControlMinIterationsMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(
-          33, SpvLoopControlUnrollMask | SpvLoopControlPeelCountMask, 5, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(TransformationSetLoopControl(33,
-                                            SpvLoopControlDontUnrollMask |
-                                                SpvLoopControlPartialCountMask,
-                                            0, 10)
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   23, (uint32_t)spv::LoopControlMask::MaxIterations, 2, 3)
                    .IsApplicable(context.get(), transformation_context));
 
-  ASSERT_TRUE(TransformationSetLoopControl(43, SpvLoopControlMaskNone, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  33, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(43, SpvLoopControlUnrollMask, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  33, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(43, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  33, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   33, (uint32_t)spv::LoopControlMask::MinIterations, 0, 0)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  33,
+                  (uint32_t)spv::LoopControlMask::Unroll |
+                      (uint32_t)spv::LoopControlMask::PeelCount,
+                  5, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   33,
+                   (uint32_t)spv::LoopControlMask::DontUnroll |
+                       (uint32_t)spv::LoopControlMask::PartialCount,
+                   0, 10)
+                   .IsApplicable(context.get(), transformation_context));
+
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  43, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  43, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  43, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationSetLoopControl(
                   43,
-                  SpvLoopControlMaskNone | SpvLoopControlDependencyInfiniteMask,
+                  (uint32_t)spv::LoopControlMask::MaskNone |
+                      (uint32_t)spv::LoopControlMask::DependencyInfinite,
                   0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(
-          43, SpvLoopControlUnrollMask | SpvLoopControlDependencyInfiniteMask,
-          0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(
-          43,
-          SpvLoopControlDontUnrollMask | SpvLoopControlDependencyInfiniteMask,
-          0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSetLoopControl(43,
-                                   SpvLoopControlDependencyInfiniteMask |
-                                       SpvLoopControlDependencyLengthMask,
-                                   0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(
-          43, SpvLoopControlUnrollMask | SpvLoopControlPeelCountMask, 5, 0)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  43,
+                  (uint32_t)spv::LoopControlMask::Unroll |
+                      (uint32_t)spv::LoopControlMask::DependencyInfinite,
+                  0, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  43,
+                  (uint32_t)spv::LoopControlMask::DontUnroll |
+                      (uint32_t)spv::LoopControlMask::DependencyInfinite,
+                  0, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   43,
+                   (uint32_t)spv::LoopControlMask::DependencyInfinite |
+                       (uint32_t)spv::LoopControlMask::DependencyLength,
+                   0, 0)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  43,
+                  (uint32_t)spv::LoopControlMask::Unroll |
+                      (uint32_t)spv::LoopControlMask::PeelCount,
+                  5, 0)
+                  .IsApplicable(context.get(), transformation_context));
 
-  ASSERT_TRUE(TransformationSetLoopControl(53, SpvLoopControlMaskNone, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  53, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(53, SpvLoopControlUnrollMask, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  53, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(53, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSetLoopControl(53, SpvLoopControlMaxIterationsMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(
-          53, SpvLoopControlMaskNone | SpvLoopControlDependencyLengthMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSetLoopControl(
-          53, SpvLoopControlUnrollMask | SpvLoopControlDependencyInfiniteMask,
-          0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(
-          53, SpvLoopControlDontUnrollMask | SpvLoopControlDependencyLengthMask,
-          0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSetLoopControl(53,
-                                   SpvLoopControlDependencyInfiniteMask |
-                                       SpvLoopControlDependencyLengthMask,
-                                   0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(
-          53,
-          SpvLoopControlUnrollMask | SpvLoopControlDependencyLengthMask |
-              SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask,
-          5, 3)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  53, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   53, (uint32_t)spv::LoopControlMask::MaxIterations, 0, 0)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  53,
+                  (uint32_t)spv::LoopControlMask::MaskNone |
+                      (uint32_t)spv::LoopControlMask::DependencyLength,
+                  0, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   53,
+                   (uint32_t)spv::LoopControlMask::Unroll |
+                       (uint32_t)spv::LoopControlMask::DependencyInfinite,
+                   0, 0)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  53,
+                  (uint32_t)spv::LoopControlMask::DontUnroll |
+                      (uint32_t)spv::LoopControlMask::DependencyLength,
+                  0, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   53,
+                   (uint32_t)spv::LoopControlMask::DependencyInfinite |
+                       (uint32_t)spv::LoopControlMask::DependencyLength,
+                   0, 0)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  53,
+                  (uint32_t)spv::LoopControlMask::Unroll |
+                      (uint32_t)spv::LoopControlMask::DependencyLength |
+                      (uint32_t)spv::LoopControlMask::PeelCount |
+                      (uint32_t)spv::LoopControlMask::PartialCount,
+                  5, 3)
+                  .IsApplicable(context.get(), transformation_context));
 
-  ASSERT_TRUE(TransformationSetLoopControl(63, SpvLoopControlMaskNone, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  63, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(63, SpvLoopControlUnrollMask, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  63, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(63, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(63,
-                                           SpvLoopControlUnrollMask |
-                                               SpvLoopControlMinIterationsMask |
-                                               SpvLoopControlPeelCountMask |
-                                               SpvLoopControlPartialCountMask,
-                                           5, 3)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  63, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(63,
-                                           SpvLoopControlUnrollMask |
-                                               SpvLoopControlMinIterationsMask |
-                                               SpvLoopControlPeelCountMask,
-                                           23, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  63,
+                  (uint32_t)spv::LoopControlMask::Unroll |
+                      (uint32_t)spv::LoopControlMask::MinIterations |
+                      (uint32_t)spv::LoopControlMask::PeelCount |
+                      (uint32_t)spv::LoopControlMask::PartialCount,
+                  5, 3)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  63,
+                  (uint32_t)spv::LoopControlMask::Unroll |
+                      (uint32_t)spv::LoopControlMask::MinIterations |
+                      (uint32_t)spv::LoopControlMask::PeelCount,
+                  23, 0)
                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSetLoopControl(
                    63,
-                   SpvLoopControlUnrollMask | SpvLoopControlMinIterationsMask |
-                       SpvLoopControlPeelCountMask,
+                   (uint32_t)spv::LoopControlMask::Unroll |
+                       (uint32_t)spv::LoopControlMask::MinIterations |
+                       (uint32_t)spv::LoopControlMask::PeelCount,
                    2, 23)
                    .IsApplicable(context.get(), transformation_context));
 
-  ASSERT_TRUE(TransformationSetLoopControl(73, SpvLoopControlMaskNone, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  73, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(73, SpvLoopControlUnrollMask, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  73, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(73, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  73, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSetLoopControl(
                    73,
-                   SpvLoopControlUnrollMask | SpvLoopControlMinIterationsMask |
-                       SpvLoopControlPeelCountMask |
-                       SpvLoopControlPartialCountMask,
+                   (uint32_t)spv::LoopControlMask::Unroll |
+                       (uint32_t)spv::LoopControlMask::MinIterations |
+                       (uint32_t)spv::LoopControlMask::PeelCount |
+                       (uint32_t)spv::LoopControlMask::PartialCount,
                    5, 3)
                    .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(73,
-                                           SpvLoopControlUnrollMask |
-                                               SpvLoopControlMaxIterationsMask |
-                                               SpvLoopControlPeelCountMask,
-                                           23, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  73,
+                  (uint32_t)spv::LoopControlMask::Unroll |
+                      (uint32_t)spv::LoopControlMask::MaxIterations |
+                      (uint32_t)spv::LoopControlMask::PeelCount,
+                  23, 0)
                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSetLoopControl(
                    73,
-                   SpvLoopControlUnrollMask | SpvLoopControlMaxIterationsMask |
-                       SpvLoopControlPeelCountMask,
+                   (uint32_t)spv::LoopControlMask::Unroll |
+                       (uint32_t)spv::LoopControlMask::MaxIterations |
+                       (uint32_t)spv::LoopControlMask::PeelCount,
                    2, 23)
                    .IsApplicable(context.get(), transformation_context));
 
-  ASSERT_TRUE(TransformationSetLoopControl(83, SpvLoopControlMaskNone, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  83, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(83, SpvLoopControlUnrollMask, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  83, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(83, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  83, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSetLoopControl(
                    83,
-                   SpvLoopControlUnrollMask | SpvLoopControlMinIterationsMask |
-                       SpvLoopControlPeelCountMask |
-                       SpvLoopControlPartialCountMask,
+                   (uint32_t)spv::LoopControlMask::Unroll |
+                       (uint32_t)spv::LoopControlMask::MinIterations |
+                       (uint32_t)spv::LoopControlMask::PeelCount |
+                       (uint32_t)spv::LoopControlMask::PartialCount,
                    5, 3)
                    .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(83,
-                                   SpvLoopControlUnrollMask |
-                                       SpvLoopControlIterationMultipleMask |
-                                       SpvLoopControlPeelCountMask,
-                                   23, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSetLoopControl(83,
-                                   SpvLoopControlUnrollMask |
-                                       SpvLoopControlIterationMultipleMask |
-                                       SpvLoopControlPeelCountMask,
-                                   2, 23)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  83,
+                  (uint32_t)spv::LoopControlMask::Unroll |
+                      (uint32_t)spv::LoopControlMask::IterationMultiple |
+                      (uint32_t)spv::LoopControlMask::PeelCount,
+                  23, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   83,
+                   (uint32_t)spv::LoopControlMask::Unroll |
+                       (uint32_t)spv::LoopControlMask::IterationMultiple |
+                       (uint32_t)spv::LoopControlMask::PeelCount,
+                   2, 23)
+                   .IsApplicable(context.get(), transformation_context));
 
-  ASSERT_TRUE(TransformationSetLoopControl(93, SpvLoopControlMaskNone, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  93, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(93, SpvLoopControlUnrollMask, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  93, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(93, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(93, SpvLoopControlPeelCountMask, 8, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSetLoopControl(93, SpvLoopControlPeelCountMask, 8, 8)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(93, SpvLoopControlPartialCountMask, 0, 8)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  93, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  93, (uint32_t)spv::LoopControlMask::PeelCount, 8, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   93, (uint32_t)spv::LoopControlMask::PeelCount, 8, 8)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  93, (uint32_t)spv::LoopControlMask::PartialCount, 0, 8)
+                  .IsApplicable(context.get(), transformation_context));
   ASSERT_TRUE(TransformationSetLoopControl(
                   93,
-                  SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask,
+                  (uint32_t)spv::LoopControlMask::PeelCount |
+                      (uint32_t)spv::LoopControlMask::PartialCount,
                   16, 8)
                   .IsApplicable(context.get(), transformation_context));
 
-  ASSERT_TRUE(TransformationSetLoopControl(103, SpvLoopControlMaskNone, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  103, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(103, SpvLoopControlUnrollMask, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  103, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(103, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(103, SpvLoopControlPartialCountMask, 0, 60)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(TransformationSetLoopControl(103,
-                                            SpvLoopControlDontUnrollMask |
-                                                SpvLoopControlPartialCountMask,
-                                            0, 60)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  103, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  103, (uint32_t)spv::LoopControlMask::PartialCount, 0, 60)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   103,
+                   (uint32_t)spv::LoopControlMask::DontUnroll |
+                       (uint32_t)spv::LoopControlMask::PartialCount,
+                   0, 60)
                    .IsApplicable(context.get(), transformation_context));
 
-  ASSERT_TRUE(TransformationSetLoopControl(113, SpvLoopControlMaskNone, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  113, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(113, SpvLoopControlUnrollMask, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  113, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(113, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(113, SpvLoopControlPeelCountMask, 12, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSetLoopControl(
-          113,
-          SpvLoopControlIterationMultipleMask | SpvLoopControlPeelCountMask, 12,
-          0)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  113, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  113, (uint32_t)spv::LoopControlMask::PeelCount, 12, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   113,
+                   (uint32_t)spv::LoopControlMask::IterationMultiple |
+                       (uint32_t)spv::LoopControlMask::PeelCount,
+                   12, 0)
+                   .IsApplicable(context.get(), transformation_context));
 
-  ASSERT_TRUE(TransformationSetLoopControl(123, SpvLoopControlMaskNone, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  123, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(123, SpvLoopControlUnrollMask, 0, 0)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  123, (uint32_t)spv::LoopControlMask::Unroll, 0, 0)
                   .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(123, SpvLoopControlDontUnrollMask, 0, 0)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(
-      TransformationSetLoopControl(
-          123,
-          SpvLoopControlMinIterationsMask | SpvLoopControlMaxIterationsMask |
-              SpvLoopControlIterationMultipleMask |
-              SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask,
-          7, 8)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_TRUE(TransformationSetLoopControl(123,
-                                           SpvLoopControlUnrollMask |
-                                               SpvLoopControlMinIterationsMask |
-                                               SpvLoopControlMaxIterationsMask |
-                                               SpvLoopControlPartialCountMask,
-                                           0, 9)
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  123, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  123,
+                  (uint32_t)spv::LoopControlMask::MinIterations |
+                      (uint32_t)spv::LoopControlMask::MaxIterations |
+                      (uint32_t)spv::LoopControlMask::IterationMultiple |
+                      (uint32_t)spv::LoopControlMask::PeelCount |
+                      (uint32_t)spv::LoopControlMask::PartialCount,
+                  7, 8)
+                  .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSetLoopControl(
+                  123,
+                  (uint32_t)spv::LoopControlMask::Unroll |
+                      (uint32_t)spv::LoopControlMask::MinIterations |
+                      (uint32_t)spv::LoopControlMask::MaxIterations |
+                      (uint32_t)spv::LoopControlMask::PartialCount,
+                  0, 9)
                   .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSetLoopControl(
                    123,
-                   SpvLoopControlUnrollMask | SpvLoopControlMinIterationsMask |
-                       SpvLoopControlMaxIterationsMask |
-                       SpvLoopControlPartialCountMask,
+                   (uint32_t)spv::LoopControlMask::Unroll |
+                       (uint32_t)spv::LoopControlMask::MinIterations |
+                       (uint32_t)spv::LoopControlMask::MaxIterations |
+                       (uint32_t)spv::LoopControlMask::PartialCount,
                    7, 9)
                    .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSetLoopControl(
-          123,
-          SpvLoopControlDontUnrollMask | SpvLoopControlMinIterationsMask |
-              SpvLoopControlMaxIterationsMask | SpvLoopControlPartialCountMask,
-          7, 9)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetLoopControl(
+                   123,
+                   (uint32_t)spv::LoopControlMask::DontUnroll |
+                       (uint32_t)spv::LoopControlMask::MinIterations |
+                       (uint32_t)spv::LoopControlMask::MaxIterations |
+                       (uint32_t)spv::LoopControlMask::PartialCount,
+                   7, 9)
+                   .IsApplicable(context.get(), transformation_context));
 
+  ApplyAndCheckFreshIds(TransformationSetLoopControl(
+                            10,
+                            (uint32_t)spv::LoopControlMask::Unroll |
+                                (uint32_t)spv::LoopControlMask::PeelCount |
+                                (uint32_t)spv::LoopControlMask::PartialCount,
+                            3, 3),
+                        context.get(), &transformation_context);
   ApplyAndCheckFreshIds(
-      TransformationSetLoopControl(10,
-                                   SpvLoopControlUnrollMask |
-                                       SpvLoopControlPeelCountMask |
-                                       SpvLoopControlPartialCountMask,
-                                   3, 3),
+      TransformationSetLoopControl(
+          23, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0),
       context.get(), &transformation_context);
-  ApplyAndCheckFreshIds(
-      TransformationSetLoopControl(23, SpvLoopControlDontUnrollMask, 0, 0),
-      context.get(), &transformation_context);
-  ApplyAndCheckFreshIds(
-      TransformationSetLoopControl(33, SpvLoopControlUnrollMask, 0, 0),
-      context.get(), &transformation_context);
+  ApplyAndCheckFreshIds(TransformationSetLoopControl(
+                            33, (uint32_t)spv::LoopControlMask::Unroll, 0, 0),
+                        context.get(), &transformation_context);
   ApplyAndCheckFreshIds(
       TransformationSetLoopControl(
           43,
-          SpvLoopControlDontUnrollMask | SpvLoopControlDependencyInfiniteMask,
+          (uint32_t)spv::LoopControlMask::DontUnroll |
+              (uint32_t)spv::LoopControlMask::DependencyInfinite,
           0, 0),
       context.get(), &transformation_context);
+  ApplyAndCheckFreshIds(TransformationSetLoopControl(
+                            53, (uint32_t)spv::LoopControlMask::MaskNone, 0, 0),
+                        context.get(), &transformation_context);
+  ApplyAndCheckFreshIds(TransformationSetLoopControl(
+                            63,
+                            (uint32_t)spv::LoopControlMask::Unroll |
+                                (uint32_t)spv::LoopControlMask::MinIterations |
+                                (uint32_t)spv::LoopControlMask::PeelCount,
+                            23, 0),
+                        context.get(), &transformation_context);
+  ApplyAndCheckFreshIds(TransformationSetLoopControl(
+                            73,
+                            (uint32_t)spv::LoopControlMask::Unroll |
+                                (uint32_t)spv::LoopControlMask::MaxIterations |
+                                (uint32_t)spv::LoopControlMask::PeelCount,
+                            23, 0),
+                        context.get(), &transformation_context);
   ApplyAndCheckFreshIds(
-      TransformationSetLoopControl(53, SpvLoopControlMaskNone, 0, 0),
+      TransformationSetLoopControl(
+          83, (uint32_t)spv::LoopControlMask::DontUnroll, 0, 0),
       context.get(), &transformation_context);
+  ApplyAndCheckFreshIds(TransformationSetLoopControl(
+                            93,
+                            (uint32_t)spv::LoopControlMask::PeelCount |
+                                (uint32_t)spv::LoopControlMask::PartialCount,
+                            16, 8),
+                        context.get(), &transformation_context);
   ApplyAndCheckFreshIds(
-      TransformationSetLoopControl(63,
-                                   SpvLoopControlUnrollMask |
-                                       SpvLoopControlMinIterationsMask |
-                                       SpvLoopControlPeelCountMask,
-                                   23, 0),
-      context.get(), &transformation_context);
-  ApplyAndCheckFreshIds(
-      TransformationSetLoopControl(73,
-                                   SpvLoopControlUnrollMask |
-                                       SpvLoopControlMaxIterationsMask |
-                                       SpvLoopControlPeelCountMask,
-                                   23, 0),
-      context.get(), &transformation_context);
-  ApplyAndCheckFreshIds(
-      TransformationSetLoopControl(83, SpvLoopControlDontUnrollMask, 0, 0),
+      TransformationSetLoopControl(
+          103, (uint32_t)spv::LoopControlMask::PartialCount, 0, 60),
       context.get(), &transformation_context);
   ApplyAndCheckFreshIds(
       TransformationSetLoopControl(
-          93, SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask, 16,
-          8),
+          113, (uint32_t)spv::LoopControlMask::PeelCount, 12, 0),
       context.get(), &transformation_context);
-  ApplyAndCheckFreshIds(
-      TransformationSetLoopControl(103, SpvLoopControlPartialCountMask, 0, 60),
-      context.get(), &transformation_context);
-  ApplyAndCheckFreshIds(
-      TransformationSetLoopControl(113, SpvLoopControlPeelCountMask, 12, 0),
-      context.get(), &transformation_context);
-  ApplyAndCheckFreshIds(
-      TransformationSetLoopControl(
-          123,
-          SpvLoopControlUnrollMask | SpvLoopControlMinIterationsMask |
-              SpvLoopControlMaxIterationsMask | SpvLoopControlPartialCountMask,
-          0, 9),
-      context.get(), &transformation_context);
+  ApplyAndCheckFreshIds(TransformationSetLoopControl(
+                            123,
+                            (uint32_t)spv::LoopControlMask::Unroll |
+                                (uint32_t)spv::LoopControlMask::MinIterations |
+                                (uint32_t)spv::LoopControlMask::MaxIterations |
+                                (uint32_t)spv::LoopControlMask::PartialCount,
+                            0, 9),
+                        context.get(), &transformation_context);
 
   std::string after_transformation = R"(
                OpCapability Shader
@@ -958,10 +1018,10 @@
         context.get(), validator_options, kConsoleMessageConsumer));
     TransformationContext transformation_context(
         MakeUnique<FactManager>(context.get()), validator_options);
-    TransformationSetLoopControl peel_count(10, SpvLoopControlPeelCountMask, 4,
-                                            0);
+    TransformationSetLoopControl peel_count(
+        10, (uint32_t)spv::LoopControlMask::PeelCount, 4, 0);
     TransformationSetLoopControl partial_count(
-        10, SpvLoopControlPartialCountMask, 0, 4);
+        10, (uint32_t)spv::LoopControlMask::PartialCount, 0, 4);
 
     switch (env) {
       case SPV_ENV_UNIVERSAL_1_0:
diff --git a/test/fuzz/transformation_set_memory_operands_mask_test.cpp b/test/fuzz/transformation_set_memory_operands_mask_test.cpp
index 29e57f4..44901f9 100644
--- a/test/fuzz/transformation_set_memory_operands_mask_test.cpp
+++ b/test/fuzz/transformation_set_memory_operands_mask_test.cpp
@@ -106,8 +106,10 @@
     {
       // Not OK: multiple operands are not supported pre SPIR-V 1.4.
       TransformationSetMemoryOperandsMask transformation(
-          MakeInstructionDescriptor(21, SpvOpCopyMemory, 3),
-          SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 1);
+          MakeInstructionDescriptor(21, spv::Op::OpCopyMemory, 3),
+          (uint32_t)spv::MemoryAccessMask::Nontemporal |
+              (uint32_t)spv::MemoryAccessMask::Volatile,
+          1);
       ASSERT_DEATH(
           transformation.IsApplicable(context.get(), transformation_context),
           "Multiple memory operand masks are not supported");
@@ -116,21 +118,24 @@
 
     // Not OK: the instruction is not a memory access.
     ASSERT_FALSE(TransformationSetMemoryOperandsMask(
-                     MakeInstructionDescriptor(21, SpvOpAccessChain, 0),
-                     SpvMemoryAccessMaskNone, 0)
+                     MakeInstructionDescriptor(21, spv::Op::OpAccessChain, 0),
+                     (uint32_t)spv::MemoryAccessMask::MaskNone, 0)
                      .IsApplicable(context.get(), transformation_context));
 
     // Not OK to remove Aligned
-    ASSERT_FALSE(
-        TransformationSetMemoryOperandsMask(
-            MakeInstructionDescriptor(147, SpvOpLoad, 0),
-            SpvMemoryAccessVolatileMask | SpvMemoryAccessNontemporalMask, 0)
-            .IsApplicable(context.get(), transformation_context));
+    ASSERT_FALSE(TransformationSetMemoryOperandsMask(
+                     MakeInstructionDescriptor(147, spv::Op::OpLoad, 0),
+                     (uint32_t)spv::MemoryAccessMask::Volatile |
+                         (uint32_t)spv::MemoryAccessMask::Nontemporal,
+                     0)
+                     .IsApplicable(context.get(), transformation_context));
 
     {
       TransformationSetMemoryOperandsMask transformation(
-          MakeInstructionDescriptor(147, SpvOpLoad, 0),
-          SpvMemoryAccessAlignedMask | SpvMemoryAccessVolatileMask, 0);
+          MakeInstructionDescriptor(147, spv::Op::OpLoad, 0),
+          (uint32_t)spv::MemoryAccessMask::Aligned |
+              (uint32_t)spv::MemoryAccessMask::Volatile,
+          0);
       ASSERT_TRUE(
           transformation.IsApplicable(context.get(), transformation_context));
       ApplyAndCheckFreshIds(transformation, context.get(),
@@ -139,22 +144,23 @@
 
     // Not OK to remove Aligned
     ASSERT_FALSE(TransformationSetMemoryOperandsMask(
-                     MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
-                     SpvMemoryAccessMaskNone, 0)
+                     MakeInstructionDescriptor(21, spv::Op::OpCopyMemory, 0),
+                     (uint32_t)spv::MemoryAccessMask::MaskNone, 0)
                      .IsApplicable(context.get(), transformation_context));
 
     // OK: leaves the mask as is
     ASSERT_TRUE(TransformationSetMemoryOperandsMask(
-                    MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
-                    SpvMemoryAccessAlignedMask, 0)
+                    MakeInstructionDescriptor(21, spv::Op::OpCopyMemory, 0),
+                    (uint32_t)spv::MemoryAccessMask::Aligned, 0)
                     .IsApplicable(context.get(), transformation_context));
 
     {
       // OK: adds Nontemporal and Volatile
       TransformationSetMemoryOperandsMask transformation(
-          MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
-          SpvMemoryAccessAlignedMask | SpvMemoryAccessNontemporalMask |
-              SpvMemoryAccessVolatileMask,
+          MakeInstructionDescriptor(21, spv::Op::OpCopyMemory, 0),
+          (uint32_t)spv::MemoryAccessMask::Aligned |
+              (uint32_t)spv::MemoryAccessMask::Nontemporal |
+              (uint32_t)spv::MemoryAccessMask::Volatile,
           0);
       ASSERT_TRUE(
           transformation.IsApplicable(context.get(), transformation_context));
@@ -164,22 +170,25 @@
 
     // Not OK to remove Volatile
     ASSERT_FALSE(TransformationSetMemoryOperandsMask(
-                     MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
-                     SpvMemoryAccessNontemporalMask, 0)
+                     MakeInstructionDescriptor(21, spv::Op::OpCopyMemory, 1),
+                     (uint32_t)spv::MemoryAccessMask::Nontemporal, 0)
                      .IsApplicable(context.get(), transformation_context));
 
     // Not OK to add Aligned
     ASSERT_FALSE(TransformationSetMemoryOperandsMask(
-                     MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
-                     SpvMemoryAccessAlignedMask | SpvMemoryAccessVolatileMask,
+                     MakeInstructionDescriptor(21, spv::Op::OpCopyMemory, 1),
+                     (uint32_t)spv::MemoryAccessMask::Aligned |
+                         (uint32_t)spv::MemoryAccessMask::Volatile,
                      0)
                      .IsApplicable(context.get(), transformation_context));
 
     {
       // OK: adds Nontemporal
       TransformationSetMemoryOperandsMask transformation(
-          MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
-          SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 0);
+          MakeInstructionDescriptor(21, spv::Op::OpCopyMemory, 1),
+          (uint32_t)spv::MemoryAccessMask::Nontemporal |
+              (uint32_t)spv::MemoryAccessMask::Volatile,
+          0);
       ASSERT_TRUE(
           transformation.IsApplicable(context.get(), transformation_context));
       ApplyAndCheckFreshIds(transformation, context.get(),
@@ -189,8 +198,10 @@
     {
       // OK: adds Nontemporal (creates new operand)
       TransformationSetMemoryOperandsMask transformation(
-          MakeInstructionDescriptor(21, SpvOpCopyMemory, 2),
-          SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 0);
+          MakeInstructionDescriptor(21, spv::Op::OpCopyMemory, 2),
+          (uint32_t)spv::MemoryAccessMask::Nontemporal |
+              (uint32_t)spv::MemoryAccessMask::Volatile,
+          0);
       ASSERT_TRUE(
           transformation.IsApplicable(context.get(), transformation_context));
       ApplyAndCheckFreshIds(transformation, context.get(),
@@ -200,8 +211,10 @@
     {
       // OK: adds Nontemporal and Volatile
       TransformationSetMemoryOperandsMask transformation(
-          MakeInstructionDescriptor(138, SpvOpCopyMemory, 0),
-          SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 0);
+          MakeInstructionDescriptor(138, spv::Op::OpCopyMemory, 0),
+          (uint32_t)spv::MemoryAccessMask::Nontemporal |
+              (uint32_t)spv::MemoryAccessMask::Volatile,
+          0);
       ASSERT_TRUE(
           transformation.IsApplicable(context.get(), transformation_context));
       ApplyAndCheckFreshIds(transformation, context.get(),
@@ -211,8 +224,8 @@
     {
       // OK: removes Nontemporal, adds Volatile
       TransformationSetMemoryOperandsMask transformation(
-          MakeInstructionDescriptor(148, SpvOpStore, 0),
-          SpvMemoryAccessVolatileMask, 0);
+          MakeInstructionDescriptor(148, spv::Op::OpStore, 0),
+          (uint32_t)spv::MemoryAccessMask::Volatile, 0);
       ASSERT_TRUE(
           transformation.IsApplicable(context.get(), transformation_context));
       ApplyAndCheckFreshIds(transformation, context.get(),
@@ -369,12 +382,14 @@
         MakeUnique<FactManager>(context.get()), validator_options);
     {
       TransformationSetMemoryOperandsMask transformation(
-          MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
-          SpvMemoryAccessAlignedMask | SpvMemoryAccessVolatileMask, 1);
+          MakeInstructionDescriptor(21, spv::Op::OpCopyMemory, 0),
+          (uint32_t)spv::MemoryAccessMask::Aligned |
+              (uint32_t)spv::MemoryAccessMask::Volatile,
+          1);
       // Bad: cannot remove aligned
       ASSERT_FALSE(TransformationSetMemoryOperandsMask(
-                       MakeInstructionDescriptor(21, SpvOpCopyMemory, 0),
-                       SpvMemoryAccessVolatileMask, 1)
+                       MakeInstructionDescriptor(21, spv::Op::OpCopyMemory, 0),
+                       (uint32_t)spv::MemoryAccessMask::Volatile, 1)
                        .IsApplicable(context.get(), transformation_context));
       ASSERT_TRUE(
           transformation.IsApplicable(context.get(), transformation_context));
@@ -384,12 +399,14 @@
 
     {
       TransformationSetMemoryOperandsMask transformation(
-          MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
-          SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 1);
+          MakeInstructionDescriptor(21, spv::Op::OpCopyMemory, 1),
+          (uint32_t)spv::MemoryAccessMask::Nontemporal |
+              (uint32_t)spv::MemoryAccessMask::Volatile,
+          1);
       // Bad: cannot remove volatile
       ASSERT_FALSE(TransformationSetMemoryOperandsMask(
-                       MakeInstructionDescriptor(21, SpvOpCopyMemory, 1),
-                       SpvMemoryAccessNontemporalMask, 0)
+                       MakeInstructionDescriptor(21, spv::Op::OpCopyMemory, 1),
+                       (uint32_t)spv::MemoryAccessMask::Nontemporal, 0)
                        .IsApplicable(context.get(), transformation_context));
       ASSERT_TRUE(
           transformation.IsApplicable(context.get(), transformation_context));
@@ -400,8 +417,10 @@
     {
       // Creates the first operand.
       TransformationSetMemoryOperandsMask transformation(
-          MakeInstructionDescriptor(21, SpvOpCopyMemory, 2),
-          SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 0);
+          MakeInstructionDescriptor(21, spv::Op::OpCopyMemory, 2),
+          (uint32_t)spv::MemoryAccessMask::Nontemporal |
+              (uint32_t)spv::MemoryAccessMask::Volatile,
+          0);
       ASSERT_TRUE(
           transformation.IsApplicable(context.get(), transformation_context));
       ApplyAndCheckFreshIds(transformation, context.get(),
@@ -411,8 +430,10 @@
     {
       // Creates both operands.
       TransformationSetMemoryOperandsMask transformation(
-          MakeInstructionDescriptor(21, SpvOpCopyMemory, 3),
-          SpvMemoryAccessNontemporalMask | SpvMemoryAccessVolatileMask, 1);
+          MakeInstructionDescriptor(21, spv::Op::OpCopyMemory, 3),
+          (uint32_t)spv::MemoryAccessMask::Nontemporal |
+              (uint32_t)spv::MemoryAccessMask::Volatile,
+          1);
       ASSERT_TRUE(
           transformation.IsApplicable(context.get(), transformation_context));
       ApplyAndCheckFreshIds(transformation, context.get(),
@@ -421,14 +442,17 @@
 
     {
       TransformationSetMemoryOperandsMask transformation(
-          MakeInstructionDescriptor(138, SpvOpCopyMemory, 0),
-          SpvMemoryAccessAlignedMask | SpvMemoryAccessNontemporalMask, 1);
+          MakeInstructionDescriptor(138, spv::Op::OpCopyMemory, 0),
+          (uint32_t)spv::MemoryAccessMask::Aligned |
+              (uint32_t)spv::MemoryAccessMask::Nontemporal,
+          1);
       // Bad: the first mask is None, so Aligned cannot be added to it.
-      ASSERT_FALSE(
-          TransformationSetMemoryOperandsMask(
-              MakeInstructionDescriptor(138, SpvOpCopyMemory, 0),
-              SpvMemoryAccessAlignedMask | SpvMemoryAccessNontemporalMask, 0)
-              .IsApplicable(context.get(), transformation_context));
+      ASSERT_FALSE(TransformationSetMemoryOperandsMask(
+                       MakeInstructionDescriptor(138, spv::Op::OpCopyMemory, 0),
+                       (uint32_t)spv::MemoryAccessMask::Aligned |
+                           (uint32_t)spv::MemoryAccessMask::Nontemporal,
+                       0)
+                       .IsApplicable(context.get(), transformation_context));
       ASSERT_TRUE(
           transformation.IsApplicable(context.get(), transformation_context));
       ApplyAndCheckFreshIds(transformation, context.get(),
@@ -437,8 +461,8 @@
 
     {
       TransformationSetMemoryOperandsMask transformation(
-          MakeInstructionDescriptor(138, SpvOpCopyMemory, 1),
-          SpvMemoryAccessVolatileMask, 1);
+          MakeInstructionDescriptor(138, spv::Op::OpCopyMemory, 1),
+          (uint32_t)spv::MemoryAccessMask::Volatile, 1);
       ASSERT_TRUE(
           transformation.IsApplicable(context.get(), transformation_context));
       ApplyAndCheckFreshIds(transformation, context.get(),
@@ -447,8 +471,10 @@
 
     {
       TransformationSetMemoryOperandsMask transformation(
-          MakeInstructionDescriptor(147, SpvOpLoad, 0),
-          SpvMemoryAccessVolatileMask | SpvMemoryAccessAlignedMask, 0);
+          MakeInstructionDescriptor(147, spv::Op::OpLoad, 0),
+          (uint32_t)spv::MemoryAccessMask::Volatile |
+              (uint32_t)spv::MemoryAccessMask::Aligned,
+          0);
       ASSERT_TRUE(
           transformation.IsApplicable(context.get(), transformation_context));
       ApplyAndCheckFreshIds(transformation, context.get(),
@@ -457,8 +483,8 @@
 
     {
       TransformationSetMemoryOperandsMask transformation(
-          MakeInstructionDescriptor(148, SpvOpStore, 0),
-          SpvMemoryAccessMaskNone, 0);
+          MakeInstructionDescriptor(148, spv::Op::OpStore, 0),
+          (uint32_t)spv::MemoryAccessMask::MaskNone, 0);
       ASSERT_TRUE(
           transformation.IsApplicable(context.get(), transformation_context));
       ApplyAndCheckFreshIds(transformation, context.get(),
diff --git a/test/fuzz/transformation_set_selection_control_test.cpp b/test/fuzz/transformation_set_selection_control_test.cpp
index c584ff1..4cecd23 100644
--- a/test/fuzz/transformation_set_selection_control_test.cpp
+++ b/test/fuzz/transformation_set_selection_control_test.cpp
@@ -109,41 +109,41 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   // %44 is not a block
-  ASSERT_FALSE(
-      TransformationSetSelectionControl(44, SpvSelectionControlFlattenMask)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetSelectionControl(
+                   44, uint32_t(spv::SelectionControlMask::Flatten))
+                   .IsApplicable(context.get(), transformation_context));
   // %13 does not end with OpSelectionMerge
-  ASSERT_FALSE(
-      TransformationSetSelectionControl(13, SpvSelectionControlMaskNone)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetSelectionControl(
+                   13, uint32_t(spv::SelectionControlMask::MaskNone))
+                   .IsApplicable(context.get(), transformation_context));
   // %10 ends in OpLoopMerge, not OpSelectionMerge
-  ASSERT_FALSE(
-      TransformationSetSelectionControl(10, SpvSelectionControlMaskNone)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSetSelectionControl(
+                   10, uint32_t(spv::SelectionControlMask::MaskNone))
+                   .IsApplicable(context.get(), transformation_context));
 
   TransformationSetSelectionControl transformation1(
-      11, SpvSelectionControlDontFlattenMask);
+      11, uint32_t(spv::SelectionControlMask::DontFlatten));
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation1, context.get(),
                         &transformation_context);
 
   TransformationSetSelectionControl transformation2(
-      23, SpvSelectionControlFlattenMask);
+      23, uint32_t(spv::SelectionControlMask::Flatten));
   ASSERT_TRUE(
       transformation2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation2, context.get(),
                         &transformation_context);
 
   TransformationSetSelectionControl transformation3(
-      31, SpvSelectionControlMaskNone);
+      31, uint32_t(spv::SelectionControlMask::MaskNone));
   ASSERT_TRUE(
       transformation3.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation3, context.get(),
                         &transformation_context);
 
   TransformationSetSelectionControl transformation4(
-      31, SpvSelectionControlFlattenMask);
+      31, uint32_t(spv::SelectionControlMask::Flatten));
   ASSERT_TRUE(
       transformation4.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation4, context.get(),
diff --git a/test/fuzz/transformation_split_block_test.cpp b/test/fuzz/transformation_split_block_test.cpp
index 55091de..1cef182 100644
--- a/test/fuzz/transformation_split_block_test.cpp
+++ b/test/fuzz/transformation_split_block_test.cpp
@@ -96,53 +96,54 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // No split before OpVariable
   ASSERT_FALSE(TransformationSplitBlock(
-                   MakeInstructionDescriptor(8, SpvOpVariable, 0), 100)
+                   MakeInstructionDescriptor(8, spv::Op::OpVariable, 0), 100)
                    .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSplitBlock(
-                   MakeInstructionDescriptor(8, SpvOpVariable, 1), 100)
+                   MakeInstructionDescriptor(8, spv::Op::OpVariable, 1), 100)
                    .IsApplicable(context.get(), transformation_context));
 
   // No split before OpLabel
   ASSERT_FALSE(TransformationSplitBlock(
-                   MakeInstructionDescriptor(14, SpvOpLabel, 0), 100)
+                   MakeInstructionDescriptor(14, spv::Op::OpLabel, 0), 100)
                    .IsApplicable(context.get(), transformation_context));
 
   // No split if base instruction is outside a function
-  ASSERT_FALSE(
-      TransformationSplitBlock(MakeInstructionDescriptor(1, SpvOpLabel, 0), 100)
-          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSplitBlock(
-                   MakeInstructionDescriptor(1, SpvOpExecutionMode, 0), 100)
+                   MakeInstructionDescriptor(1, spv::Op::OpLabel, 0), 100)
                    .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationSplitBlock(
+          MakeInstructionDescriptor(1, spv::Op::OpExecutionMode, 0), 100)
+          .IsApplicable(context.get(), transformation_context));
 
   // No split if block is loop header
-  ASSERT_FALSE(
-      TransformationSplitBlock(MakeInstructionDescriptor(27, SpvOpPhi, 0), 100)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSplitBlock(MakeInstructionDescriptor(27, SpvOpPhi, 1), 100)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSplitBlock(
+                   MakeInstructionDescriptor(27, spv::Op::OpPhi, 0), 100)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSplitBlock(
+                   MakeInstructionDescriptor(27, spv::Op::OpPhi, 1), 100)
+                   .IsApplicable(context.get(), transformation_context));
 
   // No split if base instruction does not exist
-  ASSERT_FALSE(
-      TransformationSplitBlock(MakeInstructionDescriptor(88, SpvOpIAdd, 0), 100)
-          .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSplitBlock(
-                   MakeInstructionDescriptor(88, SpvOpIMul, 22), 100)
+                   MakeInstructionDescriptor(88, spv::Op::OpIAdd, 0), 100)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSplitBlock(
+                   MakeInstructionDescriptor(88, spv::Op::OpIMul, 22), 100)
                    .IsApplicable(context.get(), transformation_context));
 
   // No split if too many instructions with the desired opcode are skipped
   ASSERT_FALSE(
       TransformationSplitBlock(
-          MakeInstructionDescriptor(18, SpvOpBranchConditional, 1), 100)
+          MakeInstructionDescriptor(18, spv::Op::OpBranchConditional, 1), 100)
           .IsApplicable(context.get(), transformation_context));
 
   // No split if id in use
   ASSERT_FALSE(TransformationSplitBlock(
-                   MakeInstructionDescriptor(18, SpvOpSLessThan, 0), 27)
+                   MakeInstructionDescriptor(18, spv::Op::OpSLessThan, 0), 27)
                    .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSplitBlock(
-                   MakeInstructionDescriptor(18, SpvOpSLessThan, 0), 14)
+                   MakeInstructionDescriptor(18, spv::Op::OpSLessThan, 0), 14)
                    .IsApplicable(context.get(), transformation_context));
 }
 
@@ -206,7 +207,7 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   auto split_1 = TransformationSplitBlock(
-      MakeInstructionDescriptor(5, SpvOpStore, 0), 100);
+      MakeInstructionDescriptor(5, spv::Op::OpStore, 0), 100);
   ASSERT_TRUE(split_1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(split_1, context.get(), &transformation_context);
   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
@@ -255,7 +256,7 @@
   ASSERT_TRUE(IsEqual(env, after_split_1, context.get()));
 
   auto split_2 = TransformationSplitBlock(
-      MakeInstructionDescriptor(11, SpvOpStore, 0), 101);
+      MakeInstructionDescriptor(11, spv::Op::OpStore, 0), 101);
   ASSERT_TRUE(split_2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(split_2, context.get(), &transformation_context);
   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
@@ -306,7 +307,7 @@
   ASSERT_TRUE(IsEqual(env, after_split_2, context.get()));
 
   auto split_3 = TransformationSplitBlock(
-      MakeInstructionDescriptor(14, SpvOpLoad, 0), 102);
+      MakeInstructionDescriptor(14, spv::Op::OpLoad, 0), 102);
   ASSERT_TRUE(split_3.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(split_3, context.get(), &transformation_context);
   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
@@ -425,15 +426,15 @@
   // Illegal to split between the merge and the conditional branch.
   ASSERT_FALSE(
       TransformationSplitBlock(
-          MakeInstructionDescriptor(14, SpvOpBranchConditional, 0), 100)
+          MakeInstructionDescriptor(14, spv::Op::OpBranchConditional, 0), 100)
           .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationSplitBlock(
-          MakeInstructionDescriptor(12, SpvOpBranchConditional, 0), 100)
+          MakeInstructionDescriptor(12, spv::Op::OpBranchConditional, 0), 100)
           .IsApplicable(context.get(), transformation_context));
 
   auto split = TransformationSplitBlock(
-      MakeInstructionDescriptor(14, SpvOpSelectionMerge, 0), 100);
+      MakeInstructionDescriptor(14, spv::Op::OpSelectionMerge, 0), 100);
   ASSERT_TRUE(split.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(split, context.get(), &transformation_context);
   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
@@ -555,14 +556,14 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // Illegal to split between the merge and the conditional branch.
   ASSERT_FALSE(TransformationSplitBlock(
-                   MakeInstructionDescriptor(9, SpvOpSwitch, 0), 100)
+                   MakeInstructionDescriptor(9, spv::Op::OpSwitch, 0), 100)
                    .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(TransformationSplitBlock(
-                   MakeInstructionDescriptor(15, SpvOpSwitch, 0), 100)
+                   MakeInstructionDescriptor(15, spv::Op::OpSwitch, 0), 100)
                    .IsApplicable(context.get(), transformation_context));
 
   auto split = TransformationSplitBlock(
-      MakeInstructionDescriptor(9, SpvOpSelectionMerge, 0), 100);
+      MakeInstructionDescriptor(9, spv::Op::OpSelectionMerge, 0), 100);
   ASSERT_TRUE(split.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(split, context.get(), &transformation_context);
   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
@@ -690,15 +691,15 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // We cannot split before OpPhi instructions, since the number of incoming
   // blocks may not appropriately match after splitting.
-  ASSERT_FALSE(
-      TransformationSplitBlock(MakeInstructionDescriptor(26, SpvOpPhi, 0), 100)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSplitBlock(MakeInstructionDescriptor(27, SpvOpPhi, 0), 100)
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationSplitBlock(MakeInstructionDescriptor(27, SpvOpPhi, 1), 100)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSplitBlock(
+                   MakeInstructionDescriptor(26, spv::Op::OpPhi, 0), 100)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSplitBlock(
+                   MakeInstructionDescriptor(27, spv::Op::OpPhi, 0), 100)
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationSplitBlock(
+                   MakeInstructionDescriptor(27, spv::Op::OpPhi, 1), 100)
+                   .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationSplitBlockTest, SplitOpPhiWithSinglePredecessor) {
@@ -741,13 +742,13 @@
   spvtools::ValidatorOptions validator_options;
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  ASSERT_TRUE(
-      TransformationSplitBlock(MakeInstructionDescriptor(21, SpvOpPhi, 0), 100)
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_TRUE(TransformationSplitBlock(
+                  MakeInstructionDescriptor(21, spv::Op::OpPhi, 0), 100)
+                  .IsApplicable(context.get(), transformation_context));
   // An equivalent transformation to the above, just described with respect to a
   // different base instruction.
-  auto split =
-      TransformationSplitBlock(MakeInstructionDescriptor(20, SpvOpPhi, 0), 100);
+  auto split = TransformationSplitBlock(
+      MakeInstructionDescriptor(20, spv::Op::OpPhi, 0), 100);
   ASSERT_TRUE(split.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(split, context.get(), &transformation_context);
   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
@@ -826,7 +827,7 @@
   transformation_context.GetFactManager()->AddFactBlockIsDead(8);
 
   auto split = TransformationSplitBlock(
-      MakeInstructionDescriptor(8, SpvOpBranch, 0), 100);
+      MakeInstructionDescriptor(8, spv::Op::OpBranch, 0), 100);
   ASSERT_TRUE(split.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(split, context.get(), &transformation_context);
   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
@@ -912,7 +913,8 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   auto split = TransformationSplitBlock(
-      MakeInstructionDescriptor(217, SpvOpImageSampleImplicitLod, 0), 500);
+      MakeInstructionDescriptor(217, spv::Op::OpImageSampleImplicitLod, 0),
+      500);
   ASSERT_FALSE(split.IsApplicable(context.get(), transformation_context));
 }
 
diff --git a/test/fuzz/transformation_store_test.cpp b/test/fuzz/transformation_store_test.cpp
index dd653e2..fe24d74 100644
--- a/test/fuzz/transformation_store_test.cpp
+++ b/test/fuzz/transformation_store_test.cpp
@@ -148,107 +148,107 @@
   //  61 - undefined
 
   // Bad: attempt to store to 11 from outside its function
-  ASSERT_FALSE(
-      TransformationStore(11, false, 0, 0, 80,
-                          MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   11, false, 0, 0, 80,
+                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer is not available
-  ASSERT_FALSE(
-      TransformationStore(81, false, 0, 0, 80,
-                          MakeInstructionDescriptor(45, SpvOpCopyObject, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   81, false, 0, 0, 80,
+                   MakeInstructionDescriptor(45, spv::Op::OpCopyObject, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: attempt to insert before OpVariable
   ASSERT_FALSE(
       TransformationStore(52, false, 0, 0, 24,
-                          MakeInstructionDescriptor(27, SpvOpVariable, 0))
+                          MakeInstructionDescriptor(27, spv::Op::OpVariable, 0))
           .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer id does not exist
-  ASSERT_FALSE(
-      TransformationStore(1000, false, 0, 0, 24,
-                          MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   1000, false, 0, 0, 24,
+                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer id exists but does not have a type
-  ASSERT_FALSE(
-      TransformationStore(5, false, 0, 0, 24,
-                          MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   5, false, 0, 0, 24,
+                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: pointer id exists and has a type, but is not a pointer
-  ASSERT_FALSE(
-      TransformationStore(24, false, 0, 0, 24,
-                          MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   24, false, 0, 0, 24,
+                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: attempt to store to a null pointer
-  ASSERT_FALSE(
-      TransformationStore(60, false, 0, 0, 24,
-                          MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   60, false, 0, 0, 24,
+                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: attempt to store to an undefined pointer
-  ASSERT_FALSE(
-      TransformationStore(61, false, 0, 0, 21,
-                          MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   61, false, 0, 0, 21,
+                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: %82 is not available at the program point
   ASSERT_FALSE(
       TransformationStore(82, false, 0, 0, 80,
-                          MakeInstructionDescriptor(37, SpvOpReturn, 0))
+                          MakeInstructionDescriptor(37, spv::Op::OpReturn, 0))
           .IsApplicable(context.get(), transformation_context));
 
   // Bad: value id does not exist
-  ASSERT_FALSE(
-      TransformationStore(27, false, 0, 0, 1000,
-                          MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   27, false, 0, 0, 1000,
+                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: value id exists but does not have a type
-  ASSERT_FALSE(
-      TransformationStore(27, false, 0, 0, 15,
-                          MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   27, false, 0, 0, 15,
+                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: value id exists but has the wrong type
-  ASSERT_FALSE(
-      TransformationStore(27, false, 0, 0, 14,
-                          MakeInstructionDescriptor(38, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   27, false, 0, 0, 14,
+                   MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: attempt to store to read-only variable
-  ASSERT_FALSE(
-      TransformationStore(92, false, 0, 0, 93,
-                          MakeInstructionDescriptor(40, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   92, false, 0, 0, 93,
+                   MakeInstructionDescriptor(40, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: value is not available
-  ASSERT_FALSE(
-      TransformationStore(27, false, 0, 0, 95,
-                          MakeInstructionDescriptor(40, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   27, false, 0, 0, 95,
+                   MakeInstructionDescriptor(40, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: variable being stored to does not have an irrelevant pointee value,
   // and the store is not in a dead block.
-  ASSERT_FALSE(
-      TransformationStore(20, false, 0, 0, 95,
-                          MakeInstructionDescriptor(45, SpvOpCopyObject, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   20, false, 0, 0, 95,
+                   MakeInstructionDescriptor(45, spv::Op::OpCopyObject, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // The described instruction does not exist.
-  ASSERT_FALSE(
-      TransformationStore(27, false, 0, 0, 80,
-                          MakeInstructionDescriptor(1000, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   27, false, 0, 0, 80,
+                   MakeInstructionDescriptor(1000, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   {
     // Store to irrelevant variable from dead block.
     TransformationStore transformation(
         27, false, 0, 0, 80,
-        MakeInstructionDescriptor(38, SpvOpAccessChain, 0));
+        MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -261,7 +261,7 @@
     // Store to irrelevant variable from live block.
     TransformationStore transformation(
         11, false, 0, 0, 95,
-        MakeInstructionDescriptor(95, SpvOpReturnValue, 0));
+        MakeInstructionDescriptor(95, spv::Op::OpReturnValue, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -274,7 +274,7 @@
     // Store to irrelevant variable from live block.
     TransformationStore transformation(
         46, false, 0, 0, 80,
-        MakeInstructionDescriptor(95, SpvOpReturnValue, 0));
+        MakeInstructionDescriptor(95, spv::Op::OpReturnValue, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -287,7 +287,7 @@
     // Store to irrelevant variable from live block.
     TransformationStore transformation(
         16, false, 0, 0, 21,
-        MakeInstructionDescriptor(95, SpvOpReturnValue, 0));
+        MakeInstructionDescriptor(95, spv::Op::OpReturnValue, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -300,7 +300,7 @@
     // Store to non-irrelevant variable from dead block.
     TransformationStore transformation(
         53, false, 0, 0, 21,
-        MakeInstructionDescriptor(38, SpvOpAccessChain, 0));
+        MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
@@ -436,15 +436,15 @@
 
   ASSERT_FALSE(
       TransformationStore(15, false, 0, 0, 13,
-                          MakeInstructionDescriptor(27, SpvOpReturn, 0))
+                          MakeInstructionDescriptor(27, spv::Op::OpReturn, 0))
           .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationStore(19, false, 0, 0, 50,
-                          MakeInstructionDescriptor(27, SpvOpReturn, 0))
+                          MakeInstructionDescriptor(27, spv::Op::OpReturn, 0))
           .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
       TransformationStore(27, false, 0, 0, 50,
-                          MakeInstructionDescriptor(27, SpvOpReturn, 0))
+                          MakeInstructionDescriptor(27, spv::Op::OpReturn, 0))
           .IsApplicable(context.get(), transformation_context));
 }
 
@@ -495,84 +495,85 @@
       14);
 
   // Bad: id 100 of memory scope instruction does not exist.
-  ASSERT_FALSE(
-      TransformationStore(14, true, 100, 20, 21,
-                          MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   14, true, 100, 20, 21,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // Bad: id 100 of memory semantics instruction does not exist.
-  ASSERT_FALSE(
-      TransformationStore(14, true, 15, 100, 21,
-                          MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   14, true, 15, 100, 21,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // Bad: memory scope should be |OpConstant| opcode.
-  ASSERT_FALSE(
-      TransformationStore(14, true, 5, 20, 21,
-                          MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   14, true, 5, 20, 21,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // Bad: memory semantics should be |OpConstant| opcode.
-  ASSERT_FALSE(
-      TransformationStore(14, true, 15, 5, 21,
-                          MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   14, true, 15, 5, 21,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: The memory scope instruction must have an Integer operand.
-  ASSERT_FALSE(
-      TransformationStore(14, true, 15, 19, 21,
-                          MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   14, true, 15, 19, 21,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // Bad: The memory memory semantics instruction must have an Integer operand.
-  ASSERT_FALSE(
-      TransformationStore(14, true, 19, 20, 21,
-                          MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   14, true, 19, 20, 21,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: Integer size of the memory scope must be equal to 32 bits.
-  ASSERT_FALSE(
-      TransformationStore(14, true, 17, 20, 21,
-                          MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   14, true, 17, 20, 21,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: Integer size of memory semantics must be equal to 32 bits.
-  ASSERT_FALSE(
-      TransformationStore(14, true, 15, 17, 21,
-                          MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   14, true, 15, 17, 21,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
-  // Bad: memory scope value must be 4 (SpvScopeInvocation).
-  ASSERT_FALSE(
-      TransformationStore(14, true, 16, 20, 21,
-                          MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  // Bad: memory scope value must be 4 (spv::Scope::Invocation).
+  ASSERT_FALSE(TransformationStore(
+                   14, true, 16, 20, 21,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: memory semantics value must be either:
   // 64 (SpvMemorySemanticsUniformMemoryMask)
   // 256 (SpvMemorySemanticsWorkgroupMemoryMask)
-  ASSERT_FALSE(
-      TransformationStore(14, true, 15, 16, 21,
-                          MakeInstructionDescriptor(24, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   14, true, 15, 16, 21,
+                   MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
   // Bad: The described instruction does not exist
-  ASSERT_FALSE(
-      TransformationStore(14, true, 15, 20, 21,
-                          MakeInstructionDescriptor(150, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   14, true, 15, 20, 21,
+                   MakeInstructionDescriptor(150, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: Can't insert OpAccessChain before the id 15 of memory scope.
-  ASSERT_FALSE(
-      TransformationStore(14, true, 15, 20, 21,
-                          MakeInstructionDescriptor(15, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   14, true, 15, 20, 21,
+                   MakeInstructionDescriptor(15, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Bad: Can't insert OpAccessChain before the id 20 of memory semantics.
-  ASSERT_FALSE(
-      TransformationStore(14, true, 15, 20, 21,
-                          MakeInstructionDescriptor(20, SpvOpAccessChain, 0))
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationStore(
+                   14, true, 15, 20, 21,
+                   MakeInstructionDescriptor(20, spv::Op::OpAccessChain, 0))
+                   .IsApplicable(context.get(), transformation_context));
 
   // Successful transformations.
   {
     TransformationStore transformation(
-        14, true, 15, 20, 21, MakeInstructionDescriptor(24, SpvOpReturn, 0));
+        14, true, 15, 20, 21,
+        MakeInstructionDescriptor(24, spv::Op::OpReturn, 0));
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
     ApplyAndCheckFreshIds(transformation, context.get(),
diff --git a/test/fuzz/transformation_swap_commutable_operands_test.cpp b/test/fuzz/transformation_swap_commutable_operands_test.cpp
index 0731529..789dd09 100644
--- a/test/fuzz/transformation_swap_commutable_operands_test.cpp
+++ b/test/fuzz/transformation_swap_commutable_operands_test.cpp
@@ -118,103 +118,108 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   // Tests existing commutative instructions
-  auto instructionDescriptor = MakeInstructionDescriptor(22, SpvOpIAdd, 0);
+  auto instructionDescriptor =
+      MakeInstructionDescriptor(22, spv::Op::OpIAdd, 0);
   auto transformation =
       TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(28, SpvOpIMul, 0);
+  instructionDescriptor = MakeInstructionDescriptor(28, spv::Op::OpIMul, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(42, SpvOpFAdd, 0);
+  instructionDescriptor = MakeInstructionDescriptor(42, spv::Op::OpFAdd, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(48, SpvOpFMul, 0);
+  instructionDescriptor = MakeInstructionDescriptor(48, spv::Op::OpFMul, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(66, SpvOpDot, 0);
+  instructionDescriptor = MakeInstructionDescriptor(66, spv::Op::OpDot, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   // Tests existing non-commutative instructions
-  instructionDescriptor = MakeInstructionDescriptor(1, SpvOpExtInstImport, 0);
+  instructionDescriptor =
+      MakeInstructionDescriptor(1, spv::Op::OpExtInstImport, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(5, SpvOpLabel, 0);
+  instructionDescriptor = MakeInstructionDescriptor(5, spv::Op::OpLabel, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(8, SpvOpConstant, 0);
+  instructionDescriptor = MakeInstructionDescriptor(8, spv::Op::OpConstant, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(11, SpvOpVariable, 0);
+  instructionDescriptor = MakeInstructionDescriptor(11, spv::Op::OpVariable, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor =
-      MakeInstructionDescriptor(14, SpvOpConstantComposite, 0);
+      MakeInstructionDescriptor(14, spv::Op::OpConstantComposite, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   // Tests the base instruction id not existing
-  instructionDescriptor = MakeInstructionDescriptor(67, SpvOpIAddCarry, 0);
+  instructionDescriptor =
+      MakeInstructionDescriptor(67, spv::Op::OpIAddCarry, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(68, SpvOpIEqual, 0);
+  instructionDescriptor = MakeInstructionDescriptor(68, spv::Op::OpIEqual, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(69, SpvOpINotEqual, 0);
+  instructionDescriptor =
+      MakeInstructionDescriptor(69, spv::Op::OpINotEqual, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(70, SpvOpFOrdEqual, 0);
+  instructionDescriptor =
+      MakeInstructionDescriptor(70, spv::Op::OpFOrdEqual, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(71, SpvOpPtrEqual, 0);
+  instructionDescriptor = MakeInstructionDescriptor(71, spv::Op::OpPtrEqual, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   // Tests there being no instruction with the desired opcode after the base
   // instruction id
-  instructionDescriptor = MakeInstructionDescriptor(24, SpvOpIAdd, 0);
+  instructionDescriptor = MakeInstructionDescriptor(24, spv::Op::OpIAdd, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(38, SpvOpIMul, 0);
+  instructionDescriptor = MakeInstructionDescriptor(38, spv::Op::OpIMul, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(45, SpvOpFAdd, 0);
+  instructionDescriptor = MakeInstructionDescriptor(45, spv::Op::OpFAdd, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(66, SpvOpFMul, 0);
+  instructionDescriptor = MakeInstructionDescriptor(66, spv::Op::OpFMul, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
@@ -222,27 +227,27 @@
   // Tests there being an instruction with the desired opcode after the base
   // instruction id, but the skip count associated with the instruction
   // descriptor being so high.
-  instructionDescriptor = MakeInstructionDescriptor(11, SpvOpIAdd, 100);
+  instructionDescriptor = MakeInstructionDescriptor(11, spv::Op::OpIAdd, 100);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(16, SpvOpIMul, 100);
+  instructionDescriptor = MakeInstructionDescriptor(16, spv::Op::OpIMul, 100);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(23, SpvOpFAdd, 100);
+  instructionDescriptor = MakeInstructionDescriptor(23, spv::Op::OpFAdd, 100);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(32, SpvOpFMul, 100);
+  instructionDescriptor = MakeInstructionDescriptor(32, spv::Op::OpFMul, 100);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(37, SpvOpDot, 100);
+  instructionDescriptor = MakeInstructionDescriptor(37, spv::Op::OpDot, 100);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
@@ -342,24 +347,25 @@
                                                kConsoleMessageConsumer));
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
-  auto instructionDescriptor = MakeInstructionDescriptor(22, SpvOpIAdd, 0);
+  auto instructionDescriptor =
+      MakeInstructionDescriptor(22, spv::Op::OpIAdd, 0);
   auto transformation =
       TransformationSwapCommutableOperands(instructionDescriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
-  instructionDescriptor = MakeInstructionDescriptor(28, SpvOpIMul, 0);
+  instructionDescriptor = MakeInstructionDescriptor(28, spv::Op::OpIMul, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
-  instructionDescriptor = MakeInstructionDescriptor(42, SpvOpFAdd, 0);
+  instructionDescriptor = MakeInstructionDescriptor(42, spv::Op::OpFAdd, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
-  instructionDescriptor = MakeInstructionDescriptor(48, SpvOpFMul, 0);
+  instructionDescriptor = MakeInstructionDescriptor(48, spv::Op::OpFMul, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
-  instructionDescriptor = MakeInstructionDescriptor(66, SpvOpDot, 0);
+  instructionDescriptor = MakeInstructionDescriptor(66, spv::Op::OpDot, 0);
   transformation = TransformationSwapCommutableOperands(instructionDescriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
diff --git a/test/fuzz/transformation_swap_conditional_branch_operands_test.cpp b/test/fuzz/transformation_swap_conditional_branch_operands_test.cpp
index 6133a7a..5f7ffe4 100644
--- a/test/fuzz/transformation_swap_conditional_branch_operands_test.cpp
+++ b/test/fuzz/transformation_swap_conditional_branch_operands_test.cpp
@@ -76,27 +76,29 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // Invalid instruction descriptor.
   ASSERT_FALSE(TransformationSwapConditionalBranchOperands(
-                   MakeInstructionDescriptor(26, SpvOpPhi, 0), 26)
+                   MakeInstructionDescriptor(26, spv::Op::OpPhi, 0), 26)
                    .IsApplicable(context.get(), transformation_context));
 
   // Descriptor for a wrong instruction.
   ASSERT_FALSE(TransformationSwapConditionalBranchOperands(
-                   MakeInstructionDescriptor(25, SpvOpPhi, 0), 26)
+                   MakeInstructionDescriptor(25, spv::Op::OpPhi, 0), 26)
                    .IsApplicable(context.get(), transformation_context));
 
   // Fresh id is not fresh.
-  ASSERT_FALSE(TransformationSwapConditionalBranchOperands(
-                   MakeInstructionDescriptor(15, SpvOpBranchConditional, 0), 25)
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationSwapConditionalBranchOperands(
+          MakeInstructionDescriptor(15, spv::Op::OpBranchConditional, 0), 25)
+          .IsApplicable(context.get(), transformation_context));
 
   TransformationSwapConditionalBranchOperands transformation(
-      MakeInstructionDescriptor(15, SpvOpBranchConditional, 0), 26);
+      MakeInstructionDescriptor(15, spv::Op::OpBranchConditional, 0), 26);
   ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(26));
   ASSERT_EQ(nullptr, context->get_instr_block(26));
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
-  ASSERT_EQ(SpvOpLogicalNot, context->get_def_use_mgr()->GetDef(26)->opcode());
+  ASSERT_EQ(spv::Op::OpLogicalNot,
+            context->get_def_use_mgr()->GetDef(26)->opcode());
   ASSERT_EQ(5, context->get_instr_block(26)->id());
   ASSERT_EQ(1, context->get_def_use_mgr()->NumUses(26));
 
@@ -109,7 +111,7 @@
     context->get_def_use_mgr()->WhileEachUse(
         entry.first,
         [&entry](opt::Instruction* inst, uint32_t operand_index) -> bool {
-          if (inst->opcode() == SpvOpBranchConditional) {
+          if (inst->opcode() == spv::Op::OpBranchConditional) {
             EXPECT_EQ(entry.second, operand_index);
             return false;
           }
diff --git a/test/fuzz/transformation_toggle_access_chain_instruction_test.cpp b/test/fuzz/transformation_toggle_access_chain_instruction_test.cpp
index 84ed20d..94ca804 100644
--- a/test/fuzz/transformation_toggle_access_chain_instruction_test.cpp
+++ b/test/fuzz/transformation_toggle_access_chain_instruction_test.cpp
@@ -119,67 +119,71 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   // Tests existing access chain instructions
   auto instructionDescriptor =
-      MakeInstructionDescriptor(18, SpvOpAccessChain, 0);
+      MakeInstructionDescriptor(18, spv::Op::OpAccessChain, 0);
   auto transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor =
-      MakeInstructionDescriptor(20, SpvOpInBoundsAccessChain, 0);
-  transformation =
-      TransformationToggleAccessChainInstruction(instructionDescriptor);
-  ASSERT_TRUE(
-      transformation.IsApplicable(context.get(), transformation_context));
-
-  instructionDescriptor = MakeInstructionDescriptor(24, SpvOpAccessChain, 0);
+      MakeInstructionDescriptor(20, spv::Op::OpInBoundsAccessChain, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor =
-      MakeInstructionDescriptor(26, SpvOpInBoundsAccessChain, 0);
+      MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0);
+  transformation =
+      TransformationToggleAccessChainInstruction(instructionDescriptor);
+  ASSERT_TRUE(
+      transformation.IsApplicable(context.get(), transformation_context));
+
+  instructionDescriptor =
+      MakeInstructionDescriptor(26, spv::Op::OpInBoundsAccessChain, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   // Tests existing non-access chain instructions
-  instructionDescriptor = MakeInstructionDescriptor(1, SpvOpExtInstImport, 0);
+  instructionDescriptor =
+      MakeInstructionDescriptor(1, spv::Op::OpExtInstImport, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
-  instructionDescriptor = MakeInstructionDescriptor(5, SpvOpLabel, 0);
+  instructionDescriptor = MakeInstructionDescriptor(5, spv::Op::OpLabel, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor =
-      MakeInstructionDescriptor(14, SpvOpConstantComposite, 0);
+      MakeInstructionDescriptor(14, spv::Op::OpConstantComposite, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   // Tests the base instruction id not existing
-  instructionDescriptor = MakeInstructionDescriptor(67, SpvOpAccessChain, 0);
-  transformation =
-      TransformationToggleAccessChainInstruction(instructionDescriptor);
-  ASSERT_FALSE(
-      transformation.IsApplicable(context.get(), transformation_context));
-
-  instructionDescriptor = MakeInstructionDescriptor(68, SpvOpAccessChain, 0);
+  instructionDescriptor =
+      MakeInstructionDescriptor(67, spv::Op::OpAccessChain, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor =
-      MakeInstructionDescriptor(69, SpvOpInBoundsAccessChain, 0);
+      MakeInstructionDescriptor(68, spv::Op::OpAccessChain, 0);
+  transformation =
+      TransformationToggleAccessChainInstruction(instructionDescriptor);
+  ASSERT_FALSE(
+      transformation.IsApplicable(context.get(), transformation_context));
+
+  instructionDescriptor =
+      MakeInstructionDescriptor(69, spv::Op::OpInBoundsAccessChain, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ASSERT_FALSE(
@@ -187,14 +191,15 @@
 
   // Tests there being no instruction with the desired opcode after the base
   // instruction id
-  instructionDescriptor = MakeInstructionDescriptor(65, SpvOpAccessChain, 0);
+  instructionDescriptor =
+      MakeInstructionDescriptor(65, spv::Op::OpAccessChain, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor =
-      MakeInstructionDescriptor(66, SpvOpInBoundsAccessChain, 0);
+      MakeInstructionDescriptor(66, spv::Op::OpInBoundsAccessChain, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ASSERT_FALSE(
@@ -203,14 +208,15 @@
   // Tests there being an instruction with the desired opcode after the base
   // instruction id, but the skip count associated with the instruction
   // descriptor being so high.
-  instructionDescriptor = MakeInstructionDescriptor(11, SpvOpAccessChain, 100);
+  instructionDescriptor =
+      MakeInstructionDescriptor(11, spv::Op::OpAccessChain, 100);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ASSERT_FALSE(
       transformation.IsApplicable(context.get(), transformation_context));
 
   instructionDescriptor =
-      MakeInstructionDescriptor(16, SpvOpInBoundsAccessChain, 100);
+      MakeInstructionDescriptor(16, spv::Op::OpInBoundsAccessChain, 100);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ASSERT_FALSE(
@@ -312,29 +318,31 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   auto instructionDescriptor =
-      MakeInstructionDescriptor(18, SpvOpAccessChain, 0);
+      MakeInstructionDescriptor(18, spv::Op::OpAccessChain, 0);
   auto transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instructionDescriptor =
-      MakeInstructionDescriptor(20, SpvOpInBoundsAccessChain, 0);
-  transformation =
-      TransformationToggleAccessChainInstruction(instructionDescriptor);
-  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
-
-  instructionDescriptor = MakeInstructionDescriptor(24, SpvOpAccessChain, 0);
+      MakeInstructionDescriptor(20, spv::Op::OpInBoundsAccessChain, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
   instructionDescriptor =
-      MakeInstructionDescriptor(26, SpvOpInBoundsAccessChain, 0);
+      MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
 
-  instructionDescriptor = MakeInstructionDescriptor(38, SpvOpAccessChain, 0);
+  instructionDescriptor =
+      MakeInstructionDescriptor(26, spv::Op::OpInBoundsAccessChain, 0);
+  transformation =
+      TransformationToggleAccessChainInstruction(instructionDescriptor);
+  ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
+
+  instructionDescriptor =
+      MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0);
   transformation =
       TransformationToggleAccessChainInstruction(instructionDescriptor);
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
diff --git a/test/fuzz/transformation_vector_shuffle_test.cpp b/test/fuzz/transformation_vector_shuffle_test.cpp
index e3dc0a7..4d8f985 100644
--- a/test/fuzz/transformation_vector_shuffle_test.cpp
+++ b/test/fuzz/transformation_vector_shuffle_test.cpp
@@ -172,80 +172,82 @@
 
   // %103 does not dominate the return instruction.
   ASSERT_FALSE(TransformationVectorShuffle(
-                   MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 103, 65,
-                   {3, 5, 7})
+                   MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200,
+                   103, 65, {3, 5, 7})
                    .IsApplicable(context.get(), transformation_context));
 
   // Illegal to shuffle a bvec2 and a vec3
   ASSERT_FALSE(TransformationVectorShuffle(
-                   MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 112, 61,
-                   {0, 2, 4})
+                   MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200,
+                   112, 61, {0, 2, 4})
                    .IsApplicable(context.get(), transformation_context));
 
   // Illegal to shuffle an ivec2 and a uvec4
   ASSERT_FALSE(TransformationVectorShuffle(
-                   MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 27, 50,
-                   {1, 3, 5})
+                   MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200,
+                   27, 50, {1, 3, 5})
                    .IsApplicable(context.get(), transformation_context));
 
   // Vector 1 does not exist
   ASSERT_FALSE(TransformationVectorShuffle(
-                   MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 300, 50,
-                   {1, 3, 5})
+                   MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200,
+                   300, 50, {1, 3, 5})
                    .IsApplicable(context.get(), transformation_context));
 
   // Vector 2 does not exist
   ASSERT_FALSE(TransformationVectorShuffle(
-                   MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 27, 300,
-                   {1, 3, 5})
+                   MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200,
+                   27, 300, {1, 3, 5})
                    .IsApplicable(context.get(), transformation_context));
 
   // Index out of range
-  ASSERT_FALSE(
-      TransformationVectorShuffle(
-          MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112, {0, 20})
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationVectorShuffle(
+                   MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200,
+                   12, 112, {0, 20})
+                   .IsApplicable(context.get(), transformation_context));
 
   // Too many indices
   ASSERT_FALSE(TransformationVectorShuffle(
-                   MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112,
-                   {0, 1, 0, 1, 0, 1, 0, 1})
+                   MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200,
+                   12, 112, {0, 1, 0, 1, 0, 1, 0, 1})
                    .IsApplicable(context.get(), transformation_context));
 
   // Too few indices
-  ASSERT_FALSE(
-      TransformationVectorShuffle(
-          MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112, {})
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationVectorShuffle(
+                   MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200,
+                   12, 112, {})
+                   .IsApplicable(context.get(), transformation_context));
 
   // Too few indices again
-  ASSERT_FALSE(
-      TransformationVectorShuffle(
-          MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112, {0})
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationVectorShuffle(
+                   MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200,
+                   12, 112, {0})
+                   .IsApplicable(context.get(), transformation_context));
 
   // Indices define unknown type: we do not have vec2
-  ASSERT_FALSE(
-      TransformationVectorShuffle(
-          MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 65, 65, {0, 1})
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationVectorShuffle(
+                   MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200,
+                   65, 65, {0, 1})
+                   .IsApplicable(context.get(), transformation_context));
 
   // The instruction to insert before does not exist
-  ASSERT_FALSE(TransformationVectorShuffle(
-                   MakeInstructionDescriptor(100, SpvOpCompositeConstruct, 1),
-                   201, 20, 12, {0xFFFFFFFF, 3, 5})
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationVectorShuffle(
+          MakeInstructionDescriptor(100, spv::Op::OpCompositeConstruct, 1), 201,
+          20, 12, {0xFFFFFFFF, 3, 5})
+          .IsApplicable(context.get(), transformation_context));
 
   // The 'fresh' id is already in use
   ASSERT_FALSE(
       TransformationVectorShuffle(
-          MakeInstructionDescriptor(100, SpvOpReturn, 0), 12, 12, 112, {})
+          MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 12, 12, 112, {})
           .IsApplicable(context.get(), transformation_context));
 
   protobufs::DataDescriptor temp_dd;
 
   TransformationVectorShuffle transformation1(
-      MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112, {1, 0});
+      MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200, 12, 112,
+      {1, 0});
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation1, context.get(),
@@ -258,7 +260,7 @@
       MakeDataDescriptor(10, {}), temp_dd));
 
   TransformationVectorShuffle transformation2(
-      MakeInstructionDescriptor(100, SpvOpReturn, 0), 201, 20, 12,
+      MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 201, 20, 12,
       {0xFFFFFFFF, 3, 5});
   ASSERT_TRUE(
       transformation2.IsApplicable(context.get(), transformation_context));
@@ -272,7 +274,8 @@
       MakeDataDescriptor(11, {}), temp_dd));
 
   TransformationVectorShuffle transformation3(
-      MakeInstructionDescriptor(100, SpvOpReturn, 0), 202, 27, 35, {5, 4, 1});
+      MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 202, 27, 35,
+      {5, 4, 1});
   ASSERT_TRUE(
       transformation3.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation3, context.get(),
@@ -288,7 +291,8 @@
       MakeDataDescriptor(26, {}), temp_dd));
 
   TransformationVectorShuffle transformation4(
-      MakeInstructionDescriptor(100, SpvOpReturn, 0), 203, 42, 46, {0, 1});
+      MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 203, 42, 46,
+      {0, 1});
   ASSERT_TRUE(
       transformation4.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation4, context.get(),
@@ -301,7 +305,8 @@
       MakeDataDescriptor(41, {}), temp_dd));
 
   TransformationVectorShuffle transformation5(
-      MakeInstructionDescriptor(100, SpvOpReturn, 0), 204, 42, 46, {2, 3, 4});
+      MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 204, 42, 46,
+      {2, 3, 4});
   ASSERT_TRUE(
       transformation5.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation5, context.get(),
@@ -317,7 +322,7 @@
       MakeDataDescriptor(40, {}), temp_dd));
 
   TransformationVectorShuffle transformation6(
-      MakeInstructionDescriptor(100, SpvOpReturn, 0), 205, 42, 42,
+      MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 205, 42, 42,
       {0, 1, 2, 3});
   ASSERT_TRUE(
       transformation6.IsApplicable(context.get(), transformation_context));
@@ -338,7 +343,7 @@
 
   // swizzle vec4 from vec4 and vec4 using some undefs
   TransformationVectorShuffle transformation7(
-      MakeInstructionDescriptor(100, SpvOpReturn, 0), 206, 65, 65,
+      MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 206, 65, 65,
       {0xFFFFFFFF, 3, 6, 0xFFFFFFFF});
   ASSERT_TRUE(
       transformation7.IsApplicable(context.get(), transformation_context));
@@ -500,50 +505,52 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   // Cannot insert before the OpVariables of a function.
-  ASSERT_FALSE(
-      TransformationVectorShuffle(
-          MakeInstructionDescriptor(101, SpvOpVariable, 0), 200, 14, 14, {0, 1})
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationVectorShuffle(
-          MakeInstructionDescriptor(101, SpvOpVariable, 1), 200, 14, 14, {1, 2})
-          .IsApplicable(context.get(), transformation_context));
-  ASSERT_FALSE(
-      TransformationVectorShuffle(
-          MakeInstructionDescriptor(102, SpvOpVariable, 0), 200, 14, 14, {1, 2})
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationVectorShuffle(
+                   MakeInstructionDescriptor(101, spv::Op::OpVariable, 0), 200,
+                   14, 14, {0, 1})
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationVectorShuffle(
+                   MakeInstructionDescriptor(101, spv::Op::OpVariable, 1), 200,
+                   14, 14, {1, 2})
+                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationVectorShuffle(
+                   MakeInstructionDescriptor(102, spv::Op::OpVariable, 0), 200,
+                   14, 14, {1, 2})
+                   .IsApplicable(context.get(), transformation_context));
   // OK to insert right after the OpVariables.
-  ASSERT_FALSE(
-      TransformationVectorShuffle(
-          MakeInstructionDescriptor(102, SpvOpBranch, 1), 200, 14, 14, {1, 1})
-          .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(TransformationVectorShuffle(
+                   MakeInstructionDescriptor(102, spv::Op::OpBranch, 1), 200,
+                   14, 14, {1, 1})
+                   .IsApplicable(context.get(), transformation_context));
 
   // Cannot insert before the OpPhis of a block.
   ASSERT_FALSE(
-      TransformationVectorShuffle(MakeInstructionDescriptor(60, SpvOpPhi, 0),
-                                  200, 14, 14, {2, 0})
+      TransformationVectorShuffle(
+          MakeInstructionDescriptor(60, spv::Op::OpPhi, 0), 200, 14, 14, {2, 0})
           .IsApplicable(context.get(), transformation_context));
   ASSERT_FALSE(
-      TransformationVectorShuffle(MakeInstructionDescriptor(59, SpvOpPhi, 0),
-                                  200, 14, 14, {3, 0})
+      TransformationVectorShuffle(
+          MakeInstructionDescriptor(59, spv::Op::OpPhi, 0), 200, 14, 14, {3, 0})
           .IsApplicable(context.get(), transformation_context));
   // OK to insert after the OpPhis.
   ASSERT_TRUE(TransformationVectorShuffle(
-                  MakeInstructionDescriptor(59, SpvOpAccessChain, 0), 200, 14,
-                  14, {3, 4})
+                  MakeInstructionDescriptor(59, spv::Op::OpAccessChain, 0), 200,
+                  14, 14, {3, 4})
                   .IsApplicable(context.get(), transformation_context));
 
   // Cannot insert before OpLoopMerge
-  ASSERT_FALSE(TransformationVectorShuffle(
-                   MakeInstructionDescriptor(33, SpvOpBranchConditional, 0),
-                   200, 14, 14, {3})
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationVectorShuffle(
+          MakeInstructionDescriptor(33, spv::Op::OpBranchConditional, 0), 200,
+          14, 14, {3})
+          .IsApplicable(context.get(), transformation_context));
 
   // Cannot insert before OpSelectionMerge
-  ASSERT_FALSE(TransformationVectorShuffle(
-                   MakeInstructionDescriptor(21, SpvOpBranchConditional, 0),
-                   200, 14, 14, {2})
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationVectorShuffle(
+          MakeInstructionDescriptor(21, spv::Op::OpBranchConditional, 0), 200,
+          14, 14, {2})
+          .IsApplicable(context.get(), transformation_context));
 }
 
 TEST(TransformationVectorShuffleTest, HandlesIrrelevantIds1) {
@@ -615,7 +622,8 @@
   TransformationContext transformation_context(
       MakeUnique<FactManager>(context.get()), validator_options);
   TransformationVectorShuffle transformation(
-      MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112, {2, 0});
+      MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200, 12, 112,
+      {2, 0});
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
@@ -697,7 +705,8 @@
       MakeUnique<FactManager>(context.get()), validator_options);
   transformation_context.GetFactManager()->AddFactIdIsIrrelevant(112);
   TransformationVectorShuffle transformation(
-      MakeInstructionDescriptor(100, SpvOpReturn, 0), 200, 12, 112, {2, 0});
+      MakeInstructionDescriptor(100, spv::Op::OpReturn, 0), 200, 12, 112,
+      {2, 0});
   ASSERT_TRUE(
       transformation.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
@@ -755,7 +764,7 @@
   transformation_context.GetFactManager()->AddFactBlockIsDead(15);
 
   TransformationVectorShuffle transformation1(
-      MakeInstructionDescriptor(15, SpvOpBranch, 0), 200, 12, 12, {0, 3});
+      MakeInstructionDescriptor(15, spv::Op::OpBranch, 0), 200, 12, 12, {0, 3});
   ASSERT_TRUE(
       transformation1.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation1, context.get(),
@@ -766,7 +775,7 @@
       MakeDataDescriptor(200, {1}), MakeDataDescriptor(12, {1})));
 
   TransformationVectorShuffle transformation2(
-      MakeInstructionDescriptor(16, SpvOpReturn, 0), 201, 12, 40, {0, 1});
+      MakeInstructionDescriptor(16, spv::Op::OpReturn, 0), 201, 12, 40, {0, 1});
   ASSERT_TRUE(
       transformation2.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation2, context.get(),
@@ -777,7 +786,7 @@
       MakeDataDescriptor(201, {1}), MakeDataDescriptor(12, {1})));
 
   TransformationVectorShuffle transformation3(
-      MakeInstructionDescriptor(16, SpvOpReturn, 0), 202, 40, 12, {2, 3});
+      MakeInstructionDescriptor(16, spv::Op::OpReturn, 0), 202, 40, 12, {2, 3});
   ASSERT_TRUE(
       transformation3.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation3, context.get(),
@@ -788,7 +797,7 @@
       MakeDataDescriptor(202, {1}), MakeDataDescriptor(12, {1})));
 
   TransformationVectorShuffle transformation4(
-      MakeInstructionDescriptor(16, SpvOpReturn, 0), 203, 40, 12, {0, 3});
+      MakeInstructionDescriptor(16, spv::Op::OpReturn, 0), 203, 40, 12, {0, 3});
   ASSERT_TRUE(
       transformation4.IsApplicable(context.get(), transformation_context));
   ApplyAndCheckFreshIds(transformation4, context.get(),
diff --git a/test/fuzz/transformation_wrap_early_terminator_in_function_test.cpp b/test/fuzz/transformation_wrap_early_terminator_in_function_test.cpp
index 7b4e487..fbbf57b 100644
--- a/test/fuzz/transformation_wrap_early_terminator_in_function_test.cpp
+++ b/test/fuzz/transformation_wrap_early_terminator_in_function_test.cpp
@@ -98,48 +98,50 @@
 
   // Bad: id is not fresh
   ASSERT_FALSE(TransformationWrapEarlyTerminatorInFunction(
-                   61, MakeInstructionDescriptor(8, SpvOpKill, 0), 0)
+                   61, MakeInstructionDescriptor(8, spv::Op::OpKill, 0), 0)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: early terminator instruction descriptor does not exist
   ASSERT_FALSE(TransformationWrapEarlyTerminatorInFunction(
-                   100, MakeInstructionDescriptor(82, SpvOpKill, 0), 0)
+                   100, MakeInstructionDescriptor(82, spv::Op::OpKill, 0), 0)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: early terminator instruction does not identify an early terminator
-  ASSERT_FALSE(TransformationWrapEarlyTerminatorInFunction(
-                   100, MakeInstructionDescriptor(5, SpvOpSelectionMerge, 0), 0)
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationWrapEarlyTerminatorInFunction(
+          100, MakeInstructionDescriptor(5, spv::Op::OpSelectionMerge, 0), 0)
+          .IsApplicable(context.get(), transformation_context));
 
   // Bad: no wrapper function is available
-  ASSERT_FALSE(TransformationWrapEarlyTerminatorInFunction(
-                   100, MakeInstructionDescriptor(9, SpvOpUnreachable, 0), 0)
-                   .IsApplicable(context.get(), transformation_context));
+  ASSERT_FALSE(
+      TransformationWrapEarlyTerminatorInFunction(
+          100, MakeInstructionDescriptor(9, spv::Op::OpUnreachable, 0), 0)
+          .IsApplicable(context.get(), transformation_context));
 
   // Bad: returned value does not exist
   ASSERT_FALSE(TransformationWrapEarlyTerminatorInFunction(
-                   100, MakeInstructionDescriptor(62, SpvOpKill, 0), 1000)
+                   100, MakeInstructionDescriptor(62, spv::Op::OpKill, 0), 1000)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: returned value does not have a type
   ASSERT_FALSE(TransformationWrapEarlyTerminatorInFunction(
-                   100, MakeInstructionDescriptor(62, SpvOpKill, 0), 61)
+                   100, MakeInstructionDescriptor(62, spv::Op::OpKill, 0), 61)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: returned value type does not match
   ASSERT_FALSE(TransformationWrapEarlyTerminatorInFunction(
-                   100, MakeInstructionDescriptor(62, SpvOpKill, 0), 91)
+                   100, MakeInstructionDescriptor(62, spv::Op::OpKill, 0), 91)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: returned value is not available
   ASSERT_FALSE(TransformationWrapEarlyTerminatorInFunction(
-                   100, MakeInstructionDescriptor(62, SpvOpKill, 0), 81)
+                   100, MakeInstructionDescriptor(62, spv::Op::OpKill, 0), 81)
                    .IsApplicable(context.get(), transformation_context));
 
   // Bad: the OpKill being targeted is in the only available wrapper; we cannot
   // have the wrapper call itself.
   ASSERT_FALSE(TransformationWrapEarlyTerminatorInFunction(
-                   100, MakeInstructionDescriptor(31, SpvOpKill, 0), 0)
+                   100, MakeInstructionDescriptor(31, spv::Op::OpKill, 0), 0)
                    .IsApplicable(context.get(), transformation_context));
 }
 
@@ -220,17 +222,20 @@
 
   for (auto& transformation :
        {TransformationWrapEarlyTerminatorInFunction(
-            100, MakeInstructionDescriptor(8, SpvOpKill, 0), 0),
+            100, MakeInstructionDescriptor(8, spv::Op::OpKill, 0), 0),
         TransformationWrapEarlyTerminatorInFunction(
-            101, MakeInstructionDescriptor(9, SpvOpUnreachable, 0), 0),
+            101, MakeInstructionDescriptor(9, spv::Op::OpUnreachable, 0), 0),
         TransformationWrapEarlyTerminatorInFunction(
-            102, MakeInstructionDescriptor(10, SpvOpTerminateInvocation, 0), 0),
+            102,
+            MakeInstructionDescriptor(10, spv::Op::OpTerminateInvocation, 0),
+            0),
         TransformationWrapEarlyTerminatorInFunction(
-            103, MakeInstructionDescriptor(62, SpvOpKill, 0), 0),
+            103, MakeInstructionDescriptor(62, spv::Op::OpKill, 0), 0),
         TransformationWrapEarlyTerminatorInFunction(
-            104, MakeInstructionDescriptor(71, SpvOpUnreachable, 0), 7),
+            104, MakeInstructionDescriptor(71, spv::Op::OpUnreachable, 0), 7),
         TransformationWrapEarlyTerminatorInFunction(
-            105, MakeInstructionDescriptor(82, SpvOpTerminateInvocation, 0),
+            105,
+            MakeInstructionDescriptor(82, spv::Op::OpTerminateInvocation, 0),
             0)}) {
     ASSERT_TRUE(
         transformation.IsApplicable(context.get(), transformation_context));
diff --git a/test/immediate_int_test.cpp b/test/immediate_int_test.cpp
index 393075a..8e7a8fd 100644
--- a/test/immediate_int_test.cpp
+++ b/test/immediate_int_test.cpp
@@ -57,34 +57,34 @@
 
 TEST_F(ImmediateIntTest, AnyWordInSimpleStatement) {
   EXPECT_THAT(CompiledInstructions("!0x00040018 %a %b %123"),
-              Eq(MakeInstruction(SpvOpTypeMatrix, {1, 2, 3})));
+              Eq(MakeInstruction(spv::Op::OpTypeMatrix, {1, 2, 3})));
   EXPECT_THAT(CompiledInstructions("!0x00040018 !1 %b %123"),
-              Eq(MakeInstruction(SpvOpTypeMatrix, {1, 1, 2})));
+              Eq(MakeInstruction(spv::Op::OpTypeMatrix, {1, 1, 2})));
   EXPECT_THAT(CompiledInstructions("%a = OpTypeMatrix !2 %123"),
-              Eq(MakeInstruction(SpvOpTypeMatrix, {1, 2, 2})));
+              Eq(MakeInstruction(spv::Op::OpTypeMatrix, {1, 2, 2})));
   EXPECT_THAT(CompiledInstructions("%a = OpTypeMatrix  %b !123"),
-              Eq(MakeInstruction(SpvOpTypeMatrix, {1, 2, 123})));
+              Eq(MakeInstruction(spv::Op::OpTypeMatrix, {1, 2, 123})));
   EXPECT_THAT(CompiledInstructions("!0x00040018 %a !2 %123"),
-              Eq(MakeInstruction(SpvOpTypeMatrix, {1, 2, 2})));
+              Eq(MakeInstruction(spv::Op::OpTypeMatrix, {1, 2, 2})));
   EXPECT_THAT(CompiledInstructions("!0x00040018 !1 %b !123"),
-              Eq(MakeInstruction(SpvOpTypeMatrix, {1, 1, 123})));
+              Eq(MakeInstruction(spv::Op::OpTypeMatrix, {1, 1, 123})));
   EXPECT_THAT(CompiledInstructions("!0x00040018 !1 !2 !123"),
-              Eq(MakeInstruction(SpvOpTypeMatrix, {1, 2, 123})));
+              Eq(MakeInstruction(spv::Op::OpTypeMatrix, {1, 2, 123})));
 }
 
 TEST_F(ImmediateIntTest, AnyWordAfterEqualsAndOpCode) {
   EXPECT_THAT(CompiledInstructions("%a = OpArrayLength !2 %c 123"),
-              Eq(MakeInstruction(SpvOpArrayLength, {2, 1, 2, 123})));
+              Eq(MakeInstruction(spv::Op::OpArrayLength, {2, 1, 2, 123})));
   EXPECT_THAT(CompiledInstructions("%a = OpArrayLength %b !3 123"),
-              Eq(MakeInstruction(SpvOpArrayLength, {1, 2, 3, 123})));
+              Eq(MakeInstruction(spv::Op::OpArrayLength, {1, 2, 3, 123})));
   EXPECT_THAT(CompiledInstructions("%a = OpArrayLength %b %c !123"),
-              Eq(MakeInstruction(SpvOpArrayLength, {1, 2, 3, 123})));
+              Eq(MakeInstruction(spv::Op::OpArrayLength, {1, 2, 3, 123})));
   EXPECT_THAT(CompiledInstructions("%a = OpArrayLength %b !3 !123"),
-              Eq(MakeInstruction(SpvOpArrayLength, {1, 2, 3, 123})));
+              Eq(MakeInstruction(spv::Op::OpArrayLength, {1, 2, 3, 123})));
   EXPECT_THAT(CompiledInstructions("%a = OpArrayLength !2 !3 123"),
-              Eq(MakeInstruction(SpvOpArrayLength, {2, 1, 3, 123})));
+              Eq(MakeInstruction(spv::Op::OpArrayLength, {2, 1, 3, 123})));
   EXPECT_THAT(CompiledInstructions("%a = OpArrayLength !2 !3 !123"),
-              Eq(MakeInstruction(SpvOpArrayLength, {2, 1, 3, 123})));
+              Eq(MakeInstruction(spv::Op::OpArrayLength, {2, 1, 3, 123})));
 }
 
 TEST_F(ImmediateIntTest, ResultIdInAssignment) {
@@ -108,8 +108,8 @@
   // With !<integer>, we can (and can only) accept 32-bit number literals,
   // even when we declare the return type is 64-bit.
   EXPECT_EQ(Concatenate({
-                MakeInstruction(SpvOpTypeInt, {1, 64, 0}),
-                MakeInstruction(SpvOpConstant, {1, 2, 4294967295}),
+                MakeInstruction(spv::Op::OpTypeInt, {1, 64, 0}),
+                MakeInstruction(spv::Op::OpConstant, {1, 2, 4294967295}),
             }),
             CompiledInstructions("%i64 = OpTypeInt 64 0\n"
                                  "!0x0004002b %i64 !2 4294967295"));
@@ -151,9 +151,9 @@
       CompiledInstructions("%1 = OpTypeFloat 32\n!0x0004002b %1 %2 -0.5"));
 
   EXPECT_EQ(Concatenate({
-                MakeInstruction(SpvOpTypeInt, {1, 64, 0}),
-                MakeInstruction(SpvOpConstant, {1, 2, 0xb, 0xa}),
-                MakeInstruction(SpvOpSwitch,
+                MakeInstruction(spv::Op::OpTypeInt, {1, 64, 0}),
+                MakeInstruction(spv::Op::OpConstant, {1, 2, 0xb, 0xa}),
+                MakeInstruction(spv::Op::OpSwitch,
                                 {2, 1234, BitwiseCast<uint32_t>(2.5f), 3}),
             }),
             CompiledInstructions("%i64 = OpTypeInt 64 0\n"
@@ -174,7 +174,7 @@
               CompiledInstructions("OpMemberName !1 !4 \"" + name + "\""))
         << name;
     const uint16_t wordCount = static_cast<uint16_t>(4 + name.size() / 4);
-    const uint32_t firstWord = spvOpcodeMake(wordCount, SpvOpMemberName);
+    const uint32_t firstWord = spvOpcodeMake(wordCount, spv::Op::OpMemberName);
     EXPECT_EQ(original, CompiledInstructions("!" + std::to_string(firstWord) +
                                              " %10 !4 \"" + name + "\""))
         << name;
@@ -205,8 +205,8 @@
   EXPECT_THAT(Subvector(CompileSuccessfully(
                             "%10 = OpTypeFloat 32 !5 !6 !7 OpEmitVertex"),
                         kFirstInstruction),
-              ElementsAre(spvOpcodeMake(3, SpvOpTypeFloat), 1, 32, 5, 6, 7,
-                          spvOpcodeMake(1, SpvOpEmitVertex)));
+              ElementsAre(spvOpcodeMake(3, spv::Op::OpTypeFloat), 1, 32, 5, 6,
+                          7, spvOpcodeMake(1, spv::Op::OpEmitVertex)));
 }
 
 TEST_F(ImmediateIntTest, NextOpcodeRecognized) {
diff --git a/test/link/binary_version_test.cpp b/test/link/binary_version_test.cpp
index a56030f..78da1ae 100644
--- a/test/link/binary_version_test.cpp
+++ b/test/link/binary_version_test.cpp
@@ -27,20 +27,20 @@
   return {
       // clang-format off
       // Header
-      SpvMagicNumber,
+      static_cast<uint32_t>(spv::MagicNumber),
       version,
       SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS, 0),
       1u,  // NOTE: Bound
       0u,  // NOTE: Schema; reserved
 
       // OpCapability Shader
-      SpvOpCapability | 2u << SpvWordCountShift,
-      SpvCapabilityShader,
+      static_cast<uint32_t>(spv::Op::OpCapability) | 2u << spv::WordCountShift,
+      static_cast<uint32_t>(spv::Capability::Shader),
 
       // OpMemoryModel Logical Simple
-      SpvOpMemoryModel | 3u << SpvWordCountShift,
-      SpvAddressingModelLogical,
-      SpvMemoryModelSimple
+      static_cast<uint32_t>(spv::Op::OpMemoryModel) | 3u << spv::WordCountShift,
+      static_cast<uint32_t>(spv::AddressingModel::Logical),
+      static_cast<uint32_t>(spv::MemoryModel::Simple)
       // clang-format on
   };
 }
diff --git a/test/link/global_values_amount_test.cpp b/test/link/global_values_amount_test.cpp
index 3158b7e..fda55d6 100644
--- a/test/link/global_values_amount_test.cpp
+++ b/test/link/global_values_amount_test.cpp
@@ -34,26 +34,26 @@
 
     spvtest::Binary common_binary = {
         // clang-format off
-        SpvMagicNumber,
-        SpvVersion,
+        static_cast<uint32_t>(spv::MagicNumber),
+        static_cast<uint32_t>(spv::Version),
         SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS, 0),
         3u + global_variable_count_per_binary,  // NOTE: Bound
         0u,                                     // NOTE: Schema; reserved
 
-        SpvOpCapability | 2u << SpvWordCountShift,
-        SpvCapabilityShader,
+        static_cast<uint32_t>(spv::Op::OpCapability) | 2u << spv::WordCountShift,
+        static_cast<uint32_t>(spv::Capability::Shader),
 
-        SpvOpMemoryModel | 3u << SpvWordCountShift,
-        SpvAddressingModelLogical,
-        SpvMemoryModelSimple,
+        static_cast<uint32_t>(spv::Op::OpMemoryModel) | 3u << spv::WordCountShift,
+        static_cast<uint32_t>(spv::AddressingModel::Logical),
+        static_cast<uint32_t>(spv::MemoryModel::Simple),
 
-        SpvOpTypeFloat | 3u << SpvWordCountShift,
+        static_cast<uint32_t>(spv::Op::OpTypeFloat) | 3u << spv::WordCountShift,
         1u,   // NOTE: Result ID
         32u,  // NOTE: Width
 
-        SpvOpTypePointer | 4u << SpvWordCountShift,
+        static_cast<uint32_t>(spv::Op::OpTypePointer) | 4u << spv::WordCountShift,
         2u,  // NOTE: Result ID
-        SpvStorageClassInput,
+        static_cast<uint32_t>(spv::StorageClass::Input),
         1u  // NOTE: Type ID
         // clang-format on
     };
@@ -64,10 +64,11 @@
     binary.insert(binary.end(), common_binary.cbegin(), common_binary.cend());
 
     for (uint32_t i = 0u; i < global_variable_count_per_binary; ++i) {
-      binary.push_back(SpvOpVariable | 4u << SpvWordCountShift);
+      binary.push_back(static_cast<uint32_t>(spv::Op::OpVariable) |
+                       4u << spv::WordCountShift);
       binary.push_back(2u);      // NOTE: Type ID
       binary.push_back(3u + i);  // NOTE: Result ID
-      binary.push_back(SpvStorageClassInput);
+      binary.push_back(static_cast<uint32_t>(spv::StorageClass::Input));
     }
 
     for (uint32_t i = 0u; i < binary_count - 1u; ++i) {
@@ -89,37 +90,37 @@
 TEST_F(EntryPointsAmountTest, OverLimit) {
   binaries.push_back({
       // clang-format off
-      SpvMagicNumber,
-      SpvVersion,
+      static_cast<uint32_t>(spv::MagicNumber),
+      static_cast<uint32_t>(spv::Version),
       SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS, 0),
       5u,  // NOTE: Bound
       0u,  // NOTE: Schema; reserved
 
-      SpvOpCapability | 2u << SpvWordCountShift,
-      SpvCapabilityShader,
+      static_cast<uint32_t>(spv::Op::OpCapability) | 2u << spv::WordCountShift,
+      static_cast<uint32_t>(spv::Capability::Shader),
 
-      SpvOpMemoryModel | 3u << SpvWordCountShift,
-      SpvAddressingModelLogical,
-      SpvMemoryModelSimple,
+      static_cast<uint32_t>(spv::Op::OpMemoryModel) | 3u << spv::WordCountShift,
+      static_cast<uint32_t>(spv::AddressingModel::Logical),
+      static_cast<uint32_t>(spv::MemoryModel::Simple),
 
-      SpvOpTypeFloat | 3u << SpvWordCountShift,
+      static_cast<uint32_t>(spv::Op::OpTypeFloat) | 3u << spv::WordCountShift,
       1u,   // NOTE: Result ID
       32u,  // NOTE: Width
 
-      SpvOpTypePointer | 4u << SpvWordCountShift,
+      static_cast<uint32_t>(spv::Op::OpTypePointer) | 4u << spv::WordCountShift,
       2u,  // NOTE: Result ID
-      SpvStorageClassInput,
+      static_cast<uint32_t>(spv::StorageClass::Input),
       1u,  // NOTE: Type ID
 
-      SpvOpVariable | 4u << SpvWordCountShift,
+      static_cast<uint32_t>(spv::Op::OpVariable) | 4u << spv::WordCountShift,
       2u,  // NOTE: Type ID
       3u,  // NOTE: Result ID
-      SpvStorageClassInput,
+      static_cast<uint32_t>(spv::StorageClass::Input),
 
-      SpvOpVariable | 4u << SpvWordCountShift,
+      static_cast<uint32_t>(spv::Op::OpVariable) | 4u << spv::WordCountShift,
       2u,  // NOTE: Type ID
       4u,  // NOTE: Result ID
-      SpvStorageClassInput
+      static_cast<uint32_t>(spv::StorageClass::Input)
       // clang-format on
   });
 
diff --git a/test/link/ids_limit_test.cpp b/test/link/ids_limit_test.cpp
index 846fbef..8182e5d 100644
--- a/test/link/ids_limit_test.cpp
+++ b/test/link/ids_limit_test.cpp
@@ -36,20 +36,20 @@
     // running the RemoveDuplicates pass.
     spvtest::Binary common_binary = {
         // clang-format off
-        SpvMagicNumber,
-        SpvVersion,
+        spv::MagicNumber,
+        spv::Version,
         SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS, 0),
         id_bound,  // NOTE: Bound
         0u,        // NOTE: Schema; reserved
 
-        SpvOpCapability | 2u << SpvWordCountShift,
-        SpvCapabilityShader,
+        static_cast<uint32_t>(spv::Op::OpCapability) | 2u << spv::WordCountShift,
+        static_cast<uint32_t>(spv::Capability::Shader),
 
-        SpvOpMemoryModel | 3u << SpvWordCountShift,
-        SpvAddressingModelLogical,
-        SpvMemoryModelSimple,
+        static_cast<uint32_t>(spv::Op::OpMemoryModel) | 3u << spv::WordCountShift,
+        static_cast<uint32_t>(spv::AddressingModel::Logical),
+        static_cast<uint32_t>(spv::MemoryModel::Simple),
 
-        SpvOpTypeBool | 2u << SpvWordCountShift,
+        static_cast<uint32_t>(spv::Op::OpTypeBool) | 2u << spv::WordCountShift,
         1u    // NOTE: Result ID
         // clang-format on
     };
@@ -60,7 +60,8 @@
     binary.insert(binary.end(), common_binary.cbegin(), common_binary.cend());
 
     for (uint32_t i = 0u; i < constant_count; ++i) {
-      binary.push_back(SpvOpConstantTrue | 3u << SpvWordCountShift);
+      binary.push_back(static_cast<uint32_t>(spv::Op::OpConstantTrue) |
+                       3u << spv::WordCountShift);
       binary.push_back(1u);      // NOTE: Type ID
       binary.push_back(2u + i);  // NOTE: Result ID
     }
@@ -74,20 +75,20 @@
   return {
       // clang-format off
       // Header
-      SpvMagicNumber,
-      SpvVersion,
+      spv::MagicNumber,
+      spv::Version,
       SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS, 0),
       id_bound,  // NOTE: Bound
       0u,        // NOTE: Schema; reserved
 
       // OpCapability Shader
-      SpvOpCapability | 2u << SpvWordCountShift,
-      SpvCapabilityShader,
+      static_cast<uint32_t>(spv::Op::OpCapability) | 2u << spv::WordCountShift,
+      static_cast<uint32_t>(spv::Capability::Shader),
 
       // OpMemoryModel Logical Simple
-      SpvOpMemoryModel | 3u << SpvWordCountShift,
-      SpvAddressingModelLogical,
-      SpvMemoryModelSimple
+      static_cast<uint32_t>(spv::Op::OpMemoryModel) | 3u << spv::WordCountShift,
+      static_cast<uint32_t>(spv::AddressingModel::Logical),
+      static_cast<uint32_t>(spv::MemoryModel::Simple)
       // clang-format on
   };
 }
@@ -105,7 +106,8 @@
   const uint32_t id_bound = binary[3];
   binary[3] = id_bound + 1u;
 
-  binary.push_back(SpvOpConstantFalse | 3u << SpvWordCountShift);
+  binary.push_back(static_cast<uint32_t>(spv::Op::OpConstantFalse) |
+                   3u << spv::WordCountShift);
   binary.push_back(1u);        // NOTE: Type ID
   binary.push_back(id_bound);  // NOTE: Result ID
 
diff --git a/test/link/memory_model_test.cpp b/test/link/memory_model_test.cpp
index 280a776..ee63c59 100644
--- a/test/link/memory_model_test.cpp
+++ b/test/link/memory_model_test.cpp
@@ -35,8 +35,10 @@
   ASSERT_EQ(SPV_SUCCESS, AssembleAndLink({body1, body2}, &linked_binary));
   EXPECT_THAT(GetErrorMessage(), std::string());
 
-  EXPECT_EQ(SpvAddressingModelLogical, linked_binary[6]);
-  EXPECT_EQ(SpvMemoryModelSimple, linked_binary[7]);
+  EXPECT_EQ(spv::AddressingModel::Logical,
+            static_cast<spv::AddressingModel>(linked_binary[6]));
+  EXPECT_EQ(spv::MemoryModel::Simple,
+            static_cast<spv::MemoryModel>(linked_binary[7]));
 }
 
 TEST_F(MemoryModel, AddressingMismatch) {
diff --git a/test/opcode_make_test.cpp b/test/opcode_make_test.cpp
index 6481ef3..6c1dab6 100644
--- a/test/opcode_make_test.cpp
+++ b/test/opcode_make_test.cpp
@@ -35,7 +35,7 @@
       uint32_t word = 0;
       word |= uint32_t(opcode);
       word |= uint32_t(wordCount) << 16;
-      EXPECT_EQ(word, spvOpcodeMake(wordCount, SpvOp(opcode)));
+      EXPECT_EQ(word, spvOpcodeMake(wordCount, spv::Op(opcode)));
     }
   }
 }
diff --git a/test/opcode_require_capabilities_test.cpp b/test/opcode_require_capabilities_test.cpp
index 07e86f8..37097c6 100644
--- a/test/opcode_require_capabilities_test.cpp
+++ b/test/opcode_require_capabilities_test.cpp
@@ -23,7 +23,7 @@
 
 // Capabilities required by an Opcode.
 struct ExpectedOpCodeCapabilities {
-  SpvOp opcode;
+  spv::Op opcode;
   CapabilitySet capabilities;
 };
 
@@ -46,33 +46,36 @@
     TableRowTest, OpcodeTableCapabilitiesTest,
     // Spot-check a few opcodes.
     ::testing::Values(
+        ExpectedOpCodeCapabilities{spv::Op::OpImageQuerySize,
+                                   CapabilitySet{spv::Capability::Kernel,
+                                                 spv::Capability::ImageQuery}},
+        ExpectedOpCodeCapabilities{spv::Op::OpImageQuerySizeLod,
+                                   CapabilitySet{spv::Capability::Kernel,
+                                                 spv::Capability::ImageQuery}},
+        ExpectedOpCodeCapabilities{spv::Op::OpImageQueryLevels,
+                                   CapabilitySet{spv::Capability::Kernel,
+                                                 spv::Capability::ImageQuery}},
+        ExpectedOpCodeCapabilities{spv::Op::OpImageQuerySamples,
+                                   CapabilitySet{spv::Capability::Kernel,
+                                                 spv::Capability::ImageQuery}},
         ExpectedOpCodeCapabilities{
-            SpvOpImageQuerySize,
-            CapabilitySet{SpvCapabilityKernel, SpvCapabilityImageQuery}},
+            spv::Op::OpImageSparseSampleImplicitLod,
+            CapabilitySet{spv::Capability::SparseResidency}},
+        ExpectedOpCodeCapabilities{spv::Op::OpCopyMemorySized,
+                                   CapabilitySet{spv::Capability::Addresses}},
+        ExpectedOpCodeCapabilities{spv::Op::OpArrayLength,
+                                   CapabilitySet{spv::Capability::Shader}},
+        ExpectedOpCodeCapabilities{spv::Op::OpFunction, CapabilitySet()},
+        ExpectedOpCodeCapabilities{spv::Op::OpConvertFToS, CapabilitySet()},
         ExpectedOpCodeCapabilities{
-            SpvOpImageQuerySizeLod,
-            CapabilitySet{SpvCapabilityKernel, SpvCapabilityImageQuery}},
+            spv::Op::OpEmitStreamVertex,
+            CapabilitySet{spv::Capability::GeometryStreams}},
         ExpectedOpCodeCapabilities{
-            SpvOpImageQueryLevels,
-            CapabilitySet{SpvCapabilityKernel, SpvCapabilityImageQuery}},
+            spv::Op::OpTypeNamedBarrier,
+            CapabilitySet{spv::Capability::NamedBarrier}},
         ExpectedOpCodeCapabilities{
-            SpvOpImageQuerySamples,
-            CapabilitySet{SpvCapabilityKernel, SpvCapabilityImageQuery}},
-        ExpectedOpCodeCapabilities{SpvOpImageSparseSampleImplicitLod,
-                                   CapabilitySet{SpvCapabilitySparseResidency}},
-        ExpectedOpCodeCapabilities{SpvOpCopyMemorySized,
-                                   CapabilitySet{SpvCapabilityAddresses}},
-        ExpectedOpCodeCapabilities{SpvOpArrayLength,
-                                   CapabilitySet{SpvCapabilityShader}},
-        ExpectedOpCodeCapabilities{SpvOpFunction, CapabilitySet()},
-        ExpectedOpCodeCapabilities{SpvOpConvertFToS, CapabilitySet()},
-        ExpectedOpCodeCapabilities{SpvOpEmitStreamVertex,
-                                   CapabilitySet{SpvCapabilityGeometryStreams}},
-        ExpectedOpCodeCapabilities{SpvOpTypeNamedBarrier,
-                                   CapabilitySet{SpvCapabilityNamedBarrier}},
-        ExpectedOpCodeCapabilities{
-            SpvOpGetKernelMaxNumSubgroups,
-            CapabilitySet{SpvCapabilitySubgroupDispatch}}));
+            spv::Op::OpGetKernelMaxNumSubgroups,
+            CapabilitySet{spv::Capability::SubgroupDispatch}}));
 
 }  // namespace
 }  // namespace spvtools
diff --git a/test/opcode_split_test.cpp b/test/opcode_split_test.cpp
index 43fedb3..e8a67b6 100644
--- a/test/opcode_split_test.cpp
+++ b/test/opcode_split_test.cpp
@@ -18,7 +18,7 @@
 namespace {
 
 TEST(OpcodeSplit, Default) {
-  uint32_t word = spvOpcodeMake(42, (SpvOp)23);
+  uint32_t word = spvOpcodeMake(42, (spv::Op)23);
   uint16_t wordCount = 0;
   uint16_t opcode;
   spvOpcodeSplit(word, &wordCount, &opcode);
diff --git a/test/operand_capabilities_test.cpp b/test/operand_capabilities_test.cpp
index 6050346..10ed82a 100644
--- a/test/operand_capabilities_test.cpp
+++ b/test/operand_capabilities_test.cpp
@@ -62,47 +62,47 @@
 
 #define CASE0(TYPE, VALUE)                            \
   {                                                   \
-    SPV_OPERAND_TYPE_##TYPE, uint32_t(Spv##VALUE), {} \
+    SPV_OPERAND_TYPE_##TYPE, uint32_t(spv::VALUE), {} \
   }
 #define CASE1(TYPE, VALUE, CAP)                                    \
   {                                                                \
-    SPV_OPERAND_TYPE_##TYPE, uint32_t(Spv##VALUE), CapabilitySet { \
-      SpvCapability##CAP                                           \
+    SPV_OPERAND_TYPE_##TYPE, uint32_t(spv::VALUE), CapabilitySet { \
+      spv::Capability::CAP                                         \
     }                                                              \
   }
 #define CASE2(TYPE, VALUE, CAP1, CAP2)                             \
   {                                                                \
-    SPV_OPERAND_TYPE_##TYPE, uint32_t(Spv##VALUE), CapabilitySet { \
-      SpvCapability##CAP1, SpvCapability##CAP2                     \
+    SPV_OPERAND_TYPE_##TYPE, uint32_t(spv::VALUE), CapabilitySet { \
+      spv::Capability::CAP1, spv::Capability::CAP2                 \
     }                                                              \
   }
-#define CASE3(TYPE, VALUE, CAP1, CAP2, CAP3)                        \
-  {                                                                 \
-    SPV_OPERAND_TYPE_##TYPE, uint32_t(Spv##VALUE), CapabilitySet {  \
-      SpvCapability##CAP1, SpvCapability##CAP2, SpvCapability##CAP3 \
-    }                                                               \
+#define CASE3(TYPE, VALUE, CAP1, CAP2, CAP3)                              \
+  {                                                                       \
+    SPV_OPERAND_TYPE_##TYPE, uint32_t(spv::VALUE), CapabilitySet {        \
+      spv::Capability::CAP1, spv::Capability::CAP2, spv::Capability::CAP3 \
+    }                                                                     \
   }
-#define CASE4(TYPE, VALUE, CAP1, CAP2, CAP3, CAP4)                   \
-  {                                                                  \
-    SPV_OPERAND_TYPE_##TYPE, uint32_t(Spv##VALUE), CapabilitySet {   \
-      SpvCapability##CAP1, SpvCapability##CAP2, SpvCapability##CAP3, \
-          SpvCapability##CAP4                                        \
-    }                                                                \
+#define CASE4(TYPE, VALUE, CAP1, CAP2, CAP3, CAP4)                         \
+  {                                                                        \
+    SPV_OPERAND_TYPE_##TYPE, uint32_t(spv::VALUE), CapabilitySet {         \
+      spv::Capability::CAP1, spv::Capability::CAP2, spv::Capability::CAP3, \
+          spv::Capability::CAP4                                            \
+    }                                                                      \
   }
-#define CASE5(TYPE, VALUE, CAP1, CAP2, CAP3, CAP4, CAP5)             \
-  {                                                                  \
-    SPV_OPERAND_TYPE_##TYPE, uint32_t(Spv##VALUE), CapabilitySet {   \
-      SpvCapability##CAP1, SpvCapability##CAP2, SpvCapability##CAP3, \
-          SpvCapability##CAP4, SpvCapability##CAP5                   \
-    }                                                                \
+#define CASE5(TYPE, VALUE, CAP1, CAP2, CAP3, CAP4, CAP5)                   \
+  {                                                                        \
+    SPV_OPERAND_TYPE_##TYPE, uint32_t(spv::VALUE), CapabilitySet {         \
+      spv::Capability::CAP1, spv::Capability::CAP2, spv::Capability::CAP3, \
+          spv::Capability::CAP4, spv::Capability::CAP5                     \
+    }                                                                      \
   }
 
-#define CASE6(TYPE, VALUE, CAP1, CAP2, CAP3, CAP4, CAP5, CAP6)          \
-  {                                                                     \
-    SPV_OPERAND_TYPE_##TYPE, uint32_t(Spv##VALUE), CapabilitySet {      \
-      SpvCapability##CAP1, SpvCapability##CAP2, SpvCapability##CAP3,    \
-          SpvCapability##CAP4, SpvCapability##CAP5, SpvCapability##CAP6 \
-    }                                                                   \
+#define CASE6(TYPE, VALUE, CAP1, CAP2, CAP3, CAP4, CAP5, CAP6)                \
+  {                                                                           \
+    SPV_OPERAND_TYPE_##TYPE, uint32_t(spv::VALUE), CapabilitySet {            \
+      spv::Capability::CAP1, spv::Capability::CAP2, spv::Capability::CAP3,    \
+          spv::Capability::CAP4, spv::Capability::CAP5, spv::Capability::CAP6 \
+    }                                                                         \
   }
 
 // See SPIR-V Section 3.3 Execution Model
@@ -110,15 +110,15 @@
     ExecutionModel, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE1(EXECUTION_MODEL, ExecutionModelVertex, Shader),
-                CASE1(EXECUTION_MODEL, ExecutionModelTessellationControl,
+                CASE1(EXECUTION_MODEL, ExecutionModel::Vertex, Shader),
+                CASE1(EXECUTION_MODEL, ExecutionModel::TessellationControl,
                       Tessellation),
-                CASE1(EXECUTION_MODEL, ExecutionModelTessellationEvaluation,
+                CASE1(EXECUTION_MODEL, ExecutionModel::TessellationEvaluation,
                       Tessellation),
-                CASE1(EXECUTION_MODEL, ExecutionModelGeometry, Geometry),
-                CASE1(EXECUTION_MODEL, ExecutionModelFragment, Shader),
-                CASE1(EXECUTION_MODEL, ExecutionModelGLCompute, Shader),
-                CASE1(EXECUTION_MODEL, ExecutionModelKernel, Kernel),
+                CASE1(EXECUTION_MODEL, ExecutionModel::Geometry, Geometry),
+                CASE1(EXECUTION_MODEL, ExecutionModel::Fragment, Shader),
+                CASE1(EXECUTION_MODEL, ExecutionModel::GLCompute, Shader),
+                CASE1(EXECUTION_MODEL, ExecutionModel::Kernel, Kernel),
             })));
 
 // See SPIR-V Section 3.4 Addressing Model
@@ -126,9 +126,9 @@
     AddressingModel, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE0(ADDRESSING_MODEL, AddressingModelLogical),
-                CASE1(ADDRESSING_MODEL, AddressingModelPhysical32, Addresses),
-                CASE1(ADDRESSING_MODEL, AddressingModelPhysical64, Addresses),
+                CASE0(ADDRESSING_MODEL, AddressingModel::Logical),
+                CASE1(ADDRESSING_MODEL, AddressingModel::Physical32, Addresses),
+                CASE1(ADDRESSING_MODEL, AddressingModel::Physical64, Addresses),
             })));
 
 // See SPIR-V Section 3.5 Memory Model
@@ -136,9 +136,9 @@
     MemoryModel, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE1(MEMORY_MODEL, MemoryModelSimple, Shader),
-                CASE1(MEMORY_MODEL, MemoryModelGLSL450, Shader),
-                CASE1(MEMORY_MODEL, MemoryModelOpenCL, Kernel),
+                CASE1(MEMORY_MODEL, MemoryModel::Simple, Shader),
+                CASE1(MEMORY_MODEL, MemoryModel::GLSL450, Shader),
+                CASE1(MEMORY_MODEL, MemoryModel::OpenCL, Kernel),
             })));
 
 // See SPIR-V Section 3.6 Execution Mode
@@ -147,54 +147,54 @@
     Combine(
         Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
         ValuesIn(std::vector<EnumCapabilityCase>{
-            CASE1(EXECUTION_MODE, ExecutionModeInvocations, Geometry),
-            CASE1(EXECUTION_MODE, ExecutionModeSpacingEqual, Tessellation),
-            CASE1(EXECUTION_MODE, ExecutionModeSpacingFractionalEven,
+            CASE1(EXECUTION_MODE, ExecutionMode::Invocations, Geometry),
+            CASE1(EXECUTION_MODE, ExecutionMode::SpacingEqual, Tessellation),
+            CASE1(EXECUTION_MODE, ExecutionMode::SpacingFractionalEven,
                   Tessellation),
-            CASE1(EXECUTION_MODE, ExecutionModeSpacingFractionalOdd,
+            CASE1(EXECUTION_MODE, ExecutionMode::SpacingFractionalOdd,
                   Tessellation),
-            CASE1(EXECUTION_MODE, ExecutionModeVertexOrderCw, Tessellation),
-            CASE1(EXECUTION_MODE, ExecutionModeVertexOrderCcw, Tessellation),
-            CASE1(EXECUTION_MODE, ExecutionModePixelCenterInteger, Shader),
-            CASE1(EXECUTION_MODE, ExecutionModeOriginUpperLeft, Shader),
-            CASE1(EXECUTION_MODE, ExecutionModeOriginLowerLeft, Shader),
-            CASE1(EXECUTION_MODE, ExecutionModeEarlyFragmentTests, Shader),
-            CASE1(EXECUTION_MODE, ExecutionModePointMode, Tessellation),
-            CASE1(EXECUTION_MODE, ExecutionModeXfb, TransformFeedback),
-            CASE1(EXECUTION_MODE, ExecutionModeDepthReplacing, Shader),
-            CASE1(EXECUTION_MODE, ExecutionModeDepthGreater, Shader),
-            CASE1(EXECUTION_MODE, ExecutionModeDepthLess, Shader),
-            CASE1(EXECUTION_MODE, ExecutionModeDepthUnchanged, Shader),
-            CASE0(EXECUTION_MODE, ExecutionModeLocalSize),
-            CASE1(EXECUTION_MODE, ExecutionModeLocalSizeHint, Kernel),
-            CASE1(EXECUTION_MODE, ExecutionModeInputPoints, Geometry),
-            CASE1(EXECUTION_MODE, ExecutionModeInputLines, Geometry),
-            CASE1(EXECUTION_MODE, ExecutionModeInputLinesAdjacency, Geometry),
-            CASE2(EXECUTION_MODE, ExecutionModeTriangles, Geometry,
+            CASE1(EXECUTION_MODE, ExecutionMode::VertexOrderCw, Tessellation),
+            CASE1(EXECUTION_MODE, ExecutionMode::VertexOrderCcw, Tessellation),
+            CASE1(EXECUTION_MODE, ExecutionMode::PixelCenterInteger, Shader),
+            CASE1(EXECUTION_MODE, ExecutionMode::OriginUpperLeft, Shader),
+            CASE1(EXECUTION_MODE, ExecutionMode::OriginLowerLeft, Shader),
+            CASE1(EXECUTION_MODE, ExecutionMode::EarlyFragmentTests, Shader),
+            CASE1(EXECUTION_MODE, ExecutionMode::PointMode, Tessellation),
+            CASE1(EXECUTION_MODE, ExecutionMode::Xfb, TransformFeedback),
+            CASE1(EXECUTION_MODE, ExecutionMode::DepthReplacing, Shader),
+            CASE1(EXECUTION_MODE, ExecutionMode::DepthGreater, Shader),
+            CASE1(EXECUTION_MODE, ExecutionMode::DepthLess, Shader),
+            CASE1(EXECUTION_MODE, ExecutionMode::DepthUnchanged, Shader),
+            CASE0(EXECUTION_MODE, ExecutionMode::LocalSize),
+            CASE1(EXECUTION_MODE, ExecutionMode::LocalSizeHint, Kernel),
+            CASE1(EXECUTION_MODE, ExecutionMode::InputPoints, Geometry),
+            CASE1(EXECUTION_MODE, ExecutionMode::InputLines, Geometry),
+            CASE1(EXECUTION_MODE, ExecutionMode::InputLinesAdjacency, Geometry),
+            CASE2(EXECUTION_MODE, ExecutionMode::Triangles, Geometry,
                   Tessellation),
-            CASE1(EXECUTION_MODE, ExecutionModeInputTrianglesAdjacency,
+            CASE1(EXECUTION_MODE, ExecutionMode::InputTrianglesAdjacency,
                   Geometry),
-            CASE1(EXECUTION_MODE, ExecutionModeQuads, Tessellation),
-            CASE1(EXECUTION_MODE, ExecutionModeIsolines, Tessellation),
-            CASE4(EXECUTION_MODE, ExecutionModeOutputVertices, Geometry,
+            CASE1(EXECUTION_MODE, ExecutionMode::Quads, Tessellation),
+            CASE1(EXECUTION_MODE, ExecutionMode::Isolines, Tessellation),
+            CASE4(EXECUTION_MODE, ExecutionMode::OutputVertices, Geometry,
                   Tessellation, MeshShadingNV, MeshShadingEXT),
-            CASE3(EXECUTION_MODE, ExecutionModeOutputPoints, Geometry,
+            CASE3(EXECUTION_MODE, ExecutionMode::OutputPoints, Geometry,
                   MeshShadingNV, MeshShadingEXT),
-            CASE1(EXECUTION_MODE, ExecutionModeOutputLineStrip, Geometry),
-            CASE1(EXECUTION_MODE, ExecutionModeOutputTriangleStrip, Geometry),
-            CASE1(EXECUTION_MODE, ExecutionModeVecTypeHint, Kernel),
-            CASE1(EXECUTION_MODE, ExecutionModeContractionOff, Kernel),
+            CASE1(EXECUTION_MODE, ExecutionMode::OutputLineStrip, Geometry),
+            CASE1(EXECUTION_MODE, ExecutionMode::OutputTriangleStrip, Geometry),
+            CASE1(EXECUTION_MODE, ExecutionMode::VecTypeHint, Kernel),
+            CASE1(EXECUTION_MODE, ExecutionMode::ContractionOff, Kernel),
         })));
 
 INSTANTIATE_TEST_SUITE_P(
     ExecutionModeV11, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE1(EXECUTION_MODE, ExecutionModeInitializer, Kernel),
-                CASE1(EXECUTION_MODE, ExecutionModeFinalizer, Kernel),
-                CASE1(EXECUTION_MODE, ExecutionModeSubgroupSize,
+                CASE1(EXECUTION_MODE, ExecutionMode::Initializer, Kernel),
+                CASE1(EXECUTION_MODE, ExecutionMode::Finalizer, Kernel),
+                CASE1(EXECUTION_MODE, ExecutionMode::SubgroupSize,
                       SubgroupDispatch),
-                CASE1(EXECUTION_MODE, ExecutionModeSubgroupsPerWorkgroup,
+                CASE1(EXECUTION_MODE, ExecutionMode::SubgroupsPerWorkgroup,
                       SubgroupDispatch)})));
 
 // See SPIR-V Section 3.7 Storage Class
@@ -202,19 +202,20 @@
     StorageClass, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE0(STORAGE_CLASS, StorageClassUniformConstant),
-                CASE1(STORAGE_CLASS, StorageClassUniform, Shader),
-                CASE1(STORAGE_CLASS, StorageClassOutput, Shader),
-                CASE0(STORAGE_CLASS, StorageClassWorkgroup),
-                CASE0(STORAGE_CLASS, StorageClassCrossWorkgroup),
-                CASE2(STORAGE_CLASS, StorageClassPrivate, Shader,
+                CASE0(STORAGE_CLASS, StorageClass::UniformConstant),
+                CASE1(STORAGE_CLASS, StorageClass::Uniform, Shader),
+                CASE1(STORAGE_CLASS, StorageClass::Output, Shader),
+                CASE0(STORAGE_CLASS, StorageClass::Workgroup),
+                CASE0(STORAGE_CLASS, StorageClass::CrossWorkgroup),
+                CASE2(STORAGE_CLASS, StorageClass::Private, Shader,
                       VectorComputeINTEL),
-                CASE0(STORAGE_CLASS, StorageClassFunction),
-                CASE1(STORAGE_CLASS, StorageClassGeneric,
+                CASE0(STORAGE_CLASS, StorageClass::Function),
+                CASE1(STORAGE_CLASS, StorageClass::Generic,
                       GenericPointer),  // Bug 14287
-                CASE1(STORAGE_CLASS, StorageClassPushConstant, Shader),
-                CASE1(STORAGE_CLASS, StorageClassAtomicCounter, AtomicStorage),
-                CASE0(STORAGE_CLASS, StorageClassImage),
+                CASE1(STORAGE_CLASS, StorageClass::PushConstant, Shader),
+                CASE1(STORAGE_CLASS, StorageClass::AtomicCounter,
+                      AtomicStorage),
+                CASE0(STORAGE_CLASS, StorageClass::Image),
             })));
 
 // See SPIR-V Section 3.8 Dim
@@ -222,37 +223,39 @@
     Dim, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE2(DIMENSIONALITY, Dim1D, Sampled1D, Image1D),
-                CASE3(DIMENSIONALITY, Dim2D, Kernel, Shader, ImageMSArray),
-                CASE0(DIMENSIONALITY, Dim3D),
-                CASE2(DIMENSIONALITY, DimCube, Shader, ImageCubeArray),
-                CASE2(DIMENSIONALITY, DimRect, SampledRect, ImageRect),
-                CASE2(DIMENSIONALITY, DimBuffer, SampledBuffer, ImageBuffer),
-                CASE1(DIMENSIONALITY, DimSubpassData, InputAttachment),
+                CASE2(DIMENSIONALITY, Dim::Dim1D, Sampled1D, Image1D),
+                CASE3(DIMENSIONALITY, Dim::Dim2D, Kernel, Shader, ImageMSArray),
+                CASE0(DIMENSIONALITY, Dim::Dim3D),
+                CASE2(DIMENSIONALITY, Dim::Cube, Shader, ImageCubeArray),
+                CASE2(DIMENSIONALITY, Dim::Rect, SampledRect, ImageRect),
+                CASE2(DIMENSIONALITY, Dim::Buffer, SampledBuffer, ImageBuffer),
+                CASE1(DIMENSIONALITY, Dim::SubpassData, InputAttachment),
             })));
 
 // See SPIR-V Section 3.9 Sampler Addressing Mode
 INSTANTIATE_TEST_SUITE_P(
     SamplerAddressingMode, EnumCapabilityTest,
-    Combine(
-        Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
-        ValuesIn(std::vector<EnumCapabilityCase>{
-            CASE1(SAMPLER_ADDRESSING_MODE, SamplerAddressingModeNone, Kernel),
-            CASE1(SAMPLER_ADDRESSING_MODE, SamplerAddressingModeClampToEdge,
-                  Kernel),
-            CASE1(SAMPLER_ADDRESSING_MODE, SamplerAddressingModeClamp, Kernel),
-            CASE1(SAMPLER_ADDRESSING_MODE, SamplerAddressingModeRepeat, Kernel),
-            CASE1(SAMPLER_ADDRESSING_MODE, SamplerAddressingModeRepeatMirrored,
-                  Kernel),
-        })));
+    Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
+            ValuesIn(std::vector<EnumCapabilityCase>{
+                CASE1(SAMPLER_ADDRESSING_MODE, SamplerAddressingMode::None,
+                      Kernel),
+                CASE1(SAMPLER_ADDRESSING_MODE,
+                      SamplerAddressingMode::ClampToEdge, Kernel),
+                CASE1(SAMPLER_ADDRESSING_MODE, SamplerAddressingMode::Clamp,
+                      Kernel),
+                CASE1(SAMPLER_ADDRESSING_MODE, SamplerAddressingMode::Repeat,
+                      Kernel),
+                CASE1(SAMPLER_ADDRESSING_MODE,
+                      SamplerAddressingMode::RepeatMirrored, Kernel),
+            })));
 
 // See SPIR-V Section 3.10 Sampler Filter Mode
 INSTANTIATE_TEST_SUITE_P(
     SamplerFilterMode, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE1(SAMPLER_FILTER_MODE, SamplerFilterModeNearest, Kernel),
-                CASE1(SAMPLER_FILTER_MODE, SamplerFilterModeLinear, Kernel),
+                CASE1(SAMPLER_FILTER_MODE, SamplerFilterMode::Nearest, Kernel),
+                CASE1(SAMPLER_FILTER_MODE, SamplerFilterMode::Linear, Kernel),
             })));
 
 // See SPIR-V Section 3.11 Image Format
@@ -261,76 +264,76 @@
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
                 // clang-format off
-        CASE0(SAMPLER_IMAGE_FORMAT, ImageFormatUnknown),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba32f, Shader),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba16f, Shader),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR32f, Shader),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba8, Shader),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba8Snorm, Shader),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg32f, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg16f, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR11fG11fB10f, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR16f, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba16, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgb10A2, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg16, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg8, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR16, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR8, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba16Snorm, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg16Snorm, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg8Snorm, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR16Snorm, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR8Snorm, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba32i, Shader),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba16i, Shader),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba8i, Shader),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR32i, Shader),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg32i, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg16i, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg8i, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR16i, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR8i, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba32ui, Shader),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba16ui, Shader),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba8ui, Shader),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgba8ui, Shader),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRgb10a2ui, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg32ui, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg16ui, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatRg8ui, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR16ui, StorageImageExtendedFormats),
-        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormatR8ui, StorageImageExtendedFormats),
+        CASE0(SAMPLER_IMAGE_FORMAT, ImageFormat::Unknown),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rgba32f, Shader),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rgba16f, Shader),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::R32f, Shader),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rgba8, Shader),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rgba8Snorm, Shader),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rg32f, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rg16f, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::R11fG11fB10f, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::R16f, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rgba16, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rgb10A2, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rg16, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rg8, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::R16, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::R8, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rgba16Snorm, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rg16Snorm, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rg8Snorm, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::R16Snorm, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::R8Snorm, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rgba32i, Shader),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rgba16i, Shader),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rgba8i, Shader),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::R32i, Shader),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rg32i, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rg16i, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rg8i, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::R16i, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::R8i, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rgba32ui, Shader),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rgba16ui, Shader),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rgba8ui, Shader),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rgba8ui, Shader),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rgb10a2ui, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rg32ui, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rg16ui, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::Rg8ui, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::R16ui, StorageImageExtendedFormats),
+        CASE1(SAMPLER_IMAGE_FORMAT, ImageFormat::R8ui, StorageImageExtendedFormats),
                 // clang-format on
             })));
 
 // See SPIR-V Section 3.12 Image Channel Order
 INSTANTIATE_TEST_SUITE_P(
     ImageChannelOrder, EnumCapabilityTest,
-    Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
-            ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderR, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderA, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderRG, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderRA, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderRGB, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderRGBA, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderBGRA, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderARGB, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderIntensity, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderLuminance, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderRx, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderRGx, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderRGBx, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderDepth, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderDepthStencil,
-                      Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrdersRGB, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrdersRGBx, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrdersRGBA, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrdersBGRA, Kernel),
-                CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderABGR, Kernel),
-            })));
+    Combine(
+        Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
+        ValuesIn(std::vector<EnumCapabilityCase>{
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::R, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::A, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::RG, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::RA, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::RGB, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::RGBA, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::BGRA, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::ARGB, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::Intensity, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::Luminance, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::Rx, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::RGx, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::RGBx, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::Depth, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::DepthStencil, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::sRGB, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::sRGBx, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::sRGBA, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::sBGRA, Kernel),
+            CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrder::ABGR, Kernel),
+        })));
 
 // See SPIR-V Section 3.13 Image Channel Data Type
 INSTANTIATE_TEST_SUITE_P(
@@ -338,23 +341,23 @@
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
                 // clang-format off
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeSnormInt8, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeSnormInt16, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeUnormInt8, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeUnormInt16, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeUnormShort565, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeUnormShort555, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeUnormInt101010, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeSignedInt8, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeSignedInt16, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeSignedInt32, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeUnsignedInt8, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeUnsignedInt16, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeUnsignedInt32, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeHalfFloat, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeFloat, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeUnormInt24, Kernel),
-                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataTypeUnormInt101010_2, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::SnormInt8, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::SnormInt16, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::UnormInt8, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::UnormInt16, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::UnormShort565, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::UnormShort555, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::UnormInt101010, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::SignedInt8, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::SignedInt16, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::SignedInt32, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::UnsignedInt8, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::UnsignedInt16, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::UnsignedInt32, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::HalfFloat, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::Float, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::UnormInt24, Kernel),
+                CASE1(IMAGE_CHANNEL_DATA_TYPE, ImageChannelDataType::UnormInt101010_2, Kernel),
                 // clang-format on
             })));
 
@@ -364,15 +367,15 @@
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
                 // clang-format off
-                CASE0(OPTIONAL_IMAGE, ImageOperandsMaskNone),
-                CASE1(OPTIONAL_IMAGE, ImageOperandsBiasMask, Shader),
-                CASE0(OPTIONAL_IMAGE, ImageOperandsLodMask),
-                CASE0(OPTIONAL_IMAGE, ImageOperandsGradMask),
-                CASE0(OPTIONAL_IMAGE, ImageOperandsConstOffsetMask),
-                CASE1(OPTIONAL_IMAGE, ImageOperandsOffsetMask, ImageGatherExtended),
-                CASE1(OPTIONAL_IMAGE, ImageOperandsConstOffsetsMask, ImageGatherExtended),
-                CASE0(OPTIONAL_IMAGE, ImageOperandsSampleMask),
-                CASE1(OPTIONAL_IMAGE, ImageOperandsMinLodMask, MinLod),
+                CASE0(OPTIONAL_IMAGE, ImageOperandsMask::MaskNone),
+                CASE1(OPTIONAL_IMAGE, ImageOperandsMask::Bias, Shader),
+                CASE0(OPTIONAL_IMAGE, ImageOperandsMask::Lod),
+                CASE0(OPTIONAL_IMAGE, ImageOperandsMask::Grad),
+                CASE0(OPTIONAL_IMAGE, ImageOperandsMask::ConstOffset),
+                CASE1(OPTIONAL_IMAGE, ImageOperandsMask::Offset, ImageGatherExtended),
+                CASE1(OPTIONAL_IMAGE, ImageOperandsMask::ConstOffsets, ImageGatherExtended),
+                CASE0(OPTIONAL_IMAGE, ImageOperandsMask::Sample),
+                CASE1(OPTIONAL_IMAGE, ImageOperandsMask::MinLod, MinLod),
                 // clang-format on
             })));
 
@@ -381,8 +384,8 @@
     LinkageType, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE1(LINKAGE_TYPE, LinkageTypeExport, Linkage),
-                CASE1(LINKAGE_TYPE, LinkageTypeImport, Linkage),
+                CASE1(LINKAGE_TYPE, LinkageType::Export, Linkage),
+                CASE1(LINKAGE_TYPE, LinkageType::Import, Linkage),
             })));
 
 // See SPIR-V Section 3.18 Access Qualifier
@@ -390,9 +393,9 @@
     AccessQualifier, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE1(ACCESS_QUALIFIER, AccessQualifierReadOnly, Kernel),
-                CASE1(ACCESS_QUALIFIER, AccessQualifierWriteOnly, Kernel),
-                CASE1(ACCESS_QUALIFIER, AccessQualifierReadWrite, Kernel),
+                CASE1(ACCESS_QUALIFIER, AccessQualifier::ReadOnly, Kernel),
+                CASE1(ACCESS_QUALIFIER, AccessQualifier::WriteOnly, Kernel),
+                CASE1(ACCESS_QUALIFIER, AccessQualifier::ReadWrite, Kernel),
             })));
 
 // See SPIR-V Section 3.19 Function Parameter Attribute
@@ -401,14 +404,14 @@
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
                 // clang-format off
-                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttributeZext, Kernel),
-                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttributeSext, Kernel),
-                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttributeByVal, Kernel),
-                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttributeSret, Kernel),
-                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttributeNoAlias, Kernel),
-                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttributeNoCapture, Kernel),
-                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttributeNoWrite, Kernel),
-                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttributeNoReadWrite, Kernel),
+                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttribute::Zext, Kernel),
+                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttribute::Sext, Kernel),
+                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttribute::ByVal, Kernel),
+                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttribute::Sret, Kernel),
+                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttribute::NoAlias, Kernel),
+                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttribute::NoCapture, Kernel),
+                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttribute::NoWrite, Kernel),
+                CASE1(FUNCTION_PARAMETER_ATTRIBUTE, FunctionParameterAttribute::NoReadWrite, Kernel),
                 // clang-format on
             })));
 
@@ -417,52 +420,53 @@
     Decoration, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE1(DECORATION, DecorationRelaxedPrecision, Shader),
+                CASE1(DECORATION, Decoration::RelaxedPrecision, Shader),
                 // DecorationSpecId handled below.
-                CASE1(DECORATION, DecorationBlock, Shader),
-                CASE1(DECORATION, DecorationBufferBlock, Shader),
-                CASE1(DECORATION, DecorationRowMajor, Matrix),
-                CASE1(DECORATION, DecorationColMajor, Matrix),
-                CASE1(DECORATION, DecorationArrayStride, Shader),
-                CASE1(DECORATION, DecorationMatrixStride, Matrix),  // Bug 15234
-                CASE1(DECORATION, DecorationGLSLShared, Shader),
-                CASE1(DECORATION, DecorationGLSLPacked, Shader),
-                CASE1(DECORATION, DecorationCPacked, Kernel),
-                CASE0(DECORATION, DecorationBuiltIn),  // Bug 15248
+                CASE1(DECORATION, Decoration::Block, Shader),
+                CASE1(DECORATION, Decoration::BufferBlock, Shader),
+                CASE1(DECORATION, Decoration::RowMajor, Matrix),
+                CASE1(DECORATION, Decoration::ColMajor, Matrix),
+                CASE1(DECORATION, Decoration::ArrayStride, Shader),
+                CASE1(DECORATION, Decoration::MatrixStride,
+                      Matrix),  // Bug 15234
+                CASE1(DECORATION, Decoration::GLSLShared, Shader),
+                CASE1(DECORATION, Decoration::GLSLPacked, Shader),
+                CASE1(DECORATION, Decoration::CPacked, Kernel),
+                CASE0(DECORATION, Decoration::BuiltIn),  // Bug 15248
                 // Value 12 placeholder
-                CASE1(DECORATION, DecorationNoPerspective, Shader),
-                CASE1(DECORATION, DecorationFlat, Shader),
-                CASE1(DECORATION, DecorationPatch, Tessellation),
-                CASE1(DECORATION, DecorationCentroid, Shader),
-                CASE1(DECORATION, DecorationSample,
+                CASE1(DECORATION, Decoration::NoPerspective, Shader),
+                CASE1(DECORATION, Decoration::Flat, Shader),
+                CASE1(DECORATION, Decoration::Patch, Tessellation),
+                CASE1(DECORATION, Decoration::Centroid, Shader),
+                CASE1(DECORATION, Decoration::Sample,
                       SampleRateShading),  // Bug 15234
-                CASE1(DECORATION, DecorationInvariant, Shader),
-                CASE0(DECORATION, DecorationRestrict),
-                CASE0(DECORATION, DecorationAliased),
-                CASE0(DECORATION, DecorationVolatile),
-                CASE1(DECORATION, DecorationConstant, Kernel),
-                CASE0(DECORATION, DecorationCoherent),
-                CASE0(DECORATION, DecorationNonWritable),
-                CASE0(DECORATION, DecorationNonReadable),
-                CASE1(DECORATION, DecorationUniform, Shader),
+                CASE1(DECORATION, Decoration::Invariant, Shader),
+                CASE0(DECORATION, Decoration::Restrict),
+                CASE0(DECORATION, Decoration::Aliased),
+                CASE0(DECORATION, Decoration::Volatile),
+                CASE1(DECORATION, Decoration::Constant, Kernel),
+                CASE0(DECORATION, Decoration::Coherent),
+                CASE0(DECORATION, Decoration::NonWritable),
+                CASE0(DECORATION, Decoration::NonReadable),
+                CASE1(DECORATION, Decoration::Uniform, Shader),
                 // Value 27 is an intentional gap in the spec numbering.
-                CASE1(DECORATION, DecorationSaturatedConversion, Kernel),
-                CASE1(DECORATION, DecorationStream, GeometryStreams),
-                CASE1(DECORATION, DecorationLocation, Shader),
-                CASE1(DECORATION, DecorationComponent, Shader),
-                CASE1(DECORATION, DecorationIndex, Shader),
-                CASE1(DECORATION, DecorationBinding, Shader),
-                CASE1(DECORATION, DecorationDescriptorSet, Shader),
-                CASE1(DECORATION, DecorationOffset, Shader),  // Bug 15268
-                CASE1(DECORATION, DecorationXfbBuffer, TransformFeedback),
-                CASE1(DECORATION, DecorationXfbStride, TransformFeedback),
-                CASE1(DECORATION, DecorationFuncParamAttr, Kernel),
-                CASE1(DECORATION, DecorationFPFastMathMode, Kernel),
-                CASE1(DECORATION, DecorationLinkageAttributes, Linkage),
-                CASE1(DECORATION, DecorationNoContraction, Shader),
-                CASE1(DECORATION, DecorationInputAttachmentIndex,
+                CASE1(DECORATION, Decoration::SaturatedConversion, Kernel),
+                CASE1(DECORATION, Decoration::Stream, GeometryStreams),
+                CASE1(DECORATION, Decoration::Location, Shader),
+                CASE1(DECORATION, Decoration::Component, Shader),
+                CASE1(DECORATION, Decoration::Index, Shader),
+                CASE1(DECORATION, Decoration::Binding, Shader),
+                CASE1(DECORATION, Decoration::DescriptorSet, Shader),
+                CASE1(DECORATION, Decoration::Offset, Shader),  // Bug 15268
+                CASE1(DECORATION, Decoration::XfbBuffer, TransformFeedback),
+                CASE1(DECORATION, Decoration::XfbStride, TransformFeedback),
+                CASE1(DECORATION, Decoration::FuncParamAttr, Kernel),
+                CASE1(DECORATION, Decoration::FPFastMathMode, Kernel),
+                CASE1(DECORATION, Decoration::LinkageAttributes, Linkage),
+                CASE1(DECORATION, Decoration::NoContraction, Shader),
+                CASE1(DECORATION, Decoration::InputAttachmentIndex,
                       InputAttachment),
-                CASE1(DECORATION, DecorationAlignment, Kernel),
+                CASE1(DECORATION, Decoration::Alignment, Kernel),
             })));
 
 #if 0
@@ -477,8 +481,8 @@
     DecorationV11, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE2(DECORATION, DecorationSpecId, Shader, Kernel),
-                CASE1(DECORATION, DecorationMaxByteOffset, Addresses)})));
+                CASE2(DECORATION, Decoration::SpecId, Shader, Kernel),
+                CASE1(DECORATION, Decoration::MaxByteOffset, Addresses)})));
 
 // See SPIR-V Section 3.21 BuiltIn
 INSTANTIATE_TEST_SUITE_P(
@@ -487,51 +491,51 @@
         Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
         ValuesIn(std::vector<EnumCapabilityCase>{
             // clang-format off
-            CASE1(BUILT_IN, BuiltInPosition, Shader),
-            CASE1(BUILT_IN, BuiltInPointSize, Shader),
+            CASE1(BUILT_IN, BuiltIn::Position, Shader),
+            CASE1(BUILT_IN, BuiltIn::PointSize, Shader),
             // 2 is an intentional gap in the spec numbering.
-            CASE1(BUILT_IN, BuiltInClipDistance, ClipDistance),  // Bug 1407, 15234
-            CASE1(BUILT_IN, BuiltInCullDistance, CullDistance),  // Bug 1407, 15234
-            CASE1(BUILT_IN, BuiltInVertexId, Shader),
-            CASE1(BUILT_IN, BuiltInInstanceId, Shader),
-            CASE6(BUILT_IN, BuiltInPrimitiveId, Geometry, Tessellation,
+            CASE1(BUILT_IN, BuiltIn::ClipDistance, ClipDistance),  // Bug 1407, 15234
+            CASE1(BUILT_IN, BuiltIn::CullDistance, CullDistance),  // Bug 1407, 15234
+            CASE1(BUILT_IN, BuiltIn::VertexId, Shader),
+            CASE1(BUILT_IN, BuiltIn::InstanceId, Shader),
+            CASE6(BUILT_IN, BuiltIn::PrimitiveId, Geometry, Tessellation,
                   RayTracingNV, RayTracingKHR, MeshShadingNV, MeshShadingEXT),
-            CASE2(BUILT_IN, BuiltInInvocationId, Geometry, Tessellation),
-            CASE4(BUILT_IN, BuiltInLayer, Geometry, ShaderViewportIndexLayerEXT, MeshShadingNV, MeshShadingEXT),
-            CASE4(BUILT_IN, BuiltInViewportIndex, MultiViewport, ShaderViewportIndexLayerEXT, MeshShadingNV, MeshShadingEXT),  // Bug 15234
-            CASE1(BUILT_IN, BuiltInTessLevelOuter, Tessellation),
-            CASE1(BUILT_IN, BuiltInTessLevelInner, Tessellation),
-            CASE1(BUILT_IN, BuiltInTessCoord, Tessellation),
-            CASE1(BUILT_IN, BuiltInPatchVertices, Tessellation),
-            CASE1(BUILT_IN, BuiltInFragCoord, Shader),
-            CASE1(BUILT_IN, BuiltInPointCoord, Shader),
-            CASE1(BUILT_IN, BuiltInFrontFacing, Shader),
-            CASE1(BUILT_IN, BuiltInSampleId, SampleRateShading),  // Bug 15234
-            CASE1(BUILT_IN, BuiltInSamplePosition, SampleRateShading), // Bug 15234
-            CASE1(BUILT_IN, BuiltInSampleMask, Shader),  // Bug 15234, Issue 182
+            CASE2(BUILT_IN, BuiltIn::InvocationId, Geometry, Tessellation),
+            CASE4(BUILT_IN, BuiltIn::Layer, Geometry, ShaderViewportIndexLayerEXT, MeshShadingNV, MeshShadingEXT),
+            CASE4(BUILT_IN, BuiltIn::ViewportIndex, MultiViewport, ShaderViewportIndexLayerEXT, MeshShadingNV, MeshShadingEXT),  // Bug 15234
+            CASE1(BUILT_IN, BuiltIn::TessLevelOuter, Tessellation),
+            CASE1(BUILT_IN, BuiltIn::TessLevelInner, Tessellation),
+            CASE1(BUILT_IN, BuiltIn::TessCoord, Tessellation),
+            CASE1(BUILT_IN, BuiltIn::PatchVertices, Tessellation),
+            CASE1(BUILT_IN, BuiltIn::FragCoord, Shader),
+            CASE1(BUILT_IN, BuiltIn::PointCoord, Shader),
+            CASE1(BUILT_IN, BuiltIn::FrontFacing, Shader),
+            CASE1(BUILT_IN, BuiltIn::SampleId, SampleRateShading),  // Bug 15234
+            CASE1(BUILT_IN, BuiltIn::SamplePosition, SampleRateShading), // Bug 15234
+            CASE1(BUILT_IN, BuiltIn::SampleMask, Shader),  // Bug 15234, Issue 182
             // Value 21 intentionally missing
-            CASE1(BUILT_IN, BuiltInFragDepth, Shader),
-            CASE1(BUILT_IN, BuiltInHelperInvocation, Shader),
-            CASE0(BUILT_IN, BuiltInNumWorkgroups),
-            CASE0(BUILT_IN, BuiltInWorkgroupSize),
-            CASE0(BUILT_IN, BuiltInWorkgroupId),
-            CASE0(BUILT_IN, BuiltInLocalInvocationId),
-            CASE0(BUILT_IN, BuiltInGlobalInvocationId),
-            CASE0(BUILT_IN, BuiltInLocalInvocationIndex),
-            CASE1(BUILT_IN, BuiltInWorkDim, Kernel),
-            CASE1(BUILT_IN, BuiltInGlobalSize, Kernel),
-            CASE1(BUILT_IN, BuiltInEnqueuedWorkgroupSize, Kernel),
-            CASE1(BUILT_IN, BuiltInGlobalOffset, Kernel),
-            CASE1(BUILT_IN, BuiltInGlobalLinearId, Kernel),
+            CASE1(BUILT_IN, BuiltIn::FragDepth, Shader),
+            CASE1(BUILT_IN, BuiltIn::HelperInvocation, Shader),
+            CASE0(BUILT_IN, BuiltIn::NumWorkgroups),
+            CASE0(BUILT_IN, BuiltIn::WorkgroupSize),
+            CASE0(BUILT_IN, BuiltIn::WorkgroupId),
+            CASE0(BUILT_IN, BuiltIn::LocalInvocationId),
+            CASE0(BUILT_IN, BuiltIn::GlobalInvocationId),
+            CASE0(BUILT_IN, BuiltIn::LocalInvocationIndex),
+            CASE1(BUILT_IN, BuiltIn::WorkDim, Kernel),
+            CASE1(BUILT_IN, BuiltIn::GlobalSize, Kernel),
+            CASE1(BUILT_IN, BuiltIn::EnqueuedWorkgroupSize, Kernel),
+            CASE1(BUILT_IN, BuiltIn::GlobalOffset, Kernel),
+            CASE1(BUILT_IN, BuiltIn::GlobalLinearId, Kernel),
             // Value 35 intentionally missing
-            CASE2(BUILT_IN, BuiltInSubgroupSize, Kernel, SubgroupBallotKHR),
-            CASE1(BUILT_IN, BuiltInSubgroupMaxSize, Kernel),
-            CASE1(BUILT_IN, BuiltInNumSubgroups, Kernel),
-            CASE1(BUILT_IN, BuiltInNumEnqueuedSubgroups, Kernel),
-            CASE1(BUILT_IN, BuiltInSubgroupId, Kernel),
-            CASE2(BUILT_IN, BuiltInSubgroupLocalInvocationId, Kernel, SubgroupBallotKHR),
-            CASE1(BUILT_IN, BuiltInVertexIndex, Shader),
-            CASE1(BUILT_IN, BuiltInInstanceIndex, Shader),
+            CASE2(BUILT_IN, BuiltIn::SubgroupSize, Kernel, SubgroupBallotKHR),
+            CASE1(BUILT_IN, BuiltIn::SubgroupMaxSize, Kernel),
+            CASE1(BUILT_IN, BuiltIn::NumSubgroups, Kernel),
+            CASE1(BUILT_IN, BuiltIn::NumEnqueuedSubgroups, Kernel),
+            CASE1(BUILT_IN, BuiltIn::SubgroupId, Kernel),
+            CASE2(BUILT_IN, BuiltIn::SubgroupLocalInvocationId, Kernel, SubgroupBallotKHR),
+            CASE1(BUILT_IN, BuiltIn::VertexIndex, Shader),
+            CASE1(BUILT_IN, BuiltIn::InstanceIndex, Shader),
             // clang-format on
         })));
 
@@ -541,9 +545,9 @@
         Values(SPV_ENV_UNIVERSAL_1_5),
         ValuesIn(std::vector<EnumCapabilityCase>{
             // SPIR-V 1.5 adds new capabilities to enable these two builtins.
-            CASE5(BUILT_IN, BuiltInLayer, Geometry, ShaderLayer,
+            CASE5(BUILT_IN, BuiltIn::Layer, Geometry, ShaderLayer,
                   ShaderViewportIndexLayerEXT, MeshShadingNV, MeshShadingEXT),
-            CASE5(BUILT_IN, BuiltInViewportIndex, MultiViewport,
+            CASE5(BUILT_IN, BuiltIn::ViewportIndex, MultiViewport,
                   ShaderViewportIndex, ShaderViewportIndexLayerEXT,
                   MeshShadingNV, MeshShadingEXT),
         })));
@@ -553,9 +557,9 @@
     SelectionControl, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE0(SELECTION_CONTROL, SelectionControlMaskNone),
-                CASE0(SELECTION_CONTROL, SelectionControlFlattenMask),
-                CASE0(SELECTION_CONTROL, SelectionControlDontFlattenMask),
+                CASE0(SELECTION_CONTROL, SelectionControlMask::MaskNone),
+                CASE0(SELECTION_CONTROL, SelectionControlMask::Flatten),
+                CASE0(SELECTION_CONTROL, SelectionControlMask::DontFlatten),
             })));
 
 // See SPIR-V Section 3.23 Loop Control
@@ -563,17 +567,17 @@
     LoopControl, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE0(LOOP_CONTROL, LoopControlMaskNone),
-                CASE0(LOOP_CONTROL, LoopControlUnrollMask),
-                CASE0(LOOP_CONTROL, LoopControlDontUnrollMask),
+                CASE0(LOOP_CONTROL, LoopControlMask::MaskNone),
+                CASE0(LOOP_CONTROL, LoopControlMask::Unroll),
+                CASE0(LOOP_CONTROL, LoopControlMask::DontUnroll),
             })));
 
 INSTANTIATE_TEST_SUITE_P(
     LoopControlV11, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE0(LOOP_CONTROL, LoopControlDependencyInfiniteMask),
-                CASE0(LOOP_CONTROL, LoopControlDependencyLengthMask),
+                CASE0(LOOP_CONTROL, LoopControlMask::DependencyInfinite),
+                CASE0(LOOP_CONTROL, LoopControlMask::DependencyLength),
             })));
 
 // See SPIR-V Section 3.24 Function Control
@@ -581,11 +585,11 @@
     FunctionControl, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE0(FUNCTION_CONTROL, FunctionControlMaskNone),
-                CASE0(FUNCTION_CONTROL, FunctionControlInlineMask),
-                CASE0(FUNCTION_CONTROL, FunctionControlDontInlineMask),
-                CASE0(FUNCTION_CONTROL, FunctionControlPureMask),
-                CASE0(FUNCTION_CONTROL, FunctionControlConstMask),
+                CASE0(FUNCTION_CONTROL, FunctionControlMask::MaskNone),
+                CASE0(FUNCTION_CONTROL, FunctionControlMask::Inline),
+                CASE0(FUNCTION_CONTROL, FunctionControlMask::DontInline),
+                CASE0(FUNCTION_CONTROL, FunctionControlMask::Pure),
+                CASE0(FUNCTION_CONTROL, FunctionControlMask::Const),
             })));
 
 // See SPIR-V Section 3.25 Memory Semantics <id>
@@ -594,20 +598,21 @@
     Combine(
         Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
         ValuesIn(std::vector<EnumCapabilityCase>{
-            CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsMaskNone),
-            CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsAcquireMask),
-            CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsReleaseMask),
-            CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsAcquireReleaseMask),
+            CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsMask::MaskNone),
+            CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsMask::Acquire),
+            CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsMask::Release),
+            CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsMask::AcquireRelease),
             CASE0(MEMORY_SEMANTICS_ID,
-                  MemorySemanticsSequentiallyConsistentMask),
-            CASE1(MEMORY_SEMANTICS_ID, MemorySemanticsUniformMemoryMask,
+                  MemorySemanticsMask::SequentiallyConsistent),
+            CASE1(MEMORY_SEMANTICS_ID, MemorySemanticsMask::UniformMemory,
                   Shader),
-            CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsSubgroupMemoryMask),
-            CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsWorkgroupMemoryMask),
-            CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsCrossWorkgroupMemoryMask),
-            CASE1(MEMORY_SEMANTICS_ID, MemorySemanticsAtomicCounterMemoryMask,
+            CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsMask::SubgroupMemory),
+            CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsMask::WorkgroupMemory),
+            CASE0(MEMORY_SEMANTICS_ID,
+                  MemorySemanticsMask::CrossWorkgroupMemory),
+            CASE1(MEMORY_SEMANTICS_ID, MemorySemanticsMask::AtomicCounterMemory,
                   AtomicStorage),  // Bug 15234
-            CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsImageMemoryMask),
+            CASE0(MEMORY_SEMANTICS_ID, MemorySemanticsMask::ImageMemory),
         })));
 
 // See SPIR-V Section 3.26 Memory Access
@@ -615,10 +620,10 @@
     MemoryAccess, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE0(OPTIONAL_MEMORY_ACCESS, MemoryAccessMaskNone),
-                CASE0(OPTIONAL_MEMORY_ACCESS, MemoryAccessVolatileMask),
-                CASE0(OPTIONAL_MEMORY_ACCESS, MemoryAccessAlignedMask),
-                CASE0(OPTIONAL_MEMORY_ACCESS, MemoryAccessNontemporalMask),
+                CASE0(OPTIONAL_MEMORY_ACCESS, MemoryAccessMask::MaskNone),
+                CASE0(OPTIONAL_MEMORY_ACCESS, MemoryAccessMask::Volatile),
+                CASE0(OPTIONAL_MEMORY_ACCESS, MemoryAccessMask::Aligned),
+                CASE0(OPTIONAL_MEMORY_ACCESS, MemoryAccessMask::Nontemporal),
             })));
 
 // See SPIR-V Section 3.27 Scope <id>
@@ -627,12 +632,12 @@
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
                    SPV_ENV_UNIVERSAL_1_2, SPV_ENV_UNIVERSAL_1_3),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE0(SCOPE_ID, ScopeCrossDevice),
-                CASE0(SCOPE_ID, ScopeDevice),
-                CASE0(SCOPE_ID, ScopeWorkgroup),
-                CASE0(SCOPE_ID, ScopeSubgroup),
-                CASE0(SCOPE_ID, ScopeInvocation),
-                CASE1(SCOPE_ID, ScopeQueueFamilyKHR, VulkanMemoryModelKHR),
+                CASE0(SCOPE_ID, Scope::CrossDevice),
+                CASE0(SCOPE_ID, Scope::Device),
+                CASE0(SCOPE_ID, Scope::Workgroup),
+                CASE0(SCOPE_ID, Scope::Subgroup),
+                CASE0(SCOPE_ID, Scope::Invocation),
+                CASE1(SCOPE_ID, Scope::QueueFamilyKHR, VulkanMemoryModelKHR),
             })));
 
 // See SPIR-V Section 3.28 Group Operation
@@ -640,11 +645,11 @@
     GroupOperation, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE3(GROUP_OPERATION, GroupOperationReduce, Kernel,
+                CASE3(GROUP_OPERATION, GroupOperation::Reduce, Kernel,
                       GroupNonUniformArithmetic, GroupNonUniformBallot),
-                CASE3(GROUP_OPERATION, GroupOperationInclusiveScan, Kernel,
+                CASE3(GROUP_OPERATION, GroupOperation::InclusiveScan, Kernel,
                       GroupNonUniformArithmetic, GroupNonUniformBallot),
-                CASE3(GROUP_OPERATION, GroupOperationExclusiveScan, Kernel,
+                CASE3(GROUP_OPERATION, GroupOperation::ExclusiveScan, Kernel,
                       GroupNonUniformArithmetic, GroupNonUniformBallot),
             })));
 
@@ -653,9 +658,9 @@
     KernelEnqueueFlags, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE1(KERNEL_ENQ_FLAGS, KernelEnqueueFlagsNoWait, Kernel),
-                CASE1(KERNEL_ENQ_FLAGS, KernelEnqueueFlagsWaitKernel, Kernel),
-                CASE1(KERNEL_ENQ_FLAGS, KernelEnqueueFlagsWaitWorkGroup,
+                CASE1(KERNEL_ENQ_FLAGS, KernelEnqueueFlags::NoWait, Kernel),
+                CASE1(KERNEL_ENQ_FLAGS, KernelEnqueueFlags::WaitKernel, Kernel),
+                CASE1(KERNEL_ENQ_FLAGS, KernelEnqueueFlags::WaitWorkGroup,
                       Kernel),
             })));
 
@@ -664,9 +669,9 @@
     KernelProfilingInfo, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE0(KERNEL_PROFILING_INFO, KernelProfilingInfoMaskNone),
-                CASE1(KERNEL_PROFILING_INFO, KernelProfilingInfoCmdExecTimeMask,
-                      Kernel),
+                CASE0(KERNEL_PROFILING_INFO, KernelProfilingInfoMask::MaskNone),
+                CASE1(KERNEL_PROFILING_INFO,
+                      KernelProfilingInfoMask::CmdExecTime, Kernel),
             })));
 
 // See SPIR-V Section 3.31 Capability
@@ -676,62 +681,62 @@
         Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
         ValuesIn(std::vector<EnumCapabilityCase>{
             // clang-format off
-            CASE0(CAPABILITY, CapabilityMatrix),
-            CASE1(CAPABILITY, CapabilityShader, Matrix),
-            CASE1(CAPABILITY, CapabilityGeometry, Shader),
-            CASE1(CAPABILITY, CapabilityTessellation, Shader),
-            CASE0(CAPABILITY, CapabilityAddresses),
-            CASE0(CAPABILITY, CapabilityLinkage),
-            CASE0(CAPABILITY, CapabilityKernel),
-            CASE1(CAPABILITY, CapabilityVector16, Kernel),
-            CASE1(CAPABILITY, CapabilityFloat16Buffer, Kernel),
-            CASE0(CAPABILITY, CapabilityFloat16),  // Bug 15234
-            CASE0(CAPABILITY, CapabilityFloat64),
-            CASE0(CAPABILITY, CapabilityInt64),
-            CASE1(CAPABILITY, CapabilityInt64Atomics, Int64),
-            CASE1(CAPABILITY, CapabilityImageBasic, Kernel),
-            CASE1(CAPABILITY, CapabilityImageReadWrite, ImageBasic),
-            CASE1(CAPABILITY, CapabilityImageMipmap, ImageBasic),
+            CASE0(CAPABILITY, Capability::Matrix),
+            CASE1(CAPABILITY, Capability::Shader, Matrix),
+            CASE1(CAPABILITY, Capability::Geometry, Shader),
+            CASE1(CAPABILITY, Capability::Tessellation, Shader),
+            CASE0(CAPABILITY, Capability::Addresses),
+            CASE0(CAPABILITY, Capability::Linkage),
+            CASE0(CAPABILITY, Capability::Kernel),
+            CASE1(CAPABILITY, Capability::Vector16, Kernel),
+            CASE1(CAPABILITY, Capability::Float16Buffer, Kernel),
+            CASE0(CAPABILITY, Capability::Float16),  // Bug 15234
+            CASE0(CAPABILITY, Capability::Float64),
+            CASE0(CAPABILITY, Capability::Int64),
+            CASE1(CAPABILITY, Capability::Int64Atomics, Int64),
+            CASE1(CAPABILITY, Capability::ImageBasic, Kernel),
+            CASE1(CAPABILITY, Capability::ImageReadWrite, ImageBasic),
+            CASE1(CAPABILITY, Capability::ImageMipmap, ImageBasic),
             // Value 16 intentionally missing.
-            CASE1(CAPABILITY, CapabilityPipes, Kernel),
-            CASE0(CAPABILITY, CapabilityGroups),
-            CASE1(CAPABILITY, CapabilityDeviceEnqueue, Kernel),
-            CASE1(CAPABILITY, CapabilityLiteralSampler, Kernel),
-            CASE1(CAPABILITY, CapabilityAtomicStorage, Shader),
-            CASE0(CAPABILITY, CapabilityInt16),
-            CASE1(CAPABILITY, CapabilityTessellationPointSize, Tessellation),
-            CASE1(CAPABILITY, CapabilityGeometryPointSize, Geometry),
-            CASE1(CAPABILITY, CapabilityImageGatherExtended, Shader),
+            CASE1(CAPABILITY, Capability::Pipes, Kernel),
+            CASE0(CAPABILITY, Capability::Groups),
+            CASE1(CAPABILITY, Capability::DeviceEnqueue, Kernel),
+            CASE1(CAPABILITY, Capability::LiteralSampler, Kernel),
+            CASE1(CAPABILITY, Capability::AtomicStorage, Shader),
+            CASE0(CAPABILITY, Capability::Int16),
+            CASE1(CAPABILITY, Capability::TessellationPointSize, Tessellation),
+            CASE1(CAPABILITY, Capability::GeometryPointSize, Geometry),
+            CASE1(CAPABILITY, Capability::ImageGatherExtended, Shader),
             // Value 26 intentionally missing.
-            CASE1(CAPABILITY, CapabilityStorageImageMultisample, Shader),
-            CASE1(CAPABILITY, CapabilityUniformBufferArrayDynamicIndexing, Shader),
-            CASE1(CAPABILITY, CapabilitySampledImageArrayDynamicIndexing, Shader),
-            CASE1(CAPABILITY, CapabilityStorageBufferArrayDynamicIndexing, Shader),
-            CASE1(CAPABILITY, CapabilityStorageImageArrayDynamicIndexing, Shader),
-            CASE1(CAPABILITY, CapabilityClipDistance, Shader),
-            CASE1(CAPABILITY, CapabilityCullDistance, Shader),
-            CASE1(CAPABILITY, CapabilityImageCubeArray, SampledCubeArray),
-            CASE1(CAPABILITY, CapabilitySampleRateShading, Shader),
-            CASE1(CAPABILITY, CapabilityImageRect, SampledRect),
-            CASE1(CAPABILITY, CapabilitySampledRect, Shader),
-            CASE1(CAPABILITY, CapabilityGenericPointer, Addresses),
-            CASE0(CAPABILITY, CapabilityInt8),
-            CASE1(CAPABILITY, CapabilityInputAttachment, Shader),
-            CASE1(CAPABILITY, CapabilitySparseResidency, Shader),
-            CASE1(CAPABILITY, CapabilityMinLod, Shader),
-            CASE1(CAPABILITY, CapabilityImage1D, Sampled1D),
-            CASE1(CAPABILITY, CapabilitySampledCubeArray, Shader),
-            CASE1(CAPABILITY, CapabilityImageBuffer, SampledBuffer),
-            CASE1(CAPABILITY, CapabilityImageMSArray, Shader),
-            CASE1(CAPABILITY, CapabilityStorageImageExtendedFormats, Shader),
-            CASE1(CAPABILITY, CapabilityImageQuery, Shader),
-            CASE1(CAPABILITY, CapabilityDerivativeControl, Shader),
-            CASE1(CAPABILITY, CapabilityInterpolationFunction, Shader),
-            CASE1(CAPABILITY, CapabilityTransformFeedback, Shader),
-            CASE1(CAPABILITY, CapabilityGeometryStreams, Geometry),
-            CASE1(CAPABILITY, CapabilityStorageImageReadWithoutFormat, Shader),
-            CASE1(CAPABILITY, CapabilityStorageImageWriteWithoutFormat, Shader),
-            CASE1(CAPABILITY, CapabilityMultiViewport, Geometry),
+            CASE1(CAPABILITY, Capability::StorageImageMultisample, Shader),
+            CASE1(CAPABILITY, Capability::UniformBufferArrayDynamicIndexing, Shader),
+            CASE1(CAPABILITY, Capability::SampledImageArrayDynamicIndexing, Shader),
+            CASE1(CAPABILITY, Capability::StorageBufferArrayDynamicIndexing, Shader),
+            CASE1(CAPABILITY, Capability::StorageImageArrayDynamicIndexing, Shader),
+            CASE1(CAPABILITY, Capability::ClipDistance, Shader),
+            CASE1(CAPABILITY, Capability::CullDistance, Shader),
+            CASE1(CAPABILITY, Capability::ImageCubeArray, SampledCubeArray),
+            CASE1(CAPABILITY, Capability::SampleRateShading, Shader),
+            CASE1(CAPABILITY, Capability::ImageRect, SampledRect),
+            CASE1(CAPABILITY, Capability::SampledRect, Shader),
+            CASE1(CAPABILITY, Capability::GenericPointer, Addresses),
+            CASE0(CAPABILITY, Capability::Int8),
+            CASE1(CAPABILITY, Capability::InputAttachment, Shader),
+            CASE1(CAPABILITY, Capability::SparseResidency, Shader),
+            CASE1(CAPABILITY, Capability::MinLod, Shader),
+            CASE1(CAPABILITY, Capability::Image1D, Sampled1D),
+            CASE1(CAPABILITY, Capability::SampledCubeArray, Shader),
+            CASE1(CAPABILITY, Capability::ImageBuffer, SampledBuffer),
+            CASE1(CAPABILITY, Capability::ImageMSArray, Shader),
+            CASE1(CAPABILITY, Capability::StorageImageExtendedFormats, Shader),
+            CASE1(CAPABILITY, Capability::ImageQuery, Shader),
+            CASE1(CAPABILITY, Capability::DerivativeControl, Shader),
+            CASE1(CAPABILITY, Capability::InterpolationFunction, Shader),
+            CASE1(CAPABILITY, Capability::TransformFeedback, Shader),
+            CASE1(CAPABILITY, Capability::GeometryStreams, Geometry),
+            CASE1(CAPABILITY, Capability::StorageImageReadWithoutFormat, Shader),
+            CASE1(CAPABILITY, Capability::StorageImageWriteWithoutFormat, Shader),
+            CASE1(CAPABILITY, Capability::MultiViewport, Geometry),
             // clang-format on
         })));
 
@@ -739,9 +744,9 @@
     CapabilityDependsOnV11, EnumCapabilityTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCapabilityCase>{
-                CASE1(CAPABILITY, CapabilitySubgroupDispatch, DeviceEnqueue),
-                CASE1(CAPABILITY, CapabilityNamedBarrier, Kernel),
-                CASE1(CAPABILITY, CapabilityPipeStorage, Pipes),
+                CASE1(CAPABILITY, Capability::SubgroupDispatch, DeviceEnqueue),
+                CASE1(CAPABILITY, Capability::NamedBarrier, Kernel),
+                CASE1(CAPABILITY, Capability::PipeStorage, Pipes),
             })));
 
 #undef CASE0
diff --git a/test/operand_pattern_test.cpp b/test/operand_pattern_test.cpp
index a98a9d7..58b8a08 100644
--- a/test/operand_pattern_test.cpp
+++ b/test/operand_pattern_test.cpp
@@ -103,17 +103,18 @@
          {PREFIX1}},
         // Volatile has no operands.
         {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
-         SpvMemoryAccessVolatileMask,
+         uint32_t(spv::MemoryAccessMask::Volatile),
          {PREFIX0},
          {PREFIX0}},
         // Aligned has one literal number operand.
         {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
-         SpvMemoryAccessAlignedMask,
+         uint32_t(spv::MemoryAccessMask::Aligned),
          {PREFIX1},
          {PREFIX1, SPV_OPERAND_TYPE_LITERAL_INTEGER}},
         // Volatile with Aligned still has just one literal number operand.
         {SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
-         SpvMemoryAccessVolatileMask | SpvMemoryAccessAlignedMask,
+         uint32_t(spv::MemoryAccessMask::Volatile |
+                  spv::MemoryAccessMask::Aligned),
          {PREFIX1},
          {PREFIX1, SPV_OPERAND_TYPE_LITERAL_INTEGER}},
         // Newer masks are not tested
diff --git a/test/opt/analyze_live_input_test.cpp b/test/opt/analyze_live_input_test.cpp
index d61dbdb..c2a8f4c 100644
--- a/test/opt/analyze_live_input_test.cpp
+++ b/test/opt/analyze_live_input_test.cpp
@@ -696,11 +696,11 @@
   auto result = SinglePassRunToBinary<AnalyzeLiveInputPass>(
       text, true, &live_inputs, &live_builtins);
 
-  auto itr0 = live_builtins.find(SpvBuiltInPointSize);
-  auto itr1 = live_builtins.find(SpvBuiltInClipDistance);
-  auto itr2 = live_builtins.find(SpvBuiltInCullDistance);
+  auto itr0 = live_builtins.find((uint32_t)spv::BuiltIn::PointSize);
+  auto itr1 = live_builtins.find((uint32_t)spv::BuiltIn::ClipDistance);
+  auto itr2 = live_builtins.find((uint32_t)spv::BuiltIn::CullDistance);
 
-  // Expect live_builtins == { SpvBuiltInPointSize }
+  // Expect live_builtins == { spv::BuiltIn::PointSize }
   EXPECT_TRUE(itr0 != live_builtins.end());
   EXPECT_TRUE(itr1 == live_builtins.end());
   EXPECT_TRUE(itr2 == live_builtins.end());
diff --git a/test/opt/dataflow.cpp b/test/opt/dataflow.cpp
index 4742015..51473d8 100644
--- a/test/opt/dataflow.cpp
+++ b/test/opt/dataflow.cpp
@@ -66,7 +66,7 @@
 
   VisitResult Visit(Instruction* inst) override {
     // Conditional branches can be enqueued from labels, so skip them.
-    if (inst->opcode() != SpvOpLabel)
+    if (inst->opcode() != spv::Op::OpLabel)
       return DataFlowAnalysis::VisitResult::kResultFixed;
     uint32_t id = inst->result_id();
     VisitResult ret = DataFlowAnalysis::VisitResult::kResultFixed;
diff --git a/test/opt/debug_info_manager_test.cpp b/test/opt/debug_info_manager_test.cpp
index e87d0be..9e479c0 100644
--- a/test/opt/debug_info_manager_test.cpp
+++ b/test/opt/debug_info_manager_test.cpp
@@ -155,7 +155,7 @@
   EXPECT_EQ(inlined_at->NumOperands(), kDebugInlinedAtOperandScopeIndex + 1);
 
   const uint32_t line_number = 77U;
-  Instruction line(context.get(), SpvOpLine);
+  Instruction line(context.get(), spv::Op::OpLine);
   line.SetInOperands({
       {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {5U}},
       {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {line_number}},
@@ -278,7 +278,7 @@
                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
 
   const uint32_t line_number = 7U;
-  Instruction line(context.get(), SpvOpLine);
+  Instruction line(context.get(), spv::Op::OpLine);
   line.SetInOperands({
       {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {5U}},
       {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER, {line_number}},
diff --git a/test/opt/decoration_manager_test.cpp b/test/opt/decoration_manager_test.cpp
index c9fabe7..cf3516a 100644
--- a/test/opt/decoration_manager_test.cpp
+++ b/test/opt/decoration_manager_test.cpp
@@ -88,7 +88,7 @@
   std::string GetErrorMessage() const { return error_message_; }
 
   std::string ToText(const std::vector<Instruction*>& inst) {
-    std::vector<uint32_t> binary = {SpvMagicNumber, 0x10200, 0u, 2u, 0u};
+    std::vector<uint32_t> binary = {spv::MagicNumber, 0x10200, 0u, 2u, 0u};
     for (const Instruction* i : inst)
       i->ToBinaryWithoutAttachedDebugInsts(&binary);
     std::string text;
@@ -118,16 +118,17 @@
 TEST_F(DecorationManagerTest,
        ComparingDecorationsWithDiffOpcodesDecorateDecorateId) {
   IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer());
-  // This parameter can be interpreted both as { SpvDecorationConstant }
+  // This parameter can be interpreted both as { spv::Decoration::Constant }
   // and also as a list of IDs:  { 22 }
-  const std::vector<uint32_t> param{SpvDecorationConstant};
+  const std::vector<uint32_t> param{
+      static_cast<uint32_t>(spv::Decoration::Constant)};
   // OpDecorate %1 Constant
   Instruction inst1(
-      &ir_context, SpvOpDecorate, 0u, 0u,
+      &ir_context, spv::Op::OpDecorate, 0u, 0u,
       {{SPV_OPERAND_TYPE_ID, {1u}}, {SPV_OPERAND_TYPE_DECORATION, param}});
   // OpDecorateId %1 %22   ; 'Constant' is decoration number 22
   Instruction inst2(
-      &ir_context, SpvOpDecorateId, 0u, 0u,
+      &ir_context, spv::Op::OpDecorateId, 0u, 0u,
       {{SPV_OPERAND_TYPE_ID, {1u}}, {SPV_OPERAND_TYPE_ID, param}});
   DecorationManager* decoManager = ir_context.get_decoration_mgr();
   EXPECT_THAT(GetErrorMessage(), "");
@@ -137,16 +138,17 @@
 TEST_F(DecorationManagerTest,
        ComparingDecorationsWithDiffOpcodesDecorateDecorateString) {
   IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer());
-  // This parameter can be interpreted both as { SpvDecorationConstant }
+  // This parameter can be interpreted both as { spv::Decoration::Constant }
   // and also as a null-terminated string with a single character with value 22.
-  const std::vector<uint32_t> param{SpvDecorationConstant};
+  const std::vector<uint32_t> param{
+      static_cast<uint32_t>(spv::Decoration::Constant)};
   // OpDecorate %1 Constant
   Instruction inst1(
-      &ir_context, SpvOpDecorate, 0u, 0u,
+      &ir_context, spv::Op::OpDecorate, 0u, 0u,
       {{SPV_OPERAND_TYPE_ID, {1u}}, {SPV_OPERAND_TYPE_DECORATION, param}});
   // OpDecorateStringGOOGLE %1 !22
   Instruction inst2(
-      &ir_context, SpvOpDecorateStringGOOGLE, 0u, 0u,
+      &ir_context, spv::Op::OpDecorateStringGOOGLE, 0u, 0u,
       {{SPV_OPERAND_TYPE_ID, {1u}}, {SPV_OPERAND_TYPE_LITERAL_STRING, param}});
   DecorationManager* decoManager = ir_context.get_decoration_mgr();
   EXPECT_THAT(GetErrorMessage(), "");
@@ -156,13 +158,15 @@
 TEST_F(DecorationManagerTest, ComparingDecorationsWithDiffDecorateParam) {
   IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer());
   // OpDecorate %1 Constant
-  Instruction inst1(&ir_context, SpvOpDecorate, 0u, 0u,
-                    {{SPV_OPERAND_TYPE_ID, {1u}},
-                     {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}});
+  Instruction inst1(
+      &ir_context, spv::Op::OpDecorate, 0u, 0u,
+      {{SPV_OPERAND_TYPE_ID, {1u}},
+       {SPV_OPERAND_TYPE_DECORATION, {uint32_t(spv::Decoration::Constant)}}});
   // OpDecorate %1 Restrict
-  Instruction inst2(&ir_context, SpvOpDecorate, 0u, 0u,
-                    {{SPV_OPERAND_TYPE_ID, {1u}},
-                     {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationRestrict}}});
+  Instruction inst2(
+      &ir_context, spv::Op::OpDecorate, 0u, 0u,
+      {{SPV_OPERAND_TYPE_ID, {1u}},
+       {SPV_OPERAND_TYPE_DECORATION, {uint32_t(spv::Decoration::Restrict)}}});
   DecorationManager* decoManager = ir_context.get_decoration_mgr();
   EXPECT_THAT(GetErrorMessage(), "");
   EXPECT_FALSE(decoManager->AreDecorationsTheSame(&inst1, &inst2, true));
@@ -172,11 +176,11 @@
   IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer());
   // OpDecorate %1 Constant
   Instruction inst1(
-      &ir_context, SpvOpDecorateId, 0u, 0u,
+      &ir_context, spv::Op::OpDecorateId, 0u, 0u,
       {{SPV_OPERAND_TYPE_ID, {1u}}, {SPV_OPERAND_TYPE_ID, {555}}});
   // OpDecorate %1 Restrict
   Instruction inst2(
-      &ir_context, SpvOpDecorateId, 0u, 0u,
+      &ir_context, spv::Op::OpDecorateId, 0u, 0u,
       {{SPV_OPERAND_TYPE_ID, {1u}}, {SPV_OPERAND_TYPE_ID, {666}}});
   DecorationManager* decoManager = ir_context.get_decoration_mgr();
   EXPECT_THAT(GetErrorMessage(), "");
@@ -186,11 +190,11 @@
 TEST_F(DecorationManagerTest, ComparingDecorationsWithDiffDecorateStringParam) {
   IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer());
   // OpDecorate %1 Constant
-  Instruction inst1(&ir_context, SpvOpDecorateStringGOOGLE, 0u, 0u,
+  Instruction inst1(&ir_context, spv::Op::OpDecorateStringGOOGLE, 0u, 0u,
                     {{SPV_OPERAND_TYPE_ID, {1u}},
                      {SPV_OPERAND_TYPE_LITERAL_STRING, MakeVector("Hello!")}});
   // OpDecorate %1 Restrict
-  Instruction inst2(&ir_context, SpvOpDecorateStringGOOGLE, 0u, 0u,
+  Instruction inst2(&ir_context, spv::Op::OpDecorateStringGOOGLE, 0u, 0u,
                     {{SPV_OPERAND_TYPE_ID, {1u}},
                      {SPV_OPERAND_TYPE_LITERAL_STRING, MakeVector("Hellx")}});
   DecorationManager* decoManager = ir_context.get_decoration_mgr();
@@ -201,13 +205,15 @@
 TEST_F(DecorationManagerTest, ComparingSameDecorationsOnDiffTargetAllowed) {
   IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer());
   // OpDecorate %1 Constant
-  Instruction inst1(&ir_context, SpvOpDecorate, 0u, 0u,
-                    {{SPV_OPERAND_TYPE_ID, {1u}},
-                     {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}});
+  Instruction inst1(
+      &ir_context, spv::Op::OpDecorate, 0u, 0u,
+      {{SPV_OPERAND_TYPE_ID, {1u}},
+       {SPV_OPERAND_TYPE_DECORATION, {uint32_t(spv::Decoration::Constant)}}});
   // OpDecorate %2 Constant
-  Instruction inst2(&ir_context, SpvOpDecorate, 0u, 0u,
-                    {{SPV_OPERAND_TYPE_ID, {2u}},
-                     {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}});
+  Instruction inst2(
+      &ir_context, spv::Op::OpDecorate, 0u, 0u,
+      {{SPV_OPERAND_TYPE_ID, {2u}},
+       {SPV_OPERAND_TYPE_DECORATION, {uint32_t(spv::Decoration::Constant)}}});
   DecorationManager* decoManager = ir_context.get_decoration_mgr();
   EXPECT_THAT(GetErrorMessage(), "");
   EXPECT_TRUE(decoManager->AreDecorationsTheSame(&inst1, &inst2, true));
@@ -216,10 +222,10 @@
 TEST_F(DecorationManagerTest, ComparingSameDecorationIdsOnDiffTargetAllowed) {
   IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer());
   Instruction inst1(
-      &ir_context, SpvOpDecorateId, 0u, 0u,
+      &ir_context, spv::Op::OpDecorateId, 0u, 0u,
       {{SPV_OPERAND_TYPE_ID, {1u}}, {SPV_OPERAND_TYPE_DECORATION, {44}}});
   Instruction inst2(
-      &ir_context, SpvOpDecorateId, 0u, 0u,
+      &ir_context, spv::Op::OpDecorateId, 0u, 0u,
       {{SPV_OPERAND_TYPE_ID, {2u}}, {SPV_OPERAND_TYPE_DECORATION, {44}}});
   DecorationManager* decoManager = ir_context.get_decoration_mgr();
   EXPECT_THAT(GetErrorMessage(), "");
@@ -229,10 +235,10 @@
 TEST_F(DecorationManagerTest,
        ComparingSameDecorationStringsOnDiffTargetAllowed) {
   IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer());
-  Instruction inst1(&ir_context, SpvOpDecorateStringGOOGLE, 0u, 0u,
+  Instruction inst1(&ir_context, spv::Op::OpDecorateStringGOOGLE, 0u, 0u,
                     {{SPV_OPERAND_TYPE_ID, {1u}},
                      {SPV_OPERAND_TYPE_LITERAL_STRING, MakeVector("hello")}});
-  Instruction inst2(&ir_context, SpvOpDecorateStringGOOGLE, 0u, 0u,
+  Instruction inst2(&ir_context, spv::Op::OpDecorateStringGOOGLE, 0u, 0u,
                     {{SPV_OPERAND_TYPE_ID, {2u}},
                      {SPV_OPERAND_TYPE_LITERAL_STRING, MakeVector("hello")}});
   DecorationManager* decoManager = ir_context.get_decoration_mgr();
@@ -243,13 +249,15 @@
 TEST_F(DecorationManagerTest, ComparingSameDecorationsOnDiffTargetDisallowed) {
   IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer());
   // OpDecorate %1 Constant
-  Instruction inst1(&ir_context, SpvOpDecorate, 0u, 0u,
-                    {{SPV_OPERAND_TYPE_ID, {1u}},
-                     {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}});
+  Instruction inst1(
+      &ir_context, spv::Op::OpDecorate, 0u, 0u,
+      {{SPV_OPERAND_TYPE_ID, {1u}},
+       {SPV_OPERAND_TYPE_DECORATION, {uint32_t(spv::Decoration::Constant)}}});
   // OpDecorate %2 Constant
-  Instruction inst2(&ir_context, SpvOpDecorate, 0u, 0u,
-                    {{SPV_OPERAND_TYPE_ID, {2u}},
-                     {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}});
+  Instruction inst2(
+      &ir_context, spv::Op::OpDecorate, 0u, 0u,
+      {{SPV_OPERAND_TYPE_ID, {2u}},
+       {SPV_OPERAND_TYPE_DECORATION, {uint32_t(spv::Decoration::Constant)}}});
   DecorationManager* decoManager = ir_context.get_decoration_mgr();
   EXPECT_THAT(GetErrorMessage(), "");
   EXPECT_FALSE(decoManager->AreDecorationsTheSame(&inst1, &inst2, false));
@@ -258,15 +266,17 @@
 TEST_F(DecorationManagerTest, ComparingMemberDecorationsOnSameTypeDiffMember) {
   IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer());
   // OpMemberDecorate %1 0 Constant
-  Instruction inst1(&ir_context, SpvOpMemberDecorate, 0u, 0u,
-                    {{SPV_OPERAND_TYPE_ID, {1u}},
-                     {SPV_OPERAND_TYPE_LITERAL_INTEGER, {0u}},
-                     {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}});
+  Instruction inst1(
+      &ir_context, spv::Op::OpMemberDecorate, 0u, 0u,
+      {{SPV_OPERAND_TYPE_ID, {1u}},
+       {SPV_OPERAND_TYPE_LITERAL_INTEGER, {0u}},
+       {SPV_OPERAND_TYPE_DECORATION, {uint32_t(spv::Decoration::Constant)}}});
   // OpMemberDecorate %1 1 Constant
-  Instruction inst2(&ir_context, SpvOpMemberDecorate, 0u, 0u,
-                    {{SPV_OPERAND_TYPE_ID, {1u}},
-                     {SPV_OPERAND_TYPE_LITERAL_INTEGER, {1u}},
-                     {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}});
+  Instruction inst2(
+      &ir_context, spv::Op::OpMemberDecorate, 0u, 0u,
+      {{SPV_OPERAND_TYPE_ID, {1u}},
+       {SPV_OPERAND_TYPE_LITERAL_INTEGER, {1u}},
+       {SPV_OPERAND_TYPE_DECORATION, {uint32_t(spv::Decoration::Constant)}}});
   DecorationManager* decoManager = ir_context.get_decoration_mgr();
   EXPECT_THAT(GetErrorMessage(), "");
   EXPECT_FALSE(decoManager->AreDecorationsTheSame(&inst1, &inst2, true));
@@ -276,15 +286,17 @@
        ComparingSameMemberDecorationsOnDiffTargetAllowed) {
   IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer());
   // OpMemberDecorate %1 0 Constant
-  Instruction inst1(&ir_context, SpvOpMemberDecorate, 0u, 0u,
-                    {{SPV_OPERAND_TYPE_ID, {1u}},
-                     {SPV_OPERAND_TYPE_LITERAL_INTEGER, {0u}},
-                     {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}});
+  Instruction inst1(
+      &ir_context, spv::Op::OpMemberDecorate, 0u, 0u,
+      {{SPV_OPERAND_TYPE_ID, {1u}},
+       {SPV_OPERAND_TYPE_LITERAL_INTEGER, {0u}},
+       {SPV_OPERAND_TYPE_DECORATION, {uint32_t(spv::Decoration::Constant)}}});
   // OpMemberDecorate %2 0 Constant
-  Instruction inst2(&ir_context, SpvOpMemberDecorate, 0u, 0u,
-                    {{SPV_OPERAND_TYPE_ID, {2u}},
-                     {SPV_OPERAND_TYPE_LITERAL_INTEGER, {0u}},
-                     {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}});
+  Instruction inst2(
+      &ir_context, spv::Op::OpMemberDecorate, 0u, 0u,
+      {{SPV_OPERAND_TYPE_ID, {2u}},
+       {SPV_OPERAND_TYPE_LITERAL_INTEGER, {0u}},
+       {SPV_OPERAND_TYPE_DECORATION, {uint32_t(spv::Decoration::Constant)}}});
   DecorationManager* decoManager = ir_context.get_decoration_mgr();
   EXPECT_THAT(GetErrorMessage(), "");
   EXPECT_TRUE(decoManager->AreDecorationsTheSame(&inst1, &inst2, true));
@@ -294,15 +306,17 @@
        ComparingSameMemberDecorationsOnDiffTargetDisallowed) {
   IRContext ir_context(SPV_ENV_UNIVERSAL_1_2, GetConsumer());
   // OpMemberDecorate %1 0 Constant
-  Instruction inst1(&ir_context, SpvOpMemberDecorate, 0u, 0u,
-                    {{SPV_OPERAND_TYPE_ID, {1u}},
-                     {SPV_OPERAND_TYPE_LITERAL_INTEGER, {0u}},
-                     {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}});
+  Instruction inst1(
+      &ir_context, spv::Op::OpMemberDecorate, 0u, 0u,
+      {{SPV_OPERAND_TYPE_ID, {1u}},
+       {SPV_OPERAND_TYPE_LITERAL_INTEGER, {0u}},
+       {SPV_OPERAND_TYPE_DECORATION, {uint32_t(spv::Decoration::Constant)}}});
   // OpMemberDecorate %2 0 Constant
-  Instruction inst2(&ir_context, SpvOpMemberDecorate, 0u, 0u,
-                    {{SPV_OPERAND_TYPE_ID, {2u}},
-                     {SPV_OPERAND_TYPE_LITERAL_INTEGER, {0u}},
-                     {SPV_OPERAND_TYPE_DECORATION, {SpvDecorationConstant}}});
+  Instruction inst2(
+      &ir_context, spv::Op::OpMemberDecorate, 0u, 0u,
+      {{SPV_OPERAND_TYPE_ID, {2u}},
+       {SPV_OPERAND_TYPE_LITERAL_INTEGER, {0u}},
+       {SPV_OPERAND_TYPE_DECORATION, {uint32_t(spv::Decoration::Constant)}}});
   DecorationManager* decoManager = ir_context.get_decoration_mgr();
   EXPECT_THAT(GetErrorMessage(), "");
   EXPECT_FALSE(decoManager->AreDecorationsTheSame(&inst1, &inst2, false));
@@ -486,7 +500,7 @@
   DecorationManager* decoManager = GetDecorationManager(spirv);
   EXPECT_THAT(GetErrorMessage(), "");
   decoManager->RemoveDecorationsFrom(1u, [](const Instruction& inst) {
-    return inst.opcode() == SpvOpDecorate &&
+    return inst.opcode() == spv::Op::OpDecorate &&
            inst.GetSingleWordInOperand(0u) == 3u;
   });
   auto decorations = decoManager->GetDecorationsFor(1u, false);
@@ -537,9 +551,10 @@
   DecorationManager* decoManager = GetDecorationManager(spirv);
   EXPECT_THAT(GetErrorMessage(), "");
   decoManager->RemoveDecorationsFrom(1u, [](const Instruction& inst) {
-    return inst.opcode() == SpvOpDecorate &&
+    return inst.opcode() == spv::Op::OpDecorate &&
            inst.GetSingleWordInOperand(0u) == 3u &&
-           inst.GetSingleWordInOperand(1u) == SpvDecorationBuiltIn;
+           spv::Decoration(inst.GetSingleWordInOperand(1u)) ==
+               spv::Decoration::BuiltIn;
   });
   auto decorations = decoManager->GetDecorationsFor(1u, false);
   EXPECT_THAT(GetErrorMessage(), "");
@@ -763,7 +778,7 @@
   EXPECT_EQ(GetErrorMessage(), "");
   EXPECT_TRUE(decorations.empty());
 
-  decoManager->CloneDecorations(1u, 8u, {SpvDecorationRelaxedPrecision});
+  decoManager->CloneDecorations(1u, 8u, {spv::Decoration::RelaxedPrecision});
   decorations = decoManager->GetDecorationsFor(8u, false);
   EXPECT_THAT(GetErrorMessage(), "");
 
@@ -822,7 +837,7 @@
   EXPECT_EQ(GetErrorMessage(), "");
   EXPECT_TRUE(decorations.empty());
 
-  decoManager->CloneDecorations(2u, 9u, {SpvDecorationRelaxedPrecision});
+  decoManager->CloneDecorations(2u, 9u, {spv::Decoration::RelaxedPrecision});
   decorations = decoManager->GetDecorationsFor(9u, false);
   EXPECT_THAT(GetErrorMessage(), "");
 
diff --git a/test/opt/def_use_test.cpp b/test/opt/def_use_test.cpp
index 0210095..4315012 100644
--- a/test/opt/def_use_test.cpp
+++ b/test/opt/def_use_test.cpp
@@ -50,9 +50,9 @@
 //
 // If |id| is used multiple times in a single instruction, that instruction's
 // opcode will appear a corresponding number of times.
-std::vector<SpvOp> GetUseOpcodes(const std::unique_ptr<IRContext>& context,
-                                 uint32_t id) {
-  std::vector<SpvOp> opcodes;
+std::vector<spv::Op> GetUseOpcodes(const std::unique_ptr<IRContext>& context,
+                                   uint32_t id) {
+  std::vector<spv::Op> opcodes;
   context->get_def_use_mgr()->ForEachUse(
       id, [&opcodes](Instruction* user, uint32_t) {
         opcodes.push_back(user->opcode());
@@ -99,7 +99,7 @@
     const auto expected_def = expected_defs_uses.defs[i].second;
     ASSERT_EQ(1u, actual_defs.count(id)) << "expected to def id [" << id << "]";
     auto def = actual_defs.at(id);
-    if (def->opcode() != SpvOpConstant) {
+    if (def->opcode() != spv::Op::OpConstant) {
       // Constants don't disassemble properly without a full context.
       EXPECT_EQ(expected_def, DisassembleInst(actual_defs.at(id)));
     }
@@ -116,7 +116,7 @@
   for (uint32_t id = 0; id != idBound; ++id) {
     if (mgr->GetDef(id)) {
       mgr->ForEachUser(id, [id, &userMap](Instruction* user) {
-        if (user->opcode() != SpvOpConstant) {
+        if (user->opcode() != spv::Op::OpConstant) {
           userMap[id].push_back(user);
         }
       });
@@ -1298,21 +1298,23 @@
 
   {
     EXPECT_EQ(2u, NumUses(context, 6));
-    std::vector<SpvOp> opcodes = GetUseOpcodes(context, 6u);
-    EXPECT_THAT(opcodes, UnorderedElementsAre(SpvOpSwitch, SpvOpReturnValue));
+    std::vector<spv::Op> opcodes = GetUseOpcodes(context, 6u);
+    EXPECT_THAT(opcodes, UnorderedElementsAre(spv::Op::OpSwitch,
+                                              spv::Op::OpReturnValue));
   }
   {
     EXPECT_EQ(6u, NumUses(context, 7));
-    std::vector<SpvOp> opcodes = GetUseOpcodes(context, 7u);
+    std::vector<spv::Op> opcodes = GetUseOpcodes(context, 7u);
     // OpSwitch is now a user of %7.
-    EXPECT_THAT(opcodes, UnorderedElementsAre(SpvOpSelectionMerge, SpvOpBranch,
-                                              SpvOpBranch, SpvOpBranch,
-                                              SpvOpBranch, SpvOpSwitch));
+    EXPECT_THAT(opcodes, UnorderedElementsAre(
+                             spv::Op::OpSelectionMerge, spv::Op::OpBranch,
+                             spv::Op::OpBranch, spv::Op::OpBranch,
+                             spv::Op::OpBranch, spv::Op::OpSwitch));
   }
   // Check all ids only used by OpSwitch after replacement.
   for (const auto id : {8u, 10u, 11u}) {
     EXPECT_EQ(1u, NumUses(context, id));
-    EXPECT_EQ(SpvOpSwitch, GetUseOpcodes(context, id).back());
+    EXPECT_EQ(spv::Op::OpSwitch, GetUseOpcodes(context, id).back());
   }
 }
 
@@ -1378,10 +1380,11 @@
   // Analyze the instructions.
   DefUseManager manager(context.module());
 
-  Instruction label(&context, SpvOpLabel, 0, 2, {});
+  Instruction label(&context, spv::Op::OpLabel, 0, 2, {});
   manager.AnalyzeInstDefUse(&label);
 
-  Instruction branch(&context, SpvOpBranch, 0, 0, {{SPV_OPERAND_TYPE_ID, {2}}});
+  Instruction branch(&context, spv::Op::OpBranch, 0, 0,
+                     {{SPV_OPERAND_TYPE_ID, {2}}});
   manager.AnalyzeInstDefUse(&branch);
   context.module()->SetIdBound(3);
 
@@ -1409,7 +1412,7 @@
   // Analyze the instructions.
   DefUseManager manager(context->module());
 
-  Instruction newInst(context.get(), SpvOpConstantTrue, 1, 2, {});
+  Instruction newInst(context.get(), spv::Op::OpConstantTrue, 1, 2, {});
   manager.AnalyzeInstDefUse(&newInst);
 
   InstDefUse expected = {
@@ -1703,7 +1706,7 @@
   DefUseManager* def_use_mgr = context->get_def_use_mgr();
   Instruction* def = def_use_mgr->GetDef(9);
   Instruction* use = def_use_mgr->GetDef(10);
-  def->SetOpcode(SpvOpCopyObject);
+  def->SetOpcode(spv::Op::OpCopyObject);
   def->SetInOperands({{SPV_OPERAND_TYPE_ID, {25}}});
   context->UpdateDefUse(def);
 
diff --git a/test/opt/eliminate_dead_output_stores_test.cpp b/test/opt/eliminate_dead_output_stores_test.cpp
index 6e382c2..470e709 100644
--- a/test/opt/eliminate_dead_output_stores_test.cpp
+++ b/test/opt/eliminate_dead_output_stores_test.cpp
@@ -652,9 +652,9 @@
 
   std::unordered_set<uint32_t> live_inputs;
   std::unordered_set<uint32_t> live_builtins;
-  // Omit SpvBuiltInPointSize
-  live_builtins.insert(SpvBuiltInClipDistance);
-  live_builtins.insert(SpvBuiltInCullDistance);
+  // Omit spv::BuiltIn::PointSize
+  live_builtins.insert((uint32_t)spv::BuiltIn::ClipDistance);
+  live_builtins.insert((uint32_t)spv::BuiltIn::CullDistance);
   SinglePassRunAndMatch<EliminateDeadOutputStoresPass>(text, true, &live_inputs,
                                                        &live_builtins);
 }
@@ -783,9 +783,9 @@
 
   std::unordered_set<uint32_t> live_inputs;
   std::unordered_set<uint32_t> live_builtins;
-  // Omit SpvBuiltInPointSize
-  live_builtins.insert(SpvBuiltInClipDistance);
-  live_builtins.insert(SpvBuiltInCullDistance);
+  // Omit spv::BuiltIn::PointSize
+  live_builtins.insert((uint32_t)spv::BuiltIn::ClipDistance);
+  live_builtins.insert((uint32_t)spv::BuiltIn::CullDistance);
   SinglePassRunAndMatch<EliminateDeadOutputStoresPass>(text, true, &live_inputs,
                                                        &live_builtins);
 }
diff --git a/test/opt/feature_manager_test.cpp b/test/opt/feature_manager_test.cpp
index 767376c..94c7734 100644
--- a/test/opt/feature_manager_test.cpp
+++ b/test/opt/feature_manager_test.cpp
@@ -100,8 +100,10 @@
       BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
   ASSERT_NE(context, nullptr);
 
-  EXPECT_TRUE(context->get_feature_mgr()->HasCapability(SpvCapabilityShader));
-  EXPECT_FALSE(context->get_feature_mgr()->HasCapability(SpvCapabilityKernel));
+  EXPECT_TRUE(
+      context->get_feature_mgr()->HasCapability(spv::Capability::Shader));
+  EXPECT_FALSE(
+      context->get_feature_mgr()->HasCapability(spv::Capability::Kernel));
 }
 
 TEST_F(FeatureManagerTest, ExplicitlyPresent2) {
@@ -114,8 +116,10 @@
       BuildModule(SPV_ENV_UNIVERSAL_1_2, nullptr, text);
   ASSERT_NE(context, nullptr);
 
-  EXPECT_FALSE(context->get_feature_mgr()->HasCapability(SpvCapabilityShader));
-  EXPECT_TRUE(context->get_feature_mgr()->HasCapability(SpvCapabilityKernel));
+  EXPECT_FALSE(
+      context->get_feature_mgr()->HasCapability(spv::Capability::Shader));
+  EXPECT_TRUE(
+      context->get_feature_mgr()->HasCapability(spv::Capability::Kernel));
 }
 
 TEST_F(FeatureManagerTest, ImplicitlyPresent) {
@@ -131,10 +135,13 @@
   // Check multiple levels of indirection.  Tessellation implies Shader, which
   // implies Matrix.
   EXPECT_TRUE(
-      context->get_feature_mgr()->HasCapability(SpvCapabilityTessellation));
-  EXPECT_TRUE(context->get_feature_mgr()->HasCapability(SpvCapabilityShader));
-  EXPECT_TRUE(context->get_feature_mgr()->HasCapability(SpvCapabilityMatrix));
-  EXPECT_FALSE(context->get_feature_mgr()->HasCapability(SpvCapabilityKernel));
+      context->get_feature_mgr()->HasCapability(spv::Capability::Tessellation));
+  EXPECT_TRUE(
+      context->get_feature_mgr()->HasCapability(spv::Capability::Shader));
+  EXPECT_TRUE(
+      context->get_feature_mgr()->HasCapability(spv::Capability::Matrix));
+  EXPECT_FALSE(
+      context->get_feature_mgr()->HasCapability(spv::Capability::Kernel));
 }
 
 }  // namespace
diff --git a/test/opt/fold_test.cpp b/test/opt/fold_test.cpp
index b324803..06b91f3 100644
--- a/test/opt/fold_test.cpp
+++ b/test/opt/fold_test.cpp
@@ -88,9 +88,9 @@
   // Make sure the instruction folded as expected.
   EXPECT_TRUE(succeeded);
   if (inst != nullptr) {
-    EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
+    EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
     inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
-    EXPECT_EQ(inst->opcode(), SpvOpConstant);
+    EXPECT_EQ(inst->opcode(), spv::Op::OpConstant);
     analysis::ConstantManager* const_mrg = context->get_constant_mgr();
     const analysis::Constant* constant = const_mrg->GetConstantFromInst(inst);
     // We expect to see either integer types or 16-bit float types here.
@@ -896,15 +896,15 @@
   // Fold the instruction to test.
   analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
   Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
-  SpvOp original_opcode = inst->opcode();
+  spv::Op original_opcode = inst->opcode();
   bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
 
   // Make sure the instruction folded as expected.
   EXPECT_EQ(succeeded, inst == nullptr || inst->opcode() != original_opcode);
   if (succeeded && inst != nullptr) {
-    EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
+    EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
     inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
-    std::vector<SpvOp> opcodes = {SpvOpConstantComposite};
+    std::vector<spv::Op> opcodes = {spv::Op::OpConstantComposite};
     EXPECT_THAT(opcodes, Contains(inst->opcode()));
     analysis::ConstantManager* const_mrg = context->get_constant_mgr();
     const analysis::Constant* result = const_mrg->GetConstantFromInst(inst);
@@ -993,9 +993,9 @@
   // Make sure the instruction folded as expected.
   EXPECT_TRUE(succeeded);
   if (succeeded && inst != nullptr) {
-    EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
+    EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
     inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
-    std::vector<SpvOp> opcodes = {SpvOpConstantComposite};
+    std::vector<spv::Op> opcodes = {spv::Op::OpConstantComposite};
     EXPECT_THAT(opcodes, Contains(inst->opcode()));
     analysis::ConstantManager* const_mrg = context->get_constant_mgr();
     const analysis::Constant* result = const_mrg->GetConstantFromInst(inst);
@@ -1094,15 +1094,15 @@
   // Fold the instruction to test.
   analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr();
   Instruction* inst = def_use_mgr->GetDef(tc.id_to_fold);
-  SpvOp original_opcode = inst->opcode();
+  spv::Op original_opcode = inst->opcode();
   bool succeeded = context->get_instruction_folder().FoldInstruction(inst);
 
   // Make sure the instruction folded as expected.
   EXPECT_EQ(succeeded, inst == nullptr || inst->opcode() != original_opcode);
   if (succeeded && inst != nullptr) {
-    EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
+    EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
     inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
-    std::vector<SpvOp> opcodes = {SpvOpConstantComposite};
+    std::vector<spv::Op> opcodes = {spv::Op::OpConstantComposite};
     EXPECT_THAT(opcodes, Contains(inst->opcode()));
     analysis::ConstantManager* const_mrg = context->get_constant_mgr();
     const analysis::Constant* result = const_mrg->GetConstantFromInst(inst);
@@ -1222,9 +1222,10 @@
   // Make sure the instruction folded as expected.
   EXPECT_TRUE(succeeded);
   if (inst != nullptr) {
-    EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
+    EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
     inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
-    std::vector<SpvOp> bool_opcodes = {SpvOpConstantTrue, SpvOpConstantFalse};
+    std::vector<spv::Op> bool_opcodes = {spv::Op::OpConstantTrue,
+                                         spv::Op::OpConstantFalse};
     EXPECT_THAT(bool_opcodes, Contains(inst->opcode()));
     analysis::ConstantManager* const_mrg = context->get_constant_mgr();
     const analysis::BoolConstant* result =
@@ -1833,9 +1834,9 @@
   // Make sure the instruction folded as expected.
   EXPECT_TRUE(succeeded);
   if (inst != nullptr) {
-    EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
+    EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
     inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
-    EXPECT_EQ(inst->opcode(), SpvOpConstant);
+    EXPECT_EQ(inst->opcode(), spv::Op::OpConstant);
     analysis::ConstantManager* const_mrg = context->get_constant_mgr();
     const analysis::FloatConstant* result =
         const_mrg->GetConstantFromInst(inst)->AsFloatConstant();
@@ -2266,9 +2267,9 @@
   // Make sure the instruction folded as expected.
   EXPECT_TRUE(succeeded);
   if (inst != nullptr) {
-    EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
+    EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
     inst = def_use_mgr->GetDef(inst->GetSingleWordInOperand(0));
-    EXPECT_EQ(inst->opcode(), SpvOpConstant);
+    EXPECT_EQ(inst->opcode(), spv::Op::OpConstant);
     analysis::ConstantManager* const_mrg = context->get_constant_mgr();
     const analysis::FloatConstant* result =
         const_mrg->GetConstantFromInst(inst)->AsFloatConstant();
@@ -3153,7 +3154,7 @@
   // Make sure the instruction folded as expected.
   EXPECT_NE(inst, nullptr);
   if (inst != nullptr) {
-    EXPECT_EQ(inst->opcode(), SpvOpConstant);
+    EXPECT_EQ(inst->opcode(), spv::Op::OpConstant);
     analysis::ConstantManager* const_mrg = context->get_constant_mgr();
     const analysis::IntConstant* result =
         const_mrg->GetConstantFromInst(inst)->AsIntConstant();
@@ -3201,7 +3202,8 @@
   // Make sure the instruction folded as expected.
   EXPECT_NE(inst, nullptr);
   if (inst != nullptr) {
-    std::vector<SpvOp> bool_opcodes = {SpvOpConstantTrue, SpvOpConstantFalse};
+    std::vector<spv::Op> bool_opcodes = {spv::Op::OpConstantTrue,
+                                         spv::Op::OpConstantFalse};
     EXPECT_THAT(bool_opcodes, Contains(inst->opcode()));
     analysis::ConstantManager* const_mrg = context->get_constant_mgr();
     const analysis::BoolConstant* result =
@@ -3253,7 +3255,7 @@
   EXPECT_EQ(inst->type_id(), original_inst->type_id());
   EXPECT_TRUE((!succeeded) == (tc.expected_result == 0));
   if (succeeded) {
-    EXPECT_EQ(inst->opcode(), SpvOpCopyObject);
+    EXPECT_EQ(inst->opcode(), spv::Op::OpCopyObject);
     EXPECT_EQ(inst->GetSingleWordInOperand(0), tc.expected_result);
   } else {
     EXPECT_EQ(inst->NumInOperands(), original_inst->NumInOperands());
@@ -4911,7 +4913,7 @@
   EXPECT_EQ(inst->type_id(), original_inst->type_id());
   EXPECT_TRUE((!succeeded) == (tc.expected_result == 0));
   if (succeeded) {
-    EXPECT_EQ(inst->opcode(), SpvOpFNegate);
+    EXPECT_EQ(inst->opcode(), spv::Op::OpFNegate);
     EXPECT_EQ(inst->GetSingleWordInOperand(0), tc.expected_result);
   } else {
     EXPECT_EQ(inst->NumInOperands(), original_inst->NumInOperands());
diff --git a/test/opt/function_test.cpp b/test/opt/function_test.cpp
index 34a0387..09cca33 100644
--- a/test/opt/function_test.cpp
+++ b/test/opt/function_test.cpp
@@ -248,7 +248,7 @@
   std::unordered_set<uint32_t> non_semantic_ids;
   func->ForEachInst(
       [&non_semantic_ids](const Instruction* inst) {
-        if (inst->opcode() == SpvOpExtInst) {
+        if (inst->opcode() == spv::Op::OpExtInst) {
           non_semantic_ids.insert(inst->result_id());
         }
       },
@@ -285,7 +285,7 @@
   std::unordered_set<uint32_t> non_semantic_ids;
   func->ForEachInst(
       [&non_semantic_ids](const Instruction* inst) {
-        if (inst->opcode() == SpvOpExtInst) {
+        if (inst->opcode() == spv::Op::OpExtInst) {
           non_semantic_ids.insert(inst->result_id());
         }
       },
diff --git a/test/opt/inline_test.cpp b/test/opt/inline_test.cpp
index f3ff81c..1e5d9f3 100644
--- a/test/opt/inline_test.cpp
+++ b/test/opt/inline_test.cpp
@@ -4437,7 +4437,7 @@
 //    Callee function returns a value generated outside the callee,
 //      e.g. a constant value. This might exercise some logic not yet
 //      exercised by the current tests: the false branch in the "if"
-//      inside the SpvOpReturnValue case in InlinePass::GenInlineCode?
+//      inside the spv::Op::OpReturnValue case in InlinePass::GenInlineCode?
 //    SampledImage before function call, but callee is only single block.
 //      Then the SampledImage instruction is not cloned. Documents existing
 //      behaviour.
diff --git a/test/opt/instruction_test.cpp b/test/opt/instruction_test.cpp
index dd749ab..6ea7fcc 100644
--- a/test/opt/instruction_test.cpp
+++ b/test/opt/instruction_test.cpp
@@ -39,7 +39,7 @@
 
 TEST(InstructionTest, CreateTrivial) {
   Instruction empty;
-  EXPECT_EQ(SpvOpNop, empty.opcode());
+  EXPECT_EQ(spv::Op::OpNop, empty.opcode());
   EXPECT_EQ(0u, empty.type_id());
   EXPECT_EQ(0u, empty.result_id());
   EXPECT_EQ(0u, empty.NumOperands());
@@ -51,8 +51,8 @@
 
 TEST(InstructionTest, CreateWithOpcodeAndNoOperands) {
   IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
-  Instruction inst(&context, SpvOpReturn);
-  EXPECT_EQ(SpvOpReturn, inst.opcode());
+  Instruction inst(&context, spv::Op::OpReturn);
+  EXPECT_EQ(spv::Op::OpReturn, inst.opcode());
   EXPECT_EQ(0u, inst.type_id());
   EXPECT_EQ(0u, inst.result_id());
   EXPECT_EQ(0u, inst.NumOperands());
@@ -81,8 +81,8 @@
 }
 
 // The words for an OpTypeInt for 32-bit signed integer resulting in Id 44.
-uint32_t kSampleInstructionWords[] = {(4 << 16) | uint32_t(SpvOpTypeInt), 44,
-                                      32, 1};
+uint32_t kSampleInstructionWords[] = {(4 << 16) | uint32_t(spv::Op::OpTypeInt),
+                                      44, 32, 1};
 // The operands that would be parsed from kSampleInstructionWords
 spv_parsed_operand_t kSampleParsedOperands[] = {
     {1, 1, SPV_OPERAND_TYPE_RESULT_ID, SPV_NUMBER_NONE, 0},
@@ -91,18 +91,19 @@
 };
 
 // A valid parse of kSampleParsedOperands.
-spv_parsed_instruction_t kSampleParsedInstruction = {kSampleInstructionWords,
-                                                     uint16_t(4),
-                                                     uint16_t(SpvOpTypeInt),
-                                                     SPV_EXT_INST_TYPE_NONE,
-                                                     0,   // type id
-                                                     44,  // result id
-                                                     kSampleParsedOperands,
-                                                     3};
+spv_parsed_instruction_t kSampleParsedInstruction = {
+    kSampleInstructionWords,
+    uint16_t(4),
+    uint16_t(spv::Op::OpTypeInt),
+    SPV_EXT_INST_TYPE_NONE,
+    0,   // type id
+    44,  // result id
+    kSampleParsedOperands,
+    3};
 
 // The words for an OpAccessChain instruction.
 uint32_t kSampleAccessChainInstructionWords[] = {
-    (7 << 16) | uint32_t(SpvOpAccessChain), 100, 101, 102, 103, 104, 105};
+    (7 << 16) | uint32_t(spv::Op::OpAccessChain), 100, 101, 102, 103, 104, 105};
 
 // The operands that would be parsed from kSampleAccessChainInstructionWords.
 spv_parsed_operand_t kSampleAccessChainOperands[] = {
@@ -118,7 +119,7 @@
 spv_parsed_instruction_t kSampleAccessChainInstruction = {
     kSampleAccessChainInstructionWords,
     uint16_t(7),
-    uint16_t(SpvOpAccessChain),
+    uint16_t(spv::Op::OpAccessChain),
     SPV_EXT_INST_TYPE_NONE,
     100,  // type id
     101,  // result id
@@ -127,7 +128,7 @@
 
 // The words for an OpControlBarrier instruction.
 uint32_t kSampleControlBarrierInstructionWords[] = {
-    (4 << 16) | uint32_t(SpvOpControlBarrier), 100, 101, 102};
+    (4 << 16) | uint32_t(spv::Op::OpControlBarrier), 100, 101, 102};
 
 // The operands that would be parsed from kSampleControlBarrierInstructionWords.
 spv_parsed_operand_t kSampleControlBarrierOperands[] = {
@@ -141,7 +142,7 @@
 spv_parsed_instruction_t kSampleControlBarrierInstruction = {
     kSampleControlBarrierInstructionWords,
     uint16_t(4),
-    uint16_t(SpvOpControlBarrier),
+    uint16_t(spv::Op::OpControlBarrier),
     SPV_EXT_INST_TYPE_NONE,
     0,  // type id
     0,  // result id
@@ -151,7 +152,7 @@
 TEST(InstructionTest, CreateWithOpcodeAndOperands) {
   IRContext context(SPV_ENV_UNIVERSAL_1_2, nullptr);
   Instruction inst(&context, kSampleParsedInstruction);
-  EXPECT_EQ(SpvOpTypeInt, inst.opcode());
+  EXPECT_EQ(spv::Op::OpTypeInt, inst.opcode());
   EXPECT_EQ(0u, inst.type_id());
   EXPECT_EQ(44u, inst.result_id());
   EXPECT_EQ(3u, inst.NumOperands());
diff --git a/test/opt/ir_builder.cpp b/test/opt/ir_builder.cpp
index cb234e0..e04e781 100644
--- a/test/opt/ir_builder.cpp
+++ b/test/opt/ir_builder.cpp
@@ -201,7 +201,7 @@
     // TODO(1841): Handle id overflow.
     fn.begin().InsertBefore(std::unique_ptr<BasicBlock>(
         new BasicBlock(std::unique_ptr<Instruction>(new Instruction(
-            context.get(), SpvOpLabel, 0, context->TakeNextId(), {})))));
+            context.get(), spv::Op::OpLabel, 0, context->TakeNextId(), {})))));
     BasicBlock& bb_true = *fn.begin();
     {
       InstructionBuilder builder(context.get(), &*bb_true.begin());
@@ -211,7 +211,7 @@
     // TODO(1841): Handle id overflow.
     fn.begin().InsertBefore(std::unique_ptr<BasicBlock>(
         new BasicBlock(std::unique_ptr<Instruction>(new Instruction(
-            context.get(), SpvOpLabel, 0, context->TakeNextId(), {})))));
+            context.get(), spv::Op::OpLabel, 0, context->TakeNextId(), {})))));
     BasicBlock& bb_cond = *fn.begin();
 
     InstructionBuilder builder(context.get(), &bb_cond);
diff --git a/test/opt/ir_context_test.cpp b/test/opt/ir_context_test.cpp
index dcae7cf..86a3f45 100644
--- a/test/opt/ir_context_test.cpp
+++ b/test/opt/ir_context_test.cpp
@@ -229,12 +229,12 @@
 
   // Make sure all of the name are removed.
   for (auto& inst : context->debugs2()) {
-    EXPECT_EQ(inst.opcode(), SpvOpNop);
+    EXPECT_EQ(inst.opcode(), spv::Op::OpNop);
   }
 
   // Make sure all of the decorations are removed.
   for (auto& inst : context->annotations()) {
-    EXPECT_EQ(inst.opcode(), SpvOpNop);
+    EXPECT_EQ(inst.opcode(), spv::Op::OpNop);
   }
 }
 
@@ -276,17 +276,17 @@
 
   // Check the OpDecorate instruction
   auto inst = context->annotation_begin();
-  EXPECT_EQ(inst->opcode(), SpvOpDecorate);
+  EXPECT_EQ(inst->opcode(), spv::Op::OpDecorate);
   EXPECT_EQ(inst->GetSingleWordInOperand(0), 3);
 
   // Check the OpDecorationGroup Instruction
   ++inst;
-  EXPECT_EQ(inst->opcode(), SpvOpDecorationGroup);
+  EXPECT_EQ(inst->opcode(), spv::Op::OpDecorationGroup);
   EXPECT_EQ(inst->result_id(), 3);
 
   // Check that %5 is no longer part of the group.
   ++inst;
-  EXPECT_EQ(inst->opcode(), SpvOpGroupDecorate);
+  EXPECT_EQ(inst->opcode(), spv::Op::OpGroupDecorate);
   EXPECT_EQ(inst->NumInOperands(), 2);
   EXPECT_EQ(inst->GetSingleWordInOperand(0), 3);
   EXPECT_EQ(inst->GetSingleWordInOperand(1), 4);
@@ -340,12 +340,12 @@
 
   // Check the OpDecorationGroup Instruction
   auto inst = context->annotation_begin();
-  EXPECT_EQ(inst->opcode(), SpvOpDecorationGroup);
+  EXPECT_EQ(inst->opcode(), spv::Op::OpDecorationGroup);
   EXPECT_EQ(inst->result_id(), 3);
 
   // Check that %5 is no longer part of the group.
   ++inst;
-  EXPECT_EQ(inst->opcode(), SpvOpGroupDecorate);
+  EXPECT_EQ(inst->opcode(), spv::Op::OpGroupDecorate);
   EXPECT_EQ(inst->NumInOperands(), 2);
   EXPECT_EQ(inst->GetSingleWordInOperand(0), 3);
   EXPECT_EQ(inst->GetSingleWordInOperand(1), 4);
diff --git a/test/opt/ir_loader_test.cpp b/test/opt/ir_loader_test.cpp
index ccdd032..45104f4 100644
--- a/test/opt/ir_loader_test.cpp
+++ b/test/opt/ir_loader_test.cpp
@@ -244,10 +244,10 @@
     auto& lines = def_use_mgr->GetDef(check.id)->dbg_line_insts();
     for (uint32_t i = 0; i < check.line_numbers.size(); ++i) {
       if (check.line_numbers[i] == kNoLine) {
-        EXPECT_EQ(lines[i].opcode(), SpvOpNoLine);
+        EXPECT_EQ(lines[i].opcode(), spv::Op::OpNoLine);
         continue;
       }
-      EXPECT_EQ(lines[i].opcode(), SpvOpLine);
+      EXPECT_EQ(lines[i].opcode(), spv::Op::OpLine);
       EXPECT_EQ(lines[i].GetSingleWordOperand(kOpLineOperandLineIndex),
                 check.line_numbers[i]);
     }
@@ -286,9 +286,10 @@
   spvtools::opt::analysis::DefUseManager* def_use_mgr =
       context->get_def_use_mgr();
 
-  std::vector<SpvOp> opcodes;
+  std::vector<spv::Op> opcodes;
   for (auto* inst = def_use_mgr->GetDef(1);
-       inst && (inst->opcode() != SpvOpFunctionEnd); inst = inst->NextNode()) {
+       inst && (inst->opcode() != spv::Op::OpFunctionEnd);
+       inst = inst->NextNode()) {
     inst->ForEachInst(
         [&opcodes](spvtools::opt::Instruction* sub_inst) {
           opcodes.push_back(sub_inst->opcode());
@@ -296,9 +297,9 @@
         true);
   }
 
-  EXPECT_THAT(opcodes,
-              ContainerEq(std::vector<SpvOp>{SpvOpFAdd, SpvOpLine, SpvOpFMul,
-                                             SpvOpFSub, SpvOpReturn}));
+  EXPECT_THAT(opcodes, ContainerEq(std::vector<spv::Op>{
+                           spv::Op::OpFAdd, spv::Op::OpLine, spv::Op::OpFMul,
+                           spv::Op::OpFSub, spv::Op::OpReturn}));
 }
 
 TEST(IrBuilder, BuildModule_WithExtraLines_IsDefault) {
@@ -333,9 +334,10 @@
   spvtools::opt::analysis::DefUseManager* def_use_mgr =
       context->get_def_use_mgr();
 
-  std::vector<SpvOp> opcodes;
+  std::vector<spv::Op> opcodes;
   for (auto* inst = def_use_mgr->GetDef(1);
-       inst && (inst->opcode() != SpvOpFunctionEnd); inst = inst->NextNode()) {
+       inst && (inst->opcode() != spv::Op::OpFunctionEnd);
+       inst = inst->NextNode()) {
     inst->ForEachInst(
         [&opcodes](spvtools::opt::Instruction* sub_inst) {
           opcodes.push_back(sub_inst->opcode());
@@ -343,9 +345,10 @@
         true);
   }
 
-  EXPECT_THAT(opcodes, ContainerEq(std::vector<SpvOp>{
-                           SpvOpFAdd, SpvOpLine, SpvOpFMul, SpvOpLine,
-                           SpvOpFSub, SpvOpLine, SpvOpReturn}));
+  EXPECT_THAT(opcodes, ContainerEq(std::vector<spv::Op>{
+                           spv::Op::OpFAdd, spv::Op::OpLine, spv::Op::OpFMul,
+                           spv::Op::OpLine, spv::Op::OpFSub, spv::Op::OpLine,
+                           spv::Op::OpReturn}));
 }
 
 TEST(IrBuilder, ConsumeDebugInfoInst) {
@@ -1297,8 +1300,9 @@
 
   const auto opundef_count = std::count_if(
       context->module()->types_values_begin(),
-      context->module()->types_values_end(),
-      [](const Instruction& inst) { return inst.opcode() == SpvOpUndef; });
+      context->module()->types_values_end(), [](const Instruction& inst) {
+        return inst.opcode() == spv::Op::OpUndef;
+      });
   EXPECT_EQ(3, opundef_count);
 
   std::vector<uint32_t> binary;
diff --git a/test/opt/loop_optimizations/dependence_analysis.cpp b/test/opt/loop_optimizations/dependence_analysis.cpp
index 8aeb20a..42d9acb 100644
--- a/test/opt/loop_optimizations/dependence_analysis.cpp
+++ b/test/opt/loop_optimizations/dependence_analysis.cpp
@@ -135,7 +135,7 @@
   const Instruction* store[4];
   int stores_found = 0;
   for (const Instruction& inst : *spvtest::GetBasicBlock(f, 13)) {
-    if (inst.opcode() == SpvOp::SpvOpStore) {
+    if (inst.opcode() == spv::Op::OpStore) {
       store[stores_found] = &inst;
       ++stores_found;
     }
@@ -292,7 +292,7 @@
   const Instruction* store[4];
   int stores_found = 0;
   for (const Instruction& inst : *spvtest::GetBasicBlock(f, 22)) {
-    if (inst.opcode() == SpvOp::SpvOpStore) {
+    if (inst.opcode() == spv::Op::OpStore) {
       store[stores_found] = &inst;
       ++stores_found;
     }
@@ -528,7 +528,7 @@
     const Instruction* store[4];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 17)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store[stores_found] = &inst;
         ++stores_found;
       }
@@ -601,7 +601,7 @@
     const Instruction* store[4];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 68)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store[stores_found] = &inst;
         ++stores_found;
       }
@@ -922,7 +922,7 @@
     const Instruction* store[4];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 29)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store[stores_found] = &inst;
         ++stores_found;
       }
@@ -978,7 +978,7 @@
     const Instruction* store[4];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 114)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store[stores_found] = &inst;
         ++stores_found;
       }
@@ -1420,7 +1420,7 @@
 
     const Instruction* store = nullptr;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 29)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store = &inst;
       }
     }
@@ -1441,7 +1441,7 @@
 
     const Instruction* store = nullptr;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 54)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store = &inst;
       }
     }
@@ -1463,7 +1463,7 @@
 
     const Instruction* store = nullptr;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 75)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store = &inst;
       }
     }
@@ -1484,7 +1484,7 @@
 
     const Instruction* store = nullptr;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 99)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store = &inst;
       }
     }
@@ -1506,7 +1506,7 @@
 
     const Instruction* store = nullptr;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 121)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store = &inst;
       }
     }
@@ -1527,7 +1527,7 @@
 
     const Instruction* store = nullptr;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 142)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store = &inst;
       }
     }
@@ -1549,7 +1549,7 @@
 
     const Instruction* store = nullptr;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 162)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store = &inst;
       }
     }
@@ -1570,7 +1570,7 @@
 
     const Instruction* store = nullptr;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 183)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store = &inst;
       }
     }
@@ -1846,7 +1846,7 @@
     const Instruction* store[4];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 19)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store[stores_found] = &inst;
         ++stores_found;
       }
@@ -1914,7 +1914,7 @@
     const Instruction* store[4];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 54)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store[stores_found] = &inst;
         ++stores_found;
       }
@@ -1981,7 +1981,7 @@
     const Instruction* store[4];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 84)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store[stores_found] = &inst;
         ++stores_found;
       }
@@ -2049,7 +2049,7 @@
     const Instruction* store[4];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 111)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store[stores_found] = &inst;
         ++stores_found;
       }
@@ -2210,7 +2210,7 @@
   const Instruction* store[6];
   int stores_found = 0;
   for (const Instruction& inst : *spvtest::GetBasicBlock(f, 11)) {
-    if (inst.opcode() == SpvOp::SpvOpStore) {
+    if (inst.opcode() == spv::Op::OpStore) {
       store[stores_found] = &inst;
       ++stores_found;
     }
@@ -2443,7 +2443,7 @@
     const Instruction* store[1];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 25)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store[stores_found] = &inst;
         ++stores_found;
       }
@@ -2479,7 +2479,7 @@
     const Instruction* store[1];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 56)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store[stores_found] = &inst;
         ++stores_found;
       }
@@ -2790,12 +2790,12 @@
   ASSERT_TRUE(spvtest::GetBasicBlock(f, block_id));
 
   for (const Instruction& inst : *spvtest::GetBasicBlock(f, block_id)) {
-    if (inst.opcode() == SpvOp::SpvOpStore) {
+    if (inst.opcode() == spv::Op::OpStore) {
       store[stores_found] = &inst;
       ++stores_found;
     }
 
-    if (inst.opcode() == SpvOp::SpvOpLoad) {
+    if (inst.opcode() == spv::Op::OpLoad) {
       load[loads_found] = &inst;
       ++loads_found;
     }
@@ -3080,12 +3080,12 @@
   ASSERT_TRUE(spvtest::GetBasicBlock(f, block_id));
 
   for (const Instruction& inst : *spvtest::GetBasicBlock(f, block_id)) {
-    if (inst.opcode() == SpvOp::SpvOpStore) {
+    if (inst.opcode() == spv::Op::OpStore) {
       store[stores_found] = &inst;
       ++stores_found;
     }
 
-    if (inst.opcode() == SpvOp::SpvOpLoad) {
+    if (inst.opcode() == spv::Op::OpLoad) {
       load[loads_found] = &inst;
       ++loads_found;
     }
@@ -3461,11 +3461,11 @@
     ASSERT_TRUE(spvtest::GetBasicBlock(f, block_id));
 
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, block_id)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store = &inst;
       }
 
-      if (inst.opcode() == SpvOp::SpvOpLoad) {
+      if (inst.opcode() == spv::Op::OpLoad) {
         load = &inst;
       }
     }
@@ -3502,11 +3502,11 @@
     ASSERT_TRUE(spvtest::GetBasicBlock(f, block_id));
 
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, block_id)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store = &inst;
       }
 
-      if (inst.opcode() == SpvOp::SpvOpLoad) {
+      if (inst.opcode() == spv::Op::OpLoad) {
         load = &inst;
       }
     }
@@ -3534,11 +3534,11 @@
     ASSERT_TRUE(spvtest::GetBasicBlock(f, block_id));
 
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, block_id)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store = &inst;
       }
 
-      if (inst.opcode() == SpvOp::SpvOpLoad) {
+      if (inst.opcode() == spv::Op::OpLoad) {
         load = &inst;
       }
     }
@@ -3569,11 +3569,11 @@
     ASSERT_TRUE(spvtest::GetBasicBlock(f, block_id));
 
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, block_id)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store = &inst;
       }
 
-      if (inst.opcode() == SpvOp::SpvOpLoad) {
+      if (inst.opcode() == spv::Op::OpLoad) {
         load = &inst;
       }
     }
@@ -3611,11 +3611,11 @@
     ASSERT_TRUE(spvtest::GetBasicBlock(f, block_id));
 
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, block_id)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store = &inst;
       }
 
-      if (inst.opcode() == SpvOp::SpvOpLoad) {
+      if (inst.opcode() == spv::Op::OpLoad) {
         load = &inst;
       }
     }
diff --git a/test/opt/loop_optimizations/dependence_analysis_helpers.cpp b/test/opt/loop_optimizations/dependence_analysis_helpers.cpp
index 715cf54..aabf478 100644
--- a/test/opt/loop_optimizations/dependence_analysis_helpers.cpp
+++ b/test/opt/loop_optimizations/dependence_analysis_helpers.cpp
@@ -172,7 +172,7 @@
     const Instruction* store[1] = {nullptr};
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 16)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store[stores_found] = &inst;
         ++stores_found;
       }
@@ -199,7 +199,7 @@
     const Instruction* store[1] = {nullptr};
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 47)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         store[stores_found] = &inst;
         ++stores_found;
       }
@@ -1495,7 +1495,7 @@
     const Instruction* stores[2];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 30)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         stores[stores_found] = &inst;
         ++stores_found;
       }
@@ -1576,7 +1576,7 @@
     const Instruction* stores[2];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 65)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         stores[stores_found] = &inst;
         ++stores_found;
       }
@@ -1655,7 +1655,7 @@
     const Instruction* stores[2];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 96)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         stores[stores_found] = &inst;
         ++stores_found;
       }
@@ -1734,7 +1734,7 @@
     const Instruction* stores[2];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 126)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         stores[stores_found] = &inst;
         ++stores_found;
       }
@@ -2067,7 +2067,7 @@
     const Instruction* stores[2];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 30)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         stores[stores_found] = &inst;
         ++stores_found;
       }
@@ -2148,7 +2148,7 @@
     const Instruction* stores[2];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 66)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         stores[stores_found] = &inst;
         ++stores_found;
       }
@@ -2229,7 +2229,7 @@
     const Instruction* stores[2];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 96)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         stores[stores_found] = &inst;
         ++stores_found;
       }
@@ -2310,7 +2310,7 @@
     const Instruction* stores[2];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 127)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         stores[stores_found] = &inst;
         ++stores_found;
       }
@@ -2705,7 +2705,7 @@
     const Instruction* stores[2];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 35)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         stores[stores_found] = &inst;
         ++stores_found;
       }
@@ -2784,7 +2784,7 @@
     const Instruction* stores[2];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 90)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         stores[stores_found] = &inst;
         ++stores_found;
       }
@@ -2863,7 +2863,7 @@
     const Instruction* stores[2];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 139)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         stores[stores_found] = &inst;
         ++stores_found;
       }
@@ -2942,7 +2942,7 @@
     const Instruction* stores[2];
     int stores_found = 0;
     for (const Instruction& inst : *spvtest::GetBasicBlock(f, 188)) {
-      if (inst.opcode() == SpvOp::SpvOpStore) {
+      if (inst.opcode() == spv::Op::OpStore) {
         stores[stores_found] = &inst;
         ++stores_found;
       }
diff --git a/test/opt/loop_optimizations/peeling.cpp b/test/opt/loop_optimizations/peeling.cpp
index 10d8add..4ff7a5a 100644
--- a/test/opt/loop_optimizations/peeling.cpp
+++ b/test/opt/loop_optimizations/peeling.cpp
@@ -765,7 +765,7 @@
     EXPECT_EQ(ld.NumLoops(), 1u);
 
     Instruction* loop_count = context->get_def_use_mgr()->GetDef(16);
-    EXPECT_EQ(loop_count->opcode(), SpvOpLoad);
+    EXPECT_EQ(loop_count->opcode(), spv::Op::OpLoad);
 
     LoopPeeling peel(&*ld.begin(), loop_count);
     EXPECT_TRUE(peel.CanPeelLoop());
@@ -817,7 +817,7 @@
     EXPECT_EQ(ld.NumLoops(), 1u);
 
     Instruction* loop_count = context->get_def_use_mgr()->GetDef(16);
-    EXPECT_EQ(loop_count->opcode(), SpvOpLoad);
+    EXPECT_EQ(loop_count->opcode(), spv::Op::OpLoad);
 
     LoopPeeling peel(&*ld.begin(), loop_count);
     EXPECT_TRUE(peel.CanPeelLoop());
@@ -1090,7 +1090,7 @@
     EXPECT_EQ(ld.NumLoops(), 1u);
 
     Instruction* loop_count = context->get_def_use_mgr()->GetDef(15);
-    EXPECT_EQ(loop_count->opcode(), SpvOpLoad);
+    EXPECT_EQ(loop_count->opcode(), spv::Op::OpLoad);
 
     LoopPeeling peel(&*ld.begin(), loop_count);
     EXPECT_TRUE(peel.CanPeelLoop());
@@ -1142,7 +1142,7 @@
     EXPECT_EQ(ld.NumLoops(), 1u);
 
     Instruction* loop_count = context->get_def_use_mgr()->GetDef(15);
-    EXPECT_EQ(loop_count->opcode(), SpvOpLoad);
+    EXPECT_EQ(loop_count->opcode(), spv::Op::OpLoad);
 
     LoopPeeling peel(&*ld.begin(), loop_count);
     EXPECT_TRUE(peel.CanPeelLoop());
diff --git a/test/opt/loop_optimizations/peeling_pass.cpp b/test/opt/loop_optimizations/peeling_pass.cpp
index 284ad83..1b5a12d 100644
--- a/test/opt/loop_optimizations/peeling_pass.cpp
+++ b/test/opt/loop_optimizations/peeling_pass.cpp
@@ -30,27 +30,27 @@
  public:
   // Generic routine to run the loop peeling pass and check
   LoopPeelingPass::LoopPeelingStats AssembleAndRunPeelingTest(
-      const std::string& text_head, const std::string& text_tail, SpvOp opcode,
-      const std::string& res_id, const std::string& op1,
+      const std::string& text_head, const std::string& text_tail,
+      spv::Op opcode, const std::string& res_id, const std::string& op1,
       const std::string& op2) {
     std::string opcode_str;
     switch (opcode) {
-      case SpvOpSLessThan:
+      case spv::Op::OpSLessThan:
         opcode_str = "OpSLessThan";
         break;
-      case SpvOpSGreaterThan:
+      case spv::Op::OpSGreaterThan:
         opcode_str = "OpSGreaterThan";
         break;
-      case SpvOpSLessThanEqual:
+      case spv::Op::OpSLessThanEqual:
         opcode_str = "OpSLessThanEqual";
         break;
-      case SpvOpSGreaterThanEqual:
+      case spv::Op::OpSGreaterThanEqual:
         opcode_str = "OpSGreaterThanEqual";
         break;
-      case SpvOpIEqual:
+      case spv::Op::OpIEqual:
         opcode_str = "OpIEqual";
         break;
-      case SpvOpINotEqual:
+      case spv::Op::OpINotEqual:
         opcode_str = "OpINotEqual";
         break;
       default:
@@ -69,9 +69,9 @@
 
   // Generic routine to run the loop peeling pass and check
   LoopPeelingPass::LoopPeelingStats RunPeelingTest(
-      const std::string& text_head, const std::string& text_tail, SpvOp opcode,
-      const std::string& res_id, const std::string& op1, const std::string& op2,
-      size_t nb_of_loops) {
+      const std::string& text_head, const std::string& text_tail,
+      spv::Op opcode, const std::string& res_id, const std::string& op1,
+      const std::string& op2, size_t nb_of_loops) {
     LoopPeelingPass::LoopPeelingStats stats = AssembleAndRunPeelingTest(
         text_head, text_tail, opcode, res_id, op1, op2);
 
@@ -86,7 +86,7 @@
       std::vector<std::pair<LoopPeelingPass::PeelDirection, uint32_t>>;
 
   void BuildAndCheckTrace(const std::string& text_head,
-                          const std::string& text_tail, SpvOp opcode,
+                          const std::string& text_tail, spv::Op opcode,
                           const std::string& res_id, const std::string& op1,
                           const std::string& op2,
                           const PeelTraceType& expected_peel_trace,
@@ -203,7 +203,7 @@
                OpFunctionEnd
   )";
 
-  auto run_test = [&text_head, &text_tail, this](SpvOp opcode,
+  auto run_test = [&text_head, &text_tail, this](spv::Op opcode,
                                                  const std::string& op1,
                                                  const std::string& op2) {
     auto stats =
@@ -225,7 +225,7 @@
     SCOPED_TRACE("Peel before iv < 4");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThan, "%32", "%int_4");
+        run_test(spv::Op::OpSLessThan, "%32", "%int_4");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -233,7 +233,7 @@
     SCOPED_TRACE("Peel before 4 > iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThan, "%int_4", "%32");
+        run_test(spv::Op::OpSGreaterThan, "%int_4", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -241,7 +241,7 @@
     SCOPED_TRACE("Peel before iv < 5");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThan, "%32", "%int_5");
+        run_test(spv::Op::OpSLessThan, "%32", "%int_5");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -249,7 +249,7 @@
     SCOPED_TRACE("Peel before 5 > iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThan, "%int_5", "%32");
+        run_test(spv::Op::OpSGreaterThan, "%int_5", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -259,7 +259,7 @@
     SCOPED_TRACE("Peel after iv < 16");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThan, "%32", "%int_16");
+        run_test(spv::Op::OpSLessThan, "%32", "%int_16");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -267,7 +267,7 @@
     SCOPED_TRACE("Peel after 16 > iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThan, "%int_16", "%32");
+        run_test(spv::Op::OpSGreaterThan, "%int_16", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -275,7 +275,7 @@
     SCOPED_TRACE("Peel after iv < 17");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThan, "%32", "%int_17");
+        run_test(spv::Op::OpSLessThan, "%32", "%int_17");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -283,7 +283,7 @@
     SCOPED_TRACE("Peel after 17 > iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThan, "%int_17", "%32");
+        run_test(spv::Op::OpSGreaterThan, "%int_17", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -294,7 +294,7 @@
     SCOPED_TRACE("Peel before iv > 5");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThan, "%32", "%int_5");
+        run_test(spv::Op::OpSGreaterThan, "%32", "%int_5");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -302,7 +302,7 @@
     SCOPED_TRACE("Peel before 5 < iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThan, "%int_5", "%32");
+        run_test(spv::Op::OpSLessThan, "%int_5", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -310,7 +310,7 @@
     SCOPED_TRACE("Peel before iv > 4");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThan, "%32", "%int_4");
+        run_test(spv::Op::OpSGreaterThan, "%32", "%int_4");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -318,7 +318,7 @@
     SCOPED_TRACE("Peel before 4 < iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThan, "%int_4", "%32");
+        run_test(spv::Op::OpSLessThan, "%int_4", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -328,7 +328,7 @@
     SCOPED_TRACE("Peel after iv > 16");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThan, "%32", "%int_16");
+        run_test(spv::Op::OpSGreaterThan, "%32", "%int_16");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -336,7 +336,7 @@
     SCOPED_TRACE("Peel after 16 < iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThan, "%int_16", "%32");
+        run_test(spv::Op::OpSLessThan, "%int_16", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -344,7 +344,7 @@
     SCOPED_TRACE("Peel after iv > 17");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThan, "%32", "%int_17");
+        run_test(spv::Op::OpSGreaterThan, "%32", "%int_17");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -352,7 +352,7 @@
     SCOPED_TRACE("Peel after 17 < iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThan, "%int_17", "%32");
+        run_test(spv::Op::OpSLessThan, "%int_17", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -363,7 +363,7 @@
     SCOPED_TRACE("Peel before iv <= 4");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThanEqual, "%32", "%int_4");
+        run_test(spv::Op::OpSLessThanEqual, "%32", "%int_4");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -371,7 +371,7 @@
     SCOPED_TRACE("Peel before 4 => iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThanEqual, "%int_4", "%32");
+        run_test(spv::Op::OpSGreaterThanEqual, "%int_4", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -379,7 +379,7 @@
     SCOPED_TRACE("Peel before iv <= 3");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThanEqual, "%32", "%int_3");
+        run_test(spv::Op::OpSLessThanEqual, "%32", "%int_3");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -387,7 +387,7 @@
     SCOPED_TRACE("Peel before 3 => iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThanEqual, "%int_3", "%32");
+        run_test(spv::Op::OpSGreaterThanEqual, "%int_3", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -397,7 +397,7 @@
     SCOPED_TRACE("Peel after iv <= 16");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThanEqual, "%32", "%int_16");
+        run_test(spv::Op::OpSLessThanEqual, "%32", "%int_16");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -405,7 +405,7 @@
     SCOPED_TRACE("Peel after 16 => iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThanEqual, "%int_16", "%32");
+        run_test(spv::Op::OpSGreaterThanEqual, "%int_16", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -413,7 +413,7 @@
     SCOPED_TRACE("Peel after iv <= 15");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThanEqual, "%32", "%int_15");
+        run_test(spv::Op::OpSLessThanEqual, "%32", "%int_15");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -421,7 +421,7 @@
     SCOPED_TRACE("Peel after 15 => iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThanEqual, "%int_15", "%32");
+        run_test(spv::Op::OpSGreaterThanEqual, "%int_15", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -432,7 +432,7 @@
     SCOPED_TRACE("Peel before iv >= 5");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThanEqual, "%32", "%int_5");
+        run_test(spv::Op::OpSGreaterThanEqual, "%32", "%int_5");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -440,7 +440,7 @@
     SCOPED_TRACE("Peel before 35 >= iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThanEqual, "%int_5", "%32");
+        run_test(spv::Op::OpSLessThanEqual, "%int_5", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -448,7 +448,7 @@
     SCOPED_TRACE("Peel before iv >= 4");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThanEqual, "%32", "%int_4");
+        run_test(spv::Op::OpSGreaterThanEqual, "%32", "%int_4");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -456,7 +456,7 @@
     SCOPED_TRACE("Peel before 4 <= iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThanEqual, "%int_4", "%32");
+        run_test(spv::Op::OpSLessThanEqual, "%int_4", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -466,7 +466,7 @@
     SCOPED_TRACE("Peel after iv >= 17");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThanEqual, "%32", "%int_17");
+        run_test(spv::Op::OpSGreaterThanEqual, "%32", "%int_17");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -474,7 +474,7 @@
     SCOPED_TRACE("Peel after 17 <= iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThanEqual, "%int_17", "%32");
+        run_test(spv::Op::OpSLessThanEqual, "%int_17", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -482,7 +482,7 @@
     SCOPED_TRACE("Peel after iv >= 16");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSGreaterThanEqual, "%32", "%int_16");
+        run_test(spv::Op::OpSGreaterThanEqual, "%32", "%int_16");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -490,7 +490,7 @@
     SCOPED_TRACE("Peel after 16 <= iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpSLessThanEqual, "%int_16", "%32");
+        run_test(spv::Op::OpSLessThanEqual, "%int_16", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 2u);
   }
@@ -501,7 +501,7 @@
     SCOPED_TRACE("Peel before iv == 1");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpIEqual, "%32", "%int_1");
+        run_test(spv::Op::OpIEqual, "%32", "%int_1");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 1u);
   }
@@ -509,7 +509,7 @@
     SCOPED_TRACE("Peel before 1 == iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpIEqual, "%int_1", "%32");
+        run_test(spv::Op::OpIEqual, "%int_1", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 1u);
   }
@@ -519,7 +519,7 @@
     SCOPED_TRACE("Peel after iv == 19");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpIEqual, "%32", "%int_19");
+        run_test(spv::Op::OpIEqual, "%32", "%int_19");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 1u);
   }
@@ -527,7 +527,7 @@
     SCOPED_TRACE("Peel after 19 == iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpIEqual, "%int_19", "%32");
+        run_test(spv::Op::OpIEqual, "%int_19", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 1u);
   }
@@ -538,7 +538,7 @@
     SCOPED_TRACE("Peel before iv != 1");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpINotEqual, "%32", "%int_1");
+        run_test(spv::Op::OpINotEqual, "%32", "%int_1");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 1u);
   }
@@ -546,7 +546,7 @@
     SCOPED_TRACE("Peel before 1 != iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpINotEqual, "%int_1", "%32");
+        run_test(spv::Op::OpINotEqual, "%int_1", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kBefore);
     EXPECT_EQ(peel_info.second, 1u);
   }
@@ -556,7 +556,7 @@
     SCOPED_TRACE("Peel after iv != 19");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpINotEqual, "%32", "%int_19");
+        run_test(spv::Op::OpINotEqual, "%32", "%int_19");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 1u);
   }
@@ -564,7 +564,7 @@
     SCOPED_TRACE("Peel after 19 != iv");
 
     std::pair<LoopPeelingPass::PeelDirection, uint32_t> peel_info =
-        run_test(SpvOpINotEqual, "%int_19", "%32");
+        run_test(spv::Op::OpINotEqual, "%int_19", "%32");
     EXPECT_EQ(peel_info.first, LoopPeelingPass::PeelDirection::kAfter);
     EXPECT_EQ(peel_info.second, 1u);
   }
@@ -573,7 +573,7 @@
   {
     SCOPED_TRACE("No Peel: 20 => iv");
 
-    auto stats = RunPeelingTest(text_head, text_tail, SpvOpSLessThanEqual,
+    auto stats = RunPeelingTest(text_head, text_tail, spv::Op::OpSLessThanEqual,
                                 "%22", "%int_20", "%32", 1);
 
     EXPECT_EQ(stats.peeled_loops_.size(), 0u);
@@ -673,7 +673,7 @@
   )";
 
   auto run_test = [&text_head, &text_tail, this](
-                      SpvOp opcode, const std::string& op1,
+                      spv::Op opcode, const std::string& op1,
                       const std::string& op2,
                       const PeelTraceType& expected_peel_trace) {
     BuildAndCheckTrace(text_head, text_tail, opcode, "%22", op1, op2,
@@ -685,13 +685,13 @@
   {
     SCOPED_TRACE("Peel before iv < 3");
 
-    run_test(SpvOpSLessThan, "%38", "%int_3",
+    run_test(spv::Op::OpSLessThan, "%38", "%int_3",
              {{LoopPeelingPass::PeelDirection::kBefore, 3u}});
   }
   {
     SCOPED_TRACE("Peel before 3 > iv");
 
-    run_test(SpvOpSGreaterThan, "%int_3", "%38",
+    run_test(spv::Op::OpSGreaterThan, "%int_3", "%38",
              {{LoopPeelingPass::PeelDirection::kBefore, 3u}});
   }
 
@@ -699,13 +699,13 @@
   {
     SCOPED_TRACE("Peel after iv < 8");
 
-    run_test(SpvOpSLessThan, "%38", "%int_8",
+    run_test(spv::Op::OpSLessThan, "%38", "%int_8",
              {{LoopPeelingPass::PeelDirection::kAfter, 2u}});
   }
   {
     SCOPED_TRACE("Peel after 8 > iv");
 
-    run_test(SpvOpSGreaterThan, "%int_8", "%38",
+    run_test(spv::Op::OpSGreaterThan, "%int_8", "%38",
              {{LoopPeelingPass::PeelDirection::kAfter, 2u}});
   }
 
@@ -714,13 +714,13 @@
   {
     SCOPED_TRACE("Peel before iv > 2");
 
-    run_test(SpvOpSGreaterThan, "%38", "%int_2",
+    run_test(spv::Op::OpSGreaterThan, "%38", "%int_2",
              {{LoopPeelingPass::PeelDirection::kBefore, 2u}});
   }
   {
     SCOPED_TRACE("Peel before 2 < iv");
 
-    run_test(SpvOpSLessThan, "%int_2", "%38",
+    run_test(spv::Op::OpSLessThan, "%int_2", "%38",
              {{LoopPeelingPass::PeelDirection::kBefore, 2u}});
   }
 
@@ -728,13 +728,13 @@
   {
     SCOPED_TRACE("Peel after iv > 7");
 
-    run_test(SpvOpSGreaterThan, "%38", "%int_7",
+    run_test(spv::Op::OpSGreaterThan, "%38", "%int_7",
              {{LoopPeelingPass::PeelDirection::kAfter, 3u}});
   }
   {
     SCOPED_TRACE("Peel after 7 < iv");
 
-    run_test(SpvOpSLessThan, "%int_7", "%38",
+    run_test(spv::Op::OpSLessThan, "%int_7", "%38",
              {{LoopPeelingPass::PeelDirection::kAfter, 3u}});
   }
 
@@ -743,13 +743,13 @@
   {
     SCOPED_TRACE("Peel before iv <= 1");
 
-    run_test(SpvOpSLessThanEqual, "%38", "%int_1",
+    run_test(spv::Op::OpSLessThanEqual, "%38", "%int_1",
              {{LoopPeelingPass::PeelDirection::kBefore, 2u}});
   }
   {
     SCOPED_TRACE("Peel before 1 => iv");
 
-    run_test(SpvOpSGreaterThanEqual, "%int_1", "%38",
+    run_test(spv::Op::OpSGreaterThanEqual, "%int_1", "%38",
              {{LoopPeelingPass::PeelDirection::kBefore, 2u}});
   }
 
@@ -757,13 +757,13 @@
   {
     SCOPED_TRACE("Peel after iv <= 7");
 
-    run_test(SpvOpSLessThanEqual, "%38", "%int_7",
+    run_test(spv::Op::OpSLessThanEqual, "%38", "%int_7",
              {{LoopPeelingPass::PeelDirection::kAfter, 2u}});
   }
   {
     SCOPED_TRACE("Peel after 7 => iv");
 
-    run_test(SpvOpSGreaterThanEqual, "%int_7", "%38",
+    run_test(spv::Op::OpSGreaterThanEqual, "%int_7", "%38",
              {{LoopPeelingPass::PeelDirection::kAfter, 2u}});
   }
 
@@ -772,13 +772,13 @@
   {
     SCOPED_TRACE("Peel before iv >= 2");
 
-    run_test(SpvOpSGreaterThanEqual, "%38", "%int_2",
+    run_test(spv::Op::OpSGreaterThanEqual, "%38", "%int_2",
              {{LoopPeelingPass::PeelDirection::kBefore, 2u}});
   }
   {
     SCOPED_TRACE("Peel before 2 <= iv");
 
-    run_test(SpvOpSLessThanEqual, "%int_2", "%38",
+    run_test(spv::Op::OpSLessThanEqual, "%int_2", "%38",
              {{LoopPeelingPass::PeelDirection::kBefore, 2u}});
   }
 
@@ -786,13 +786,13 @@
   {
     SCOPED_TRACE("Peel after iv >= 8");
 
-    run_test(SpvOpSGreaterThanEqual, "%38", "%int_8",
+    run_test(spv::Op::OpSGreaterThanEqual, "%38", "%int_8",
              {{LoopPeelingPass::PeelDirection::kAfter, 2u}});
   }
   {
     SCOPED_TRACE("Peel after 8 <= iv");
 
-    run_test(SpvOpSLessThanEqual, "%int_8", "%38",
+    run_test(spv::Op::OpSLessThanEqual, "%int_8", "%38",
              {{LoopPeelingPass::PeelDirection::kAfter, 2u}});
   }
   // Test EQ
@@ -800,13 +800,13 @@
   {
     SCOPED_TRACE("Peel before iv == 0");
 
-    run_test(SpvOpIEqual, "%38", "%int_0",
+    run_test(spv::Op::OpIEqual, "%38", "%int_0",
              {{LoopPeelingPass::PeelDirection::kBefore, 1u}});
   }
   {
     SCOPED_TRACE("Peel before 0 == iv");
 
-    run_test(SpvOpIEqual, "%int_0", "%38",
+    run_test(spv::Op::OpIEqual, "%int_0", "%38",
              {{LoopPeelingPass::PeelDirection::kBefore, 1u}});
   }
 
@@ -814,13 +814,13 @@
   {
     SCOPED_TRACE("Peel after iv == 9");
 
-    run_test(SpvOpIEqual, "%38", "%int_9",
+    run_test(spv::Op::OpIEqual, "%38", "%int_9",
              {{LoopPeelingPass::PeelDirection::kBefore, 1u}});
   }
   {
     SCOPED_TRACE("Peel after 9 == iv");
 
-    run_test(SpvOpIEqual, "%int_9", "%38",
+    run_test(spv::Op::OpIEqual, "%int_9", "%38",
              {{LoopPeelingPass::PeelDirection::kBefore, 1u}});
   }
 
@@ -829,13 +829,13 @@
   {
     SCOPED_TRACE("Peel before iv != 0");
 
-    run_test(SpvOpINotEqual, "%38", "%int_0",
+    run_test(spv::Op::OpINotEqual, "%38", "%int_0",
              {{LoopPeelingPass::PeelDirection::kBefore, 1u}});
   }
   {
     SCOPED_TRACE("Peel before 0 != iv");
 
-    run_test(SpvOpINotEqual, "%int_0", "%38",
+    run_test(spv::Op::OpINotEqual, "%int_0", "%38",
              {{LoopPeelingPass::PeelDirection::kBefore, 1u}});
   }
 
@@ -843,13 +843,13 @@
   {
     SCOPED_TRACE("Peel after iv != 9");
 
-    run_test(SpvOpINotEqual, "%38", "%int_9",
+    run_test(spv::Op::OpINotEqual, "%38", "%int_9",
              {{LoopPeelingPass::PeelDirection::kBefore, 1u}});
   }
   {
     SCOPED_TRACE("Peel after 9 != iv");
 
-    run_test(SpvOpINotEqual, "%int_9", "%38",
+    run_test(spv::Op::OpINotEqual, "%int_9", "%38",
              {{LoopPeelingPass::PeelDirection::kBefore, 1u}});
   }
 }
@@ -952,7 +952,7 @@
 
   auto run_test =
       [&text_head, &text_tail, this](
-          SpvOp opcode, const std::string& op1, const std::string& op2,
+          spv::Op opcode, const std::string& op1, const std::string& op2,
           const PeelTraceType& expected_peel_trace, size_t nb_of_loops) {
         BuildAndCheckTrace(text_head, text_tail, opcode, "%30", op1, op2,
                            expected_peel_trace, nb_of_loops);
@@ -963,7 +963,7 @@
     SCOPED_TRACE("Peel before iv_i < 3");
 
     // Expect peel before by a factor of 3 and 4 loops at the end.
-    run_test(SpvOpSLessThan, "%42", "%int_3",
+    run_test(spv::Op::OpSLessThan, "%42", "%int_3",
              {{LoopPeelingPass::PeelDirection::kBefore, 3u}}, 4);
   }
   // Peeling outer loop after by a factor of 3.
@@ -971,7 +971,7 @@
     SCOPED_TRACE("Peel after iv_i < 7");
 
     // Expect peel after by a factor of 3 and 4 loops at the end.
-    run_test(SpvOpSLessThan, "%42", "%int_7",
+    run_test(spv::Op::OpSLessThan, "%42", "%int_7",
              {{LoopPeelingPass::PeelDirection::kAfter, 3u}}, 4);
   }
 
@@ -980,7 +980,7 @@
     SCOPED_TRACE("Peel before iv_j < 3");
 
     // Expect peel before by a factor of 3 and 3 loops at the end.
-    run_test(SpvOpSLessThan, "%46", "%int_3",
+    run_test(spv::Op::OpSLessThan, "%46", "%int_3",
              {{LoopPeelingPass::PeelDirection::kBefore, 3u}}, 3);
   }
   // Peeling inner loop after by a factor of 3.
@@ -988,7 +988,7 @@
     SCOPED_TRACE("Peel after iv_j < 7");
 
     // Expect peel after by a factor of 3 and 3 loops at the end.
-    run_test(SpvOpSLessThan, "%46", "%int_7",
+    run_test(spv::Op::OpSLessThan, "%46", "%int_7",
              {{LoopPeelingPass::PeelDirection::kAfter, 3u}}, 3);
   }
 
@@ -997,7 +997,7 @@
     SCOPED_TRACE("No peel");
 
     // Expect no peeling and 2 loops at the end.
-    run_test(SpvOpSLessThan, "%46", "%42", {}, 2);
+    run_test(spv::Op::OpSLessThan, "%46", "%42", {}, 2);
   }
 
   // Could do a peeling of 3, but the goes over the threshold.
@@ -1007,7 +1007,7 @@
     size_t current_threshold = LoopPeelingPass::GetLoopPeelingThreshold();
     LoopPeelingPass::SetLoopPeelingThreshold(1u);
     // Expect no peeling and 2 loops at the end.
-    run_test(SpvOpSLessThan, "%46", "%int_7", {}, 2);
+    run_test(spv::Op::OpSLessThan, "%46", "%int_7", {}, 2);
     LoopPeelingPass::SetLoopPeelingThreshold(current_threshold);
   }
 }
diff --git a/test/opt/module_test.cpp b/test/opt/module_test.cpp
index 17a1365..33dc05f 100644
--- a/test/opt/module_test.cpp
+++ b/test/opt/module_test.cpp
@@ -324,7 +324,7 @@
   std::unordered_set<uint32_t> non_semantic_ids;
   context->module()->ForEachInst(
       [&non_semantic_ids](const Instruction* inst) {
-        if (inst->opcode() == SpvOpExtInst) {
+        if (inst->opcode() == spv::Op::OpExtInst) {
           non_semantic_ids.insert(inst->result_id());
         }
       },
diff --git a/test/opt/pass_manager_test.cpp b/test/opt/pass_manager_test.cpp
index 4f36d5b..ec11069 100644
--- a/test/opt/pass_manager_test.cpp
+++ b/test/opt/pass_manager_test.cpp
@@ -144,8 +144,8 @@
 
   const char* name() const override { return "AppendTypeVoidInstPass"; }
   Status Process() override {
-    auto inst = MakeUnique<Instruction>(context(), SpvOpTypeVoid, 0, result_id_,
-                                        std::vector<Operand>{});
+    auto inst = MakeUnique<Instruction>(context(), spv::Op::OpTypeVoid, 0,
+                                        result_id_, std::vector<Operand>{});
     context()->AddType(std::move(inst));
     return Status::SuccessWithChange;
   }
diff --git a/test/opt/pass_remove_duplicates_test.cpp b/test/opt/pass_remove_duplicates_test.cpp
index 887fdfd..ac87db1 100644
--- a/test/opt/pass_remove_duplicates_test.cpp
+++ b/test/opt/pass_remove_duplicates_test.cpp
@@ -91,7 +91,7 @@
   std::string GetErrorMessage() const { return error_message_; }
 
   std::string ToText(const std::vector<Instruction*>& inst) {
-    std::vector<uint32_t> binary = {SpvMagicNumber, 0x10200, 0u, 2u, 0u};
+    std::vector<uint32_t> binary = {spv::MagicNumber, 0x10200, 0u, 2u, 0u};
     for (const Instruction* i : inst)
       i->ToBinaryWithoutAttachedDebugInsts(&binary);
     std::string text;
diff --git a/test/opt/propagator_test.cpp b/test/opt/propagator_test.cpp
index fb8e487..76211a5 100644
--- a/test/opt/propagator_test.cpp
+++ b/test/opt/propagator_test.cpp
@@ -107,11 +107,11 @@
 
   const auto visit_fn = [this](Instruction* instr, BasicBlock** dest_bb) {
     *dest_bb = nullptr;
-    if (instr->opcode() == SpvOpStore) {
+    if (instr->opcode() == spv::Op::OpStore) {
       uint32_t lhs_id = instr->GetSingleWordOperand(0);
       uint32_t rhs_id = instr->GetSingleWordOperand(1);
       Instruction* rhs_def = ctx_->get_def_use_mgr()->GetDef(rhs_id);
-      if (rhs_def->opcode() == SpvOpConstant) {
+      if (rhs_def->opcode() == spv::Op::OpConstant) {
         uint32_t val = rhs_def->GetSingleWordOperand(2);
         values_[lhs_id] = val;
         return SSAPropagator::kInteresting;
@@ -175,15 +175,15 @@
   const auto visit_fn = [this, &phi_instr](Instruction* instr,
                                            BasicBlock** dest_bb) {
     *dest_bb = nullptr;
-    if (instr->opcode() == SpvOpLoad) {
+    if (instr->opcode() == spv::Op::OpLoad) {
       uint32_t rhs_id = instr->GetSingleWordOperand(2);
       Instruction* rhs_def = ctx_->get_def_use_mgr()->GetDef(rhs_id);
-      if (rhs_def->opcode() == SpvOpConstant) {
+      if (rhs_def->opcode() == spv::Op::OpConstant) {
         uint32_t val = rhs_def->GetSingleWordOperand(2);
         values_[instr->result_id()] = val;
         return SSAPropagator::kInteresting;
       }
-    } else if (instr->opcode() == SpvOpPhi) {
+    } else if (instr->opcode() == spv::Op::OpPhi) {
       phi_instr = instr;
       SSAPropagator::PropStatus retval;
       for (uint32_t i = 2; i < instr->NumOperands(); i += 2) {
diff --git a/test/opt/scalar_analysis.cpp b/test/opt/scalar_analysis.cpp
index df2aa8f..14f82af 100644
--- a/test/opt/scalar_analysis.cpp
+++ b/test/opt/scalar_analysis.cpp
@@ -109,10 +109,10 @@
   const Instruction* store = nullptr;
   const Instruction* load = nullptr;
   for (const Instruction& inst : *spvtest::GetBasicBlock(f, 11)) {
-    if (inst.opcode() == SpvOp::SpvOpStore) {
+    if (inst.opcode() == spv::Op::OpStore) {
       store = &inst;
     }
-    if (inst.opcode() == SpvOp::SpvOpLoad) {
+    if (inst.opcode() == spv::Op::OpLoad) {
       load = &inst;
     }
   }
@@ -236,7 +236,7 @@
 
   const Instruction* load = nullptr;
   for (const Instruction& inst : *spvtest::GetBasicBlock(f, 28)) {
-    if (inst.opcode() == SpvOp::SpvOpLoad) {
+    if (inst.opcode() == spv::Op::OpLoad) {
       load = &inst;
     }
   }
@@ -352,7 +352,7 @@
 
   const Instruction* load = nullptr;
   for (const Instruction& inst : *spvtest::GetBasicBlock(f, 21)) {
-    if (inst.opcode() == SpvOp::SpvOpLoad && inst.result_id() == 33) {
+    if (inst.opcode() == spv::Op::OpLoad && inst.result_id() == 33) {
       load = &inst;
     }
   }
@@ -506,11 +506,11 @@
   int store_count = 0;
 
   for (const Instruction& inst : *spvtest::GetBasicBlock(f, 22)) {
-    if (inst.opcode() == SpvOp::SpvOpLoad) {
+    if (inst.opcode() == spv::Op::OpLoad) {
       loads[load_count] = &inst;
       ++load_count;
     }
-    if (inst.opcode() == SpvOp::SpvOpStore) {
+    if (inst.opcode() == spv::Op::OpStore) {
       stores[store_count] = &inst;
       ++store_count;
     }
@@ -745,11 +745,11 @@
   int store_count = 0;
 
   for (const Instruction& inst : *spvtest::GetBasicBlock(f, 31)) {
-    if (inst.opcode() == SpvOp::SpvOpLoad) {
+    if (inst.opcode() == spv::Op::OpLoad) {
       loads[load_count] = &inst;
       ++load_count;
     }
-    if (inst.opcode() == SpvOp::SpvOpStore) {
+    if (inst.opcode() == spv::Op::OpStore) {
       stores[store_count] = &inst;
       ++store_count;
     }
@@ -880,7 +880,7 @@
   int load_count = 0;
 
   for (const Instruction& inst : *spvtest::GetBasicBlock(f, 29)) {
-    if (inst.opcode() == SpvOp::SpvOpLoad) {
+    if (inst.opcode() == spv::Op::OpLoad) {
       loads[load_count] = &inst;
       ++load_count;
     }
@@ -1025,10 +1025,10 @@
   std::vector<const Instruction*> stores{};
 
   for (const Instruction& inst : *spvtest::GetBasicBlock(f, 30)) {
-    if (inst.opcode() == SpvOp::SpvOpLoad) {
+    if (inst.opcode() == spv::Op::OpLoad) {
       loads.push_back(&inst);
     }
-    if (inst.opcode() == SpvOp::SpvOpStore) {
+    if (inst.opcode() == spv::Op::OpStore) {
       stores.push_back(&inst);
     }
   }
@@ -1194,7 +1194,7 @@
   std::vector<const Instruction*> phis{};
 
   for (const Instruction& inst : *spvtest::GetBasicBlock(f, 21)) {
-    if (inst.opcode() == SpvOp::SpvOpPhi) {
+    if (inst.opcode() == spv::Op::OpPhi) {
       phis.push_back(&inst);
     }
   }
diff --git a/test/opt/type_manager_test.cpp b/test/opt/type_manager_test.cpp
index df216bc..eebc50d 100644
--- a/test/opt/type_manager_test.cpp
+++ b/test/opt/type_manager_test.cpp
@@ -98,15 +98,19 @@
   types.emplace_back(new Matrix(v3f32, 4));
 
   // Images
-  types.emplace_back(new Image(s32, SpvDim2D, 0, 0, 0, 0, SpvImageFormatRg8,
-                               SpvAccessQualifierReadOnly));
+  types.emplace_back(new Image(s32, spv::Dim::Dim2D, 0, 0, 0, 0,
+                               spv::ImageFormat::Rg8,
+                               spv::AccessQualifier::ReadOnly));
   auto* image1 = types.back().get();
-  types.emplace_back(new Image(s32, SpvDim2D, 0, 1, 0, 0, SpvImageFormatRg8,
-                               SpvAccessQualifierReadOnly));
-  types.emplace_back(new Image(s32, SpvDim3D, 0, 1, 0, 0, SpvImageFormatRg8,
-                               SpvAccessQualifierReadOnly));
-  types.emplace_back(new Image(voidt, SpvDim3D, 0, 1, 0, 1, SpvImageFormatRg8,
-                               SpvAccessQualifierReadWrite));
+  types.emplace_back(new Image(s32, spv::Dim::Dim2D, 0, 1, 0, 0,
+                               spv::ImageFormat::Rg8,
+                               spv::AccessQualifier::ReadOnly));
+  types.emplace_back(new Image(s32, spv::Dim::Dim3D, 0, 1, 0, 0,
+                               spv::ImageFormat::Rg8,
+                               spv::AccessQualifier::ReadOnly));
+  types.emplace_back(new Image(voidt, spv::Dim::Dim3D, 0, 1, 0, 1,
+                               spv::ImageFormat::Rg8,
+                               spv::AccessQualifier::ReadWrite));
   auto* image2 = types.back().get();
 
   // Sampler
@@ -140,9 +144,9 @@
   types.emplace_back(new Opaque("world"));
 
   // Pointer
-  types.emplace_back(new Pointer(f32, SpvStorageClassInput));
-  types.emplace_back(new Pointer(sts32f32, SpvStorageClassFunction));
-  types.emplace_back(new Pointer(a42f32, SpvStorageClassFunction));
+  types.emplace_back(new Pointer(f32, spv::StorageClass::Input));
+  types.emplace_back(new Pointer(sts32f32, spv::StorageClass::Function));
+  types.emplace_back(new Pointer(a42f32, spv::StorageClass::Function));
 
   // Function
   types.emplace_back(new Function(voidt, {}));
@@ -158,11 +162,11 @@
 
   // Pipe, Forward Pointer, PipeStorage, NamedBarrier, AccelerationStructureNV,
   // CooperativeMatrixNV
-  types.emplace_back(new Pipe(SpvAccessQualifierReadWrite));
-  types.emplace_back(new Pipe(SpvAccessQualifierReadOnly));
-  types.emplace_back(new ForwardPointer(1, SpvStorageClassInput));
-  types.emplace_back(new ForwardPointer(2, SpvStorageClassInput));
-  types.emplace_back(new ForwardPointer(2, SpvStorageClassUniform));
+  types.emplace_back(new Pipe(spv::AccessQualifier::ReadWrite));
+  types.emplace_back(new Pipe(spv::AccessQualifier::ReadOnly));
+  types.emplace_back(new ForwardPointer(1, spv::StorageClass::Input));
+  types.emplace_back(new ForwardPointer(2, spv::StorageClass::Input));
+  types.emplace_back(new ForwardPointer(2, spv::StorageClass::Uniform));
   types.emplace_back(new PipeStorage());
   types.emplace_back(new NamedBarrier());
   types.emplace_back(new AccelerationStructureNV());
@@ -814,22 +818,22 @@
   EXPECT_NE(context, nullptr);
 
   Integer u32(32, false);
-  Pointer u32Ptr(&u32, SpvStorageClassFunction);
+  Pointer u32Ptr(&u32, spv::StorageClass::Function);
   Struct st({&u32});
-  Pointer stPtr(&st, SpvStorageClassInput);
+  Pointer stPtr(&st, spv::StorageClass::Input);
 
   auto pair = context->get_type_mgr()->GetTypeAndPointerType(
-      3u, SpvStorageClassFunction);
+      3u, spv::StorageClass::Function);
   ASSERT_EQ(nullptr, pair.first);
   ASSERT_EQ(nullptr, pair.second);
 
   pair = context->get_type_mgr()->GetTypeAndPointerType(
-      1u, SpvStorageClassFunction);
+      1u, spv::StorageClass::Function);
   ASSERT_TRUE(pair.first->IsSame(&u32));
   ASSERT_TRUE(pair.second->IsSame(&u32Ptr));
 
-  pair =
-      context->get_type_mgr()->GetTypeAndPointerType(2u, SpvStorageClassInput);
+  pair = context->get_type_mgr()->GetTypeAndPointerType(
+      2u, spv::StorageClass::Input);
   ASSERT_TRUE(pair.first->IsSame(&st));
   ASSERT_TRUE(pair.second->IsSame(&stPtr));
 }
@@ -1155,7 +1159,7 @@
                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   EXPECT_NE(context, nullptr);
 
-  context->get_type_mgr()->FindPointerToType(1, SpvStorageClassFunction);
+  context->get_type_mgr()->FindPointerToType(1, spv::StorageClass::Function);
   Match(text, context.get());
 }
 
@@ -1180,7 +1184,7 @@
                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   EXPECT_NE(context, nullptr);
 
-  context->get_type_mgr()->FindPointerToType(2, SpvStorageClassFunction);
+  context->get_type_mgr()->FindPointerToType(2, spv::StorageClass::Function);
   Match(text, context.get());
 }
 
diff --git a/test/opt/types_test.cpp b/test/opt/types_test.cpp
index 552ad97..4352b7c 100644
--- a/test/opt/types_test.cpp
+++ b/test/opt/types_test.cpp
@@ -34,9 +34,9 @@
     u32_t_ = MakeUnique<Integer>(32, false);
     f64_t_ = MakeUnique<Float>(64);
     v3u32_t_ = MakeUnique<Vector>(u32_t_.get(), 3);
-    image_t_ =
-        MakeUnique<Image>(f64_t_.get(), SpvDim2D, 1, 1, 0, 0, SpvImageFormatR16,
-                          SpvAccessQualifierReadWrite);
+    image_t_ = MakeUnique<Image>(f64_t_.get(), spv::Dim::Dim2D, 1, 1, 0, 0,
+                                 spv::ImageFormat::R16,
+                                 spv::AccessQualifier::ReadWrite);
   }
 
   // Element types to be used for constructing other types for testing.
@@ -72,9 +72,9 @@
 TestMultipleInstancesOfTheSameType(Float, 64)
 TestMultipleInstancesOfTheSameType(Vector, u32_t_.get(), 3)
 TestMultipleInstancesOfTheSameType(Matrix, v3u32_t_.get(), 4)
-TestMultipleInstancesOfTheSameType(Image, f64_t_.get(), SpvDimCube, 0, 0, 1, 1,
-                                   SpvImageFormatRgb10A2,
-                                   SpvAccessQualifierWriteOnly)
+TestMultipleInstancesOfTheSameType(Image, f64_t_.get(), spv::Dim::Cube, 0, 0, 1, 1,
+                                   spv::ImageFormat::Rgb10A2,
+                                   spv::AccessQualifier::WriteOnly)
 TestMultipleInstancesOfTheSameType(Sampler)
 TestMultipleInstancesOfTheSameType(SampledImage, image_t_.get())
 // There are three classes of arrays, based on the kinds of length information
@@ -98,15 +98,15 @@
 TestMultipleInstancesOfTheSameType(Struct, std::vector<const Type*>{
                                                u32_t_.get(), f64_t_.get()})
 TestMultipleInstancesOfTheSameType(Opaque, "testing rocks")
-TestMultipleInstancesOfTheSameType(Pointer, u32_t_.get(), SpvStorageClassInput)
+TestMultipleInstancesOfTheSameType(Pointer, u32_t_.get(), spv::StorageClass::Input)
 TestMultipleInstancesOfTheSameType(Function, u32_t_.get(),
                                    {f64_t_.get(), f64_t_.get()})
 TestMultipleInstancesOfTheSameType(Event)
 TestMultipleInstancesOfTheSameType(DeviceEvent)
 TestMultipleInstancesOfTheSameType(ReserveId)
 TestMultipleInstancesOfTheSameType(Queue)
-TestMultipleInstancesOfTheSameType(Pipe, SpvAccessQualifierReadWrite)
-TestMultipleInstancesOfTheSameType(ForwardPointer, 10, SpvStorageClassUniform)
+TestMultipleInstancesOfTheSameType(Pipe, spv::AccessQualifier::ReadWrite)
+TestMultipleInstancesOfTheSameType(ForwardPointer, 10, spv::StorageClass::Uniform)
 TestMultipleInstancesOfTheSameType(PipeStorage)
 TestMultipleInstancesOfTheSameType(NamedBarrier)
 TestMultipleInstancesOfTheSameType(AccelerationStructureNV)
@@ -119,8 +119,8 @@
   std::vector<std::unique_ptr<Type>> types;
 
   // Forward Pointer
-  types.emplace_back(new ForwardPointer(10000, SpvStorageClassInput));
-  types.emplace_back(new ForwardPointer(20000, SpvStorageClassInput));
+  types.emplace_back(new ForwardPointer(10000, spv::StorageClass::Input));
+  types.emplace_back(new ForwardPointer(20000, spv::StorageClass::Input));
 
   // Void, Bool
   types.emplace_back(new Void());
@@ -155,15 +155,19 @@
   types.emplace_back(new Matrix(v3f32, 4));
 
   // Images
-  types.emplace_back(new Image(s32, SpvDim2D, 0, 0, 0, 0, SpvImageFormatRg8,
-                               SpvAccessQualifierReadOnly));
+  types.emplace_back(new Image(s32, spv::Dim::Dim2D, 0, 0, 0, 0,
+                               spv::ImageFormat::Rg8,
+                               spv::AccessQualifier::ReadOnly));
   auto* image1 = types.back().get();
-  types.emplace_back(new Image(s32, SpvDim2D, 0, 1, 0, 0, SpvImageFormatRg8,
-                               SpvAccessQualifierReadOnly));
-  types.emplace_back(new Image(s32, SpvDim3D, 0, 1, 0, 0, SpvImageFormatRg8,
-                               SpvAccessQualifierReadOnly));
-  types.emplace_back(new Image(voidt, SpvDim3D, 0, 1, 0, 1, SpvImageFormatRg8,
-                               SpvAccessQualifierReadWrite));
+  types.emplace_back(new Image(s32, spv::Dim::Dim2D, 0, 1, 0, 0,
+                               spv::ImageFormat::Rg8,
+                               spv::AccessQualifier::ReadOnly));
+  types.emplace_back(new Image(s32, spv::Dim::Dim3D, 0, 1, 0, 0,
+                               spv::ImageFormat::Rg8,
+                               spv::AccessQualifier::ReadOnly));
+  types.emplace_back(new Image(voidt, spv::Dim::Dim3D, 0, 1, 0, 1,
+                               spv::ImageFormat::Rg8,
+                               spv::AccessQualifier::ReadWrite));
   auto* image2 = types.back().get();
 
   // Sampler
@@ -218,10 +222,10 @@
   types.emplace_back(new Opaque("world"));
 
   // Pointer
-  types.emplace_back(new Pointer(f32, SpvStorageClassInput));
-  types.emplace_back(new Pointer(sts32f32, SpvStorageClassFunction));
-  types.emplace_back(new Pointer(a42f32, SpvStorageClassFunction));
-  types.emplace_back(new Pointer(voidt, SpvStorageClassFunction));
+  types.emplace_back(new Pointer(f32, spv::StorageClass::Input));
+  types.emplace_back(new Pointer(sts32f32, spv::StorageClass::Function));
+  types.emplace_back(new Pointer(a42f32, spv::StorageClass::Function));
+  types.emplace_back(new Pointer(voidt, spv::StorageClass::Function));
 
   // Function
   types.emplace_back(new Function(voidt, {}));
@@ -236,11 +240,11 @@
   types.emplace_back(new Queue());
 
   // Pipe, Forward Pointer, PipeStorage, NamedBarrier
-  types.emplace_back(new Pipe(SpvAccessQualifierReadWrite));
-  types.emplace_back(new Pipe(SpvAccessQualifierReadOnly));
-  types.emplace_back(new ForwardPointer(1, SpvStorageClassInput));
-  types.emplace_back(new ForwardPointer(2, SpvStorageClassInput));
-  types.emplace_back(new ForwardPointer(2, SpvStorageClassUniform));
+  types.emplace_back(new Pipe(spv::AccessQualifier::ReadWrite));
+  types.emplace_back(new Pipe(spv::AccessQualifier::ReadOnly));
+  types.emplace_back(new ForwardPointer(1, spv::StorageClass::Input));
+  types.emplace_back(new ForwardPointer(2, spv::StorageClass::Input));
+  types.emplace_back(new ForwardPointer(2, spv::StorageClass::Uniform));
   types.emplace_back(new PipeStorage());
   types.emplace_back(new NamedBarrier());
 
diff --git a/test/reduce/reducer_test.cpp b/test/reduce/reducer_test.cpp
index 276aedc..019e14e 100644
--- a/test/reduce/reducer_test.cpp
+++ b/test/reduce/reducer_test.cpp
@@ -222,7 +222,7 @@
 }
 
 bool InterestingWhileOpcodeExists(const std::vector<uint32_t>& binary,
-                                  uint32_t opcode, uint32_t count, bool dump) {
+                                  spv::Op opcode, uint32_t count, bool dump) {
   if (dump) {
     std::stringstream ss;
     ss << "temp_" << count << ".spv";
@@ -238,7 +238,7 @@
         &*function.begin(),
         [opcode, &interesting](opt::BasicBlock* block) -> void {
           for (auto& inst : *block) {
-            if (inst.opcode() == opcode) {
+            if (inst.opcode() == spv::Op(opcode)) {
               interesting = true;
               break;
             }
@@ -253,12 +253,12 @@
 
 bool InterestingWhileIMulReachable(const std::vector<uint32_t>& binary,
                                    uint32_t count) {
-  return InterestingWhileOpcodeExists(binary, SpvOpIMul, count, false);
+  return InterestingWhileOpcodeExists(binary, spv::Op::OpIMul, count, false);
 }
 
 bool InterestingWhileSDivReachable(const std::vector<uint32_t>& binary,
                                    uint32_t count) {
-  return InterestingWhileOpcodeExists(binary, SpvOpSDiv, count, false);
+  return InterestingWhileOpcodeExists(binary, spv::Op::OpSDiv, count, false);
 }
 
 // The shader below was derived from the following GLSL, and optimized.
diff --git a/test/reduce/validation_during_reduction_test.cpp b/test/reduce/validation_during_reduction_test.cpp
index 04a4923..8cf14a3 100644
--- a/test/reduce/validation_during_reduction_test.cpp
+++ b/test/reduce/validation_during_reduction_test.cpp
@@ -67,7 +67,7 @@
 
   bool PreconditionHolds() override {
     Instruction* first_instruction = &*function_->begin()[0].begin();
-    return first_instruction->opcode() == SpvOpVariable;
+    return first_instruction->opcode() == spv::Op::OpVariable;
   }
 
  protected:
@@ -75,7 +75,7 @@
     // Duplicate the first OpVariable instruction.
 
     Instruction* first_instruction = &*function_->begin()[0].begin();
-    assert(first_instruction->opcode() == SpvOpVariable &&
+    assert(first_instruction->opcode() == spv::Op::OpVariable &&
            "Expected first instruction to be OpVariable");
     IRContext* context = first_instruction->context();
     Instruction* cloned_instruction = first_instruction->Clone(context);
@@ -105,7 +105,7 @@
     std::vector<std::unique_ptr<ReductionOpportunity>> result;
     for (auto& function : *context->module()) {
       Instruction* first_instruction = &*function.begin()[0].begin();
-      if (first_instruction->opcode() == SpvOpVariable) {
+      if (first_instruction->opcode() == spv::Op::OpVariable) {
         result.push_back(
             MakeUnique<OpVariableDuplicatorReductionOpportunity>(&function));
       }
diff --git a/test/text_to_binary.annotation_test.cpp b/test/text_to_binary.annotation_test.cpp
index 76776de..826812b 100644
--- a/test/text_to_binary.annotation_test.cpp
+++ b/test/text_to_binary.annotation_test.cpp
@@ -41,7 +41,7 @@
 
 using OpDecorateSimpleTest =
     spvtest::TextToBinaryTestBase<::testing::TestWithParam<
-        std::tuple<spv_target_env, EnumCase<SpvDecoration>>>>;
+        std::tuple<spv_target_env, EnumCase<spv::Decoration>>>>;
 
 TEST_P(OpDecorateSimpleTest, AnySimpleDecoration) {
   // This string should assemble, but should not validate.
@@ -51,7 +51,7 @@
     input << " " << operand;
   input << std::endl;
   EXPECT_THAT(CompiledInstructions(input.str(), std::get<0>(GetParam())),
-              Eq(MakeInstruction(SpvOpDecorate,
+              Eq(MakeInstruction(spv::Op::OpDecorate,
                                  {1, uint32_t(std::get<1>(GetParam()).value())},
                                  std::get<1>(GetParam()).operands())));
   // Also check disassembly.
@@ -64,7 +64,7 @@
 // Like above, but parameters to the decoration are IDs.
 using OpDecorateSimpleIdTest =
     spvtest::TextToBinaryTestBase<::testing::TestWithParam<
-        std::tuple<spv_target_env, EnumCase<SpvDecoration>>>>;
+        std::tuple<spv_target_env, EnumCase<spv::Decoration>>>>;
 
 TEST_P(OpDecorateSimpleIdTest, AnySimpleDecoration) {
   // This string should assemble, but should not validate.
@@ -74,7 +74,7 @@
     input << " %" << operand;
   input << std::endl;
   EXPECT_THAT(CompiledInstructions(input.str(), std::get<0>(GetParam())),
-              Eq(MakeInstruction(SpvOpDecorateId,
+              Eq(MakeInstruction(spv::Op::OpDecorateId,
                                  {1, uint32_t(std::get<1>(GetParam()).value())},
                                  std::get<1>(GetParam()).operands())));
   // Also check disassembly.
@@ -84,11 +84,11 @@
       Eq(input.str()));
 }
 
-#define CASE(NAME) SpvDecoration##NAME, #NAME
+#define CASE(NAME) spv::Decoration::NAME, #NAME
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryDecorateSimple, OpDecorateSimpleTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
-            ValuesIn(std::vector<EnumCase<SpvDecoration>>{
+            ValuesIn(std::vector<EnumCase<spv::Decoration>>{
                 // The operand literal values are arbitrarily chosen,
                 // but there are the right number of them.
                 {CASE(RelaxedPrecision), {}},
@@ -134,23 +134,24 @@
 
 INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateSimpleV11, OpDecorateSimpleTest,
                          Combine(Values(SPV_ENV_UNIVERSAL_1_1),
-                                 Values(EnumCase<SpvDecoration>{
+                                 Values(EnumCase<spv::Decoration>{
                                      CASE(MaxByteOffset), {128}})));
 
-INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateSimpleV14, OpDecorateSimpleTest,
-                         Combine(Values(SPV_ENV_UNIVERSAL_1_4),
-                                 ValuesIn(std::vector<EnumCase<SpvDecoration>>{
-                                     {CASE(Uniform), {}},
-                                 })));
+INSTANTIATE_TEST_SUITE_P(
+    TextToBinaryDecorateSimpleV14, OpDecorateSimpleTest,
+    Combine(Values(SPV_ENV_UNIVERSAL_1_4),
+            ValuesIn(std::vector<EnumCase<spv::Decoration>>{
+                {CASE(Uniform), {}},
+            })));
 
-INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateSimpleIdV14,
-                         OpDecorateSimpleIdTest,
-                         Combine(Values(SPV_ENV_UNIVERSAL_1_4),
-                                 ValuesIn(std::vector<EnumCase<SpvDecoration>>{
-                                     // In 1.4, UniformId decoration takes a
-                                     // scope Id.
-                                     {CASE(UniformId), {1}},
-                                 })));
+INSTANTIATE_TEST_SUITE_P(
+    TextToBinaryDecorateSimpleIdV14, OpDecorateSimpleIdTest,
+    Combine(Values(SPV_ENV_UNIVERSAL_1_4),
+            ValuesIn(std::vector<EnumCase<spv::Decoration>>{
+                // In 1.4, UniformId decoration takes a
+                // scope Id.
+                {CASE(UniformId), {1}},
+            })));
 #undef CASE
 
 TEST_F(OpDecorateSimpleTest, WrongDecoration) {
@@ -195,14 +196,14 @@
   const std::string input =
       "OpDecorate %1 " + GetParam().enum_name + " " + GetParam().name;
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpDecorate, {1, GetParam().enum_value,
-                                                 GetParam().value})));
+              Eq(MakeInstruction(spv::Op::OpDecorate, {1, GetParam().enum_value,
+                                                       GetParam().value})));
 }
 
 // Test OpDecorate BuiltIn.
 // clang-format off
 #define CASE(NAME) \
-  { SpvBuiltIn##NAME, #NAME, SpvDecorationBuiltIn, "BuiltIn" }
+  { uint32_t(spv::BuiltIn::NAME), #NAME, uint32_t(spv::Decoration::BuiltIn), "BuiltIn" }
 INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateBuiltIn, OpDecorateEnumTest,
                         ::testing::ValuesIn(std::vector<DecorateEnumCase>{
                             CASE(Position),
@@ -260,7 +261,7 @@
 // Test OpDecorate FuncParamAttr
 // clang-format off
 #define CASE(NAME) \
-  { SpvFunctionParameterAttribute##NAME, #NAME, SpvDecorationFuncParamAttr, "FuncParamAttr" }
+  { uint32_t(spv::FunctionParameterAttribute::NAME), #NAME, uint32_t(spv::Decoration::FuncParamAttr), "FuncParamAttr" }
 INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateFuncParamAttr, OpDecorateEnumTest,
                         ::testing::ValuesIn(std::vector<DecorateEnumCase>{
                             CASE(Zext),
@@ -283,7 +284,7 @@
 // Test OpDecorate FPRoundingMode
 // clang-format off
 #define CASE(NAME) \
-  { SpvFPRoundingMode##NAME, #NAME, SpvDecorationFPRoundingMode, "FPRoundingMode" }
+  { uint32_t(spv::FPRoundingMode::NAME), #NAME, uint32_t(spv::Decoration::FPRoundingMode), "FPRoundingMode" }
 INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateFPRoundingMode, OpDecorateEnumTest,
                         ::testing::ValuesIn(std::vector<DecorateEnumCase>{
                             CASE(RTE),
@@ -306,15 +307,15 @@
 
 // clang-format off
 #define CASE(ENUM,NAME) \
-  { SpvFPFastMathMode##ENUM, #NAME, SpvDecorationFPFastMathMode, "FPFastMathMode" }
+  { uint32_t(spv::FPFastMathModeMask::ENUM), #NAME, uint32_t(spv::Decoration::FPFastMathMode), "FPFastMathMode" }
 INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateFPFastMathMode, OpDecorateEnumTest,
                         ::testing::ValuesIn(std::vector<DecorateEnumCase>{
                             CASE(MaskNone, None),
-                            CASE(NotNaNMask, NotNaN),
-                            CASE(NotInfMask, NotInf),
-                            CASE(NSZMask, NSZ),
-                            CASE(AllowRecipMask, AllowRecip),
-                            CASE(FastMask, Fast),
+                            CASE(NotNaN, NotNaN),
+                            CASE(NotInf, NotInf),
+                            CASE(NSZ, NSZ),
+                            CASE(AllowRecip, AllowRecip),
+                            CASE(Fast, Fast),
                       }));
 #undef CASE
 // clang-format on
@@ -323,13 +324,13 @@
   // Sample a single combination.  This ensures we've integrated
   // the instruction parsing logic with spvTextParseMask.
   const std::string input = "OpDecorate %1 FPFastMathMode NotNaN|NotInf|NSZ";
-  const uint32_t expected_enum = SpvDecorationFPFastMathMode;
-  const uint32_t expected_mask = SpvFPFastMathModeNotNaNMask |
-                                 SpvFPFastMathModeNotInfMask |
-                                 SpvFPFastMathModeNSZMask;
-  EXPECT_THAT(
-      CompiledInstructions(input),
-      Eq(MakeInstruction(SpvOpDecorate, {1, expected_enum, expected_mask})));
+  const uint32_t expected_enum = uint32_t(spv::Decoration::FPFastMathMode);
+  const uint32_t expected_mask = uint32_t(spv::FPFastMathModeMask::NotNaN) |
+                                 uint32_t(spv::FPFastMathModeMask::NotInf) |
+                                 uint32_t(spv::FPFastMathModeMask::NSZ);
+  EXPECT_THAT(CompiledInstructions(input),
+              Eq(MakeInstruction(spv::Op::OpDecorate,
+                                 {1, expected_enum, expected_mask})));
 }
 
 TEST_F(OpDecorateEnumTest, WrongFPFastMathMode) {
@@ -355,7 +356,8 @@
   const std::string input = "OpDecorate %1 LinkageAttributes \"" +
                             GetParam().external_name + "\" " +
                             GetParam().linkage_type_name;
-  std::vector<uint32_t> expected_operands{1, SpvDecorationLinkageAttributes};
+  std::vector<uint32_t> expected_operands{
+      1, uint32_t(spv::Decoration::LinkageAttributes)};
   std::vector<uint32_t> encoded_external_name =
       MakeVector(GetParam().external_name);
   expected_operands.insert(expected_operands.end(),
@@ -363,11 +365,11 @@
                            encoded_external_name.end());
   expected_operands.push_back(GetParam().linkage_type_value);
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpDecorate, expected_operands)));
+              Eq(MakeInstruction(spv::Op::OpDecorate, expected_operands)));
 }
 
 // clang-format off
-#define CASE(ENUM) SpvLinkageType##ENUM, #ENUM
+#define CASE(ENUM) uint32_t(spv::LinkageType::ENUM), #ENUM
 INSTANTIATE_TEST_SUITE_P(TextToBinaryDecorateLinkage, OpDecorateLinkageTest,
                         ::testing::ValuesIn(std::vector<DecorateLinkageCase>{
                             { CASE(Import), "a" },
@@ -387,13 +389,13 @@
 
 TEST_F(TextToBinaryTest, GroupMemberDecorateGoodOneTarget) {
   EXPECT_THAT(CompiledInstructions("OpGroupMemberDecorate %group %id0 42"),
-              Eq(MakeInstruction(SpvOpGroupMemberDecorate, {1, 2, 42})));
+              Eq(MakeInstruction(spv::Op::OpGroupMemberDecorate, {1, 2, 42})));
 }
 
 TEST_F(TextToBinaryTest, GroupMemberDecorateGoodTwoTargets) {
   EXPECT_THAT(
       CompiledInstructions("OpGroupMemberDecorate %group %id0 96 %id1 42"),
-      Eq(MakeInstruction(SpvOpGroupMemberDecorate, {1, 2, 96, 3, 42})));
+      Eq(MakeInstruction(spv::Op::OpGroupMemberDecorate, {1, 2, 96, 3, 42})));
 }
 
 TEST_F(TextToBinaryTest, GroupMemberDecorateMissingGroupId) {
@@ -443,7 +445,7 @@
 
 using OpMemberDecorateSimpleTest =
     spvtest::TextToBinaryTestBase<::testing::TestWithParam<
-        std::tuple<spv_target_env, EnumCase<SpvDecoration>>>>;
+        std::tuple<spv_target_env, EnumCase<spv::Decoration>>>>;
 
 TEST_P(OpMemberDecorateSimpleTest, AnySimpleDecoration) {
   // This string should assemble, but should not validate.
@@ -454,7 +456,7 @@
   input << std::endl;
   EXPECT_THAT(
       CompiledInstructions(input.str(), std::get<0>(GetParam())),
-      Eq(MakeInstruction(SpvOpMemberDecorate,
+      Eq(MakeInstruction(spv::Op::OpMemberDecorate,
                          {1, 42, uint32_t(std::get<1>(GetParam()).value())},
                          std::get<1>(GetParam()).operands())));
   // Also check disassembly.
@@ -464,11 +466,11 @@
       Eq(input.str()));
 }
 
-#define CASE(NAME) SpvDecoration##NAME, #NAME
+#define CASE(NAME) spv::Decoration::NAME, #NAME
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryDecorateSimple, OpMemberDecorateSimpleTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
-            ValuesIn(std::vector<EnumCase<SpvDecoration>>{
+            ValuesIn(std::vector<EnumCase<spv::Decoration>>{
                 // The operand literal values are arbitrarily chosen,
                 // but there are the right number of them.
                 {CASE(RelaxedPrecision), {}},
@@ -515,7 +517,7 @@
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryDecorateSimpleV11, OpMemberDecorateSimpleTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_1),
-            Values(EnumCase<SpvDecoration>{CASE(MaxByteOffset), {128}})));
+            Values(EnumCase<spv::Decoration>{CASE(MaxByteOffset), {128}})));
 #undef CASE
 
 TEST_F(OpMemberDecorateSimpleTest, WrongDecoration) {
diff --git a/test/text_to_binary.barrier_test.cpp b/test/text_to_binary.barrier_test.cpp
index f1cb4fb..380cacb 100644
--- a/test/text_to_binary.barrier_test.cpp
+++ b/test/text_to_binary.barrier_test.cpp
@@ -37,7 +37,7 @@
 TEST_F(OpMemoryBarrier, Good) {
   const std::string input = "OpMemoryBarrier %1 %2\n";
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpMemoryBarrier, {1, 2})));
+              Eq(MakeInstruction(spv::Op::OpMemoryBarrier, {1, 2})));
   EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(input));
 }
 
@@ -89,7 +89,7 @@
   EXPECT_THAT(
       CompiledInstructions("OpMemoryNamedBarrier %bar %scope %semantics",
                            SPV_ENV_UNIVERSAL_1_0),
-      ElementsAre(spvOpcodeMake(4, SpvOpMemoryNamedBarrier), _, _, _));
+      ElementsAre(spvOpcodeMake(4, spv::Op::OpMemoryNamedBarrier), _, _, _));
 }
 
 TEST_F(NamedMemoryBarrierTest, ArgumentCount) {
@@ -107,7 +107,7 @@
   EXPECT_THAT(
       CompiledInstructions("OpMemoryNamedBarrier %bar %scope %semantics",
                            SPV_ENV_UNIVERSAL_1_1),
-      ElementsAre(spvOpcodeMake(4, SpvOpMemoryNamedBarrier), _, _, _));
+      ElementsAre(spvOpcodeMake(4, spv::Op::OpMemoryNamedBarrier), _, _, _));
   EXPECT_THAT(
       CompileFailure("OpMemoryNamedBarrier %bar %scope %semantics %extra",
                      SPV_ENV_UNIVERSAL_1_1),
@@ -128,7 +128,7 @@
 TEST_F(TypeNamedBarrierTest, OpcodeAssemblesInV10) {
   EXPECT_THAT(
       CompiledInstructions("%t = OpTypeNamedBarrier", SPV_ENV_UNIVERSAL_1_0),
-      ElementsAre(spvOpcodeMake(2, SpvOpTypeNamedBarrier), _));
+      ElementsAre(spvOpcodeMake(2, spv::Op::OpTypeNamedBarrier), _));
 }
 
 TEST_F(TypeNamedBarrierTest, ArgumentCount) {
@@ -137,7 +137,7 @@
                  "found 'OpTypeNamedBarrier'."));
   EXPECT_THAT(
       CompiledInstructions("%t = OpTypeNamedBarrier", SPV_ENV_UNIVERSAL_1_1),
-      ElementsAre(spvOpcodeMake(2, SpvOpTypeNamedBarrier), _));
+      ElementsAre(spvOpcodeMake(2, spv::Op::OpTypeNamedBarrier), _));
   EXPECT_THAT(
       CompileFailure("%t = OpTypeNamedBarrier 1 2 3", SPV_ENV_UNIVERSAL_1_1),
       Eq("Expected <opcode> or <result-id> at the beginning of an instruction, "
@@ -150,7 +150,8 @@
   EXPECT_THAT(
       CompiledInstructions("%bar = OpNamedBarrierInitialize %type %count",
                            SPV_ENV_UNIVERSAL_1_0),
-      ElementsAre(spvOpcodeMake(4, SpvOpNamedBarrierInitialize), _, _, _));
+      ElementsAre(spvOpcodeMake(4, spv::Op::OpNamedBarrierInitialize), _, _,
+                  _));
 }
 
 TEST_F(NamedBarrierInitializeTest, ArgumentCount) {
@@ -165,7 +166,8 @@
   EXPECT_THAT(
       CompiledInstructions("%bar = OpNamedBarrierInitialize %type %count",
                            SPV_ENV_UNIVERSAL_1_1),
-      ElementsAre(spvOpcodeMake(4, SpvOpNamedBarrierInitialize), _, _, _));
+      ElementsAre(spvOpcodeMake(4, spv::Op::OpNamedBarrierInitialize), _, _,
+                  _));
   EXPECT_THAT(
       CompileFailure("%bar = OpNamedBarrierInitialize %type %count \"extra\"",
                      SPV_ENV_UNIVERSAL_1_1),
diff --git a/test/text_to_binary.constant_test.cpp b/test/text_to_binary.constant_test.cpp
index 7ab4ca5..bc5cd06 100644
--- a/test/text_to_binary.constant_test.cpp
+++ b/test/text_to_binary.constant_test.cpp
@@ -35,21 +35,21 @@
 // Test Sampler Addressing Mode enum values
 
 using SamplerAddressingModeTest = spvtest::TextToBinaryTestBase<
-    ::testing::TestWithParam<EnumCase<SpvSamplerAddressingMode>>>;
+    ::testing::TestWithParam<EnumCase<spv::SamplerAddressingMode>>>;
 
 TEST_P(SamplerAddressingModeTest, AnySamplerAddressingMode) {
   const std::string input =
       "%result = OpConstantSampler %type " + GetParam().name() + " 0 Nearest";
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpConstantSampler,
-                                 {1, 2, GetParam().value(), 0, 0})));
+              Eq(MakeInstruction(spv::Op::OpConstantSampler,
+                                 {1, 2, uint32_t(GetParam().value()), 0, 0})));
 }
 
 // clang-format off
-#define CASE(NAME) { SpvSamplerAddressingMode##NAME, #NAME }
+#define CASE(NAME) { spv::SamplerAddressingMode::NAME, #NAME }
 INSTANTIATE_TEST_SUITE_P(
     TextToBinarySamplerAddressingMode, SamplerAddressingModeTest,
-    ::testing::ValuesIn(std::vector<EnumCase<SpvSamplerAddressingMode>>{
+    ::testing::ValuesIn(std::vector<EnumCase<spv::SamplerAddressingMode>>{
         CASE(None),
         CASE(ClampToEdge),
         CASE(Clamp),
@@ -67,21 +67,21 @@
 // Test Sampler Filter Mode enum values
 
 using SamplerFilterModeTest = spvtest::TextToBinaryTestBase<
-    ::testing::TestWithParam<EnumCase<SpvSamplerFilterMode>>>;
+    ::testing::TestWithParam<EnumCase<spv::SamplerFilterMode>>>;
 
 TEST_P(SamplerFilterModeTest, AnySamplerFilterMode) {
   const std::string input =
       "%result = OpConstantSampler %type Clamp 0 " + GetParam().name();
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpConstantSampler,
-                                 {1, 2, 2, 0, GetParam().value()})));
+              Eq(MakeInstruction(spv::Op::OpConstantSampler,
+                                 {1, 2, 2, 0, uint32_t(GetParam().value())})));
 }
 
 // clang-format off
-#define CASE(NAME) { SpvSamplerFilterMode##NAME, #NAME}
+#define CASE(NAME) { spv::SamplerFilterMode::NAME, #NAME}
 INSTANTIATE_TEST_SUITE_P(
     TextToBinarySamplerFilterMode, SamplerFilterModeTest,
-    ::testing::ValuesIn(std::vector<EnumCase<SpvSamplerFilterMode>>{
+    ::testing::ValuesIn(std::vector<EnumCase<spv::SamplerFilterMode>>{
         CASE(Nearest),
         CASE(Linear),
     }));
@@ -119,119 +119,119 @@
     ::testing::ValuesIn(std::vector<ConstantTestCase>{
       // Check 16 bits
       {"OpTypeInt 16 0", "0x1234",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0x1234})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 0}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x1234})})},
       {"OpTypeInt 16 0", "0x8000",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0x8000})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 0}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x8000})})},
       {"OpTypeInt 16 0", "0",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 0}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0})})},
       {"OpTypeInt 16 0", "65535",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}),
-         MakeInstruction(SpvOpConstant, {1, 2, 65535})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 0}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 65535})})},
       {"OpTypeInt 16 0", "0xffff",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}),
-         MakeInstruction(SpvOpConstant, {1, 2, 65535})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 0}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 65535})})},
       {"OpTypeInt 16 1", "0x8000", // Test sign extension.
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0xffff8000})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0xffff8000})})},
       {"OpTypeInt 16 1", "-32",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-32)})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, uint32_t(-32)})})},
       {"OpTypeInt 16 1", "0",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0})})},
       {"OpTypeInt 16 1", "-0",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0})})},
       {"OpTypeInt 16 1", "-0x0",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0})})},
       {"OpTypeInt 16 1", "-32768",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-32768)})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, uint32_t(-32768)})})},
       // Check 32 bits
       {"OpTypeInt 32 0", "42",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 0}),
-         MakeInstruction(SpvOpConstant, {1, 2, 42})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 0}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 42})})},
       {"OpTypeInt 32 1", "-32",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-32)})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, uint32_t(-32)})})},
       {"OpTypeInt 32 1", "0",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0})})},
       {"OpTypeInt 32 1", "-0",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0})})},
       {"OpTypeInt 32 1", "-0x0",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0})})},
       {"OpTypeInt 32 1", "-0x001",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-1)})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, uint32_t(-1)})})},
       {"OpTypeInt 32 1", "2147483647",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0x7fffffffu})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x7fffffffu})})},
       {"OpTypeInt 32 1", "-2147483648",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0x80000000u})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x80000000u})})},
       {"OpTypeFloat 32", "1.0",
-        Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0x3f800000})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x3f800000})})},
       {"OpTypeFloat 32", "10.0",
-        Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0x41200000})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x41200000})})},
       {"OpTypeFloat 32", "-0x1p+128", // -infinity
-        Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0xFF800000})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0xFF800000})})},
       {"OpTypeFloat 32", "0x1p+128", // +infinity
-        Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0x7F800000})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x7F800000})})},
       {"OpTypeFloat 32", "-0x1.8p+128", // A -NaN
-        Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0xFFC00000})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0xFFC00000})})},
       {"OpTypeFloat 32", "-0x1.0002p+128", // A +NaN
-        Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0xFF800100})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0xFF800100})})},
       // Check 48 bits
       {"OpTypeInt 48 0", "0x1234",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 0}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0x1234, 0})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 0}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x1234, 0})})},
       {"OpTypeInt 48 0", "0x800000000001",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 0}),
-         MakeInstruction(SpvOpConstant, {1, 2, 1, 0x00008000})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 0}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 1, 0x00008000})})},
       {"OpTypeInt 48 1", "0x800000000000", // Test sign extension.
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0, 0xffff8000})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0, 0xffff8000})})},
       {"OpTypeInt 48 1", "-32",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-32), uint32_t(-1)})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, uint32_t(-32), uint32_t(-1)})})},
       // Check 64 bits
       {"OpTypeInt 64 0", "0x1234",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 0}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0x1234, 0})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 0}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x1234, 0})})},
       {"OpTypeInt 64 0", "18446744073709551615",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 0}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0xffffffffu, 0xffffffffu})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 0}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0xffffffffu, 0xffffffffu})})},
       {"OpTypeInt 64 0", "0xffffffffffffffff",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 0}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0xffffffffu, 0xffffffffu})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 0}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0xffffffffu, 0xffffffffu})})},
       {"OpTypeInt 64 1", "0x1234",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0x1234, 0})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x1234, 0})})},
       {"OpTypeInt 64 1", "-42",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, uint32_t(-42), uint32_t(-1)})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, uint32_t(-42), uint32_t(-1)})})},
       {"OpTypeInt 64 1", "-0x01",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0xffffffffu, 0xffffffffu})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0xffffffffu, 0xffffffffu})})},
       {"OpTypeInt 64 1", "9223372036854775807",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0xffffffffu, 0x7fffffffu})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0xffffffffu, 0x7fffffffu})})},
       {"OpTypeInt 64 1", "0x7fffffff",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}),
-         MakeInstruction(SpvOpConstant, {1, 2, 0x7fffffffu, 0})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 1}),
+         MakeInstruction(spv::Op::OpConstant, {1, 2, 0x7fffffffu, 0})})},
     }));
 // clang-format on
 
@@ -388,53 +388,53 @@
     ::testing::ValuesIn(std::vector<ConstantTestCase>{
       // Check 16 bits
       {"OpTypeInt 16 0", "0x1234",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}),
-         MakeInstruction(SpvOpSpecConstant, {1, 2, 0x1234})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 0}),
+         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0x1234})})},
       {"OpTypeInt 16 0", "0x8000",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 0}),
-         MakeInstruction(SpvOpSpecConstant, {1, 2, 0x8000})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 0}),
+         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0x8000})})},
       {"OpTypeInt 16 1", "0x8000", // Test sign extension.
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}),
-         MakeInstruction(SpvOpSpecConstant, {1, 2, 0xffff8000})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
+         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0xffff8000})})},
       {"OpTypeInt 16 1", "-32",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 16, 1}),
-         MakeInstruction(SpvOpSpecConstant, {1, 2, uint32_t(-32)})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 16, 1}),
+         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, uint32_t(-32)})})},
       // Check 32 bits
       {"OpTypeInt 32 0", "42",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 0}),
-         MakeInstruction(SpvOpSpecConstant, {1, 2, 42})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 0}),
+         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 42})})},
       {"OpTypeInt 32 1", "-32",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
-         MakeInstruction(SpvOpSpecConstant, {1, 2, uint32_t(-32)})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
+         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, uint32_t(-32)})})},
       {"OpTypeFloat 32", "1.0",
-        Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}),
-         MakeInstruction(SpvOpSpecConstant, {1, 2, 0x3f800000})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
+         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0x3f800000})})},
       {"OpTypeFloat 32", "10.0",
-        Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}),
-         MakeInstruction(SpvOpSpecConstant, {1, 2, 0x41200000})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
+         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0x41200000})})},
       // Check 48 bits
       {"OpTypeInt 48 0", "0x1234",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 0}),
-         MakeInstruction(SpvOpSpecConstant, {1, 2, 0x1234, 0})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 0}),
+         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0x1234, 0})})},
       {"OpTypeInt 48 0", "0x800000000001",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 0}),
-         MakeInstruction(SpvOpSpecConstant, {1, 2, 1, 0x00008000})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 0}),
+         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 1, 0x00008000})})},
       {"OpTypeInt 48 1", "0x800000000000", // Test sign extension.
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 1}),
-         MakeInstruction(SpvOpSpecConstant, {1, 2, 0, 0xffff8000})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 1}),
+         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0, 0xffff8000})})},
       {"OpTypeInt 48 1", "-32",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 48, 1}),
-         MakeInstruction(SpvOpSpecConstant, {1, 2, uint32_t(-32), uint32_t(-1)})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 48, 1}),
+         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, uint32_t(-32), uint32_t(-1)})})},
       // Check 64 bits
       {"OpTypeInt 64 0", "0x1234",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 0}),
-         MakeInstruction(SpvOpSpecConstant, {1, 2, 0x1234, 0})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 0}),
+         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0x1234, 0})})},
       {"OpTypeInt 64 1", "0x1234",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}),
-         MakeInstruction(SpvOpSpecConstant, {1, 2, 0x1234, 0})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 1}),
+         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, 0x1234, 0})})},
       {"OpTypeInt 64 1", "-42",
-        Concatenate({MakeInstruction(SpvOpTypeInt, {1, 64, 1}),
-         MakeInstruction(SpvOpSpecConstant, {1, 2, uint32_t(-42), uint32_t(-1)})})},
+        Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 64, 1}),
+         MakeInstruction(spv::Op::OpSpecConstant, {1, 2, uint32_t(-42), uint32_t(-1)})})},
     }));
 // clang-format on
 
@@ -648,7 +648,7 @@
 // Test OpSpecConstantOp
 
 using OpSpecConstantOpTestWithIds =
-    spvtest::TextToBinaryTestBase<::testing::TestWithParam<EnumCase<SpvOp>>>;
+    spvtest::TextToBinaryTestBase<::testing::TestWithParam<EnumCase<spv::Op>>>;
 
 // The operands to the OpSpecConstantOp opcode are all Ids.
 TEST_P(OpSpecConstantOpTestWithIds, Assembly) {
@@ -658,7 +658,7 @@
   input << "\n";
 
   EXPECT_THAT(CompiledInstructions(input.str()),
-              Eq(MakeInstruction(SpvOpSpecConstantOp,
+              Eq(MakeInstruction(spv::Op::OpSpecConstantOp,
                                  {1, 2, uint32_t(GetParam().value())},
                                  GetParam().operands())));
 
@@ -667,15 +667,15 @@
 }
 
 // clang-format off
-#define CASE1(NAME) { SpvOp##NAME, #NAME, {3} }
-#define CASE2(NAME) { SpvOp##NAME, #NAME, {3, 4} }
-#define CASE3(NAME) { SpvOp##NAME, #NAME, {3, 4, 5} }
-#define CASE4(NAME) { SpvOp##NAME, #NAME, {3, 4, 5, 6} }
-#define CASE5(NAME) { SpvOp##NAME, #NAME, {3, 4, 5, 6, 7} }
-#define CASE6(NAME) { SpvOp##NAME, #NAME, {3, 4, 5, 6, 7, 8} }
+#define CASE1(NAME) { spv::Op::Op##NAME, #NAME, {3} }
+#define CASE2(NAME) { spv::Op::Op##NAME, #NAME, {3, 4} }
+#define CASE3(NAME) { spv::Op::Op##NAME, #NAME, {3, 4, 5} }
+#define CASE4(NAME) { spv::Op::Op##NAME, #NAME, {3, 4, 5, 6} }
+#define CASE5(NAME) { spv::Op::Op##NAME, #NAME, {3, 4, 5, 6, 7} }
+#define CASE6(NAME) { spv::Op::Op##NAME, #NAME, {3, 4, 5, 6, 7, 8} }
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryOpSpecConstantOp, OpSpecConstantOpTestWithIds,
-    ::testing::ValuesIn(std::vector<EnumCase<SpvOp>>{
+    ::testing::ValuesIn(std::vector<EnumCase<spv::Op>>{
         // Conversion
         CASE1(SConvert),
         CASE1(FConvert),
@@ -759,7 +759,7 @@
 // clang-format on
 
 using OpSpecConstantOpTestWithTwoIdsThenLiteralNumbers =
-    spvtest::TextToBinaryTestBase<::testing::TestWithParam<EnumCase<SpvOp>>>;
+    spvtest::TextToBinaryTestBase<::testing::TestWithParam<EnumCase<spv::Op>>>;
 
 // The operands to the OpSpecConstantOp opcode are two Ids followed by a
 // sequence of literal numbers.
@@ -770,7 +770,7 @@
   input << "\n";
 
   EXPECT_THAT(CompiledInstructions(input.str()),
-              Eq(MakeInstruction(SpvOpSpecConstantOp,
+              Eq(MakeInstruction(spv::Op::OpSpecConstantOp,
                                  {1, 2, uint32_t(GetParam().value()), 3, 4},
                                  GetParam().operands())));
 
@@ -778,11 +778,11 @@
   EXPECT_THAT(EncodeAndDecodeSuccessfully(input.str()), input.str());
 }
 
-#define CASE(NAME) SpvOp##NAME, #NAME
+#define CASE(NAME) spv::Op::Op##NAME, #NAME
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryOpSpecConstantOp,
     OpSpecConstantOpTestWithTwoIdsThenLiteralNumbers,
-    ::testing::ValuesIn(std::vector<EnumCase<SpvOp>>{
+    ::testing::ValuesIn(std::vector<EnumCase<spv::Op>>{
         // For VectorShuffle, there are two vector operands, and at least
         // two selector Ids.  OpenCL can have up to 16-element vectors.
         {CASE(VectorShuffle), {0, 0}},
@@ -797,7 +797,7 @@
     }));
 
 using OpSpecConstantOpTestWithOneIdThenLiteralNumbers =
-    spvtest::TextToBinaryTestBase<::testing::TestWithParam<EnumCase<SpvOp>>>;
+    spvtest::TextToBinaryTestBase<::testing::TestWithParam<EnumCase<spv::Op>>>;
 
 // The operands to the OpSpecConstantOp opcode are one Id followed by a
 // sequence of literal numbers.
@@ -808,7 +808,7 @@
   input << "\n";
 
   EXPECT_THAT(CompiledInstructions(input.str()),
-              Eq(MakeInstruction(SpvOpSpecConstantOp,
+              Eq(MakeInstruction(spv::Op::OpSpecConstantOp,
                                  {1, 2, uint32_t(GetParam().value()), 3},
                                  GetParam().operands())));
 
@@ -816,11 +816,11 @@
   EXPECT_THAT(EncodeAndDecodeSuccessfully(input.str()), input.str());
 }
 
-#define CASE(NAME) SpvOp##NAME, #NAME
+#define CASE(NAME) spv::Op::Op##NAME, #NAME
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryOpSpecConstantOp,
     OpSpecConstantOpTestWithOneIdThenLiteralNumbers,
-    ::testing::ValuesIn(std::vector<EnumCase<SpvOp>>{
+    ::testing::ValuesIn(std::vector<EnumCase<spv::Op>>{
         // For CompositeExtract, the universal limit permits up to 255 literal
         // indices.  Let's only test a few.
         {CASE(CompositeExtract), {0}},
diff --git a/test/text_to_binary.control_flow_test.cpp b/test/text_to_binary.control_flow_test.cpp
index 472cb6d..bc64aa3 100644
--- a/test/text_to_binary.control_flow_test.cpp
+++ b/test/text_to_binary.control_flow_test.cpp
@@ -40,22 +40,22 @@
 // Test OpSelectionMerge
 
 using OpSelectionMergeTest = spvtest::TextToBinaryTestBase<
-    TestWithParam<EnumCase<SpvSelectionControlMask>>>;
+    TestWithParam<EnumCase<spv::SelectionControlMask>>>;
 
 TEST_P(OpSelectionMergeTest, AnySingleSelectionControlMask) {
   const std::string input = "OpSelectionMerge %1 " + GetParam().name();
-  EXPECT_THAT(
-      CompiledInstructions(input),
-      Eq(MakeInstruction(SpvOpSelectionMerge, {1, GetParam().value()})));
+  EXPECT_THAT(CompiledInstructions(input),
+              Eq(MakeInstruction(spv::Op::OpSelectionMerge,
+                                 {1, uint32_t(GetParam().value())})));
 }
 
 // clang-format off
-#define CASE(VALUE,NAME) { SpvSelectionControl##VALUE, NAME}
+#define CASE(VALUE,NAME) { spv::SelectionControlMask::VALUE, NAME}
 INSTANTIATE_TEST_SUITE_P(TextToBinarySelectionMerge, OpSelectionMergeTest,
-                        ValuesIn(std::vector<EnumCase<SpvSelectionControlMask>>{
+                        ValuesIn(std::vector<EnumCase<spv::SelectionControlMask>>{
                             CASE(MaskNone, "None"),
-                            CASE(FlattenMask, "Flatten"),
-                            CASE(DontFlattenMask, "DontFlatten"),
+                            CASE(Flatten, "Flatten"),
+                            CASE(DontFlatten, "DontFlatten"),
                         }));
 #undef CASE
 // clang-format on
@@ -63,9 +63,11 @@
 TEST_F(OpSelectionMergeTest, CombinedSelectionControlMask) {
   const std::string input = "OpSelectionMerge %1 Flatten|DontFlatten";
   const uint32_t expected_mask =
-      SpvSelectionControlFlattenMask | SpvSelectionControlDontFlattenMask;
-  EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpSelectionMerge, {1, expected_mask})));
+      uint32_t(spv::SelectionControlMask::Flatten |
+               spv::SelectionControlMask::DontFlatten);
+  EXPECT_THAT(
+      CompiledInstructions(input),
+      Eq(MakeInstruction(spv::Op::OpSelectionMerge, {1, expected_mask})));
 }
 
 TEST_F(OpSelectionMergeTest, WrongSelectionControl) {
@@ -85,15 +87,15 @@
   input << "OpLoopMerge %merge %continue " << ctrl.name();
   for (auto num : ctrl.operands()) input << " " << num;
   EXPECT_THAT(CompiledInstructions(input.str(), std::get<0>(GetParam())),
-              Eq(MakeInstruction(SpvOpLoopMerge, {1, 2, ctrl.value()},
+              Eq(MakeInstruction(spv::Op::OpLoopMerge, {1, 2, ctrl.value()},
                                  ctrl.operands())));
 }
 
 #define CASE(VALUE, NAME) \
-  { SpvLoopControl##VALUE, NAME }
-#define CASE1(VALUE, NAME, PARM)          \
-  {                                       \
-    SpvLoopControl##VALUE, NAME, { PARM } \
+  { int32_t(spv::LoopControlMask::VALUE), NAME }
+#define CASE1(VALUE, NAME, PARM)                         \
+  {                                                      \
+    int32_t(spv::LoopControlMask::VALUE), NAME, { PARM } \
   }
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryLoopMerge, OpLoopMergeTest,
@@ -101,8 +103,8 @@
             ValuesIn(std::vector<EnumCase<int>>{
                 // clang-format off
                 CASE(MaskNone, "None"),
-                CASE(UnrollMask, "Unroll"),
-                CASE(DontUnrollMask, "DontUnroll"),
+                CASE(Unroll, "Unroll"),
+                CASE(DontUnroll, "DontUnroll"),
                 // clang-format on
             })));
 
@@ -111,9 +113,9 @@
     Combine(Values(SPV_ENV_UNIVERSAL_1_1),
             ValuesIn(std::vector<EnumCase<int>>{
                 // clang-format off
-                CASE(DependencyInfiniteMask, "DependencyInfinite"),
-                CASE1(DependencyLengthMask, "DependencyLength", 234),
-                {SpvLoopControlUnrollMask|SpvLoopControlDependencyLengthMask,
+                CASE(DependencyInfinite, "DependencyInfinite"),
+                CASE1(DependencyLength, "DependencyLength", 234),
+                {int32_t(spv::LoopControlMask::Unroll|spv::LoopControlMask::DependencyLength),
                       "DependencyLength|Unroll", {33}},
                 // clang-format on
             })));
@@ -123,9 +125,9 @@
 TEST_F(OpLoopMergeTest, CombinedLoopControlMask) {
   const std::string input = "OpLoopMerge %merge %continue Unroll|DontUnroll";
   const uint32_t expected_mask =
-      SpvLoopControlUnrollMask | SpvLoopControlDontUnrollMask;
+      uint32_t(spv::LoopControlMask::Unroll | spv::LoopControlMask::DontUnroll);
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpLoopMerge, {1, 2, expected_mask})));
+              Eq(MakeInstruction(spv::Op::OpLoopMerge, {1, 2, expected_mask})));
 }
 
 TEST_F(OpLoopMergeTest, WrongLoopControl) {
@@ -137,16 +139,17 @@
 
 TEST_F(TextToBinaryTest, SwitchGoodZeroTargets) {
   EXPECT_THAT(CompiledInstructions("OpSwitch %selector %default"),
-              Eq(MakeInstruction(SpvOpSwitch, {1, 2})));
+              Eq(MakeInstruction(spv::Op::OpSwitch, {1, 2})));
 }
 
 TEST_F(TextToBinaryTest, SwitchGoodOneTarget) {
-  EXPECT_THAT(CompiledInstructions("%1 = OpTypeInt 32 0\n"
-                                   "%2 = OpConstant %1 52\n"
-                                   "OpSwitch %2 %default 12 %target0"),
-              Eq(Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 0}),
-                              MakeInstruction(SpvOpConstant, {1, 2, 52}),
-                              MakeInstruction(SpvOpSwitch, {2, 3, 12, 4})})));
+  EXPECT_THAT(
+      CompiledInstructions("%1 = OpTypeInt 32 0\n"
+                           "%2 = OpConstant %1 52\n"
+                           "OpSwitch %2 %default 12 %target0"),
+      Eq(Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 0}),
+                      MakeInstruction(spv::Op::OpConstant, {1, 2, 52}),
+                      MakeInstruction(spv::Op::OpSwitch, {2, 3, 12, 4})})));
 }
 
 TEST_F(TextToBinaryTest, SwitchGoodTwoTargets) {
@@ -155,9 +158,9 @@
                            "%2 = OpConstant %1 52\n"
                            "OpSwitch %2 %default 12 %target0 42 %target1"),
       Eq(Concatenate({
-          MakeInstruction(SpvOpTypeInt, {1, 32, 0}),
-          MakeInstruction(SpvOpConstant, {1, 2, 52}),
-          MakeInstruction(SpvOpSwitch, {2, 3, 12, 4, 42, 5}),
+          MakeInstruction(spv::Op::OpTypeInt, {1, 32, 0}),
+          MakeInstruction(spv::Op::OpConstant, {1, 2, 52}),
+          MakeInstruction(spv::Op::OpSwitch, {2, 3, 12, 4, 42, 5}),
       })));
 }
 
@@ -246,11 +249,11 @@
       constant_str,
       case_value_str,
       {Concatenate(
-          {MakeInstruction(SpvOpTypeInt,
+          {MakeInstruction(spv::Op::OpTypeInt,
                            {1, integer_width, integer_signedness}),
-           MakeInstruction(SpvOpConstant,
+           MakeInstruction(spv::Op::OpConstant,
                            Concatenate({{1, 2}, encoded_constant})),
-           MakeInstruction(SpvOpSwitch,
+           MakeInstruction(spv::Op::OpSwitch,
                            Concatenate({{2, 3}, encoded_case_value, {4}}))})}};
 }
 
diff --git a/test/text_to_binary.debug_test.cpp b/test/text_to_binary.debug_test.cpp
index 39ba5c5..013107b 100644
--- a/test/text_to_binary.debug_test.cpp
+++ b/test/text_to_binary.debug_test.cpp
@@ -39,7 +39,7 @@
     return static_cast<uint32_t>(language_value);
   }
   const char* language_name;
-  SpvSourceLanguage language_value;
+  spv::SourceLanguage language_value;
   uint32_t version;
 };
 
@@ -47,7 +47,7 @@
 // The list of OpSource cases to use.
 const LanguageCase kLanguageCases[] = {
 #define CASE(NAME, VERSION) \
-  { #NAME, SpvSourceLanguage##NAME, VERSION }
+  { #NAME, spv::SourceLanguage::NAME, VERSION }
   CASE(Unknown, 0),
   CASE(Unknown, 999),
   CASE(ESSL, 310),
@@ -69,9 +69,10 @@
   const std::string input = std::string("OpSource ") +
                             GetParam().language_name + " " +
                             std::to_string(GetParam().version);
-  EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpSource, {GetParam().get_language_value(),
-                                               GetParam().version})));
+  EXPECT_THAT(
+      CompiledInstructions(input),
+      Eq(MakeInstruction(spv::Op::OpSource, {GetParam().get_language_value(),
+                                             GetParam().version})));
 }
 
 INSTANTIATE_TEST_SUITE_P(TextToBinaryTestDebug, OpSourceTest,
@@ -87,7 +88,8 @@
   const std::string input = "OpSource GLSL 450 %file_id";
   EXPECT_THAT(
       CompiledInstructions(input),
-      Eq(MakeInstruction(SpvOpSource, {SpvSourceLanguageGLSL, 450, 1})));
+      Eq(MakeInstruction(spv::Op::OpSource,
+                         {uint32_t(spv::SourceLanguage::GLSL), 450, 1})));
 }
 
 TEST_F(TextToBinaryTest, OpSourceAcceptsOptionalSourceText) {
@@ -95,7 +97,8 @@
   const std::string input =
       "OpSource GLSL 450 %file_id \"" + fake_source + "\"";
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpSource, {SpvSourceLanguageGLSL, 450, 1},
+              Eq(MakeInstruction(spv::Op::OpSource,
+                                 {uint32_t(spv::SourceLanguage::GLSL), 450, 1},
                                  MakeVector(fake_source))));
 }
 
@@ -110,7 +113,7 @@
       std::string("OpSourceContinued \"") + GetParam() + "\"";
   EXPECT_THAT(
       CompiledInstructions(input),
-      Eq(MakeInstruction(SpvOpSourceContinued, MakeVector(GetParam()))));
+      Eq(MakeInstruction(spv::Op::OpSourceContinued, MakeVector(GetParam()))));
 }
 
 // TODO(dneto): utf-8, quoting, escaping
@@ -129,7 +132,7 @@
       std::string("OpSourceExtension \"") + GetParam() + "\"";
   EXPECT_THAT(
       CompiledInstructions(input),
-      Eq(MakeInstruction(SpvOpSourceExtension, MakeVector(GetParam()))));
+      Eq(MakeInstruction(spv::Op::OpSourceExtension, MakeVector(GetParam()))));
 }
 
 // TODO(dneto): utf-8, quoting, escaping
@@ -139,12 +142,12 @@
 
 TEST_F(TextToBinaryTest, OpLine) {
   EXPECT_THAT(CompiledInstructions("OpLine %srcfile 42 99"),
-              Eq(MakeInstruction(SpvOpLine, {1, 42, 99})));
+              Eq(MakeInstruction(spv::Op::OpLine, {1, 42, 99})));
 }
 
 TEST_F(TextToBinaryTest, OpNoLine) {
   EXPECT_THAT(CompiledInstructions("OpNoLine"),
-              Eq(MakeInstruction(SpvOpNoLine, {})));
+              Eq(MakeInstruction(spv::Op::OpNoLine, {})));
 }
 
 using OpStringTest =
@@ -154,8 +157,9 @@
   // TODO(dneto): utf-8, quoting, escaping
   const std::string input =
       std::string("%result = OpString \"") + GetParam() + "\"";
-  EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpString, {1}, MakeVector(GetParam()))));
+  EXPECT_THAT(
+      CompiledInstructions(input),
+      Eq(MakeInstruction(spv::Op::OpString, {1}, MakeVector(GetParam()))));
 }
 
 // TODO(dneto): utf-8, quoting, escaping
@@ -169,8 +173,9 @@
 TEST_P(OpNameTest, AnyString) {
   const std::string input =
       std::string("OpName %target \"") + GetParam() + "\"";
-  EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpName, {1}, MakeVector(GetParam()))));
+  EXPECT_THAT(
+      CompiledInstructions(input),
+      Eq(MakeInstruction(spv::Op::OpName, {1}, MakeVector(GetParam()))));
 }
 
 // UTF-8, quoting, escaping, etc. are covered in the StringLiterals tests in
@@ -185,9 +190,9 @@
   // TODO(dneto): utf-8, quoting, escaping
   const std::string input =
       std::string("OpMemberName %type 42 \"") + GetParam() + "\"";
-  EXPECT_THAT(
-      CompiledInstructions(input),
-      Eq(MakeInstruction(SpvOpMemberName, {1, 42}, MakeVector(GetParam()))));
+  EXPECT_THAT(CompiledInstructions(input),
+              Eq(MakeInstruction(spv::Op::OpMemberName, {1, 42},
+                                 MakeVector(GetParam()))));
 }
 
 // TODO(dneto): utf-8, quoting, escaping
@@ -205,7 +210,7 @@
       std::string("OpModuleProcessed \"") + GetParam() + "\"";
   EXPECT_THAT(
       CompiledInstructions(input, SPV_ENV_UNIVERSAL_1_1),
-      Eq(MakeInstruction(SpvOpModuleProcessed, MakeVector(GetParam()))));
+      Eq(MakeInstruction(spv::Op::OpModuleProcessed, MakeVector(GetParam()))));
 }
 
 INSTANTIATE_TEST_SUITE_P(TextToBinaryTestDebug, OpModuleProcessedTest,
diff --git a/test/text_to_binary.device_side_enqueue_test.cpp b/test/text_to_binary.device_side_enqueue_test.cpp
index 2f4dd70..7f424f3 100644
--- a/test/text_to_binary.device_side_enqueue_test.cpp
+++ b/test/text_to_binary.device_side_enqueue_test.cpp
@@ -44,7 +44,7 @@
       " %wait_events %ret_event %invoke %param %param_size %param_align " +
       GetParam().local_size_source;
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpEnqueueKernel,
+              Eq(MakeInstruction(spv::Op::OpEnqueueKernel,
                                  {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12},
                                  GetParam().local_size_operands)));
 }
diff --git a/test/text_to_binary.extension_test.cpp b/test/text_to_binary.extension_test.cpp
index cf4919a..6780c7e 100644
--- a/test/text_to_binary.extension_test.cpp
+++ b/test/text_to_binary.extension_test.cpp
@@ -87,12 +87,14 @@
   EXPECT_THAT(
       CompiledInstructions(input),
       Eq(Concatenate({
-          MakeInstruction(SpvOpExtInstImport, {1}, MakeVector("OpenCL.std")),
-          MakeInstruction(SpvOpExtInstImport, {2}, MakeVector("GLSL.std.450")),
+          MakeInstruction(spv::Op::OpExtInstImport, {1},
+                          MakeVector("OpenCL.std")),
+          MakeInstruction(spv::Op::OpExtInstImport, {2},
+                          MakeVector("GLSL.std.450")),
           MakeInstruction(
-              SpvOpExtInst,
+              spv::Op::OpExtInst,
               {3, 4, 1, uint32_t(OpenCLLIB::Entrypoints::Native_sqrt), 5}),
-          MakeInstruction(SpvOpExtInst,
+          MakeInstruction(spv::Op::OpExtInst,
                           {6, 7, 2, uint32_t(GLSLstd450MatrixInverse), 8}),
       })));
 
@@ -140,62 +142,74 @@
     SPV_KHR_shader_ballot, ExtensionRoundTripTest,
     // We'll get coverage over operand tables by trying the universal
     // environments, and at least one specific environment.
-    Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
-                   SPV_ENV_VULKAN_1_0),
-            ValuesIn(std::vector<AssemblyCase>{
-                {"OpCapability SubgroupBallotKHR\n",
-                 MakeInstruction(SpvOpCapability,
-                                 {SpvCapabilitySubgroupBallotKHR})},
-                {"%2 = OpSubgroupBallotKHR %1 %3\n",
-                 MakeInstruction(SpvOpSubgroupBallotKHR, {1, 2, 3})},
-                {"%2 = OpSubgroupFirstInvocationKHR %1 %3\n",
-                 MakeInstruction(SpvOpSubgroupFirstInvocationKHR, {1, 2, 3})},
-                {"OpDecorate %1 BuiltIn SubgroupEqMask\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInSubgroupEqMaskKHR})},
-                {"OpDecorate %1 BuiltIn SubgroupGeMask\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInSubgroupGeMaskKHR})},
-                {"OpDecorate %1 BuiltIn SubgroupGtMask\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInSubgroupGtMaskKHR})},
-                {"OpDecorate %1 BuiltIn SubgroupLeMask\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInSubgroupLeMaskKHR})},
-                {"OpDecorate %1 BuiltIn SubgroupLtMask\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInSubgroupLtMaskKHR})},
-            })));
+    Combine(
+        Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
+               SPV_ENV_VULKAN_1_0),
+        ValuesIn(std::vector<AssemblyCase>{
+            {"OpCapability SubgroupBallotKHR\n",
+             MakeInstruction(spv::Op::OpCapability,
+                             {uint32_t(spv::Capability::SubgroupBallotKHR)})},
+            {"%2 = OpSubgroupBallotKHR %1 %3\n",
+             MakeInstruction(spv::Op::OpSubgroupBallotKHR, {1, 2, 3})},
+            {"%2 = OpSubgroupFirstInvocationKHR %1 %3\n",
+             MakeInstruction(spv::Op::OpSubgroupFirstInvocationKHR, {1, 2, 3})},
+            {"OpDecorate %1 BuiltIn SubgroupEqMask\n",
+             MakeInstruction(spv::Op::OpDecorate,
+                             {1, uint32_t(spv::Decoration::BuiltIn),
+                              uint32_t(spv::BuiltIn::SubgroupEqMaskKHR)})},
+            {"OpDecorate %1 BuiltIn SubgroupGeMask\n",
+             MakeInstruction(spv::Op::OpDecorate,
+                             {1, uint32_t(spv::Decoration::BuiltIn),
+                              uint32_t(spv::BuiltIn::SubgroupGeMaskKHR)})},
+            {"OpDecorate %1 BuiltIn SubgroupGtMask\n",
+             MakeInstruction(spv::Op::OpDecorate,
+                             {1, uint32_t(spv::Decoration::BuiltIn),
+                              uint32_t(spv::BuiltIn::SubgroupGtMaskKHR)})},
+            {"OpDecorate %1 BuiltIn SubgroupLeMask\n",
+             MakeInstruction(spv::Op::OpDecorate,
+                             {1, uint32_t(spv::Decoration::BuiltIn),
+                              uint32_t(spv::BuiltIn::SubgroupLeMaskKHR)})},
+            {"OpDecorate %1 BuiltIn SubgroupLtMask\n",
+             MakeInstruction(spv::Op::OpDecorate,
+                             {1, uint32_t(spv::Decoration::BuiltIn),
+                              uint32_t(spv::BuiltIn::SubgroupLtMaskKHR)})},
+        })));
 
 INSTANTIATE_TEST_SUITE_P(
     SPV_KHR_shader_ballot_vulkan_1_1, ExtensionRoundTripTest,
     // In SPIR-V 1.3 and Vulkan 1.1 we can drop the KHR suffix on the
     // builtin enums.
-    Combine(Values(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_1),
-            ValuesIn(std::vector<AssemblyCase>{
-                {"OpCapability SubgroupBallotKHR\n",
-                 MakeInstruction(SpvOpCapability,
-                                 {SpvCapabilitySubgroupBallotKHR})},
-                {"%2 = OpSubgroupBallotKHR %1 %3\n",
-                 MakeInstruction(SpvOpSubgroupBallotKHR, {1, 2, 3})},
-                {"%2 = OpSubgroupFirstInvocationKHR %1 %3\n",
-                 MakeInstruction(SpvOpSubgroupFirstInvocationKHR, {1, 2, 3})},
-                {"OpDecorate %1 BuiltIn SubgroupEqMask\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInSubgroupEqMask})},
-                {"OpDecorate %1 BuiltIn SubgroupGeMask\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInSubgroupGeMask})},
-                {"OpDecorate %1 BuiltIn SubgroupGtMask\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInSubgroupGtMask})},
-                {"OpDecorate %1 BuiltIn SubgroupLeMask\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInSubgroupLeMask})},
-                {"OpDecorate %1 BuiltIn SubgroupLtMask\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInSubgroupLtMask})},
-            })));
+    Combine(
+        Values(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_1),
+        ValuesIn(std::vector<AssemblyCase>{
+            {"OpCapability SubgroupBallotKHR\n",
+             MakeInstruction(spv::Op::OpCapability,
+                             {(uint32_t)spv::Capability::SubgroupBallotKHR})},
+            {"%2 = OpSubgroupBallotKHR %1 %3\n",
+             MakeInstruction(spv::Op::OpSubgroupBallotKHR, {1, 2, 3})},
+            {"%2 = OpSubgroupFirstInvocationKHR %1 %3\n",
+             MakeInstruction(spv::Op::OpSubgroupFirstInvocationKHR, {1, 2, 3})},
+            {"OpDecorate %1 BuiltIn SubgroupEqMask\n",
+             MakeInstruction(spv::Op::OpDecorate,
+                             {1, uint32_t(spv::Decoration::BuiltIn),
+                              uint32_t(spv::BuiltIn::SubgroupEqMask)})},
+            {"OpDecorate %1 BuiltIn SubgroupGeMask\n",
+             MakeInstruction(spv::Op::OpDecorate,
+                             {1, uint32_t(spv::Decoration::BuiltIn),
+                              uint32_t(spv::BuiltIn::SubgroupGeMask)})},
+            {"OpDecorate %1 BuiltIn SubgroupGtMask\n",
+             MakeInstruction(spv::Op::OpDecorate,
+                             {1, uint32_t(spv::Decoration::BuiltIn),
+                              uint32_t(spv::BuiltIn::SubgroupGtMask)})},
+            {"OpDecorate %1 BuiltIn SubgroupLeMask\n",
+             MakeInstruction(spv::Op::OpDecorate,
+                             {1, uint32_t(spv::Decoration::BuiltIn),
+                              uint32_t(spv::BuiltIn::SubgroupLeMask)})},
+            {"OpDecorate %1 BuiltIn SubgroupLtMask\n",
+             MakeInstruction(spv::Op::OpDecorate,
+                             {1, uint32_t(spv::Decoration::BuiltIn),
+                              uint32_t(spv::BuiltIn::SubgroupLtMask)})},
+        })));
 
 // The old builtin names (with KHR suffix) still work in the assembler, and
 // map to the enums without the KHR.
@@ -206,20 +220,25 @@
     Combine(Values(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_1),
             ValuesIn(std::vector<AssemblyCase>{
                 {"OpDecorate %1 BuiltIn SubgroupEqMaskKHR\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInSubgroupEqMask})},
+                 MakeInstruction(spv::Op::OpDecorate,
+                                 {1, (uint32_t)spv::Decoration::BuiltIn,
+                                  (uint32_t)spv::BuiltIn::SubgroupEqMask})},
                 {"OpDecorate %1 BuiltIn SubgroupGeMaskKHR\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInSubgroupGeMask})},
+                 MakeInstruction(spv::Op::OpDecorate,
+                                 {1, (uint32_t)spv::Decoration::BuiltIn,
+                                  (uint32_t)spv::BuiltIn::SubgroupGeMask})},
                 {"OpDecorate %1 BuiltIn SubgroupGtMaskKHR\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInSubgroupGtMask})},
+                 MakeInstruction(spv::Op::OpDecorate,
+                                 {1, (uint32_t)spv::Decoration::BuiltIn,
+                                  (uint32_t)spv::BuiltIn::SubgroupGtMask})},
                 {"OpDecorate %1 BuiltIn SubgroupLeMaskKHR\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInSubgroupLeMask})},
+                 MakeInstruction(spv::Op::OpDecorate,
+                                 {1, (uint32_t)spv::Decoration::BuiltIn,
+                                  (uint32_t)spv::BuiltIn::SubgroupLeMask})},
                 {"OpDecorate %1 BuiltIn SubgroupLtMaskKHR\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInSubgroupLtMask})},
+                 MakeInstruction(spv::Op::OpDecorate,
+                                 {1, (uint32_t)spv::Decoration::BuiltIn,
+                                  (uint32_t)spv::BuiltIn::SubgroupLtMask})},
             })));
 
 // SPV_KHR_shader_draw_parameters
@@ -228,21 +247,24 @@
     SPV_KHR_shader_draw_parameters, ExtensionRoundTripTest,
     // We'll get coverage over operand tables by trying the universal
     // environments, and at least one specific environment.
-    Combine(
-        ValuesIn(CommonVulkanEnvs()),
-        ValuesIn(std::vector<AssemblyCase>{
-            {"OpCapability DrawParameters\n",
-             MakeInstruction(SpvOpCapability, {SpvCapabilityDrawParameters})},
-            {"OpDecorate %1 BuiltIn BaseVertex\n",
-             MakeInstruction(SpvOpDecorate,
-                             {1, SpvDecorationBuiltIn, SpvBuiltInBaseVertex})},
-            {"OpDecorate %1 BuiltIn BaseInstance\n",
-             MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                             SpvBuiltInBaseInstance})},
-            {"OpDecorate %1 BuiltIn DrawIndex\n",
-             MakeInstruction(SpvOpDecorate,
-                             {1, SpvDecorationBuiltIn, SpvBuiltInDrawIndex})},
-        })));
+    Combine(ValuesIn(CommonVulkanEnvs()),
+            ValuesIn(std::vector<AssemblyCase>{
+                {"OpCapability DrawParameters\n",
+                 MakeInstruction(spv::Op::OpCapability,
+                                 {(uint32_t)spv::Capability::DrawParameters})},
+                {"OpDecorate %1 BuiltIn BaseVertex\n",
+                 MakeInstruction(spv::Op::OpDecorate,
+                                 {1, (uint32_t)spv::Decoration::BuiltIn,
+                                  (uint32_t)spv::BuiltIn::BaseVertex})},
+                {"OpDecorate %1 BuiltIn BaseInstance\n",
+                 MakeInstruction(spv::Op::OpDecorate,
+                                 {1, (uint32_t)spv::Decoration::BuiltIn,
+                                  (uint32_t)spv::BuiltIn::BaseInstance})},
+                {"OpDecorate %1 BuiltIn DrawIndex\n",
+                 MakeInstruction(spv::Op::OpDecorate,
+                                 {1, (uint32_t)spv::Decoration::BuiltIn,
+                                  (uint32_t)spv::BuiltIn::DrawIndex})},
+            })));
 
 // SPV_KHR_subgroup_vote
 
@@ -253,14 +275,14 @@
     Combine(ValuesIn(CommonVulkanEnvs()),
             ValuesIn(std::vector<AssemblyCase>{
                 {"OpCapability SubgroupVoteKHR\n",
-                 MakeInstruction(SpvOpCapability,
-                                 {SpvCapabilitySubgroupVoteKHR})},
+                 MakeInstruction(spv::Op::OpCapability,
+                                 {(uint32_t)spv::Capability::SubgroupVoteKHR})},
                 {"%2 = OpSubgroupAnyKHR %1 %3\n",
-                 MakeInstruction(SpvOpSubgroupAnyKHR, {1, 2, 3})},
+                 MakeInstruction(spv::Op::OpSubgroupAnyKHR, {1, 2, 3})},
                 {"%2 = OpSubgroupAllKHR %1 %3\n",
-                 MakeInstruction(SpvOpSubgroupAllKHR, {1, 2, 3})},
+                 MakeInstruction(spv::Op::OpSubgroupAllKHR, {1, 2, 3})},
                 {"%2 = OpSubgroupAllEqualKHR %1 %3\n",
-                 MakeInstruction(SpvOpSubgroupAllEqualKHR, {1, 2, 3})},
+                 MakeInstruction(spv::Op::OpSubgroupAllEqualKHR, {1, 2, 3})},
             })));
 
 // SPV_KHR_16bit_storage
@@ -269,42 +291,50 @@
     SPV_KHR_16bit_storage, ExtensionRoundTripTest,
     // We'll get coverage over operand tables by trying the universal
     // environments, and at least one specific environment.
-    Combine(ValuesIn(CommonVulkanEnvs()),
-            ValuesIn(std::vector<AssemblyCase>{
-                {"OpCapability StorageBuffer16BitAccess\n",
-                 MakeInstruction(SpvOpCapability,
-                                 {SpvCapabilityStorageUniformBufferBlock16})},
-                {"OpCapability StorageBuffer16BitAccess\n",
-                 MakeInstruction(SpvOpCapability,
-                                 {SpvCapabilityStorageBuffer16BitAccess})},
-                {"OpCapability UniformAndStorageBuffer16BitAccess\n",
-                 MakeInstruction(
-                     SpvOpCapability,
-                     {SpvCapabilityUniformAndStorageBuffer16BitAccess})},
-                {"OpCapability UniformAndStorageBuffer16BitAccess\n",
-                 MakeInstruction(SpvOpCapability,
-                                 {SpvCapabilityStorageUniform16})},
-                {"OpCapability StoragePushConstant16\n",
-                 MakeInstruction(SpvOpCapability,
-                                 {SpvCapabilityStoragePushConstant16})},
-                {"OpCapability StorageInputOutput16\n",
-                 MakeInstruction(SpvOpCapability,
-                                 {SpvCapabilityStorageInputOutput16})},
-            })));
+    Combine(
+        ValuesIn(CommonVulkanEnvs()),
+        ValuesIn(std::vector<AssemblyCase>{
+            {"OpCapability StorageBuffer16BitAccess\n",
+             MakeInstruction(
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::StorageUniformBufferBlock16})},
+            {"OpCapability StorageBuffer16BitAccess\n",
+             MakeInstruction(
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::StorageBuffer16BitAccess})},
+            {"OpCapability UniformAndStorageBuffer16BitAccess\n",
+             MakeInstruction(
+                 spv::Op::OpCapability,
+                 {(uint32_t)
+                      spv::Capability::UniformAndStorageBuffer16BitAccess})},
+            {"OpCapability UniformAndStorageBuffer16BitAccess\n",
+             MakeInstruction(spv::Op::OpCapability,
+                             {(uint32_t)spv::Capability::StorageUniform16})},
+            {"OpCapability StoragePushConstant16\n",
+             MakeInstruction(
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::StoragePushConstant16})},
+            {"OpCapability StorageInputOutput16\n",
+             MakeInstruction(
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::StorageInputOutput16})},
+        })));
 
 INSTANTIATE_TEST_SUITE_P(
     SPV_KHR_16bit_storage_alias_check, ExtensionAssemblyTest,
-    Combine(ValuesIn(CommonVulkanEnvs()),
-            ValuesIn(std::vector<AssemblyCase>{
-                // The old name maps to the new enum.
-                {"OpCapability StorageUniformBufferBlock16\n",
-                 MakeInstruction(SpvOpCapability,
-                                 {SpvCapabilityStorageBuffer16BitAccess})},
-                // The new name maps to the old enum.
-                {"OpCapability UniformAndStorageBuffer16BitAccess\n",
-                 MakeInstruction(SpvOpCapability,
-                                 {SpvCapabilityStorageUniform16})},
-            })));
+    Combine(
+        ValuesIn(CommonVulkanEnvs()),
+        ValuesIn(std::vector<AssemblyCase>{
+            // The old name maps to the new enum.
+            {"OpCapability StorageUniformBufferBlock16\n",
+             MakeInstruction(
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::StorageBuffer16BitAccess})},
+            // The new name maps to the old enum.
+            {"OpCapability UniformAndStorageBuffer16BitAccess\n",
+             MakeInstruction(spv::Op::OpCapability,
+                             {(uint32_t)spv::Capability::StorageUniform16})},
+        })));
 
 // SPV_KHR_device_group
 
@@ -315,10 +345,12 @@
     Combine(ValuesIn(CommonVulkanEnvs()),
             ValuesIn(std::vector<AssemblyCase>{
                 {"OpCapability DeviceGroup\n",
-                 MakeInstruction(SpvOpCapability, {SpvCapabilityDeviceGroup})},
+                 MakeInstruction(spv::Op::OpCapability,
+                                 {(uint32_t)spv::Capability::DeviceGroup})},
                 {"OpDecorate %1 BuiltIn DeviceIndex\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInDeviceIndex})},
+                 MakeInstruction(spv::Op::OpDecorate,
+                                 {1, (uint32_t)spv::Decoration::BuiltIn,
+                                  (uint32_t)spv::BuiltIn::DeviceIndex})},
             })));
 
 // SPV_KHR_8bit_storage
@@ -327,19 +359,22 @@
     SPV_KHR_8bit_storage, ExtensionRoundTripTest,
     // We'll get coverage over operand tables by trying the universal
     // environments, and at least one specific environment.
-    Combine(
-        ValuesIn(CommonVulkanEnvs()),
-        ValuesIn(std::vector<AssemblyCase>{
-            {"OpCapability StorageBuffer8BitAccess\n",
-             MakeInstruction(SpvOpCapability,
-                             {SpvCapabilityStorageBuffer8BitAccess})},
-            {"OpCapability UniformAndStorageBuffer8BitAccess\n",
-             MakeInstruction(SpvOpCapability,
-                             {SpvCapabilityUniformAndStorageBuffer8BitAccess})},
-            {"OpCapability StoragePushConstant8\n",
-             MakeInstruction(SpvOpCapability,
-                             {SpvCapabilityStoragePushConstant8})},
-        })));
+    Combine(ValuesIn(CommonVulkanEnvs()),
+            ValuesIn(std::vector<AssemblyCase>{
+                {"OpCapability StorageBuffer8BitAccess\n",
+                 MakeInstruction(
+                     spv::Op::OpCapability,
+                     {(uint32_t)spv::Capability::StorageBuffer8BitAccess})},
+                {"OpCapability UniformAndStorageBuffer8BitAccess\n",
+                 MakeInstruction(
+                     spv::Op::OpCapability,
+                     {(uint32_t)
+                          spv::Capability::UniformAndStorageBuffer8BitAccess})},
+                {"OpCapability StoragePushConstant8\n",
+                 MakeInstruction(
+                     spv::Op::OpCapability,
+                     {(uint32_t)spv::Capability::StoragePushConstant8})},
+            })));
 
 // SPV_KHR_multiview
 
@@ -351,10 +386,12 @@
                    SPV_ENV_VULKAN_1_0),
             ValuesIn(std::vector<AssemblyCase>{
                 {"OpCapability MultiView\n",
-                 MakeInstruction(SpvOpCapability, {SpvCapabilityMultiView})},
+                 MakeInstruction(spv::Op::OpCapability,
+                                 {(uint32_t)spv::Capability::MultiView})},
                 {"OpDecorate %1 BuiltIn ViewIndex\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInViewIndex})},
+                 MakeInstruction(spv::Op::OpDecorate,
+                                 {1, (uint32_t)spv::Decoration::BuiltIn,
+                                  (uint32_t)spv::BuiltIn::ViewIndex})},
             })));
 
 // SPV_AMD_shader_explicit_vertex_parameter
@@ -372,9 +409,9 @@
             {PREAMBLE "%3 = OpExtInst %2 %1 InterpolateAtVertexAMD %4 %5\n",
              Concatenate(
                  {MakeInstruction(
-                      SpvOpExtInstImport, {1},
+                      spv::Op::OpExtInstImport, {1},
                       MakeVector("SPV_AMD_shader_explicit_vertex_parameter")),
-                  MakeInstruction(SpvOpExtInst, {2, 3, 1, 1, 4, 5})})},
+                  MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 1, 4, 5})})},
         })));
 #undef PREAMBLE
 
@@ -391,49 +428,49 @@
         ValuesIn(std::vector<AssemblyCase>{
             {PREAMBLE "%3 = OpExtInst %2 %1 FMin3AMD %4 %5 %6\n",
              Concatenate(
-                 {MakeInstruction(SpvOpExtInstImport, {1},
+                 {MakeInstruction(spv::Op::OpExtInstImport, {1},
                                   MakeVector("SPV_AMD_shader_trinary_minmax")),
-                  MakeInstruction(SpvOpExtInst, {2, 3, 1, 1, 4, 5, 6})})},
+                  MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 1, 4, 5, 6})})},
             {PREAMBLE "%3 = OpExtInst %2 %1 UMin3AMD %4 %5 %6\n",
              Concatenate(
-                 {MakeInstruction(SpvOpExtInstImport, {1},
+                 {MakeInstruction(spv::Op::OpExtInstImport, {1},
                                   MakeVector("SPV_AMD_shader_trinary_minmax")),
-                  MakeInstruction(SpvOpExtInst, {2, 3, 1, 2, 4, 5, 6})})},
+                  MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 2, 4, 5, 6})})},
             {PREAMBLE "%3 = OpExtInst %2 %1 SMin3AMD %4 %5 %6\n",
              Concatenate(
-                 {MakeInstruction(SpvOpExtInstImport, {1},
+                 {MakeInstruction(spv::Op::OpExtInstImport, {1},
                                   MakeVector("SPV_AMD_shader_trinary_minmax")),
-                  MakeInstruction(SpvOpExtInst, {2, 3, 1, 3, 4, 5, 6})})},
+                  MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 3, 4, 5, 6})})},
             {PREAMBLE "%3 = OpExtInst %2 %1 FMax3AMD %4 %5 %6\n",
              Concatenate(
-                 {MakeInstruction(SpvOpExtInstImport, {1},
+                 {MakeInstruction(spv::Op::OpExtInstImport, {1},
                                   MakeVector("SPV_AMD_shader_trinary_minmax")),
-                  MakeInstruction(SpvOpExtInst, {2, 3, 1, 4, 4, 5, 6})})},
+                  MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 4, 4, 5, 6})})},
             {PREAMBLE "%3 = OpExtInst %2 %1 UMax3AMD %4 %5 %6\n",
              Concatenate(
-                 {MakeInstruction(SpvOpExtInstImport, {1},
+                 {MakeInstruction(spv::Op::OpExtInstImport, {1},
                                   MakeVector("SPV_AMD_shader_trinary_minmax")),
-                  MakeInstruction(SpvOpExtInst, {2, 3, 1, 5, 4, 5, 6})})},
+                  MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 5, 4, 5, 6})})},
             {PREAMBLE "%3 = OpExtInst %2 %1 SMax3AMD %4 %5 %6\n",
              Concatenate(
-                 {MakeInstruction(SpvOpExtInstImport, {1},
+                 {MakeInstruction(spv::Op::OpExtInstImport, {1},
                                   MakeVector("SPV_AMD_shader_trinary_minmax")),
-                  MakeInstruction(SpvOpExtInst, {2, 3, 1, 6, 4, 5, 6})})},
+                  MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 6, 4, 5, 6})})},
             {PREAMBLE "%3 = OpExtInst %2 %1 FMid3AMD %4 %5 %6\n",
              Concatenate(
-                 {MakeInstruction(SpvOpExtInstImport, {1},
+                 {MakeInstruction(spv::Op::OpExtInstImport, {1},
                                   MakeVector("SPV_AMD_shader_trinary_minmax")),
-                  MakeInstruction(SpvOpExtInst, {2, 3, 1, 7, 4, 5, 6})})},
+                  MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 7, 4, 5, 6})})},
             {PREAMBLE "%3 = OpExtInst %2 %1 UMid3AMD %4 %5 %6\n",
              Concatenate(
-                 {MakeInstruction(SpvOpExtInstImport, {1},
+                 {MakeInstruction(spv::Op::OpExtInstImport, {1},
                                   MakeVector("SPV_AMD_shader_trinary_minmax")),
-                  MakeInstruction(SpvOpExtInst, {2, 3, 1, 8, 4, 5, 6})})},
+                  MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 8, 4, 5, 6})})},
             {PREAMBLE "%3 = OpExtInst %2 %1 SMid3AMD %4 %5 %6\n",
              Concatenate(
-                 {MakeInstruction(SpvOpExtInstImport, {1},
+                 {MakeInstruction(spv::Op::OpExtInstImport, {1},
                                   MakeVector("SPV_AMD_shader_trinary_minmax")),
-                  MakeInstruction(SpvOpExtInst, {2, 3, 1, 9, 4, 5, 6})})},
+                  MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 9, 4, 5, 6})})},
         })));
 #undef PREAMBLE
 
@@ -444,22 +481,25 @@
     SPV_AMD_gcn_shader, ExtensionRoundTripTest,
     // We'll get coverage over operand tables by trying the universal
     // environments, and at least one specific environment.
-    Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
-                   SPV_ENV_VULKAN_1_0),
-            ValuesIn(std::vector<AssemblyCase>{
-                {PREAMBLE "%3 = OpExtInst %2 %1 CubeFaceIndexAMD %4\n",
-                 Concatenate({MakeInstruction(SpvOpExtInstImport, {1},
-                                              MakeVector("SPV_AMD_gcn_shader")),
-                              MakeInstruction(SpvOpExtInst, {2, 3, 1, 1, 4})})},
-                {PREAMBLE "%3 = OpExtInst %2 %1 CubeFaceCoordAMD %4\n",
-                 Concatenate({MakeInstruction(SpvOpExtInstImport, {1},
-                                              MakeVector("SPV_AMD_gcn_shader")),
-                              MakeInstruction(SpvOpExtInst, {2, 3, 1, 2, 4})})},
-                {PREAMBLE "%3 = OpExtInst %2 %1 TimeAMD\n",
-                 Concatenate({MakeInstruction(SpvOpExtInstImport, {1},
-                                              MakeVector("SPV_AMD_gcn_shader")),
-                              MakeInstruction(SpvOpExtInst, {2, 3, 1, 3})})},
-            })));
+    Combine(
+        Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
+               SPV_ENV_VULKAN_1_0),
+        ValuesIn(std::vector<AssemblyCase>{
+            {PREAMBLE "%3 = OpExtInst %2 %1 CubeFaceIndexAMD %4\n",
+             Concatenate({MakeInstruction(spv::Op::OpExtInstImport, {1},
+                                          MakeVector("SPV_AMD_gcn_shader")),
+                          MakeInstruction(spv::Op::OpExtInst,
+                                          {2, 3, 1, 1, 4})})},
+            {PREAMBLE "%3 = OpExtInst %2 %1 CubeFaceCoordAMD %4\n",
+             Concatenate({MakeInstruction(spv::Op::OpExtInstImport, {1},
+                                          MakeVector("SPV_AMD_gcn_shader")),
+                          MakeInstruction(spv::Op::OpExtInst,
+                                          {2, 3, 1, 2, 4})})},
+            {PREAMBLE "%3 = OpExtInst %2 %1 TimeAMD\n",
+             Concatenate({MakeInstruction(spv::Op::OpExtInstImport, {1},
+                                          MakeVector("SPV_AMD_gcn_shader")),
+                          MakeInstruction(spv::Op::OpExtInst, {2, 3, 1, 3})})},
+        })));
 #undef PREAMBLE
 
 // SPV_AMD_shader_ballot
@@ -474,23 +514,26 @@
                SPV_ENV_VULKAN_1_0),
         ValuesIn(std::vector<AssemblyCase>{
             {PREAMBLE "%3 = OpExtInst %2 %1 SwizzleInvocationsAMD %4 %5\n",
-             Concatenate({MakeInstruction(SpvOpExtInstImport, {1},
+             Concatenate({MakeInstruction(spv::Op::OpExtInstImport, {1},
                                           MakeVector("SPV_AMD_shader_ballot")),
-                          MakeInstruction(SpvOpExtInst, {2, 3, 1, 1, 4, 5})})},
+                          MakeInstruction(spv::Op::OpExtInst,
+                                          {2, 3, 1, 1, 4, 5})})},
             {PREAMBLE
              "%3 = OpExtInst %2 %1 SwizzleInvocationsMaskedAMD %4 %5\n",
-             Concatenate({MakeInstruction(SpvOpExtInstImport, {1},
+             Concatenate({MakeInstruction(spv::Op::OpExtInstImport, {1},
                                           MakeVector("SPV_AMD_shader_ballot")),
-                          MakeInstruction(SpvOpExtInst, {2, 3, 1, 2, 4, 5})})},
+                          MakeInstruction(spv::Op::OpExtInst,
+                                          {2, 3, 1, 2, 4, 5})})},
             {PREAMBLE "%3 = OpExtInst %2 %1 WriteInvocationAMD %4 %5 %6\n",
-             Concatenate({MakeInstruction(SpvOpExtInstImport, {1},
+             Concatenate({MakeInstruction(spv::Op::OpExtInstImport, {1},
                                           MakeVector("SPV_AMD_shader_ballot")),
-                          MakeInstruction(SpvOpExtInst,
+                          MakeInstruction(spv::Op::OpExtInst,
                                           {2, 3, 1, 3, 4, 5, 6})})},
             {PREAMBLE "%3 = OpExtInst %2 %1 MbcntAMD %4\n",
-             Concatenate({MakeInstruction(SpvOpExtInstImport, {1},
+             Concatenate({MakeInstruction(spv::Op::OpExtInstImport, {1},
                                           MakeVector("SPV_AMD_shader_ballot")),
-                          MakeInstruction(SpvOpExtInst, {2, 3, 1, 4, 4})})},
+                          MakeInstruction(spv::Op::OpExtInst,
+                                          {2, 3, 1, 4, 4})})},
         })));
 #undef PREAMBLE
 
@@ -500,16 +543,18 @@
     SPV_KHR_variable_pointers, ExtensionRoundTripTest,
     // We'll get coverage over operand tables by trying the universal
     // environments, and at least one specific environment.
-    Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
-                   SPV_ENV_VULKAN_1_0),
-            ValuesIn(std::vector<AssemblyCase>{
-                {"OpCapability VariablePointers\n",
-                 MakeInstruction(SpvOpCapability,
-                                 {SpvCapabilityVariablePointers})},
-                {"OpCapability VariablePointersStorageBuffer\n",
-                 MakeInstruction(SpvOpCapability,
-                                 {SpvCapabilityVariablePointersStorageBuffer})},
-            })));
+    Combine(
+        Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1,
+               SPV_ENV_VULKAN_1_0),
+        ValuesIn(std::vector<AssemblyCase>{
+            {"OpCapability VariablePointers\n",
+             MakeInstruction(spv::Op::OpCapability,
+                             {(uint32_t)spv::Capability::VariablePointers})},
+            {"OpCapability VariablePointersStorageBuffer\n",
+             MakeInstruction(
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::VariablePointersStorageBuffer})},
+        })));
 
 // SPV_KHR_vulkan_memory_model
 
@@ -528,126 +573,145 @@
                SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1),
         ValuesIn(std::vector<AssemblyCase>{
             {"OpCapability VulkanMemoryModel\n",
-             MakeInstruction(SpvOpCapability,
-                             {SpvCapabilityVulkanMemoryModelKHR})},
+             MakeInstruction(
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::VulkanMemoryModelKHR})},
             {"OpCapability VulkanMemoryModelDeviceScope\n",
-             MakeInstruction(SpvOpCapability,
-                             {SpvCapabilityVulkanMemoryModelDeviceScopeKHR})},
+             MakeInstruction(
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::VulkanMemoryModelDeviceScopeKHR})},
             {"OpMemoryModel Logical Vulkan\n",
-             MakeInstruction(SpvOpMemoryModel, {SpvAddressingModelLogical,
-                                                SpvMemoryModelVulkanKHR})},
+             MakeInstruction(spv::Op::OpMemoryModel,
+                             {(uint32_t)spv::AddressingModel::Logical,
+                              (uint32_t)spv::MemoryModel::VulkanKHR})},
             {"OpStore %1 %2 MakePointerAvailable %3\n",
-             MakeInstruction(SpvOpStore,
-                             {1, 2, SpvMemoryAccessMakePointerAvailableKHRMask,
-                              3})},
+             MakeInstruction(
+                 spv::Op::OpStore,
+                 {1, 2,
+                  (uint32_t)spv::MemoryAccessMask::MakePointerAvailableKHR,
+                  3})},
             {"OpStore %1 %2 Volatile|MakePointerAvailable %3\n",
-             MakeInstruction(SpvOpStore,
-                             {1, 2,
-                              int(SpvMemoryAccessMakePointerAvailableKHRMask) |
-                                  int(SpvMemoryAccessVolatileMask),
-                              3})},
+             MakeInstruction(
+                 spv::Op::OpStore,
+                 {1, 2,
+                  int(spv::MemoryAccessMask::MakePointerAvailableKHR) |
+                      int(spv::MemoryAccessMask::Volatile),
+                  3})},
             {"OpStore %1 %2 Aligned|MakePointerAvailable 4 %3\n",
-             MakeInstruction(SpvOpStore,
-                             {1, 2,
-                              int(SpvMemoryAccessMakePointerAvailableKHRMask) |
-                                  int(SpvMemoryAccessAlignedMask),
-                              4, 3})},
+             MakeInstruction(
+                 spv::Op::OpStore,
+                 {1, 2,
+                  int(spv::MemoryAccessMask::MakePointerAvailableKHR) |
+                      int(spv::MemoryAccessMask::Aligned),
+                  4, 3})},
             {"OpStore %1 %2 MakePointerAvailable|NonPrivatePointer %3\n",
-             MakeInstruction(SpvOpStore,
-                             {1, 2,
-                              int(SpvMemoryAccessMakePointerAvailableKHRMask) |
-                                  int(SpvMemoryAccessNonPrivatePointerKHRMask),
-                              3})},
+             MakeInstruction(
+                 spv::Op::OpStore,
+                 {1, 2,
+                  int(spv::MemoryAccessMask::MakePointerAvailableKHR) |
+                      int(spv::MemoryAccessMask::NonPrivatePointerKHR),
+                  3})},
             {"%2 = OpLoad %1 %3 MakePointerVisible %4\n",
-             MakeInstruction(SpvOpLoad,
-                             {1, 2, 3, SpvMemoryAccessMakePointerVisibleKHRMask,
-                              4})},
+             MakeInstruction(
+                 spv::Op::OpLoad,
+                 {1, 2, 3,
+                  (uint32_t)spv::MemoryAccessMask::MakePointerVisibleKHR, 4})},
             {"%2 = OpLoad %1 %3 Volatile|MakePointerVisible %4\n",
-             MakeInstruction(SpvOpLoad,
-                             {1, 2, 3,
-                              int(SpvMemoryAccessMakePointerVisibleKHRMask) |
-                                  int(SpvMemoryAccessVolatileMask),
-                              4})},
+             MakeInstruction(
+                 spv::Op::OpLoad,
+                 {1, 2, 3,
+                  int(spv::MemoryAccessMask::MakePointerVisibleKHR) |
+                      int(spv::MemoryAccessMask::Volatile),
+                  4})},
             {"%2 = OpLoad %1 %3 Aligned|MakePointerVisible 8 %4\n",
-             MakeInstruction(SpvOpLoad,
-                             {1, 2, 3,
-                              int(SpvMemoryAccessMakePointerVisibleKHRMask) |
-                                  int(SpvMemoryAccessAlignedMask),
-                              8, 4})},
+             MakeInstruction(
+                 spv::Op::OpLoad,
+                 {1, 2, 3,
+                  int(spv::MemoryAccessMask::MakePointerVisibleKHR) |
+                      int(spv::MemoryAccessMask::Aligned),
+                  8, 4})},
             {"%2 = OpLoad %1 %3 MakePointerVisible|NonPrivatePointer "
              "%4\n",
-             MakeInstruction(SpvOpLoad,
-                             {1, 2, 3,
-                              int(SpvMemoryAccessMakePointerVisibleKHRMask) |
-                                  int(SpvMemoryAccessNonPrivatePointerKHRMask),
-                              4})},
+             MakeInstruction(
+                 spv::Op::OpLoad,
+                 {1, 2, 3,
+                  int(spv::MemoryAccessMask::MakePointerVisibleKHR) |
+                      int(spv::MemoryAccessMask::NonPrivatePointerKHR),
+                  4})},
             {"OpCopyMemory %1 %2 "
              "MakePointerAvailable|"
              "MakePointerVisible|"
              "NonPrivatePointer "
              "%3 %4\n",
-             MakeInstruction(SpvOpCopyMemory,
-                             {1, 2,
-                              (int(SpvMemoryAccessMakePointerVisibleKHRMask) |
-                               int(SpvMemoryAccessMakePointerAvailableKHRMask) |
-                               int(SpvMemoryAccessNonPrivatePointerKHRMask)),
-                              3, 4})},
+             MakeInstruction(
+                 spv::Op::OpCopyMemory,
+                 {1, 2,
+                  (int(spv::MemoryAccessMask::MakePointerVisibleKHR) |
+                   int(spv::MemoryAccessMask::MakePointerAvailableKHR) |
+                   int(spv::MemoryAccessMask::NonPrivatePointerKHR)),
+                  3, 4})},
             {"OpCopyMemorySized %1 %2 %3 "
              "MakePointerAvailable|"
              "MakePointerVisible|"
              "NonPrivatePointer "
              "%4 %5\n",
-             MakeInstruction(SpvOpCopyMemorySized,
-                             {1, 2, 3,
-                              (int(SpvMemoryAccessMakePointerVisibleKHRMask) |
-                               int(SpvMemoryAccessMakePointerAvailableKHRMask) |
-                               int(SpvMemoryAccessNonPrivatePointerKHRMask)),
-                              4, 5})},
+             MakeInstruction(
+                 spv::Op::OpCopyMemorySized,
+                 {1, 2, 3,
+                  (int(spv::MemoryAccessMask::MakePointerVisibleKHR) |
+                   int(spv::MemoryAccessMask::MakePointerAvailableKHR) |
+                   int(spv::MemoryAccessMask::NonPrivatePointerKHR)),
+                  4, 5})},
             // Image operands
             {"OpImageWrite %1 %2 %3 MakeTexelAvailable "
              "%4\n",
              MakeInstruction(
-                 SpvOpImageWrite,
-                 {1, 2, 3, int(SpvImageOperandsMakeTexelAvailableKHRMask), 4})},
+                 spv::Op::OpImageWrite,
+                 {1, 2, 3, int(spv::ImageOperandsMask::MakeTexelAvailableKHR),
+                  4})},
             {"OpImageWrite %1 %2 %3 MakeTexelAvailable|NonPrivateTexel "
              "%4\n",
-             MakeInstruction(SpvOpImageWrite,
-                             {1, 2, 3,
-                              int(SpvImageOperandsMakeTexelAvailableKHRMask) |
-                                  int(SpvImageOperandsNonPrivateTexelKHRMask),
-                              4})},
+             MakeInstruction(
+                 spv::Op::OpImageWrite,
+                 {1, 2, 3,
+                  int(spv::ImageOperandsMask::MakeTexelAvailableKHR) |
+                      int(spv::ImageOperandsMask::NonPrivateTexelKHR),
+                  4})},
             {"OpImageWrite %1 %2 %3 "
              "MakeTexelAvailable|NonPrivateTexel|VolatileTexel "
              "%4\n",
-             MakeInstruction(SpvOpImageWrite,
-                             {1, 2, 3,
-                              int(SpvImageOperandsMakeTexelAvailableKHRMask) |
-                                  int(SpvImageOperandsNonPrivateTexelKHRMask) |
-                                  int(SpvImageOperandsVolatileTexelKHRMask),
-                              4})},
+             MakeInstruction(
+                 spv::Op::OpImageWrite,
+                 {1, 2, 3,
+                  int(spv::ImageOperandsMask::MakeTexelAvailableKHR) |
+                      int(spv::ImageOperandsMask::NonPrivateTexelKHR) |
+                      int(spv::ImageOperandsMask::VolatileTexelKHR),
+                  4})},
             {"%2 = OpImageRead %1 %3 %4 MakeTexelVisible "
              "%5\n",
-             MakeInstruction(SpvOpImageRead,
+             MakeInstruction(spv::Op::OpImageRead,
                              {1, 2, 3, 4,
-                              int(SpvImageOperandsMakeTexelVisibleKHRMask),
+                              int(spv::ImageOperandsMask::MakeTexelVisibleKHR),
                               5})},
             {"%2 = OpImageRead %1 %3 %4 "
              "MakeTexelVisible|NonPrivateTexel "
              "%5\n",
-             MakeInstruction(SpvOpImageRead,
-                             {1, 2, 3, 4,
-                              int(SpvImageOperandsMakeTexelVisibleKHRMask) |
-                                  int(SpvImageOperandsNonPrivateTexelKHRMask),
-                              5})},
+             MakeInstruction(
+                 spv::Op::OpImageRead,
+                 {1, 2, 3, 4,
+                  int(spv::ImageOperandsMask::MakeTexelVisibleKHR) |
+                      int(spv::ImageOperandsMask::NonPrivateTexelKHR),
+                  5})},
             {"%2 = OpImageRead %1 %3 %4 "
              "MakeTexelVisible|NonPrivateTexel|VolatileTexel "
              "%5\n",
-             MakeInstruction(SpvOpImageRead,
-                             {1, 2, 3, 4,
-                              int(SpvImageOperandsMakeTexelVisibleKHRMask) |
-                                  int(SpvImageOperandsNonPrivateTexelKHRMask) |
-                                  int(SpvImageOperandsVolatileTexelKHRMask),
-                              5})},
+             MakeInstruction(
+                 spv::Op::OpImageRead,
+                 {1, 2, 3, 4,
+                  int(spv::ImageOperandsMask::MakeTexelVisibleKHR) |
+                      int(spv::ImageOperandsMask::NonPrivateTexelKHR) |
+                      int(spv::ImageOperandsMask::VolatileTexelKHR),
+                  5})},
 
             // Memory semantics ID values are numbers put into a SPIR-V
             // constant integer referenced by Id. There is no token for
@@ -670,20 +734,20 @@
                SPV_ENV_UNIVERSAL_1_2, SPV_ENV_VULKAN_1_0),
         ValuesIn(std::vector<AssemblyCase>{
             {"OpDecorateString %1 UserSemantic \"ABC\"\n",
-             MakeInstruction(SpvOpDecorateStringGOOGLE,
-                             {1, SpvDecorationHlslSemanticGOOGLE},
+             MakeInstruction(spv::Op::OpDecorateStringGOOGLE,
+                             {1, (uint32_t)spv::Decoration::HlslSemanticGOOGLE},
                              MakeVector("ABC"))},
             {"OpDecorateString %1 UserSemantic \"ABC\"\n",
-             MakeInstruction(SpvOpDecorateString,
-                             {1, SpvDecorationUserSemantic},
+             MakeInstruction(spv::Op::OpDecorateString,
+                             {1, (uint32_t)spv::Decoration::UserSemantic},
                              MakeVector("ABC"))},
             {"OpMemberDecorateString %1 3 UserSemantic \"DEF\"\n",
-             MakeInstruction(SpvOpMemberDecorateStringGOOGLE,
-                             {1, 3, SpvDecorationUserSemantic},
+             MakeInstruction(spv::Op::OpMemberDecorateStringGOOGLE,
+                             {1, 3, (uint32_t)spv::Decoration::UserSemantic},
                              MakeVector("DEF"))},
             {"OpMemberDecorateString %1 3 UserSemantic \"DEF\"\n",
-             MakeInstruction(SpvOpMemberDecorateString,
-                             {1, 3, SpvDecorationUserSemantic},
+             MakeInstruction(spv::Op::OpMemberDecorateString,
+                             {1, 3, (uint32_t)spv::Decoration::UserSemantic},
                              MakeVector("DEF"))},
         })));
 
@@ -696,12 +760,13 @@
                SPV_ENV_UNIVERSAL_1_2, SPV_ENV_VULKAN_1_0),
         ValuesIn(std::vector<AssemblyCase>{
             {"OpDecorateStringGOOGLE %1 HlslSemanticGOOGLE \"ABC\"\n",
-             MakeInstruction(SpvOpDecorateStringGOOGLE,
-                             {1, SpvDecorationHlslSemanticGOOGLE},
+             MakeInstruction(spv::Op::OpDecorateStringGOOGLE,
+                             {1, (uint32_t)spv::Decoration::HlslSemanticGOOGLE},
                              MakeVector("ABC"))},
             {"OpMemberDecorateStringGOOGLE %1 3 HlslSemanticGOOGLE \"DEF\"\n",
-             MakeInstruction(SpvOpMemberDecorateStringGOOGLE,
-                             {1, 3, SpvDecorationHlslSemanticGOOGLE},
+             MakeInstruction(spv::Op::OpMemberDecorateStringGOOGLE,
+                             {1, 3,
+                              (uint32_t)spv::Decoration::HlslSemanticGOOGLE},
                              MakeVector("DEF"))},
         })));
 
@@ -721,11 +786,12 @@
         // they are coupled together.
         ValuesIn(std::vector<AssemblyCase>{
             {"OpDecorateId %1 CounterBuffer %2\n",
-             MakeInstruction(SpvOpDecorateId,
-                             {1, SpvDecorationHlslCounterBufferGOOGLE, 2})},
+             MakeInstruction(
+                 spv::Op::OpDecorateId,
+                 {1, (uint32_t)spv::Decoration::HlslCounterBufferGOOGLE, 2})},
             {"OpDecorateId %1 CounterBuffer %2\n",
-             MakeInstruction(SpvOpDecorateId,
-                             {1, SpvDecorationCounterBuffer, 2})},
+             MakeInstruction(spv::Op::OpDecorateId,
+                             {1, (uint32_t)spv::Decoration::CounterBuffer, 2})},
         })));
 
 INSTANTIATE_TEST_SUITE_P(
@@ -739,8 +805,9 @@
         // they are coupled together.
         ValuesIn(std::vector<AssemblyCase>{
             {"OpDecorateId %1 HlslCounterBufferGOOGLE %2\n",
-             MakeInstruction(SpvOpDecorateId,
-                             {1, SpvDecorationHlslCounterBufferGOOGLE, 2})},
+             MakeInstruction(
+                 spv::Op::OpDecorateId,
+                 {1, (uint32_t)spv::Decoration::HlslCounterBufferGOOGLE, 2})},
         })));
 
 // SPV_NV_viewport_array2
@@ -752,23 +819,26 @@
                    SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1),
             ValuesIn(std::vector<AssemblyCase>{
                 {"OpExtension \"SPV_NV_viewport_array2\"\n",
-                 MakeInstruction(SpvOpExtension,
+                 MakeInstruction(spv::Op::OpExtension,
                                  MakeVector("SPV_NV_viewport_array2"))},
                 // The EXT and NV extensions have the same token number for this
                 // capability.
                 {"OpCapability ShaderViewportIndexLayerEXT\n",
-                 MakeInstruction(SpvOpCapability,
-                                 {SpvCapabilityShaderViewportIndexLayerNV})},
+                 MakeInstruction(
+                     spv::Op::OpCapability,
+                     {(uint32_t)spv::Capability::ShaderViewportIndexLayerNV})},
                 // Check the new capability's token number
                 {"OpCapability ShaderViewportIndexLayerEXT\n",
-                 MakeInstruction(SpvOpCapability, {5254})},
+                 MakeInstruction(spv::Op::OpCapability, {5254})},
                 // Decorations
                 {"OpDecorate %1 ViewportRelativeNV\n",
-                 MakeInstruction(SpvOpDecorate,
-                                 {1, SpvDecorationViewportRelativeNV})},
+                 MakeInstruction(
+                     spv::Op::OpDecorate,
+                     {1, (uint32_t)spv::Decoration::ViewportRelativeNV})},
                 {"OpDecorate %1 BuiltIn ViewportMaskNV\n",
-                 MakeInstruction(SpvOpDecorate, {1, SpvDecorationBuiltIn,
-                                                 SpvBuiltInViewportMaskNV})},
+                 MakeInstruction(spv::Op::OpDecorate,
+                                 {1, (uint32_t)spv::Decoration::BuiltIn,
+                                  (uint32_t)spv::BuiltIn::ViewportMaskNV})},
             })));
 
 // SPV_NV_shader_subgroup_partitioned
@@ -779,38 +849,44 @@
         Values(SPV_ENV_UNIVERSAL_1_3, SPV_ENV_VULKAN_1_1),
         ValuesIn(std::vector<AssemblyCase>{
             {"OpExtension \"SPV_NV_shader_subgroup_partitioned\"\n",
-             MakeInstruction(SpvOpExtension,
+             MakeInstruction(spv::Op::OpExtension,
                              MakeVector("SPV_NV_shader_subgroup_partitioned"))},
             {"OpCapability GroupNonUniformPartitionedNV\n",
-             MakeInstruction(SpvOpCapability,
-                             {SpvCapabilityGroupNonUniformPartitionedNV})},
+             MakeInstruction(
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::GroupNonUniformPartitionedNV})},
             // Check the new capability's token number
             {"OpCapability GroupNonUniformPartitionedNV\n",
-             MakeInstruction(SpvOpCapability, {5297})},
+             MakeInstruction(spv::Op::OpCapability, {5297})},
             {"%2 = OpGroupNonUniformPartitionNV %1 %3\n",
-             MakeInstruction(SpvOpGroupNonUniformPartitionNV, {1, 2, 3})},
+             MakeInstruction(spv::Op::OpGroupNonUniformPartitionNV, {1, 2, 3})},
             // Check the new instruction's token number
             {"%2 = OpGroupNonUniformPartitionNV %1 %3\n",
-             MakeInstruction(static_cast<SpvOp>(5296), {1, 2, 3})},
+             MakeInstruction(static_cast<spv::Op>(5296), {1, 2, 3})},
             // Check the new group operations
             {"%2 = OpGroupIAdd %1 %3 PartitionedReduceNV %4\n",
-             MakeInstruction(SpvOpGroupIAdd,
-                             {1, 2, 3, SpvGroupOperationPartitionedReduceNV,
-                              4})},
+             MakeInstruction(
+                 spv::Op::OpGroupIAdd,
+                 {1, 2, 3, (uint32_t)spv::GroupOperation::PartitionedReduceNV,
+                  4})},
             {"%2 = OpGroupIAdd %1 %3 PartitionedReduceNV %4\n",
-             MakeInstruction(SpvOpGroupIAdd, {1, 2, 3, 6, 4})},
+             MakeInstruction(spv::Op::OpGroupIAdd, {1, 2, 3, 6, 4})},
             {"%2 = OpGroupIAdd %1 %3 PartitionedInclusiveScanNV %4\n",
-             MakeInstruction(SpvOpGroupIAdd,
-                             {1, 2, 3,
-                              SpvGroupOperationPartitionedInclusiveScanNV, 4})},
+             MakeInstruction(
+                 spv::Op::OpGroupIAdd,
+                 {1, 2, 3,
+                  (uint32_t)spv::GroupOperation::PartitionedInclusiveScanNV,
+                  4})},
             {"%2 = OpGroupIAdd %1 %3 PartitionedInclusiveScanNV %4\n",
-             MakeInstruction(SpvOpGroupIAdd, {1, 2, 3, 7, 4})},
+             MakeInstruction(spv::Op::OpGroupIAdd, {1, 2, 3, 7, 4})},
             {"%2 = OpGroupIAdd %1 %3 PartitionedExclusiveScanNV %4\n",
-             MakeInstruction(SpvOpGroupIAdd,
-                             {1, 2, 3,
-                              SpvGroupOperationPartitionedExclusiveScanNV, 4})},
+             MakeInstruction(
+                 spv::Op::OpGroupIAdd,
+                 {1, 2, 3,
+                  (uint32_t)spv::GroupOperation::PartitionedExclusiveScanNV,
+                  4})},
             {"%2 = OpGroupIAdd %1 %3 PartitionedExclusiveScanNV %4\n",
-             MakeInstruction(SpvOpGroupIAdd, {1, 2, 3, 8, 4})},
+             MakeInstruction(spv::Op::OpGroupIAdd, {1, 2, 3, 8, 4})},
         })));
 
 // SPV_EXT_descriptor_indexing
@@ -823,86 +899,90 @@
                SPV_ENV_VULKAN_1_1),
         ValuesIn(std::vector<AssemblyCase>{
             {"OpExtension \"SPV_EXT_descriptor_indexing\"\n",
-             MakeInstruction(SpvOpExtension,
+             MakeInstruction(spv::Op::OpExtension,
                              MakeVector("SPV_EXT_descriptor_indexing"))},
             // Check capabilities, by name
             {"OpCapability ShaderNonUniform\n",
-             MakeInstruction(SpvOpCapability,
-                             {SpvCapabilityShaderNonUniformEXT})},
+             MakeInstruction(spv::Op::OpCapability,
+                             {(uint32_t)spv::Capability::ShaderNonUniformEXT})},
             {"OpCapability RuntimeDescriptorArray\n",
-             MakeInstruction(SpvOpCapability,
-                             {SpvCapabilityRuntimeDescriptorArrayEXT})},
+             MakeInstruction(
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::RuntimeDescriptorArrayEXT})},
             {"OpCapability InputAttachmentArrayDynamicIndexing\n",
-             MakeInstruction(
-                 SpvOpCapability,
-                 {SpvCapabilityInputAttachmentArrayDynamicIndexingEXT})},
+             MakeInstruction(spv::Op::OpCapability,
+                             {(uint32_t)spv::Capability::
+                                  InputAttachmentArrayDynamicIndexingEXT})},
             {"OpCapability UniformTexelBufferArrayDynamicIndexing\n",
-             MakeInstruction(
-                 SpvOpCapability,
-                 {SpvCapabilityUniformTexelBufferArrayDynamicIndexingEXT})},
+             MakeInstruction(spv::Op::OpCapability,
+                             {(uint32_t)spv::Capability::
+                                  UniformTexelBufferArrayDynamicIndexingEXT})},
             {"OpCapability StorageTexelBufferArrayDynamicIndexing\n",
-             MakeInstruction(
-                 SpvOpCapability,
-                 {SpvCapabilityStorageTexelBufferArrayDynamicIndexingEXT})},
+             MakeInstruction(spv::Op::OpCapability,
+                             {(uint32_t)spv::Capability::
+                                  StorageTexelBufferArrayDynamicIndexingEXT})},
             {"OpCapability UniformBufferArrayNonUniformIndexing\n",
-             MakeInstruction(
-                 SpvOpCapability,
-                 {SpvCapabilityUniformBufferArrayNonUniformIndexingEXT})},
+             MakeInstruction(spv::Op::OpCapability,
+                             {(uint32_t)spv::Capability::
+                                  UniformBufferArrayNonUniformIndexingEXT})},
             {"OpCapability SampledImageArrayNonUniformIndexing\n",
-             MakeInstruction(
-                 SpvOpCapability,
-                 {SpvCapabilitySampledImageArrayNonUniformIndexingEXT})},
+             MakeInstruction(spv::Op::OpCapability,
+                             {(uint32_t)spv::Capability::
+                                  SampledImageArrayNonUniformIndexingEXT})},
             {"OpCapability StorageBufferArrayNonUniformIndexing\n",
-             MakeInstruction(
-                 SpvOpCapability,
-                 {SpvCapabilityStorageBufferArrayNonUniformIndexingEXT})},
+             MakeInstruction(spv::Op::OpCapability,
+                             {(uint32_t)spv::Capability::
+                                  StorageBufferArrayNonUniformIndexingEXT})},
             {"OpCapability StorageImageArrayNonUniformIndexing\n",
-             MakeInstruction(
-                 SpvOpCapability,
-                 {SpvCapabilityStorageImageArrayNonUniformIndexingEXT})},
+             MakeInstruction(spv::Op::OpCapability,
+                             {(uint32_t)spv::Capability::
+                                  StorageImageArrayNonUniformIndexingEXT})},
             {"OpCapability InputAttachmentArrayNonUniformIndexing\n",
-             MakeInstruction(
-                 SpvOpCapability,
-                 {SpvCapabilityInputAttachmentArrayNonUniformIndexingEXT})},
+             MakeInstruction(spv::Op::OpCapability,
+                             {(uint32_t)spv::Capability::
+                                  InputAttachmentArrayNonUniformIndexingEXT})},
             {"OpCapability UniformTexelBufferArrayNonUniformIndexing\n",
              MakeInstruction(
-                 SpvOpCapability,
-                 {SpvCapabilityUniformTexelBufferArrayNonUniformIndexingEXT})},
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::
+                      UniformTexelBufferArrayNonUniformIndexingEXT})},
             {"OpCapability StorageTexelBufferArrayNonUniformIndexing\n",
              MakeInstruction(
-                 SpvOpCapability,
-                 {SpvCapabilityStorageTexelBufferArrayNonUniformIndexingEXT})},
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::
+                      StorageTexelBufferArrayNonUniformIndexingEXT})},
             // Check capabilities, by number
             {"OpCapability ShaderNonUniform\n",
-             MakeInstruction(SpvOpCapability, {5301})},
+             MakeInstruction(spv::Op::OpCapability, {5301})},
             {"OpCapability RuntimeDescriptorArray\n",
-             MakeInstruction(SpvOpCapability, {5302})},
+             MakeInstruction(spv::Op::OpCapability, {5302})},
             {"OpCapability InputAttachmentArrayDynamicIndexing\n",
-             MakeInstruction(SpvOpCapability, {5303})},
+             MakeInstruction(spv::Op::OpCapability, {5303})},
             {"OpCapability UniformTexelBufferArrayDynamicIndexing\n",
-             MakeInstruction(SpvOpCapability, {5304})},
+             MakeInstruction(spv::Op::OpCapability, {5304})},
             {"OpCapability StorageTexelBufferArrayDynamicIndexing\n",
-             MakeInstruction(SpvOpCapability, {5305})},
+             MakeInstruction(spv::Op::OpCapability, {5305})},
             {"OpCapability UniformBufferArrayNonUniformIndexing\n",
-             MakeInstruction(SpvOpCapability, {5306})},
+             MakeInstruction(spv::Op::OpCapability, {5306})},
             {"OpCapability SampledImageArrayNonUniformIndexing\n",
-             MakeInstruction(SpvOpCapability, {5307})},
+             MakeInstruction(spv::Op::OpCapability, {5307})},
             {"OpCapability StorageBufferArrayNonUniformIndexing\n",
-             MakeInstruction(SpvOpCapability, {5308})},
+             MakeInstruction(spv::Op::OpCapability, {5308})},
             {"OpCapability StorageImageArrayNonUniformIndexing\n",
-             MakeInstruction(SpvOpCapability, {5309})},
+             MakeInstruction(spv::Op::OpCapability, {5309})},
             {"OpCapability InputAttachmentArrayNonUniformIndexing\n",
-             MakeInstruction(SpvOpCapability, {5310})},
+             MakeInstruction(spv::Op::OpCapability, {5310})},
             {"OpCapability UniformTexelBufferArrayNonUniformIndexing\n",
-             MakeInstruction(SpvOpCapability, {5311})},
+             MakeInstruction(spv::Op::OpCapability, {5311})},
             {"OpCapability StorageTexelBufferArrayNonUniformIndexing\n",
-             MakeInstruction(SpvOpCapability, {5312})},
+             MakeInstruction(spv::Op::OpCapability, {5312})},
 
             // Check the decoration token
             {"OpDecorate %1 NonUniform\n",
-             MakeInstruction(SpvOpDecorate, {1, SpvDecorationNonUniformEXT})},
+             MakeInstruction(spv::Op::OpDecorate,
+                             {1, (uint32_t)spv::Decoration::NonUniformEXT})},
             {"OpDecorate %1 NonUniform\n",
-             MakeInstruction(SpvOpDecorate, {1, 5300})},
+             MakeInstruction(spv::Op::OpDecorate, {1, 5300})},
         })));
 
 // SPV_KHR_linkonce_odr
@@ -914,13 +994,14 @@
                SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_2),
         ValuesIn(std::vector<AssemblyCase>{
             {"OpExtension \"SPV_KHR_linkonce_odr\"\n",
-             MakeInstruction(SpvOpExtension,
+             MakeInstruction(spv::Op::OpExtension,
                              MakeVector("SPV_KHR_linkonce_odr"))},
             {"OpDecorate %1 LinkageAttributes \"foobar\" LinkOnceODR\n",
-             MakeInstruction(SpvOpDecorate,
-                             Concatenate({{1, SpvDecorationLinkageAttributes},
-                                          MakeVector("foobar"),
-                                          {SpvLinkageTypeLinkOnceODR}}))},
+             MakeInstruction(
+                 spv::Op::OpDecorate,
+                 Concatenate({{1, (uint32_t)spv::Decoration::LinkageAttributes},
+                              MakeVector("foobar"),
+                              {(uint32_t)spv::LinkageType::LinkOnceODR}}))},
         })));
 
 // SPV_KHR_expect_assume
@@ -931,10 +1012,10 @@
                    SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_2),
             ValuesIn(std::vector<AssemblyCase>{
                 {"OpExtension \"SPV_KHR_expect_assume\"\n",
-                 MakeInstruction(SpvOpExtension,
+                 MakeInstruction(spv::Op::OpExtension,
                                  MakeVector("SPV_KHR_expect_assume"))},
                 {"OpAssumeTrueKHR %1\n",
-                 MakeInstruction(SpvOpAssumeTrueKHR, {1})}})));
+                 MakeInstruction(spv::Op::OpAssumeTrueKHR, {1})}})));
 // SPV_KHR_subgroup_uniform_control_flow
 
 INSTANTIATE_TEST_SUITE_P(
@@ -944,12 +1025,12 @@
             ValuesIn(std::vector<AssemblyCase>{
                 {"OpExtension \"SPV_KHR_subgroup_uniform_control_flow\"\n",
                  MakeInstruction(
-                     SpvOpExtension,
+                     spv::Op::OpExtension,
                      MakeVector("SPV_KHR_subgroup_uniform_control_flow"))},
                 {"OpExecutionMode %1 SubgroupUniformControlFlowKHR\n",
-                 MakeInstruction(
-                     SpvOpExecutionMode,
-                     {1, SpvExecutionModeSubgroupUniformControlFlowKHR})},
+                 MakeInstruction(spv::Op::OpExecutionMode,
+                                 {1, (uint32_t)spv::ExecutionMode::
+                                         SubgroupUniformControlFlowKHR})},
             })));
 
 // SPV_KHR_integer_dot_product
@@ -962,61 +1043,71 @@
                SPV_ENV_VULKAN_1_2, SPV_ENV_VULKAN_1_3),
         ValuesIn(std::vector<AssemblyCase>{
             {"OpExtension \"SPV_KHR_integer_dot_product\"\n",
-             MakeInstruction(SpvOpExtension,
+             MakeInstruction(spv::Op::OpExtension,
                              MakeVector("SPV_KHR_integer_dot_product"))},
             {"OpCapability DotProductInputAll\n",
-             MakeInstruction(SpvOpCapability,
-                             {SpvCapabilityDotProductInputAllKHR})},
+             MakeInstruction(
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::DotProductInputAllKHR})},
             {"OpCapability DotProductInput4x8Bit\n",
-             MakeInstruction(SpvOpCapability,
-                             {SpvCapabilityDotProductInput4x8BitKHR})},
+             MakeInstruction(
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::DotProductInput4x8BitKHR})},
             {"OpCapability DotProductInput4x8BitPacked\n",
-             MakeInstruction(SpvOpCapability,
-                             {SpvCapabilityDotProductInput4x8BitPackedKHR})},
+             MakeInstruction(
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::DotProductInput4x8BitPackedKHR})},
             {"OpCapability DotProduct\n",
-             MakeInstruction(SpvOpCapability, {SpvCapabilityDotProductKHR})},
+             MakeInstruction(spv::Op::OpCapability,
+                             {(uint32_t)spv::Capability::DotProductKHR})},
             {"%2 = OpSDot %1 %3 %4\n",
-             MakeInstruction(SpvOpSDotKHR, {1, 2, 3, 4})},
+             MakeInstruction(spv::Op::OpSDotKHR, {1, 2, 3, 4})},
             {"%2 = OpSDot %1 %3 %4 PackedVectorFormat4x8Bit\n",
              MakeInstruction(
-                 SpvOpSDotKHR,
+                 spv::Op::OpSDotKHR,
                  {1, 2, 3, 4,
-                  SpvPackedVectorFormatPackedVectorFormat4x8BitKHR})},
+                  (uint32_t)
+                      spv::PackedVectorFormat::PackedVectorFormat4x8BitKHR})},
             {"%2 = OpUDot %1 %3 %4\n",
-             MakeInstruction(SpvOpUDotKHR, {1, 2, 3, 4})},
+             MakeInstruction(spv::Op::OpUDotKHR, {1, 2, 3, 4})},
             {"%2 = OpUDot %1 %3 %4 PackedVectorFormat4x8Bit\n",
              MakeInstruction(
-                 SpvOpUDotKHR,
+                 spv::Op::OpUDotKHR,
                  {1, 2, 3, 4,
-                  SpvPackedVectorFormatPackedVectorFormat4x8BitKHR})},
+                  (uint32_t)
+                      spv::PackedVectorFormat::PackedVectorFormat4x8BitKHR})},
             {"%2 = OpSUDot %1 %3 %4\n",
-             MakeInstruction(SpvOpSUDotKHR, {1, 2, 3, 4})},
+             MakeInstruction(spv::Op::OpSUDotKHR, {1, 2, 3, 4})},
             {"%2 = OpSUDot %1 %3 %4 PackedVectorFormat4x8Bit\n",
              MakeInstruction(
-                 SpvOpSUDotKHR,
+                 spv::Op::OpSUDotKHR,
                  {1, 2, 3, 4,
-                  SpvPackedVectorFormatPackedVectorFormat4x8BitKHR})},
+                  (uint32_t)
+                      spv::PackedVectorFormat::PackedVectorFormat4x8BitKHR})},
             {"%2 = OpSDotAccSat %1 %3 %4 %5\n",
-             MakeInstruction(SpvOpSDotAccSatKHR, {1, 2, 3, 4, 5})},
+             MakeInstruction(spv::Op::OpSDotAccSatKHR, {1, 2, 3, 4, 5})},
             {"%2 = OpSDotAccSat %1 %3 %4 %5 PackedVectorFormat4x8Bit\n",
              MakeInstruction(
-                 SpvOpSDotAccSatKHR,
+                 spv::Op::OpSDotAccSatKHR,
                  {1, 2, 3, 4, 5,
-                  SpvPackedVectorFormatPackedVectorFormat4x8BitKHR})},
+                  (uint32_t)
+                      spv::PackedVectorFormat::PackedVectorFormat4x8BitKHR})},
             {"%2 = OpUDotAccSat %1 %3 %4 %5\n",
-             MakeInstruction(SpvOpUDotAccSatKHR, {1, 2, 3, 4, 5})},
+             MakeInstruction(spv::Op::OpUDotAccSatKHR, {1, 2, 3, 4, 5})},
             {"%2 = OpUDotAccSat %1 %3 %4 %5 PackedVectorFormat4x8Bit\n",
              MakeInstruction(
-                 SpvOpUDotAccSatKHR,
+                 spv::Op::OpUDotAccSatKHR,
                  {1, 2, 3, 4, 5,
-                  SpvPackedVectorFormatPackedVectorFormat4x8BitKHR})},
+                  (uint32_t)
+                      spv::PackedVectorFormat::PackedVectorFormat4x8BitKHR})},
             {"%2 = OpSUDotAccSat %1 %3 %4 %5\n",
-             MakeInstruction(SpvOpSUDotAccSatKHR, {1, 2, 3, 4, 5})},
+             MakeInstruction(spv::Op::OpSUDotAccSatKHR, {1, 2, 3, 4, 5})},
             {"%2 = OpSUDotAccSat %1 %3 %4 %5 PackedVectorFormat4x8Bit\n",
              MakeInstruction(
-                 SpvOpSUDotAccSatKHR,
+                 spv::Op::OpSUDotAccSatKHR,
                  {1, 2, 3, 4, 5,
-                  SpvPackedVectorFormatPackedVectorFormat4x8BitKHR})},
+                  (uint32_t)
+                      spv::PackedVectorFormat::PackedVectorFormat4x8BitKHR})},
         })));
 
 // SPV_KHR_bit_instructions
@@ -1027,11 +1118,11 @@
                    SPV_ENV_VULKAN_1_0, SPV_ENV_VULKAN_1_1, SPV_ENV_VULKAN_1_2),
             ValuesIn(std::vector<AssemblyCase>{
                 {"OpExtension \"SPV_KHR_bit_instructions\"\n",
-                 MakeInstruction(SpvOpExtension,
+                 MakeInstruction(spv::Op::OpExtension,
                                  MakeVector("SPV_KHR_bit_instructions"))},
                 {"OpCapability BitInstructions\n",
-                 MakeInstruction(SpvOpCapability,
-                                 {SpvCapabilityBitInstructions})},
+                 MakeInstruction(spv::Op::OpCapability,
+                                 {(uint32_t)spv::Capability::BitInstructions})},
             })));
 
 // SPV_KHR_uniform_group_instructions
@@ -1044,35 +1135,44 @@
                SPV_ENV_VULKAN_1_2, SPV_ENV_VULKAN_1_3),
         ValuesIn(std::vector<AssemblyCase>{
             {"OpExtension \"SPV_KHR_uniform_group_instructions\"\n",
-             MakeInstruction(SpvOpExtension,
+             MakeInstruction(spv::Op::OpExtension,
                              MakeVector("SPV_KHR_uniform_group_instructions"))},
             {"OpCapability GroupUniformArithmeticKHR\n",
-             MakeInstruction(SpvOpCapability,
-                             {SpvCapabilityGroupUniformArithmeticKHR})},
+             MakeInstruction(
+                 spv::Op::OpCapability,
+                 {(uint32_t)spv::Capability::GroupUniformArithmeticKHR})},
             {"%2 = OpGroupIMulKHR %1 %3 Reduce %4\n",
-             MakeInstruction(SpvOpGroupIMulKHR,
-                             {1, 2, 3, SpvGroupOperationReduce, 4})},
+             MakeInstruction(spv::Op::OpGroupIMulKHR,
+                             {1, 2, 3, (uint32_t)spv::GroupOperation::Reduce,
+                              4})},
             {"%2 = OpGroupFMulKHR %1 %3 Reduce %4\n",
-             MakeInstruction(SpvOpGroupFMulKHR,
-                             {1, 2, 3, SpvGroupOperationReduce, 4})},
+             MakeInstruction(spv::Op::OpGroupFMulKHR,
+                             {1, 2, 3, (uint32_t)spv::GroupOperation::Reduce,
+                              4})},
             {"%2 = OpGroupBitwiseAndKHR %1 %3 Reduce %4\n",
-             MakeInstruction(SpvOpGroupBitwiseAndKHR,
-                             {1, 2, 3, SpvGroupOperationReduce, 4})},
+             MakeInstruction(spv::Op::OpGroupBitwiseAndKHR,
+                             {1, 2, 3, (uint32_t)spv::GroupOperation::Reduce,
+                              4})},
             {"%2 = OpGroupBitwiseOrKHR %1 %3 Reduce %4\n",
-             MakeInstruction(SpvOpGroupBitwiseOrKHR,
-                             {1, 2, 3, SpvGroupOperationReduce, 4})},
+             MakeInstruction(spv::Op::OpGroupBitwiseOrKHR,
+                             {1, 2, 3, (uint32_t)spv::GroupOperation::Reduce,
+                              4})},
             {"%2 = OpGroupBitwiseXorKHR %1 %3 Reduce %4\n",
-             MakeInstruction(SpvOpGroupBitwiseXorKHR,
-                             {1, 2, 3, SpvGroupOperationReduce, 4})},
+             MakeInstruction(spv::Op::OpGroupBitwiseXorKHR,
+                             {1, 2, 3, (uint32_t)spv::GroupOperation::Reduce,
+                              4})},
             {"%2 = OpGroupLogicalAndKHR %1 %3 Reduce %4\n",
-             MakeInstruction(SpvOpGroupLogicalAndKHR,
-                             {1, 2, 3, SpvGroupOperationReduce, 4})},
+             MakeInstruction(spv::Op::OpGroupLogicalAndKHR,
+                             {1, 2, 3, (uint32_t)spv::GroupOperation::Reduce,
+                              4})},
             {"%2 = OpGroupLogicalOrKHR %1 %3 Reduce %4\n",
-             MakeInstruction(SpvOpGroupLogicalOrKHR,
-                             {1, 2, 3, SpvGroupOperationReduce, 4})},
+             MakeInstruction(spv::Op::OpGroupLogicalOrKHR,
+                             {1, 2, 3, (uint32_t)spv::GroupOperation::Reduce,
+                              4})},
             {"%2 = OpGroupLogicalXorKHR %1 %3 Reduce %4\n",
-             MakeInstruction(SpvOpGroupLogicalXorKHR,
-                             {1, 2, 3, SpvGroupOperationReduce, 4})},
+             MakeInstruction(spv::Op::OpGroupLogicalXorKHR,
+                             {1, 2, 3, (uint32_t)spv::GroupOperation::Reduce,
+                              4})},
         })));
 
 // SPV_KHR_subgroup_rotate
@@ -1084,16 +1184,17 @@
                    SPV_ENV_VULKAN_1_3, SPV_ENV_OPENCL_2_1),
             ValuesIn(std::vector<AssemblyCase>{
                 {"OpExtension \"SPV_KHR_subgroup_rotate\"\n",
-                 MakeInstruction(SpvOpExtension,
+                 MakeInstruction(spv::Op::OpExtension,
                                  MakeVector("SPV_KHR_subgroup_rotate"))},
                 {"OpCapability GroupNonUniformRotateKHR\n",
-                 MakeInstruction(SpvOpCapability,
-                                 {SpvCapabilityGroupNonUniformRotateKHR})},
+                 MakeInstruction(
+                     spv::Op::OpCapability,
+                     {(uint32_t)spv::Capability::GroupNonUniformRotateKHR})},
                 {"%2 = OpGroupNonUniformRotateKHR %1 %3 %4 %5\n",
-                 MakeInstruction(SpvOpGroupNonUniformRotateKHR,
+                 MakeInstruction(spv::Op::OpGroupNonUniformRotateKHR,
                                  {1, 2, 3, 4, 5})},
                 {"%2 = OpGroupNonUniformRotateKHR %1 %3 %4 %5 %6\n",
-                 MakeInstruction(SpvOpGroupNonUniformRotateKHR,
+                 MakeInstruction(spv::Op::OpGroupNonUniformRotateKHR,
                                  {1, 2, 3, 4, 5, 6})},
             })));
 
diff --git a/test/text_to_binary.function_test.cpp b/test/text_to_binary.function_test.cpp
index 55a8e6c..9361d6c 100644
--- a/test/text_to_binary.function_test.cpp
+++ b/test/text_to_binary.function_test.cpp
@@ -33,25 +33,25 @@
 // Test OpFunction
 
 using OpFunctionControlTest = spvtest::TextToBinaryTestBase<
-    ::testing::TestWithParam<EnumCase<SpvFunctionControlMask>>>;
+    ::testing::TestWithParam<EnumCase<spv::FunctionControlMask>>>;
 
 TEST_P(OpFunctionControlTest, AnySingleFunctionControlMask) {
   const std::string input = "%result_id = OpFunction %result_type " +
                             GetParam().name() + " %function_type ";
-  EXPECT_THAT(
-      CompiledInstructions(input),
-      Eq(MakeInstruction(SpvOpFunction, {1, 2, GetParam().value(), 3})));
+  EXPECT_THAT(CompiledInstructions(input),
+              Eq(MakeInstruction(spv::Op::OpFunction,
+                                 {1, 2, (uint32_t)GetParam().value(), 3})));
 }
 
 // clang-format off
-#define CASE(VALUE,NAME) { SpvFunctionControl##VALUE, NAME }
+#define CASE(VALUE,NAME) { spv::FunctionControlMask::VALUE, NAME }
 INSTANTIATE_TEST_SUITE_P(TextToBinaryFunctionTest, OpFunctionControlTest,
-                        ::testing::ValuesIn(std::vector<EnumCase<SpvFunctionControlMask>>{
+                        ::testing::ValuesIn(std::vector<EnumCase<spv::FunctionControlMask>>{
                             CASE(MaskNone, "None"),
-                            CASE(InlineMask, "Inline"),
-                            CASE(DontInlineMask, "DontInline"),
-                            CASE(PureMask, "Pure"),
-                            CASE(ConstMask, "Const"),
+                            CASE(Inline, "Inline"),
+                            CASE(DontInline, "DontInline"),
+                            CASE(Pure, "Pure"),
+                            CASE(Const, "Const"),
                         }));
 #undef CASE
 // clang-format on
@@ -61,11 +61,12 @@
   // the instruction parsing logic with spvTextParseMask.
   const std::string input =
       "%result_id = OpFunction %result_type Inline|Pure|Const %function_type";
-  const uint32_t expected_mask = SpvFunctionControlInlineMask |
-                                 SpvFunctionControlPureMask |
-                                 SpvFunctionControlConstMask;
-  EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpFunction, {1, 2, expected_mask, 3})));
+  const uint32_t expected_mask = uint32_t(spv::FunctionControlMask::Inline |
+                                          spv::FunctionControlMask::Pure |
+                                          spv::FunctionControlMask::Const);
+  EXPECT_THAT(
+      CompiledInstructions(input),
+      Eq(MakeInstruction(spv::Op::OpFunction, {1, 2, expected_mask, 3})));
 }
 
 TEST_F(OpFunctionControlTest, WrongFunctionControl) {
diff --git a/test/text_to_binary.group_test.cpp b/test/text_to_binary.group_test.cpp
index becc3aa..606e00e 100644
--- a/test/text_to_binary.group_test.cpp
+++ b/test/text_to_binary.group_test.cpp
@@ -32,20 +32,20 @@
 // Test GroupOperation enum
 
 using GroupOperationTest = spvtest::TextToBinaryTestBase<
-    ::testing::TestWithParam<EnumCase<SpvGroupOperation>>>;
+    ::testing::TestWithParam<EnumCase<spv::GroupOperation>>>;
 
 TEST_P(GroupOperationTest, AnyGroupOperation) {
   const std::string input =
       "%result = OpGroupIAdd %type %scope " + GetParam().name() + " %x";
-  EXPECT_THAT(
-      CompiledInstructions(input),
-      Eq(MakeInstruction(SpvOpGroupIAdd, {1, 2, 3, GetParam().value(), 4})));
+  EXPECT_THAT(CompiledInstructions(input),
+              Eq(MakeInstruction(spv::Op::OpGroupIAdd,
+                                 {1, 2, 3, (uint32_t)GetParam().value(), 4})));
 }
 
 // clang-format off
-#define CASE(NAME) { SpvGroupOperation##NAME, #NAME}
+#define CASE(NAME) { spv::GroupOperation::NAME, #NAME}
 INSTANTIATE_TEST_SUITE_P(TextToBinaryGroupOperation, GroupOperationTest,
-                        ::testing::ValuesIn(std::vector<EnumCase<SpvGroupOperation>>{
+                        ::testing::ValuesIn(std::vector<EnumCase<spv::GroupOperation>>{
                             CASE(Reduce),
                             CASE(InclusiveScan),
                             CASE(ExclusiveScan),
diff --git a/test/text_to_binary.image_test.cpp b/test/text_to_binary.image_test.cpp
index 8d8ff43..3e7a560 100644
--- a/test/text_to_binary.image_test.cpp
+++ b/test/text_to_binary.image_test.cpp
@@ -45,11 +45,11 @@
   const std::string input =
       "%2 = OpImageFetch %1 %3 %4" + GetParam().image_operands + "\n";
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpImageFetch, {1, 2, 3, 4},
+              Eq(MakeInstruction(spv::Op::OpImageFetch, {1, 2, 3, 4},
                                  GetParam().expected_mask_and_operands)));
 }
 
-#define MASK(NAME) SpvImageOperands##NAME##Mask
+#define MASK(NAME) uint32_t(spv::ImageOperandsMask::NAME)
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryImageOperandsAny, ImageOperandsTest,
     ::testing::ValuesIn(std::vector<ImageOperandsCase>{
@@ -68,7 +68,7 @@
         {" MinLod %5", {MASK(MinLod), 5}},
     }));
 #undef MASK
-#define MASK(NAME) static_cast<uint32_t>(SpvImageOperands##NAME##Mask)
+#define MASK(NAME) static_cast<uint32_t>(spv::ImageOperandsMask::NAME)
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryImageOperandsCombination, ImageOperandsTest,
     ::testing::ValuesIn(std::vector<ImageOperandsCase>{
@@ -110,7 +110,7 @@
 TEST_F(OpImageTest, Valid) {
   const std::string input = "%2 = OpImage %1 %3\n";
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpImage, {1, 2, 3})));
+              Eq(MakeInstruction(spv::Op::OpImage, {1, 2, 3})));
 
   // Test the disassembler.
   EXPECT_THAT(EncodeAndDecodeSuccessfully(input), input);
@@ -153,7 +153,7 @@
 TEST_F(OpImageSparseReadTest, OnlyRequiredOperands) {
   const std::string input = "%2 = OpImageSparseRead %1 %3 %4\n";
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpImageSparseRead, {1, 2, 3, 4})));
+              Eq(MakeInstruction(spv::Op::OpImageSparseRead, {1, 2, 3, 4})));
   // Test the disassembler.
   EXPECT_THAT(EncodeAndDecodeSuccessfully(input), input);
 }
@@ -167,13 +167,13 @@
   const std::string input =
       "%2 = OpImageSparseRead %1 %3 %4" + GetParam().image_operands + "\n";
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpImageSparseRead, {1, 2, 3, 4},
+              Eq(MakeInstruction(spv::Op::OpImageSparseRead, {1, 2, 3, 4},
                                  GetParam().expected_mask_and_operands)));
   // Test the disassembler.
   EXPECT_THAT(EncodeAndDecodeSuccessfully(input), input);
 }
 
-#define MASK(NAME) SpvImageOperands##NAME##Mask
+#define MASK(NAME) uint32_t(spv::ImageOperandsMask::NAME)
 INSTANTIATE_TEST_SUITE_P(ImageSparseReadImageOperandsAny,
                          ImageSparseReadImageOperandsTest,
                          ::testing::ValuesIn(std::vector<ImageOperandsCase>{
@@ -190,7 +190,7 @@
                              {" MinLod %5", {MASK(MinLod), 5}},
                          }));
 #undef MASK
-#define MASK(NAME) static_cast<uint32_t>(SpvImageOperands##NAME##Mask)
+#define MASK(NAME) static_cast<uint32_t>(spv::ImageOperandsMask::NAME)
 INSTANTIATE_TEST_SUITE_P(
     ImageSparseReadImageOperandsCombination, ImageSparseReadImageOperandsTest,
     ::testing::ValuesIn(std::vector<ImageOperandsCase>{
diff --git a/test/text_to_binary.memory_test.cpp b/test/text_to_binary.memory_test.cpp
index f94c134..629ab66 100644
--- a/test/text_to_binary.memory_test.cpp
+++ b/test/text_to_binary.memory_test.cpp
@@ -35,51 +35,53 @@
 // Test assembly of Memory Access masks
 
 using MemoryAccessTest = spvtest::TextToBinaryTestBase<
-    ::testing::TestWithParam<EnumCase<SpvMemoryAccessMask>>>;
+    ::testing::TestWithParam<EnumCase<spv::MemoryAccessMask>>>;
 
 TEST_P(MemoryAccessTest, AnySingleMemoryAccessMask) {
   std::stringstream input;
   input << "OpStore %ptr %value " << GetParam().name();
   for (auto operand : GetParam().operands()) input << " " << operand;
-  EXPECT_THAT(CompiledInstructions(input.str()),
-              Eq(MakeInstruction(SpvOpStore, {1, 2, GetParam().value()},
-                                 GetParam().operands())));
+  EXPECT_THAT(
+      CompiledInstructions(input.str()),
+      Eq(MakeInstruction(spv::Op::OpStore, {1, 2, (uint32_t)GetParam().value()},
+                         GetParam().operands())));
 }
 
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryMemoryAccessTest, MemoryAccessTest,
-    ::testing::ValuesIn(std::vector<EnumCase<SpvMemoryAccessMask>>{
-        {SpvMemoryAccessMaskNone, "None", {}},
-        {SpvMemoryAccessVolatileMask, "Volatile", {}},
-        {SpvMemoryAccessAlignedMask, "Aligned", {16}},
-        {SpvMemoryAccessNontemporalMask, "Nontemporal", {}},
+    ::testing::ValuesIn(std::vector<EnumCase<spv::MemoryAccessMask>>{
+        {spv::MemoryAccessMask::MaskNone, "None", {}},
+        {spv::MemoryAccessMask::Volatile, "Volatile", {}},
+        {spv::MemoryAccessMask::Aligned, "Aligned", {16}},
+        {spv::MemoryAccessMask::Nontemporal, "Nontemporal", {}},
     }));
 
 TEST_F(TextToBinaryTest, CombinedMemoryAccessMask) {
   const std::string input = "OpStore %ptr %value Volatile|Aligned 16";
-  const uint32_t expected_mask =
-      SpvMemoryAccessVolatileMask | SpvMemoryAccessAlignedMask;
+  const uint32_t expected_mask = uint32_t(spv::MemoryAccessMask::Volatile |
+                                          spv::MemoryAccessMask::Aligned);
   EXPECT_THAT(expected_mask, Eq(3u));
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpStore, {1, 2, expected_mask, 16})));
+              Eq(MakeInstruction(spv::Op::OpStore, {1, 2, expected_mask, 16})));
 }
 
 // Test Storage Class enum values
 
 using StorageClassTest = spvtest::TextToBinaryTestBase<
-    ::testing::TestWithParam<EnumCase<SpvStorageClass>>>;
+    ::testing::TestWithParam<EnumCase<spv::StorageClass>>>;
 
 TEST_P(StorageClassTest, AnyStorageClass) {
   const std::string input = "%1 = OpVariable %2 " + GetParam().name();
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpVariable, {1, 2, GetParam().value()})));
+              Eq(MakeInstruction(spv::Op::OpVariable,
+                                 {1, 2, (uint32_t)GetParam().value()})));
 }
 
 // clang-format off
-#define CASE(NAME) { SpvStorageClass##NAME, #NAME, {} }
+#define CASE(NAME) { spv::StorageClass::NAME, #NAME, {} }
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryStorageClassTest, StorageClassTest,
-    ::testing::ValuesIn(std::vector<EnumCase<SpvStorageClass>>{
+    ::testing::ValuesIn(std::vector<EnumCase<spv::StorageClass>>{
         CASE(UniformConstant),
         CASE(Input),
         CASE(Uniform),
@@ -103,7 +105,7 @@
 TEST_F(MemoryRoundTripTest, OpPtrEqualGood) {
   std::string spirv = "%2 = OpPtrEqual %1 %3 %4\n";
   EXPECT_THAT(CompiledInstructions(spirv, SPV_ENV_UNIVERSAL_1_4),
-              Eq(MakeInstruction(SpvOpPtrEqual, {1, 2, 3, 4})));
+              Eq(MakeInstruction(spv::Op::OpPtrEqual, {1, 2, 3, 4})));
   std::string disassembly = EncodeAndDecodeSuccessfully(
       spirv, SPV_BINARY_TO_TEXT_OPTION_NONE, SPV_ENV_UNIVERSAL_1_4);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -120,7 +122,7 @@
 TEST_F(MemoryRoundTripTest, OpPtrNotEqualGood) {
   std::string spirv = "%2 = OpPtrNotEqual %1 %3 %4\n";
   EXPECT_THAT(CompiledInstructions(spirv, SPV_ENV_UNIVERSAL_1_4),
-              Eq(MakeInstruction(SpvOpPtrNotEqual, {1, 2, 3, 4})));
+              Eq(MakeInstruction(spv::Op::OpPtrNotEqual, {1, 2, 3, 4})));
   std::string disassembly = EncodeAndDecodeSuccessfully(
       spirv, SPV_BINARY_TO_TEXT_OPTION_NONE, SPV_ENV_UNIVERSAL_1_4);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -137,7 +139,7 @@
 TEST_F(MemoryRoundTripTest, OpPtrDiffGood) {
   std::string spirv = "%2 = OpPtrDiff %1 %3 %4\n";
   EXPECT_THAT(CompiledInstructions(spirv, SPV_ENV_UNIVERSAL_1_4),
-              Eq(MakeInstruction(SpvOpPtrDiff, {1, 2, 3, 4})));
+              Eq(MakeInstruction(spv::Op::OpPtrDiff, {1, 2, 3, 4})));
   std::string disassembly = EncodeAndDecodeSuccessfully(
       spirv, SPV_BINARY_TO_TEXT_OPTION_NONE, SPV_ENV_UNIVERSAL_1_4);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -157,7 +159,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemoryNoMemAccessGood) {
   std::string spirv = "OpCopyMemory %1 %2\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemory, {1, 2})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -179,7 +181,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemoryAccessNoneGood) {
   std::string spirv = "OpCopyMemory %1 %2 None\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 0})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 0})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -188,7 +190,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemoryAccessVolatileGood) {
   std::string spirv = "OpCopyMemory %1 %2 Volatile\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 1})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 1})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -197,7 +199,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemoryAccessAligned8Good) {
   std::string spirv = "OpCopyMemory %1 %2 Aligned 8\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 2, 8})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 2, 8})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -206,7 +208,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemoryAccessNontemporalGood) {
   std::string spirv = "OpCopyMemory %1 %2 Nontemporal\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 4})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 4})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -215,7 +217,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemoryAccessAvGood) {
   std::string spirv = "OpCopyMemory %1 %2 MakePointerAvailable %3\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 8, 3})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 8, 3})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -224,7 +226,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemoryAccessVisGood) {
   std::string spirv = "OpCopyMemory %1 %2 MakePointerVisible %3\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 16, 3})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 16, 3})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -233,7 +235,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemoryAccessNonPrivateGood) {
   std::string spirv = "OpCopyMemory %1 %2 NonPrivatePointer\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 32})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 32})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -245,7 +247,7 @@
       "Volatile|Aligned|Nontemporal|MakePointerAvailable|"
       "MakePointerVisible|NonPrivatePointer 16 %3 %4\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 63, 16, 3, 4})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 63, 16, 3, 4})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -255,7 +257,7 @@
   std::string spirv = "OpCopyMemory %1 %2 Volatile Volatile\n";
   // Note: This will assemble but should not validate for SPIR-V 1.3
   EXPECT_THAT(CompiledInstructions(spirv, SPV_ENV_UNIVERSAL_1_3),
-              Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 1, 1})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 1, 1})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -264,7 +266,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemoryTwoAccessV14Good) {
   std::string spirv = "OpCopyMemory %1 %2 Volatile Volatile\n";
   EXPECT_THAT(CompiledInstructions(spirv, SPV_ENV_UNIVERSAL_1_4),
-              Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 1, 1})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 1, 1})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -275,8 +277,9 @@
       "OpCopyMemory %1 %2 Volatile|Nontemporal|"
       "MakePointerVisible %3 "
       "Aligned|MakePointerAvailable|NonPrivatePointer 16 %4\n";
-  EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemory, {1, 2, 21, 3, 42, 16, 4})));
+  EXPECT_THAT(
+      CompiledInstructions(spirv),
+      Eq(MakeInstruction(spv::Op::OpCopyMemory, {1, 2, 21, 3, 42, 16, 4})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -287,7 +290,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemorySizedNoMemAccessGood) {
   std::string spirv = "OpCopyMemorySized %1 %2 %3\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -309,7 +312,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemorySizedAccessNoneGood) {
   std::string spirv = "OpCopyMemorySized %1 %2 %3 None\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 0})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3, 0})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -318,7 +321,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemorySizedAccessVolatileGood) {
   std::string spirv = "OpCopyMemorySized %1 %2 %3 Volatile\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 1})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3, 1})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -327,7 +330,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemorySizedAccessAligned8Good) {
   std::string spirv = "OpCopyMemorySized %1 %2 %3 Aligned 8\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 2, 8})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3, 2, 8})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -336,7 +339,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemorySizedAccessNontemporalGood) {
   std::string spirv = "OpCopyMemorySized %1 %2 %3 Nontemporal\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 4})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3, 4})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -345,7 +348,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemorySizedAccessAvGood) {
   std::string spirv = "OpCopyMemorySized %1 %2 %3 MakePointerAvailable %4\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 8, 4})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3, 8, 4})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -353,8 +356,9 @@
 
 TEST_F(MemoryRoundTripTest, OpCopyMemorySizedAccessVisGood) {
   std::string spirv = "OpCopyMemorySized %1 %2 %3 MakePointerVisible %4\n";
-  EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 16, 4})));
+  EXPECT_THAT(
+      CompiledInstructions(spirv),
+      Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3, 16, 4})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -363,7 +367,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemorySizedAccessNonPrivateGood) {
   std::string spirv = "OpCopyMemorySized %1 %2 %3 NonPrivatePointer\n";
   EXPECT_THAT(CompiledInstructions(spirv),
-              Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 32})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3, 32})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -376,7 +380,7 @@
       "MakePointerVisible|NonPrivatePointer 16 %4 %5\n";
   EXPECT_THAT(
       CompiledInstructions(spirv),
-      Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 63, 16, 4, 5})));
+      Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3, 63, 16, 4, 5})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -386,7 +390,7 @@
   std::string spirv = "OpCopyMemorySized %1 %2 %3 Volatile Volatile\n";
   // Note: This will assemble but should not validate for SPIR-V 1.3
   EXPECT_THAT(CompiledInstructions(spirv, SPV_ENV_UNIVERSAL_1_3),
-              Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 1, 1})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3, 1, 1})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -395,7 +399,7 @@
 TEST_F(MemoryRoundTripTest, OpCopyMemorySizedTwoAccessV14Good) {
   std::string spirv = "OpCopyMemorySized %1 %2 %3 Volatile Volatile\n";
   EXPECT_THAT(CompiledInstructions(spirv, SPV_ENV_UNIVERSAL_1_4),
-              Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 1, 1})));
+              Eq(MakeInstruction(spv::Op::OpCopyMemorySized, {1, 2, 3, 1, 1})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
@@ -406,9 +410,9 @@
       "OpCopyMemorySized %1 %2 %3 Volatile|Nontemporal|"
       "MakePointerVisible %4 "
       "Aligned|MakePointerAvailable|NonPrivatePointer 16 %5\n";
-  EXPECT_THAT(
-      CompiledInstructions(spirv),
-      Eq(MakeInstruction(SpvOpCopyMemorySized, {1, 2, 3, 21, 4, 42, 16, 5})));
+  EXPECT_THAT(CompiledInstructions(spirv),
+              Eq(MakeInstruction(spv::Op::OpCopyMemorySized,
+                                 {1, 2, 3, 21, 4, 42, 16, 5})));
   std::string disassembly =
       EncodeAndDecodeSuccessfully(spirv, SPV_BINARY_TO_TEXT_OPTION_NONE);
   EXPECT_THAT(disassembly, Eq(spirv));
diff --git a/test/text_to_binary.misc_test.cpp b/test/text_to_binary.misc_test.cpp
index 03b1e09..9ee425a 100644
--- a/test/text_to_binary.misc_test.cpp
+++ b/test/text_to_binary.misc_test.cpp
@@ -29,7 +29,8 @@
 using TextToBinaryMisc = spvtest::TextToBinaryTest;
 
 TEST_F(TextToBinaryMisc, OpNop) {
-  EXPECT_THAT(CompiledInstructions("OpNop"), Eq(MakeInstruction(SpvOpNop, {})));
+  EXPECT_THAT(CompiledInstructions("OpNop"),
+              Eq(MakeInstruction(spv::Op::OpNop, {})));
 }
 
 TEST_F(TextToBinaryMisc, OpUndef) {
@@ -37,7 +38,8 @@
                                                    %u = OpUndef %f32)");
   const uint32_t typeID = 1;
   EXPECT_THAT(code[1], Eq(typeID));
-  EXPECT_THAT(Subvector(code, 3), Eq(MakeInstruction(SpvOpUndef, {typeID, 2})));
+  EXPECT_THAT(Subvector(code, 3),
+              Eq(MakeInstruction(spv::Op::OpUndef, {typeID, 2})));
 }
 
 TEST_F(TextToBinaryMisc, OpWrong) {
diff --git a/test/text_to_binary.mode_setting_test.cpp b/test/text_to_binary.mode_setting_test.cpp
index 7f15c8b..c62ba3e 100644
--- a/test/text_to_binary.mode_setting_test.cpp
+++ b/test/text_to_binary.mode_setting_test.cpp
@@ -46,9 +46,9 @@
   uint32_t get_memory_value() const {
     return static_cast<uint32_t>(memory_value);
   }
-  SpvAddressingModel addressing_value;
+  spv::AddressingModel addressing_value;
   std::string addressing_name;
-  SpvMemoryModel memory_value;
+  spv::MemoryModel memory_value;
   std::string memory_name;
 };
 
@@ -58,16 +58,16 @@
 TEST_P(OpMemoryModelTest, AnyMemoryModelCase) {
   const std::string input = "OpMemoryModel " + GetParam().addressing_name +
                             " " + GetParam().memory_name;
-  EXPECT_THAT(
-      CompiledInstructions(input),
-      Eq(MakeInstruction(SpvOpMemoryModel, {GetParam().get_addressing_value(),
-                                            GetParam().get_memory_value()})));
+  EXPECT_THAT(CompiledInstructions(input),
+              Eq(MakeInstruction(spv::Op::OpMemoryModel,
+                                 {GetParam().get_addressing_value(),
+                                  GetParam().get_memory_value()})));
 }
 
-#define CASE(ADDRESSING, MEMORY)                                         \
-  {                                                                      \
-    SpvAddressingModel##ADDRESSING, #ADDRESSING, SpvMemoryModel##MEMORY, \
-        #MEMORY                                                          \
+#define CASE(ADDRESSING, MEMORY)                                             \
+  {                                                                          \
+    spv::AddressingModel::ADDRESSING, #ADDRESSING, spv::MemoryModel::MEMORY, \
+        #MEMORY                                                              \
   }
 // clang-format off
 INSTANTIATE_TEST_SUITE_P(TextToBinaryMemoryModel, OpMemoryModelTest,
@@ -97,7 +97,7 @@
   uint32_t get_execution_value() const {
     return static_cast<uint32_t>(execution_value);
   }
-  SpvExecutionModel execution_value;
+  spv::ExecutionModel execution_value;
   std::string execution_name;
   std::string entry_point_name;
 };
@@ -109,14 +109,14 @@
   // TODO(dneto): utf-8, escaping, quoting cases for entry point name.
   const std::string input = "OpEntryPoint " + GetParam().execution_name +
                             " %1 \"" + GetParam().entry_point_name + "\"";
-  EXPECT_THAT(
-      CompiledInstructions(input),
-      Eq(MakeInstruction(SpvOpEntryPoint, {GetParam().get_execution_value(), 1},
-                         MakeVector(GetParam().entry_point_name))));
+  EXPECT_THAT(CompiledInstructions(input),
+              Eq(MakeInstruction(spv::Op::OpEntryPoint,
+                                 {GetParam().get_execution_value(), 1},
+                                 MakeVector(GetParam().entry_point_name))));
 }
 
 // clang-format off
-#define CASE(NAME) SpvExecutionModel##NAME, #NAME
+#define CASE(NAME) spv::ExecutionModel::NAME, #NAME
 INSTANTIATE_TEST_SUITE_P(TextToBinaryEntryPoint, OpEntryPointTest,
                         ValuesIn(std::vector<EntryPointCase>{
                           { CASE(Vertex), "" },
@@ -137,7 +137,7 @@
 
 // Test OpExecutionMode
 using OpExecutionModeTest = spvtest::TextToBinaryTestBase<
-    TestWithParam<std::tuple<spv_target_env, EnumCase<SpvExecutionMode>>>>;
+    TestWithParam<std::tuple<spv_target_env, EnumCase<spv::ExecutionMode>>>>;
 
 TEST_P(OpExecutionModeTest, AnyExecutionMode) {
   // This string should assemble, but should not validate.
@@ -146,16 +146,16 @@
   for (auto operand : std::get<1>(GetParam()).operands())
     input << " " << operand;
   EXPECT_THAT(CompiledInstructions(input.str(), std::get<0>(GetParam())),
-              Eq(MakeInstruction(SpvOpExecutionMode,
+              Eq(MakeInstruction(spv::Op::OpExecutionMode,
                                  {1, std::get<1>(GetParam()).value()},
                                  std::get<1>(GetParam()).operands())));
 }
 
-#define CASE(NAME) SpvExecutionMode##NAME, #NAME
+#define CASE(NAME) spv::ExecutionMode::NAME, #NAME
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryExecutionMode, OpExecutionModeTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
-            ValuesIn(std::vector<EnumCase<SpvExecutionMode>>{
+            ValuesIn(std::vector<EnumCase<spv::ExecutionMode>>{
                 // The operand literal values are arbitrarily chosen,
                 // but there are the right number of them.
                 {CASE(Invocations), {101}},
@@ -195,7 +195,7 @@
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryExecutionModeV11, OpExecutionModeTest,
     Combine(Values(SPV_ENV_UNIVERSAL_1_1),
-            ValuesIn(std::vector<EnumCase<SpvExecutionMode>>{
+            ValuesIn(std::vector<EnumCase<spv::ExecutionMode>>{
                 {CASE(Initializer)},
                 {CASE(Finalizer)},
                 {CASE(SubgroupSize), {12}},
@@ -216,18 +216,18 @@
 // Test OpCapability
 
 using OpCapabilityTest =
-    spvtest::TextToBinaryTestBase<TestWithParam<EnumCase<SpvCapability>>>;
+    spvtest::TextToBinaryTestBase<TestWithParam<EnumCase<spv::Capability>>>;
 
 TEST_P(OpCapabilityTest, AnyCapability) {
   const std::string input = "OpCapability " + GetParam().name();
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpCapability, {GetParam().value()})));
+              Eq(MakeInstruction(spv::Op::OpCapability, {GetParam().value()})));
 }
 
 // clang-format off
-#define CASE(NAME) { SpvCapability##NAME, #NAME }
+#define CASE(NAME) { spv::Capability::NAME, #NAME }
 INSTANTIATE_TEST_SUITE_P(TextToBinaryCapability, OpCapabilityTest,
-                        ValuesIn(std::vector<EnumCase<SpvCapability>>{
+                        ValuesIn(std::vector<EnumCase<spv::Capability>>{
                             CASE(Matrix),
                             CASE(Shader),
                             CASE(Geometry),
diff --git a/test/text_to_binary.pipe_storage_test.cpp b/test/text_to_binary.pipe_storage_test.cpp
index 955f5ef..2a41d42 100644
--- a/test/text_to_binary.pipe_storage_test.cpp
+++ b/test/text_to_binary.pipe_storage_test.cpp
@@ -28,7 +28,7 @@
 TEST_F(OpTypePipeStorageTest, OpcodeAssemblesInV10) {
   EXPECT_THAT(
       CompiledInstructions("%res = OpTypePipeStorage", SPV_ENV_UNIVERSAL_1_0),
-      Eq(MakeInstruction(SpvOpTypePipeStorage, {1})));
+      Eq(MakeInstruction(spv::Op::OpTypePipeStorage, {1})));
 }
 
 TEST_F(OpTypePipeStorageTest, ArgumentCount) {
@@ -38,7 +38,7 @@
          "'OpTypePipeStorage'."));
   EXPECT_THAT(
       CompiledInstructions("%res = OpTypePipeStorage", SPV_ENV_UNIVERSAL_1_1),
-      Eq(MakeInstruction(SpvOpTypePipeStorage, {1})));
+      Eq(MakeInstruction(spv::Op::OpTypePipeStorage, {1})));
   EXPECT_THAT(CompileFailure("%res = OpTypePipeStorage %1 %2 %3 %4 %5",
                              SPV_ENV_UNIVERSAL_1_1),
               Eq("'=' expected after result id."));
@@ -47,9 +47,10 @@
 using OpConstantPipeStorageTest = spvtest::TextToBinaryTest;
 
 TEST_F(OpConstantPipeStorageTest, OpcodeAssemblesInV10) {
-  EXPECT_THAT(CompiledInstructions("%1 = OpConstantPipeStorage %2 3 4 5",
-                                   SPV_ENV_UNIVERSAL_1_0),
-              Eq(MakeInstruction(SpvOpConstantPipeStorage, {1, 2, 3, 4, 5})));
+  EXPECT_THAT(
+      CompiledInstructions("%1 = OpConstantPipeStorage %2 3 4 5",
+                           SPV_ENV_UNIVERSAL_1_0),
+      Eq(MakeInstruction(spv::Op::OpConstantPipeStorage, {1, 2, 3, 4, 5})));
 }
 
 TEST_F(OpConstantPipeStorageTest, ArgumentCount) {
@@ -65,9 +66,10 @@
                              SPV_ENV_UNIVERSAL_1_1),
               Eq("Expected operand for OpConstantPipeStorage instruction, but "
                  "found the end of the stream."));
-  EXPECT_THAT(CompiledInstructions("%1 = OpConstantPipeStorage %2 3 4 5",
-                                   SPV_ENV_UNIVERSAL_1_1),
-              Eq(MakeInstruction(SpvOpConstantPipeStorage, {1, 2, 3, 4, 5})));
+  EXPECT_THAT(
+      CompiledInstructions("%1 = OpConstantPipeStorage %2 3 4 5",
+                           SPV_ENV_UNIVERSAL_1_1),
+      Eq(MakeInstruction(spv::Op::OpConstantPipeStorage, {1, 2, 3, 4, 5})));
   EXPECT_THAT(CompileFailure("%1 = OpConstantPipeStorage %2 3 4 5 %6 %7",
                              SPV_ENV_UNIVERSAL_1_1),
               Eq("'=' expected after result id."));
@@ -91,9 +93,10 @@
 using OpCreatePipeFromPipeStorageTest = spvtest::TextToBinaryTest;
 
 TEST_F(OpCreatePipeFromPipeStorageTest, OpcodeAssemblesInV10) {
-  EXPECT_THAT(CompiledInstructions("%1 = OpCreatePipeFromPipeStorage %2 %3",
-                                   SPV_ENV_UNIVERSAL_1_0),
-              Eq(MakeInstruction(SpvOpCreatePipeFromPipeStorage, {1, 2, 3})));
+  EXPECT_THAT(
+      CompiledInstructions("%1 = OpCreatePipeFromPipeStorage %2 %3",
+                           SPV_ENV_UNIVERSAL_1_0),
+      Eq(MakeInstruction(spv::Op::OpCreatePipeFromPipeStorage, {1, 2, 3})));
 }
 
 TEST_F(OpCreatePipeFromPipeStorageTest, ArgumentCount) {
@@ -109,9 +112,10 @@
                              SPV_ENV_UNIVERSAL_1_1),
               Eq("Expected operand for OpCreatePipeFromPipeStorage "
                  "instruction, but found the next instruction instead."));
-  EXPECT_THAT(CompiledInstructions("%1 = OpCreatePipeFromPipeStorage %2 %3",
-                                   SPV_ENV_UNIVERSAL_1_1),
-              Eq(MakeInstruction(SpvOpCreatePipeFromPipeStorage, {1, 2, 3})));
+  EXPECT_THAT(
+      CompiledInstructions("%1 = OpCreatePipeFromPipeStorage %2 %3",
+                           SPV_ENV_UNIVERSAL_1_1),
+      Eq(MakeInstruction(spv::Op::OpCreatePipeFromPipeStorage, {1, 2, 3})));
   EXPECT_THAT(CompileFailure("%1 = OpCreatePipeFromPipeStorage %2 %3 %4 %5",
                              SPV_ENV_UNIVERSAL_1_1),
               Eq("'=' expected after result id."));
diff --git a/test/text_to_binary.reserved_sampling_test.cpp b/test/text_to_binary.reserved_sampling_test.cpp
index 42e4e2a..abc1667 100644
--- a/test/text_to_binary.reserved_sampling_test.cpp
+++ b/test/text_to_binary.reserved_sampling_test.cpp
@@ -30,33 +30,36 @@
 
 TEST_F(ReservedSamplingInstTest, OpImageSparseSampleProjImplicitLod) {
   std::string input = "%2 = OpImageSparseSampleProjImplicitLod %1 %3 %4\n";
-  EXPECT_THAT(
-      CompiledInstructions(input, SPV_ENV_UNIVERSAL_1_0),
-      Eq(MakeInstruction(SpvOpImageSparseSampleProjImplicitLod, {1, 2, 3, 4})));
+  EXPECT_THAT(CompiledInstructions(input, SPV_ENV_UNIVERSAL_1_0),
+              Eq(MakeInstruction(spv::Op::OpImageSparseSampleProjImplicitLod,
+                                 {1, 2, 3, 4})));
 }
 
 TEST_F(ReservedSamplingInstTest, OpImageSparseSampleProjExplicitLod) {
   std::string input =
       "%2 = OpImageSparseSampleProjExplicitLod %1 %3 %4 Lod %5\n";
   EXPECT_THAT(CompiledInstructions(input, SPV_ENV_UNIVERSAL_1_0),
-              Eq(MakeInstruction(SpvOpImageSparseSampleProjExplicitLod,
-                                 {1, 2, 3, 4, SpvImageOperandsLodMask, 5})));
+              Eq(MakeInstruction(
+                  spv::Op::OpImageSparseSampleProjExplicitLod,
+                  {1, 2, 3, 4, (uint32_t)spv::ImageOperandsMask::Lod, 5})));
 }
 
 TEST_F(ReservedSamplingInstTest, OpImageSparseSampleProjDrefImplicitLod) {
   std::string input =
       "%2 = OpImageSparseSampleProjDrefImplicitLod %1 %3 %4 %5\n";
-  EXPECT_THAT(CompiledInstructions(input, SPV_ENV_UNIVERSAL_1_0),
-              Eq(MakeInstruction(SpvOpImageSparseSampleProjDrefImplicitLod,
-                                 {1, 2, 3, 4, 5})));
+  EXPECT_THAT(
+      CompiledInstructions(input, SPV_ENV_UNIVERSAL_1_0),
+      Eq(MakeInstruction(spv::Op::OpImageSparseSampleProjDrefImplicitLod,
+                         {1, 2, 3, 4, 5})));
 }
 
 TEST_F(ReservedSamplingInstTest, OpImageSparseSampleProjDrefExplicitLod) {
   std::string input =
       "%2 = OpImageSparseSampleProjDrefExplicitLod %1 %3 %4 %5 Lod %6\n";
   EXPECT_THAT(CompiledInstructions(input, SPV_ENV_UNIVERSAL_1_0),
-              Eq(MakeInstruction(SpvOpImageSparseSampleProjDrefExplicitLod,
-                                 {1, 2, 3, 4, 5, SpvImageOperandsLodMask, 6})));
+              Eq(MakeInstruction(
+                  spv::Op::OpImageSparseSampleProjDrefExplicitLod,
+                  {1, 2, 3, 4, 5, (uint32_t)spv::ImageOperandsMask::Lod, 6})));
 }
 
 }  // namespace
diff --git a/test/text_to_binary.subgroup_dispatch_test.cpp b/test/text_to_binary.subgroup_dispatch_test.cpp
index 8c40445..45d7780 100644
--- a/test/text_to_binary.subgroup_dispatch_test.cpp
+++ b/test/text_to_binary.subgroup_dispatch_test.cpp
@@ -35,7 +35,7 @@
       CompiledInstructions("%res = OpGetKernelLocalSizeForSubgroupCount %type "
                            "%sgcount %invoke %param %param_size %param_align",
                            SPV_ENV_UNIVERSAL_1_0),
-      Eq(MakeInstruction(SpvOpGetKernelLocalSizeForSubgroupCount,
+      Eq(MakeInstruction(spv::Op::OpGetKernelLocalSizeForSubgroupCount,
                          {1, 2, 3, 4, 5, 6, 7})));
 }
 
@@ -57,7 +57,7 @@
       CompiledInstructions("%res = OpGetKernelLocalSizeForSubgroupCount %type "
                            "%sgcount %invoke %param %param_size %param_align",
                            SPV_ENV_UNIVERSAL_1_1),
-      Eq(MakeInstruction(SpvOpGetKernelLocalSizeForSubgroupCount,
+      Eq(MakeInstruction(spv::Op::OpGetKernelLocalSizeForSubgroupCount,
                          {1, 2, 3, 4, 5, 6, 7})));
   EXPECT_THAT(
       CompileFailure("%res = OpGetKernelLocalSizeForSubgroupCount %type "
@@ -81,11 +81,11 @@
 using OpGetKernelMaxNumSubgroupsTest = spvtest::TextToBinaryTest;
 
 TEST_F(OpGetKernelMaxNumSubgroupsTest, OpcodeAssemblesInV10) {
-  EXPECT_THAT(
-      CompiledInstructions("%res = OpGetKernelMaxNumSubgroups %type "
-                           "%invoke %param %param_size %param_align",
-                           SPV_ENV_UNIVERSAL_1_0),
-      Eq(MakeInstruction(SpvOpGetKernelMaxNumSubgroups, {1, 2, 3, 4, 5, 6})));
+  EXPECT_THAT(CompiledInstructions("%res = OpGetKernelMaxNumSubgroups %type "
+                                   "%invoke %param %param_size %param_align",
+                                   SPV_ENV_UNIVERSAL_1_0),
+              Eq(MakeInstruction(spv::Op::OpGetKernelMaxNumSubgroups,
+                                 {1, 2, 3, 4, 5, 6})));
 }
 
 TEST_F(OpGetKernelMaxNumSubgroupsTest, ArgumentCount) {
@@ -101,11 +101,11 @@
                              SPV_ENV_UNIVERSAL_1_1),
               Eq("Expected operand for OpGetKernelMaxNumSubgroups instruction, "
                  "but found the end of the stream."));
-  EXPECT_THAT(
-      CompiledInstructions("%res = OpGetKernelMaxNumSubgroups %type "
-                           "%invoke %param %param_size %param_align",
-                           SPV_ENV_UNIVERSAL_1_1),
-      Eq(MakeInstruction(SpvOpGetKernelMaxNumSubgroups, {1, 2, 3, 4, 5, 6})));
+  EXPECT_THAT(CompiledInstructions("%res = OpGetKernelMaxNumSubgroups %type "
+                                   "%invoke %param %param_size %param_align",
+                                   SPV_ENV_UNIVERSAL_1_1),
+              Eq(MakeInstruction(spv::Op::OpGetKernelMaxNumSubgroups,
+                                 {1, 2, 3, 4, 5, 6})));
   EXPECT_THAT(CompileFailure("%res = OpGetKernelMaxNumSubgroups %type %invoke "
                              "%param %param_size %param_align %extra",
                              SPV_ENV_UNIVERSAL_1_1),
diff --git a/test/text_to_binary.type_declaration_test.cpp b/test/text_to_binary.type_declaration_test.cpp
index 65a2355..241600e 100644
--- a/test/text_to_binary.type_declaration_test.cpp
+++ b/test/text_to_binary.type_declaration_test.cpp
@@ -32,28 +32,29 @@
 // Test Dim enums via OpTypeImage
 
 using DimTest =
-    spvtest::TextToBinaryTestBase<::testing::TestWithParam<EnumCase<SpvDim>>>;
+    spvtest::TextToBinaryTestBase<::testing::TestWithParam<EnumCase<spv::Dim>>>;
 
 TEST_P(DimTest, AnyDim) {
   const std::string input =
       "%1 = OpTypeImage %2 " + GetParam().name() + " 2 3 0 4 Rgba8\n";
-  EXPECT_THAT(
-      CompiledInstructions(input),
-      Eq(MakeInstruction(SpvOpTypeImage, {1, 2, GetParam().value(), 2, 3, 0, 4,
-                                          SpvImageFormatRgba8})));
+  EXPECT_THAT(CompiledInstructions(input),
+              Eq(MakeInstruction(spv::Op::OpTypeImage,
+                                 {1, 2, (uint32_t)GetParam().value(), 2, 3, 0,
+                                  4, (uint32_t)spv::ImageFormat::Rgba8})));
 
   // Check the disassembler as well.
   EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(input));
 }
 
 // clang-format off
-#define CASE(NAME) {SpvDim##NAME, #NAME}
+#define CASE(NAME) {spv::Dim::NAME, #NAME}
+#define CASE1(DIM, NAME) {spv::Dim::DIM, #NAME}
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryDim, DimTest,
-    ::testing::ValuesIn(std::vector<EnumCase<SpvDim>>{
-        CASE(1D),
-        CASE(2D),
-        CASE(3D),
+    ::testing::ValuesIn(std::vector<EnumCase<spv::Dim>>{
+        CASE1(Dim1D, 1D),
+        CASE1(Dim2D, 2D),
+        CASE1(Dim3D, 3D),
         CASE(Cube),
         CASE(Rect),
         CASE(Buffer),
@@ -70,23 +71,24 @@
 // Test ImageFormat enums via OpTypeImage
 
 using ImageFormatTest = spvtest::TextToBinaryTestBase<
-    ::testing::TestWithParam<EnumCase<SpvImageFormat>>>;
+    ::testing::TestWithParam<EnumCase<spv::ImageFormat>>>;
 
 TEST_P(ImageFormatTest, AnyImageFormatAndNoAccessQualifier) {
   const std::string input =
       "%1 = OpTypeImage %2 1D 2 3 0 4 " + GetParam().name() + "\n";
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpTypeImage, {1, 2, SpvDim1D, 2, 3, 0, 4,
-                                                  GetParam().value()})));
+              Eq(MakeInstruction(spv::Op::OpTypeImage,
+                                 {1, 2, (uint32_t)spv::Dim::Dim1D, 2, 3, 0, 4,
+                                  GetParam().value()})));
   // Check the disassembler as well.
   EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(input));
 }
 
 // clang-format off
-#define CASE(NAME) {SpvImageFormat##NAME, #NAME}
+#define CASE(NAME) {spv::ImageFormat::NAME, #NAME}
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryImageFormat, ImageFormatTest,
-    ::testing::ValuesIn(std::vector<EnumCase<SpvImageFormat>>{
+    ::testing::ValuesIn(std::vector<EnumCase<spv::ImageFormat>>{
         CASE(Unknown),
         CASE(Rgba32f),
         CASE(Rgba16f),
@@ -138,24 +140,25 @@
 
 // Test AccessQualifier enums via OpTypeImage.
 using ImageAccessQualifierTest = spvtest::TextToBinaryTestBase<
-    ::testing::TestWithParam<EnumCase<SpvAccessQualifier>>>;
+    ::testing::TestWithParam<EnumCase<spv::AccessQualifier>>>;
 
 TEST_P(ImageAccessQualifierTest, AnyAccessQualifier) {
   const std::string input =
       "%1 = OpTypeImage %2 1D 2 3 0 4 Rgba8 " + GetParam().name() + "\n";
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpTypeImage,
-                                 {1, 2, SpvDim1D, 2, 3, 0, 4,
-                                  SpvImageFormatRgba8, GetParam().value()})));
+              Eq(MakeInstruction(
+                  spv::Op::OpTypeImage,
+                  {1, 2, (uint32_t)spv::Dim::Dim1D, 2, 3, 0, 4,
+                   (uint32_t)spv::ImageFormat::Rgba8, GetParam().value()})));
   // Check the disassembler as well.
   EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(input));
 }
 
 // clang-format off
-#define CASE(NAME) {SpvAccessQualifier##NAME, #NAME}
+#define CASE(NAME) {spv::AccessQualifier::NAME, #NAME}
 INSTANTIATE_TEST_SUITE_P(
     AccessQualifier, ImageAccessQualifierTest,
-    ::testing::ValuesIn(std::vector<EnumCase<SpvAccessQualifier>>{
+    ::testing::ValuesIn(std::vector<EnumCase<spv::AccessQualifier>>{
       CASE(ReadOnly),
       CASE(WriteOnly),
       CASE(ReadWrite),
@@ -166,21 +169,22 @@
 // Test AccessQualifier enums via OpTypePipe.
 
 using OpTypePipeTest = spvtest::TextToBinaryTestBase<
-    ::testing::TestWithParam<EnumCase<SpvAccessQualifier>>>;
+    ::testing::TestWithParam<EnumCase<spv::AccessQualifier>>>;
 
 TEST_P(OpTypePipeTest, AnyAccessQualifier) {
   const std::string input = "%1 = OpTypePipe " + GetParam().name() + "\n";
-  EXPECT_THAT(CompiledInstructions(input),
-              Eq(MakeInstruction(SpvOpTypePipe, {1, GetParam().value()})));
+  EXPECT_THAT(
+      CompiledInstructions(input),
+      Eq(MakeInstruction(spv::Op::OpTypePipe, {1, GetParam().value()})));
   // Check the disassembler as well.
   EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(input));
 }
 
 // clang-format off
-#define CASE(NAME) {SpvAccessQualifier##NAME, #NAME}
+#define CASE(NAME) {spv::AccessQualifier::NAME, #NAME}
 INSTANTIATE_TEST_SUITE_P(
     TextToBinaryTypePipe, OpTypePipeTest,
-    ::testing::ValuesIn(std::vector<EnumCase<SpvAccessQualifier>>{
+    ::testing::ValuesIn(std::vector<EnumCase<spv::AccessQualifier>>{
                             CASE(ReadOnly),
                             CASE(WriteOnly),
                             CASE(ReadWrite),
@@ -195,12 +199,12 @@
 
 using OpTypeForwardPointerTest = spvtest::TextToBinaryTest;
 
-#define CASE(storage_class)                                               \
-  do {                                                                    \
-    EXPECT_THAT(                                                          \
-        CompiledInstructions("OpTypeForwardPointer %pt " #storage_class), \
-        Eq(MakeInstruction(SpvOpTypeForwardPointer,                       \
-                           {1, SpvStorageClass##storage_class})));        \
+#define CASE(storage_class)                                                    \
+  do {                                                                         \
+    EXPECT_THAT(                                                               \
+        CompiledInstructions("OpTypeForwardPointer %pt " #storage_class),      \
+        Eq(MakeInstruction(spv::Op::OpTypeForwardPointer,                      \
+                           {1, (uint32_t)spv::StorageClass::storage_class}))); \
   } while (0)
 
 TEST_F(OpTypeForwardPointerTest, ValidStorageClass) {
@@ -245,7 +249,7 @@
 TEST_F(OpSizeOfTest, OpcodeAssemblesInV10) {
   EXPECT_THAT(
       CompiledInstructions("%1 = OpSizeOf %2 %3", SPV_ENV_UNIVERSAL_1_0),
-      Eq(MakeInstruction(SpvOpSizeOf, {1, 2, 3})));
+      Eq(MakeInstruction(spv::Op::OpSizeOf, {1, 2, 3})));
 }
 
 TEST_F(OpSizeOfTest, ArgumentCount) {
@@ -258,7 +262,7 @@
                  "next instruction instead."));
   EXPECT_THAT(
       CompiledInstructions("%1 = OpSizeOf %2 %3", SPV_ENV_UNIVERSAL_1_1),
-      Eq(MakeInstruction(SpvOpSizeOf, {1, 2, 3})));
+      Eq(MakeInstruction(spv::Op::OpSizeOf, {1, 2, 3})));
   EXPECT_THAT(
       CompileFailure("%1 = OpSizeOf %2 %3 44 55 ", SPV_ENV_UNIVERSAL_1_1),
       Eq("Expected <opcode> or <result-id> at the beginning of an instruction, "
diff --git a/test/text_to_binary_test.cpp b/test/text_to_binary_test.cpp
index 0b348e8..a958097 100644
--- a/test/text_to_binary_test.cpp
+++ b/test/text_to_binary_test.cpp
@@ -180,9 +180,10 @@
 TEST_F(TextToBinaryTest, CRLF) {
   const std::string input =
       "%i32 = OpTypeInt 32 1\r\n%c = OpConstant %i32 123\r\n";
-  EXPECT_THAT(CompiledInstructions(input),
-              Eq(Concatenate({MakeInstruction(SpvOpTypeInt, {1, 32, 1}),
-                              MakeInstruction(SpvOpConstant, {1, 2, 123})})));
+  EXPECT_THAT(
+      CompiledInstructions(input),
+      Eq(Concatenate({MakeInstruction(spv::Op::OpTypeInt, {1, 32, 1}),
+                      MakeInstruction(spv::Op::OpConstant, {1, 2, 123})})));
 }
 
 using TextToBinaryFloatValueTest = spvtest::TextToBinaryTestBase<
@@ -192,8 +193,8 @@
   const std::string input =
       "%1 = OpTypeFloat 32\n%2 = OpConstant %1 " + GetParam().first;
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 32}),
-                              MakeInstruction(SpvOpConstant,
+              Eq(Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 32}),
+                              MakeInstruction(spv::Op::OpConstant,
                                               {1, 2, GetParam().second})})));
 }
 
@@ -222,8 +223,8 @@
   const std::string input =
       "%1 = OpTypeFloat 16\n%2 = OpConstant %1 " + GetParam().first;
   EXPECT_THAT(CompiledInstructions(input),
-              Eq(Concatenate({MakeInstruction(SpvOpTypeFloat, {1, 16}),
-                              MakeInstruction(SpvOpConstant,
+              Eq(Concatenate({MakeInstruction(spv::Op::OpTypeFloat, {1, 16}),
+                              MakeInstruction(spv::Op::OpConstant,
                                               {1, 2, GetParam().second})})));
 }
 
diff --git a/test/unit_spirv.h b/test/unit_spirv.h
index f0a2958..bc9857e 100644
--- a/test/unit_spirv.h
+++ b/test/unit_spirv.h
@@ -105,7 +105,7 @@
 // Returns a vector of words representing a single instruction with the
 // given opcode and operand words as a vector.
 inline std::vector<uint32_t> MakeInstruction(
-    SpvOp opcode, const std::vector<uint32_t>& args) {
+    spv::Op opcode, const std::vector<uint32_t>& args) {
   std::vector<uint32_t> result{
       spvOpcodeMake(uint16_t(args.size() + 1), opcode)};
   result.insert(result.end(), args.begin(), args.end());
@@ -116,7 +116,7 @@
 // given opcode and whose operands are the concatenation of the two given
 // argument lists.
 inline std::vector<uint32_t> MakeInstruction(
-    SpvOp opcode, std::vector<uint32_t> args,
+    spv::Op opcode, std::vector<uint32_t> args,
     const std::vector<uint32_t>& extra_args) {
   args.insert(args.end(), extra_args.begin(), extra_args.end());
   return MakeInstruction(opcode, args);
@@ -200,10 +200,10 @@
 }
 
 // Returns the capabilities in a CapabilitySet as an ordered vector.
-inline std::vector<SpvCapability> ElementsIn(
+inline std::vector<spv::Capability> ElementsIn(
     const spvtools::CapabilitySet& capabilities) {
-  std::vector<SpvCapability> result;
-  capabilities.ForEach([&result](SpvCapability c) { result.push_back(c); });
+  std::vector<spv::Capability> result;
+  capabilities.ForEach([&result](spv::Capability c) { result.push_back(c); });
   return result;
 }
 
diff --git a/test/val/val_cfg_test.cpp b/test/val/val_cfg_test.cpp
index c8dd4a2..d2edec1 100644
--- a/test/val/val_cfg_test.cpp
+++ b/test/val/val_cfg_test.cpp
@@ -37,7 +37,7 @@
 using ::testing::HasSubstr;
 using ::testing::MatchesRegex;
 
-using ValidateCFG = spvtest::ValidateBase<SpvCapability>;
+using ValidateCFG = spvtest::ValidateBase<spv::Capability>;
 using spvtest::ScopedContext;
 
 std::string nameOps() { return ""; }
@@ -58,7 +58,7 @@
 class Block {
   std::string label_;
   std::string body_;
-  SpvOp type_;
+  spv::Op type_;
   std::vector<Block> successors_;
 
  public:
@@ -66,7 +66,7 @@
   ///
   /// @param[in]: label the label id of the block
   /// @param[in]: type the branch instruction that ends the block
-  explicit Block(std::string label, SpvOp type = SpvOpBranch)
+  explicit Block(std::string label, spv::Op type = spv::Op::OpBranch)
       : label_(label), body_(), type_(type), successors_() {}
 
   /// Sets the instructions which will appear in the body of the block
@@ -89,13 +89,13 @@
     }
 
     switch (type_) {
-      case SpvOpBranchConditional:
+      case spv::Op::OpBranchConditional:
         out << "OpBranchConditional %cond ";
         for (Block& b : successors_) {
           out << "%" + b.label_ + " ";
         }
         break;
-      case SpvOpSwitch: {
+      case spv::Op::OpSwitch: {
         out << "OpSwitch %one %" + successors_.front().label_;
         std::stringstream ss;
         for (size_t i = 1; i < successors_.size(); i++) {
@@ -103,25 +103,25 @@
         }
         out << ss.str();
       } break;
-      case SpvOpLoopMerge: {
+      case spv::Op::OpLoopMerge: {
         assert(successors_.size() == 2);
         out << "OpLoopMerge %" + successors_[0].label_ + " %" +
                    successors_[0].label_ + "None";
       } break;
 
-      case SpvOpReturn:
+      case spv::Op::OpReturn:
         assert(successors_.size() == 0);
         out << "OpReturn\n";
         break;
-      case SpvOpUnreachable:
+      case spv::Op::OpUnreachable:
         assert(successors_.size() == 0);
         out << "OpUnreachable\n";
         break;
-      case SpvOpBranch:
+      case spv::Op::OpBranch:
         assert(successors_.size() == 1);
         out << "OpBranch %" + successors_.front().label_;
         break;
-      case SpvOpKill:
+      case spv::Op::OpKill:
         assert(successors_.size() == 0);
         out << "OpKill\n";
         break;
@@ -138,9 +138,9 @@
 
 /// Assigns the successors for the Block on the lhs
 Block& operator>>(Block& lhs, std::vector<Block> successors) {
-  if (lhs.type_ == SpvOpBranchConditional) {
+  if (lhs.type_ == spv::Op::OpBranchConditional) {
     assert(successors.size() == 2);
-  } else if (lhs.type_ == SpvOpSwitch) {
+  } else if (lhs.type_ == spv::Op::OpSwitch) {
     assert(successors.size() > 1);
   }
   lhs.successors_ = successors;
@@ -149,12 +149,12 @@
 
 /// Assigns the successor for the Block on the lhs
 Block& operator>>(Block& lhs, Block& successor) {
-  assert(lhs.type_ == SpvOpBranch);
+  assert(lhs.type_ == spv::Op::OpBranch);
   lhs.successors_.push_back(successor);
   return lhs;
 }
 
-const std::string& GetDefaultHeader(SpvCapability cap) {
+const std::string& GetDefaultHeader(spv::Capability cap) {
   static const std::string shader_header =
       "OpCapability Shader\n"
       "OpCapability Linkage\n"
@@ -165,7 +165,7 @@
       "OpCapability Linkage\n"
       "OpMemoryModel Logical OpenCL\n";
 
-  return (cap == SpvCapabilityShader) ? shader_header : kernel_header;
+  return (cap == spv::Capability::Shader) ? shader_header : kernel_header;
 }
 
 const std::string& types_consts() {
@@ -181,8 +181,8 @@
 }
 
 INSTANTIATE_TEST_SUITE_P(StructuredControlFlow, ValidateCFG,
-                         ::testing::Values(SpvCapabilityShader,
-                                           SpvCapabilityKernel));
+                         ::testing::Values(spv::Capability::Shader,
+                                           spv::Capability::Kernel));
 
 TEST_P(ValidateCFG, LoopReachableFromEntryButNeverLeadingToReturn) {
   // In this case, the loop is reachable from a node without a predecessor,
@@ -268,11 +268,11 @@
 }
 
 TEST_P(ValidateCFG, Simple) {
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
-  Block loop("loop", SpvOpBranchConditional);
+  Block loop("loop", spv::Op::OpBranchConditional);
   Block cont("cont");
-  Block merge("merge", SpvOpReturn);
+  Block merge("merge", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) {
@@ -298,7 +298,7 @@
 TEST_P(ValidateCFG, Variable) {
   Block entry("entry");
   Block cont("cont");
-  Block exit("exit", SpvOpReturn);
+  Block exit("exit", spv::Op::OpReturn);
 
   entry.SetBody("%var = OpVariable %ptrt Function\n");
 
@@ -317,7 +317,7 @@
 TEST_P(ValidateCFG, VariableNotInFirstBlockBad) {
   Block entry("entry");
   Block cont("cont");
-  Block exit("exit", SpvOpReturn);
+  Block exit("exit", spv::Op::OpReturn);
 
   // This operation should only be performed in the entry block
   cont.SetBody("%var = OpVariable %ptrt Function\n");
@@ -339,10 +339,10 @@
 }
 
 TEST_P(ValidateCFG, BlockSelfLoopIsOk) {
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
-  Block loop("loop", SpvOpBranchConditional);
-  Block merge("merge", SpvOpReturn);
+  Block loop("loop", spv::Op::OpBranchConditional);
+  Block merge("merge", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) loop.SetBody("OpLoopMerge %merge %loop None\n");
@@ -363,11 +363,11 @@
 }
 
 TEST_P(ValidateCFG, BlockAppearsBeforeDominatorBad) {
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
   Block cont("cont");
-  Block branch("branch", SpvOpBranchConditional);
-  Block merge("merge", SpvOpReturn);
+  Block branch("branch", spv::Op::OpBranchConditional);
+  Block merge("merge", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) branch.SetBody("OpSelectionMerge %merge None\n");
@@ -392,11 +392,11 @@
 }
 
 TEST_P(ValidateCFG, MergeBlockTargetedByMultipleHeaderBlocksBad) {
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
   Block loop("loop");
-  Block selection("selection", SpvOpBranchConditional);
-  Block merge("merge", SpvOpReturn);
+  Block selection("selection", spv::Op::OpBranchConditional);
+  Block merge("merge", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) loop.SetBody(" OpLoopMerge %merge %loop None\n");
@@ -428,11 +428,11 @@
 }
 
 TEST_P(ValidateCFG, MergeBlockTargetedByMultipleHeaderBlocksSelectionBad) {
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
-  Block loop("loop", SpvOpBranchConditional);
-  Block selection("selection", SpvOpBranchConditional);
-  Block merge("merge", SpvOpReturn);
+  Block loop("loop", spv::Op::OpBranchConditional);
+  Block selection("selection", spv::Op::OpBranchConditional);
+  Block merge("merge", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) selection.SetBody(" OpSelectionMerge %merge None\n");
@@ -466,7 +466,7 @@
 TEST_P(ValidateCFG, BranchTargetFirstBlockBadSinceEntryBlock) {
   Block entry("entry");
   Block bad("bad");
-  Block end("end", SpvOpReturn);
+  Block end("end", spv::Op::OpReturn);
   std::string str = GetDefaultHeader(GetParam()) +
                     nameOps("entry", "bad", std::make_pair("func", "Main")) +
                     types_consts() +
@@ -489,7 +489,7 @@
   Block entry("entry");
   entry.SetBody("%undef = OpUndef %boolt\n");
   Block bad("bad");
-  Block end("end", SpvOpReturn);
+  Block end("end", spv::Op::OpReturn);
   Block badvalue("undef");  // This references the OpUndef.
   std::string str = GetDefaultHeader(GetParam()) +
                     nameOps("entry", "bad", std::make_pair("func", "Main")) +
@@ -511,8 +511,8 @@
 
 TEST_P(ValidateCFG, BranchConditionalTrueTargetFirstBlockBad) {
   Block entry("entry");
-  Block bad("bad", SpvOpBranchConditional);
-  Block exit("exit", SpvOpReturn);
+  Block bad("bad", spv::Op::OpBranchConditional);
+  Block exit("exit", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   bad.SetBody(" OpLoopMerge %entry %exit None\n");
@@ -538,10 +538,10 @@
 
 TEST_P(ValidateCFG, BranchConditionalFalseTargetFirstBlockBad) {
   Block entry("entry");
-  Block bad("bad", SpvOpBranchConditional);
+  Block bad("bad", spv::Op::OpBranchConditional);
   Block t("t");
   Block merge("merge");
-  Block end("end", SpvOpReturn);
+  Block end("end", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   bad.SetBody("OpLoopMerge %merge %cont None\n");
@@ -568,13 +568,13 @@
 
 TEST_P(ValidateCFG, SwitchTargetFirstBlockBad) {
   Block entry("entry");
-  Block bad("bad", SpvOpSwitch);
+  Block bad("bad", spv::Op::OpSwitch);
   Block block1("block1");
   Block block2("block2");
   Block block3("block3");
   Block def("def");  // default block
   Block merge("merge");
-  Block end("end", SpvOpReturn);
+  Block end("end", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   bad.SetBody("OpSelectionMerge %merge None\n");
@@ -605,15 +605,15 @@
 
 TEST_P(ValidateCFG, BranchToBlockInOtherFunctionBad) {
   Block entry("entry");
-  Block middle("middle", SpvOpBranchConditional);
-  Block end("end", SpvOpReturn);
+  Block middle("middle", spv::Op::OpBranchConditional);
+  Block end("end", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   middle.SetBody("OpSelectionMerge %end None\n");
 
   Block entry2("entry2");
   Block middle2("middle2");
-  Block end2("end2", SpvOpReturn);
+  Block end2("end2", spv::Op::OpReturn);
 
   std::string str = GetDefaultHeader(GetParam()) +
                     nameOps("middle2", std::make_pair("func", "Main")) +
@@ -643,9 +643,9 @@
 TEST_P(ValidateCFG, HeaderDoesntStrictlyDominateMergeBad) {
   // If a merge block is reachable, then it must be strictly dominated by
   // its header block.
-  bool is_shader = GetParam() == SpvCapabilityShader;
-  Block head("head", SpvOpBranchConditional);
-  Block exit("exit", SpvOpReturn);
+  bool is_shader = GetParam() == spv::Capability::Shader;
+  Block head("head", spv::Op::OpBranchConditional);
+  Block exit("exit", spv::Op::OpReturn);
 
   head.SetBody("%cond = OpSLessThan %boolt %one %two\n");
 
@@ -675,16 +675,16 @@
   }
 }
 
-std::string GetUnreachableMergeNoMergeInst(SpvCapability cap) {
+std::string GetUnreachableMergeNoMergeInst(spv::Capability cap) {
   std::string header = GetDefaultHeader(cap);
   Block entry("entry");
-  Block branch("branch", SpvOpBranchConditional);
-  Block t("t", SpvOpReturn);
-  Block f("f", SpvOpReturn);
-  Block merge("merge", SpvOpReturn);
+  Block branch("branch", spv::Op::OpBranchConditional);
+  Block t("t", spv::Op::OpReturn);
+  Block f("f", spv::Op::OpReturn);
+  Block merge("merge", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
-  if (cap == SpvCapabilityShader)
+  if (cap == spv::Capability::Shader)
     branch.AppendBody("OpSelectionMerge %merge None\n");
 
   std::string str = header;
@@ -705,18 +705,18 @@
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-std::string GetUnreachableMergeTerminatedBy(SpvCapability cap, SpvOp op) {
+std::string GetUnreachableMergeTerminatedBy(spv::Capability cap, spv::Op op) {
   std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
-  Block branch("branch", SpvOpBranchConditional);
-  Block t("t", SpvOpReturn);
-  Block f("f", SpvOpReturn);
+  Block branch("branch", spv::Op::OpBranchConditional);
+  Block t("t", spv::Op::OpReturn);
+  Block f("f", spv::Op::OpReturn);
   Block merge("merge", op);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   std::string str = header;
-  if (cap == SpvCapabilityShader)
+  if (cap == spv::Capability::Shader)
     branch.AppendBody("OpSelectionMerge %merge None\n");
 
   str += nameOps("branch", "merge", std::make_pair("func", "Main"));
@@ -734,33 +734,35 @@
 
 TEST_P(ValidateCFG, UnreachableMergeTerminatedByOpUnreachable) {
   CompileSuccessfully(
-      GetUnreachableMergeTerminatedBy(GetParam(), SpvOpUnreachable));
+      GetUnreachableMergeTerminatedBy(GetParam(), spv::Op::OpUnreachable));
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
 TEST_F(ValidateCFG, UnreachableMergeTerminatedByOpKill) {
-  CompileSuccessfully(
-      GetUnreachableMergeTerminatedBy(SpvCapabilityShader, SpvOpKill));
+  CompileSuccessfully(GetUnreachableMergeTerminatedBy(spv::Capability::Shader,
+                                                      spv::Op::OpKill));
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
 TEST_P(ValidateCFG, UnreachableMergeTerminatedByOpReturn) {
-  CompileSuccessfully(GetUnreachableMergeTerminatedBy(GetParam(), SpvOpReturn));
+  CompileSuccessfully(
+      GetUnreachableMergeTerminatedBy(GetParam(), spv::Op::OpReturn));
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-std::string GetUnreachableContinueTerminatedBy(SpvCapability cap, SpvOp op) {
+std::string GetUnreachableContinueTerminatedBy(spv::Capability cap,
+                                               spv::Op op) {
   std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
-  Block branch("branch", SpvOpBranch);
-  Block merge("merge", SpvOpReturn);
+  Block branch("branch", spv::Op::OpBranch);
+  Block merge("merge", spv::Op::OpReturn);
   Block target("target", op);
 
-  if (op == SpvOpBranch) target >> branch;
+  if (op == spv::Op::OpBranch) target >> branch;
 
   std::string str = header;
-  if (cap == SpvCapabilityShader)
+  if (cap == spv::Capability::Shader)
     branch.AppendBody("OpLoopMerge %merge %target None\n");
 
   str += nameOps("branch", "merge", "target", std::make_pair("func", "Main"));
@@ -775,10 +777,10 @@
   return str;
 }
 
-TEST_P(ValidateCFG, UnreachableContinueTerminatedBySpvOpUnreachable) {
+TEST_P(ValidateCFG, UnreachableContinueTerminatedByOpUnreachable) {
   CompileSuccessfully(
-      GetUnreachableContinueTerminatedBy(GetParam(), SpvOpUnreachable));
-  if (GetParam() == SpvCapabilityShader) {
+      GetUnreachableContinueTerminatedBy(GetParam(), spv::Op::OpUnreachable));
+  if (GetParam() == spv::Capability::Shader) {
     ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
     EXPECT_THAT(getDiagnosticString(),
                 HasSubstr("targeted by 0 back-edge blocks"));
@@ -787,18 +789,18 @@
   }
 }
 
-TEST_F(ValidateCFG, UnreachableContinueTerminatedBySpvOpKill) {
-  CompileSuccessfully(
-      GetUnreachableContinueTerminatedBy(SpvCapabilityShader, SpvOpKill));
+TEST_F(ValidateCFG, UnreachableContinueTerminatedByOpKill) {
+  CompileSuccessfully(GetUnreachableContinueTerminatedBy(
+      spv::Capability::Shader, spv::Op::OpKill));
   ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
               HasSubstr("targeted by 0 back-edge blocks"));
 }
 
-TEST_P(ValidateCFG, UnreachableContinueTerminatedBySpvOpReturn) {
+TEST_P(ValidateCFG, UnreachableContinueTerminatedByOpReturn) {
   CompileSuccessfully(
-      GetUnreachableContinueTerminatedBy(GetParam(), SpvOpReturn));
-  if (GetParam() == SpvCapabilityShader) {
+      GetUnreachableContinueTerminatedBy(GetParam(), spv::Op::OpReturn));
+  if (GetParam() == spv::Capability::Shader) {
     ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
     EXPECT_THAT(getDiagnosticString(),
                 HasSubstr("targeted by 0 back-edge blocks"));
@@ -807,25 +809,25 @@
   }
 }
 
-TEST_P(ValidateCFG, UnreachableContinueTerminatedBySpvOpBranch) {
+TEST_P(ValidateCFG, UnreachableContinueTerminatedByOpBranch) {
   CompileSuccessfully(
-      GetUnreachableContinueTerminatedBy(GetParam(), SpvOpBranch));
+      GetUnreachableContinueTerminatedBy(GetParam(), spv::Op::OpBranch));
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-std::string GetUnreachableMergeUnreachableMergeInst(SpvCapability cap) {
+std::string GetUnreachableMergeUnreachableMergeInst(spv::Capability cap) {
   std::string header = GetDefaultHeader(cap);
 
-  Block body("body", SpvOpReturn);
+  Block body("body", spv::Op::OpReturn);
   Block entry("entry");
-  Block branch("branch", SpvOpBranchConditional);
-  Block t("t", SpvOpReturn);
-  Block f("f", SpvOpReturn);
-  Block merge("merge", SpvOpUnreachable);
+  Block branch("branch", spv::Op::OpBranchConditional);
+  Block t("t", spv::Op::OpReturn);
+  Block f("f", spv::Op::OpReturn);
+  Block merge("merge", spv::Op::OpUnreachable);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   std::string str = header;
-  if (cap == SpvCapabilityShader)
+  if (cap == spv::Capability::Shader)
     branch.AppendBody("OpSelectionMerge %merge None\n");
 
   str += nameOps("branch", "merge", std::make_pair("func", "Main"));
@@ -847,19 +849,19 @@
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-std::string GetUnreachableContinueUnreachableLoopInst(SpvCapability cap) {
+std::string GetUnreachableContinueUnreachableLoopInst(spv::Capability cap) {
   std::string header = GetDefaultHeader(cap);
 
-  Block body("body", SpvOpReturn);
+  Block body("body", spv::Op::OpReturn);
   Block entry("entry");
-  Block branch("branch", SpvOpBranch);
-  Block merge("merge", SpvOpReturn);
-  Block target("target", SpvOpBranch);
+  Block branch("branch", spv::Op::OpBranch);
+  Block merge("merge", spv::Op::OpReturn);
+  Block target("target", spv::Op::OpBranch);
 
   target >> branch;
 
   std::string str = header;
-  if (cap == SpvCapabilityShader)
+  if (cap == spv::Capability::Shader)
     branch.AppendBody("OpLoopMerge %merge %target None\n");
 
   str += nameOps("branch", "merge", "target", std::make_pair("func", "Main"));
@@ -880,21 +882,21 @@
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-std::string GetUnreachableMergeWithComplexBody(SpvCapability cap) {
+std::string GetUnreachableMergeWithComplexBody(spv::Capability cap) {
   std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
-  Block branch("branch", SpvOpBranchConditional);
-  Block t("t", SpvOpReturn);
-  Block f("f", SpvOpReturn);
-  Block merge("merge", SpvOpUnreachable);
+  Block branch("branch", spv::Op::OpBranchConditional);
+  Block t("t", spv::Op::OpReturn);
+  Block f("f", spv::Op::OpReturn);
+  Block merge("merge", spv::Op::OpUnreachable);
 
   entry.AppendBody("%placeholder   = OpVariable %intptrt Function\n");
   entry.AppendBody("%cond    = OpSLessThan %boolt %one %two\n");
   merge.AppendBody("OpStore %placeholder %one\n");
 
   std::string str = header;
-  if (cap == SpvCapabilityShader)
+  if (cap == spv::Capability::Shader)
     branch.AppendBody("OpSelectionMerge %merge None\n");
 
   str += nameOps("branch", "merge", std::make_pair("func", "Main"));
@@ -916,13 +918,13 @@
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-std::string GetUnreachableContinueWithComplexBody(SpvCapability cap) {
+std::string GetUnreachableContinueWithComplexBody(spv::Capability cap) {
   std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
-  Block branch("branch", SpvOpBranch);
-  Block merge("merge", SpvOpReturn);
-  Block target("target", SpvOpBranch);
+  Block branch("branch", spv::Op::OpBranch);
+  Block merge("merge", spv::Op::OpReturn);
+  Block target("target", spv::Op::OpBranch);
 
   target >> branch;
 
@@ -930,7 +932,7 @@
   target.AppendBody("OpStore %placeholder %one\n");
 
   std::string str = header;
-  if (cap == SpvCapabilityShader)
+  if (cap == spv::Capability::Shader)
     branch.AppendBody("OpLoopMerge %merge %target None\n");
 
   str += nameOps("branch", "merge", "target", std::make_pair("func", "Main"));
@@ -951,19 +953,19 @@
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-std::string GetUnreachableMergeWithBranchUse(SpvCapability cap) {
+std::string GetUnreachableMergeWithBranchUse(spv::Capability cap) {
   std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
-  Block branch("branch", SpvOpBranchConditional);
-  Block t("t", SpvOpBranch);
-  Block f("f", SpvOpReturn);
-  Block merge("merge", SpvOpUnreachable);
+  Block branch("branch", spv::Op::OpBranchConditional);
+  Block t("t", spv::Op::OpBranch);
+  Block f("f", spv::Op::OpReturn);
+  Block merge("merge", spv::Op::OpUnreachable);
 
   entry.AppendBody("%cond    = OpSLessThan %boolt %one %two\n");
 
   std::string str = header;
-  if (cap == SpvCapabilityShader)
+  if (cap == spv::Capability::Shader)
     branch.AppendBody("OpSelectionMerge %merge None\n");
 
   str += nameOps("branch", "merge", std::make_pair("func", "Main"));
@@ -984,20 +986,20 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-std::string GetUnreachableMergeWithMultipleUses(SpvCapability cap) {
+std::string GetUnreachableMergeWithMultipleUses(spv::Capability cap) {
   std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
-  Block branch("branch", SpvOpBranchConditional);
-  Block t("t", SpvOpReturn);
-  Block f("f", SpvOpReturn);
-  Block merge("merge", SpvOpUnreachable);
-  Block duplicate("duplicate", SpvOpBranchConditional);
+  Block branch("branch", spv::Op::OpBranchConditional);
+  Block t("t", spv::Op::OpReturn);
+  Block f("f", spv::Op::OpReturn);
+  Block merge("merge", spv::Op::OpUnreachable);
+  Block duplicate("duplicate", spv::Op::OpBranchConditional);
 
   entry.AppendBody("%cond    = OpSLessThan %boolt %one %two\n");
 
   std::string str = header;
-  if (cap == SpvCapabilityShader) {
+  if (cap == spv::Capability::Shader) {
     branch.AppendBody("OpSelectionMerge %merge None\n");
     duplicate.AppendBody("OpSelectionMerge %merge None\n");
   }
@@ -1018,7 +1020,7 @@
 
 TEST_P(ValidateCFG, UnreachableMergeWithMultipleUses) {
   CompileSuccessfully(GetUnreachableMergeWithMultipleUses(GetParam()));
-  if (GetParam() == SpvCapabilityShader) {
+  if (GetParam() == spv::Capability::Shader) {
     ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
     EXPECT_THAT(getDiagnosticString(),
                 HasSubstr("is already a merge block for another header"));
@@ -1027,20 +1029,20 @@
   }
 }
 
-std::string GetUnreachableContinueWithBranchUse(SpvCapability cap) {
+std::string GetUnreachableContinueWithBranchUse(spv::Capability cap) {
   std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
-  Block branch("branch", SpvOpBranch);
-  Block merge("merge", SpvOpReturn);
-  Block target("target", SpvOpBranch);
+  Block branch("branch", spv::Op::OpBranch);
+  Block merge("merge", spv::Op::OpReturn);
+  Block target("target", spv::Op::OpBranch);
 
   target >> branch;
 
   entry.AppendBody("%placeholder   = OpVariable %intptrt Function\n");
 
   std::string str = header;
-  if (cap == SpvCapabilityShader)
+  if (cap == spv::Capability::Shader)
     branch.AppendBody("OpLoopMerge %merge %target None\n");
 
   str += nameOps("branch", "merge", "target", std::make_pair("func", "Main"));
@@ -1061,16 +1063,16 @@
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-std::string GetReachableMergeAndContinue(SpvCapability cap) {
+std::string GetReachableMergeAndContinue(spv::Capability cap) {
   std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
-  Block branch("branch", SpvOpBranch);
-  Block merge("merge", SpvOpReturn);
-  Block target("target", SpvOpBranch);
-  Block body("body", SpvOpBranchConditional);
-  Block t("t", SpvOpBranch);
-  Block f("f", SpvOpBranch);
+  Block branch("branch", spv::Op::OpBranch);
+  Block merge("merge", spv::Op::OpReturn);
+  Block target("target", spv::Op::OpBranch);
+  Block body("body", spv::Op::OpBranchConditional);
+  Block t("t", spv::Op::OpBranch);
+  Block f("f", spv::Op::OpBranch);
 
   target >> branch;
   body.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
@@ -1078,7 +1080,7 @@
   f >> target;
 
   std::string str = header;
-  if (cap == SpvCapabilityShader) {
+  if (cap == spv::Capability::Shader) {
     branch.AppendBody("OpLoopMerge %merge %target None\n");
     body.AppendBody("OpSelectionMerge %f None\n");
   }
@@ -1104,23 +1106,23 @@
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-std::string GetUnreachableMergeAndContinue(SpvCapability cap) {
+std::string GetUnreachableMergeAndContinue(spv::Capability cap) {
   std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
-  Block branch("branch", SpvOpBranch);
-  Block merge("merge", SpvOpReturn);
-  Block target("target", SpvOpBranch);
-  Block body("body", SpvOpBranchConditional);
-  Block t("t", SpvOpReturn);
-  Block f("f", SpvOpReturn);
-  Block pre_target("pre_target", SpvOpBranch);
+  Block branch("branch", spv::Op::OpBranch);
+  Block merge("merge", spv::Op::OpReturn);
+  Block target("target", spv::Op::OpBranch);
+  Block body("body", spv::Op::OpBranchConditional);
+  Block t("t", spv::Op::OpReturn);
+  Block f("f", spv::Op::OpReturn);
+  Block pre_target("pre_target", spv::Op::OpBranch);
 
   target >> branch;
   body.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
 
   std::string str = header;
-  if (cap == SpvCapabilityShader) {
+  if (cap == spv::Capability::Shader) {
     branch.AppendBody("OpLoopMerge %merge %target None\n");
     body.AppendBody("OpSelectionMerge %pre_target None\n");
   }
@@ -1147,12 +1149,12 @@
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-std::string GetUnreachableBlock(SpvCapability cap) {
+std::string GetUnreachableBlock(spv::Capability cap) {
   std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
   Block unreachable("unreachable");
-  Block exit("exit", SpvOpReturn);
+  Block exit("exit", spv::Op::OpReturn);
 
   std::string str = header;
   str += nameOps("unreachable", "exit", std::make_pair("func", "Main"));
@@ -1171,18 +1173,18 @@
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
 }
 
-std::string GetUnreachableBranch(SpvCapability cap) {
+std::string GetUnreachableBranch(spv::Capability cap) {
   std::string header = GetDefaultHeader(cap);
 
   Block entry("entry");
-  Block unreachable("unreachable", SpvOpBranchConditional);
+  Block unreachable("unreachable", spv::Op::OpBranchConditional);
   Block unreachablechildt("unreachablechildt");
   Block unreachablechildf("unreachablechildf");
   Block merge("merge");
-  Block exit("exit", SpvOpReturn);
+  Block exit("exit", spv::Op::OpReturn);
 
   unreachable.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
-  if (cap == SpvCapabilityShader)
+  if (cap == spv::Capability::Shader)
     unreachable.AppendBody("OpSelectionMerge %merge None\n");
 
   std::string str = header;
@@ -1219,10 +1221,10 @@
 }
 
 TEST_P(ValidateCFG, SingleBlockLoop) {
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
-  Block loop("loop", SpvOpBranchConditional);
-  Block exit("exit", SpvOpReturn);
+  Block loop("loop", spv::Op::OpBranchConditional);
+  Block exit("exit", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) loop.AppendBody("OpLoopMerge %exit %loop None\n");
@@ -1240,15 +1242,15 @@
 }
 
 TEST_P(ValidateCFG, NestedLoops) {
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
   Block loop1("loop1");
   Block loop1_cont_break_block("loop1_cont_break_block",
-                               SpvOpBranchConditional);
-  Block loop2("loop2", SpvOpBranchConditional);
+                               spv::Op::OpBranchConditional);
+  Block loop2("loop2", spv::Op::OpBranchConditional);
   Block loop2_merge("loop2_merge");
   Block loop1_merge("loop1_merge");
-  Block exit("exit", SpvOpReturn);
+  Block exit("exit", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) {
@@ -1275,7 +1277,7 @@
 }
 
 TEST_P(ValidateCFG, NestedSelection) {
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
   const int N = 256;
   std::vector<Block> if_blocks;
@@ -1284,18 +1286,18 @@
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
 
-  if_blocks.emplace_back("if0", SpvOpBranchConditional);
+  if_blocks.emplace_back("if0", spv::Op::OpBranchConditional);
 
   if (is_shader) if_blocks[0].SetBody("OpSelectionMerge %if_merge0 None\n");
-  merge_blocks.emplace_back("if_merge0", SpvOpReturn);
+  merge_blocks.emplace_back("if_merge0", spv::Op::OpReturn);
 
   for (int i = 1; i < N; i++) {
     std::stringstream ss;
     ss << i;
-    if_blocks.emplace_back("if" + ss.str(), SpvOpBranchConditional);
+    if_blocks.emplace_back("if" + ss.str(), spv::Op::OpBranchConditional);
     if (is_shader)
       if_blocks[i].SetBody("OpSelectionMerge %if_merge" + ss.str() + " None\n");
-    merge_blocks.emplace_back("if_merge" + ss.str(), SpvOpBranch);
+    merge_blocks.emplace_back("if_merge" + ss.str(), spv::Op::OpBranch);
   }
   std::string str = GetDefaultHeader(GetParam()) + std::string(types_consts()) +
                     "%func    = OpFunction %voidt None %funct\n";
@@ -1318,14 +1320,14 @@
 }
 
 TEST_P(ValidateCFG, BackEdgeBlockDoesntPostDominateContinueTargetBad) {
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
-  Block loop1("loop1", SpvOpBranchConditional);
-  Block loop2("loop2", SpvOpBranchConditional);
+  Block loop1("loop1", spv::Op::OpBranchConditional);
+  Block loop2("loop2", spv::Op::OpBranchConditional);
   Block loop2_merge("loop2_merge");
-  Block loop1_cont("loop1_cont", SpvOpBranchConditional);
+  Block loop1_cont("loop1_cont", spv::Op::OpBranchConditional);
   Block be_block("be_block");
-  Block exit("exit", SpvOpReturn);
+  Block exit("exit", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) {
@@ -1348,7 +1350,7 @@
   str += "OpFunctionEnd";
 
   CompileSuccessfully(str);
-  if (GetParam() == SpvCapabilityShader) {
+  if (GetParam() == spv::Capability::Shader) {
     ASSERT_EQ(SPV_ERROR_INVALID_CFG, ValidateInstructions());
     EXPECT_THAT(
         getDiagnosticString(),
@@ -1363,12 +1365,12 @@
 }
 
 TEST_P(ValidateCFG, BranchingToNonLoopHeaderBlockBad) {
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
-  Block split("split", SpvOpBranchConditional);
+  Block split("split", spv::Op::OpBranchConditional);
   Block t("t");
   Block f("f");
-  Block exit("exit", SpvOpReturn);
+  Block exit("exit", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) split.SetBody("OpSelectionMerge %exit None\n");
@@ -1398,10 +1400,10 @@
 }
 
 TEST_P(ValidateCFG, BranchingToSameNonLoopHeaderBlockBad) {
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
-  Block split("split", SpvOpBranchConditional);
-  Block exit("exit", SpvOpReturn);
+  Block split("split", spv::Op::OpBranchConditional);
+  Block exit("exit", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) split.SetBody("OpSelectionMerge %exit None\n");
@@ -1429,12 +1431,12 @@
 }
 
 TEST_P(ValidateCFG, MultipleBackEdgeBlocksToLoopHeaderBad) {
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
-  Block loop("loop", SpvOpBranchConditional);
+  Block loop("loop", spv::Op::OpBranchConditional);
   Block back0("back0");
   Block back1("back1");
-  Block merge("merge", SpvOpReturn);
+  Block merge("merge", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) loop.SetBody("OpLoopMerge %merge %back0 None\n");
@@ -1465,13 +1467,13 @@
 }
 
 TEST_P(ValidateCFG, ContinueTargetMustBePostDominatedByBackEdge) {
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
-  Block loop("loop", SpvOpBranchConditional);
-  Block cheader("cheader", SpvOpBranchConditional);
+  Block loop("loop", spv::Op::OpBranchConditional);
+  Block cheader("cheader", spv::Op::OpBranchConditional);
   Block be_block("be_block");
-  Block merge("merge", SpvOpReturn);
-  Block exit("exit", SpvOpReturn);
+  Block merge("merge", spv::Op::OpReturn);
+  Block exit("exit", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) loop.SetBody("OpLoopMerge %merge %cheader None\n");
@@ -1504,11 +1506,11 @@
 }
 
 TEST_P(ValidateCFG, BranchOutOfConstructToMergeBad) {
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
-  Block loop("loop", SpvOpBranchConditional);
-  Block cont("cont", SpvOpBranchConditional);
-  Block merge("merge", SpvOpReturn);
+  Block loop("loop", spv::Op::OpBranchConditional);
+  Block cont("cont", spv::Op::OpBranchConditional);
+  Block merge("merge", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) loop.SetBody("OpLoopMerge %merge %loop None\n");
@@ -1539,12 +1541,12 @@
 }
 
 TEST_P(ValidateCFG, BranchOutOfConstructBad) {
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
-  Block loop("loop", SpvOpBranchConditional);
-  Block cont("cont", SpvOpBranchConditional);
+  Block loop("loop", spv::Op::OpBranchConditional);
+  Block cont("cont", spv::Op::OpBranchConditional);
   Block merge("merge");
-  Block exit("exit", SpvOpReturn);
+  Block exit("exit", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) loop.SetBody("OpLoopMerge %merge %loop None\n");
@@ -1575,12 +1577,12 @@
 }
 
 TEST_F(ValidateCFG, OpSwitchToUnreachableBlock) {
-  Block entry("entry", SpvOpSwitch);
+  Block entry("entry", spv::Op::OpSwitch);
   Block case0("case0");
   Block case1("case1");
   Block case2("case2");
-  Block def("default", SpvOpUnreachable);
-  Block phi("phi", SpvOpReturn);
+  Block def("default", spv::Op::OpUnreachable);
+  Block phi("phi", spv::Op::OpReturn);
 
   std::string str = R"(
 OpCapability Shader
@@ -1687,13 +1689,13 @@
   // The nested construct has an unreachable merge block.  In the
   // augmented CFG that merge block
   // we still determine that the
-  bool is_shader = GetParam() == SpvCapabilityShader;
-  Block entry("entry", SpvOpBranchConditional);
-  Block inner_head("inner_head", SpvOpBranchConditional);
-  Block inner_true("inner_true", SpvOpReturn);
-  Block inner_false("inner_false", SpvOpReturn);
+  bool is_shader = GetParam() == spv::Capability::Shader;
+  Block entry("entry", spv::Op::OpBranchConditional);
+  Block inner_head("inner_head", spv::Op::OpBranchConditional);
+  Block inner_true("inner_true", spv::Op::OpReturn);
+  Block inner_false("inner_false", spv::Op::OpReturn);
   Block inner_merge("inner_merge");
-  Block exit("exit", SpvOpReturn);
+  Block exit("exit", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) {
@@ -1721,13 +1723,13 @@
   // The continue construct cannot be the merge target of a nested selection
   // because the loop construct must contain "if_merge" because it contains
   // "if_head".
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
   Block loop("loop");
-  Block if_head("if_head", SpvOpBranchConditional);
+  Block if_head("if_head", spv::Op::OpBranchConditional);
   Block if_true("if_true");
-  Block if_merge("if_merge", SpvOpBranchConditional);
-  Block merge("merge", SpvOpReturn);
+  Block if_merge("if_merge", spv::Op::OpBranchConditional);
+  Block merge("merge", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) {
@@ -1765,11 +1767,11 @@
 TEST_P(ValidateCFG, SingleLatchBlockMultipleBranchesToLoopHeader) {
   // This test case ensures we allow both branches of a loop latch block
   // to go back to the loop header.  It still counts as a single back edge.
-  bool is_shader = GetParam() == SpvCapabilityShader;
+  bool is_shader = GetParam() == spv::Capability::Shader;
   Block entry("entry");
-  Block loop("loop", SpvOpBranchConditional);
-  Block latch("latch", SpvOpBranchConditional);
-  Block merge("merge", SpvOpReturn);
+  Block loop("loop", spv::Op::OpBranchConditional);
+  Block latch("latch", spv::Op::OpBranchConditional);
+  Block merge("merge", spv::Op::OpReturn);
 
   entry.SetBody("%cond    = OpSLessThan %boolt %one %two\n");
   if (is_shader) {
diff --git a/test/val/val_decoration_test.cpp b/test/val/val_decoration_test.cpp
index d864bbf..64ab8d0 100644
--- a/test/val/val_decoration_test.cpp
+++ b/test/val/val_decoration_test.cpp
@@ -62,9 +62,10 @@
   CompileSuccessfully(spirv);
   EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
   // Must have 2 decorations.
-  EXPECT_THAT(vstate_->id_decorations(id),
-              Eq(std::set<Decoration>{Decoration(SpvDecorationLocation, {4}),
-                                      Decoration(SpvDecorationCentroid)}));
+  EXPECT_THAT(
+      vstate_->id_decorations(id),
+      Eq(std::set<Decoration>{Decoration(spv::Decoration::Location, {4}),
+                              Decoration(spv::Decoration::Centroid)}));
 }
 
 TEST_F(ValidateDecorations, ValidateOpMemberDecorateRegistration) {
@@ -89,15 +90,15 @@
   const uint32_t arr_id = 1;
   EXPECT_THAT(
       vstate_->id_decorations(arr_id),
-      Eq(std::set<Decoration>{Decoration(SpvDecorationArrayStride, {4})}));
+      Eq(std::set<Decoration>{Decoration(spv::Decoration::ArrayStride, {4})}));
 
   // The struct must have 3 decorations.
   const uint32_t struct_id = 2;
   EXPECT_THAT(
       vstate_->id_decorations(struct_id),
-      Eq(std::set<Decoration>{Decoration(SpvDecorationNonReadable, {}, 2),
-                              Decoration(SpvDecorationOffset, {2}, 2),
-                              Decoration(SpvDecorationBufferBlock)}));
+      Eq(std::set<Decoration>{Decoration(spv::Decoration::NonReadable, {}, 2),
+                              Decoration(spv::Decoration::Offset, {2}, 2),
+                              Decoration(spv::Decoration::BufferBlock)}));
 }
 
 TEST_F(ValidateDecorations, ValidateOpMemberDecorateOutOfBound) {
@@ -152,9 +153,9 @@
 
   // Decoration group has 3 decorations.
   auto expected_decorations =
-      std::set<Decoration>{Decoration(SpvDecorationDescriptorSet, {0}),
-                           Decoration(SpvDecorationRelaxedPrecision),
-                           Decoration(SpvDecorationRestrict)};
+      std::set<Decoration>{Decoration(spv::Decoration::DescriptorSet, {0}),
+                           Decoration(spv::Decoration::RelaxedPrecision),
+                           Decoration(spv::Decoration::Restrict)};
 
   // Decoration group is applied to id 1, 2, 3, and 4. Note that id 1 (which is
   // the decoration group id) also has all the decorations.
@@ -182,7 +183,7 @@
   EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
   // Decoration group has 1 decoration.
   auto expected_decorations =
-      std::set<Decoration>{Decoration(SpvDecorationOffset, {3}, 3)};
+      std::set<Decoration>{Decoration(spv::Decoration::Offset, {3}, 3)};
 
   // Decoration group is applied to id 2, 3, and 4.
   EXPECT_THAT(vstate_->id_decorations(2), Eq(expected_decorations));
diff --git a/test/val/val_non_uniform_test.cpp b/test/val/val_non_uniform_test.cpp
index 3840eec..af571d3 100644
--- a/test/val/val_non_uniform_test.cpp
+++ b/test/val/val_non_uniform_test.cpp
@@ -97,24 +97,25 @@
   return ss.str();
 }
 
-SpvScope scopes[] = {SpvScopeCrossDevice, SpvScopeDevice, SpvScopeWorkgroup,
-                     SpvScopeSubgroup, SpvScopeInvocation};
+spv::Scope scopes[] = {spv::Scope::CrossDevice, spv::Scope::Device,
+                       spv::Scope::Workgroup, spv::Scope::Subgroup,
+                       spv::Scope::Invocation};
 
 using ValidateGroupNonUniform = spvtest::ValidateBase<bool>;
 using GroupNonUniform = spvtest::ValidateBase<
-    std::tuple<std::string, std::string, SpvScope, std::string, std::string>>;
+    std::tuple<std::string, std::string, spv::Scope, std::string, std::string>>;
 
-std::string ConvertScope(SpvScope scope) {
+std::string ConvertScope(spv::Scope scope) {
   switch (scope) {
-    case SpvScopeCrossDevice:
+    case spv::Scope::CrossDevice:
       return "%cross_device";
-    case SpvScopeDevice:
+    case spv::Scope::Device:
       return "%device";
-    case SpvScopeWorkgroup:
+    case spv::Scope::Workgroup:
       return "%workgroup";
-    case SpvScopeSubgroup:
+    case spv::Scope::Subgroup:
       return "%subgroup";
-    case SpvScopeInvocation:
+    case spv::Scope::Invocation:
       return "%invocation";
     default:
       return "";
@@ -124,7 +125,7 @@
 TEST_P(GroupNonUniform, Vulkan1p1) {
   std::string opcode = std::get<0>(GetParam());
   std::string type = std::get<1>(GetParam());
-  SpvScope execution_scope = std::get<2>(GetParam());
+  spv::Scope execution_scope = std::get<2>(GetParam());
   std::string args = std::get<3>(GetParam());
   std::string error = std::get<4>(GetParam());
 
@@ -137,7 +138,7 @@
   CompileSuccessfully(GenerateShaderCode(sstr.str()), SPV_ENV_VULKAN_1_1);
   spv_result_t result = ValidateInstructions(SPV_ENV_VULKAN_1_1);
   if (error == "") {
-    if (execution_scope == SpvScopeSubgroup) {
+    if (execution_scope == spv::Scope::Subgroup) {
       EXPECT_EQ(SPV_SUCCESS, result);
     } else {
       EXPECT_EQ(SPV_ERROR_INVALID_DATA, result);
@@ -157,7 +158,7 @@
 TEST_P(GroupNonUniform, Spirv1p3) {
   std::string opcode = std::get<0>(GetParam());
   std::string type = std::get<1>(GetParam());
-  SpvScope execution_scope = std::get<2>(GetParam());
+  spv::Scope execution_scope = std::get<2>(GetParam());
   std::string args = std::get<3>(GetParam());
   std::string error = std::get<4>(GetParam());
 
@@ -170,8 +171,8 @@
   CompileSuccessfully(GenerateShaderCode(sstr.str()), SPV_ENV_UNIVERSAL_1_3);
   spv_result_t result = ValidateInstructions(SPV_ENV_UNIVERSAL_1_3);
   if (error == "") {
-    if (execution_scope == SpvScopeSubgroup ||
-        execution_scope == SpvScopeWorkgroup) {
+    if (execution_scope == spv::Scope::Subgroup ||
+        execution_scope == spv::Scope::Workgroup) {
       EXPECT_EQ(SPV_SUCCESS, result);
     } else {
       EXPECT_EQ(SPV_ERROR_INVALID_DATA, result);
@@ -280,12 +281,12 @@
     GroupNonUniformBallotBitCountBadResultType, GroupNonUniform,
     Combine(
         Values("OpGroupNonUniformBallotBitCount"), Values("%float", "%int"),
-        Values(SpvScopeSubgroup), Values("Reduce %u32vec4_null"),
+        Values(spv::Scope::Subgroup), Values("Reduce %u32vec4_null"),
         Values("Expected Result Type to be an unsigned integer type scalar.")));
 
 INSTANTIATE_TEST_SUITE_P(GroupNonUniformBallotBitCountBadValue, GroupNonUniform,
                          Combine(Values("OpGroupNonUniformBallotBitCount"),
-                                 Values("%u32"), Values(SpvScopeSubgroup),
+                                 Values("%u32"), Values(spv::Scope::Subgroup),
                                  Values("Reduce %u32vec3_null", "Reduce %u32_0",
                                         "Reduce %float_0"),
                                  Values("Expected Value to be a vector of four "
diff --git a/test/val/val_state_test.cpp b/test/val/val_state_test.cpp
index 65cb1c3..4097a1f 100644
--- a/test/val/val_state_test.cpp
+++ b/test/val/val_state_test.cpp
@@ -59,40 +59,41 @@
 
 TEST_F(ValidationState_HasAnyOfCapabilities, EmptyMask) {
   EXPECT_TRUE(state_.HasAnyOfCapabilities({}));
-  state_.RegisterCapability(SpvCapabilityMatrix);
+  state_.RegisterCapability(spv::Capability::Matrix);
   EXPECT_TRUE(state_.HasAnyOfCapabilities({}));
-  state_.RegisterCapability(SpvCapabilityImageMipmap);
+  state_.RegisterCapability(spv::Capability::ImageMipmap);
   EXPECT_TRUE(state_.HasAnyOfCapabilities({}));
-  state_.RegisterCapability(SpvCapabilityPipes);
+  state_.RegisterCapability(spv::Capability::Pipes);
   EXPECT_TRUE(state_.HasAnyOfCapabilities({}));
-  state_.RegisterCapability(SpvCapabilityStorageImageArrayDynamicIndexing);
+  state_.RegisterCapability(spv::Capability::StorageImageArrayDynamicIndexing);
   EXPECT_TRUE(state_.HasAnyOfCapabilities({}));
-  state_.RegisterCapability(SpvCapabilityClipDistance);
+  state_.RegisterCapability(spv::Capability::ClipDistance);
   EXPECT_TRUE(state_.HasAnyOfCapabilities({}));
-  state_.RegisterCapability(SpvCapabilityStorageImageWriteWithoutFormat);
+  state_.RegisterCapability(spv::Capability::StorageImageWriteWithoutFormat);
   EXPECT_TRUE(state_.HasAnyOfCapabilities({}));
 }
 
 TEST_F(ValidationState_HasAnyOfCapabilities, SingleCapMask) {
-  EXPECT_FALSE(state_.HasAnyOfCapabilities({SpvCapabilityMatrix}));
-  EXPECT_FALSE(state_.HasAnyOfCapabilities({SpvCapabilityImageMipmap}));
-  state_.RegisterCapability(SpvCapabilityMatrix);
-  EXPECT_TRUE(state_.HasAnyOfCapabilities({SpvCapabilityMatrix}));
-  EXPECT_FALSE(state_.HasAnyOfCapabilities({SpvCapabilityImageMipmap}));
-  state_.RegisterCapability(SpvCapabilityImageMipmap);
-  EXPECT_TRUE(state_.HasAnyOfCapabilities({SpvCapabilityMatrix}));
-  EXPECT_TRUE(state_.HasAnyOfCapabilities({SpvCapabilityImageMipmap}));
+  EXPECT_FALSE(state_.HasAnyOfCapabilities({spv::Capability::Matrix}));
+  EXPECT_FALSE(state_.HasAnyOfCapabilities({spv::Capability::ImageMipmap}));
+  state_.RegisterCapability(spv::Capability::Matrix);
+  EXPECT_TRUE(state_.HasAnyOfCapabilities({spv::Capability::Matrix}));
+  EXPECT_FALSE(state_.HasAnyOfCapabilities({spv::Capability::ImageMipmap}));
+  state_.RegisterCapability(spv::Capability::ImageMipmap);
+  EXPECT_TRUE(state_.HasAnyOfCapabilities({spv::Capability::Matrix}));
+  EXPECT_TRUE(state_.HasAnyOfCapabilities({spv::Capability::ImageMipmap}));
 }
 
 TEST_F(ValidationState_HasAnyOfCapabilities, MultiCapMask) {
   const auto set1 =
-      CapabilitySet{SpvCapabilitySampledRect, SpvCapabilityImageBuffer};
-  const auto set2 = CapabilitySet{SpvCapabilityStorageImageWriteWithoutFormat,
-                                  SpvCapabilityStorageImageReadWithoutFormat,
-                                  SpvCapabilityGeometryStreams};
+      CapabilitySet{spv::Capability::SampledRect, spv::Capability::ImageBuffer};
+  const auto set2 =
+      CapabilitySet{spv::Capability::StorageImageWriteWithoutFormat,
+                    spv::Capability::StorageImageReadWithoutFormat,
+                    spv::Capability::GeometryStreams};
   EXPECT_FALSE(state_.HasAnyOfCapabilities(set1));
   EXPECT_FALSE(state_.HasAnyOfCapabilities(set2));
-  state_.RegisterCapability(SpvCapabilityImageBuffer);
+  state_.RegisterCapability(spv::Capability::ImageBuffer);
   EXPECT_TRUE(state_.HasAnyOfCapabilities(set1));
   EXPECT_FALSE(state_.HasAnyOfCapabilities(set2));
 }
@@ -139,50 +140,52 @@
 
 TEST_F(ValidationState_InLayoutState, Variable) {
   state_.SetCurrentLayoutSectionForTesting(kLayoutTypes);
-  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(SpvOpVariable));
+  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(spv::Op::OpVariable));
 
   state_.SetCurrentLayoutSectionForTesting(kLayoutFunctionDefinitions);
-  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(SpvOpVariable));
+  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(spv::Op::OpVariable));
 }
 
 TEST_F(ValidationState_InLayoutState, ExtInst) {
   state_.SetCurrentLayoutSectionForTesting(kLayoutTypes);
-  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(SpvOpExtInst));
+  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(spv::Op::OpExtInst));
 
   state_.SetCurrentLayoutSectionForTesting(kLayoutFunctionDefinitions);
-  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(SpvOpExtInst));
+  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(spv::Op::OpExtInst));
 }
 
 TEST_F(ValidationState_InLayoutState, Undef) {
   state_.SetCurrentLayoutSectionForTesting(kLayoutTypes);
-  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(SpvOpUndef));
+  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(spv::Op::OpUndef));
 
   state_.SetCurrentLayoutSectionForTesting(kLayoutFunctionDefinitions);
-  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(SpvOpUndef));
+  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(spv::Op::OpUndef));
 }
 
 TEST_F(ValidationState_InLayoutState, Function) {
   state_.SetCurrentLayoutSectionForTesting(kLayoutFunctionDeclarations);
-  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(SpvOpFunction));
+  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(spv::Op::OpFunction));
 
   state_.SetCurrentLayoutSectionForTesting(kLayoutFunctionDefinitions);
-  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(SpvOpFunction));
+  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(spv::Op::OpFunction));
 }
 
 TEST_F(ValidationState_InLayoutState, FunctionParameter) {
   state_.SetCurrentLayoutSectionForTesting(kLayoutFunctionDeclarations);
-  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(SpvOpFunctionParameter));
+  EXPECT_TRUE(
+      state_.IsOpcodeInCurrentLayoutSection(spv::Op::OpFunctionParameter));
 
   state_.SetCurrentLayoutSectionForTesting(kLayoutFunctionDefinitions);
-  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(SpvOpFunctionParameter));
+  EXPECT_TRUE(
+      state_.IsOpcodeInCurrentLayoutSection(spv::Op::OpFunctionParameter));
 }
 
 TEST_F(ValidationState_InLayoutState, FunctionEnd) {
   state_.SetCurrentLayoutSectionForTesting(kLayoutFunctionDeclarations);
-  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(SpvOpFunctionEnd));
+  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(spv::Op::OpFunctionEnd));
 
   state_.SetCurrentLayoutSectionForTesting(kLayoutFunctionDefinitions);
-  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(SpvOpFunctionEnd));
+  EXPECT_TRUE(state_.IsOpcodeInCurrentLayoutSection(spv::Op::OpFunctionEnd));
 }
 
 }  // namespace
diff --git a/test/val/val_type_unique_test.cpp b/test/val/val_type_unique_test.cpp
index 45a4d50..31ad3a6 100644
--- a/test/val/val_type_unique_test.cpp
+++ b/test/val/val_type_unique_test.cpp
@@ -90,7 +90,7 @@
 
 // Returns expected error string if |opcode| produces a duplicate type
 // declaration.
-std::string GetErrorString(SpvOp opcode) {
+std::string GetErrorString(spv::Op opcode) {
   return "Duplicate non-aggregate type declarations are not allowed. Opcode: " +
          std::string(spvOpcodeString(opcode));
 }
@@ -107,7 +107,8 @@
 )" + GetBody();
   CompileSuccessfully(str.c_str());
   ASSERT_EQ(kDuplicateTypeError, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr(GetErrorString(SpvOpTypeVoid)));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(GetErrorString(spv::Op::OpTypeVoid)));
 }
 
 TEST_F(ValidateTypeUnique, duplicate_bool) {
@@ -116,7 +117,8 @@
 )" + GetBody();
   CompileSuccessfully(str.c_str());
   ASSERT_EQ(kDuplicateTypeError, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr(GetErrorString(SpvOpTypeBool)));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(GetErrorString(spv::Op::OpTypeBool)));
 }
 
 TEST_F(ValidateTypeUnique, duplicate_int) {
@@ -125,7 +127,8 @@
 )" + GetBody();
   CompileSuccessfully(str.c_str());
   ASSERT_EQ(kDuplicateTypeError, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr(GetErrorString(SpvOpTypeInt)));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(GetErrorString(spv::Op::OpTypeInt)));
 }
 
 TEST_F(ValidateTypeUnique, duplicate_float) {
@@ -134,7 +137,8 @@
 )" + GetBody();
   CompileSuccessfully(str.c_str());
   ASSERT_EQ(kDuplicateTypeError, ValidateInstructions());
-  EXPECT_THAT(getDiagnosticString(), HasSubstr(GetErrorString(SpvOpTypeFloat)));
+  EXPECT_THAT(getDiagnosticString(),
+              HasSubstr(GetErrorString(spv::Op::OpTypeFloat)));
 }
 
 TEST_F(ValidateTypeUnique, duplicate_vec3) {
@@ -144,7 +148,7 @@
   CompileSuccessfully(str.c_str());
   ASSERT_EQ(kDuplicateTypeError, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr(GetErrorString(SpvOpTypeVector)));
+              HasSubstr(GetErrorString(spv::Op::OpTypeVector)));
 }
 
 TEST_F(ValidateTypeUnique, duplicate_mat33) {
@@ -154,7 +158,7 @@
   CompileSuccessfully(str.c_str());
   ASSERT_EQ(kDuplicateTypeError, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr(GetErrorString(SpvOpTypeMatrix)));
+              HasSubstr(GetErrorString(spv::Op::OpTypeMatrix)));
 }
 
 TEST_F(ValidateTypeUnique, duplicate_vfunc) {
@@ -164,7 +168,7 @@
   CompileSuccessfully(str.c_str());
   ASSERT_EQ(kDuplicateTypeError, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr(GetErrorString(SpvOpTypeFunction)));
+              HasSubstr(GetErrorString(spv::Op::OpTypeFunction)));
 }
 
 TEST_F(ValidateTypeUnique, duplicate_pipe_storage) {
@@ -181,7 +185,7 @@
   CompileSuccessfully(str.c_str(), SPV_ENV_UNIVERSAL_1_1);
   ASSERT_EQ(kDuplicateTypeError, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr(GetErrorString(SpvOpTypePipeStorage)));
+              HasSubstr(GetErrorString(spv::Op::OpTypePipeStorage)));
 }
 
 TEST_F(ValidateTypeUnique, duplicate_named_barrier) {
@@ -197,7 +201,7 @@
   CompileSuccessfully(str.c_str(), SPV_ENV_UNIVERSAL_1_1);
   ASSERT_EQ(kDuplicateTypeError, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
   EXPECT_THAT(getDiagnosticString(),
-              HasSubstr(GetErrorString(SpvOpTypeNamedBarrier)));
+              HasSubstr(GetErrorString(spv::Op::OpTypeNamedBarrier)));
 }
 
 TEST_F(ValidateTypeUnique, duplicate_forward_pointer) {
@@ -234,7 +238,7 @@
   CompileSuccessfully(str.c_str());
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              Not(HasSubstr(GetErrorString(SpvOpTypeVoid))));
+              Not(HasSubstr(GetErrorString(spv::Op::OpTypeVoid))));
 }
 
 TEST_F(ValidateTypeUnique, DuplicatePointerTypesNoExtension) {
@@ -263,7 +267,7 @@
   CompileSuccessfully(str.c_str());
   ASSERT_EQ(SPV_SUCCESS, ValidateInstructions());
   EXPECT_THAT(getDiagnosticString(),
-              Not(HasSubstr(GetErrorString(SpvOpTypePointer))));
+              Not(HasSubstr(GetErrorString(spv::Op::OpTypePointer))));
 }
 
 }  // namespace
diff --git a/test/val/val_validation_state_test.cpp b/test/val/val_validation_state_test.cpp
index 3dd9e64..a5e88de 100644
--- a/test/val/val_validation_state_test.cpp
+++ b/test/val/val_validation_state_test.cpp
@@ -180,7 +180,7 @@
   CompileSuccessfully(spirv);
   EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
   EXPECT_EQ(size_t(1), vstate_->entry_points().size());
-  EXPECT_EQ(SpvOpFunction,
+  EXPECT_EQ(spv::Op::OpFunction,
             vstate_->FindDef(vstate_->entry_points()[0])->opcode());
 }
 
diff --git a/tools/cfg/bin_to_dot.cpp b/tools/cfg/bin_to_dot.cpp
index 72e7693..40a7dc4 100644
--- a/tools/cfg/bin_to_dot.cpp
+++ b/tools/cfg/bin_to_dot.cpp
@@ -81,26 +81,26 @@
 
 spv_result_t DotConverter::HandleInstruction(
     const spv_parsed_instruction_t& inst) {
-  switch (inst.opcode) {
-    case SpvOpFunction:
+  switch (spv::Op(inst.opcode)) {
+    case spv::Op::OpFunction:
       current_function_id_ = inst.result_id;
       seen_function_entry_block_ = false;
       break;
-    case SpvOpFunctionEnd:
+    case spv::Op::OpFunctionEnd:
       current_function_id_ = 0;
       break;
 
-    case SpvOpLabel:
+    case spv::Op::OpLabel:
       current_block_id_ = inst.result_id;
       break;
 
-    case SpvOpBranch:
+    case spv::Op::OpBranch:
       FlushBlock({inst.words[1]});
       break;
-    case SpvOpBranchConditional:
+    case spv::Op::OpBranchConditional:
       FlushBlock({inst.words[2], inst.words[3]});
       break;
-    case SpvOpSwitch: {
+    case spv::Op::OpSwitch: {
       std::vector<uint32_t> successors{inst.words[2]};
       for (size_t i = 3; i < inst.num_operands; i += 2) {
         successors.push_back(inst.words[inst.operands[i].offset]);
@@ -108,18 +108,18 @@
       FlushBlock(successors);
     } break;
 
-    case SpvOpKill:
-    case SpvOpReturn:
-    case SpvOpUnreachable:
-    case SpvOpReturnValue:
+    case spv::Op::OpKill:
+    case spv::Op::OpReturn:
+    case spv::Op::OpUnreachable:
+    case spv::Op::OpReturnValue:
       FlushBlock({});
       break;
 
-    case SpvOpLoopMerge:
+    case spv::Op::OpLoopMerge:
       merge_ = inst.words[1];
       continue_target_ = inst.words[2];
       break;
-    case SpvOpSelectionMerge:
+    case spv::Op::OpSelectionMerge:
       merge_ = inst.words[1];
       break;
     default:
diff --git a/utils/generate_grammar_tables.py b/utils/generate_grammar_tables.py
index 74aa282..6b7167b 100755
--- a/utils/generate_grammar_tables.py
+++ b/utils/generate_grammar_tables.py
@@ -33,6 +33,7 @@
 SPV_KHR_non_semantic_info
 """
 
+OUTPUT_LANGUAGE = 'c'
 
 def make_path_to_file(f):
     """Makes all ancestor directories to the given file, if they don't yet
@@ -76,9 +77,14 @@
       - caps: a sequence of capability names
 
     Returns:
-      a string containing the braced list of SpvCapability* enums named by caps.
+      a string containing the braced list of SpvCapability* or spv::Capability:: enums named by caps.
     """
-    return '{' + ', '.join(['SpvCapability{}'.format(c) for c in caps]) + '}'
+    base_string = 'SpvCapability'
+    global OUTPUT_LANGUAGE
+    if OUTPUT_LANGUAGE == 'c++':
+        base_string = 'spv::Capability::'
+
+    return '{' + ', '.join([(base_string + '{}').format(c) for c in caps]) + '}'
 
 
 def get_capability_array_name(caps):
@@ -99,8 +105,12 @@
       - caps: a sequence of sequence of capability names
     """
     caps = sorted(set([tuple(c) for c in caps if c]))
+    cap_str = 'SpvCapability'
+    global OUTPUT_LANGUAGE
+    if OUTPUT_LANGUAGE == 'c++':
+        cap_str = 'spv::Capability'
     arrays = [
-        'static const SpvCapability {}[] = {};'.format(
+        'static const ' + cap_str + ' {}[] = {};'.format(
             get_capability_array_name(c), compose_capability_list(c))
         for c in caps]
     return '\n'.join(arrays)
@@ -255,7 +265,12 @@
             self.operands.pop()
 
     def __str__(self):
-        template = ['{{"{opname}"', 'SpvOp{opname}',
+        global OUTPUT_LANGUAGE
+        base_str = 'SpvOp'
+        if OUTPUT_LANGUAGE == 'c++':
+            base_str = 'spv::Op::Op'
+
+        template = ['{{"{opname}"', base_str + '{opname}',
                     '{num_caps}', '{caps_mask}',
                     '{num_operands}', '{{{operands}}}',
                     '{def_result_id}', '{ref_type_id}',
@@ -634,9 +649,16 @@
 
     We take care to avoid emitting duplicate values.
     """
-    function = 'const char* CapabilityToString(SpvCapability capability) {\n'
+    cap_str = 'SpvCapability'
+    cap_join = ''
+    global OUTPUT_LANGUAGE
+    if OUTPUT_LANGUAGE == 'c++':
+        cap_str = 'spv::Capability'
+        cap_join = '::'
+
+    function = 'const char* CapabilityToString(' + cap_str + ' capability) {\n'
     function += '  switch (capability) {\n'
-    template = '    case SpvCapability{capability}:\n' \
+    template = '    case ' + cap_str + cap_join + '{capability}:\n' \
         '      return "{capability}";\n'
     emitted = set()  # The values of capabilities we already have emitted
     for capability in get_capabilities(operand_kinds):
@@ -644,8 +666,8 @@
         if value not in emitted:
             emitted.add(value)
             function += template.format(capability=capability.get('enumerant'))
-    function += '    case SpvCapabilityMax:\n' \
-        '      assert(0 && "Attempting to convert SpvCapabilityMax to string");\n' \
+    function += '    case ' + cap_str + cap_join + 'Max:\n' \
+        '      assert(0 && "Attempting to convert ' + cap_str + cap_join + 'Max to string");\n' \
         '      return "";\n'
     function += '  }\n\n  return "";\n}'
     return function
@@ -734,6 +756,10 @@
                         type=str, required=False, default=None,
                         help='input JSON grammar file for OpenCL extended '
                         'instruction set')
+    parser.add_argument('--output-language',
+                        type=str, required=False, default='c',
+                        choices=['c','c++'],
+                        help='specify output language type')
 
     parser.add_argument('--core-insts-output', metavar='<path>',
                         type=str, required=False, default=None,
@@ -765,6 +791,9 @@
                         help='prefix for operand kinds (to disambiguate operand type enums)')
     args = parser.parse_args()
 
+    global OUTPUT_LANGUAGE
+    OUTPUT_LANGUAGE = args.output_language
+
     # The GN build system needs this because it doesn't handle quoting
     # empty string arguments well.
     if args.vendor_operand_kind_prefix == "...nil...":