| 1129 | // above. |
| 1130 | |
| 1131 | class InstructionParser { |
| 1132 | //===----------------------------------------------------------------------===// |
| 1133 | // Helper for Operation Creation and Result Handling |
| 1134 | //===----------------------------------------------------------------------===// |
| 1135 | /// Creates an operation using OperationState and pushes its results to the |
| 1136 | /// valueIndexList. The numResultsForValueIndex parameter controls how many |
| 1137 | /// results are added to valueIndexList. |
| 1138 | static LogicalResult createOperationGeneric( |
| 1139 | OpBuilder &builder, Location loc, StringRef opNameStr, |
| 1140 | ArrayRef<Type> resultTypes, ArrayRef<Value> operands, |
| 1141 | ArrayRef<NamedAttribute> attributes, std::vector<Value> &valueIndexList, |
| 1142 | SmallVectorImpl<std::unique_ptr<Region>> &parsedRegions, |
| 1143 | std::optional<size_t> numResultsForValueIndex = std::nullopt) { |
| 1144 | OperationState state(loc, opNameStr, operands, resultTypes, attributes); |
| 1145 | |
| 1146 | // Add parsed regions to the operation state. |
| 1147 | for (auto ®ion_ptr : parsedRegions) |
| 1148 | state.addRegion(std::move(region_ptr)); |
| 1149 | |
| 1150 | Operation *op = builder.create(state); |
| 1151 | // Operation creation using OperationState can fail if verification fails. |
| 1152 | // Emit an error noting the failure. |
| 1153 | if (!op) |
| 1154 | return ::emitError(loc) << "failed to create operation '" << opNameStr |
| 1155 | << "'due to verification error."; |
| 1156 | // Add results to the value index list. Only add numResultsForValueIndex |
| 1157 | // results if specified (for backward compat with older bytecode that |
| 1158 | // didn't have newer results). |
| 1159 | size_t numToAdd = numResultsForValueIndex.value_or(op->getNumResults()); |
| 1160 | for (size_t i = 0; i < numToAdd; ++i) |
| 1161 | valueIndexList.push_back(op->getResult(i)); |
| 1162 | |
| 1163 | return success(); |
| 1164 | } |
| 1165 | |
| 1166 | /// Parses operand indices and returns the corresponding Values from the |
| 1167 | /// valueIndexList. If numOperandsToRead is std::nullopt, it first reads the |
| 1168 | /// number of operands as a VarInt. Otherwise, it uses the provided count. |
| 1169 | static LogicalResult |
| 1170 | parseOperands(EncodingReader &reader, Location loc, |
| 1171 | ArrayRef<Value> valueIndexList, SmallVectorImpl<Value> &results, |
| 1172 | std::optional<uint64_t> numOperandsToRead = std::nullopt) { |
| 1173 | uint64_t numOperands; |
| 1174 | if (numOperandsToRead.has_value()) |
| 1175 | numOperands = *numOperandsToRead; |
| 1176 | else if (failed(reader.readVarInt( |
| 1177 | numOperands, std::numeric_limits<uint32_t>::max() - 1))) |
| 1178 | return reader.emitError() << "failed to read operand count"; |
| 1179 | |
| 1180 | results.reserve(numOperands); |
| 1181 | for (uint64_t i = 0; i < numOperands; ++i) { |
| 1182 | uint64_t operandIdx; |
| 1183 | if (failed(reader.readVarInt(operandIdx))) |
| 1184 | return reader.emitError() << "failed to read operand index " << i; |
| 1185 | if (operandIdx >= valueIndexList.size()) |
| 1186 | return reader.emitError() |
| 1187 | << "operand index " << operandIdx |
| 1188 | << " out of bounds (size=" << valueIndexList.size() |
nothing calls this directly
no outgoing calls
no test coverage detected