| 468 | } |
| 469 | |
| 470 | spv_result_t Parser::parseOperand(size_t inst_offset, |
| 471 | spv_parsed_instruction_t* inst, |
| 472 | const spv_operand_type_t type, |
| 473 | std::vector<uint32_t>* words, |
| 474 | std::vector<spv_parsed_operand_t>* operands, |
| 475 | spv_operand_pattern_t* expected_operands) { |
| 476 | const spv::Op opcode = static_cast<spv::Op>(inst->opcode); |
| 477 | // We'll fill in this result as we go along. |
| 478 | spv_parsed_operand_t parsed_operand; |
| 479 | parsed_operand.offset = uint16_t(_.word_index - inst_offset); |
| 480 | // Most operands occupy one word. This might be be adjusted later. |
| 481 | parsed_operand.num_words = 1; |
| 482 | // The type argument is the one used by the grammar to parse the instruction. |
| 483 | // But it can exposes internal parser details such as whether an operand is |
| 484 | // optional or actually represents a variable-length sequence of operands. |
| 485 | // The resulting type should be adjusted to avoid those internal details. |
| 486 | // In most cases, the resulting operand type is the same as the grammar type. |
| 487 | parsed_operand.type = type; |
| 488 | |
| 489 | // Assume non-numeric values. This will be updated for literal numbers. |
| 490 | parsed_operand.number_kind = SPV_NUMBER_NONE; |
| 491 | parsed_operand.number_bit_width = 0; |
| 492 | |
| 493 | if (_.word_index >= _.num_words) |
| 494 | return exhaustedInputDiagnostic(inst_offset, opcode, type); |
| 495 | |
| 496 | const uint32_t word = peek(); |
| 497 | |
| 498 | // Do the words in this operand have to be converted to native endianness? |
| 499 | // True for all but literal strings. |
| 500 | bool convert_operand_endianness = true; |
| 501 | |
| 502 | switch (type) { |
| 503 | case SPV_OPERAND_TYPE_TYPE_ID: |
| 504 | if (!word) |
| 505 | return diagnostic(SPV_ERROR_INVALID_ID) << "Error: Type Id is 0"; |
| 506 | inst->type_id = word; |
| 507 | break; |
| 508 | |
| 509 | case SPV_OPERAND_TYPE_RESULT_ID: |
| 510 | if (!word) |
| 511 | return diagnostic(SPV_ERROR_INVALID_ID) << "Error: Result Id is 0"; |
| 512 | inst->result_id = word; |
| 513 | // Save the result ID to type ID mapping. |
| 514 | // In the grammar, type ID always appears before result ID. |
| 515 | if (_.id_to_type_id.find(inst->result_id) != _.id_to_type_id.end()) |
| 516 | return diagnostic(SPV_ERROR_INVALID_ID) |
| 517 | << "Id " << inst->result_id << " is defined more than once"; |
| 518 | // Record it. |
| 519 | // A regular value maps to its type. Some instructions (e.g. OpLabel) |
| 520 | // have no type Id, and will map to 0. The result Id for a |
| 521 | // type-generating instruction (e.g. OpTypeInt) maps to itself. |
| 522 | _.id_to_type_id[inst->result_id] = |
| 523 | spvOpcodeGeneratesType(opcode) ? inst->result_id : inst->type_id; |
| 524 | break; |
| 525 | |
| 526 | case SPV_OPERAND_TYPE_ID: |
| 527 | case SPV_OPERAND_TYPE_OPTIONAL_ID: |
nothing calls this directly
no test coverage detected