<NME> text_handler.h
<BEF> // Copyright (c) 2015-2016 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef SOURCE_TEXT_HANDLER_H_
#define SOURCE_TEXT_HANDLER_H_

#include <iomanip>
#include <set>
#include <sstream>
#include <string>
#include <type_traits>
#include <unordered_map>
#include <utility>

#include "source/diagnostic.h"
#include "source/instruction.h"
#include "source/text.h"
#include "spirv-tools/libspirv.h"

namespace spvtools {

// Structures

// This is a lattice for tracking types.
#include <libspirv/libspirv.h>
#include "diagnostic.h"
#include "instruction.h"
#include "operand.h"
#include "text.h"

namespace libspirv {

// Contains ID type information that needs to be tracked across all Ids.
// Bitwidth is only valid when type_class is kScalarIntegerType or
// kScalarFloatType.
struct IdType {
  uint32_t bitwidth;  // Safe to assume that we will not have > 2^32 bits.
  bool isSigned;      // This is only significant if type_class is integral.
  IdTypeClass type_class;
};

// Default equality operator for IdType. Tests if all members are the same.
inline bool operator==(const IdType& first, const IdType& second) {
  return (first.bitwidth == second.bitwidth) &&
         (first.isSigned == second.isSigned) &&
         (first.type_class == second.type_class);
}

// Tests whether any member of the IdTypes do not match.
inline bool operator!=(const IdType& first, const IdType& second) {
  return !(first == second);
}

// A value representing an unknown type.
extern const IdType kUnknownType;

// Returns true if the type is a scalar integer type.
inline bool isScalarIntegral(const IdType& type) {
  return type.type_class == IdTypeClass::kScalarIntegerType;
}

// Returns true if the type is a scalar floating point type.
inline bool isScalarFloating(const IdType& type) {
  return type.type_class == IdTypeClass::kScalarFloatType;
}

// Returns the number of bits in the type.
// This is only valid for bottom, scalar integer, and scalar floating
// classes.  For bottom, assume 32 bits.
inline int assumedBitWidth(const IdType& type) {
  switch (type.type_class) {
    case IdTypeClass::kBottom:
      return 32;
    case IdTypeClass::kScalarIntegerType:
    case IdTypeClass::kScalarFloatType:
      return type.bitwidth;
    default:
      break;
  }
  // We don't care about this case.
  return 0;
}

// A templated class with a static member function Clamp, where Clamp
// sets a referenced value of type T to 0 if T is an unsigned
// integer type, and returns true if it modified the referenced
// value.
template <typename T, typename = void>
class ClampToZeroIfUnsignedType {
 public:
  return 0;
}

// Encapsulates the grammar to use for SPIR-V assembly.
// Contains methods to query for valid instructions and operands.
class AssemblyGrammar {
 public:
  AssemblyGrammar(const spv_operand_table operand_table,
                  const spv_opcode_table opcode_table,
                  const spv_ext_inst_table ext_inst_table)
      : operandTable_(operand_table),
        opcodeTable_(opcode_table),
        extInstTable_(ext_inst_table) {}

  // Returns true if the compilation_data has been initialized with valid data.
  bool isValid() const;

  // Fills in the desc parameter with the information about the opcode
  // of the given name. Returns SPV_SUCCESS if the opcode was found, and
  // SPV_ERROR_INVALID_LOOKUP if the opcode does not exist.
  spv_result_t lookupOpcode(const char *name, spv_opcode_desc *desc) const;

  // Fills in the desc parameter with the information about the opcode
  // of the valid. Returns SPV_SUCCESS if the opcode was found, and
  // SPV_ERROR_INVALID_LOOKUP if the opcode does not exist.
  spv_result_t lookupOpcode(Op opcode, spv_opcode_desc *desc) const;

  // Fills in the desc parameter with the information about the given
  // operand. Returns SPV_SUCCESS if the operand was found, and
  // SPV_ERROR_INVALID_LOOKUP otherwise.
  spv_result_t lookupOperand(spv_operand_type_t type, const char *name,
                             size_t name_len, spv_operand_desc *desc) const;

  // Fills in the desc parameter with the information about the given
  // operand. Returns SPV_SUCCESS if the operand was found, and
  // SPV_ERROR_INVALID_LOOKUP otherwise.
  spv_result_t lookupOperand(spv_operand_type_t type, uint32_t operand,
                             spv_operand_desc *desc) const;

  // Parses a mask expression string for the given operand type.
  //
  // A mask expression is a sequence of one or more terms separated by '|',
  // where each term is a named enum value for a given type. No whitespace
  // is permitted.
  //
  // On success, the value is written to pValue, and SPV_SUCCESS is returend.
  // The operand type is defined by the type parameter, and the text to be
  // parsed is defined by the textValue parameter.
  spv_result_t parseMaskOperand(const spv_operand_type_t type,
                                const char *textValue, uint32_t *pValue) const;


  // Writes the extended operand with the given type and text to the *extInst
  // parameter.
  // Returns SPV_SUCCESS if the value could be found.
  spv_result_t lookupExtInst(spv_ext_inst_type_t type, const char *textValue,
                             spv_ext_inst_desc *extInst) const;

  // Writes the extended operand with the given type and first encoded word
  // to the *extInst parameter.
  // Returns SPV_SUCCESS if the value could be found.
  spv_result_t lookupExtInst(spv_ext_inst_type_t type,
                             uint32_t firstWord,
                             spv_ext_inst_desc *extInst) const;

  // Inserts the operands expected after the given typed mask onto the front
  // of the given pattern.
  //
  // Each set bit in the mask represents zero or more operand types that should
  // be prepended onto the pattern. Opearnds for a less significant bit always
  // appear before operands for a more significatn bit.
  //
  // If a set bit is unknown, then we assume it has no operands.
  void prependOperandTypesForMask(const spv_operand_type_t type,
                                  const uint32_t mask,
                                  spv_operand_pattern_t *pattern) const;

 private:
  const spv_operand_table operandTable_;
  const spv_opcode_table opcodeTable_;
  const spv_ext_inst_table extInstTable_;
};

// Encapsulates the data used during the assembly of a SPIR-V module.
class AssemblyContext {
 public:
template <typename T>
class ClampToZeroIfUnsignedType<
    T, typename std::enable_if<std::is_unsigned<T>::value>::type> {
 public:
  static bool Clamp(T* value_pointer) {
    if (*value_pointer) {
      *value_pointer = 0;
      return true;
    }
    return false;
  }
};

// Encapsulates the data used during the assembly of a SPIR-V module.
class AssemblyContext {
 public:
  AssemblyContext(spv_text text, const MessageConsumer& consumer,
                  std::set<uint32_t>&& ids_to_preserve = std::set<uint32_t>())
      : current_position_({}),
        consumer_(consumer),
        text_(text),
        bound_(1),
        next_id_(1),
        ids_to_preserve_(std::move(ids_to_preserve)) {}

  // Assigns a new integer value to the given text ID, or returns the previously
  // assigned integer value if the ID has been seen before.
  uint32_t spvNamedIdAssignOrGet(const char* textValue);

  // Returns the largest largest numeric ID that has been assigned.
  uint32_t getBound() const;

  // Advances position to point to the next word in the input stream.
  // Returns SPV_SUCCESS on success.
  spv_result_t advance();

  // Sets word to the next word in the input text. Fills next_position with
  // the next location past the end of the word.
  spv_result_t getWord(std::string* word, spv_position next_position);

  // Returns true if the next word in the input is the start of a new Opcode.
  bool startsWithOp();

  // Returns true if the next word in the input is the start of a new
  // instruction.
  bool isStartOfNewInst();

  // Returns a diagnostic object initialized with current position in the input
  // stream, and for the given error code. Any data written to this object will
  // show up in pDiagnsotic on destruction.
  DiagnosticStream diagnostic(spv_result_t error) {
    return DiagnosticStream(current_position_, consumer_, "", error);
  }

  // Returns a diagnostic object with the default assembly error code.
  DiagnosticStream diagnostic() {
    // The default failure for assembly is invalid text.
    return diagnostic(SPV_ERROR_INVALID_TEXT);
  }

  // Returns then next character in the input stream.
  char peek() const;

  // Returns true if there is more text in the input stream.
  bool hasText() const;

  // Seeks the input stream forward by 'size' characters.
  void seekForward(uint32_t size);

  // Sets the current position in the input stream to the given position.
  void setPosition(const spv_position_t& newPosition) {
    current_position_ = newPosition;
  }

  // Returns the current position in the input stream.
  const spv_position_t& position() const { return current_position_; }

  // Appends the given 32-bit value to the given instruction.
  // Returns SPV_SUCCESS if the value could be correctly inserted in the
  // instruction.
  spv_result_t binaryEncodeU32(const uint32_t value, spv_instruction_t* pInst);

  // Appends the given string to the given instruction.
  // Returns SPV_SUCCESS if the value could be correctly inserted in the
  // instruction.
  spv_result_t binaryEncodeString(const char* value, spv_instruction_t* pInst);

  // Appends the given numeric literal to the given instruction.
  // Validates and respects the bitwidth supplied in the IdType argument.
  // If the type is of class kBottom the value will be encoded as a
  // 32-bit integer.
  // Returns SPV_SUCCESS if the value could be correctly added to the
  // instruction.  Returns the given error code on failure, and emits
  // a diagnostic if that error code is not SPV_FAILED_MATCH.
  spv_result_t binaryEncodeNumericLiteral(const char* numeric_literal,
                                          spv_result_t error_code,
                                          const IdType& type,
                                          spv_instruction_t* pInst);

  // Returns the IdType associated with this type-generating value.
  // If the type has not been previously recorded with recordTypeDefinition,
  // kUnknownType  will be returned.
  IdType getTypeOfTypeGeneratingValue(uint32_t value) const;

  // Returns the IdType that represents the return value of this Value
  // generating instruction.
  // If the value has not been recorded with recordTypeIdForValue, or the type
  // could not be determined kUnknownType will be returned.
  IdType getTypeOfValueInstruction(uint32_t value) const;

  // Tracks the type-defining instruction. The result of the tracking can
  // later be queried using getValueType.
  // pInst is expected to be completely filled in by the time this instruction
  // is called.
  // Returns SPV_SUCCESS on success, or SPV_ERROR_INVALID_VALUE on error.
  spv_result_t recordTypeDefinition(const spv_instruction_t* pInst);

  // Tracks the relationship between the value and its type.
  spv_result_t recordTypeIdForValue(uint32_t value, uint32_t type);

  // Records the given Id as being the import of the given extended instruction
  // type.
  spv_result_t recordIdAsExtInstImport(uint32_t id, spv_ext_inst_type_t type);

  // Returns the extended instruction type corresponding to the import with
  // the given Id, if it exists.  Returns SPV_EXT_INST_TYPE_NONE if the
  // id is not the id for an extended instruction type.
  spv_ext_inst_type_t getExtInstTypeForId(uint32_t id) const;

  // Returns a set consisting of each ID generated by spvNamedIdAssignOrGet from
  // a numeric ID text representation. For example, generated from "%12" but not
  // from "%foo".
  std::set<uint32_t> GetNumericIds() const;

 private:
  // Maps ID names to their corresponding numerical ids.
  using spv_named_id_table = std::unordered_map<std::string, uint32_t>;
  // Maps type-defining IDs to their IdType.
  using spv_id_to_type_map = std::unordered_map<uint32_t, IdType>;
  // Maps Ids to the id of their type.
  using spv_id_to_type_id = std::unordered_map<uint32_t, uint32_t>;

  spv_named_id_table named_ids_;
  spv_id_to_type_map types_;
  spv_id_to_type_id value_types_;
  // Maps an extended instruction import Id to the extended instruction type.
  std::unordered_map<uint32_t, spv_ext_inst_type_t> import_id_to_ext_inst_type_;
  spv_position_t current_position_;
  MessageConsumer consumer_;
  spv_text text_;
  uint32_t bound_;
  uint32_t next_id_;
  std::set<uint32_t> ids_to_preserve_;
};

}  // namespace spvtools

#endif  // SOURCE_TEXT_HANDLER_H_

<MSG> Move AssemblyGrammar into its own source files

<DFF> @@ -36,7 +36,6 @@
 #include <libspirv/libspirv.h>
 #include "diagnostic.h"
 #include "instruction.h"
-#include "operand.h"
 #include "text.h"
 
 namespace libspirv {
@@ -102,86 +101,6 @@ inline int assumedBitWidth(const IdType& type) {
   return 0;
 }
 
-// Encapsulates the grammar to use for SPIR-V assembly.
-// Contains methods to query for valid instructions and operands.
-class AssemblyGrammar {
- public:
-  AssemblyGrammar(const spv_operand_table operand_table,
-                  const spv_opcode_table opcode_table,
-                  const spv_ext_inst_table ext_inst_table)
-      : operandTable_(operand_table),
-        opcodeTable_(opcode_table),
-        extInstTable_(ext_inst_table) {}
-
-  // Returns true if the compilation_data has been initialized with valid data.
-  bool isValid() const;
-
-  // Fills in the desc parameter with the information about the opcode
-  // of the given name. Returns SPV_SUCCESS if the opcode was found, and
-  // SPV_ERROR_INVALID_LOOKUP if the opcode does not exist.
-  spv_result_t lookupOpcode(const char *name, spv_opcode_desc *desc) const;
-
-  // Fills in the desc parameter with the information about the opcode
-  // of the valid. Returns SPV_SUCCESS if the opcode was found, and
-  // SPV_ERROR_INVALID_LOOKUP if the opcode does not exist.
-  spv_result_t lookupOpcode(Op opcode, spv_opcode_desc *desc) const;
-
-  // Fills in the desc parameter with the information about the given
-  // operand. Returns SPV_SUCCESS if the operand was found, and
-  // SPV_ERROR_INVALID_LOOKUP otherwise.
-  spv_result_t lookupOperand(spv_operand_type_t type, const char *name,
-                             size_t name_len, spv_operand_desc *desc) const;
-
-  // Fills in the desc parameter with the information about the given
-  // operand. Returns SPV_SUCCESS if the operand was found, and
-  // SPV_ERROR_INVALID_LOOKUP otherwise.
-  spv_result_t lookupOperand(spv_operand_type_t type, uint32_t operand,
-                             spv_operand_desc *desc) const;
-
-  // Parses a mask expression string for the given operand type.
-  //
-  // A mask expression is a sequence of one or more terms separated by '|',
-  // where each term is a named enum value for a given type. No whitespace
-  // is permitted.
-  //
-  // On success, the value is written to pValue, and SPV_SUCCESS is returend.
-  // The operand type is defined by the type parameter, and the text to be
-  // parsed is defined by the textValue parameter.
-  spv_result_t parseMaskOperand(const spv_operand_type_t type,
-                                const char *textValue, uint32_t *pValue) const;
-
-
-  // Writes the extended operand with the given type and text to the *extInst
-  // parameter.
-  // Returns SPV_SUCCESS if the value could be found.
-  spv_result_t lookupExtInst(spv_ext_inst_type_t type, const char *textValue,
-                             spv_ext_inst_desc *extInst) const;
-
-  // Writes the extended operand with the given type and first encoded word
-  // to the *extInst parameter.
-  // Returns SPV_SUCCESS if the value could be found.
-  spv_result_t lookupExtInst(spv_ext_inst_type_t type,
-                             uint32_t firstWord,
-                             spv_ext_inst_desc *extInst) const;
-
-  // Inserts the operands expected after the given typed mask onto the front
-  // of the given pattern.
-  //
-  // Each set bit in the mask represents zero or more operand types that should
-  // be prepended onto the pattern. Opearnds for a less significant bit always
-  // appear before operands for a more significatn bit.
-  //
-  // If a set bit is unknown, then we assume it has no operands.
-  void prependOperandTypesForMask(const spv_operand_type_t type,
-                                  const uint32_t mask,
-                                  spv_operand_pattern_t *pattern) const;
-
- private:
-  const spv_operand_table operandTable_;
-  const spv_opcode_table opcodeTable_;
-  const spv_ext_inst_table extInstTable_;
-};
-
 // Encapsulates the data used during the assembly of a SPIR-V module.
 class AssemblyContext {
  public:

{'commit': 'diff --git a/CMakeLists.txt b/CMakeLists.txt\nindex ce2c3663..af4762c8 100644\n--- a/CMakeLists.txt\n+++ b/CMakeLists.txt\n@@ -103,6 +103,7 @@ include_directories(\n set(SPIRV_SOURCES\n   ${CMAKE_CURRENT_SOURCE_DIR}/include/libspirv/libspirv.h\n   ${CMAKE_CURRENT_SOURCE_DIR}/include/util/bitutils.h\n+  ${CMAKE_CURRENT_SOURCE_DIR}/source/assembly_grammar.h\n   ${CMAKE_CURRENT_SOURCE_DIR}/source/binary.h\n   ${CMAKE_CURRENT_SOURCE_DIR}/source/diagnostic.h\n   ${CMAKE_CURRENT_SOURCE_DIR}/source/ext_inst.h\n@@ -113,6 +114,7 @@ set(SPIRV_SOURCES\n   ${CMAKE_CURRENT_SOURCE_DIR}/source/text.h\n   ${CMAKE_CURRENT_SOURCE_DIR}/source/text_handler.h\n   ${CMAKE_CURRENT_SOURCE_DIR}/source/validate.h\n+  ${CMAKE_CURRENT_SOURCE_DIR}/source/assembly_grammar.cpp\n   ${CMAKE_CURRENT_SOURCE_DIR}/source/binary.cpp\n   ${CMAKE_CURRENT_SOURCE_DIR}/source/diagnostic.cpp\n   ${CMAKE_CURRENT_SOURCE_DIR}/source/ext_inst.cpp\ndiff --git a/source/assembly_grammar.cpp b/source/assembly_grammar.cpp\nnew file mode 100644\nindex 00000000..e9564426\n--- /dev/null\n+++ b/source/assembly_grammar.cpp\n@@ -0,0 +1,137 @@\n+// Copyright (c) 2015 The Khronos Group Inc.\n+//\n+// Permission is hereby granted, free of charge, to any person obtaining a\n+// copy of this software and/or associated documentation files (the\n+// "Materials"), to deal in the Materials without restriction, including\n+// without limitation the rights to use, copy, modify, merge, publish,\n+// distribute, sublicense, and/or sell copies of the Materials, and to\n+// permit persons to whom the Materials are furnished to do so, subject to\n+// the following conditions:\n+//\n+// The above copyright notice and this permission notice shall be included\n+// in all copies or substantial portions of the Materials.\n+//\n+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS\n+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS\n+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT\n+//    https://www.khronos.org/registry/\n+//\n+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\n+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.\n+\n+#include "assembly_grammar.h"\n+\n+#include <algorithm>\n+#include <cstring>\n+\n+#include "ext_inst.h"\n+#include "opcode.h"\n+\n+namespace {\n+\n+/// @brief Parses a mask expression string for the given operand type.\n+///\n+/// A mask expression is a sequence of one or more terms separated by \'|\',\n+/// where each term a named enum value for the given type.  No whitespace\n+/// is permitted.\n+///\n+/// On success, the value is written to pValue.\n+///\n+/// @param[in] operandTable operand lookup table\n+/// @param[in] type of the operand\n+/// @param[in] textValue word of text to be parsed\n+/// @param[out] pValue where the resulting value is written\n+///\n+/// @return result code\n+spv_result_t spvTextParseMaskOperand(const spv_operand_table operandTable,\n+                                     const spv_operand_type_t type,\n+                                     const char *textValue, uint32_t *pValue) {\n+  if (textValue == nullptr) return SPV_ERROR_INVALID_TEXT;\n+  size_t text_length = strlen(textValue);\n+  if (text_length == 0) return SPV_ERROR_INVALID_TEXT;\n+  const char *text_end = textValue + text_length;\n+\n+  // We only support mask expressions in ASCII, so the separator value is a\n+  // char.\n+  const char separator = \'|\';\n+\n+  // Accumulate the result by interpreting one word at a time, scanning\n+  // from left to right.\n+  uint32_t value = 0;\n+  const char *begin = textValue;  // The left end of the current word.\n+  const char *end = nullptr;  // One character past the end of the current word.\n+  do {\n+    end = std::find(begin, text_end, separator);\n+\n+    spv_operand_desc entry = nullptr;\n+    if (spvOperandTableNameLookup(operandTable, type, begin, end - begin,\n+                                  &entry)) {\n+      return SPV_ERROR_INVALID_TEXT;\n+    }\n+    value |= entry->value;\n+\n+    // Advance to the next word by skipping over the separator.\n+    begin = end + 1;\n+  } while (end != text_end);\n+\n+  *pValue = value;\n+  return SPV_SUCCESS;\n+}\n+}  // anonymous namespace\n+\n+namespace libspirv {\n+\n+bool AssemblyGrammar::isValid() const {\n+  return operandTable_ && opcodeTable_ && extInstTable_;\n+}\n+\n+spv_result_t AssemblyGrammar::lookupOpcode(const char *name,\n+                                           spv_opcode_desc *desc) const {\n+  return spvOpcodeTableNameLookup(opcodeTable_, name, desc);\n+}\n+\n+spv_result_t AssemblyGrammar::lookupOpcode(Op opcode,\n+                                           spv_opcode_desc *desc) const {\n+  return spvOpcodeTableValueLookup(opcodeTable_, opcode, desc);\n+}\n+\n+spv_result_t AssemblyGrammar::lookupOperand(spv_operand_type_t type,\n+                                            const char *name, size_t name_len,\n+                                            spv_operand_desc *desc) const {\n+  return spvOperandTableNameLookup(operandTable_, type, name, name_len, desc);\n+}\n+\n+spv_result_t AssemblyGrammar::lookupOperand(spv_operand_type_t type,\n+                                            uint32_t operand,\n+                                            spv_operand_desc *desc) const {\n+  return spvOperandTableValueLookup(operandTable_, type, operand, desc);\n+}\n+\n+spv_result_t AssemblyGrammar::parseMaskOperand(const spv_operand_type_t type,\n+                                               const char *textValue,\n+                                               uint32_t *pValue) const {\n+  return spvTextParseMaskOperand(operandTable_, type, textValue, pValue);\n+}\n+spv_result_t AssemblyGrammar::lookupExtInst(spv_ext_inst_type_t type,\n+                                            const char *textValue,\n+                                            spv_ext_inst_desc *extInst) const {\n+  return spvExtInstTableNameLookup(extInstTable_, type, textValue, extInst);\n+}\n+\n+spv_result_t AssemblyGrammar::lookupExtInst(spv_ext_inst_type_t type,\n+                                            uint32_t firstWord,\n+                                            spv_ext_inst_desc *extInst) const {\n+  return spvExtInstTableValueLookup(extInstTable_, type, firstWord, extInst);\n+}\n+\n+void AssemblyGrammar::prependOperandTypesForMask(\n+    const spv_operand_type_t type, const uint32_t mask,\n+    spv_operand_pattern_t *pattern) const {\n+  spvPrependOperandTypesForMask(operandTable_, type, mask, pattern);\n+}\n+}  // namespace libspirv\ndiff --git a/source/assembly_grammar.h b/source/assembly_grammar.h\nnew file mode 100644\nindex 00000000..9cb9c4a0\n--- /dev/null\n+++ b/source/assembly_grammar.h\n@@ -0,0 +1,114 @@\n+// Copyright (c) 2015 The Khronos Group Inc.\n+//\n+// Permission is hereby granted, free of charge, to any person obtaining a\n+// copy of this software and/or associated documentation files (the\n+// "Materials"), to deal in the Materials without restriction, including\n+// without limitation the rights to use, copy, modify, merge, publish,\n+// distribute, sublicense, and/or sell copies of the Materials, and to\n+// permit persons to whom the Materials are furnished to do so, subject to\n+// the following conditions:\n+//\n+// The above copyright notice and this permission notice shall be included\n+// in all copies or substantial portions of the Materials.\n+//\n+// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS\n+// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS\n+// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT\n+//    https://www.khronos.org/registry/\n+//\n+// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\n+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\n+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n+// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.\n+\n+#ifndef _LIBSPIRV_UTIL_ASSEMBLY_GRAMMAR_H_\n+#define _LIBSPIRV_UTIL_ASSEMBLY_GRAMMAR_H_\n+\n+#include <libspirv/libspirv.h>\n+#include "operand.h"\n+\n+namespace libspirv {\n+\n+// Encapsulates the grammar to use for SPIR-V assembly.\n+// Contains methods to query for valid instructions and operands.\n+class AssemblyGrammar {\n+ public:\n+  AssemblyGrammar(const spv_operand_table operand_table,\n+                  const spv_opcode_table opcode_table,\n+                  const spv_ext_inst_table ext_inst_table)\n+      : operandTable_(operand_table),\n+        opcodeTable_(opcode_table),\n+        extInstTable_(ext_inst_table) {}\n+\n+  // Returns true if the compilation_data has been initialized with valid data.\n+  bool isValid() const;\n+\n+  // Fills in the desc parameter with the information about the opcode\n+  // of the given name. Returns SPV_SUCCESS if the opcode was found, and\n+  // SPV_ERROR_INVALID_LOOKUP if the opcode does not exist.\n+  spv_result_t lookupOpcode(const char *name, spv_opcode_desc *desc) const;\n+\n+  // Fills in the desc parameter with the information about the opcode\n+  // of the valid. Returns SPV_SUCCESS if the opcode was found, and\n+  // SPV_ERROR_INVALID_LOOKUP if the opcode does not exist.\n+  spv_result_t lookupOpcode(Op opcode, spv_opcode_desc *desc) const;\n+\n+  // Fills in the desc parameter with the information about the given\n+  // operand. Returns SPV_SUCCESS if the operand was found, and\n+  // SPV_ERROR_INVALID_LOOKUP otherwise.\n+  spv_result_t lookupOperand(spv_operand_type_t type, const char *name,\n+                             size_t name_len, spv_operand_desc *desc) const;\n+\n+  // Fills in the desc parameter with the information about the given\n+  // operand. Returns SPV_SUCCESS if the operand was found, and\n+  // SPV_ERROR_INVALID_LOOKUP otherwise.\n+  spv_result_t lookupOperand(spv_operand_type_t type, uint32_t operand,\n+                             spv_operand_desc *desc) const;\n+\n+  // Parses a mask expression string for the given operand type.\n+  //\n+  // A mask expression is a sequence of one or more terms separated by \'|\',\n+  // where each term is a named enum value for a given type. No whitespace\n+  // is permitted.\n+  //\n+  // On success, the value is written to pValue, and SPV_SUCCESS is returend.\n+  // The operand type is defined by the type parameter, and the text to be\n+  // parsed is defined by the textValue parameter.\n+  spv_result_t parseMaskOperand(const spv_operand_type_t type,\n+                                const char *textValue, uint32_t *pValue) const;\n+\n+  // Writes the extended operand with the given type and text to the *extInst\n+  // parameter.\n+  // Returns SPV_SUCCESS if the value could be found.\n+  spv_result_t lookupExtInst(spv_ext_inst_type_t type, const char *textValue,\n+                             spv_ext_inst_desc *extInst) const;\n+\n+  // Writes the extended operand with the given type and first encoded word\n+  // to the *extInst parameter.\n+  // Returns SPV_SUCCESS if the value could be found.\n+  spv_result_t lookupExtInst(spv_ext_inst_type_t type, uint32_t firstWord,\n+                             spv_ext_inst_desc *extInst) const;\n+\n+  // Inserts the operands expected after the given typed mask onto the front\n+  // of the given pattern.\n+  //\n+  // Each set bit in the mask represents zero or more operand types that should\n+  // be prepended onto the pattern. Opearnds for a less significant bit always\n+  // appear before operands for a more significatn bit.\n+  //\n+  // If a set bit is unknown, then we assume it has no operands.\n+  void prependOperandTypesForMask(const spv_operand_type_t type,\n+                                  const uint32_t mask,\n+                                  spv_operand_pattern_t *pattern) const;\n+\n+ private:\n+  const spv_operand_table operandTable_;\n+  const spv_opcode_table opcodeTable_;\n+  const spv_ext_inst_table extInstTable_;\n+};\n+}\n+#endif  // _LIBSPIRV_UTIL_ASSEMBLY_GRAMMAR_H_\n+\ndiff --git a/source/binary.cpp b/source/binary.cpp\nindex 9df80d32..de291061 100644\n--- a/source/binary.cpp\n+++ b/source/binary.cpp\n@@ -24,8 +24,15 @@\n // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n // MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.\n \n-#include <libspirv/libspirv.h>\n #include "binary.h"\n+\n+#include <cassert>\n+#include <cstring>\n+#include <sstream>\n+#include <unordered_map>\n+\n+#include <libspirv/libspirv.h>\n+#include "assembly_grammar.h"\n #include "diagnostic.h"\n #include "ext_inst.h"\n #include "instruction.h"\n@@ -33,12 +40,6 @@\n #include "operand.h"\n #include "text_handler.h"\n \n-#include <assert.h>\n-#include <string.h>\n-\n-#include <sstream>\n-#include <unordered_map>\n-\n // Binary API\n \n enum {\ndiff --git a/source/text.cpp b/source/text.cpp\nindex 388ebdbf..8853ed20 100644\n--- a/source/text.cpp\n+++ b/source/text.cpp\n@@ -38,6 +38,7 @@\n #include <unordered_map>\n #include <vector>\n \n+#include "assembly_grammar.h"\n #include "binary.h"\n #include "diagnostic.h"\n #include "ext_inst.h"\ndiff --git a/source/text_handler.cpp b/source/text_handler.cpp\nindex 88f7827d..803d9142 100644\n--- a/source/text_handler.cpp\n+++ b/source/text_handler.cpp\n@@ -26,12 +26,12 @@\n \n #include "text_handler.h"\n \n-#include <algorithm>\n #include <cassert>\n #include <cstdlib>\n #include <cstring>\n #include <tuple>\n \n+#include "assembly_grammar.h"\n #include "binary.h"\n #include "ext_inst.h"\n #include "instruction.h"\n@@ -163,110 +163,12 @@ bool startsWithOp(spv_text text, spv_position position) {\n   return (\'O\' == ch0 && \'p\' == ch1 && (\'A\' <= ch2 && ch2 <= \'Z\'));\n }\n \n-/// @brief Parses a mask expression string for the given operand type.\n-///\n-/// A mask expression is a sequence of one or more terms separated by \'|\',\n-/// where each term a named enum value for the given type.  No whitespace\n-/// is permitted.\n-///\n-/// On success, the value is written to pValue.\n-///\n-/// @param[in] operandTable operand lookup table\n-/// @param[in] type of the operand\n-/// @param[in] textValue word of text to be parsed\n-/// @param[out] pValue where the resulting value is written\n-///\n-/// @return result code\n-spv_result_t spvTextParseMaskOperand(const spv_operand_table operandTable,\n-                                     const spv_operand_type_t type,\n-                                     const char *textValue, uint32_t *pValue) {\n-  if (textValue == nullptr) return SPV_ERROR_INVALID_TEXT;\n-  size_t text_length = strlen(textValue);\n-  if (text_length == 0) return SPV_ERROR_INVALID_TEXT;\n-  const char *text_end = textValue + text_length;\n-\n-  // We only support mask expressions in ASCII, so the separator value is a\n-  // char.\n-  const char separator = \'|\';\n-\n-  // Accumulate the result by interpreting one word at a time, scanning\n-  // from left to right.\n-  uint32_t value = 0;\n-  const char *begin = textValue;  // The left end of the current word.\n-  const char *end = nullptr;  // One character past the end of the current word.\n-  do {\n-    end = std::find(begin, text_end, separator);\n-\n-    spv_operand_desc entry = nullptr;\n-    if (spvOperandTableNameLookup(operandTable, type, begin, end - begin,\n-                                  &entry)) {\n-      return SPV_ERROR_INVALID_TEXT;\n-    }\n-    value |= entry->value;\n-\n-    // Advance to the next word by skipping over the separator.\n-    begin = end + 1;\n-  } while (end != text_end);\n-\n-  *pValue = value;\n-  return SPV_SUCCESS;\n-}\n-\n }  // anonymous namespace\n \n namespace libspirv {\n \n const IdType kUnknownType = {0, false, IdTypeClass::kBottom};\n \n-bool AssemblyGrammar::isValid() const {\n-  return operandTable_ && opcodeTable_ && extInstTable_;\n-}\n-\n-spv_result_t AssemblyGrammar::lookupOpcode(const char *name,\n-                                           spv_opcode_desc *desc) const {\n-  return spvOpcodeTableNameLookup(opcodeTable_, name, desc);\n-}\n-\n-spv_result_t AssemblyGrammar::lookupOpcode(Op opcode,\n-                                           spv_opcode_desc *desc) const {\n-  return spvOpcodeTableValueLookup(opcodeTable_, opcode, desc);\n-}\n-\n-spv_result_t AssemblyGrammar::lookupOperand(spv_operand_type_t type,\n-                                            const char *name, size_t name_len,\n-                                            spv_operand_desc *desc) const {\n-  return spvOperandTableNameLookup(operandTable_, type, name, name_len, desc);\n-}\n-\n-spv_result_t AssemblyGrammar::lookupOperand(spv_operand_type_t type,\n-                                            uint32_t operand,\n-                                            spv_operand_desc *desc) const {\n-  return spvOperandTableValueLookup(operandTable_, type, operand, desc);\n-}\n-\n-spv_result_t AssemblyGrammar::parseMaskOperand(const spv_operand_type_t type,\n-                                               const char *textValue,\n-                                               uint32_t *pValue) const {\n-  return spvTextParseMaskOperand(operandTable_, type, textValue, pValue);\n-}\n-spv_result_t AssemblyGrammar::lookupExtInst(spv_ext_inst_type_t type,\n-                                            const char *textValue,\n-                                            spv_ext_inst_desc *extInst) const {\n-  return spvExtInstTableNameLookup(extInstTable_, type, textValue, extInst);\n-}\n-\n-spv_result_t AssemblyGrammar::lookupExtInst(spv_ext_inst_type_t type,\n-                                            uint32_t firstWord,\n-                                            spv_ext_inst_desc *extInst) const {\n-  return spvExtInstTableValueLookup(extInstTable_, type, firstWord, extInst);\n-}\n-\n-void AssemblyGrammar::prependOperandTypesForMask(\n-    const spv_operand_type_t type, const uint32_t mask,\n-    spv_operand_pattern_t *pattern) const {\n-  spvPrependOperandTypesForMask(operandTable_, type, mask, pattern);\n-}\n-\n // TODO(dneto): Reorder AssemblyContext definitions to match declaration order.\n \n // This represents all of the data that is only valid for the duration of\ndiff --git a/source/text_handler.h b/source/text_handler.h\nindex adbde16f..9d9c1259 100644\n--- a/source/text_handler.h\n+++ b/source/text_handler.h\n@@ -36,7 +36,6 @@\n #include <libspirv/libspirv.h>\n #include "diagnostic.h"\n #include "instruction.h"\n-#include "operand.h"\n #include "text.h"\n \n namespace libspirv {\n@@ -102,86 +101,6 @@ inline int assumedBitWidth(const IdType& type) {\n   return 0;\n }\n \n-// Encapsulates the grammar to use for SPIR-V assembly.\n-// Contains methods to query for valid instructions and operands.\n-class AssemblyGrammar {\n- public:\n-  AssemblyGrammar(const spv_operand_table operand_table,\n-                  const spv_opcode_table opcode_table,\n-                  const spv_ext_inst_table ext_inst_table)\n-      : operandTable_(operand_table),\n-        opcodeTable_(opcode_table),\n-        extInstTable_(ext_inst_table) {}\n-\n-  // Returns true if the compilation_data has been initialized with valid data.\n-  bool isValid() const;\n-\n-  // Fills in the desc parameter with the information about the opcode\n-  // of the given name. Returns SPV_SUCCESS if the opcode was found, and\n-  // SPV_ERROR_INVALID_LOOKUP if the opcode does not exist.\n-  spv_result_t lookupOpcode(const char *name, spv_opcode_desc *desc) const;\n-\n-  // Fills in the desc parameter with the information about the opcode\n-  // of the valid. Returns SPV_SUCCESS if the opcode was found, and\n-  // SPV_ERROR_INVALID_LOOKUP if the opcode does not exist.\n-  spv_result_t lookupOpcode(Op opcode, spv_opcode_desc *desc) const;\n-\n-  // Fills in the desc parameter with the information about the given\n-  // operand. Returns SPV_SUCCESS if the operand was found, and\n-  // SPV_ERROR_INVALID_LOOKUP otherwise.\n-  spv_result_t lookupOperand(spv_operand_type_t type, const char *name,\n-                             size_t name_len, spv_operand_desc *desc) const;\n-\n-  // Fills in the desc parameter with the information about the given\n-  // operand. Returns SPV_SUCCESS if the operand was found, and\n-  // SPV_ERROR_INVALID_LOOKUP otherwise.\n-  spv_result_t lookupOperand(spv_operand_type_t type, uint32_t operand,\n-                             spv_operand_desc *desc) const;\n-\n-  // Parses a mask expression string for the given operand type.\n-  //\n-  // A mask expression is a sequence of one or more terms separated by \'|\',\n-  // where each term is a named enum value for a given type. No whitespace\n-  // is permitted.\n-  //\n-  // On success, the value is written to pValue, and SPV_SUCCESS is returend.\n-  // The operand type is defined by the type parameter, and the text to be\n-  // parsed is defined by the textValue parameter.\n-  spv_result_t parseMaskOperand(const spv_operand_type_t type,\n-                                const char *textValue, uint32_t *pValue) const;\n-\n-\n-  // Writes the extended operand with the given type and text to the *extInst\n-  // parameter.\n-  // Returns SPV_SUCCESS if the value could be found.\n-  spv_result_t lookupExtInst(spv_ext_inst_type_t type, const char *textValue,\n-                             spv_ext_inst_desc *extInst) const;\n-\n-  // Writes the extended operand with the given type and first encoded word\n-  // to the *extInst parameter.\n-  // Returns SPV_SUCCESS if the value could be found.\n-  spv_result_t lookupExtInst(spv_ext_inst_type_t type,\n-                             uint32_t firstWord,\n-                             spv_ext_inst_desc *extInst) const;\n-\n-  // Inserts the operands expected after the given typed mask onto the front\n-  // of the given pattern.\n-  //\n-  // Each set bit in the mask represents zero or more operand types that should\n-  // be prepended onto the pattern. Opearnds for a less significant bit always\n-  // appear before operands for a more significatn bit.\n-  //\n-  // If a set bit is unknown, then we assume it has no operands.\n-  void prependOperandTypesForMask(const spv_operand_type_t type,\n-                                  const uint32_t mask,\n-                                  spv_operand_pattern_t *pattern) const;\n-\n- private:\n-  const spv_operand_table operandTable_;\n-  const spv_opcode_table opcodeTable_;\n-  const spv_ext_inst_table extInstTable_;\n-};\n-\n // Encapsulates the data used during the assembly of a SPIR-V module.\n class AssemblyContext {\n  public:\ndiff --git a/test/UnitSPIRV.h b/test/UnitSPIRV.h\nindex aca53f8e..4686d257 100644\n--- a/test/UnitSPIRV.h\n+++ b/test/UnitSPIRV.h\n@@ -28,6 +28,7 @@\n #define _CODEPLAY_UNITBIL_H_\n \n #include <libspirv/libspirv.h>\n+#include "../source/assembly_grammar.h"\n #include "../source/binary.h"\n #include "../source/diagnostic.h"\n #include "../source/opcode.h"\n', 'commit_subject': 'Move AssemblyGrammar into its own source files', 'repo_name': 'KhronosGroup/SPIRV-Tools', 'committer': {'name': 'David Neto', 'email': '3f97edd74090acb1bf9368021b16e328eddf820c@google.com', 'time_sec': '1446490325', 'tz_offset': '-300', 'date': {'seconds': '1446490325'}}, 'commit_tree': '08dc3934b7255cd7cb9105abf06726c87f6b5e45', 'commit_message': 'Move AssemblyGrammar into its own source files\n', 'language_name': 'C++', 'license': 'apache-2.0', 'hunks': '@@ -36,7 +36,6 @@\n #include <libspirv/libspirv.h>\n #include "diagnostic.h"\n #include "instruction.h"\n-#include "operand.h"\n #include "text.h"\n \n namespace libspirv {\n@@ -102,86 +101,6 @@ inline int assumedBitWidth(const IdType& type) {\n   return 0;\n }\n \n-// Encapsulates the grammar to use for SPIR-V assembly.\n-// Contains methods to query for valid instructions and operands.\n-class AssemblyGrammar {\n- public:\n-  AssemblyGrammar(const spv_operand_table operand_table,\n-                  const spv_opcode_table opcode_table,\n-                  const spv_ext_inst_table ext_inst_table)\n-      : operandTable_(operand_table),\n-        opcodeTable_(opcode_table),\n-        extInstTable_(ext_inst_table) {}\n-\n-  // Returns true if the compilation_data has been initialized with valid data.\n-  bool isValid() const;\n-\n-  // Fills in the desc parameter with the information about the opcode\n-  // of the given name. Returns SPV_SUCCESS if the opcode was found, and\n-  // SPV_ERROR_INVALID_LOOKUP if the opcode does not exist.\n-  spv_result_t lookupOpcode(const char *name, spv_opcode_desc *desc) const;\n-\n-  // Fills in the desc parameter with the information about the opcode\n-  // of the valid. Returns SPV_SUCCESS if the opcode was found, and\n-  // SPV_ERROR_INVALID_LOOKUP if the opcode does not exist.\n-  spv_result_t lookupOpcode(Op opcode, spv_opcode_desc *desc) const;\n-\n-  // Fills in the desc parameter with the information about the given\n-  // operand. Returns SPV_SUCCESS if the operand was found, and\n-  // SPV_ERROR_INVALID_LOOKUP otherwise.\n-  spv_result_t lookupOperand(spv_operand_type_t type, const char *name,\n-                             size_t name_len, spv_operand_desc *desc) const;\n-\n-  // Fills in the desc parameter with the information about the given\n-  // operand. Returns SPV_SUCCESS if the operand was found, and\n-  // SPV_ERROR_INVALID_LOOKUP otherwise.\n-  spv_result_t lookupOperand(spv_operand_type_t type, uint32_t operand,\n-                             spv_operand_desc *desc) const;\n-\n-  // Parses a mask expression string for the given operand type.\n-  //\n-  // A mask expression is a sequence of one or more terms separated by \'|\',\n-  // where each term is a named enum value for a given type. No whitespace\n-  // is permitted.\n-  //\n-  // On success, the value is written to pValue, and SPV_SUCCESS is returend.\n-  // The operand type is defined by the type parameter, and the text to be\n-  // parsed is defined by the textValue parameter.\n-  spv_result_t parseMaskOperand(const spv_operand_type_t type,\n-                                const char *textValue, uint32_t *pValue) const;\n-\n-\n-  // Writes the extended operand with the given type and text to the *extInst\n-  // parameter.\n-  // Returns SPV_SUCCESS if the value could be found.\n-  spv_result_t lookupExtInst(spv_ext_inst_type_t type, const char *textValue,\n-                             spv_ext_inst_desc *extInst) const;\n-\n-  // Writes the extended operand with the given type and first encoded word\n-  // to the *extInst parameter.\n-  // Returns SPV_SUCCESS if the value could be found.\n-  spv_result_t lookupExtInst(spv_ext_inst_type_t type,\n-                             uint32_t firstWord,\n-                             spv_ext_inst_desc *extInst) const;\n-\n-  // Inserts the operands expected after the given typed mask onto the front\n-  // of the given pattern.\n-  //\n-  // Each set bit in the mask represents zero or more operand types that should\n-  // be prepended onto the pattern. Opearnds for a less significant bit always\n-  // appear before operands for a more significatn bit.\n-  //\n-  // If a set bit is unknown, then we assume it has no operands.\n-  void prependOperandTypesForMask(const spv_operand_type_t type,\n-                                  const uint32_t mask,\n-                                  spv_operand_pattern_t *pattern) const;\n-\n- private:\n-  const spv_operand_table operandTable_;\n-  const spv_opcode_table opcodeTable_;\n-  const spv_ext_inst_table extInstTable_;\n-};\n-\n // Encapsulates the data used during the assembly of a SPIR-V module.\n class AssemblyContext {\n  public:\n', 'addition_count': 0, 'deletion_count': 81, 'src_file': 'a/source/text_handler.h', 'tgt_file': 'b/source/text_handler.h', 'file_extension': '.h', 'before_file': '// Copyright (c) 2015-2016 The Khronos Group Inc.\n//\n// Licensed under the Apache License, Version 2.0 (the "License");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n//     http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an "AS IS" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\n#ifndef SOURCE_TEXT_HANDLER_H_\n#define SOURCE_TEXT_HANDLER_H_\n\n#include <iomanip>\n#include <set>\n#include <sstream>\n#include <string>\n#include <type_traits>\n#include <unordered_map>\n#include <utility>\n\n#include "source/diagnostic.h"\n#include "source/instruction.h"\n#include "source/text.h"\n#include "spirv-tools/libspirv.h"\n\nnamespace spvtools {\n\n// Structures\n\n// This is a lattice for tracking types.\n#include <libspirv/libspirv.h>\n#include "diagnostic.h"\n#include "instruction.h"\n#include "operand.h"\n#include "text.h"\n\nnamespace libspirv {\n\n// Contains ID type information that needs to be tracked across all Ids.\n// Bitwidth is only valid when type_class is kScalarIntegerType or\n// kScalarFloatType.\nstruct IdType {\n  uint32_t bitwidth;  // Safe to assume that we will not have > 2^32 bits.\n  bool isSigned;      // This is only significant if type_class is integral.\n  IdTypeClass type_class;\n};\n\n// Default equality operator for IdType. Tests if all members are the same.\ninline bool operator==(const IdType& first, const IdType& second) {\n  return (first.bitwidth == second.bitwidth) &&\n         (first.isSigned == second.isSigned) &&\n         (first.type_class == second.type_class);\n}\n\n// Tests whether any member of the IdTypes do not match.\ninline bool operator!=(const IdType& first, const IdType& second) {\n  return !(first == second);\n}\n\n// A value representing an unknown type.\nextern const IdType kUnknownType;\n\n// Returns true if the type is a scalar integer type.\ninline bool isScalarIntegral(const IdType& type) {\n  return type.type_class == IdTypeClass::kScalarIntegerType;\n}\n\n// Returns true if the type is a scalar floating point type.\ninline bool isScalarFloating(const IdType& type) {\n  return type.type_class == IdTypeClass::kScalarFloatType;\n}\n\n// Returns the number of bits in the type.\n// This is only valid for bottom, scalar integer, and scalar floating\n// classes.  For bottom, assume 32 bits.\ninline int assumedBitWidth(const IdType& type) {\n  switch (type.type_class) {\n    case IdTypeClass::kBottom:\n      return 32;\n    case IdTypeClass::kScalarIntegerType:\n    case IdTypeClass::kScalarFloatType:\n      return type.bitwidth;\n    default:\n      break;\n  }\n  // We don\'t care about this case.\n  return 0;\n}\n\n// A templated class with a static member function Clamp, where Clamp\n// sets a referenced value of type T to 0 if T is an unsigned\n// integer type, and returns true if it modified the referenced\n// value.\ntemplate <typename T, typename = void>\nclass ClampToZeroIfUnsignedType {\n public:\n  return 0;\n}\n\n// Encapsulates the grammar to use for SPIR-V assembly.\n// Contains methods to query for valid instructions and operands.\nclass AssemblyGrammar {\n public:\n  AssemblyGrammar(const spv_operand_table operand_table,\n                  const spv_opcode_table opcode_table,\n                  const spv_ext_inst_table ext_inst_table)\n      : operandTable_(operand_table),\n        opcodeTable_(opcode_table),\n        extInstTable_(ext_inst_table) {}\n\n  // Returns true if the compilation_data has been initialized with valid data.\n  bool isValid() const;\n\n  // Fills in the desc parameter with the information about the opcode\n  // of the given name. Returns SPV_SUCCESS if the opcode was found, and\n  // SPV_ERROR_INVALID_LOOKUP if the opcode does not exist.\n  spv_result_t lookupOpcode(const char *name, spv_opcode_desc *desc) const;\n\n  // Fills in the desc parameter with the information about the opcode\n  // of the valid. Returns SPV_SUCCESS if the opcode was found, and\n  // SPV_ERROR_INVALID_LOOKUP if the opcode does not exist.\n  spv_result_t lookupOpcode(Op opcode, spv_opcode_desc *desc) const;\n\n  // Fills in the desc parameter with the information about the given\n  // operand. Returns SPV_SUCCESS if the operand was found, and\n  // SPV_ERROR_INVALID_LOOKUP otherwise.\n  spv_result_t lookupOperand(spv_operand_type_t type, const char *name,\n                             size_t name_len, spv_operand_desc *desc) const;\n\n  // Fills in the desc parameter with the information about the given\n  // operand. Returns SPV_SUCCESS if the operand was found, and\n  // SPV_ERROR_INVALID_LOOKUP otherwise.\n  spv_result_t lookupOperand(spv_operand_type_t type, uint32_t operand,\n                             spv_operand_desc *desc) const;\n\n  // Parses a mask expression string for the given operand type.\n  //\n  // A mask expression is a sequence of one or more terms separated by \'|\',\n  // where each term is a named enum value for a given type. No whitespace\n  // is permitted.\n  //\n  // On success, the value is written to pValue, and SPV_SUCCESS is returend.\n  // The operand type is defined by the type parameter, and the text to be\n  // parsed is defined by the textValue parameter.\n  spv_result_t parseMaskOperand(const spv_operand_type_t type,\n                                const char *textValue, uint32_t *pValue) const;\n\n\n  // Writes the extended operand with the given type and text to the *extInst\n  // parameter.\n  // Returns SPV_SUCCESS if the value could be found.\n  spv_result_t lookupExtInst(spv_ext_inst_type_t type, const char *textValue,\n                             spv_ext_inst_desc *extInst) const;\n\n  // Writes the extended operand with the given type and first encoded word\n  // to the *extInst parameter.\n  // Returns SPV_SUCCESS if the value could be found.\n  spv_result_t lookupExtInst(spv_ext_inst_type_t type,\n                             uint32_t firstWord,\n                             spv_ext_inst_desc *extInst) const;\n\n  // Inserts the operands expected after the given typed mask onto the front\n  // of the given pattern.\n  //\n  // Each set bit in the mask represents zero or more operand types that should\n  // be prepended onto the pattern. Opearnds for a less significant bit always\n  // appear before operands for a more significatn bit.\n  //\n  // If a set bit is unknown, then we assume it has no operands.\n  void prependOperandTypesForMask(const spv_operand_type_t type,\n                                  const uint32_t mask,\n                                  spv_operand_pattern_t *pattern) const;\n\n private:\n  const spv_operand_table operandTable_;\n  const spv_opcode_table opcodeTable_;\n  const spv_ext_inst_table extInstTable_;\n};\n\n// Encapsulates the data used during the assembly of a SPIR-V module.\nclass AssemblyContext {\n public:\ntemplate <typename T>\nclass ClampToZeroIfUnsignedType<\n    T, typename std::enable_if<std::is_unsigned<T>::value>::type> {\n public:\n  static bool Clamp(T* value_pointer) {\n    if (*value_pointer) {\n      *value_pointer = 0;\n      return true;\n    }\n    return false;\n  }\n};\n\n// Encapsulates the data used during the assembly of a SPIR-V module.\nclass AssemblyContext {\n public:\n  AssemblyContext(spv_text text, const MessageConsumer& consumer,\n                  std::set<uint32_t>&& ids_to_preserve = std::set<uint32_t>())\n      : current_position_({}),\n        consumer_(consumer),\n        text_(text),\n        bound_(1),\n        next_id_(1),\n        ids_to_preserve_(std::move(ids_to_preserve)) {}\n\n  // Assigns a new integer value to the given text ID, or returns the previously\n  // assigned integer value if the ID has been seen before.\n  uint32_t spvNamedIdAssignOrGet(const char* textValue);\n\n  // Returns the largest largest numeric ID that has been assigned.\n  uint32_t getBound() const;\n\n  // Advances position to point to the next word in the input stream.\n  // Returns SPV_SUCCESS on success.\n  spv_result_t advance();\n\n  // Sets word to the next word in the input text. Fills next_position with\n  // the next location past the end of the word.\n  spv_result_t getWord(std::string* word, spv_position next_position);\n\n  // Returns true if the next word in the input is the start of a new Opcode.\n  bool startsWithOp();\n\n  // Returns true if the next word in the input is the start of a new\n  // instruction.\n  bool isStartOfNewInst();\n\n  // Returns a diagnostic object initialized with current position in the input\n  // stream, and for the given error code. Any data written to this object will\n  // show up in pDiagnsotic on destruction.\n  DiagnosticStream diagnostic(spv_result_t error) {\n    return DiagnosticStream(current_position_, consumer_, "", error);\n  }\n\n  // Returns a diagnostic object with the default assembly error code.\n  DiagnosticStream diagnostic() {\n    // The default failure for assembly is invalid text.\n    return diagnostic(SPV_ERROR_INVALID_TEXT);\n  }\n\n  // Returns then next character in the input stream.\n  char peek() const;\n\n  // Returns true if there is more text in the input stream.\n  bool hasText() const;\n\n  // Seeks the input stream forward by \'size\' characters.\n  void seekForward(uint32_t size);\n\n  // Sets the current position in the input stream to the given position.\n  void setPosition(const spv_position_t& newPosition) {\n    current_position_ = newPosition;\n  }\n\n  // Returns the current position in the input stream.\n  const spv_position_t& position() const { return current_position_; }\n\n  // Appends the given 32-bit value to the given instruction.\n  // Returns SPV_SUCCESS if the value could be correctly inserted in the\n  // instruction.\n  spv_result_t binaryEncodeU32(const uint32_t value, spv_instruction_t* pInst);\n\n  // Appends the given string to the given instruction.\n  // Returns SPV_SUCCESS if the value could be correctly inserted in the\n  // instruction.\n  spv_result_t binaryEncodeString(const char* value, spv_instruction_t* pInst);\n\n  // Appends the given numeric literal to the given instruction.\n  // Validates and respects the bitwidth supplied in the IdType argument.\n  // If the type is of class kBottom the value will be encoded as a\n  // 32-bit integer.\n  // Returns SPV_SUCCESS if the value could be correctly added to the\n  // instruction.  Returns the given error code on failure, and emits\n  // a diagnostic if that error code is not SPV_FAILED_MATCH.\n  spv_result_t binaryEncodeNumericLiteral(const char* numeric_literal,\n                                          spv_result_t error_code,\n                                          const IdType& type,\n                                          spv_instruction_t* pInst);\n\n  // Returns the IdType associated with this type-generating value.\n  // If the type has not been previously recorded with recordTypeDefinition,\n  // kUnknownType  will be returned.\n  IdType getTypeOfTypeGeneratingValue(uint32_t value) const;\n\n  // Returns the IdType that represents the return value of this Value\n  // generating instruction.\n  // If the value has not been recorded with recordTypeIdForValue, or the type\n  // could not be determined kUnknownType will be returned.\n  IdType getTypeOfValueInstruction(uint32_t value) const;\n\n  // Tracks the type-defining instruction. The result of the tracking can\n  // later be queried using getValueType.\n  // pInst is expected to be completely filled in by the time this instruction\n  // is called.\n  // Returns SPV_SUCCESS on success, or SPV_ERROR_INVALID_VALUE on error.\n  spv_result_t recordTypeDefinition(const spv_instruction_t* pInst);\n\n  // Tracks the relationship between the value and its type.\n  spv_result_t recordTypeIdForValue(uint32_t value, uint32_t type);\n\n  // Records the given Id as being the import of the given extended instruction\n  // type.\n  spv_result_t recordIdAsExtInstImport(uint32_t id, spv_ext_inst_type_t type);\n\n  // Returns the extended instruction type corresponding to the import with\n  // the given Id, if it exists.  Returns SPV_EXT_INST_TYPE_NONE if the\n  // id is not the id for an extended instruction type.\n  spv_ext_inst_type_t getExtInstTypeForId(uint32_t id) const;\n\n  // Returns a set consisting of each ID generated by spvNamedIdAssignOrGet from\n  // a numeric ID text representation. For example, generated from "%12" but not\n  // from "%foo".\n  std::set<uint32_t> GetNumericIds() const;\n\n private:\n  // Maps ID names to their corresponding numerical ids.\n  using spv_named_id_table = std::unordered_map<std::string, uint32_t>;\n  // Maps type-defining IDs to their IdType.\n  using spv_id_to_type_map = std::unordered_map<uint32_t, IdType>;\n  // Maps Ids to the id of their type.\n  using spv_id_to_type_id = std::unordered_map<uint32_t, uint32_t>;\n\n  spv_named_id_table named_ids_;\n  spv_id_to_type_map types_;\n  spv_id_to_type_id value_types_;\n  // Maps an extended instruction import Id to the extended instruction type.\n  std::unordered_map<uint32_t, spv_ext_inst_type_t> import_id_to_ext_inst_type_;\n  spv_position_t current_position_;\n  MessageConsumer consumer_;\n  spv_text text_;\n  uint32_t bound_;\n  uint32_t next_id_;\n  std::set<uint32_t> ids_to_preserve_;\n};\n\n}  // namespace spvtools\n\n#endif  // SOURCE_TEXT_HANDLER_H_\n', 'message': 'Move AssemblyGrammar into its own source files\n', 'author_name': 'David Neto', 'lang': 'h'}