MARK-V decoder supports extended instructions

This commit is contained in:
Andrey Tuganov 2017-06-30 14:59:24 -04:00 committed by David Neto
parent 826d968a63
commit abc6f5a672
2 changed files with 64 additions and 7 deletions

View File

@ -38,6 +38,7 @@
#include "diagnostic.h" #include "diagnostic.h"
#include "enum_string_mapping.h" #include "enum_string_mapping.h"
#include "extensions.h" #include "extensions.h"
#include "ext_inst.h"
#include "instruction.h" #include "instruction.h"
#include "opcode.h" #include "opcode.h"
#include "operand.h" #include "operand.h"
@ -161,6 +162,8 @@ size_t GetOperandVariableWidthChunkLength(spv_operand_type_t type) {
case SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS: case SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS:
case SPV_OPERAND_TYPE_SELECTION_CONTROL: case SPV_OPERAND_TYPE_SELECTION_CONTROL:
return 4; return 4;
case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER:
return 6;
default: default:
return 0; return 0;
} }
@ -674,6 +677,8 @@ class MarkvDecoder : public MarkvCodecBase {
std::unordered_map<uint32_t, uint32_t> id_to_type_id_; std::unordered_map<uint32_t, uint32_t> id_to_type_id_;
// Maps a type ID to its number type description. // Maps a type ID to its number type description.
std::unordered_map<uint32_t, NumberType> type_id_to_number_type_info_; std::unordered_map<uint32_t, NumberType> type_id_to_number_type_info_;
// Maps an ExtInstImport id to the extended instruction type.
std::unordered_map<uint32_t, spv_ext_inst_type_t> import_id_to_ext_inst_type_;
}; };
void MarkvEncoder::EncodeLiteralNumber(const Instruction& instruction, void MarkvEncoder::EncodeLiteralNumber(const Instruction& instruction,
@ -1028,16 +1033,35 @@ spv_result_t MarkvDecoder::DecodeOperand(
parsed_operand.type = SPV_OPERAND_TYPE_ID; parsed_operand.type = SPV_OPERAND_TYPE_ID;
if (opcode == SpvOpExtInst && parsed_operand.offset == 3) { if (opcode == SpvOpExtInst && parsed_operand.offset == 3) {
// TODO(atgoo@github.com) Work in progress. // The current word is the extended instruction set id.
assert(0 && "Not implemented"); // Set the extended instruction set type for the current instruction.
auto ext_inst_type_iter = import_id_to_ext_inst_type_.find(id);
if (ext_inst_type_iter == import_id_to_ext_inst_type_.end()) {
return vstate_.diag(SPV_ERROR_INVALID_ID)
<< "OpExtInst set id " << id
<< " does not reference an OpExtInstImport result Id";
}
inst->ext_inst_type = ext_inst_type_iter->second;
} }
} }
break; break;
} }
case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER: { case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER: {
// TODO(atgoo@github.com) Work in progress. uint32_t word = 0;
assert(0 && "Not implemented"); if (!DecodeOperandWord(type, &word))
return vstate_.diag(SPV_ERROR_INVALID_BINARY)
<< "Failed to read enum";
spirv_.push_back(word);
assert(SpvOpExtInst == opcode);
assert(inst->ext_inst_type != SPV_EXT_INST_TYPE_NONE);
spv_ext_inst_desc ext_inst;
if (grammar_.lookupExtInst(inst->ext_inst_type, word, &ext_inst))
return vstate_.diag(SPV_ERROR_INVALID_BINARY)
<< "Invalid extended instruction number: " << word;
spvPushOperandTypes(ext_inst->operandTypes, expected_operands);
break; break;
} }
@ -1130,8 +1154,22 @@ spv_result_t MarkvDecoder::DecodeOperand(
std::memcpy(&spirv_[first_word_index], str.data(), str.size()); std::memcpy(&spirv_[first_word_index], str.data(), str.size());
if (SpvOpExtInstImport == opcode) { if (SpvOpExtInstImport == opcode) {
// TODO(atgoo@github.com) Work in progress. // Record the extended instruction type for the ID for this import.
assert(0 && "Not implemented"); // There is only one string literal argument to OpExtInstImport,
// so it's sufficient to guard this just on the opcode.
const spv_ext_inst_type_t ext_inst_type =
spvExtInstImportTypeGet(str.data());
if (SPV_EXT_INST_TYPE_NONE == ext_inst_type) {
return vstate_.diag(SPV_ERROR_INVALID_BINARY)
<< "Invalid extended instruction import '" << str.data() << "'";
}
// We must have parsed a valid result ID. It's a condition
// of the grammar, and we only accept non-zero result Ids.
assert(inst->result_id);
const bool inserted = import_id_to_ext_inst_type_.emplace(
inst->result_id, ext_inst_type).second;
(void)inserted;
assert(inserted);
} }
break; break;
} }
@ -1327,7 +1365,6 @@ spv_result_t MarkvDecoder::DecodeInstruction(spv_parsed_instruction_t* inst) {
spirv_[instruction_offset] = spirv_[instruction_offset] =
spvOpcodeMake(inst->num_words, SpvOp(inst->opcode)); spvOpcodeMake(inst->num_words, SpvOp(inst->opcode));
assert(inst->num_words == std::accumulate( assert(inst->num_words == std::accumulate(
parsed_operands_.begin(), parsed_operands_.end(), 1, parsed_operands_.begin(), parsed_operands_.end(), 1,
[](size_t num_words, const spv_parsed_operand_t& operand) { [](size_t num_words, const spv_parsed_operand_t& operand) {

View File

@ -410,4 +410,24 @@ OpDecorate %1 Uniform
)"); )");
} }
TEST(Markv, WithExtInst) {
TestEncodeDecode(R"(
OpCapability Addresses
OpCapability Kernel
OpCapability GenericPointer
OpCapability Linkage
%opencl = OpExtInstImport "OpenCL.std"
OpMemoryModel Physical32 OpenCL
%f32 = OpTypeFloat 32
%void = OpTypeVoid
%void_func = OpTypeFunction %void
%100 = OpConstant %f32 1.1
%main = OpFunction %void None %void_func
%entry_main = OpLabel
%200 = OpExtInst %f32 %opencl cos %100
OpReturn
OpFunctionEnd
)");
}
} // namespace } // namespace