| 228 | } |
| 229 | |
| 230 | bool TransformationAddFunction::TryToAddFunction( |
| 231 | opt::IRContext* ir_context) const { |
| 232 | // This function returns false if |message_.instruction| was not well-formed |
| 233 | // enough to actually create a function and add it to |ir_context|. |
| 234 | |
| 235 | // A function must have at least some instructions. |
| 236 | if (message_.instruction().empty()) { |
| 237 | return false; |
| 238 | } |
| 239 | |
| 240 | // A function must start with OpFunction. |
| 241 | auto function_begin = message_.instruction(0); |
| 242 | if (spv::Op(function_begin.opcode()) != spv::Op::OpFunction) { |
| 243 | return false; |
| 244 | } |
| 245 | |
| 246 | // Make a function, headed by the OpFunction instruction. |
| 247 | std::unique_ptr<opt::Function> new_function = MakeUnique<opt::Function>( |
| 248 | InstructionFromMessage(ir_context, function_begin)); |
| 249 | |
| 250 | // Keeps track of which instruction protobuf message we are currently |
| 251 | // considering. |
| 252 | uint32_t instruction_index = 1; |
| 253 | const auto num_instructions = |
| 254 | static_cast<uint32_t>(message_.instruction().size()); |
| 255 | |
| 256 | // Iterate through all function parameter instructions, adding parameters to |
| 257 | // the new function. |
| 258 | while (instruction_index < num_instructions && |
| 259 | spv::Op(message_.instruction(instruction_index).opcode()) == |
| 260 | spv::Op::OpFunctionParameter) { |
| 261 | new_function->AddParameter(InstructionFromMessage( |
| 262 | ir_context, message_.instruction(instruction_index))); |
| 263 | instruction_index++; |
| 264 | } |
| 265 | |
| 266 | // After the parameters, there needs to be a label. |
| 267 | if (instruction_index == num_instructions || |
| 268 | spv::Op(message_.instruction(instruction_index).opcode()) != |
| 269 | spv::Op::OpLabel) { |
| 270 | return false; |
| 271 | } |
| 272 | |
| 273 | // Iterate through the instructions block by block until the end of the |
| 274 | // function is reached. |
| 275 | while (instruction_index < num_instructions && |
| 276 | spv::Op(message_.instruction(instruction_index).opcode()) != |
| 277 | spv::Op::OpFunctionEnd) { |
| 278 | // Invariant: we should always be at a label instruction at this point. |
| 279 | assert(spv::Op(message_.instruction(instruction_index).opcode()) == |
| 280 | spv::Op::OpLabel); |
| 281 | |
| 282 | // Make a basic block using the label instruction. |
| 283 | std::unique_ptr<opt::BasicBlock> block = |
| 284 | MakeUnique<opt::BasicBlock>(InstructionFromMessage( |
| 285 | ir_context, message_.instruction(instruction_index))); |
| 286 | |
| 287 | // Consider successive instructions until we hit another label or the end |
no test coverage detected