From: Jacob Lifshay Date: Tue, 4 Jul 2017 14:43:39 +0000 (-0700) Subject: working on refactoring generate_spirv_parser X-Git-Tag: gsoc-2017~73^2~10 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=98c30271bf152812b05e0c036dff307ff097a6bf;p=kazan.git working on refactoring generate_spirv_parser --- diff --git a/src/generate_spirv_parser/generate.cpp b/src/generate_spirv_parser/generate.cpp index a537c2d..bbbbba2 100644 --- a/src/generate_spirv_parser/generate.cpp +++ b/src/generate_spirv_parser/generate.cpp @@ -23,6 +23,7 @@ #include "generate.h" #include "json/json.h" #include +#include #include #include #include @@ -291,115 +292,442 @@ struct Spirv_and_parser_generator : public Generator 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::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_parts; + template + void register_output_part(Output_part part, + detail::Generated_output_stream Derived_class::*variable) + { + static_assert(std::is_base_of::value, ""); + assert(dynamic_cast(this)); + output_parts.insert_or_assign( + part, static_cast(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 = "<<<<>>>>"_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"_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 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: @@ -606,11 +934,6 @@ 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; @@ -621,68 +944,6 @@ private: 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; @@ -699,97 +960,6 @@ vulkan_cpu_util_generate_enum_traits()" 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 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 @@ -812,8 +982,8 @@ private: }; private: - util::Enum_map literal_type_descriptors; + util::Enum_map + literal_type_descriptors; private: void fill_literal_type_descriptors() @@ -824,40 +994,167 @@ private: 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_list; + std::unordered_map::const_iterator> id_type_map; + +private: + std::list::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 = "<<<<>>>>"_sv; - switch(*literal_kind) + add_id_type_descriptor(Id_type_descriptor(operand_kind.kind)); + } + } + std::list::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::const_iterator, + std::list::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::const_iterator iter) + { + retval = iter->cpp_name; + } + void operator()(std::list::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::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 + 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_list; + std::unordered_map::const_iterator> + operand_kind_map; + +private: + std::list::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"_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); } } @@ -866,26 +1163,14 @@ public: { 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{&spirv_h, &spirv_cpp, &parser_h, &parser_cpp}) + file->fill_output(*this); + for(auto *file : + std::initializer_list{&spirv_h, &spirv_cpp, &parser_h, &parser_cpp}) + file->write_to_file(); } }; diff --git a/src/generate_spirv_parser/generate.h b/src/generate_spirv_parser/generate.h index 34aa3dc..453b72d 100644 --- a/src/generate_spirv_parser/generate.h +++ b/src/generate_spirv_parser/generate.h @@ -28,11 +28,13 @@ #include "util/filesystem.h" #include "util/string_view.h" #include "word_iterator.h" +#include "util/enum.h" #include #include #include #include #include +#include namespace vulkan_cpu { @@ -212,6 +214,12 @@ public: value.push_back(ch); return *this; } + Generated_output_stream &operator<<(const Generated_output_stream &s) + { + assert(this != &s); + value.insert(value.end(), s.value.begin(), s.value.end()); + return *this; + } Generated_output_stream &operator<<(util::string_view sv) { for(char ch : sv) @@ -396,12 +404,10 @@ public: } template static constexpr Name_from_words_holder - name_from_words(Name_format name_format, Args &&... args) noexcept( - noexcept(Name_from_words_holder(name_format, - std::forward(args)...))) + name_from_words(Name_format name_format, Args &&... args) noexcept(noexcept( + Name_from_words_holder(name_format, std::forward(args)...))) { - return Name_from_words_holder(name_format, - std::forward(args)...); + return Name_from_words_holder(name_format, std::forward(args)...); } }; @@ -438,38 +444,51 @@ constexpr auto signed_integer(std::int64_t value, unsigned base) noexcept constexpr Generated_output_stream::Guard_macro guard_macro{}; template -constexpr auto name_from_words(Generated_output_stream::Name_format name_format, Args &&... args) noexcept( - noexcept(Generated_output_stream::name_from_words(name_format, std::forward(args)...))) +constexpr auto name_from_words( + Generated_output_stream::Name_format name_format, + Args &&... args) noexcept(noexcept(Generated_output_stream::name_from_words(name_format, + std::forward( + args)...))) { return Generated_output_stream::name_from_words(name_format, std::forward(args)...); } template constexpr auto name_from_words_all_lowercase(Args &&... args) noexcept( - noexcept(Generated_output_stream::name_from_words(Generated_output_stream::all_lowercase, std::forward(args)...))) + noexcept(Generated_output_stream::name_from_words(Generated_output_stream::all_lowercase, + std::forward(args)...))) { - return Generated_output_stream::name_from_words(Generated_output_stream::all_lowercase, std::forward(args)...); + return Generated_output_stream::name_from_words(Generated_output_stream::all_lowercase, + std::forward(args)...); } template constexpr auto name_from_words_all_uppercase(Args &&... args) noexcept( - noexcept(Generated_output_stream::name_from_words(Generated_output_stream::all_uppercase, std::forward(args)...))) + noexcept(Generated_output_stream::name_from_words(Generated_output_stream::all_uppercase, + std::forward(args)...))) { - return Generated_output_stream::name_from_words(Generated_output_stream::all_uppercase, std::forward(args)...); + return Generated_output_stream::name_from_words(Generated_output_stream::all_uppercase, + std::forward(args)...); } template constexpr auto name_from_words_initial_capital(Args &&... args) noexcept( - noexcept(Generated_output_stream::name_from_words(Generated_output_stream::initial_capital, std::forward(args)...))) + noexcept(Generated_output_stream::name_from_words(Generated_output_stream::initial_capital, + std::forward(args)...))) { - return Generated_output_stream::name_from_words(Generated_output_stream::initial_capital, std::forward(args)...); + return Generated_output_stream::name_from_words(Generated_output_stream::initial_capital, + std::forward(args)...); } template constexpr auto name_from_words_all_uppercase_with_trailing_underline(Args &&... args) noexcept( - noexcept(Generated_output_stream::name_from_words(Generated_output_stream::all_uppercase_with_trailing_underline, std::forward(args)...))) + noexcept(Generated_output_stream::name_from_words( + Generated_output_stream::all_uppercase_with_trailing_underline, + std::forward(args)...))) { - return Generated_output_stream::name_from_words(Generated_output_stream::all_uppercase_with_trailing_underline, std::forward(args)...); + return Generated_output_stream::name_from_words( + Generated_output_stream::all_uppercase_with_trailing_underline, + std::forward(args)...); } }