blob: d5ba7eb726cbebfcc340634d051428e8e2affc79 [file] [log] [blame]
Andrew Woloszyn71fc0552015-09-24 10:26:51 -04001// Copyright (c) 2015 The Khronos Group Inc.
2//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and/or associated documentation files (the
5// "Materials"), to deal in the Materials without restriction, including
6// without limitation the rights to use, copy, modify, merge, publish,
7// distribute, sublicense, and/or sell copies of the Materials, and to
8// permit persons to whom the Materials are furnished to do so, subject to
9// the following conditions:
10//
11// The above copyright notice and this permission notice shall be included
12// in all copies or substantial portions of the Materials.
13//
14// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
15// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
16// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
17// https://www.khronos.org/registry/
18//
19// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
26
27#ifndef _LIBSPIRV_UTIL_TEXT_HANDLER_H_
28#define _LIBSPIRV_UTIL_TEXT_HANDLER_H_
29
30#include <libspirv/libspirv.h>
31#include <unordered_map>
32
33#include "diagnostic.h"
David Netob5dc8fc2015-10-06 16:22:00 -040034#include "instruction.h"
Andrew Woloszyn71fc0552015-09-24 10:26:51 -040035#include "operand.h"
36
37namespace libspirv {
38// Structures
39
Andrew Woloszyn71fc0552015-09-24 10:26:51 -040040// This is a lattice for tracking types.
41enum class IdTypeClass {
42 kBottom, // We have no information yet.
43 kScalarIntegerType,
44 kScalarFloatType,
45 kOtherType
46};
47
48
49// Contains ID type information that needs to be tracked across all Ids.
50// Bitwidth is only valid when type_class is kScalarIntegerType or
51// kScalarFloatType.
52struct IdType {
53 uint32_t bitwidth; // Safe to assume that we will not have > 2^32 bits.
54 IdTypeClass type_class;
55};
56
57// Encapsulates the grammar to use for SPIR-V assembly.
58// Contains methods to query for valid instructions and operands.
59class AssemblyGrammar {
60 public:
61 AssemblyGrammar(const spv_operand_table operand_table,
62 const spv_opcode_table opcode_table,
63 const spv_ext_inst_table ext_inst_table)
64 : operandTable_(operand_table),
65 opcodeTable_(opcode_table),
66 extInstTable_(ext_inst_table) {}
67
68 // Returns true if the compilation_data has been initialized with valid data.
69 bool isValid() const;
70
71 // Fills in the desc parameter with the information about the opcode
72 // of the given name. Returns SPV_SUCCESS if the opcode was found, and
73 // SPV_ERROR_INVALID_LOOKUP if the opcode does not exist.
74 spv_result_t lookupOpcode(const char *name, spv_opcode_desc *desc) const;
75
76 // Fills in the desc parameter with the information about the given
77 // operand. Returns SPV_SUCCESS if the operand was found, and
78 // SPV_ERROR_INVALID_LOOKUP otherwise.
79 spv_result_t lookupOperand(spv_operand_type_t type, const char *name,
80 size_t name_len, spv_operand_desc *desc) const;
81
82 // Parses a mask expression string for the given operand type.
83 //
84 // A mask expression is a sequence of one or more terms separated by '|',
85 // where each term is a named enum value for a given type. No whitespace
86 // is permitted.
87 //
88 // On success, the value is written to pValue, and SPV_SUCCESS is returend.
89 // The operand type is defined by the type parameter, and the text to be
90 // parsed is defined by the textValue parameter.
91 spv_result_t parseMaskOperand(const spv_operand_type_t type,
92 const char *textValue, uint32_t *pValue) const;
93
94
95 // Writes the extended operand with the given type and text to the *extInst
96 // parameter.
97 // Returns SPV_SUCCESS if the value could be found.
98 spv_result_t lookupExtInst(spv_ext_inst_type_t type, const char *textValue,
99 spv_ext_inst_desc *extInst) const;
100
101 // Inserts the operands expected after the given typed mask onto the front
102 // of the given pattern.
103 //
104 // Each set bit in the mask represents zero or more operand types that should
105 // be prepended onto the pattern. Opearnds for a less significant bit always
106 // appear before operands for a more significatn bit.
107 //
108 // If a set bit is unknown, then we assume it has no operands.
109 void prependOperandTypesForMask(const spv_operand_type_t type,
110 const uint32_t mask,
111 spv_operand_pattern_t *pattern) const;
112
113 private:
114 const spv_operand_table operandTable_;
115 const spv_opcode_table opcodeTable_;
116 const spv_ext_inst_table extInstTable_;
117};
118
119// Encapsulates the data used during the assembly of a SPIR-V module.
120class AssemblyContext {
121 public:
122 AssemblyContext(spv_text text, spv_diagnostic *diagnostic)
123 : current_position_({}),
124 pDiagnostic_(diagnostic),
125 text_(text),
126 bound_(1) {}
127
128 // Assigns a new integer value to the given text ID, or returns the previously
129 // assigned integer value if the ID has been seen before.
130 uint32_t spvNamedIdAssignOrGet(const char *textValue);
131
132 // Returns the largest largest numeric ID that has been assigned.
133 uint32_t getBound() const;
134
135 // Advances position to point to the next word in the input stream.
136 // Returns SPV_SUCCESS on success.
137 spv_result_t advance();
138
139 // Sets word to the next word in the input text. Fills endPosition with
140 // the next location past the end of the word.
141 spv_result_t getWord(std::string &word, spv_position endPosition);
142
143 // Returns the next word in the input stream. It is invalid to call this
144 // method if position has been set to a location in the stream that does not
145 // exist. If there are no subsequent words, the empty string will be returend.
146 std::string getWord() const;
147
148 // Returns true if the next word in the input is the start of a new Opcode.
149 bool startsWithOp();
150
151 // Returns true if the next word in the input is the start of a new
152 // instruction.
153 bool isStartOfNewInst();
154
155 // Returns a diagnostic object initialized with current position in the input
156 // stream. Any data written to this object will show up in pDiagnsotic on
157 // destruction.
158 DiagnosticStream diagnostic() {
159 return DiagnosticStream(&current_position_, pDiagnostic_);
160 }
161
162 // Returns then next characted in the input stream.
163 char peek() const;
164
165 // Returns true if there is more text in the input stream.
166 bool hasText() const;
167
168 // Seeks the input stream forward by 'size' characters.
169 void seekForward(uint32_t size);
170
171 // Sets the current position in the input stream to the given position.
172 void setPosition(const spv_position_t &newPosition) {
173 current_position_ = newPosition;
174 }
175
176 // Returns the current position in the input stream.
177 const spv_position_t &position() const { return current_position_; }
178
179 // Appends the given 32-bit value to the given instruction.
180 // Returns SPV_SUCCESS if the value could be correctly inserted in the the
181 // instruction.
182 spv_result_t binaryEncodeU32(const uint32_t value, spv_instruction_t *pInst);
183 // Appends the given 64-bit value to the given instruction.
184 // Returns SPV_SUCCESS if the value could be correctly inserted in the the
185 // instruction.
186 spv_result_t binaryEncodeU64(const uint64_t value, spv_instruction_t *pInst);
187 // Appends the given string to the given instruction.
188 // Returns SPV_SUCCESS if the value could be correctly inserted in the the
189 // instruction.
190 spv_result_t binaryEncodeString(const char *value, spv_instruction_t *pInst);
191
192 private:
193 // Maps ID names to their corresponding numerical ids.
194 using spv_named_id_table = std::unordered_map<std::string, uint32_t>;
195 // Maps type-defining IDs to their IdType.
196 using spv_id_to_type_map = std::unordered_map<uint32_t, IdType>;
197 // Maps Ids to the id of their type.
198 using spv_id_to_type_id = std::unordered_map<uint32_t, uint32_t>;
199
200 spv_named_id_table named_ids_;
201 spv_id_to_type_map types_;
202 spv_id_to_type_id value_types_;
203 spv_position_t current_position_;
204 spv_diagnostic *pDiagnostic_;
205 spv_text text_;
206 uint32_t bound_;
207};
208}
209#endif // _LIBSPIRV_UTIL_TEXT_HANDLER_H_
210