1 // Copyright 2020 The Tint Authors. 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 "src/writer/spirv/binary_writer.h" 16 17 #include <cstring> 18 19 namespace tint { 20 namespace writer { 21 namespace spirv { 22 namespace { 23 24 const uint32_t kGeneratorId = 23u << 16; 25 26 } // namespace 27 28 BinaryWriter::BinaryWriter() = default; 29 30 BinaryWriter::~BinaryWriter() = default; 31 WriteBuilder(Builder * builder)32void BinaryWriter::WriteBuilder(Builder* builder) { 33 out_.reserve(builder->total_size()); 34 builder->iterate( 35 [this](const Instruction& inst) { this->process_instruction(inst); }); 36 } 37 WriteInstruction(const Instruction & inst)38void BinaryWriter::WriteInstruction(const Instruction& inst) { 39 process_instruction(inst); 40 } 41 WriteHeader(uint32_t bound)42void BinaryWriter::WriteHeader(uint32_t bound) { 43 out_.push_back(spv::MagicNumber); 44 out_.push_back(0x00010300); // Version 1.3 45 out_.push_back(kGeneratorId); 46 out_.push_back(bound); 47 out_.push_back(0); 48 } 49 process_instruction(const Instruction & inst)50void BinaryWriter::process_instruction(const Instruction& inst) { 51 out_.push_back(inst.word_length() << 16 | 52 static_cast<uint32_t>(inst.opcode())); 53 for (const auto& op : inst.operands()) { 54 process_op(op); 55 } 56 } 57 process_op(const Operand & op)58void BinaryWriter::process_op(const Operand& op) { 59 if (op.IsFloat()) { 60 // Allocate space for the float 61 out_.push_back(0); 62 auto f = op.to_f(); 63 uint8_t* ptr = reinterpret_cast<uint8_t*>(out_.data() + (out_.size() - 1)); 64 memcpy(ptr, &f, 4); 65 } else if (op.IsInt()) { 66 out_.push_back(op.to_i()); 67 } else { 68 auto idx = out_.size(); 69 const auto& str = op.to_s(); 70 out_.resize(out_.size() + op.length(), 0); 71 memcpy(out_.data() + idx, str.c_str(), str.size() + 1); 72 } 73 } 74 75 } // namespace spirv 76 } // namespace writer 77 } // namespace tint 78