/* This file is part of the sirit project. * Copyright (c) 2018 ReinUsesLisp * This software may be used and distributed according to the terms of the GNU * Lesser General Public License version 2.1 or any later version. */ #include #include #include "sirit/sirit.h" #include "common_types.h" #include "op.h" #include "stream.h" namespace Sirit { template inline void WriteEnum(Stream& stream, spv::Op opcode, T value) { Op op{opcode}; op.Add(static_cast(value)); op.Write(stream); } Module::Module() {} Module::~Module() = default; std::vector Module::Assembly() const { std::vector bytes; Stream stream{bytes}; stream.Write(spv::MagicNumber); stream.Write(spv::Version); stream.Write(GeneratorMagicNumber); stream.Write(bound); stream.Write(static_cast(0)); for (auto capability : capabilities) { WriteEnum(stream, spv::Op::OpCapability, capability); } // TODO write extensions // TODO write ext inst imports Op memory_model_ref{spv::Op::OpMemoryModel}; memory_model_ref.Add(static_cast(addressing_model)); memory_model_ref.Add(static_cast(memory_model)); memory_model_ref.Write(stream); for (const auto& entry_point : entry_points) { entry_point->Write(stream); } // TODO write execution mode // TODO write debug symbols // TODO write annotations for (const auto& decl : declarations) { decl->Write(stream); } for (const auto& line : code) { line->Write(stream); } return bytes; } void Module::Optimize(int level) { } void Module::AddCapability(spv::Capability capability) { capabilities.insert(capability); } void Module::SetMemoryModel(spv::AddressingModel addressing_model, spv::MemoryModel memory_model) { this->addressing_model = addressing_model; this->memory_model = memory_model; } void Module::AddEntryPoint(spv::ExecutionModel execution_model, Ref entry_point, const std::string& name, const std::vector& interfaces) { Op* op{new Op(spv::Op::OpEntryPoint)}; op->Add(static_cast(execution_model)); op->Add(entry_point); op->Add(name); op->Add(interfaces); entry_points.push_back(std::unique_ptr(op)); } Ref Module::Emit(Ref op) { assert(op); code.push_back(op); return op; } Ref Module::AddCode(Op* op) { code_store.push_back(std::unique_ptr(op)); return op; } Ref Module::AddCode(spv::Op opcode, u32 id) { return AddCode(new Op{opcode, id}); } Ref Module::AddDeclaration(Op* op) { const auto& found{std::find_if(declarations.begin(), declarations.end(), [=](const auto& other) { return *other == *op; })}; if (found != declarations.end()) { delete op; return found->get(); } else { declarations.push_back(std::unique_ptr(op)); bound++; return op; } } } // namespace Sirit