1 // Copyright (c) 2016 Google Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "instruction.h" 16 17 #include <initializer_list> 18 19 #include "reflect.h" 20 21 namespace spvtools { 22 namespace ir { 23 24 Instruction::Instruction(const spv_parsed_instruction_t& inst, 25 std::vector<Instruction>&& dbg_line) 26 : opcode_(static_cast<SpvOp>(inst.opcode)), 27 type_id_(inst.type_id), 28 result_id_(inst.result_id), 29 dbg_line_insts_(std::move(dbg_line)) { 30 assert((!IsDebugLineInst(opcode_) || dbg_line.empty()) && 31 "Op(No)Line attaching to Op(No)Line found"); 32 for (uint32_t i = 0; i < inst.num_operands; ++i) { 33 const auto& current_payload = inst.operands[i]; 34 std::vector<uint32_t> words( 35 inst.words + current_payload.offset, 36 inst.words + current_payload.offset + current_payload.num_words); 37 operands_.emplace_back(current_payload.type, std::move(words)); 38 } 39 } 40 41 Instruction::Instruction(SpvOp op, uint32_t ty_id, uint32_t res_id, 42 const std::vector<Operand>& in_operands) 43 : opcode_(op), type_id_(ty_id), result_id_(res_id), operands_() { 44 if (type_id_ != 0) { 45 operands_.emplace_back(spv_operand_type_t::SPV_OPERAND_TYPE_TYPE_ID, 46 std::initializer_list<uint32_t>{type_id_}); 47 } 48 if (result_id_ != 0) { 49 operands_.emplace_back(spv_operand_type_t::SPV_OPERAND_TYPE_RESULT_ID, 50 std::initializer_list<uint32_t>{result_id_}); 51 } 52 operands_.insert(operands_.end(), in_operands.begin(), in_operands.end()); 53 } 54 55 Instruction::Instruction(Instruction&& that) 56 : opcode_(that.opcode_), 57 type_id_(that.type_id_), 58 result_id_(that.result_id_), 59 operands_(std::move(that.operands_)), 60 dbg_line_insts_(std::move(that.dbg_line_insts_)) {} 61 62 Instruction& Instruction::operator=(Instruction&& that) { 63 opcode_ = that.opcode_; 64 type_id_ = that.type_id_; 65 result_id_ = that.result_id_; 66 operands_ = std::move(that.operands_); 67 dbg_line_insts_ = std::move(that.dbg_line_insts_); 68 return *this; 69 } 70 71 uint32_t Instruction::GetSingleWordOperand(uint32_t index) const { 72 const auto& words = GetOperand(index).words; 73 assert(words.size() == 1 && "expected the operand only taking one word"); 74 return words.front(); 75 } 76 77 uint32_t Instruction::NumInOperandWords() const { 78 uint32_t size = 0; 79 for (uint32_t i = TypeResultIdCount(); i < operands_.size(); ++i) 80 size += static_cast<uint32_t>(operands_[i].words.size()); 81 return size; 82 } 83 84 void Instruction::ToBinaryWithoutAttachedDebugInsts( 85 std::vector<uint32_t>* binary) const { 86 const uint32_t num_words = 1 + NumOperandWords(); 87 binary->push_back((num_words << 16) | static_cast<uint16_t>(opcode_)); 88 for (const auto& operand : operands_) 89 binary->insert(binary->end(), operand.words.begin(), operand.words.end()); 90 } 91 92 } // namespace ir 93 } // namespace spvtools 94