Convert validation to use libspriv::Instruction where possible. (#1663)

For the instructions which execute after the IdPass check we can provide
the Instruction instead of the spv_parsed_instruction_t. This
Instruction class provides a bit more context (like the source line)
that is not available from spv_parsed_instruction_t.
diff --git a/source/val/instruction.h b/source/val/instruction.h
index c47e6ba..72881d9 100644
--- a/source/val/instruction.h
+++ b/source/val/instruction.h
@@ -67,6 +67,11 @@
   /// The words used to define the Instruction
   const std::vector<uint32_t>& words() const { return words_; }
 
+  /// Returns the operand at |idx|.
+  const spv_parsed_operand_t& operand(size_t idx) const {
+    return operands_[idx];
+  }
+
   /// The operands of the Instruction
   const std::vector<spv_parsed_operand_t>& operands() const {
     return operands_;
@@ -75,13 +80,18 @@
   /// Provides direct access to the stored C instruction object.
   const spv_parsed_instruction_t& c_inst() const { return inst_; }
 
+  /// Provides direct access to instructions spv_ext_inst_type_t object.
+  const spv_ext_inst_type_t& ext_inst_type() const {
+    return inst_.ext_inst_type;
+  }
+
   // Casts the words belonging to the operand under |index| to |T| and returns.
   template <typename T>
   T GetOperandAs(size_t index) const {
-    const spv_parsed_operand_t& operand = operands_.at(index);
-    assert(operand.num_words * 4 >= sizeof(T));
-    assert(operand.offset + operand.num_words <= inst_.num_words);
-    return *reinterpret_cast<const T*>(&words_[operand.offset]);
+    const spv_parsed_operand_t& o = operands_.at(index);
+    assert(o.num_words * 4 >= sizeof(T));
+    assert(o.offset + o.num_words <= inst_.num_words);
+    return *reinterpret_cast<const T*>(&words_[o.offset]);
   }
 
   int InstructionPosition() const { return instruction_position_; }
diff --git a/source/val/validation_state.cpp b/source/val/validation_state.cpp
index afcc786..6907e59 100644
--- a/source/val/validation_state.cpp
+++ b/source/val/validation_state.cpp
@@ -487,20 +487,20 @@
 
 void ValidationState_t::setIdBound(const uint32_t bound) { id_bound_ = bound; }
 
-bool ValidationState_t::RegisterUniqueTypeDeclaration(
-    const spv_parsed_instruction_t& inst) {
+bool ValidationState_t::RegisterUniqueTypeDeclaration(const Instruction* inst) {
   std::vector<uint32_t> key;
-  key.push_back(static_cast<uint32_t>(inst.opcode));
-  for (int index = 0; index < inst.num_operands; ++index) {
-    const spv_parsed_operand_t& operand = inst.operands[index];
+  key.push_back(static_cast<uint32_t>(inst->opcode()));
+  for (size_t index = 0; index < inst->operands().size(); ++index) {
+    const spv_parsed_operand_t& operand = inst->operand(index);
 
     if (operand.type == SPV_OPERAND_TYPE_RESULT_ID) continue;
 
     const int words_begin = operand.offset;
     const int words_end = words_begin + operand.num_words;
-    assert(words_end <= static_cast<int>(inst.num_words));
+    assert(words_end <= static_cast<int>(inst->words().size()));
 
-    key.insert(key.end(), inst.words + words_begin, inst.words + words_end);
+    key.insert(key.end(), inst->words().begin() + words_begin,
+               inst->words().begin() + words_end);
   }
 
   return unique_type_declarations_.insert(std::move(key)).second;
@@ -784,12 +784,9 @@
   return true;
 }
 
-uint32_t ValidationState_t::GetOperandTypeId(
-    const spv_parsed_instruction_t* inst, size_t operand_index) const {
-  assert(operand_index < inst->num_operands);
-  const spv_parsed_operand_t& operand = inst->operands[operand_index];
-  assert(operand.num_words == 1);
-  return GetTypeId(inst->words[operand.offset]);
+uint32_t ValidationState_t::GetOperandTypeId(const Instruction* inst,
+                                             size_t operand_index) const {
+  return GetTypeId(inst->GetOperandAs<uint32_t>(operand_index));
 }
 
 bool ValidationState_t::GetConstantValUint64(uint32_t id, uint64_t* val) const {
diff --git a/source/val/validation_state.h b/source/val/validation_state.h
index 463cb23..d1b5281 100644
--- a/source/val/validation_state.h
+++ b/source/val/validation_state.h
@@ -400,7 +400,7 @@
 
   /// Adds the instruction data to unique_type_declarations_.
   /// Returns false if an identical type declaration already exists.
-  bool RegisterUniqueTypeDeclaration(const spv_parsed_instruction_t& inst);
+  bool RegisterUniqueTypeDeclaration(const Instruction* inst);
 
   // Returns type_id of the scalar component of |id|.
   // |id| can be either
@@ -466,7 +466,7 @@
   // 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
   // id.
-  uint32_t GetOperandTypeId(const spv_parsed_instruction_t* inst,
+  uint32_t GetOperandTypeId(const Instruction* inst,
                             size_t operand_index) const;
 
   // Provides information on pointer type. Returns false iff not pointer type.
diff --git a/source/validate.cpp b/source/validate.cpp
index 76a81df..64321e6 100644
--- a/source/validate.cpp
+++ b/source/validate.cpp
@@ -174,24 +174,24 @@
 
   const Instruction* instruction = &(_.ordered_instructions().back());
 
-  if (auto error = DataRulesPass(_, inst)) return error;
-  if (auto error = ModuleLayoutPass(_, inst)) return error;
+  if (auto error = DataRulesPass(_, instruction)) return error;
+  if (auto error = ModuleLayoutPass(_, instruction)) return error;
   if (auto error = CfgPass(_, instruction)) return error;
-  if (auto error = InstructionPass(_, inst)) return error;
-  if (auto error = TypeUniquePass(_, inst)) return error;
-  if (auto error = ArithmeticsPass(_, inst)) return error;
-  if (auto error = CompositesPass(_, inst)) return error;
-  if (auto error = ConversionPass(_, inst)) return error;
-  if (auto error = DerivativesPass(_, inst)) return error;
-  if (auto error = LogicalsPass(_, inst)) return error;
-  if (auto error = BitwisePass(_, inst)) return error;
-  if (auto error = ExtInstPass(_, inst)) return error;
-  if (auto error = ImagePass(_, inst)) return error;
-  if (auto error = AtomicsPass(_, inst)) return error;
-  if (auto error = BarriersPass(_, inst)) return error;
-  if (auto error = PrimitivesPass(_, inst)) return error;
-  if (auto error = LiteralsPass(_, inst)) return error;
-  if (auto error = NonUniformPass(_, inst)) return error;
+  if (auto error = InstructionPass(_, instruction)) return error;
+  if (auto error = TypeUniquePass(_, instruction)) return error;
+  if (auto error = ArithmeticsPass(_, instruction)) return error;
+  if (auto error = CompositesPass(_, instruction)) return error;
+  if (auto error = ConversionPass(_, instruction)) return error;
+  if (auto error = DerivativesPass(_, instruction)) return error;
+  if (auto error = LogicalsPass(_, instruction)) return error;
+  if (auto error = BitwisePass(_, instruction)) return error;
+  if (auto error = ExtInstPass(_, instruction)) return error;
+  if (auto error = ImagePass(_, instruction)) return error;
+  if (auto error = AtomicsPass(_, instruction)) return error;
+  if (auto error = BarriersPass(_, instruction)) return error;
+  if (auto error = PrimitivesPass(_, instruction)) return error;
+  if (auto error = LiteralsPass(_, instruction)) return error;
+  if (auto error = NonUniformPass(_, instruction)) return error;
 
   return SPV_SUCCESS;
 }
diff --git a/source/validate.h b/source/validate.h
index 5d84629..845ffa4 100644
--- a/source/validate.h
+++ b/source/validate.h
@@ -106,8 +106,7 @@
 
 /// Performs logical layout validation as described in section 2.4 of the SPIR-V
 /// spec.
-spv_result_t ModuleLayoutPass(ValidationState_t& _,
-                              const spv_parsed_instruction_t* inst);
+spv_result_t ModuleLayoutPass(ValidationState_t& _, const Instruction* inst);
 
 /// Performs Control Flow Graph validation of a module
 spv_result_t CfgPass(ValidationState_t& _, const Instruction* inst);
@@ -118,12 +117,10 @@
 /// Performs validation of the Data Rules subsection of 2.16.1 Universal
 /// Validation Rules.
 /// TODO(ehsann): add more comments here as more validation code is added.
-spv_result_t DataRulesPass(ValidationState_t& _,
-                           const spv_parsed_instruction_t* inst);
+spv_result_t DataRulesPass(ValidationState_t& _, const Instruction* inst);
 
 /// Performs instruction validation.
-spv_result_t InstructionPass(ValidationState_t& _,
-                             const spv_parsed_instruction_t* inst);
+spv_result_t InstructionPass(ValidationState_t& _, const Instruction* inst);
 
 /// Performs decoration validation.
 spv_result_t ValidateDecorations(ValidationState_t& _);
@@ -134,56 +131,43 @@
 /// Validates that type declarations are unique, unless multiple declarations
 /// of the same data type are allowed by the specification.
 /// (see section 2.8 Types and Variables)
-spv_result_t TypeUniquePass(ValidationState_t& _,
-                            const spv_parsed_instruction_t* inst);
+spv_result_t TypeUniquePass(ValidationState_t& _, const Instruction* inst);
 
 /// Validates correctness of arithmetic instructions.
-spv_result_t ArithmeticsPass(ValidationState_t& _,
-                             const spv_parsed_instruction_t* inst);
+spv_result_t ArithmeticsPass(ValidationState_t& _, const Instruction* inst);
 
 /// Validates correctness of composite instructions.
-spv_result_t CompositesPass(ValidationState_t& _,
-                            const spv_parsed_instruction_t* inst);
+spv_result_t CompositesPass(ValidationState_t& _, const Instruction* inst);
 
 /// Validates correctness of conversion instructions.
-spv_result_t ConversionPass(ValidationState_t& _,
-                            const spv_parsed_instruction_t* inst);
+spv_result_t ConversionPass(ValidationState_t& _, const Instruction* inst);
 
 /// Validates correctness of derivative instructions.
-spv_result_t DerivativesPass(ValidationState_t& _,
-                             const spv_parsed_instruction_t* inst);
+spv_result_t DerivativesPass(ValidationState_t& _, const Instruction* inst);
 
 /// Validates correctness of logical instructions.
-spv_result_t LogicalsPass(ValidationState_t& _,
-                          const spv_parsed_instruction_t* inst);
+spv_result_t LogicalsPass(ValidationState_t& _, const Instruction* inst);
 
 /// Validates correctness of bitwise instructions.
-spv_result_t BitwisePass(ValidationState_t& _,
-                         const spv_parsed_instruction_t* inst);
+spv_result_t BitwisePass(ValidationState_t& _, const Instruction* inst);
 
 /// Validates correctness of image instructions.
-spv_result_t ImagePass(ValidationState_t& _,
-                       const spv_parsed_instruction_t* inst);
+spv_result_t ImagePass(ValidationState_t& _, const Instruction* inst);
 
 /// Validates correctness of atomic instructions.
-spv_result_t AtomicsPass(ValidationState_t& _,
-                         const spv_parsed_instruction_t* inst);
+spv_result_t AtomicsPass(ValidationState_t& _, const Instruction* inst);
 
 /// Validates correctness of barrier instructions.
-spv_result_t BarriersPass(ValidationState_t& _,
-                          const spv_parsed_instruction_t* inst);
+spv_result_t BarriersPass(ValidationState_t& _, const Instruction* inst);
 
 /// Validates correctness of literal numbers.
-spv_result_t LiteralsPass(ValidationState_t& _,
-                          const spv_parsed_instruction_t* inst);
+spv_result_t LiteralsPass(ValidationState_t& _, const Instruction* inst);
 
 /// Validates correctness of ExtInst instructions.
-spv_result_t ExtInstPass(ValidationState_t& _,
-                         const spv_parsed_instruction_t* inst);
+spv_result_t ExtInstPass(ValidationState_t& _, const Instruction* inst);
 
 /// Validates correctness of non-uniform group instructions.
-spv_result_t NonUniformPass(ValidationState_t& _,
-                            const spv_parsed_instruction_t* inst);
+spv_result_t NonUniformPass(ValidationState_t& _, const Instruction* inst);
 
 // Validates that capability declarations use operands allowed in the current
 // context.
@@ -191,8 +175,7 @@
                             const spv_parsed_instruction_t* inst);
 
 /// Validates correctness of primitive instructions.
-spv_result_t PrimitivesPass(ValidationState_t& _,
-                            const spv_parsed_instruction_t* inst);
+spv_result_t PrimitivesPass(ValidationState_t& _, const Instruction* inst);
 
 /// @brief Validate the ID usage of the instruction stream
 ///
diff --git a/source/validate_arithmetics.cpp b/source/validate_arithmetics.cpp
index 3460cde..d40c234 100644
--- a/source/validate_arithmetics.cpp
+++ b/source/validate_arithmetics.cpp
@@ -23,33 +23,11 @@
 
 namespace spvtools {
 namespace val {
-namespace {
-
-// Returns operand word for given instruction and operand index.
-// The operand is expected to only have one word.
-inline uint32_t GetOperandWord(const spv_parsed_instruction_t* inst,
-                               size_t operand_index) {
-  assert(operand_index < inst->num_operands);
-  const spv_parsed_operand_t& operand = inst->operands[operand_index];
-  assert(operand.num_words == 1);
-  return inst->words[operand.offset];
-}
-
-// Returns the type id of instruction operand at |operand_index|.
-// The operand is expected to be an id.
-inline uint32_t GetOperandTypeId(ValidationState_t& _,
-                                 const spv_parsed_instruction_t* inst,
-                                 size_t operand_index) {
-  return _.GetTypeId(GetOperandWord(inst, operand_index));
-}
-
-}  // namespace
 
 // Validates correctness of arithmetic instructions.
-spv_result_t ArithmeticsPass(ValidationState_t& _,
-                             const spv_parsed_instruction_t* inst) {
-  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
-  const uint32_t result_type = inst->type_id;
+spv_result_t ArithmeticsPass(ValidationState_t& _, const Instruction* inst) {
+  const SpvOp opcode = inst->opcode();
+  const uint32_t result_type = inst->type_id();
 
   switch (opcode) {
     case SpvOpFAdd:
@@ -65,9 +43,9 @@
                << "Expected floating scalar or vector type as Result Type: "
                << spvOpcodeString(opcode);
 
-      for (size_t operand_index = 2; operand_index < inst->num_operands;
+      for (size_t operand_index = 2; operand_index < inst->operands().size();
            ++operand_index) {
-        if (GetOperandTypeId(_, inst, operand_index) != result_type)
+        if (_.GetOperandTypeId(inst, operand_index) != result_type)
           return _.diag(SPV_ERROR_INVALID_DATA)
                  << "Expected arithmetic operands to be of Result Type: "
                  << spvOpcodeString(opcode) << " operand index "
@@ -84,9 +62,9 @@
                << "Expected unsigned int scalar or vector type as Result Type: "
                << spvOpcodeString(opcode);
 
-      for (size_t operand_index = 2; operand_index < inst->num_operands;
+      for (size_t operand_index = 2; operand_index < inst->operands().size();
            ++operand_index) {
-        if (GetOperandTypeId(_, inst, operand_index) != result_type)
+        if (_.GetOperandTypeId(inst, operand_index) != result_type)
           return _.diag(SPV_ERROR_INVALID_DATA)
                  << "Expected arithmetic operands to be of Result Type: "
                  << spvOpcodeString(opcode) << " operand index "
@@ -110,9 +88,9 @@
       const uint32_t dimension = _.GetDimension(result_type);
       const uint32_t bit_width = _.GetBitWidth(result_type);
 
-      for (size_t operand_index = 2; operand_index < inst->num_operands;
+      for (size_t operand_index = 2; operand_index < inst->operands().size();
            ++operand_index) {
-        const uint32_t type_id = GetOperandTypeId(_, inst, operand_index);
+        const uint32_t type_id = _.GetOperandTypeId(inst, operand_index);
         if (!type_id ||
             (!_.IsIntScalarType(type_id) && !_.IsIntVectorType(type_id)))
           return _.diag(SPV_ERROR_INVALID_DATA)
@@ -143,9 +121,9 @@
 
       uint32_t first_vector_num_components = 0;
 
-      for (size_t operand_index = 2; operand_index < inst->num_operands;
+      for (size_t operand_index = 2; operand_index < inst->operands().size();
            ++operand_index) {
-        const uint32_t type_id = GetOperandTypeId(_, inst, operand_index);
+        const uint32_t type_id = _.GetOperandTypeId(inst, operand_index);
 
         if (!type_id || !_.IsFloatVectorType(type_id))
           return _.diag(SPV_ERROR_INVALID_DATA)
@@ -178,7 +156,7 @@
                << "Expected float vector type as Result Type: "
                << spvOpcodeString(opcode);
 
-      const uint32_t vector_type_id = GetOperandTypeId(_, inst, 2);
+      const uint32_t vector_type_id = _.GetOperandTypeId(inst, 2);
       if (result_type != vector_type_id)
         return _.diag(SPV_ERROR_INVALID_DATA)
                << "Expected vector operand type to be equal to Result Type: "
@@ -186,7 +164,7 @@
 
       const uint32_t component_type = _.GetComponentType(vector_type_id);
 
-      const uint32_t scalar_type_id = GetOperandTypeId(_, inst, 3);
+      const uint32_t scalar_type_id = _.GetOperandTypeId(inst, 3);
       if (component_type != scalar_type_id)
         return _.diag(SPV_ERROR_INVALID_DATA)
                << "Expected scalar operand type to be equal to the component "
@@ -201,7 +179,7 @@
                << "Expected float matrix type as Result Type: "
                << spvOpcodeString(opcode);
 
-      const uint32_t matrix_type_id = GetOperandTypeId(_, inst, 2);
+      const uint32_t matrix_type_id = _.GetOperandTypeId(inst, 2);
       if (result_type != matrix_type_id)
         return _.diag(SPV_ERROR_INVALID_DATA)
                << "Expected matrix operand type to be equal to Result Type: "
@@ -209,7 +187,7 @@
 
       const uint32_t component_type = _.GetComponentType(matrix_type_id);
 
-      const uint32_t scalar_type_id = GetOperandTypeId(_, inst, 3);
+      const uint32_t scalar_type_id = _.GetOperandTypeId(inst, 3);
       if (component_type != scalar_type_id)
         return _.diag(SPV_ERROR_INVALID_DATA)
                << "Expected scalar operand type to be equal to the component "
@@ -219,8 +197,8 @@
     }
 
     case SpvOpVectorTimesMatrix: {
-      const uint32_t vector_type_id = GetOperandTypeId(_, inst, 2);
-      const uint32_t matrix_type_id = GetOperandTypeId(_, inst, 3);
+      const uint32_t vector_type_id = _.GetOperandTypeId(inst, 2);
+      const uint32_t matrix_type_id = _.GetOperandTypeId(inst, 3);
 
       if (!_.IsFloatVectorType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA)
@@ -269,8 +247,8 @@
     }
 
     case SpvOpMatrixTimesVector: {
-      const uint32_t matrix_type_id = GetOperandTypeId(_, inst, 2);
-      const uint32_t vector_type_id = GetOperandTypeId(_, inst, 3);
+      const uint32_t matrix_type_id = _.GetOperandTypeId(inst, 2);
+      const uint32_t vector_type_id = _.GetOperandTypeId(inst, 3);
 
       if (!_.IsFloatVectorType(result_type))
         return _.diag(SPV_ERROR_INVALID_DATA)
@@ -313,8 +291,8 @@
     }
 
     case SpvOpMatrixTimesMatrix: {
-      const uint32_t left_type_id = GetOperandTypeId(_, inst, 2);
-      const uint32_t right_type_id = GetOperandTypeId(_, inst, 3);
+      const uint32_t left_type_id = _.GetOperandTypeId(inst, 2);
+      const uint32_t right_type_id = _.GetOperandTypeId(inst, 3);
 
       uint32_t res_num_rows = 0;
       uint32_t res_num_cols = 0;
@@ -379,8 +357,8 @@
     }
 
     case SpvOpOuterProduct: {
-      const uint32_t left_type_id = GetOperandTypeId(_, inst, 2);
-      const uint32_t right_type_id = GetOperandTypeId(_, inst, 3);
+      const uint32_t left_type_id = _.GetOperandTypeId(inst, 2);
+      const uint32_t right_type_id = _.GetOperandTypeId(inst, 3);
 
       uint32_t res_num_rows = 0;
       uint32_t res_num_cols = 0;
@@ -451,8 +429,8 @@
                << "Expected Result Type struct member types to be identical: "
                << spvOpcodeString(opcode);
 
-      const uint32_t left_type_id = GetOperandTypeId(_, inst, 2);
-      const uint32_t right_type_id = GetOperandTypeId(_, inst, 3);
+      const uint32_t left_type_id = _.GetOperandTypeId(inst, 2);
+      const uint32_t right_type_id = _.GetOperandTypeId(inst, 3);
 
       if (left_type_id != result_types[0] || right_type_id != result_types[0])
         return _.diag(SPV_ERROR_INVALID_DATA)
diff --git a/source/validate_atomics.cpp b/source/validate_atomics.cpp
index b4a196c..f4eaba4 100644
--- a/source/validate_atomics.cpp
+++ b/source/validate_atomics.cpp
@@ -27,10 +27,9 @@
 namespace val {
 
 // Validates Memory Scope operand.
-spv_result_t ValidateMemoryScope(ValidationState_t& _,
-                                 const spv_parsed_instruction_t* inst,
+spv_result_t ValidateMemoryScope(ValidationState_t& _, const Instruction* inst,
                                  uint32_t id) {
-  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
+  const SpvOp opcode = inst->opcode();
   bool is_int32 = false, is_const_int32 = false;
   uint32_t value = 0;
   std::tie(is_int32, is_const_int32, value) = _.EvalInt32IfConst(id);
@@ -64,13 +63,12 @@
 
 // Validates a Memory Semantics operand.
 spv_result_t ValidateMemorySemantics(ValidationState_t& _,
-                                     const spv_parsed_instruction_t* inst,
+                                     const Instruction* inst,
                                      uint32_t operand_index) {
-  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
+  const SpvOp opcode = inst->opcode();
   bool is_int32 = false, is_const_int32 = false;
   uint32_t flags = 0;
-  const uint32_t memory_semantics_id =
-      inst->words[inst->operands[operand_index].offset];
+  auto memory_semantics_id = inst->GetOperandAs<const uint32_t>(operand_index);
   std::tie(is_int32, is_const_int32, flags) =
       _.EvalInt32IfConst(memory_semantics_id);
 
@@ -154,10 +152,9 @@
 }
 
 // Validates correctness of atomic instructions.
-spv_result_t AtomicsPass(ValidationState_t& _,
-                         const spv_parsed_instruction_t* inst) {
-  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
-  const uint32_t result_type = inst->type_id;
+spv_result_t AtomicsPass(ValidationState_t& _, const Instruction* inst) {
+  const SpvOp opcode = inst->opcode();
+  const uint32_t result_type = inst->type_id();
 
   switch (opcode) {
     case SpvOpAtomicLoad:
@@ -262,8 +259,7 @@
         }
       }
 
-      const uint32_t memory_scope =
-          inst->words[inst->operands[operand_index++].offset];
+      auto memory_scope = inst->GetOperandAs<const uint32_t>(operand_index++);
       if (auto error = ValidateMemoryScope(_, inst, memory_scope)) {
         return error;
       }
diff --git a/source/validate_barriers.cpp b/source/validate_barriers.cpp
index 8985ada..0a49407 100644
--- a/source/validate_barriers.cpp
+++ b/source/validate_barriers.cpp
@@ -30,9 +30,8 @@
 
 // Validates Execution Scope operand.
 spv_result_t ValidateExecutionScope(ValidationState_t& _,
-                                    const spv_parsed_instruction_t* inst,
-                                    uint32_t id) {
-  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
+                                    const Instruction* inst, uint32_t id) {
+  const SpvOp opcode = inst->opcode();
   bool is_int32 = false, is_const_int32 = false;
   uint32_t value = 0;
   std::tie(is_int32, is_const_int32, value) = _.EvalInt32IfConst(id);
@@ -82,10 +81,9 @@
 }
 
 // Validates Memory Scope operand.
-spv_result_t ValidateMemoryScope(ValidationState_t& _,
-                                 const spv_parsed_instruction_t* inst,
+spv_result_t ValidateMemoryScope(ValidationState_t& _, const Instruction* inst,
                                  uint32_t id) {
-  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
+  const SpvOp opcode = inst->opcode();
   bool is_int32 = false, is_const_int32 = false;
   uint32_t value = 0;
   std::tie(is_int32, is_const_int32, value) = _.EvalInt32IfConst(id);
@@ -124,9 +122,8 @@
 
 // Validates Memory Semantics operand.
 spv_result_t ValidateMemorySemantics(ValidationState_t& _,
-                                     const spv_parsed_instruction_t* inst,
-                                     uint32_t id) {
-  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
+                                     const Instruction* inst, uint32_t id) {
+  const SpvOp opcode = inst->opcode();
   bool is_int32 = false, is_const_int32 = false;
   uint32_t value = 0;
   std::tie(is_int32, is_const_int32, value) = _.EvalInt32IfConst(id);
@@ -193,10 +190,9 @@
 }  // namespace
 
 // Validates correctness of barrier instructions.
-spv_result_t BarriersPass(ValidationState_t& _,
-                          const spv_parsed_instruction_t* inst) {
-  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
-  const uint32_t result_type = inst->type_id;
+spv_result_t BarriersPass(ValidationState_t& _, const Instruction* inst) {
+  const SpvOp opcode = inst->opcode();
+  const uint32_t result_type = inst->type_id();
 
   switch (opcode) {
     case SpvOpControlBarrier: {
@@ -219,9 +215,9 @@
             });
       }
 
-      const uint32_t execution_scope = inst->words[1];
-      const uint32_t memory_scope = inst->words[2];
-      const uint32_t memory_semantics = inst->words[3];
+      const uint32_t execution_scope = inst->word(1);
+      const uint32_t memory_scope = inst->word(2);
+      const uint32_t memory_semantics = inst->word(3);
 
       if (auto error = ValidateExecutionScope(_, inst, execution_scope)) {
         return error;
@@ -238,8 +234,8 @@
     }
 
     case SpvOpMemoryBarrier: {
-      const uint32_t memory_scope = inst->words[1];
-      const uint32_t memory_semantics = inst->words[2];
+      const uint32_t memory_scope = inst->word(1);
+      const uint32_t memory_semantics = inst->word(2);
 
       if (auto error = ValidateMemoryScope(_, inst, memory_scope)) {
         return error;
@@ -276,8 +272,8 @@
                << ": expected Named Barrier to be of type OpTypeNamedBarrier";
       }
 
-      const uint32_t memory_scope = inst->words[2];
-      const uint32_t memory_semantics = inst->words[3];
+      const uint32_t memory_scope = inst->word(2);
+      const uint32_t memory_semantics = inst->word(3);
 
       if (auto error = ValidateMemoryScope(_, inst, memory_scope)) {
         return error;
diff --git a/source/validate_bitwise.cpp b/source/validate_bitwise.cpp
index cd00cd6..953fc46 100644
--- a/source/validate_bitwise.cpp
+++ b/source/validate_bitwise.cpp
@@ -23,33 +23,11 @@
 
 namespace spvtools {
 namespace val {
-namespace {
-
-// Returns operand word for given instruction and operand index.
-// The operand is expected to only have one word.
-inline uint32_t GetOperandWord(const spv_parsed_instruction_t* inst,
-                               size_t operand_index) {
-  assert(operand_index < inst->num_operands);
-  const spv_parsed_operand_t& operand = inst->operands[operand_index];
-  assert(operand.num_words == 1);
-  return inst->words[operand.offset];
-}
-
-// Returns the type id of instruction operand at |operand_index|.
-// The operand is expected to be an id.
-inline uint32_t GetOperandTypeId(ValidationState_t& _,
-                                 const spv_parsed_instruction_t* inst,
-                                 size_t operand_index) {
-  return _.GetTypeId(GetOperandWord(inst, operand_index));
-}
-
-}  // namespace
 
 // Validates correctness of bitwise instructions.
-spv_result_t BitwisePass(ValidationState_t& _,
-                         const spv_parsed_instruction_t* inst) {
-  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
-  const uint32_t result_type = inst->type_id;
+spv_result_t BitwisePass(ValidationState_t& _, const Instruction* inst) {
+  const SpvOp opcode = inst->opcode();
+  const uint32_t result_type = inst->type_id();
 
   switch (opcode) {
     case SpvOpShiftRightLogical:
@@ -61,8 +39,8 @@
                << spvOpcodeString(opcode);
 
       const uint32_t result_dimension = _.GetDimension(result_type);
-      const uint32_t base_type = GetOperandTypeId(_, inst, 2);
-      const uint32_t shift_type = GetOperandTypeId(_, inst, 3);
+      const uint32_t base_type = _.GetOperandTypeId(inst, 2);
+      const uint32_t shift_type = _.GetOperandTypeId(inst, 3);
 
       if (!base_type ||
           (!_.IsIntScalarType(base_type) && !_.IsIntVectorType(base_type)))
@@ -105,9 +83,9 @@
       const uint32_t result_dimension = _.GetDimension(result_type);
       const uint32_t result_bit_width = _.GetBitWidth(result_type);
 
-      for (size_t operand_index = 2; operand_index < inst->num_operands;
+      for (size_t operand_index = 2; operand_index < inst->operands().size();
            ++operand_index) {
-        const uint32_t type_id = GetOperandTypeId(_, inst, operand_index);
+        const uint32_t type_id = _.GetOperandTypeId(inst, operand_index);
         if (!type_id ||
             (!_.IsIntScalarType(type_id) && !_.IsIntVectorType(type_id)))
           return _.diag(SPV_ERROR_INVALID_DATA)
@@ -136,10 +114,10 @@
                << "Expected int scalar or vector type as Result Type: "
                << spvOpcodeString(opcode);
 
-      const uint32_t base_type = GetOperandTypeId(_, inst, 2);
-      const uint32_t insert_type = GetOperandTypeId(_, inst, 3);
-      const uint32_t offset_type = GetOperandTypeId(_, inst, 4);
-      const uint32_t count_type = GetOperandTypeId(_, inst, 5);
+      const uint32_t base_type = _.GetOperandTypeId(inst, 2);
+      const uint32_t insert_type = _.GetOperandTypeId(inst, 3);
+      const uint32_t offset_type = _.GetOperandTypeId(inst, 4);
+      const uint32_t count_type = _.GetOperandTypeId(inst, 5);
 
       if (base_type != result_type)
         return _.diag(SPV_ERROR_INVALID_DATA)
@@ -170,9 +148,9 @@
                << "Expected int scalar or vector type as Result Type: "
                << spvOpcodeString(opcode);
 
-      const uint32_t base_type = GetOperandTypeId(_, inst, 2);
-      const uint32_t offset_type = GetOperandTypeId(_, inst, 3);
-      const uint32_t count_type = GetOperandTypeId(_, inst, 4);
+      const uint32_t base_type = _.GetOperandTypeId(inst, 2);
+      const uint32_t offset_type = _.GetOperandTypeId(inst, 3);
+      const uint32_t count_type = _.GetOperandTypeId(inst, 4);
 
       if (base_type != result_type)
         return _.diag(SPV_ERROR_INVALID_DATA)
@@ -197,7 +175,7 @@
                << "Expected int scalar or vector type as Result Type: "
                << spvOpcodeString(opcode);
 
-      const uint32_t base_type = GetOperandTypeId(_, inst, 2);
+      const uint32_t base_type = _.GetOperandTypeId(inst, 2);
 
       if (base_type != result_type)
         return _.diag(SPV_ERROR_INVALID_DATA)
@@ -212,7 +190,7 @@
                << "Expected int scalar or vector type as Result Type: "
                << spvOpcodeString(opcode);
 
-      const uint32_t base_type = GetOperandTypeId(_, inst, 2);
+      const uint32_t base_type = _.GetOperandTypeId(inst, 2);
       if (!base_type ||
           (!_.IsIntScalarType(base_type) && !_.IsIntVectorType(base_type)))
         return _.diag(SPV_ERROR_INVALID_DATA)
diff --git a/source/validate_cfg.cpp b/source/validate_cfg.cpp
index e09063a..ab3cd95 100644
--- a/source/validate_cfg.cpp
+++ b/source/validate_cfg.cpp
@@ -549,7 +549,7 @@
 }
 
 spv_result_t CfgPass(ValidationState_t& _, const Instruction* inst) {
-  SpvOp opcode = static_cast<SpvOp>(inst->opcode());
+  SpvOp opcode = inst->opcode();
   switch (opcode) {
     case SpvOpLabel:
       if (auto error = _.current_function().RegisterBlock(inst->id()))
diff --git a/source/validate_composites.cpp b/source/validate_composites.cpp
index f4ba74e..ce0a2df 100644
--- a/source/validate_composites.cpp
+++ b/source/validate_composites.cpp
@@ -32,12 +32,12 @@
 // fails (encountered non-composite, out of bounds, nesting too deep).
 // Returns the type of Composite operand if the instruction has no indices.
 spv_result_t GetExtractInsertValueType(ValidationState_t& _,
-                                       const spv_parsed_instruction_t& inst,
+                                       const Instruction* inst,
                                        uint32_t* member_type) {
-  const SpvOp opcode = static_cast<SpvOp>(inst.opcode);
+  const SpvOp opcode = inst->opcode();
   assert(opcode == SpvOpCompositeExtract || opcode == SpvOpCompositeInsert);
   uint32_t word_index = opcode == SpvOpCompositeExtract ? 4 : 5;
-  const uint32_t num_words = static_cast<uint32_t>(inst.num_words);
+  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;
@@ -49,7 +49,7 @@
            << ". Found " << num_indices << " indexes.";
   }
 
-  *member_type = _.GetTypeId(inst.words[composite_id_index]);
+  *member_type = _.GetTypeId(inst->word(composite_id_index));
   if (*member_type == 0) {
     return _.diag(SPV_ERROR_INVALID_DATA)
            << spvOpcodeString(opcode)
@@ -57,7 +57,7 @@
   }
 
   for (; word_index < num_words; ++word_index) {
-    const uint32_t component_index = inst.words[word_index];
+    const uint32_t component_index = inst->word(word_index);
     const Instruction* const type_inst = _.FindDef(*member_type);
     assert(type_inst);
     switch (type_inst->opcode()) {
@@ -136,11 +136,10 @@
 }  // anonymous namespace
 
 // Validates correctness of composite instructions.
-spv_result_t CompositesPass(ValidationState_t& _,
-                            const spv_parsed_instruction_t* inst) {
-  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
-  const uint32_t result_type = inst->type_id;
-  const uint32_t num_operands = static_cast<uint32_t>(inst->num_operands);
+spv_result_t CompositesPass(ValidationState_t& _, const Instruction* inst) {
+  const SpvOp opcode = inst->opcode();
+  const uint32_t result_type = inst->type_id();
+  const uint32_t num_operands = static_cast<uint32_t>(inst->operands().size());
 
   switch (opcode) {
     case SpvOpVectorExtractDynamic: {
@@ -367,7 +366,7 @@
     case SpvOpCompositeExtract: {
       uint32_t member_type = 0;
       if (spv_result_t error =
-              GetExtractInsertValueType(_, *inst, &member_type)) {
+              GetExtractInsertValueType(_, inst, &member_type)) {
         return error;
       }
 
@@ -396,7 +395,7 @@
 
       uint32_t member_type = 0;
       if (spv_result_t error =
-              GetExtractInsertValueType(_, *inst, &member_type)) {
+              GetExtractInsertValueType(_, inst, &member_type)) {
         return error;
       }
 
diff --git a/source/validate_conversion.cpp b/source/validate_conversion.cpp
index a4e75ed..ff2b774 100644
--- a/source/validate_conversion.cpp
+++ b/source/validate_conversion.cpp
@@ -25,10 +25,9 @@
 namespace val {
 
 // Validates correctness of conversion instructions.
-spv_result_t ConversionPass(ValidationState_t& _,
-                            const spv_parsed_instruction_t* inst) {
-  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
-  const uint32_t result_type = inst->type_id;
+spv_result_t ConversionPass(ValidationState_t& _, const Instruction* inst) {
+  const SpvOp opcode = inst->opcode();
+  const uint32_t result_type = inst->type_id();
 
   switch (opcode) {
     case SpvOpConvertFToU: {
@@ -321,7 +320,7 @@
                << "Expected Result Type to be a pointer: "
                << spvOpcodeString(opcode);
 
-      const uint32_t target_storage_class = inst->words[4];
+      const uint32_t target_storage_class = inst->word(4);
       if (result_storage_class != target_storage_class)
         return _.diag(SPV_ERROR_INVALID_DATA)
                << "Expected Result Type to be of target storage class: "
diff --git a/source/validate_datarules.cpp b/source/validate_datarules.cpp
index 59dba8b..7c78318 100644
--- a/source/validate_datarules.cpp
+++ b/source/validate_datarules.cpp
@@ -34,9 +34,9 @@
 // Vector types can only be parameterized as having 2, 3, or 4 components.
 // If the Vector16 capability is added, 8 and 16 components are also allowed.
 spv_result_t ValidateVecNumComponents(ValidationState_t& _,
-                                      const spv_parsed_instruction_t* inst) {
+                                      const Instruction* inst) {
   // Operand 2 specifies the number of components in the vector.
-  const uint32_t num_components = inst->words[inst->operands[2].offset];
+  auto num_components = inst->GetOperandAs<const uint32_t>(2);
   if (num_components == 2 || num_components == 3 || num_components == 4) {
     return SPV_SUCCESS;
   }
@@ -46,12 +46,12 @@
     }
     return _.diag(SPV_ERROR_INVALID_DATA)
            << "Having " << num_components << " components for "
-           << spvOpcodeString(static_cast<SpvOp>(inst->opcode))
+           << spvOpcodeString(inst->opcode())
            << " requires the Vector16 capability";
   }
   return _.diag(SPV_ERROR_INVALID_DATA)
          << "Illegal number of components (" << num_components << ") for "
-         << spvOpcodeString(static_cast<SpvOp>(inst->opcode));
+         << spvOpcodeString(inst->opcode());
 }
 
 // Validates that the number of bits specifed for a float type is valid.
@@ -59,10 +59,9 @@
 // Float16 capability allows using a 16-bit OpTypeFloat.
 // Float16Buffer capability allows creation of a 16-bit OpTypeFloat.
 // Float64 capability allows using a 64-bit OpTypeFloat.
-spv_result_t ValidateFloatSize(ValidationState_t& _,
-                               const spv_parsed_instruction_t* inst) {
+spv_result_t ValidateFloatSize(ValidationState_t& _, const Instruction* inst) {
   // Operand 1 is the number of bits for this float
-  const uint32_t num_bits = inst->words[inst->operands[1].offset];
+  auto num_bits = inst->GetOperandAs<const uint32_t>(1);
   if (num_bits == 32) {
     return SPV_SUCCESS;
   }
@@ -91,10 +90,9 @@
 // Scalar integer types can be parameterized only with 32-bits.
 // Int8, Int16, and Int64 capabilities allow using 8-bit, 16-bit, and 64-bit
 // integers, respectively.
-spv_result_t ValidateIntSize(ValidationState_t& _,
-                             const spv_parsed_instruction_t* inst) {
+spv_result_t ValidateIntSize(ValidationState_t& _, const Instruction* inst) {
   // Operand 1 is the number of bits for this integer.
-  const uint32_t num_bits = inst->words[inst->operands[1].offset];
+  auto num_bits = inst->GetOperandAs<const uint32_t>(1);
   if (num_bits == 32) {
     return SPV_SUCCESS;
   }
@@ -127,10 +125,10 @@
 
 // Validates that the matrix is parameterized with floating-point types.
 spv_result_t ValidateMatrixColumnType(ValidationState_t& _,
-                                      const spv_parsed_instruction_t* inst) {
+                                      const Instruction* inst) {
   // Find the component type of matrix columns (must be vector).
   // Operand 1 is the <id> of the type specified for matrix columns.
-  auto type_id = inst->words[inst->operands[1].offset];
+  auto type_id = inst->GetOperandAs<const uint32_t>(1);
   auto col_type_instr = _.FindDef(type_id);
   if (col_type_instr->opcode() != SpvOpTypeVector) {
     return _.diag(SPV_ERROR_INVALID_ID)
@@ -152,9 +150,9 @@
 
 // Validates that the matrix has 2,3, or 4 columns.
 spv_result_t ValidateMatrixNumCols(ValidationState_t& _,
-                                   const spv_parsed_instruction_t* inst) {
+                                   const Instruction* inst) {
   // Operand 2 is the number of columns in the matrix.
-  const uint32_t num_cols = inst->words[inst->operands[2].offset];
+  auto num_cols = inst->GetOperandAs<const uint32_t>(2);
   if (num_cols != 2 && num_cols != 3 && num_cols != 4) {
     return _.diag(SPV_ERROR_INVALID_DATA) << "Matrix types can only be "
                                              "parameterized as having only 2, "
@@ -165,9 +163,9 @@
 
 // Validates that OpSpecConstant specializes to either int or float type.
 spv_result_t ValidateSpecConstNumerical(ValidationState_t& _,
-                                        const spv_parsed_instruction_t* inst) {
+                                        const Instruction* inst) {
   // Operand 0 is the <id> of the type that we're specializing to.
-  auto type_id = inst->words[inst->operands[0].offset];
+  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) {
@@ -180,9 +178,9 @@
 
 // Validates that OpSpecConstantTrue and OpSpecConstantFalse specialize to bool.
 spv_result_t ValidateSpecConstBoolean(ValidationState_t& _,
-                                      const spv_parsed_instruction_t* inst) {
+                                      const Instruction* inst) {
   // Find out the type that we're specializing to.
-  auto type_instruction = _.FindDef(inst->type_id);
+  auto type_instruction = _.FindDef(inst->type_id());
   if (type_instruction->opcode() != SpvOpTypeBool) {
     return _.diag(SPV_ERROR_INVALID_ID) << "Specialization constant must be "
                                            "a boolean type.";
@@ -192,21 +190,20 @@
 
 // Records the <id> of the forward pointer to be used for validation.
 spv_result_t ValidateForwardPointer(ValidationState_t& _,
-                                    const spv_parsed_instruction_t* inst) {
+                                    const Instruction* inst) {
   // Record the <id> (which is operand 0) to ensure it's used properly.
   // OpTypeStruct can only include undefined pointers that are
   // previously declared as a ForwardPointer
-  return (_.RegisterForwardPointer(inst->words[inst->operands[0].offset]));
+  return (_.RegisterForwardPointer(inst->GetOperandAs<uint32_t>(0)));
 }
 
 // Validates that any undefined component of the struct is a forward pointer.
 // It is valid to declare a forward pointer, and use its <id> as one of the
 // components of a struct.
-spv_result_t ValidateStruct(ValidationState_t& _,
-                            const spv_parsed_instruction_t* inst) {
+spv_result_t ValidateStruct(ValidationState_t& _, const Instruction* inst) {
   // Struct components are operands 1, 2, etc.
-  for (unsigned i = 1; i < inst->num_operands; i++) {
-    auto type_id = inst->words[inst->operands[i].offset];
+  for (unsigned i = 1; i < inst->operands().size(); i++) {
+    auto type_id = inst->GetOperandAs<const uint32_t>(i);
     auto type_instruction = _.FindDef(type_id);
     if (type_instruction == nullptr && !_.IsForwardPointer(type_id)) {
       return _.diag(SPV_ERROR_INVALID_ID)
@@ -221,9 +218,8 @@
 
 // Validates that Data Rules are followed according to the specifications.
 // (Data Rules subsection of 2.16.1 Universal Validation Rules)
-spv_result_t DataRulesPass(ValidationState_t& _,
-                           const spv_parsed_instruction_t* inst) {
-  switch (inst->opcode) {
+spv_result_t DataRulesPass(ValidationState_t& _, const Instruction* inst) {
+  switch (inst->opcode()) {
     case SpvOpTypeVector: {
       if (auto error = ValidateVecNumComponents(_, inst)) return error;
       break;
diff --git a/source/validate_decorations.cpp b/source/validate_decorations.cpp
index 9b320a0..28a6865 100644
--- a/source/validate_decorations.cpp
+++ b/source/validate_decorations.cpp
@@ -408,7 +408,7 @@
     }
     // Check arrays.
     if (SpvOpTypeArray == opcode) {
-      const auto typeId = inst->words()[2];
+      const auto typeId = inst->word(2);
       const auto arrayInst = vstate.FindDef(typeId);
       if (SpvOpTypeStruct == arrayInst->opcode() &&
           SPV_SUCCESS != (recursive_status = checkLayout(
@@ -549,8 +549,7 @@
           return vstate.diag(SPV_ERROR_INVALID_ID)
                  << "Interfaces passed to OpEntryPoint must be of type "
                     "OpTypeVariable. Found Op"
-                 << spvOpcodeString(static_cast<SpvOp>(var_instr->opcode()))
-                 << ".";
+                 << spvOpcodeString(var_instr->opcode()) << ".";
         }
         const uint32_t ptr_id = var_instr->word(1);
         Instruction* ptr_instr = vstate.FindDef(ptr_id);
@@ -622,19 +621,18 @@
     }
     if (!has_descriptor_set) continue;
 
-    const auto& words = inst->words();
-    const auto* ptrInst = vstate.FindDef(words[1]);
+    const auto* ptrInst = vstate.FindDef(inst->word(1));
     assert(SpvOpTypePointer == ptrInst->opcode());
 
     // Check for a first level array
-    const auto typePtr = vstate.FindDef(ptrInst->words()[3]);
+    const auto typePtr = vstate.FindDef(ptrInst->word(3));
     if (SpvOpTypeRuntimeArray != typePtr->opcode() &&
         SpvOpTypeArray != typePtr->opcode()) {
       continue;
     }
 
     // Check for a second level array
-    const auto secondaryTypePtr = vstate.FindDef(typePtr->words()[2]);
+    const auto secondaryTypePtr = vstate.FindDef(typePtr->word(2));
     if (SpvOpTypeRuntimeArray == secondaryTypePtr->opcode() ||
         SpvOpTypeArray == secondaryTypePtr->opcode()) {
       return vstate.diag(SPV_ERROR_INVALID_ID)
diff --git a/source/validate_derivatives.cpp b/source/validate_derivatives.cpp
index 5a794f3..df732fd 100644
--- a/source/validate_derivatives.cpp
+++ b/source/validate_derivatives.cpp
@@ -25,10 +25,9 @@
 namespace val {
 
 // Validates correctness of derivative instructions.
-spv_result_t DerivativesPass(ValidationState_t& _,
-                             const spv_parsed_instruction_t* inst) {
-  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
-  const uint32_t result_type = inst->type_id;
+spv_result_t DerivativesPass(ValidationState_t& _, const Instruction* inst) {
+  const SpvOp opcode = inst->opcode();
+  const uint32_t result_type = inst->type_id();
 
   switch (opcode) {
     case SpvOpDPdx:
diff --git a/source/validate_ext_inst.cpp b/source/validate_ext_inst.cpp
index 85e9dcf..6fb9451 100644
--- a/source/validate_ext_inst.cpp
+++ b/source/validate_ext_inst.cpp
@@ -41,18 +41,17 @@
 }  // anonymous namespace
 
 // Validates correctness of ExtInst instructions.
-spv_result_t ExtInstPass(ValidationState_t& _,
-                         const spv_parsed_instruction_t* inst) {
-  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
-  const uint32_t result_type = inst->type_id;
-  const uint32_t num_operands = inst->num_operands;
+spv_result_t ExtInstPass(ValidationState_t& _, const Instruction* inst) {
+  const SpvOp opcode = inst->opcode();
+  const uint32_t result_type = inst->type_id();
+  const uint32_t num_operands = static_cast<uint32_t>(inst->operands().size());
 
   if (opcode != SpvOpExtInst) return SPV_SUCCESS;
 
-  const uint32_t ext_inst_set = inst->words[3];
-  const uint32_t ext_inst_index = inst->words[4];
+  const uint32_t ext_inst_set = inst->word(3);
+  const uint32_t ext_inst_index = inst->word(4);
   const spv_ext_inst_type_t ext_inst_type =
-      spv_ext_inst_type_t(inst->ext_inst_type);
+      spv_ext_inst_type_t(inst->ext_inst_type());
 
   auto ext_inst_name = [&_, ext_inst_set, ext_inst_type, ext_inst_index]() {
     spv_ext_inst_desc desc = nullptr;
@@ -1530,7 +1529,7 @@
                     "type of Result Type";
         }
 
-        const uint32_t n_value = inst->words[7];
+        const uint32_t n_value = inst->word(7);
         if (num_components != n_value) {
           return _.diag(SPV_ERROR_INVALID_DATA)
                  << ext_inst_name() << ": "
@@ -1716,7 +1715,7 @@
                  << "expected operand P data type to be 16-bit float scalar";
         }
 
-        const uint32_t n_value = inst->words[7];
+        const uint32_t n_value = inst->word(7);
         if (num_components != n_value) {
           return _.diag(SPV_ERROR_INVALID_DATA)
                  << ext_inst_name() << ": "
diff --git a/source/validate_image.cpp b/source/validate_image.cpp
index e4dbe76..c7a5fca 100644
--- a/source/validate_image.cpp
+++ b/source/validate_image.cpp
@@ -199,14 +199,14 @@
 
 // Checks ImageOperand bitfield and respective operands.
 spv_result_t ValidateImageOperands(ValidationState_t& _,
-                                   const spv_parsed_instruction_t& inst,
+                                   const Instruction* inst,
                                    const ImageTypeInfo& info, uint32_t mask,
                                    uint32_t word_index) {
   static const bool kAllImageOperandsHandled = CheckAllImageOperandsHandled();
   (void)kAllImageOperandsHandled;
 
-  const SpvOp opcode = static_cast<SpvOp>(inst.opcode);
-  const uint32_t num_words = inst.num_words;
+  const SpvOp opcode = inst->opcode();
+  const size_t num_words = inst->words().size();
 
   size_t expected_num_image_operand_words = spvtools::utils::CountSetBits(mask);
   if (mask & SpvImageOperandsGradMask) {
@@ -240,7 +240,7 @@
              << spvOpcodeString(opcode);
     };
 
-    const uint32_t type_id = _.GetTypeId(inst.words[word_index++]);
+    const uint32_t type_id = _.GetTypeId(inst->word(word_index++));
     if (!_.IsFloatScalarType(type_id)) {
       return _.diag(SPV_ERROR_INVALID_DATA)
              << "Expected Image Operand Bias to be float scalar: "
@@ -277,7 +277,7 @@
              << spvOpcodeString(opcode);
     }
 
-    const uint32_t type_id = _.GetTypeId(inst.words[word_index++]);
+    const uint32_t type_id = _.GetTypeId(inst->word(word_index++));
     if (is_explicit_lod) {
       if (!_.IsFloatScalarType(type_id)) {
         return _.diag(SPV_ERROR_INVALID_DATA)
@@ -314,8 +314,8 @@
              << spvOpcodeString(opcode);
     };
 
-    const uint32_t dx_type_id = _.GetTypeId(inst.words[word_index++]);
-    const uint32_t dy_type_id = _.GetTypeId(inst.words[word_index++]);
+    const uint32_t dx_type_id = _.GetTypeId(inst->word(word_index++));
+    const uint32_t dy_type_id = _.GetTypeId(inst->word(word_index++));
     if (!_.IsFloatScalarOrVectorType(dx_type_id) ||
         !_.IsFloatScalarOrVectorType(dy_type_id)) {
       return _.diag(SPV_ERROR_INVALID_DATA)
@@ -355,7 +355,7 @@
              << spvOpcodeString(opcode);
     }
 
-    const uint32_t id = inst.words[word_index++];
+    const uint32_t id = inst->word(word_index++);
     const uint32_t type_id = _.GetTypeId(id);
     if (!_.IsIntScalarOrVectorType(type_id)) {
       return _.diag(SPV_ERROR_INVALID_DATA)
@@ -386,7 +386,7 @@
              << spvOpcodeString(opcode);
     }
 
-    const uint32_t id = inst.words[word_index++];
+    const uint32_t id = inst->word(word_index++);
     const uint32_t type_id = _.GetTypeId(id);
     if (!_.IsIntScalarOrVectorType(type_id)) {
       return _.diag(SPV_ERROR_INVALID_DATA)
@@ -421,7 +421,7 @@
              << spvOpcodeString(opcode);
     }
 
-    const uint32_t id = inst.words[word_index++];
+    const uint32_t id = inst->word(word_index++);
     const uint32_t type_id = _.GetTypeId(id);
     const Instruction* type_inst = _.FindDef(type_id);
     assert(type_inst);
@@ -475,7 +475,7 @@
              << spvOpcodeString(opcode);
     }
 
-    const uint32_t type_id = _.GetTypeId(inst.words[word_index++]);
+    const uint32_t type_id = _.GetTypeId(inst->word(word_index++));
     if (!_.IsIntScalarType(type_id)) {
       return _.diag(SPV_ERROR_INVALID_DATA)
              << "Expected Image Operand Sample to be int scalar: "
@@ -491,7 +491,7 @@
              << spvOpcodeString(opcode);
     };
 
-    const uint32_t type_id = _.GetTypeId(inst.words[word_index++]);
+    const uint32_t type_id = _.GetTypeId(inst->word(word_index++));
     if (!_.IsFloatScalarType(type_id)) {
       return _.diag(SPV_ERROR_INVALID_DATA)
              << "Expected Image Operand MinLod to be float scalar: "
@@ -517,10 +517,9 @@
 }
 
 // Checks some of the validation rules which are common to multiple opcodes.
-spv_result_t ValidateImageCommon(ValidationState_t& _,
-                                 const spv_parsed_instruction_t& inst,
+spv_result_t ValidateImageCommon(ValidationState_t& _, const Instruction* inst,
                                  const ImageTypeInfo& info) {
-  const SpvOp opcode = static_cast<SpvOp>(inst.opcode);
+  const SpvOp opcode = inst->opcode();
   if (IsProj(opcode)) {
     if (info.dim != SpvDim1D && info.dim != SpvDim2D && info.dim != SpvDim3D &&
         info.dim != SpvDimRect) {
@@ -616,13 +615,12 @@
 // Checks sparse image opcode result type and returns the second struct member.
 // Returns inst.type_id for non-sparse image opcodes.
 // Not valid for sparse image opcodes which do not return a struct.
-spv_result_t GetActualResultType(ValidationState_t& _,
-                                 const spv_parsed_instruction_t& inst,
+spv_result_t GetActualResultType(ValidationState_t& _, const Instruction* inst,
                                  uint32_t* actual_result_type) {
-  const SpvOp opcode = static_cast<SpvOp>(inst.opcode);
+  const SpvOp opcode = inst->opcode();
 
   if (IsSparse(opcode)) {
-    const Instruction* const type_inst = _.FindDef(inst.type_id);
+    const Instruction* const type_inst = _.FindDef(inst->type_id());
     assert(type_inst);
 
     if (!type_inst || type_inst->opcode() != SpvOpTypeStruct) {
@@ -642,7 +640,7 @@
 
     *actual_result_type = type_inst->word(3);
   } else {
-    *actual_result_type = inst.type_id;
+    *actual_result_type = inst->type_id();
   }
 
   return SPV_SUCCESS;
@@ -658,10 +656,9 @@
 }  // namespace
 
 // Validates correctness of image instructions.
-spv_result_t ImagePass(ValidationState_t& _,
-                       const spv_parsed_instruction_t* inst) {
-  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
-  const uint32_t result_type = inst->type_id;
+spv_result_t ImagePass(ValidationState_t& _, const Instruction* inst) {
+  const SpvOp opcode = inst->opcode();
+  const uint32_t result_type = inst->type_id();
 
   if (IsImplicitLod(opcode)) {
     _.current_function().RegisterExecutionModelLimitation(
@@ -674,7 +671,7 @@
       assert(result_type == 0);
 
       ImageTypeInfo info;
-      if (!GetImageTypeInfo(_, inst->words[1], &info)) {
+      if (!GetImageTypeInfo(_, inst->word(1), &info)) {
         return _.diag(SPV_ERROR_INVALID_DATA)
                << "OpTypeImage: corrupt definition";
       }
@@ -746,7 +743,7 @@
     }
 
     case SpvOpTypeSampledImage: {
-      const uint32_t image_type = inst->words[2];
+      const uint32_t image_type = inst->word(2);
       if (_.GetIdOpcode(image_type) != SpvOpTypeImage) {
         return _.diag(SPV_ERROR_INVALID_DATA)
                << spvOpcodeString(opcode)
@@ -817,7 +814,7 @@
     case SpvOpImageSparseSampleExplicitLod: {
       uint32_t actual_result_type = 0;
       if (spv_result_t error =
-              GetActualResultType(_, *inst, &actual_result_type)) {
+              GetActualResultType(_, inst, &actual_result_type)) {
         return error;
       }
 
@@ -848,7 +845,7 @@
                << "Corrupt image type definition";
       }
 
-      if (spv_result_t result = ValidateImageCommon(_, *inst, info))
+      if (spv_result_t result = ValidateImageCommon(_, inst, info))
         return result;
 
       if (_.GetIdOpcode(info.sampled_type) != SpvOpTypeVoid) {
@@ -889,14 +886,14 @@
                << spvOpcodeString(opcode);
       }
 
-      if (inst->num_words <= 5) {
+      if (inst->words().size() <= 5) {
         assert(IsImplicitLod(opcode));
         break;
       }
 
-      const uint32_t mask = inst->words[5];
+      const uint32_t mask = inst->word(5);
       if (spv_result_t result =
-              ValidateImageOperands(_, *inst, info, mask, /* word_index = */ 6))
+              ValidateImageOperands(_, inst, info, mask, /* word_index = */ 6))
         return result;
 
       break;
@@ -910,7 +907,7 @@
     case SpvOpImageSparseSampleDrefExplicitLod: {
       uint32_t actual_result_type = 0;
       if (spv_result_t error =
-              GetActualResultType(_, *inst, &actual_result_type)) {
+              GetActualResultType(_, inst, &actual_result_type)) {
         return error;
       }
 
@@ -935,7 +932,7 @@
                << "Corrupt image type definition";
       }
 
-      if (spv_result_t result = ValidateImageCommon(_, *inst, info))
+      if (spv_result_t result = ValidateImageCommon(_, inst, info))
         return result;
 
       if (actual_result_type != info.sampled_type) {
@@ -968,14 +965,14 @@
                << ": Expected Dref to be of 32-bit float type";
       }
 
-      if (inst->num_words <= 6) {
+      if (inst->words().size() <= 6) {
         assert(IsImplicitLod(opcode));
         break;
       }
 
-      const uint32_t mask = inst->words[6];
+      const uint32_t mask = inst->word(6);
       if (spv_result_t result =
-              ValidateImageOperands(_, *inst, info, mask, /* word_index = */ 7))
+              ValidateImageOperands(_, inst, info, mask, /* word_index = */ 7))
         return result;
 
       break;
@@ -985,7 +982,7 @@
     case SpvOpImageSparseFetch: {
       uint32_t actual_result_type = 0;
       if (spv_result_t error =
-              GetActualResultType(_, *inst, &actual_result_type)) {
+              GetActualResultType(_, inst, &actual_result_type)) {
         return error;
       }
 
@@ -1054,11 +1051,11 @@
                << spvOpcodeString(opcode);
       }
 
-      if (inst->num_words <= 5) break;
+      if (inst->words().size() <= 5) break;
 
-      const uint32_t mask = inst->words[5];
+      const uint32_t mask = inst->word(5);
       if (spv_result_t result =
-              ValidateImageOperands(_, *inst, info, mask, /* word_index = */ 6))
+              ValidateImageOperands(_, inst, info, mask, /* word_index = */ 6))
         return result;
 
       break;
@@ -1070,7 +1067,7 @@
     case SpvOpImageSparseDrefGather: {
       uint32_t actual_result_type = 0;
       if (spv_result_t error =
-              GetActualResultType(_, *inst, &actual_result_type)) {
+              GetActualResultType(_, inst, &actual_result_type)) {
         return error;
       }
 
@@ -1156,11 +1153,11 @@
         }
       }
 
-      if (inst->num_words <= 6) break;
+      if (inst->words().size() <= 6) break;
 
-      const uint32_t mask = inst->words[6];
+      const uint32_t mask = inst->word(6);
       if (spv_result_t result =
-              ValidateImageOperands(_, *inst, info, mask, /* word_index = */ 7))
+              ValidateImageOperands(_, inst, info, mask, /* word_index = */ 7))
         return result;
 
       break;
@@ -1170,7 +1167,7 @@
     case SpvOpImageSparseRead: {
       uint32_t actual_result_type = 0;
       if (spv_result_t error =
-              GetActualResultType(_, *inst, &actual_result_type)) {
+              GetActualResultType(_, inst, &actual_result_type)) {
         return error;
       }
 
@@ -1228,7 +1225,7 @@
         }
       }
 
-      if (spv_result_t result = ValidateImageCommon(_, *inst, info))
+      if (spv_result_t result = ValidateImageCommon(_, inst, info))
         return result;
 
       const uint32_t coord_type = _.GetOperandTypeId(inst, 3);
@@ -1255,11 +1252,11 @@
                << "read storage image: " << spvOpcodeString(opcode);
       }
 
-      if (inst->num_words <= 5) break;
+      if (inst->words().size() <= 5) break;
 
-      const uint32_t mask = inst->words[5];
+      const uint32_t mask = inst->word(5);
       if (spv_result_t result =
-              ValidateImageOperands(_, *inst, info, mask, /* word_index = */ 6))
+              ValidateImageOperands(_, inst, info, mask, /* word_index = */ 6))
         return result;
 
       break;
@@ -1285,7 +1282,7 @@
                << spvOpcodeString(opcode);
       }
 
-      if (spv_result_t result = ValidateImageCommon(_, *inst, info))
+      if (spv_result_t result = ValidateImageCommon(_, inst, info))
         return result;
 
       const uint32_t coord_type = _.GetOperandTypeId(inst, 1);
@@ -1341,11 +1338,11 @@
                << "to storage image: " << spvOpcodeString(opcode);
       }
 
-      if (inst->num_words <= 4) break;
+      if (inst->words().size() <= 4) break;
 
-      const uint32_t mask = inst->words[4];
+      const uint32_t mask = inst->word(4);
       if (spv_result_t result =
-              ValidateImageOperands(_, *inst, info, mask, /* word_index = */ 5))
+              ValidateImageOperands(_, inst, info, mask, /* word_index = */ 5))
         return result;
 
       break;
diff --git a/source/validate_instruction.cpp b/source/validate_instruction.cpp
index 605ae3c..b71d6ba 100644
--- a/source/validate_instruction.cpp
+++ b/source/validate_instruction.cpp
@@ -57,7 +57,7 @@
 
 // Reports a missing-capability error to _'s diagnostic stream and returns
 // SPV_ERROR_INVALID_CAPABILITY.
-spv_result_t CapabilityError(const ValidationState_t& _, int which_operand,
+spv_result_t CapabilityError(const ValidationState_t& _, size_t which_operand,
                              SpvOp opcode,
                              const std::string& required_capabilities) {
   return _.diag(SPV_ERROR_INVALID_CAPABILITY)
@@ -100,7 +100,7 @@
 // in the module.  Otherwise issues an error message and returns
 // SPV_ERROR_INVALID_CAPABILITY.
 spv_result_t CheckRequiredCapabilities(const ValidationState_t& state,
-                                       SpvOp opcode, int which_operand,
+                                       SpvOp opcode, size_t which_operand,
                                        spv_operand_type_t type,
                                        uint32_t operand) {
   // Mere mention of PointSize, ClipDistance, or CullDistance in a Builtin
@@ -181,9 +181,8 @@
 // Returns SPV_ERROR_INVALID_BINARY and emits a diagnostic if the instruction
 // is explicitly reserved in the SPIR-V core spec.  Otherwise return
 // SPV_SUCCESS.
-spv_result_t ReservedCheck(ValidationState_t& _,
-                           const spv_parsed_instruction_t* inst) {
-  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
+spv_result_t ReservedCheck(ValidationState_t& _, const Instruction* inst) {
+  const SpvOp opcode = inst->opcode();
   switch (opcode) {
     // These instructions are enabled by a capability, but should never
     // be used anyway.
@@ -204,9 +203,8 @@
 
 // Returns SPV_ERROR_INVALID_BINARY and emits a diagnostic if the instruction
 // is invalid because of an execution environment constraint.
-spv_result_t EnvironmentCheck(ValidationState_t& _,
-                              const spv_parsed_instruction_t* inst) {
-  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
+spv_result_t EnvironmentCheck(ValidationState_t& _, const Instruction* inst) {
+  const SpvOp opcode = inst->opcode();
   switch (opcode) {
     case SpvOpUndef:
       if (_.features().bans_op_undef) {
@@ -222,9 +220,8 @@
 // Returns SPV_ERROR_INVALID_CAPABILITY and emits a diagnostic if the
 // instruction is invalid because the required capability isn't declared
 // in the module.
-spv_result_t CapabilityCheck(ValidationState_t& _,
-                             const spv_parsed_instruction_t* inst) {
-  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
+spv_result_t CapabilityCheck(ValidationState_t& _, const Instruction* inst) {
+  const SpvOp opcode = inst->opcode();
   CapabilitySet opcode_caps = EnablingCapabilitiesForOp(_, opcode);
   if (!_.HasAnyOfCapabilities(opcode_caps)) {
     return _.diag(SPV_ERROR_INVALID_CAPABILITY)
@@ -232,9 +229,9 @@
            << " requires one of these capabilities: "
            << ToString(opcode_caps, _.grammar());
   }
-  for (int i = 0; i < inst->num_operands; ++i) {
-    const auto& operand = inst->operands[i];
-    const auto word = inst->words[operand.offset];
+  for (size_t i = 0; i < inst->operands().size(); ++i) {
+    const auto& operand = inst->operand(i);
+    const auto word = inst->word(operand.offset);
     if (spvOperandIsConcreteMask(operand.type)) {
       // Check for required capabilities for each bit position of the mask.
       for (uint32_t mask_bit = 0x80000000; mask_bit; mask_bit >>= 1) {
@@ -260,13 +257,12 @@
 
 // Checks that all extensions required by the given instruction's operands were
 // declared in the module.
-spv_result_t ExtensionCheck(ValidationState_t& _,
-                            const spv_parsed_instruction_t* inst) {
-  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
-  for (size_t operand_index = 0; operand_index < inst->num_operands;
+spv_result_t ExtensionCheck(ValidationState_t& _, const Instruction* inst) {
+  const SpvOp opcode = inst->opcode();
+  for (size_t operand_index = 0; operand_index < inst->operands().size();
        ++operand_index) {
-    const auto& operand = inst->operands[operand_index];
-    const uint32_t word = inst->words[operand.offset];
+    const auto& operand = inst->operand(operand_index);
+    const uint32_t word = inst->word(operand.offset);
     const ExtensionSet required_extensions =
         RequiredExtensions(_, operand.type, word);
     if (!_.HasAnyOfExtensions(required_extensions)) {
@@ -283,9 +279,8 @@
 // Checks that the instruction can be used in this target environment's base
 // version. Assumes that CapabilityCheck has checked direct capability
 // dependencies for the opcode.
-spv_result_t VersionCheck(ValidationState_t& _,
-                          const spv_parsed_instruction_t* inst) {
-  const auto opcode = static_cast<SpvOp>(inst->opcode);
+spv_result_t VersionCheck(ValidationState_t& _, const Instruction* inst) {
+  const auto opcode = inst->opcode();
   spv_opcode_desc inst_desc;
   const bool r = _.grammar().lookupOpcode(opcode, &inst_desc);
   assert(r == SPV_SUCCESS);
@@ -339,20 +334,18 @@
 }
 
 // Checks that the Resuld <id> is within the valid bound.
-spv_result_t LimitCheckIdBound(ValidationState_t& _,
-                               const spv_parsed_instruction_t* inst) {
-  if (inst->result_id >= _.getIdBound()) {
+spv_result_t LimitCheckIdBound(ValidationState_t& _, const Instruction* inst) {
+  if (inst->id() >= _.getIdBound()) {
     return _.diag(SPV_ERROR_INVALID_BINARY)
-           << "Result <id> '" << inst->result_id
+           << "Result <id> '" << inst->id()
            << "' must be less than the ID bound '" << _.getIdBound() << "'.";
   }
   return SPV_SUCCESS;
 }
 
 // Checks that the number of OpTypeStruct members is within the limit.
-spv_result_t LimitCheckStruct(ValidationState_t& _,
-                              const spv_parsed_instruction_t* inst) {
-  if (SpvOpTypeStruct != inst->opcode) {
+spv_result_t LimitCheckStruct(ValidationState_t& _, const Instruction* inst) {
+  if (SpvOpTypeStruct != inst->opcode()) {
     return SPV_SUCCESS;
   }
 
@@ -360,9 +353,9 @@
   // One operand is the result ID.
   const uint16_t limit =
       static_cast<uint16_t>(_.options()->universal_limits_.max_struct_members);
-  if (inst->num_operands - 1 > limit) {
+  if (inst->operands().size() - 1 > limit) {
     return _.diag(SPV_ERROR_INVALID_BINARY)
-           << "Number of OpTypeStruct members (" << inst->num_operands - 1
+           << "Number of OpTypeStruct members (" << inst->operands().size() - 1
            << ") has exceeded the limit (" << limit << ").";
   }
 
@@ -375,8 +368,8 @@
   // Scalars are at depth 0.
   uint32_t max_member_depth = 0;
   // Struct members start at word 2 of OpTypeStruct instruction.
-  for (size_t word_i = 2; word_i < inst->num_words; ++word_i) {
-    auto member = inst->words[word_i];
+  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()) {
       max_member_depth = std::max(
@@ -386,7 +379,7 @@
 
   const uint32_t depth_limit = _.options()->universal_limits_.max_struct_depth;
   const uint32_t cur_depth = 1 + max_member_depth;
-  _.set_struct_nesting_depth(inst->result_id, cur_depth);
+  _.set_struct_nesting_depth(inst->id(), cur_depth);
   if (cur_depth > depth_limit) {
     return _.diag(SPV_ERROR_INVALID_BINARY)
            << "Structure Nesting Depth may not be larger than " << depth_limit
@@ -397,14 +390,13 @@
 
 // Checks that the number of (literal, label) pairs in OpSwitch is within the
 // limit.
-spv_result_t LimitCheckSwitch(ValidationState_t& _,
-                              const spv_parsed_instruction_t* inst) {
-  if (SpvOpSwitch == inst->opcode) {
+spv_result_t LimitCheckSwitch(ValidationState_t& _, const Instruction* inst) {
+  if (SpvOpSwitch == 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.
     // It is guaranteed at this point that num_operands is an even numner.
-    unsigned int num_pairs = (inst->num_operands - 2) / 2;
+    size_t num_pairs = (inst->operands().size() - 2) / 2;
     const unsigned int num_pairs_limit =
         _.options()->universal_limits_.max_switch_branches;
     if (num_pairs > num_pairs_limit) {
@@ -446,27 +438,27 @@
 // Registers necessary decoration(s) for the appropriate IDs based on the
 // instruction.
 spv_result_t RegisterDecorations(ValidationState_t& _,
-                                 const spv_parsed_instruction_t* inst) {
-  switch (inst->opcode) {
+                                 const Instruction* inst) {
+  switch (inst->opcode()) {
     case SpvOpDecorate: {
-      const uint32_t target_id = inst->words[1];
-      const SpvDecoration dec_type = static_cast<SpvDecoration>(inst->words[2]);
+      const uint32_t target_id = inst->word(1);
+      const SpvDecoration dec_type = static_cast<SpvDecoration>(inst->word(2));
       std::vector<uint32_t> dec_params;
-      if (inst->num_words > 3) {
-        dec_params.insert(dec_params.end(), inst->words + 3,
-                          inst->words + inst->num_words);
+      if (inst->words().size() > 3) {
+        dec_params.insert(dec_params.end(), inst->words().begin() + 3,
+                          inst->words().end());
       }
       _.RegisterDecorationForId(target_id, Decoration(dec_type, dec_params));
       break;
     }
     case SpvOpMemberDecorate: {
-      const uint32_t struct_id = inst->words[1];
-      const uint32_t index = inst->words[2];
-      const SpvDecoration dec_type = static_cast<SpvDecoration>(inst->words[3]);
+      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));
       std::vector<uint32_t> dec_params;
-      if (inst->num_words > 4) {
-        dec_params.insert(dec_params.end(), inst->words + 4,
-                          inst->words + inst->num_words);
+      if (inst->words().size() > 4) {
+        dec_params.insert(dec_params.end(), inst->words().begin() + 4,
+                          inst->words().end());
       }
       _.RegisterDecorationForId(struct_id,
                                 Decoration(dec_type, dec_params, index));
@@ -480,11 +472,11 @@
     case SpvOpGroupDecorate: {
       // 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->words[1];
+      const uint32_t decoration_group_id = inst->word(1);
       std::vector<Decoration>& group_decorations =
           _.id_decorations(decoration_group_id);
-      for (int i = 2; i < inst->num_words; ++i) {
-        const uint32_t target_id = inst->words[i];
+      for (size_t i = 2; i < inst->words().size(); ++i) {
+        const uint32_t target_id = inst->word(i);
         _.RegisterDecorationsForId(target_id, group_decorations.begin(),
                                    group_decorations.end());
       }
@@ -494,14 +486,14 @@
       // 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.
-      const uint32_t decoration_group_id = inst->words[1];
+      const uint32_t decoration_group_id = inst->word(1);
       std::vector<Decoration>& group_decorations =
           _.id_decorations(decoration_group_id);
       // Grammar checks ensures that the number of arguments to this instruction
       // is an odd number: 1 decoration group + (id,literal) pairs.
-      for (int i = 2; i + 1 < inst->num_words; i = i + 2) {
-        const uint32_t struct_id = inst->words[i];
-        const uint32_t index = inst->words[i + 1];
+      for (size_t i = 2; i + 1 < inst->words().size(); i = i + 2) {
+        const uint32_t struct_id = inst->word(i);
+        const uint32_t index = inst->word(i + 1);
         // ID validation phase ensures this is in fact a struct instruction and
         // that the index is not out of bound.
         _.RegisterDecorationsForStructMember(struct_id, index,
@@ -517,9 +509,8 @@
 }
 
 // Parses OpExtension instruction and logs warnings if unsuccessful.
-void CheckIfKnownExtension(ValidationState_t& _,
-                           const spv_parsed_instruction_t* inst) {
-  const std::string extension_str = GetExtensionString(inst);
+void CheckIfKnownExtension(ValidationState_t& _, const Instruction* inst) {
+  const std::string extension_str = GetExtensionString(&(inst->c_inst()));
   Extension extension;
   if (!GetExtensionFromString(extension_str.c_str(), &extension)) {
     _.diag(SPV_SUCCESS) << "Found unrecognized extension " << extension_str;
@@ -529,31 +520,26 @@
 
 }  // namespace
 
-spv_result_t InstructionPass(ValidationState_t& _,
-                             const spv_parsed_instruction_t* inst) {
-  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
+spv_result_t InstructionPass(ValidationState_t& _, const Instruction* inst) {
+  const SpvOp opcode = inst->opcode();
   if (opcode == SpvOpExtension) {
     CheckIfKnownExtension(_, inst);
   } else if (opcode == SpvOpCapability) {
-    _.RegisterCapability(
-        static_cast<SpvCapability>(inst->words[inst->operands[0].offset]));
+    _.RegisterCapability(inst->GetOperandAs<SpvCapability>(0));
   } else if (opcode == SpvOpMemoryModel) {
     if (_.has_memory_model_specified()) {
       return _.diag(SPV_ERROR_INVALID_LAYOUT)
              << "OpMemoryModel should only be provided once.";
     }
-    _.set_addressing_model(
-        static_cast<SpvAddressingModel>(inst->words[inst->operands[0].offset]));
-    _.set_memory_model(
-        static_cast<SpvMemoryModel>(inst->words[inst->operands[1].offset]));
+    _.set_addressing_model(inst->GetOperandAs<SpvAddressingModel>(0));
+    _.set_memory_model(inst->GetOperandAs<SpvMemoryModel>(1));
   } else if (opcode == SpvOpExecutionMode) {
-    const uint32_t entry_point = inst->words[1];
+    const uint32_t entry_point = inst->word(1);
     _.RegisterExecutionModeForEntryPoint(entry_point,
-                                         SpvExecutionMode(inst->words[2]));
+                                         SpvExecutionMode(inst->word(2)));
   } else if (opcode == SpvOpVariable) {
-    const auto storage_class =
-        static_cast<SpvStorageClass>(inst->words[inst->operands[2].offset]);
-    if (auto error = LimitCheckNumVars(_, inst->result_id, storage_class)) {
+    const auto storage_class = inst->GetOperandAs<SpvStorageClass>(2);
+    if (auto error = LimitCheckNumVars(_, inst->id(), storage_class)) {
       return error;
     }
     if (storage_class == SpvStorageClassGeneric)
@@ -582,8 +568,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) &&
-      inst->words[inst->operands[2].offset] != 0u) {
+  if (SpvOpTypeInt == inst->opcode() && _.HasCapability(SpvCapabilityKernel) &&
+      inst->GetOperandAs<uint32_t>(2) != 0u) {
     return _.diag(SPV_ERROR_INVALID_BINARY) << "The Signedness in OpTypeInt "
                                                "must always be 0 when Kernel "
                                                "capability is used.";
diff --git a/source/validate_layout.cpp b/source/validate_layout.cpp
index 287a49e..e45d4d4 100644
--- a/source/validate_layout.cpp
+++ b/source/validate_layout.cpp
@@ -23,6 +23,7 @@
 #include "operand.h"
 #include "spirv-tools/libspirv.h"
 #include "val/function.h"
+#include "val/instruction.h"
 #include "val/validation_state.h"
 
 namespace spvtools {
@@ -33,8 +34,7 @@
 // is part of the current layout section. If it is not then the next sections is
 // checked.
 spv_result_t ModuleScopedInstructions(ValidationState_t& _,
-                                      const spv_parsed_instruction_t* inst,
-                                      SpvOp opcode) {
+                                      const Instruction* inst, SpvOp opcode) {
   while (_.IsOpcodeInCurrentLayoutSection(opcode) == false) {
     _.ProgressToNextLayoutSectionOrder();
 
@@ -63,8 +63,7 @@
 // inside of another function. This stage ends when the first label is
 // encountered inside of a function.
 spv_result_t FunctionScopedInstructions(ValidationState_t& _,
-                                        const spv_parsed_instruction_t* inst,
-                                        SpvOp opcode) {
+                                        const Instruction* inst, SpvOp opcode) {
   if (_.IsOpcodeInCurrentLayoutSection(opcode)) {
     switch (opcode) {
       case SpvOpFunction: {
@@ -72,11 +71,10 @@
           return _.diag(SPV_ERROR_INVALID_LAYOUT)
                  << "Cannot declare a function in a function body";
         }
-        auto control_mask = static_cast<SpvFunctionControlMask>(
-            inst->words[inst->operands[2].offset]);
+        auto control_mask = inst->GetOperandAs<SpvFunctionControlMask>(2);
         if (auto error =
-                _.RegisterFunction(inst->result_id, inst->type_id, control_mask,
-                                   inst->words[inst->operands[3].offset]))
+                _.RegisterFunction(inst->id(), inst->type_id(), control_mask,
+                                   inst->GetOperandAs<uint32_t>(3)))
           return error;
         if (_.current_layout_section() == kLayoutFunctionDefinitions) {
           if (auto error = _.current_function().RegisterSetFunctionDeclType(
@@ -97,7 +95,7 @@
                     "the function definition";
         }
         if (auto error = _.current_function().RegisterFunctionParameter(
-                inst->result_id, inst->type_id))
+                inst->id(), inst->type_id()))
           return error;
         break;
 
@@ -174,9 +172,8 @@
 // TODO(umar): Better error messages
 // NOTE: This function does not handle CFG related validation
 // Performs logical layout validation. See Section 2.4
-spv_result_t ModuleLayoutPass(ValidationState_t& _,
-                              const spv_parsed_instruction_t* inst) {
-  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
+spv_result_t ModuleLayoutPass(ValidationState_t& _, const Instruction* inst) {
+  const SpvOp opcode = inst->opcode();
 
   switch (_.current_layout_section()) {
     case kLayoutCapabilities:
diff --git a/source/validate_literals.cpp b/source/validate_literals.cpp
index 3f8e55e..76ef467 100644
--- a/source/validate_literals.cpp
+++ b/source/validate_literals.cpp
@@ -28,8 +28,8 @@
 namespace {
 
 // Returns true if the operand holds a literal number
-bool IsLiteralNumber(const spv_parsed_operand_t* operand) {
-  switch (operand->number_kind) {
+bool IsLiteralNumber(const spv_parsed_operand_t& operand) {
+  switch (operand.number_kind) {
     case SPV_NUMBER_SIGNED_INT:
     case SPV_NUMBER_UNSIGNED_INT:
     case SPV_NUMBER_FLOATING:
@@ -64,31 +64,30 @@
 }  // namespace
 
 // Validates that literal numbers are represented according to the spec
-spv_result_t LiteralsPass(ValidationState_t& _,
-                          const spv_parsed_instruction_t* inst) {
+spv_result_t LiteralsPass(ValidationState_t& _, const Instruction* inst) {
   // For every operand that is a literal number
-  for (uint16_t i = 0; i < inst->num_operands; i++) {
-    const spv_parsed_operand_t* operand = inst->operands + i;
+  for (size_t i = 0; i < inst->operands().size(); i++) {
+    const spv_parsed_operand_t& operand = inst->operand(i);
     if (!IsLiteralNumber(operand)) continue;
 
     // The upper bits are always in the last word (little-endian)
-    int last_index = operand->offset + operand->num_words - 1;
-    const uint32_t upper_word = inst->words[last_index];
+    int last_index = operand.offset + operand.num_words - 1;
+    const uint32_t upper_word = inst->word(last_index);
 
     // TODO(jcaraban): is the |word size| defined in some header?
     const uint32_t word_size = 32;
-    uint32_t bit_width = operand->number_bit_width;
+    uint32_t bit_width = operand.number_bit_width;
 
     // Bit widths that are a multiple of the word size have no upper bits
     const auto remaining_value_bits = bit_width % word_size;
     if (remaining_value_bits == 0) continue;
 
-    const bool signedness = operand->number_kind == SPV_NUMBER_SIGNED_INT;
+    const bool signedness = operand.number_kind == SPV_NUMBER_SIGNED_INT;
 
     if (!VerifyUpperBits(upper_word, remaining_value_bits, signedness)) {
       return _.diag(SPV_ERROR_INVALID_VALUE)
              << "The high-order bits of a literal number in instruction <id> "
-             << inst->result_id << " must be 0 for a floating-point type, "
+             << inst->id() << " must be 0 for a floating-point type, "
              << "or 0 for an integer type with Signedness of 0, "
              << "or sign extended when Signedness is 1";
     }
diff --git a/source/validate_logicals.cpp b/source/validate_logicals.cpp
index a893d3f..7239968 100644
--- a/source/validate_logicals.cpp
+++ b/source/validate_logicals.cpp
@@ -23,32 +23,11 @@
 
 namespace spvtools {
 namespace val {
-namespace {
-
-// Returns operand word for given instruction and operand index.
-// The operand is expected to only have one word.
-inline uint32_t GetOperandWord(const spv_parsed_instruction_t* inst,
-                               size_t operand_index) {
-  assert(operand_index < inst->num_operands);
-  const spv_parsed_operand_t& operand = inst->operands[operand_index];
-  assert(operand.num_words == 1);
-  return inst->words[operand.offset];
-}
-
-// Returns the type id of instruction operand at |operand_index|.
-// The operand is expected to be an id.
-inline uint32_t GetOperandTypeId(ValidationState_t& _,
-                                 const spv_parsed_instruction_t* inst,
-                                 size_t operand_index) {
-  return _.GetTypeId(GetOperandWord(inst, operand_index));
-}
-}  // namespace
 
 // Validates correctness of logical instructions.
-spv_result_t LogicalsPass(ValidationState_t& _,
-                          const spv_parsed_instruction_t* inst) {
-  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
-  const uint32_t result_type = inst->type_id;
+spv_result_t LogicalsPass(ValidationState_t& _, const Instruction* inst) {
+  const SpvOp opcode = inst->opcode();
+  const uint32_t result_type = inst->type_id();
 
   switch (opcode) {
     case SpvOpAny:
@@ -58,7 +37,7 @@
                << "Expected bool scalar type as Result Type: "
                << spvOpcodeString(opcode);
 
-      const uint32_t vector_type = GetOperandTypeId(_, inst, 2);
+      const uint32_t vector_type = _.GetOperandTypeId(inst, 2);
       if (!vector_type || !_.IsBoolVectorType(vector_type))
         return _.diag(SPV_ERROR_INVALID_DATA)
                << "Expected operand to be vector bool: "
@@ -77,7 +56,7 @@
                << "Expected bool scalar or vector type as Result Type: "
                << spvOpcodeString(opcode);
 
-      const uint32_t operand_type = GetOperandTypeId(_, inst, 2);
+      const uint32_t operand_type = _.GetOperandTypeId(inst, 2);
       if (!operand_type || (!_.IsFloatScalarType(operand_type) &&
                             !_.IsFloatVectorType(operand_type)))
         return _.diag(SPV_ERROR_INVALID_DATA)
@@ -113,7 +92,7 @@
                << "Expected bool scalar or vector type as Result Type: "
                << spvOpcodeString(opcode);
 
-      const uint32_t left_operand_type = GetOperandTypeId(_, inst, 2);
+      const uint32_t left_operand_type = _.GetOperandTypeId(inst, 2);
       if (!left_operand_type || (!_.IsFloatScalarType(left_operand_type) &&
                                  !_.IsFloatVectorType(left_operand_type)))
         return _.diag(SPV_ERROR_INVALID_DATA)
@@ -126,7 +105,7 @@
                   "equal: "
                << spvOpcodeString(opcode);
 
-      if (left_operand_type != GetOperandTypeId(_, inst, 3))
+      if (left_operand_type != _.GetOperandTypeId(inst, 3))
         return _.diag(SPV_ERROR_INVALID_DATA)
                << "Expected left and right operands to have the same type: "
                << spvOpcodeString(opcode);
@@ -143,8 +122,8 @@
                << "Expected bool scalar or vector type as Result Type: "
                << spvOpcodeString(opcode);
 
-      if (result_type != GetOperandTypeId(_, inst, 2) ||
-          result_type != GetOperandTypeId(_, inst, 3))
+      if (result_type != _.GetOperandTypeId(inst, 2) ||
+          result_type != _.GetOperandTypeId(inst, 3))
         return _.diag(SPV_ERROR_INVALID_DATA)
                << "Expected both operands to be of Result Type: "
                << spvOpcodeString(opcode);
@@ -158,7 +137,7 @@
                << "Expected bool scalar or vector type as Result Type: "
                << spvOpcodeString(opcode);
 
-      if (result_type != GetOperandTypeId(_, inst, 2))
+      if (result_type != _.GetOperandTypeId(inst, 2))
         return _.diag(SPV_ERROR_INVALID_DATA)
                << "Expected operand to be of Result Type: "
                << spvOpcodeString(opcode);
@@ -202,9 +181,9 @@
         }
       }
 
-      const uint32_t condition_type = GetOperandTypeId(_, inst, 2);
-      const uint32_t left_type = GetOperandTypeId(_, inst, 3);
-      const uint32_t right_type = GetOperandTypeId(_, inst, 4);
+      const uint32_t condition_type = _.GetOperandTypeId(inst, 2);
+      const uint32_t left_type = _.GetOperandTypeId(inst, 3);
+      const uint32_t right_type = _.GetOperandTypeId(inst, 4);
 
       if (!condition_type || (!_.IsBoolScalarType(condition_type) &&
                               !_.IsBoolVectorType(condition_type)))
@@ -240,8 +219,8 @@
                << "Expected bool scalar or vector type as Result Type: "
                << spvOpcodeString(opcode);
 
-      const uint32_t left_type = GetOperandTypeId(_, inst, 2);
-      const uint32_t right_type = GetOperandTypeId(_, inst, 3);
+      const uint32_t left_type = _.GetOperandTypeId(inst, 2);
+      const uint32_t right_type = _.GetOperandTypeId(inst, 3);
 
       if (!left_type ||
           (!_.IsIntScalarType(left_type) && !_.IsIntVectorType(left_type)))
diff --git a/source/validate_non_uniform.cpp b/source/validate_non_uniform.cpp
index de42dea..070c773 100644
--- a/source/validate_non_uniform.cpp
+++ b/source/validate_non_uniform.cpp
@@ -29,9 +29,8 @@
 namespace {
 
 spv_result_t ValidateExecutionScope(ValidationState_t& _,
-                                    const spv_parsed_instruction_t* inst,
-                                    uint32_t scope) {
-  SpvOp opcode = static_cast<SpvOp>(inst->opcode);
+                                    const Instruction* inst, uint32_t scope) {
+  SpvOp 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);
@@ -67,12 +66,11 @@
 }  // namespace
 
 // Validates correctness of non-uniform group instructions.
-spv_result_t NonUniformPass(ValidationState_t& _,
-                            const spv_parsed_instruction_t* inst) {
-  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
+spv_result_t NonUniformPass(ValidationState_t& _, const Instruction* inst) {
+  const SpvOp opcode = inst->opcode();
 
   if (spvOpcodeIsNonUniformGroupOperation(opcode)) {
-    const uint32_t execution_scope = inst->words[3];
+    const uint32_t execution_scope = inst->word(3);
     if (auto error = ValidateExecutionScope(_, inst, execution_scope)) {
       return error;
     }
diff --git a/source/validate_primitives.cpp b/source/validate_primitives.cpp
index 4705496..289ac39 100644
--- a/source/validate_primitives.cpp
+++ b/source/validate_primitives.cpp
@@ -27,9 +27,8 @@
 namespace val {
 
 // Validates correctness of primitive instructions.
-spv_result_t PrimitivesPass(ValidationState_t& _,
-                            const spv_parsed_instruction_t* inst) {
-  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
+spv_result_t PrimitivesPass(ValidationState_t& _, const Instruction* inst) {
+  const SpvOp opcode = inst->opcode();
 
   switch (opcode) {
     case SpvOpEmitVertex:
@@ -48,7 +47,7 @@
   switch (opcode) {
     case SpvOpEmitStreamVertex:
     case SpvOpEndStreamPrimitive: {
-      const uint32_t stream_id = inst->words[1];
+      const uint32_t stream_id = inst->word(1);
       const uint32_t stream_type = _.GetTypeId(stream_id);
       if (!_.IsIntScalarType(stream_type)) {
         return _.diag(SPV_ERROR_INVALID_DATA)
diff --git a/source/validate_type_unique.cpp b/source/validate_type_unique.cpp
index c251f6c..643c1e1 100644
--- a/source/validate_type_unique.cpp
+++ b/source/validate_type_unique.cpp
@@ -29,12 +29,11 @@
 // (see section 2.8 Types and Variables)
 // Doesn't do anything if SPV_VAL_ignore_type_decl_unique was declared in the
 // module.
-spv_result_t TypeUniquePass(ValidationState_t& _,
-                            const spv_parsed_instruction_t* inst) {
+spv_result_t TypeUniquePass(ValidationState_t& _, const Instruction* inst) {
   if (_.HasExtension(Extension::kSPV_VALIDATOR_ignore_type_decl_unique))
     return SPV_SUCCESS;
 
-  const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
+  const SpvOp opcode = inst->opcode();
 
   if (spvOpcodeGeneratesType(opcode)) {
     if (opcode == SpvOpTypeArray || opcode == SpvOpTypeRuntimeArray ||
@@ -43,11 +42,11 @@
       return SPV_SUCCESS;
     }
 
-    if (!_.RegisterUniqueTypeDeclaration(*inst)) {
+    if (!_.RegisterUniqueTypeDeclaration(inst)) {
       return _.diag(SPV_ERROR_INVALID_DATA)
              << "Duplicate non-aggregate type declarations are not allowed."
-             << " Opcode: " << spvOpcodeString(SpvOp(inst->opcode))
-             << " id: " << inst->result_id;
+             << " Opcode: " << spvOpcodeString(SpvOp(inst->opcode()))
+             << " id: " << inst->id();
     }
   }
 
diff --git a/test/opt/loop_optimizations/unroll_simple.cpp b/test/opt/loop_optimizations/unroll_simple.cpp
index 7f985de..d13520a 100644
--- a/test/opt/loop_optimizations/unroll_simple.cpp
+++ b/test/opt/loop_optimizations/unroll_simple.cpp
@@ -44,7 +44,6 @@
 }
 */
 TEST_F(PassClassTest, SimpleFullyUnrollTest) {
-  // clang-format off
   // With opt::LocalMultiStoreElimPass
   const std::string text = R"(
             OpCapability Shader
@@ -98,8 +97,7 @@
             OpFunctionEnd
   )";
 
-const std::string output =
-R"(OpCapability Shader
+  const std::string output = R"(OpCapability Shader
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %2 "main" %3
@@ -183,17 +181,17 @@
 OpReturn
 OpFunctionEnd
 )";
-  // clang-format on
-std::unique_ptr<opt::IRContext> context =
-    BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
-                SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-opt::Module* module = context->module();
-EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n"
-                           << text << std::endl;
 
-opt::LoopUnroller loop_unroller;
-SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
-SinglePassRunAndCheck<opt::LoopUnroller>(text, output, false);
+  std::unique_ptr<opt::IRContext> context =
+      BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
+                  SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  opt::Module* module = context->module();
+  EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n"
+                             << text << std::endl;
+
+  opt::LoopUnroller loop_unroller;
+  SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
+  SinglePassRunAndCheck<opt::LoopUnroller>(text, output, false);
 }
 
 template <int factor>
@@ -228,7 +226,6 @@
 }
 */
 TEST_F(PassClassTest, SimplePartialUnroll) {
-  // clang-format off
   // With opt::LocalMultiStoreElimPass
   const std::string text = R"(
             OpCapability Shader
@@ -344,7 +341,7 @@
 OpReturn
 OpFunctionEnd
 )";
-  // clang-format on
+
   std::unique_ptr<opt::IRContext> context =
       BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
                   SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
@@ -369,7 +366,6 @@
 }
 */
 TEST_F(PassClassTest, SimpleUnevenPartialUnroll) {
-  // clang-format off
   // With opt::LocalMultiStoreElimPass
   const std::string text = R"(
             OpCapability Shader
@@ -423,8 +419,7 @@
             OpFunctionEnd
   )";
 
-const std::string output =
-R"(OpCapability Shader
+  const std::string output = R"(OpCapability Shader
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %2 "main" %3
@@ -517,20 +512,20 @@
 OpReturn
 OpFunctionEnd
 )";
-  // clang-format on
-std::unique_ptr<opt::IRContext> context =
-    BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
-                SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-opt::Module* module = context->module();
-EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n"
-                           << text << std::endl;
 
-opt::LoopUnroller loop_unroller;
-SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
-// By unrolling by a factor that doesn't divide evenly into the number of loop
-// iterations we perfom an additional transform when partially unrolling to
-// account for the remainder.
-SinglePassRunAndCheck<PartialUnrollerTestPass<3>>(text, output, false);
+  std::unique_ptr<opt::IRContext> context =
+      BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
+                  SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  opt::Module* module = context->module();
+  EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n"
+                             << text << std::endl;
+
+  opt::LoopUnroller loop_unroller;
+  SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
+  // By unrolling by a factor that doesn't divide evenly into the number of loop
+  // iterations we perfom an additional transform when partially unrolling to
+  // account for the remainder.
+  SinglePassRunAndCheck<PartialUnrollerTestPass<3>>(text, output, false);
 }
 
 /* Generated from
@@ -544,7 +539,6 @@
 }
 */
 TEST_F(PassClassTest, SimpleLoopIterationsCheck) {
-  // clang-format off
   // With opt::LocalMultiStoreElimPass
   const std::string text = R"(
 OpCapability Shader
@@ -596,7 +590,6 @@
 OpReturn
 OpFunctionEnd
 )";
-  // clang-format on
 
   std::unique_ptr<opt::IRContext> context =
       BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
@@ -639,7 +632,6 @@
 }
 */
 TEST_F(PassClassTest, SimpleLoopIterationsCheckSignedInit) {
-  // clang-format off
   // With opt::LocalMultiStoreElimPass
   const std::string text = R"(
 OpCapability Shader
@@ -692,7 +684,6 @@
 OpReturn
 OpFunctionEnd
 )";
-  // clang-format on
 
   std::unique_ptr<opt::IRContext> context =
       BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
@@ -739,7 +730,6 @@
 }
 */
 TEST_F(PassClassTest, UnrollNestedLoops) {
-  // clang-format off
   // With opt::LocalMultiStoreElimPass
   const std::string text = R"(
                OpCapability Shader
@@ -809,8 +799,7 @@
                OpFunctionEnd
     )";
 
-const std::string output =
-R"(OpCapability Shader
+  const std::string output = R"(OpCapability Shader
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %2 "main"
@@ -964,16 +953,16 @@
 OpReturn
 OpFunctionEnd
 )";
-  // clang-format on
-std::unique_ptr<opt::IRContext> context =
-    BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
-                SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-opt::Module* module = context->module();
-EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n"
-                           << text << std::endl;
-opt::LoopUnroller loop_unroller;
-SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
-SinglePassRunAndCheck<opt::LoopUnroller>(text, output, false);
+
+  std::unique_ptr<opt::IRContext> context =
+      BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
+                  SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  opt::Module* module = context->module();
+  EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n"
+                             << text << std::endl;
+  opt::LoopUnroller loop_unroller;
+  SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
+  SinglePassRunAndCheck<opt::LoopUnroller>(text, output, false);
 }
 
 /*
@@ -987,9 +976,8 @@
 }
 */
 TEST_F(PassClassTest, NegativeConditionAndInit) {
-  // clang-format off
   // With opt::LocalMultiStoreElimPass
-const std::string text = R"(
+  const std::string text = R"(
                OpCapability Shader
           %1 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
@@ -1035,7 +1023,7 @@
                OpFunctionEnd
 )";
 
-const std::string expected = R"(OpCapability Shader
+  const std::string expected = R"(OpCapability Shader
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %2 "main"
@@ -1090,42 +1078,41 @@
 OpReturn
 OpFunctionEnd
 )";
-  // clang-format on
 
-std::unique_ptr<opt::IRContext> context =
-    BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
-                SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-opt::Module* module = context->module();
-EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n"
-                           << text << std::endl;
+  std::unique_ptr<opt::IRContext> context =
+      BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
+                  SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  opt::Module* module = context->module();
+  EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n"
+                             << text << std::endl;
 
-opt::LoopUnroller loop_unroller;
-SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
-// SinglePassRunAndCheck<opt::LoopUnroller>(text, expected, false);
+  opt::LoopUnroller loop_unroller;
+  SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
+  // SinglePassRunAndCheck<opt::LoopUnroller>(text, expected, false);
 
-opt::Function* f = spvtest::GetFunction(module, 4);
+  opt::Function* f = spvtest::GetFunction(module, 4);
 
-opt::LoopDescriptor& loop_descriptor = *context->GetLoopDescriptor(f);
-EXPECT_EQ(loop_descriptor.NumLoops(), 1u);
+  opt::LoopDescriptor& loop_descriptor = *context->GetLoopDescriptor(f);
+  EXPECT_EQ(loop_descriptor.NumLoops(), 1u);
 
-opt::Loop& loop = loop_descriptor.GetLoopByIndex(0);
+  opt::Loop& loop = loop_descriptor.GetLoopByIndex(0);
 
-EXPECT_TRUE(loop.HasUnrollLoopControl());
+  EXPECT_TRUE(loop.HasUnrollLoopControl());
 
-opt::BasicBlock* condition = loop.FindConditionBlock();
-EXPECT_EQ(condition->id(), 14u);
+  opt::BasicBlock* condition = loop.FindConditionBlock();
+  EXPECT_EQ(condition->id(), 14u);
 
-opt::Instruction* induction = loop.FindConditionVariable(condition);
-EXPECT_EQ(induction->result_id(), 32u);
+  opt::Instruction* induction = loop.FindConditionVariable(condition);
+  EXPECT_EQ(induction->result_id(), 32u);
 
-opt::LoopUtils loop_utils{context.get(), &loop};
-EXPECT_TRUE(loop_utils.CanPerformUnroll());
+  opt::LoopUtils loop_utils{context.get(), &loop};
+  EXPECT_TRUE(loop_utils.CanPerformUnroll());
 
-size_t iterations = 0;
-EXPECT_TRUE(
-    loop.FindNumberOfIterations(induction, &*condition->ctail(), &iterations));
-EXPECT_EQ(iterations, 2u);
-SinglePassRunAndCheck<opt::LoopUnroller>(text, expected, false);
+  size_t iterations = 0;
+  EXPECT_TRUE(loop.FindNumberOfIterations(induction, &*condition->ctail(),
+                                          &iterations));
+  EXPECT_EQ(iterations, 2u);
+  SinglePassRunAndCheck<opt::LoopUnroller>(text, expected, false);
 }
 
 /*
@@ -1139,9 +1126,8 @@
 }
 */
 TEST_F(PassClassTest, NegativeConditionAndInitResidualUnroll) {
-  // clang-format off
   // With opt::LocalMultiStoreElimPass
-const std::string text = R"(
+  const std::string text = R"(
                OpCapability Shader
           %1 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
@@ -1187,7 +1173,7 @@
                OpFunctionEnd
 )";
 
-const std::string expected = R"(OpCapability Shader
+  const std::string expected = R"(OpCapability Shader
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %2 "main"
@@ -1313,7 +1299,6 @@
 }
 */
 TEST_F(PassClassTest, UnrollNestedLoopsValidateDescriptor) {
-  // clang-format off
   // With opt::LocalMultiStoreElimPass
   const std::string text = R"(
                OpCapability Shader
@@ -1383,8 +1368,6 @@
                OpFunctionEnd
     )";
 
-  // clang-format on
-
   {  // Test fully unroll
     std::unique_ptr<opt::IRContext> context =
         BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
@@ -1479,7 +1462,6 @@
 }
 */
 TEST_F(PassClassTest, FullyUnrollNegativeStepLoopTest) {
-  // clang-format off
   // With opt::LocalMultiStoreElimPass
   const std::string text = R"(
                OpCapability Shader
@@ -1528,8 +1510,7 @@
                OpFunctionEnd
     )";
 
-const std::string output =
-R"(OpCapability Shader
+  const std::string output = R"(OpCapability Shader
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %2 "main"
@@ -1598,17 +1579,17 @@
 OpReturn
 OpFunctionEnd
 )";
-  // clang-format on
-std::unique_ptr<opt::IRContext> context =
-    BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
-                SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-opt::Module* module = context->module();
-EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n"
-                           << text << std::endl;
 
-opt::LoopUnroller loop_unroller;
-SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
-SinglePassRunAndCheck<opt::LoopUnroller>(text, output, false);
+  std::unique_ptr<opt::IRContext> context =
+      BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
+                  SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  opt::Module* module = context->module();
+  EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n"
+                             << text << std::endl;
+
+  opt::LoopUnroller loop_unroller;
+  SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
+  SinglePassRunAndCheck<opt::LoopUnroller>(text, output, false);
 }
 
 /*
@@ -1622,7 +1603,6 @@
 }
 */
 TEST_F(PassClassTest, FullyUnrollNegativeNonOneStepLoop) {
-  // clang-format off
   // With opt::LocalMultiStoreElimPass
   const std::string text = R"(
                OpCapability Shader
@@ -1671,8 +1651,7 @@
                OpFunctionEnd
     )";
 
-const std::string output =
-R"(OpCapability Shader
+  const std::string output = R"(OpCapability Shader
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %2 "main"
@@ -1741,17 +1720,17 @@
 OpReturn
 OpFunctionEnd
 )";
-  // clang-format on
-std::unique_ptr<opt::IRContext> context =
-    BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
-                SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-opt::Module* module = context->module();
-EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n"
-                           << text << std::endl;
 
-opt::LoopUnroller loop_unroller;
-SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
-SinglePassRunAndCheck<opt::LoopUnroller>(text, output, false);
+  std::unique_ptr<opt::IRContext> context =
+      BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
+                  SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  opt::Module* module = context->module();
+  EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n"
+                             << text << std::endl;
+
+  opt::LoopUnroller loop_unroller;
+  SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
+  SinglePassRunAndCheck<opt::LoopUnroller>(text, output, false);
 }
 
 /*
@@ -1765,7 +1744,6 @@
 }
 */
 TEST_F(PassClassTest, FullyUnrollNonDivisibleStepLoop) {
-  // clang-format off
   // With opt::LocalMultiStoreElimPass
   const std::string text = R"(OpCapability Shader
 %1 = OpExtInstImport "GLSL.std.450"
@@ -1813,8 +1791,7 @@
 OpFunctionEnd
 )";
 
-const std::string output =
-R"(OpCapability Shader
+  const std::string output = R"(OpCapability Shader
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %2 "main"
@@ -1883,17 +1860,17 @@
 OpReturn
 OpFunctionEnd
 )";
-  // clang-format on
-std::unique_ptr<opt::IRContext> context =
-    BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
-                SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-opt::Module* module = context->module();
-EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n"
-                           << text << std::endl;
 
-opt::LoopUnroller loop_unroller;
-SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
-SinglePassRunAndCheck<opt::LoopUnroller>(text, output, false);
+  std::unique_ptr<opt::IRContext> context =
+      BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
+                  SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  opt::Module* module = context->module();
+  EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n"
+                             << text << std::endl;
+
+  opt::LoopUnroller loop_unroller;
+  SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
+  SinglePassRunAndCheck<opt::LoopUnroller>(text, output, false);
 }
 
 /*
@@ -1907,7 +1884,6 @@
 }
 */
 TEST_F(PassClassTest, FullyUnrollNegativeNonDivisibleStepLoop) {
-  // clang-format off
   // With opt::LocalMultiStoreElimPass
   const std::string text = R"(OpCapability Shader
 %1 = OpExtInstImport "GLSL.std.450"
@@ -1955,8 +1931,7 @@
 OpFunctionEnd
 )";
 
-const std::string output =
-R"(OpCapability Shader
+  const std::string output = R"(OpCapability Shader
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %2 "main"
@@ -2038,20 +2013,19 @@
 OpReturn
 OpFunctionEnd
 )";
-  // clang-format on
-std::unique_ptr<opt::IRContext> context =
-    BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
-                SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-opt::Module* module = context->module();
-EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n"
-                           << text << std::endl;
 
-opt::LoopUnroller loop_unroller;
-SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
-SinglePassRunAndCheck<opt::LoopUnroller>(text, output, false);
+  std::unique_ptr<opt::IRContext> context =
+      BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
+                  SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  opt::Module* module = context->module();
+  EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n"
+                             << text << std::endl;
+
+  opt::LoopUnroller loop_unroller;
+  SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
+  SinglePassRunAndCheck<opt::LoopUnroller>(text, output, false);
 }
 
-// clang-format off
 // With opt::LocalMultiStoreElimPass
 static const std::string multiple_phi_shader = R"(
                OpCapability Shader
@@ -2102,12 +2076,9 @@
                OpReturnValue %37
                OpFunctionEnd
     )";
-// clang-format on
 
 TEST_F(PassClassTest, PartiallyUnrollResidualMultipleInductionVariables) {
-  // clang-format off
-const std::string output =
-R"(OpCapability Shader
+  const std::string output = R"(OpCapability Shader
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %2 "main"
@@ -2218,24 +2189,22 @@
 OpReturnValue %30
 OpFunctionEnd
 )";
-  // clang-format on
-std::unique_ptr<opt::IRContext> context =
-    BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, multiple_phi_shader,
-                SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-opt::Module* module = context->module();
-EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n"
-                           << multiple_phi_shader << std::endl;
 
-opt::LoopUnroller loop_unroller;
-SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
-SinglePassRunAndCheck<PartialUnrollerTestPass<4>>(multiple_phi_shader, output,
-                                                  false);
+  std::unique_ptr<opt::IRContext> context =
+      BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, multiple_phi_shader,
+                  SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  opt::Module* module = context->module();
+  EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n"
+                             << multiple_phi_shader << std::endl;
+
+  opt::LoopUnroller loop_unroller;
+  SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
+  SinglePassRunAndCheck<PartialUnrollerTestPass<4>>(multiple_phi_shader, output,
+                                                    false);
 }
 
 TEST_F(PassClassTest, PartiallyUnrollMultipleInductionVariables) {
-  // clang-format off
-const std::string output =
-R"(OpCapability Shader
+  const std::string output = R"(OpCapability Shader
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %2 "main"
@@ -2296,24 +2265,22 @@
 OpReturnValue %30
 OpFunctionEnd
 )";
-  // clang-format on
-std::unique_ptr<opt::IRContext> context =
-    BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, multiple_phi_shader,
-                SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-opt::Module* module = context->module();
-EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n"
-                           << multiple_phi_shader << std::endl;
 
-opt::LoopUnroller loop_unroller;
-SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
-SinglePassRunAndCheck<PartialUnrollerTestPass<2>>(multiple_phi_shader, output,
-                                                  false);
+  std::unique_ptr<opt::IRContext> context =
+      BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, multiple_phi_shader,
+                  SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  opt::Module* module = context->module();
+  EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n"
+                             << multiple_phi_shader << std::endl;
+
+  opt::LoopUnroller loop_unroller;
+  SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
+  SinglePassRunAndCheck<PartialUnrollerTestPass<2>>(multiple_phi_shader, output,
+                                                    false);
 }
 
 TEST_F(PassClassTest, FullyUnrollMultipleInductionVariables) {
-  // clang-format off
-const std::string output =
-R"(OpCapability Shader
+  const std::string output = R"(OpCapability Shader
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %2 "main"
@@ -2422,17 +2389,17 @@
 OpReturnValue %30
 OpFunctionEnd
 )";
-  // clang-format on
-std::unique_ptr<opt::IRContext> context =
-    BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, multiple_phi_shader,
-                SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-opt::Module* module = context->module();
-EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n"
-                           << multiple_phi_shader << std::endl;
 
-opt::LoopUnroller loop_unroller;
-SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
-SinglePassRunAndCheck<opt::LoopUnroller>(multiple_phi_shader, output, false);
+  std::unique_ptr<opt::IRContext> context =
+      BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, multiple_phi_shader,
+                  SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  opt::Module* module = context->module();
+  EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n"
+                             << multiple_phi_shader << std::endl;
+
+  opt::LoopUnroller loop_unroller;
+  SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
+  SinglePassRunAndCheck<opt::LoopUnroller>(multiple_phi_shader, output, false);
 }
 
 /*
@@ -2449,7 +2416,6 @@
 }
 */
 TEST_F(PassClassTest, FullyUnrollEqualToOperations) {
-  // clang-format off
   // With opt::LocalMultiStoreElimPass
   const std::string text = R"(
                OpCapability Shader
@@ -2505,8 +2471,7 @@
                OpFunctionEnd
     )";
 
-const std::string output =
-R"(OpCapability Shader
+  const std::string output = R"(OpCapability Shader
 %1 = OpExtInstImport "GLSL.std.450"
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %2 "main"
@@ -2585,22 +2550,21 @@
 OpReturn
 OpFunctionEnd
 )";
-  // clang-format on
-std::unique_ptr<opt::IRContext> context =
-    BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
-                SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-opt::Module* module = context->module();
-EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n"
-                           << text << std::endl;
 
-opt::LoopUnroller loop_unroller;
-SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
-SinglePassRunAndCheck<opt::LoopUnroller>(text, output, false);
+  std::unique_ptr<opt::IRContext> context =
+      BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
+                  SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  opt::Module* module = context->module();
+  EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n"
+                             << text << std::endl;
+
+  opt::LoopUnroller loop_unroller;
+  SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
+  SinglePassRunAndCheck<opt::LoopUnroller>(text, output, false);
 }
 
-// clang-format off
-  // With opt::LocalMultiStoreElimPass
-  const std::string condition_in_header = R"(
+// With opt::LocalMultiStoreElimPass
+const std::string condition_in_header = R"(
                OpCapability Shader
                OpMemoryModel Logical GLSL450
                OpEntryPoint Fragment %main "main" %o
@@ -2637,14 +2601,9 @@
                OpReturn
                OpFunctionEnd
     )";
-//clang-format on
-
 
 TEST_F(PassClassTest, FullyUnrollConditionIsInHeaderBlock) {
-
-// clang-format off
-const std::string output =
-R"(OpCapability Shader
+  const std::string output = R"(OpCapability Shader
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %1 "main" %2
 OpExecutionMode %1 OriginUpperLeft
@@ -2700,23 +2659,21 @@
 OpReturn
 OpFunctionEnd
 )";
-  // clang-format on
-std::unique_ptr<opt::IRContext> context =
-    BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, condition_in_header,
-                SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-opt::Module* module = context->module();
-EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n"
-                           << condition_in_header << std::endl;
 
-opt::LoopUnroller loop_unroller;
-SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
-SinglePassRunAndCheck<opt::LoopUnroller>(condition_in_header, output, false);
+  std::unique_ptr<opt::IRContext> context =
+      BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, condition_in_header,
+                  SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  opt::Module* module = context->module();
+  EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n"
+                             << condition_in_header << std::endl;
+
+  opt::LoopUnroller loop_unroller;
+  SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
+  SinglePassRunAndCheck<opt::LoopUnroller>(condition_in_header, output, false);
 }
 
 TEST_F(PassClassTest, PartiallyUnrollResidualConditionIsInHeaderBlock) {
-  // clang-format off
-const std::string output =
-R"(OpCapability Shader
+  const std::string output = R"(OpCapability Shader
 OpMemoryModel Logical GLSL450
 OpEntryPoint Fragment %1 "main" %2
 OpExecutionMode %1 OriginUpperLeft
@@ -2782,18 +2739,18 @@
 OpReturn
 OpFunctionEnd
 )";
-  // clang-format on
-std::unique_ptr<opt::IRContext> context =
-    BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, condition_in_header,
-                SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
-opt::Module* module = context->module();
-EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n"
-                           << condition_in_header << std::endl;
 
-opt::LoopUnroller loop_unroller;
-SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
-SinglePassRunAndCheck<PartialUnrollerTestPass<2>>(condition_in_header, output,
-                                                  false);
+  std::unique_ptr<opt::IRContext> context =
+      BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, condition_in_header,
+                  SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
+  opt::Module* module = context->module();
+  EXPECT_NE(nullptr, module) << "Assembling failed for ushader:\n"
+                             << condition_in_header << std::endl;
+
+  opt::LoopUnroller loop_unroller;
+  SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
+  SinglePassRunAndCheck<PartialUnrollerTestPass<2>>(condition_in_header, output,
+                                                    false);
 }
 
 /*
@@ -2808,7 +2765,6 @@
 }
 */
 TEST_F(PassClassTest, PartiallyUnrollLatchNotContinue) {
-  // clang-format off
   const std::string text = R"(OpCapability Shader
           %1 = OpExtInstImport "GLSL.std.450"
                OpMemoryModel Logical GLSL450
@@ -2967,7 +2923,7 @@
 OpReturn
 OpFunctionEnd
 )";
-  // clang-format on
+
   SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
   SinglePassRunAndCheck<PartialUnrollerTestPass<3>>(text, expected, true);