Helper function to parse a given block during deserialization.
| 1194 | |
| 1195 | /// Helper function to parse a given block during deserialization. |
| 1196 | static LogicalResult |
| 1197 | parseBlock(EncodingReader &reader, OpBuilder &builder, Location loc, |
| 1198 | Block &targetBlock, std::vector<Value> &valueIndexList, |
| 1199 | ArrayRef<ArrayRef<uint8_t>> constants, LazyTypeTable &types, |
| 1200 | DenseElementsAttrCache &constCache, |
| 1201 | DebugInfoReader::Iterator &diIterator, MLIRContext &context, |
| 1202 | const BytecodeVersion &bytecodeVersion) { |
| 1203 | // Read number of block arguments |
| 1204 | uint64_t numBlockArgs; |
| 1205 | if (failed(reader.readVarInt(numBlockArgs))) |
| 1206 | return reader.emitError() << "failed to read block argument count."; |
| 1207 | |
| 1208 | // Record the current size of valueIndexList. Block arguments and operations |
| 1209 | // defined within this block will be added, and then the list will be |
| 1210 | // resized back to this original size upon exiting the block. |
| 1211 | size_t originalValueIndexListSize = valueIndexList.size(); |
| 1212 | |
| 1213 | // Read argument types and create block arguments in the targetBlock. |
| 1214 | for (uint64_t i = 0; i < numBlockArgs; ++i) { |
| 1215 | Type argType = types.readAndGetType(reader); |
| 1216 | if (!argType) |
| 1217 | return reader.emitError() |
| 1218 | << "failed to read block argument type: " << i; |
| 1219 | Value arg = targetBlock.addArgument(argType, loc); |
| 1220 | valueIndexList.push_back(arg); |
| 1221 | } |
| 1222 | |
| 1223 | // Read number of operations in the block. |
| 1224 | uint64_t numOps; |
| 1225 | if (failed(reader.readVarInt(numOps))) |
| 1226 | return reader.emitError() << "failed to read block operation count."; |
| 1227 | |
| 1228 | // Set insertion point to the end of the targetBlock for parsing operations. |
| 1229 | OpBuilder::InsertionGuard guard(builder); |
| 1230 | builder.setInsertionPointToEnd(&targetBlock); |
| 1231 | |
| 1232 | // Parse operations in the block using the valueIndexList. |
| 1233 | for (uint64_t i = 0; i < numOps; ++i) { |
| 1234 | if (failed(InstructionParser::parseOperation( |
| 1235 | reader, builder, valueIndexList, constants, types, constCache, |
| 1236 | diIterator, context, bytecodeVersion))) |
| 1237 | return reader.emitError() |
| 1238 | << "failed to parse operation " << i << " in block."; |
| 1239 | } |
| 1240 | |
| 1241 | // Validate block structure: ensure block has terminator. |
| 1242 | if (!targetBlock.empty()) { |
| 1243 | Operation *lastOp = &targetBlock.back(); |
| 1244 | if (!lastOp->hasTrait<OpTrait::IsTerminator>()) |
| 1245 | return reader.emitError() |
| 1246 | << "invalid block structure: block is expected to have a " |
| 1247 | "terminator " |
| 1248 | << "operation, but the last operation '" << lastOp->getName() |
| 1249 | << "' is not a terminator."; |
| 1250 | } else { |
| 1251 | return reader.emitError() |
| 1252 | << "invalid block structure: block is expected to have a " |
| 1253 | "terminator operation, but it is empty"; |
nothing calls this directly
no test coverage detected