#include "generate.h"
#include "json/json.h"
#include <fstream>
+#include <iostream>
#include <cassert>
#include <limits>
#include <unordered_map>
using namespace util::string_view_literals;
-struct Spirv_and_parser_generator::State
+namespace
{
-private:
- const ast::Top_level &top_level;
- detail::Generated_output_stream spirv_h;
- detail::Generated_output_stream spirv_cpp;
- detail::Generated_output_stream parser_h;
- detail::Generated_output_stream parser_cpp;
+enum class Output_part
+{
+ file_comments,
+ include_guard_start,
+ includes,
+ namespaces_start,
+ basic_types,
+ basic_constants,
+ id_types,
+ enum_definitions,
+ enum_properties_definitions,
+ literal_types,
+ namespaces_end,
+ include_guard_end
+};
-public:
- State(const util::filesystem::path &output_directory, const ast::Top_level &top_level)
- : top_level(top_level),
- spirv_h(output_directory / "spirv.h"),
- spirv_cpp(output_directory / "spirv.cpp"),
- parser_h(output_directory / "parser.h"),
- parser_cpp(output_directory / "parser.cpp")
- {
- }
+vulkan_cpu_util_generate_enum_traits(Output_part,
+ Output_part::file_comments,
+ Output_part::include_guard_start,
+ Output_part::includes,
+ Output_part::namespaces_start,
+ Output_part::basic_types,
+ Output_part::basic_constants,
+ Output_part::id_types,
+ Output_part::enum_definitions,
+ Output_part::enum_properties_definitions,
+ Output_part::literal_types,
+ Output_part::namespaces_end,
+ Output_part::include_guard_end);
+
+static_assert(util::Enum_traits<Output_part>::is_compact,
+ "mismatch between declaration and generate enum traits");
+}
+struct Spirv_and_parser_generator::State
+{
private:
- void write_file_comments()
+ struct Output_file_base
{
- constexpr auto automatically_generated_file_warning_comment =
- R"(/* This file is automatically generated by generate_spirv_parser. DO NOT MODIFY. */
+ util::Enum_map<Output_part, detail::Generated_output_stream Output_file_base::*>
+ output_parts;
+ template <typename Derived_class>
+ void register_output_part(Output_part part,
+ detail::Generated_output_stream Derived_class::*variable)
+ {
+ static_assert(std::is_base_of<Output_file_base, Derived_class>::value, "");
+ assert(dynamic_cast<Derived_class *>(this));
+ output_parts.insert_or_assign(
+ part, static_cast<detail::Generated_output_stream Output_file_base::*>(variable));
+ }
+ const util::filesystem::path file_path;
+ detail::Generated_output_stream file_comments;
+ detail::Generated_output_stream includes;
+ detail::Generated_output_stream namespaces_start;
+ detail::Generated_output_stream namespaces_end;
+ explicit Output_file_base(const util::filesystem::path &file_path)
+ : file_path(file_path),
+ file_comments(file_path),
+ includes(file_path),
+ namespaces_start(file_path),
+ namespaces_end(file_path)
+ {
+ register_output_part(Output_part::file_comments, &Output_file_base::file_comments);
+ register_output_part(Output_part::includes, &Output_file_base::includes);
+ register_output_part(Output_part::namespaces_start,
+ &Output_file_base::namespaces_start);
+ register_output_part(Output_part::namespaces_end, &Output_file_base::namespaces_end);
+ }
+ virtual void fill_output(State &state)
+ {
+ constexpr auto automatically_generated_file_warning_comment =
+ R"(/* This file is automatically generated by generate_spirv_parser. DO NOT MODIFY. */
)"_sv;
- spirv_h << automatically_generated_file_warning_comment << top_level.copyright;
- spirv_cpp << automatically_generated_file_warning_comment << top_level.copyright;
- parser_h << automatically_generated_file_warning_comment << top_level.copyright;
- parser_cpp << automatically_generated_file_warning_comment << top_level.copyright;
- }
- static void write_opening_inclusion_guard(detail::Generated_output_stream &os)
+ file_comments << automatically_generated_file_warning_comment
+ << state.top_level.copyright;
+ namespaces_start << R"(
+namespace vulkan_cpu
+{
+namespace spirv
+{
+)";
+ namespaces_end << R"(}
+}
+)";
+ }
+ detail::Generated_output_stream get_whole_output() const
+ {
+ detail::Generated_output_stream retval(file_path);
+ for(auto &part : output_parts)
+ retval << this->*std::get<1>(part);
+ return retval;
+ }
+ virtual void write_to_file() const
+ {
+ get_whole_output().write_to_file();
+ }
+ void write_local_include_string(util::string_view header_file)
+ {
+ includes << R"(#include ")" << header_file << R"("
+)";
+ }
+ void write_local_include_path(util::filesystem::path header_file)
+ {
+ auto dir_path = file_path;
+ dir_path.remove_filename();
+ write_local_include_string(header_file.lexically_proximate(dir_path).generic_string());
+ }
+ void write_system_include(util::string_view header_file)
+ {
+ includes << R"(#include <)" << header_file << R"(>
+)";
+ }
+ };
+ struct Header_file_base : public Output_file_base
{
- using detail::guard_macro;
- os << R"(#ifndef )" << guard_macro << R"(
-#define )" << guard_macro
- << R"(
+ detail::Generated_output_stream include_guard_start;
+ detail::Generated_output_stream include_guard_end;
+ explicit Header_file_base(const util::filesystem::path &file_path)
+ : Output_file_base(file_path),
+ include_guard_start(file_path),
+ include_guard_end(file_path)
+ {
+ register_output_part(Output_part::include_guard_start,
+ &Header_file_base::include_guard_start);
+ register_output_part(Output_part::include_guard_end,
+ &Header_file_base::include_guard_end);
+ }
+ virtual void fill_output(State &state) override
+ {
+ using detail::guard_macro;
+ Output_file_base::fill_output(state);
+ include_guard_start << R"(#ifndef )" << guard_macro << R"(
+#define )" << guard_macro << R"(
)";
- }
- static void write_closing_inclusion_guard(detail::Generated_output_stream &os)
- {
- using detail::guard_macro;
- os << R"(
-#endif /* )"
- << guard_macro << R"( */
+ include_guard_end << R"(
+#endif /* )" << guard_macro << R"( */
)";
- }
- void write_opening_inclusion_guards()
- {
- write_opening_inclusion_guard(spirv_h);
- write_opening_inclusion_guard(parser_h);
- }
- void write_closing_inclusion_guards()
+ }
+ };
+ struct Source_file_base : public Output_file_base
{
- write_closing_inclusion_guard(spirv_h);
- write_closing_inclusion_guard(parser_h);
- }
- static void write_local_include(detail::Generated_output_stream &os, util::string_view file)
+ const Header_file_base *const header;
+ explicit Source_file_base(const util::filesystem::path &file_path,
+ const Header_file_base *header)
+ : Output_file_base(file_path), header(header)
+ {
+ }
+ virtual void fill_output(State &state) override
+ {
+ using detail::guard_macro;
+ Output_file_base::fill_output(state);
+ write_local_include_path(header->file_path);
+ }
+ };
+ struct Spirv_h : public Header_file_base
{
- os << R"(#include ")" << file << R"("
+ detail::Generated_output_stream basic_types;
+ detail::Generated_output_stream basic_constants;
+ detail::Generated_output_stream id_types;
+ detail::Generated_output_stream enum_definitions;
+ detail::Generated_output_stream enum_properties_definitions;
+ detail::Generated_output_stream literal_types;
+ explicit Spirv_h(const util::filesystem::path &file_path)
+ : Header_file_base(file_path),
+ basic_types(file_path),
+ basic_constants(file_path),
+ id_types(file_path),
+ enum_definitions(file_path),
+ enum_properties_definitions(file_path),
+ literal_types(file_path)
+ {
+ register_output_part(Output_part::basic_types, &Spirv_h::basic_types);
+ register_output_part(Output_part::basic_constants, &Spirv_h::basic_constants);
+ register_output_part(Output_part::id_types, &Spirv_h::id_types);
+ register_output_part(Output_part::enum_definitions, &Spirv_h::enum_definitions);
+ register_output_part(Output_part::enum_properties_definitions,
+ &Spirv_h::enum_properties_definitions);
+ register_output_part(Output_part::literal_types, &Spirv_h::literal_types);
+ }
+ void write_literal_kinds(State &state)
+ {
+ for(auto &operand_kind : state.top_level.operand_kinds.operand_kinds)
+ {
+ if(operand_kind.category != ast::Operand_kinds::Operand_kind::Category::literal)
+ continue;
+ auto literal_kind =
+ ast::Operand_kinds::Operand_kind::get_literal_kind_from_json_name(
+ operand_kind.kind);
+ if(!literal_kind)
+ throw Generate_error("unknown literal kind: " + operand_kind.kind);
+ auto underlying_type = "<<<<<Unknown>>>>>"_sv;
+ switch(*literal_kind)
+ {
+ case ast::Operand_kinds::Operand_kind::Literal_kind::literal_integer:
+ underlying_type = "std::uint64_t"_sv;
+ break;
+ case ast::Operand_kinds::Operand_kind::Literal_kind::literal_string:
+ // Literal_string is defined in write_basic_types
+ continue;
+ case ast::Operand_kinds::Operand_kind::Literal_kind::
+ literal_context_dependent_number:
+ underlying_type = "std::vector<Word>"_sv;
+ break;
+ case ast::Operand_kinds::Operand_kind::Literal_kind::literal_ext_inst_integer:
+ underlying_type = "Word"_sv;
+ break;
+ case ast::Operand_kinds::Operand_kind::Literal_kind::
+ literal_spec_constant_op_integer:
+ underlying_type = state.op_enumeration.value()->cpp_name;
+ break;
+ }
+ auto &descriptor = state.literal_type_descriptors.at(*literal_kind);
+ literal_types << R"(
+typedef )" << underlying_type << " "
+ << descriptor.cpp_name << R"(;
)";
- }
- static void write_system_include(detail::Generated_output_stream &os, util::string_view file)
- {
- os << R"(#include <)" << file << R"(>
+ }
+ }
+ void write_basic_constants(State &state)
+ {
+ using detail::unsigned_integer;
+ basic_constants << R"(
+constexpr Word magic_number = 0x)"
+ << unsigned_integer(state.top_level.magic_number, 0x10, 8) << R"(UL;
+constexpr std::uint32_t major_version = )"
+ << unsigned_integer(state.top_level.major_version) << R"(UL;
+constexpr std::uint32_t minor_version = )"
+ << unsigned_integer(state.top_level.minor_version) << R"(UL;
+constexpr std::uint32_t revision = )"
+ << unsigned_integer(state.top_level.revision) << R"(UL;
)";
- }
- void write_includes()
- {
- write_local_include(spirv_cpp, spirv_h.get_file_path().filename().string());
- write_local_include(parser_h, spirv_h.get_file_path().filename().string());
- write_local_include(parser_cpp, parser_h.get_file_path().filename().string());
- write_system_include(spirv_h, "cstdint");
- write_system_include(spirv_h, "vector");
- write_system_include(spirv_h, "string");
- write_system_include(spirv_h, "iterator");
- write_local_include(spirv_h, "util/string_view.h");
- write_local_include(spirv_h, "util/enum.h");
- write_local_include(spirv_h, "spirv/word.h");
- write_local_include(spirv_h, "spirv/literal_string.h");
- }
- static void write_opening_namespaces(detail::Generated_output_stream &os)
- {
- os << R"(
-namespace vulkan_cpu
+ for(auto &instruction_set : state.top_level.extension_instruction_sets)
+ {
+ basic_constants << R"(
+constexpr std::uint32_t )" << instruction_set_version_name(instruction_set)
+ << R"( = )" << unsigned_integer(instruction_set.version) << R"(UL;
+constexpr std::uint32_t )" << instruction_set_revision_name(instruction_set)
+ << R"( = )" << unsigned_integer(instruction_set.revision) << R"(UL;
+)";
+ }
+ }
+ void write_enums(State &state)
+ {
+ using detail::unsigned_integer;
+ for(auto &enumeration : state.enumerations_list)
+ {
+ enum_definitions << R"(
+enum class )" << enumeration.cpp_name
+ << R"( : Word
{
-namespace spirv
+@+)";
+ enum_properties_definitions << R"(
+constexpr util::string_view get_enumerant_name()"
+ << enumeration.cpp_name << R"( v) noexcept
{
+ using namespace util::string_view_literals;
+ switch(v)
+ {
+@+@+)";
+ for(auto &enumerant : enumeration.enumerants)
+ {
+ enum_definitions << enumerant.cpp_name << " = ";
+ if(enumeration.is_bitwise)
+ enum_definitions << "0x" << unsigned_integer(enumerant.value, 0x10) << "UL";
+ else
+ enum_definitions << unsigned_integer(enumerant.value, 10) << "UL";
+ enum_definitions << ",\n";
+ }
+ enum_definitions << R"(@-};
+
+vulkan_cpu_util_generate_enum_traits()"
+ << enumeration.cpp_name;
+ std::unordered_set<std::uint32_t> values;
+ for(auto &enumerant : enumeration.enumerants)
+ {
+ enum_definitions << R"(,
+`````````````````````````````````````)"
+ << enumeration.cpp_name << "::" << enumerant.cpp_name;
+ if(std::get<1>(values.insert(enumerant.value)))
+ {
+ enum_properties_definitions << "case " << enumeration.cpp_name
+ << "::" << enumerant.cpp_name << R"(:
+ return ")" << enumerant.json_name << R"("_sv;
)";
- }
- void write_opening_namespaces()
+ }
+ }
+ enum_definitions << R"();
+)";
+ enum_properties_definitions << R"(@-@_}
+ return ""_sv;
+}
+
+constexpr util::Enum_set<)" << state.capability_enumeration.value()->cpp_name
+ << R"(> get_directly_required_capabilities()"
+ << enumeration.cpp_name << R"( v) noexcept
+{
+ switch(v)
{
- write_opening_namespaces(spirv_h);
- write_opening_namespaces(spirv_cpp);
- write_opening_namespaces(parser_h);
- write_opening_namespaces(parser_cpp);
- }
- static void write_closing_namespaces(detail::Generated_output_stream &os)
+@+@+)";
+ values.clear();
+ for(auto &enumerant : enumeration.enumerants)
+ {
+ if(std::get<1>(values.insert(enumerant.value)))
+ {
+ enum_properties_definitions << "case " << enumeration.cpp_name
+ << "::" << enumerant.cpp_name << R"(:
+ return {)";
+ auto separator = ""_sv;
+ for(auto &capability : enumerant.capabilities.capabilities)
+ {
+ enum_properties_definitions << separator;
+ separator = ", "_sv;
+ enum_properties_definitions
+ << state.capability_enumeration.value()->cpp_name
+ << "::" << state.get_capability(capability).cpp_name;
+ }
+ enum_properties_definitions << R"(};
+)";
+ }
+ }
+ enum_properties_definitions << R"(@-@_}
+ return {};
+}
+
+constexpr util::Enum_set<)" << state.extension_enumeration.value()->cpp_name
+ << R"(> get_directly_required_extensions()"
+ << enumeration.cpp_name << R"( v) noexcept
+{
+ switch(v)
{
- os << R"(}
+@+@+)";
+ values.clear();
+ for(auto &enumerant : enumeration.enumerants)
+ {
+ if(std::get<1>(values.insert(enumerant.value)))
+ {
+ enum_properties_definitions << "case " << enumeration.cpp_name
+ << "::" << enumerant.cpp_name << R"(:
+ return {)";
+ auto separator = ""_sv;
+ for(auto &extension : enumerant.extensions.extensions)
+ {
+ enum_properties_definitions << separator;
+ separator = ", "_sv;
+ enum_properties_definitions
+ << state.extension_enumeration.value()->cpp_name
+ << "::" << state.get_extension(extension).cpp_name;
+ }
+ enum_properties_definitions << R"(};
+)";
+ }
+ }
+ enum_properties_definitions << R"(@-@_}
+ return {};
}
)";
- }
- void write_closing_namespaces()
+ }
+#warning add writing enum parameters
+ }
+ void write_id_types(State &state)
+ {
+ id_types << "\n";
+ for(auto &id_type : state.id_type_list)
+ {
+ id_types << "typedef Id " << id_type.cpp_name
+ << R"(;
+)";
+ }
+ }
+ virtual void fill_output(State &state) override
+ {
+ Header_file_base::fill_output(state);
+ write_system_include("cstdint");
+ write_system_include("vector");
+ write_system_include("string");
+ write_system_include("iterator");
+ write_local_include_string("util/string_view.h");
+ write_local_include_string("util/enum.h");
+ write_local_include_string("spirv/word.h");
+ write_local_include_string("spirv/literal_string.h");
+ basic_types << R"(typedef Word Id;
+)";
+#warning finish
+ include_guard_start << R"(#error generator not finished being implemented
+
+)";
+ write_literal_kinds(state);
+ write_basic_constants(state);
+ write_enums(state);
+ write_id_types(state);
+ }
+ };
+ struct Spirv_cpp : public Source_file_base
+ {
+ explicit Spirv_cpp(const util::filesystem::path &file_path, const Spirv_h *header)
+ : Source_file_base(file_path, header)
+ {
+ }
+ };
+ struct Parser_h : public Header_file_base
+ {
+ explicit Parser_h(const util::filesystem::path &file_path) : Header_file_base(file_path)
+ {
+ }
+ virtual void fill_output(State &state) override
+ {
+ Header_file_base::fill_output(state);
+ write_local_include_path(state.spirv_h.file_path);
+ }
+ };
+ struct Parser_cpp : public Source_file_base
+ {
+ explicit Parser_cpp(const util::filesystem::path &file_path, const Parser_h *header)
+ : Source_file_base(file_path, header)
+ {
+ }
+ };
+
+private:
+ const ast::Top_level &top_level;
+ Spirv_h spirv_h;
+ Spirv_cpp spirv_cpp;
+ Parser_h parser_h;
+ Parser_cpp parser_cpp;
+
+public:
+ State(const util::filesystem::path &output_directory, const ast::Top_level &top_level)
+ : top_level(top_level),
+ spirv_h(output_directory / "spirv.h"),
+ spirv_cpp(output_directory / "spirv.cpp", &spirv_h),
+ parser_h(output_directory / "parser.h"),
+ parser_cpp(output_directory / "parser.cpp", &parser_h)
{
- write_closing_namespaces(spirv_h);
- write_closing_namespaces(spirv_cpp);
- write_closing_namespaces(parser_h);
- write_closing_namespaces(parser_cpp);
}
private:
if(!capability_enumeration)
throw Generate_error("missing " + std::string(capability_enum_json_name) + " enum");
}
- void write_basic_types()
- {
- spirv_h << R"(typedef Word Id;
-)";
- }
static std::string instruction_set_version_name(const ast::Extension_instruction_set &v)
{
using detail::name_from_words_all_lowercase;
using detail::name_from_words_all_lowercase;
return name_from_words_all_lowercase("revision"_sv, v.import_name).to_string();
}
- void write_basic_constants()
- {
- using detail::unsigned_integer;
- spirv_h << R"(
-constexpr Word magic_number = 0x)"
- << unsigned_integer(top_level.magic_number, 0x10, 8) << R"(UL;
-constexpr std::uint32_t major_version = )"
- << unsigned_integer(top_level.major_version) << R"(UL;
-constexpr std::uint32_t minor_version = )"
- << unsigned_integer(top_level.minor_version) << R"(UL;
-constexpr std::uint32_t revision = )"
- << unsigned_integer(top_level.revision) << R"(UL;
-)";
- for(auto &instruction_set : top_level.extension_instruction_sets)
- {
- spirv_h << R"(
-constexpr std::uint32_t )"
- << instruction_set_version_name(instruction_set) << R"( = )"
- << unsigned_integer(instruction_set.version) << R"(UL;
-constexpr std::uint32_t )"
- << instruction_set_revision_name(instruction_set) << R"( = )"
- << unsigned_integer(instruction_set.revision) << R"(UL;
-)";
- }
- }
- void write_enum_declarations()
- {
- spirv_h << "\n";
- for(auto &enumeration : enumerations_list)
- spirv_h << "enum class " << enumeration.cpp_name << " : Word;\n";
- }
- void write_enum_definitions()
- {
- using detail::unsigned_integer;
- for(auto &enumeration : enumerations_list)
- {
- spirv_h << R"(
-enum class )" << enumeration.cpp_name
- << R"( : Word
-{
-@+)";
- for(auto &enumerant : enumeration.enumerants)
- {
- spirv_h << enumerant.cpp_name << " = ";
- if(enumeration.is_bitwise)
- spirv_h << "0x" << unsigned_integer(enumerant.value, 0x10) << "UL";
- else
- spirv_h << unsigned_integer(enumerant.value, 10) << "UL";
- spirv_h << ",\n";
- }
- spirv_h << R"(@-};
-
-vulkan_cpu_util_generate_enum_traits()"
- << enumeration.cpp_name;
- for(auto &enumerant : enumeration.enumerants)
- spirv_h << R"(,
-`````````````````````````````````````)"
- << enumeration.cpp_name << "::" << enumerant.cpp_name;
- spirv_h << R"();
-)";
- }
- }
const Enumerant_descriptor &get_capability(const std::string &capability)
{
auto &enumerant_map = capability_enumeration.value()->json_name_to_enumerant_map;
throw Generate_error("unknown extension: " + extension);
return *std::get<1>(*iter);
}
- void write_enum_properties_definitions()
- {
- for(auto &enumeration : enumerations_list)
- {
- spirv_h << R"(
-constexpr util::string_view get_enumerant_name()"
- << enumeration.cpp_name << R"( v) noexcept
-{
- using namespace util::string_view_literals;
- switch(v)
- {
-@+@+)";
- std::unordered_set<std::uint32_t> values;
- for(auto &enumerant : enumeration.enumerants)
- {
- if(std::get<1>(values.insert(enumerant.value)))
- {
- spirv_h << "case " << enumeration.cpp_name << "::" << enumerant.cpp_name << R"(:
- return ")" << enumerant.json_name
- << R"("_sv;
-)";
- }
- }
- spirv_h << R"(@-@_}
- return ""_sv;
-}
-
-constexpr util::Enum_set<)"
- << capability_enumeration.value()->cpp_name
- << R"(> get_directly_required_capabilities()" << enumeration.cpp_name
- << R"( v) noexcept
-{
- switch(v)
- {
-@+@+)";
- values.clear();
- for(auto &enumerant : enumeration.enumerants)
- {
- if(std::get<1>(values.insert(enumerant.value)))
- {
- spirv_h << "case " << enumeration.cpp_name << "::" << enumerant.cpp_name << R"(:
- return {)";
- auto separator = ""_sv;
- for(auto &capability : enumerant.capabilities.capabilities)
- {
- spirv_h << separator;
- separator = ", "_sv;
- spirv_h << capability_enumeration.value()->cpp_name
- << "::" << get_capability(capability).cpp_name;
- }
- spirv_h << R"(};
-)";
- }
- }
- spirv_h << R"(@-@_}
- return {};
-}
-
-constexpr util::Enum_set<)"
- << extension_enumeration.value()->cpp_name
- << R"(> get_directly_required_extensions()" << enumeration.cpp_name
- << R"( v) noexcept
-{
- switch(v)
- {
-@+@+)";
- values.clear();
- for(auto &enumerant : enumeration.enumerants)
- {
- if(std::get<1>(values.insert(enumerant.value)))
- {
- spirv_h << "case " << enumeration.cpp_name << "::" << enumerant.cpp_name << R"(:
- return {)";
- auto separator = ""_sv;
- for(auto &extension : enumerant.extensions.extensions)
- {
- spirv_h << separator;
- separator = ", "_sv;
- spirv_h << extension_enumeration.value()->cpp_name
- << "::" << get_extension(extension).cpp_name;
- }
- spirv_h << R"(};
-)";
- }
- }
- spirv_h << R"(@-@_}
- return {};
-}
-)";
- }
- }
private:
struct Literal_type_descriptor
};
private:
- util::Enum_map<ast::Operand_kinds::Operand_kind::Literal_kind,
- Literal_type_descriptor> literal_type_descriptors;
+ util::Enum_map<ast::Operand_kinds::Operand_kind::Literal_kind, Literal_type_descriptor>
+ literal_type_descriptors;
private:
void fill_literal_type_descriptors()
literal_type_descriptors.emplace(literal_kind, Literal_type_descriptor(literal_kind));
}
}
- void write_literal_kinds()
+ static ast::Operand_kinds::Operand_kind::Literal_kind get_literal_kind(
+ util::string_view json_name)
+ {
+ auto retval = ast::Operand_kinds::Operand_kind::get_literal_kind_from_json_name(json_name);
+ if(!retval)
+ throw Generate_error("unknown literal kind: " + std::string(json_name));
+ return *retval;
+ }
+
+private:
+ struct Id_type_descriptor
+ {
+ std::string cpp_name;
+ std::string json_name;
+ static std::string get_cpp_name(util::string_view json_name)
+ {
+ using detail::name_from_words_initial_capital;
+ return name_from_words_initial_capital(json_name).to_string();
+ }
+ explicit Id_type_descriptor(std::string json_name)
+ : cpp_name(get_cpp_name(json_name)), json_name(std::move(json_name))
+ {
+ }
+ };
+
+private:
+ std::list<Id_type_descriptor> id_type_list;
+ std::unordered_map<std::string, std::list<Id_type_descriptor>::const_iterator> id_type_map;
+
+private:
+ std::list<Id_type_descriptor>::const_iterator add_id_type_descriptor(
+ Id_type_descriptor &&id_type_descriptor)
+ {
+ auto name = id_type_descriptor.json_name;
+ auto iter = id_type_list.insert(id_type_list.end(), std::move(id_type_descriptor));
+ if(!std::get<1>(id_type_map.emplace(name, iter)))
+ throw Generate_error("duplicate id type: " + name);
+ return iter;
+ }
+ void fill_id_type_descriptors()
{
for(auto &operand_kind : top_level.operand_kinds.operand_kinds)
{
- if(operand_kind.category != ast::Operand_kinds::Operand_kind::Category::literal)
+ if(operand_kind.category != ast::Operand_kinds::Operand_kind::Category::id)
continue;
- auto literal_kind = ast::Operand_kinds::Operand_kind::get_literal_kind_from_json_name(
- operand_kind.kind);
- if(!literal_kind)
- throw Generate_error("unknown literal kind: " + operand_kind.kind);
- auto underlying_type = "<<<<<Unknown>>>>>"_sv;
- switch(*literal_kind)
+ add_id_type_descriptor(Id_type_descriptor(operand_kind.kind));
+ }
+ }
+ std::list<Id_type_descriptor>::const_iterator get_id_type(const std::string &json_name)
+ {
+ auto iter = id_type_map.find(json_name);
+ if(iter == id_type_map.end())
+ throw Generate_error("unknown id type: " + json_name);
+ return std::get<1>(*iter);
+ }
+
+private:
+ struct Operand_kind_descriptor
+ {
+ std::string json_name;
+ util::variant<util::monostate,
+ std::list<Enumeration_descriptor>::const_iterator,
+ std::list<Id_type_descriptor>::const_iterator,
+ ast::Operand_kinds::Operand_kind::Literal_kind> value;
+ std::string make_cpp_name() const
+ {
+ std::string retval;
+ struct Visitor
{
- case ast::Operand_kinds::Operand_kind::Literal_kind::literal_integer:
- underlying_type = "std::uint64_t"_sv;
- break;
- case ast::Operand_kinds::Operand_kind::Literal_kind::literal_string:
- // Literal_string is defined in write_basic_types
+ std::string &retval;
+ const std::string &json_name;
+ void operator()(util::monostate)
+ {
+ retval = detail::name_from_words_initial_capital(json_name).to_string();
+ }
+ void operator()(std::list<Enumeration_descriptor>::const_iterator iter)
+ {
+ retval = iter->cpp_name;
+ }
+ void operator()(std::list<Id_type_descriptor>::const_iterator iter)
+ {
+ retval = iter->cpp_name;
+ }
+ void operator()(ast::Operand_kinds::Operand_kind::Literal_kind literal_kind)
+ {
+ retval = Literal_type_descriptor::get_cpp_name(literal_kind);
+ }
+ };
+ util::visit(Visitor{retval, json_name}, value);
+ return retval;
+ }
+ std::string make_cpp_name_with_parameters() const
+ {
+ auto *iter = util::get_if<std::list<Enumeration_descriptor>::const_iterator>(&value);
+ if(iter)
+ {
+ bool need_parameters = false;
+#warning finish
+ if(need_parameters)
+ return detail::name_from_words_initial_capital(json_name, "with parameters"_sv)
+ .to_string();
+ }
+ return cpp_name;
+ }
+ std::string cpp_name;
+ std::string cpp_name_with_parameters;
+ explicit Operand_kind_descriptor(std::string json_name)
+ : Operand_kind_descriptor(std::move(json_name), util::monostate{})
+ {
+ }
+ template <typename T>
+ Operand_kind_descriptor(std::string json_name, T arg)
+ : json_name(std::move(json_name)),
+ value(std::move(arg)),
+ cpp_name(make_cpp_name()),
+ cpp_name_with_parameters(make_cpp_name_with_parameters())
+ {
+ }
+ };
+
+private:
+ std::list<Operand_kind_descriptor> operand_kind_list;
+ std::unordered_map<std::string, std::list<Operand_kind_descriptor>::const_iterator>
+ operand_kind_map;
+
+private:
+ std::list<Operand_kind_descriptor>::const_iterator add_operand_kind(
+ Operand_kind_descriptor &&operand_kind_descriptor)
+ {
+ auto name = operand_kind_descriptor.json_name;
+ auto iter =
+ operand_kind_list.insert(operand_kind_list.end(), std::move(operand_kind_descriptor));
+ if(!std::get<1>(operand_kind_map.emplace(name, iter)))
+ throw Generate_error("duplicate operand kind: " + name);
+ return iter;
+ }
+ void fill_operand_kinds()
+ {
+ for(auto &operand_kind : top_level.operand_kinds.operand_kinds)
+ {
+ switch(operand_kind.category)
+ {
+ case ast::Operand_kinds::Operand_kind::Category::bit_enum:
+ case ast::Operand_kinds::Operand_kind::Category::value_enum:
+ add_operand_kind(Operand_kind_descriptor(operand_kind.kind,
+ enumerations_map.at(operand_kind.kind)));
+ continue;
+ case ast::Operand_kinds::Operand_kind::Category::id:
+ add_operand_kind(Operand_kind_descriptor(operand_kind.kind,
+ id_type_map.at(operand_kind.kind)));
+ continue;
+ case ast::Operand_kinds::Operand_kind::Category::literal:
+ add_operand_kind(Operand_kind_descriptor(operand_kind.kind,
+ get_literal_kind(operand_kind.kind)));
+ continue;
+ case ast::Operand_kinds::Operand_kind::Category::composite:
+#warning finish
+ add_operand_kind(Operand_kind_descriptor(operand_kind.kind));
continue;
- case ast::Operand_kinds::Operand_kind::Literal_kind::literal_context_dependent_number:
- underlying_type = "std::vector<Word>"_sv;
- break;
- case ast::Operand_kinds::Operand_kind::Literal_kind::literal_ext_inst_integer:
- underlying_type = "Word"_sv;
- break;
- case ast::Operand_kinds::Operand_kind::Literal_kind::literal_spec_constant_op_integer:
- underlying_type = op_enumeration.value()->cpp_name;
- break;
}
- auto &descriptor = literal_type_descriptors.at(*literal_kind);
- spirv_h << R"(
-typedef )" << underlying_type
- << " " << descriptor.cpp_name << R"(;
-)";
+ assert(false);
}
}
{
fill_literal_type_descriptors();
fill_enumerations();
- write_file_comments();
- write_opening_inclusion_guards();
-#warning finish
- spirv_h << R"(#error generator not finished being implemented
-
-)";
- write_includes();
- write_opening_namespaces();
- write_basic_types();
- write_basic_constants();
- write_enum_declarations();
- write_enum_definitions();
- write_enum_properties_definitions();
- write_literal_kinds();
- write_closing_namespaces();
- write_closing_inclusion_guards();
- spirv_h.write_to_file();
- spirv_cpp.write_to_file();
- parser_h.write_to_file();
- parser_cpp.write_to_file();
+ fill_id_type_descriptors();
+ fill_operand_kinds();
+ for(auto *file :
+ std::initializer_list<Output_file_base *>{&spirv_h, &spirv_cpp, &parser_h, &parser_cpp})
+ file->fill_output(*this);
+ for(auto *file :
+ std::initializer_list<Output_file_base *>{&spirv_h, &spirv_cpp, &parser_h, &parser_cpp})
+ file->write_to_file();
}
};