2018-08-23 09:59:57 +02:00
|
|
|
/* 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
|
2018-08-27 04:28:39 +02:00
|
|
|
* Lesser General Public License version 2.1 or any later version.
|
2018-08-23 09:59:57 +02:00
|
|
|
*/
|
|
|
|
|
2018-08-26 01:16:37 +02:00
|
|
|
#include "sirit/sirit.h"
|
|
|
|
#include "common_types.h"
|
2018-08-26 01:34:06 +02:00
|
|
|
#include "op.h"
|
2018-08-26 01:16:37 +02:00
|
|
|
#include "stream.h"
|
2018-10-03 05:32:45 +02:00
|
|
|
#include <algorithm>
|
|
|
|
#include <cassert>
|
2018-08-26 01:16:37 +02:00
|
|
|
|
|
|
|
namespace Sirit {
|
|
|
|
|
2018-10-03 05:32:45 +02:00
|
|
|
template <typename T>
|
|
|
|
static void WriteEnum(Stream& stream, spv::Op opcode, T value) {
|
2018-08-28 09:05:47 +02:00
|
|
|
Op op{opcode};
|
|
|
|
op.Add(static_cast<u32>(value));
|
|
|
|
op.Write(stream);
|
|
|
|
}
|
|
|
|
|
2018-10-28 17:44:12 +01:00
|
|
|
template <typename T> static void WriteSet(Stream& stream, const T& set) {
|
2018-10-20 07:52:55 +02:00
|
|
|
for (const auto& item : set) {
|
|
|
|
item->Write(stream);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-08-26 01:16:37 +02:00
|
|
|
Module::Module() {}
|
|
|
|
|
|
|
|
Module::~Module() = default;
|
|
|
|
|
2018-08-31 08:41:30 +02:00
|
|
|
std::vector<u8> Module::Assemble() const {
|
2018-08-26 01:16:37 +02:00
|
|
|
std::vector<u8> bytes;
|
|
|
|
Stream stream{bytes};
|
|
|
|
|
|
|
|
stream.Write(spv::MagicNumber);
|
|
|
|
stream.Write(spv::Version);
|
2018-10-03 05:32:45 +02:00
|
|
|
stream.Write(GENERATOR_MAGIC_NUMBER);
|
2018-08-26 01:16:37 +02:00
|
|
|
stream.Write(bound);
|
|
|
|
stream.Write(static_cast<u32>(0));
|
|
|
|
|
2018-10-23 10:09:17 +02:00
|
|
|
for (const auto capability : capabilities) {
|
2018-08-26 01:16:37 +02:00
|
|
|
WriteEnum(stream, spv::Op::OpCapability, capability);
|
|
|
|
}
|
|
|
|
// TODO write extensions
|
|
|
|
// TODO write ext inst imports
|
|
|
|
|
2018-08-26 01:34:06 +02:00
|
|
|
Op memory_model_ref{spv::Op::OpMemoryModel};
|
2018-08-26 01:16:37 +02:00
|
|
|
memory_model_ref.Add(static_cast<u32>(addressing_model));
|
|
|
|
memory_model_ref.Add(static_cast<u32>(memory_model));
|
|
|
|
memory_model_ref.Write(stream);
|
|
|
|
|
2018-10-20 07:52:55 +02:00
|
|
|
WriteSet(stream, entry_points);
|
2018-08-26 01:16:37 +02:00
|
|
|
// TODO write execution mode
|
2018-10-20 07:52:55 +02:00
|
|
|
WriteSet(stream, debug);
|
2018-10-23 09:45:56 +02:00
|
|
|
WriteSet(stream, annotations);
|
2018-10-20 07:52:55 +02:00
|
|
|
WriteSet(stream, declarations);
|
|
|
|
WriteSet(stream, global_variables);
|
|
|
|
WriteSet(stream, code);
|
2018-08-26 01:16:37 +02:00
|
|
|
|
|
|
|
return bytes;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Module::AddCapability(spv::Capability capability) {
|
|
|
|
capabilities.insert(capability);
|
|
|
|
}
|
|
|
|
|
2018-10-03 05:32:45 +02:00
|
|
|
void Module::SetMemoryModel(spv::AddressingModel addressing_model,
|
|
|
|
spv::MemoryModel memory_model) {
|
2018-08-26 01:16:37 +02:00
|
|
|
this->addressing_model = addressing_model;
|
|
|
|
this->memory_model = memory_model;
|
|
|
|
}
|
|
|
|
|
2018-11-01 02:20:49 +01:00
|
|
|
void Module::AddEntryPoint(spv::ExecutionModel execution_model, Id entry_point,
|
2018-10-03 05:32:45 +02:00
|
|
|
const std::string& name,
|
2018-11-01 02:20:49 +01:00
|
|
|
const std::vector<Id>& interfaces) {
|
2018-11-01 09:13:30 +01:00
|
|
|
auto op{std::make_unique<Op>(spv::Op::OpEntryPoint)};
|
2018-08-26 01:16:37 +02:00
|
|
|
op->Add(static_cast<u32>(execution_model));
|
|
|
|
op->Add(entry_point);
|
|
|
|
op->Add(name);
|
|
|
|
op->Add(interfaces);
|
2018-11-01 09:13:30 +01:00
|
|
|
entry_points.push_back(std::move(op));
|
2018-08-26 01:16:37 +02:00
|
|
|
}
|
|
|
|
|
2018-11-01 02:20:49 +01:00
|
|
|
Id Module::Emit(Id op) {
|
2018-08-26 01:34:06 +02:00
|
|
|
code.push_back(op);
|
|
|
|
return op;
|
2018-08-26 01:16:37 +02:00
|
|
|
}
|
|
|
|
|
2018-11-01 02:20:49 +01:00
|
|
|
Id Module::AddGlobalVariable(Id variable) {
|
2018-10-20 07:52:55 +02:00
|
|
|
assert(variable);
|
|
|
|
global_variables.push_back(variable);
|
|
|
|
return variable;
|
|
|
|
}
|
|
|
|
|
2018-11-01 04:02:45 +01:00
|
|
|
Id Module::AddCode(std::unique_ptr<Op> op) {
|
2018-11-01 09:13:30 +01:00
|
|
|
const auto id = op.get();
|
2018-11-01 04:02:45 +01:00
|
|
|
code_store.push_back(std::move(op));
|
2018-11-01 09:13:30 +01:00
|
|
|
return id;
|
2018-08-26 01:16:37 +02:00
|
|
|
}
|
|
|
|
|
2018-11-01 02:20:49 +01:00
|
|
|
Id Module::AddCode(spv::Op opcode, std::optional<u32> id) {
|
2018-11-01 04:02:45 +01:00
|
|
|
return AddCode(std::make_unique<Op>(opcode, id));
|
2018-08-26 01:16:37 +02:00
|
|
|
}
|
|
|
|
|
2018-11-01 04:02:45 +01:00
|
|
|
Id Module::AddDeclaration(std::unique_ptr<Op> op) {
|
2018-10-03 05:32:45 +02:00
|
|
|
const auto& found{
|
|
|
|
std::find_if(declarations.begin(), declarations.end(),
|
|
|
|
[&op](const auto& other) { return *other == *op; })};
|
2018-08-26 01:16:37 +02:00
|
|
|
if (found != declarations.end()) {
|
|
|
|
return found->get();
|
|
|
|
}
|
2018-11-01 04:02:45 +01:00
|
|
|
const auto id = op.get();
|
|
|
|
declarations.push_back(std::move(op));
|
|
|
|
bound++;
|
|
|
|
return id;
|
2018-08-26 01:16:37 +02:00
|
|
|
}
|
|
|
|
|
2018-11-01 04:02:45 +01:00
|
|
|
Id Module::AddAnnotation(std::unique_ptr<Op> op) {
|
2018-11-01 09:13:30 +01:00
|
|
|
const auto id = op.get();
|
2018-11-01 04:02:45 +01:00
|
|
|
annotations.push_back(std::move(op));
|
2018-11-01 09:13:30 +01:00
|
|
|
return id;
|
2018-10-23 09:45:56 +02:00
|
|
|
}
|
|
|
|
|
2018-08-26 01:16:37 +02:00
|
|
|
} // namespace Sirit
|