From 183a513bc2ffd52e312e8287d2d8b032aaa29fe4 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Wed, 21 Jun 2017 20:52:43 -0700 Subject: [PATCH] working on adding enum parameters to generate_spirv_parser --- src/generate_spirv_parser/CMakeLists.txt | 3 +- src/generate_spirv_parser/ast.h | 6 +- src/generate_spirv_parser/generate.cpp | 188 ++++++++++++++---- src/generate_spirv_parser/generate.h | 28 ++- .../generate_spirv_parser.cpp | 3 + 5 files changed, 180 insertions(+), 48 deletions(-) diff --git a/src/generate_spirv_parser/CMakeLists.txt b/src/generate_spirv_parser/CMakeLists.txt index 6ac1316..23beaad 100644 --- a/src/generate_spirv_parser/CMakeLists.txt +++ b/src/generate_spirv_parser/CMakeLists.txt @@ -22,6 +22,7 @@ cmake_minimum_required(VERSION 3.1 FATAL_ERROR) set(sources ast.cpp generate.cpp generate_spirv_parser.cpp - parser.cpp) + parser.cpp + patch.cpp) add_executable(generate_spirv_parser ${sources}) target_link_libraries(generate_spirv_parser util json) diff --git a/src/generate_spirv_parser/ast.h b/src/generate_spirv_parser/ast.h index 0d1a1c9..d3fdefa 100644 --- a/src/generate_spirv_parser/ast.h +++ b/src/generate_spirv_parser/ast.h @@ -207,13 +207,11 @@ struct Operand_kinds { enum class Category { - bit_enum, // enum categories must be first + bit_enum, value_enum, - id, literal, - - composite, // composite must be last + composite, }; Category category; static constexpr const char *get_json_name_from_category(Category category) noexcept diff --git a/src/generate_spirv_parser/generate.cpp b/src/generate_spirv_parser/generate.cpp index fd48e25..5252909 100644 --- a/src/generate_spirv_parser/generate.cpp +++ b/src/generate_spirv_parser/generate.cpp @@ -29,8 +29,6 @@ #include #include -#error finish converting to use get_enum_with_parameters_struct_name - namespace vulkan_cpu { namespace generate_spirv_parser @@ -395,7 +393,7 @@ void Generator::write_extensions_set(Generator_state &state, const ast::Extensio state << "}"; } -std::string Generator::get_member_name_from_words(const std::string &words) +std::string Generator::get_name_from_words(const std::string &words) { enum class Char_class { @@ -592,7 +590,7 @@ std::string Generator::get_member_name_from_words(const std::string &words) } #if 0 -#warning testing Generator::get_member_name_from_words +#warning testing Generator::get_name_from_words struct Generator::Tester { struct Test_runner @@ -610,7 +608,7 @@ struct Generator::Tester "abc def", "AbcDef", "ABCDef", "'abc, def'", }) { - std::cout << "\"" << input << "\" -> " << get_member_name_from_words(input) + std::cout << "\"" << input << "\" -> " << get_name_from_words(input) << std::endl; } } @@ -623,16 +621,24 @@ std::string Generator::get_member_name_from_operand( const ast::Instructions::Instruction::Operands::Operand &operand) { if(!operand.name.empty()) - return get_member_name_from_words(operand.name); + return get_name_from_words(operand.name); util::string_view id_str = "Id"; if(util::string_view(operand.kind).compare(0, id_str.size(), id_str) == 0 && id_str.size() < operand.kind.size() && is_uppercase_letter(operand.kind[id_str.size()])) - return get_member_name_from_words(operand.kind.substr(id_str.size())); - return get_member_name_from_words(operand.kind); + return get_name_from_words(operand.kind.substr(id_str.size())); + return get_name_from_words(operand.kind); +} + +std::string Generator::get_member_name_from_parameter( + const ast::Operand_kinds::Operand_kind::Enumerants::Enumerant::Parameters::Parameter ¶meter) +{ + if(!parameter.name.empty()) + return get_name_from_words(parameter.name); + return get_name_from_words(parameter.kind); } -std::string Generator::get_enum_with_parameters_struct_name( +std::string Generator::get_operand_with_parameters_name( Generator_state &state, const ast::Operand_kinds::Operand_kind &operand_kind) { if(get_operand_has_any_parameters(state, operand_kind)) @@ -746,18 +752,31 @@ struct Spirv_header_generator final : public Generator return false; return l < r; } + /** lower priority means that the operand kind is declared first */ + static int get_operand_category_priority( + ast::Operand_kinds::Operand_kind::Category category) noexcept + { + switch(category) + { + case ast::Operand_kinds::Operand_kind::Category::bit_enum: + case ast::Operand_kinds::Operand_kind::Category::value_enum: + return 1; + case ast::Operand_kinds::Operand_kind::Category::id: + return 0; + case ast::Operand_kinds::Operand_kind::Category::literal: + return 0; + case ast::Operand_kinds::Operand_kind::Category::composite: + return 2; + } + return 0; + } static bool compare_operand_kinds(const ast::Operand_kinds::Operand_kind &l, const ast::Operand_kinds::Operand_kind &r) { - // treat both enum categories as equivalent - auto l_category = l.category == ast::Operand_kinds::Operand_kind::Category::bit_enum ? - ast::Operand_kinds::Operand_kind::Category::value_enum : - l.category; - auto r_category = r.category == ast::Operand_kinds::Operand_kind::Category::bit_enum ? - ast::Operand_kinds::Operand_kind::Category::value_enum : - r.category; - if(l_category != r_category) - return l_category < r_category; + auto l_priority = get_operand_category_priority(l.category); + auto r_priority = get_operand_category_priority(r.category); + if(l_priority != r_priority) + return l_priority < r_priority; return compare_enum_names(l.kind, r.kind); } virtual void run(Generator_args &generator_args, const ast::Top_level &top_level) const override @@ -769,7 +788,9 @@ struct Spirv_header_generator final : public Generator state << indent(R"(#include #include "util/enum.h" #include "util/optional.h" +#include "util/variant.h" #include + )"); write_namespaces_start(state, spirv_namespace_names); state << indent(R"(typedef std::uint32_t Word; @@ -869,8 +890,8 @@ constexpr Word magic_number = )") auto unique_enumerants = get_unique_enumerants(enumerants.enumerants); state << "\n" "enum class " - << operand_kind->kind << " : Word\n" - "{\n"; + << get_enum_name(*operand_kind) << " : Word\n" + "{\n"; { auto push_indent = state.pushed_indent(); for(auto &enumerant : enumerants.enumerants) @@ -888,18 +909,18 @@ constexpr Word magic_number = )") state << "};\n" "\n" "vulkan_cpu_util_generate_enum_traits(" - << operand_kind->kind; + << get_enum_name(*operand_kind); { auto push_indent = state.pushed_indent(); for(auto &enumerant : unique_enumerants) - state << ",\n" << indent << operand_kind->kind << "::" + state << ",\n" << indent << get_enum_name(*operand_kind) << "::" << get_enumerant_name(operand_kind->kind, enumerant.enumerant, false); state << ");\n"; } state << "\n" "constexpr const char *get_enumerant_name(" - << operand_kind->kind << " v) noexcept\n" - "{\n"; + << get_enum_name(*operand_kind) << " v) noexcept\n" + "{\n"; { auto push_indent = state.pushed_indent(); state << indent( @@ -907,7 +928,7 @@ constexpr Word magic_number = )") "{\n"); for(auto &enumerant : unique_enumerants) { - state << indent("case ") << operand_kind->kind << "::" + state << indent("case ") << get_enum_name(*operand_kind) << "::" << get_enumerant_name(operand_kind->kind, enumerant.enumerant, false) << indent(true, ":\n" @@ -918,12 +939,12 @@ constexpr Word magic_number = )") "}\n" "return \"\";\n"); } - state << "}\n" - "\n" + state << "}\n"; + state << "\n" "constexpr util::Enum_set<" << capability_enum_name << "> get_directly_required_capability_set(" - << operand_kind->kind << " v) noexcept\n" - "{\n"; + << get_enum_name(*operand_kind) << " v) noexcept\n" + "{\n"; { auto push_indent = state.pushed_indent(); state << indent( @@ -931,11 +952,11 @@ constexpr Word magic_number = )") "{\n"); for(auto &enumerant : unique_enumerants) { - state << indent("case ") << operand_kind->kind << "::" + state << indent("case ") << get_enum_name(*operand_kind) << "::" << get_enumerant_name(operand_kind->kind, enumerant.enumerant, false) << indent(true, ":\n" - "return ") + "`return ") << enumerant.capabilities << ";\n"; } state << indent( @@ -946,8 +967,8 @@ constexpr Word magic_number = )") "\n" "constexpr util::Enum_set<" << extension_enum_name << "> get_directly_required_extension_set(" - << operand_kind->kind << " v) noexcept\n" - "{\n"; + << get_enum_name(*operand_kind) << " v) noexcept\n" + "{\n"; { auto push_indent = state.pushed_indent(); state << indent( @@ -955,11 +976,11 @@ constexpr Word magic_number = )") "{\n"); for(auto &enumerant : unique_enumerants) { - state << indent("case ") << operand_kind->kind << "::" + state << indent("case ") << get_enum_name(*operand_kind) << "::" << get_enumerant_name(operand_kind->kind, enumerant.enumerant, false) << indent(true, ":\n" - "return ") + "`return ") << enumerant.extensions << ";\n"; } state << indent( @@ -978,14 +999,20 @@ constexpr Word magic_number = )") << operand_kind->kind << "\n" "{\n"; auto push_indent = state.pushed_indent(); + std::vector member_types; std::vector member_names; + member_types.reserve(bases.values.size()); member_names.reserve(bases.values.size()); for(std::size_t i = 0; i < bases.values.size(); i++) + { + member_types.push_back( + get_operand_with_parameters_name(state, bases.values[i])); member_names.push_back( json::ast::Number_value::append_unsigned_integer_to_string(i + 1, "part_")); + } write_struct_nonstatic_members_and_constructors(state, operand_kind->kind, - bases.values.data(), + member_types.data(), member_names.data(), bases.values.size()); push_indent.finish(); @@ -1041,6 +1068,95 @@ constexpr Word magic_number = )") } } } + for(auto *operand_kind : operand_kinds) + { + switch(operand_kind->category) + { + case ast::Operand_kinds::Operand_kind::Category::bit_enum: + case ast::Operand_kinds::Operand_kind::Category::value_enum: + { + bool is_bit_enum = + operand_kind->category == ast::Operand_kinds::Operand_kind::Category::bit_enum; + auto &enumerants = + util::get(operand_kind->value); + auto unique_enumerants = get_unique_enumerants(enumerants.enumerants); + if(get_operand_has_any_parameters(state, *operand_kind)) + { + for(auto &enumerant : unique_enumerants) + { + if(enumerant.parameters.empty()) + continue; + auto struct_name = get_enumerant_parameters_struct_name( + operand_kind->kind, enumerant.enumerant, false); + state << "\n" + "struct " + << struct_name << indent(true, R"( +{ +`static constexpr )") << get_enum_name(*operand_kind) + << indent(true, R"( get_enumerant() noexcept +`{ +``return )") << get_enum_name(*operand_kind) + << "::" + << get_enumerant_name(operand_kind->kind, enumerant.enumerant, false) + << indent(true, R"(; +`} +)"); + std::vector member_types; + std::vector member_names; + member_types.reserve(enumerant.parameters.parameters.size()); + member_names.reserve(enumerant.parameters.parameters.size()); + for(auto ¶meter : enumerant.parameters.parameters) + { + member_types.push_back( + get_operand_with_parameters_name(state, parameter.kind)); + member_names.push_back(get_member_name_from_parameter(parameter)); + } + auto push_indent = state.pushed_indent(); + write_struct_nonstatic_members_and_constructors( + state, + struct_name, + member_types.data(), + member_names.data(), + enumerant.parameters.parameters.size()); + push_indent.finish(); + state << "};\n"; + } + auto struct_name = get_operand_with_parameters_name(state, *operand_kind); + state << indent(R"( +struct )") << struct_name << indent(true, R"( +{ +`typedef util::variantkind, enumerant.enumerant, false); + } + state << indent(true, R"(> Parameters; +)"); + auto push_indent = state.pushed_indent(); + constexpr std::size_t member_count = 2; + std::string member_types[member_count] = { + get_enum_name(*operand_kind), "Parameters", + }; + std::string member_names[member_count] = { + "value", "parameters", + }; + write_struct_nonstatic_members_and_constructors( + state, struct_name, member_types, member_names, member_count); + push_indent.finish(); + state << "};\n"; + } + break; + } + case ast::Operand_kinds::Operand_kind::Category::composite: + case ast::Operand_kinds::Operand_kind::Category::id: + case ast::Operand_kinds::Operand_kind::Category::literal: + break; + } + } +#warning finish converting std::vector instructions; instructions.reserve(top_level.instructions.instructions.size()); for(auto &instruction : top_level.instructions.instructions) diff --git a/src/generate_spirv_parser/generate.h b/src/generate_spirv_parser/generate.h index 7a76acb..4cfc4f6 100644 --- a/src/generate_spirv_parser/generate.h +++ b/src/generate_spirv_parser/generate.h @@ -360,9 +360,11 @@ protected: static void write_capabilities_set(Generator_state &state, const ast::Capabilities &capabilities); static void write_extensions_set(Generator_state &state, const ast::Extensions &extensions); - static std::string get_member_name_from_words(const std::string &words); + static std::string get_name_from_words(const std::string &words); static std::string get_member_name_from_operand( const ast::Instructions::Instruction::Operands::Operand &operand); + static std::string get_member_name_from_parameter( + const ast::Operand_kinds::Operand_kind::Enumerants::Enumerant::Parameters::Parameter ¶meter); static const ast::Operand_kinds::Operand_kind &get_operand_kind_from_string( Generator_state &state, const std::string &operand_kind_str) { @@ -376,20 +378,32 @@ protected: { return state.operand_has_any_parameters_map[&operand_kind]; } - static std::string get_enumerant_parameters_struct_name(util::string_view enumeration_name, std::string enumerant_name, bool input_name_should_have_prefix) + static std::string get_enumerant_parameters_struct_name(util::string_view enumeration_name, + std::string enumerant_name, + bool input_name_should_have_prefix) { - auto retval = "_" + get_enumerant_name(enumeration_name, enumerant_name, input_name_should_have_prefix) + "_parameters"; + auto retval = "_" + get_enumerant_name( + enumeration_name, enumerant_name, input_name_should_have_prefix) + + "_parameters"; retval.insert(retval.begin(), enumeration_name.begin(), enumeration_name.end()); return retval; } - static std::string get_enum_with_parameters_struct_name( + static std::string get_operand_with_parameters_name( Generator_state &state, const ast::Operand_kinds::Operand_kind &operand_kind); - static std::string get_enum_with_parameters_struct_name(Generator_state &state, - const std::string &operand_kind_str) + static std::string get_operand_with_parameters_name(Generator_state &state, + const std::string &operand_kind_str) { - return get_enum_with_parameters_struct_name( + return get_operand_with_parameters_name( state, get_operand_kind_from_string(state, operand_kind_str)); } + static std::string get_enum_name(std::string operand_kind_str) + { + return operand_kind_str; + } + static std::string get_enum_name(const ast::Operand_kinds::Operand_kind &operand_kind) + { + return get_enum_name(operand_kind.kind); + } static void write_struct_nonstatic_members_and_constructors(Generator_state &state, const std::string &struct_name, const std::string *member_types, diff --git a/src/generate_spirv_parser/generate_spirv_parser.cpp b/src/generate_spirv_parser/generate_spirv_parser.cpp index 05e1579..8888aa9 100644 --- a/src/generate_spirv_parser/generate_spirv_parser.cpp +++ b/src/generate_spirv_parser/generate_spirv_parser.cpp @@ -26,6 +26,7 @@ #include "parser.h" #include "util/optional.h" #include "generate.h" +#include "patch.h" namespace vulkan_cpu { @@ -53,6 +54,8 @@ int generate_spirv_parser_main(int argc, char **argv) { auto json_in = json::parse(&source); auto ast = parser::parse(json_in.duplicate()); + for(auto *patch : Ast_patches::get_patches()) + patch->run(ast, &std::cout); for(auto &generator : generate::Generators::make_all_generators()) { generator->run(generate::Generator::Generator_args(output_directory), ast); -- 2.30.2