From 1982e3599ce8d46674ab1847d47822fd732fb6c4 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Tue, 11 Jul 2017 05:20:42 -0700 Subject: [PATCH] generate_spirv_parser generates all of spirv::Dump_callbacks --- src/generate_spirv_parser/generate.cpp | 227 ++++++++++++++++++++----- 1 file changed, 189 insertions(+), 38 deletions(-) diff --git a/src/generate_spirv_parser/generate.cpp b/src/generate_spirv_parser/generate.cpp index eb020f7..efd29f1 100644 --- a/src/generate_spirv_parser/generate.cpp +++ b/src/generate_spirv_parser/generate.cpp @@ -420,6 +420,7 @@ static_assert(util::Enum_traits::is_compact, struct Spirv_and_parser_generator::State { private: + struct Operand_descriptor; struct Output_base { Output_base(const Output_base &) = delete; @@ -1123,6 +1124,26 @@ constexpr util::Enum_set<)" << state.extension_enumeration.value()->cpp_name true); } } + void write_instruction_operand(State &state, + const Operand_descriptor &operand, + Output_struct &instruction_struct) + { + typedef Operand_descriptor::Quantifier Quantifier; + std::string member_type = + state.get_operand_kind(operand.json_kind)->cpp_name_with_parameters; + switch(operand.quantifier) + { + case Quantifier::none: + break; + case Quantifier::optional: + member_type = "util::optional<" + std::move(member_type) + ">"; + break; + case Quantifier::variable: + member_type = "std::vector<" + std::move(member_type) + ">"; + break; + } + instruction_struct.add_nonstatic_member(member_type, operand.cpp_name, true); + } void write_instructions(State &state) { for(auto &instruction_descriptor : state.instruction_descriptor_list) @@ -1137,25 +1158,10 @@ constexpr util::Enum_set<)" << state.extension_enumeration.value()->cpp_name << "::" << instruction_descriptor.enumerant->cpp_name << R"(; } )"; - for(auto &operand : instruction_descriptor.operands) - { - typedef Operand_descriptor::Quantifier Quantifier; - std::string member_type = - state.get_operand_kind(operand.json_kind)->cpp_name_with_parameters; - switch(operand.quantifier) - { - case Quantifier::none: - break; - case Quantifier::optional: - member_type = "util::optional<" + std::move(member_type) + ">"; - break; - case Quantifier::variable: - member_type = "std::vector<" + std::move(member_type) + ">"; - break; - } - instruction_struct.add_nonstatic_member(member_type, operand.cpp_name, true); - } -#warning finish + for(auto &operand : instruction_descriptor.implied_operands) + write_instruction_operand(state, operand, instruction_struct); + for(auto &operand : instruction_descriptor.explicit_operands) + write_instruction_operand(state, operand, instruction_struct); } } virtual void fill_output(State &state) override @@ -1209,6 +1215,35 @@ constexpr util::Enum_set<)" << state.extension_enumeration.value()->cpp_name &Parser_h::dump_callbacks_class); register_output_part(Output_part::parser_class, &Parser_h::parser_class); } + void write_instruction_operand(State &state, Operand_descriptor &operand) + { + typedef Operand_descriptor::Quantifier Quantifier; + auto operand_kind = state.get_operand_kind(operand.json_kind); + switch(operand.quantifier) + { + case Quantifier::none: + dump_callbacks_class << operand_kind->cpp_dump_function_name << "(instruction." + << operand.cpp_name << ", indent_depth + 1);\n"; +#warning finish + break; + case Quantifier::optional: + dump_callbacks_class << "if(instruction." << operand.cpp_name << R"() + )" << operand_kind->cpp_dump_function_name + << "(*instruction." << operand.cpp_name + << R"(, indent_depth + 1); +)"; +#warning finish + break; + case Quantifier::variable: + dump_callbacks_class << "for(auto &operand : instruction." << operand.cpp_name + << R"() + )" << operand_kind->cpp_dump_function_name + << R"((operand, indent_depth + 1); +)"; +#warning finish + break; + } + } virtual void fill_output(State &state) override { Header_file_base::fill_output(state); @@ -1369,10 +1404,10 @@ if(bits == 0) else if(enumerant.value & (enumerant.value - 1)) { throw Generate_error( - "in bitwise enum, enumerant is not a power of 2 or zero: " - + enumeration->json_name - + "." - + enumerant.json_name); + "in bitwise enum, enumerant is not a power of 2 or zero: " + + enumeration->json_name + + "." + + enumerant.json_name); } dump_callbacks_class << R"(if(bits & static_cast()" << enumeration->cpp_name << "::" << enumerant.cpp_name @@ -1383,21 +1418,80 @@ if(bits == 0) << R"(\n"; bits &= ~static_cast()" << enumeration->cpp_name << "::" << enumerant.cpp_name << R"(); -)"; - for(auto ¶meter : enumerant.parameters) +@+)"; + if(!enumerant.parameters.empty()) { - parameter; -#warning finish + dump_callbacks_class << "auto ¶meters = *operand." + << enumerant.parameters_variable_cpp_name << ";\n"; + } + for(auto *parameter : enumerant.parameters) + { + auto parameter_operand_kind = + state.get_operand_kind(parameter->json_kind); + dump_callbacks_class << parameter_operand_kind->cpp_dump_function_name + << R"((parameters.)" << parameter->cpp_name + << R"(, indent_depth + 2); +)"; } - dump_callbacks_class << R"(} + dump_callbacks_class << R"(@-} )"; } -#warning finish break; } case Category::value_enum: -#warning finish + { + dump_callbacks_class << R"(write_indent(indent_depth); +ss << ")" << operand_kind.operand_kind->kind + << R"(: "; +switch(operand)" << (operand_kind.enum_parameters.empty() ? "" : ".value") + << R"() +{ +)"; + auto enumeration = util::get::const_iterator>( + operand_kind.value); + std::unordered_set values; + for(auto &enumerant : enumeration->enumerants) + { + if(!std::get<1>(values.insert(enumerant.value))) + continue; // skip duplicate values + dump_callbacks_class << "case " << enumeration->cpp_name + << "::" << enumerant.cpp_name << R"(: +)" << (enumerant.parameters.empty() ? "" : "{\n") + << R"( ss << ")" << enumerant.json_name + << (enumerant.parameters.empty() ? "" : ":") << R"(\n"; +@+)"; + if(!enumerant.parameters.empty()) + { + dump_callbacks_class << "auto ¶meters = util::get<" + << enumerant.parameters_struct_cpp_name + << ">(operand.parameters);\n"; + for(auto *parameter : enumerant.parameters) + { + auto parameter_operand_kind = + state.get_operand_kind(parameter->json_kind); + dump_callbacks_class + << parameter_operand_kind->cpp_dump_function_name + << R"((parameters.)" << parameter->cpp_name + << R"(, indent_depth + 1); +)"; + } + dump_callbacks_class << R"(return; +@-} +)"; + } + else + { + dump_callbacks_class << R"(return; +@-)"; + } + } + dump_callbacks_class << R"(} +ss << " (" << static_cast(operand)" + << (operand_kind.enum_parameters.empty() ? "" : ".value") + << R"() << ")\n"; +)"; break; + } case Category::id: dump_callbacks_class << R"(write_indent(indent_depth); ss << ")" << operand_kind.operand_kind->kind @@ -1454,7 +1548,6 @@ ss << "}\n"; } case Category::composite: { -#warning finish dump_callbacks_class << R"(write_indent(indent_depth); ss << ")" << operand_kind.operand_kind->kind << R"(:\n"; @@ -1482,7 +1575,30 @@ ss << ")" << operand_kind.operand_kind->kind << " instruction) = 0;\n"; dump_callbacks_class << "virtual void " << instruction.cpp_parse_callback_name << "(" << instruction.cpp_struct_name - << " instruction) override\n{\n@+"; + << R"( instruction) override +{ + ss << ")"; + if(instruction.extension_instruction_set) + dump_callbacks_class << op_ext_inst_json_name; + else + dump_callbacks_class << instruction.json_name; + dump_callbacks_class << R"(:\n"; +@+)"; + if(!instruction.implied_operands.empty() || !instruction.explicit_operands.empty() + || instruction.extension_instruction_set) + dump_callbacks_class << "constexpr std::size_t indent_depth = 0;\n"; + else + dump_callbacks_class << "static_cast(instruction);\n"; + for(auto &operand : instruction.implied_operands) + write_instruction_operand(state, operand); + if(instruction.extension_instruction_set) + { + dump_callbacks_class << R"(write_indent(indent_depth + 1); +ss << ")" << instruction.json_name << R"(\n"; +)"; + } + for(auto &operand : instruction.explicit_operands) + write_instruction_operand(state, operand); #warning finish dump_callbacks_class << "@-}\n"; } @@ -1527,6 +1643,11 @@ private: "Extension_instruction_set"_sv; static constexpr util::string_view unknown_extension_instruction_set_enumerant_json_name = "Unknown"_sv; + static constexpr util::string_view op_ext_inst_import_json_name = "OpExtInstImport"_sv; + static constexpr util::string_view op_ext_inst_json_name = "OpExtInst"_sv; + static constexpr util::string_view id_result_json_name = "IdResult"_sv; + static constexpr util::string_view id_result_type_json_name = "IdResultType"_sv; + static constexpr util::string_view id_ref_json_name = "IdRef"_sv; struct Enum_parameter; struct Enumerant_descriptor { @@ -2213,7 +2334,8 @@ private: std::list::const_iterator enumerant; const ast::Extension_instruction_set *extension_instruction_set; std::string json_name; - std::list operands; + std::list implied_operands; + std::list explicit_operands; const Instruction_properties_descriptor *properties_descriptor; static std::string make_cpp_struct_name( const ast::Extension_instruction_set *extension_instruction_set, @@ -2235,7 +2357,8 @@ private: std::list::const_iterator enumerant, const ast::Extension_instruction_set *extension_instruction_set, std::string json_name, - std::list operands, + std::list implied_operands, + std::list explicit_operands, const Instruction_properties_descriptor *properties_descriptor) : cpp_struct_name(make_cpp_struct_name(extension_instruction_set, json_name)), cpp_parse_callback_name(make_cpp_parse_callback_name(cpp_struct_name)), @@ -2243,7 +2366,8 @@ private: enumerant(enumerant), extension_instruction_set(extension_instruction_set), json_name(std::move(json_name)), - operands(std::move(operands)), + implied_operands(std::move(implied_operands)), + explicit_operands(std::move(explicit_operands)), properties_descriptor(properties_descriptor) { } @@ -2354,6 +2478,25 @@ private: retval += "}},"; return retval; } + std::list make_instruction_implied_operands(bool is_extension) + { + if(!is_extension) + return {}; + std::list retval; + retval.push_back(Operand_descriptor( + "", + std::string(id_result_type_json_name), + ast::Instructions::Instruction::Operands::Operand::Quantifier::none)); + retval.push_back(Operand_descriptor( + "", + std::string(id_result_json_name), + ast::Instructions::Instruction::Operands::Operand::Quantifier::none)); + retval.push_back(Operand_descriptor( + "'Set'", + std::string(id_ref_json_name), + ast::Instructions::Instruction::Operands::Operand::Quantifier::none)); + return retval; + } void fill_instruction_descriptors( const ast::Extension_instruction_set *extension_instruction_set, const ast::Instructions &instructions) @@ -2389,7 +2532,9 @@ private: get_instruction_properties_descriptor(extension_instruction_set->import_name, instruction.opname) : get_instruction_properties_descriptor({}, instruction.opname); - std::list operands; + auto implied_operands = + make_instruction_implied_operands(extension_instruction_set != nullptr); + std::list explicit_operands; util::optional operand_properties_iter; if(instruction_properties_descriptor) @@ -2397,7 +2542,7 @@ private: instruction_properties_descriptor->operand_descriptors.begin(); for(auto &operand : instruction.operands.operands) { - operands.push_back( + explicit_operands.push_back( Operand_descriptor(operand.name, operand.kind, operand.quantifier)); bool has_integer_literal_size = false; if(operand_properties_iter) @@ -2440,7 +2585,8 @@ private: enumerant, extension_instruction_set, instruction.opname, - std::move(operands), + std::move(implied_operands), + std::move(explicit_operands), instruction_properties_descriptor)); } } @@ -2477,6 +2623,11 @@ constexpr util::string_view Spirv_and_parser_generator::State::extension_instruction_set_enum_json_name; constexpr util::string_view Spirv_and_parser_generator::State::unknown_extension_instruction_set_enumerant_json_name; +constexpr util::string_view Spirv_and_parser_generator::State::op_ext_inst_import_json_name; +constexpr util::string_view Spirv_and_parser_generator::State::op_ext_inst_json_name; +constexpr util::string_view Spirv_and_parser_generator::State::id_result_json_name; +constexpr util::string_view Spirv_and_parser_generator::State::id_result_type_json_name; +constexpr util::string_view Spirv_and_parser_generator::State::id_ref_json_name; void Spirv_and_parser_generator::run(Generator_args &generator_args, const ast::Top_level &top_level) const -- 2.30.2