From: Jacob Lifshay Date: Thu, 13 Jul 2017 01:21:28 +0000 (-0700) Subject: remove old files X-Git-Tag: gsoc-2017~73^2 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=76e499b04f354af9db7bd2a87ac28009bc340667;p=kazan.git remove old files --- diff --git a/src/generate_spirv_parser/generate-old.cpp b/src/generate_spirv_parser/generate-old.cpp deleted file mode 100644 index ab78874..0000000 --- a/src/generate_spirv_parser/generate-old.cpp +++ /dev/null @@ -1,2342 +0,0 @@ -/* - * Copyright 2017 Jacob Lifshay - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ -#include "generate-old.h" -#include "json/json.h" -#include "util/optional.h" -#include -#include -#include -#include -#include - -namespace vulkan_cpu -{ -namespace generate_spirv_parser -{ -namespace generate -{ -Generator::Generator_state::Generator_state(const Generator *generator, - Generator_args &generator_args, - const ast::Top_level &top_level) - : generator_args(generator_args), - indent_level(0), - full_output_file_name(generator_args.output_directory + "/" - + generator->output_base_file_name), - guard_macro_name(get_guard_macro_name_from_file_name(full_output_file_name)), - os(), - top_level(top_level), - operand_kind_map(), - operand_has_any_parameters_map() -{ - os.exceptions(std::ios::badbit | std::ios::failbit); - for(auto &operand_kind : top_level.operand_kinds.operand_kinds) - { - operand_kind_map.emplace(operand_kind.kind, &operand_kind); - bool &has_any_parameters = operand_has_any_parameters_map[&operand_kind]; - has_any_parameters = false; - if(util::holds_alternative( - operand_kind.value)) - { - auto &enumerants = - util::get(operand_kind.value); - for(auto &enumerant : enumerants.enumerants) - { - if(!enumerant.parameters.empty()) - { - has_any_parameters = true; - break; - } - } - } - } -} - -void Generator::Generator_state::open_output_file() -{ - os.open(full_output_file_name); -} - -constexpr Generator::Indent_t Generator::indent; -constexpr const char *Generator::vulkan_cpu_namespace_name; -constexpr const char *Generator::spirv_namespace_name; -constexpr const char *Generator::spirv_namespace_names[]; -constexpr const char *Generator::extension_enum_name; -constexpr const char *Generator::capability_enum_name; -constexpr const char *Generator::op_enum_name; - -std::string Generator::get_guard_macro_name_from_file_name(std::string file_name) -{ - auto retval = std::move(file_name); - for(char &ch : retval) - { - if(ch >= 'a' && ch <= 'z') - { - ch = ch - 'a' + 'A'; // convert to uppercase - continue; - } - if(ch >= 'A' && ch <= 'Z') - continue; - if(ch >= '0' && ch <= '9') - continue; - ch = '_'; - } - retval += '_'; - if(retval[0] >= '0' && retval[0] <= '9') - retval.insert(0, 1, '_'); - for(std::size_t double_underline_index = retval.find("__"); - double_underline_index != std::string::npos; - double_underline_index = retval.find("__", double_underline_index + 1)) - { - // insert a u in all pairs of underlines to prevent generating a reserved identifier - retval.insert(++double_underline_index, "u"); - } - if(retval.size() >= 2 && retval[0] == '_' && retval[1] >= 'A' && retval[1] <= 'Z') - { - // insert a u to prevent generating a reserved identifier: starting with an underline and a - // capital letter - retval.insert(1, "u"); - } - return retval; -} - -namespace -{ -constexpr bool is_uppercase_letter(char ch) noexcept -{ - if(ch >= 'A' && ch <= 'Z') - return true; - return false; -} - -constexpr bool is_lowercase_letter(char ch) noexcept -{ - if(ch >= 'a' && ch <= 'z') - return true; - return false; -} - -constexpr bool is_letter(char ch) noexcept -{ - return is_uppercase_letter(ch) || is_lowercase_letter(ch); -} - -constexpr bool is_identifier_start(char ch) noexcept -{ - return is_letter(ch) || ch == '_'; -} - -constexpr bool is_digit(char ch) noexcept -{ - if(ch >= '0' && ch <= '9') - return true; - return false; -} -} - -std::string Generator::get_enumerant_name(const char *enumeration_name, - std::size_t enumeration_name_size, - std::string enumerant_name, - bool input_name_should_have_prefix) -{ - bool starts_with_enumeration_name = - enumerant_name.compare(0, enumeration_name_size, enumeration_name, enumeration_name_size) - == 0; - bool starts_with_doubled_enumeration_name = false; - if(starts_with_enumeration_name) - starts_with_doubled_enumeration_name = enumerant_name.compare(enumeration_name_size, - enumeration_name_size, - enumeration_name, - enumeration_name_size) - == 0; - std::size_t needed_prefix_count; - if(input_name_should_have_prefix) - { - if(!starts_with_enumeration_name) - needed_prefix_count = 2; - else if(starts_with_doubled_enumeration_name) - needed_prefix_count = 1; - else - needed_prefix_count = 0; - } - else - { - if(starts_with_enumeration_name) - needed_prefix_count = 1; // ensure that we don't end up with name collisions - else if(enumerant_name.empty()) - needed_prefix_count = 1; // return something other than the empty string - else - needed_prefix_count = is_identifier_start(enumerant_name[0]) ? 0 : 1; - } - for(std::size_t i = 0; i < needed_prefix_count; i++) - enumerant_name.insert(0, enumeration_name, enumeration_name_size); - return enumerant_name; -} - -void Generator::write_indent_absolute(Generator_state &state, std::size_t amount) -{ - static constexpr auto indent_string = " "; - for(std::size_t i = 0; i < amount; i++) - state << indent_string; -} - -void Generator::write_indent_interpreted_text(Generator_state &state, - const char *text, - std::ptrdiff_t offset, - bool start_indented) -{ - bool did_indent = start_indented; - std::size_t indent_amount = offset + state.indent_level; - for(; *text; text++) - { - auto &ch = *text; - if(ch == '\n') - { - state << ch; - did_indent = false; - indent_amount = offset + state.indent_level; - } - else if(!did_indent && ch == '`') - { - indent_amount++; - } - else - { - if(!did_indent) - { - did_indent = true; - write_indent_absolute(state, indent_amount); - } - state << ch; - } - } -} - -void Generator::write_automatically_generated_file_warning(Generator_state &state) -{ - state - << "/* This file is automatically generated by generate_spirv_parser. DO NOT MODIFY. */\n"; -} - -void Generator::write_copyright_comment(Generator_state &state, const ast::Copyright ©right) -{ - state << "/*\n"; - for(auto &line : copyright.lines) - { - if(line.empty()) - { - state << " *\n"; - continue; - } - state << " * "; - bool was_last_star = false; - for(char ch : line) - { - if(was_last_star && ch == '/') - state << ' '; - was_last_star = (ch == '*'); - state << ch; - } - state << "\n"; - } - state << " */\n"; -} - -void Generator::write_file_guard_start(Generator_state &state) -{ - state << "#ifndef " << state.guard_macro_name << R"( -#define )" - << state.guard_macro_name << "\n" - "\n"; -} - -void Generator::write_file_guard_end(Generator_state &state) -{ - state << "#endif /* " << state.guard_macro_name << " */\n"; -} - -void Generator::write_namespace_start(Generator_state &state, const char *namespace_name) -{ - state << "namespace " << namespace_name << "\n" - "{\n"; -} - -void Generator::write_namespace_start(Generator_state &state, const std::string &namespace_name) -{ - state << "namespace " << namespace_name << "\n" - "{\n"; -} - -void Generator::write_namespace_end(Generator_state &state) -{ - state << "}\n"; -} - -void Generator::write_unsigned_integer_literal(Generator_state &state, - std::uint64_t value, - Integer_literal_base base, - std::size_t minimum_digit_count) -{ - constexpr std::uint64_t max_unsigned_value = std::numeric_limits::max(); - constexpr std::uint64_t max_unsigned_long_value = std::numeric_limits::max(); - auto literal_type = - value <= max_unsigned_value ? "U" : value <= max_unsigned_long_value ? "UL" : "ULL"; - auto number_prefix = ""; - unsigned base_as_number = 10; - switch(base) - { - case Integer_literal_base::dec: - minimum_digit_count = 1; - break; - case Integer_literal_base::hex: - base_as_number = 0x10; - number_prefix = "0x"; - break; - case Integer_literal_base::oct: - base_as_number = 010; - number_prefix = "0"; - break; - } - auto number_string = json::ast::Number_value::append_unsigned_integer_to_string( - value, number_prefix, base_as_number, minimum_digit_count) - + literal_type; - state << number_string; -} - -void Generator::write_signed_integer_literal(Generator_state &state, std::int64_t value) -{ - constexpr std::int64_t max_int_value = std::numeric_limits::max(); - constexpr std::int64_t min_int_value = std::numeric_limits::min(); - constexpr std::int64_t max_long_value = std::numeric_limits::max(); - constexpr std::int64_t min_long_value = std::numeric_limits::min(); - auto literal_type = ""; - if(value < min_int_value || value > max_int_value) - literal_type = "L"; - if(value < min_long_value || value > max_long_value) - literal_type = "LL"; - state << value << literal_type; -} - -struct Generator::Get_extensions_visitor -{ - std::unordered_set &retval; - constexpr Get_extensions_visitor(std::unordered_set &retval) noexcept - : retval(retval) - { - } - template - void operator()(const T &) - { - } - void operator()(const ast::Extensions &extensions) - { - for(auto &extension : extensions.extensions) - retval.insert(extension); - } -}; - -std::unordered_set Generator::get_extensions(const ast::Top_level &top_level) -{ - std::unordered_set retval; - top_level.visit(Get_extensions_visitor(retval)); - return retval; -} - -void Generator::write_capabilities_set(Generator_state &state, - const ast::Capabilities &capabilities) -{ - state << "util::Enum_set<" << capability_enum_name << ">{"; - auto separator = ""; - for(auto &capability : capabilities.capabilities) - { - state << separator << capability_enum_name - << "::" << get_enumerant_name(capability_enum_name, capability, false); - separator = ", "; - } - state << "}"; -} - -void Generator::write_extensions_set(Generator_state &state, const ast::Extensions &extensions) -{ - state << "util::Enum_set<" << extension_enum_name << ">{"; - auto separator = ""; - for(auto &extension : extensions.extensions) - { - state << separator << extension_enum_name - << "::" << get_enumerant_name(extension_enum_name, extension, false); - separator = ", "; - } - state << "}"; -} - -std::string Generator::get_name_from_words(const std::string &words) -{ - enum class Char_class - { - Uppercase, - OtherIdentifier, - WordSeparator, - }; - auto get_char_class = [](char ch) -> Char_class - { - if(is_uppercase_letter(ch)) - return Char_class::Uppercase; - if(is_letter(ch) || is_digit(ch)) - return Char_class::OtherIdentifier; - return Char_class::WordSeparator; - }; - auto find_words = [&](auto found_word_callback) -> void - { - util::optional word_start; - auto finish_word = [&](std::size_t index) - { - found_word_callback(util::string_view(words.data() + *word_start, index - *word_start)); - word_start = {}; - }; - auto start_word = [&](std::size_t index) - { - word_start = index; - }; - auto last_char_class = Char_class::WordSeparator; - for(std::size_t i = 0; i < words.size(); i++) - { - auto current_char_class = get_char_class(words[i]); - if(word_start) - { - switch(current_char_class) - { - case Char_class::WordSeparator: - finish_word(i); - break; - case Char_class::Uppercase: - if(last_char_class != Char_class::Uppercase) - { - finish_word(i); - start_word(i); - } - else if(i + 1 < words.size() - && get_char_class(words[i + 1]) == Char_class::OtherIdentifier) - { - finish_word(i); - start_word(i); - } - break; - case Char_class::OtherIdentifier: - break; - } - } - else if(current_char_class != Char_class::WordSeparator) - { - start_word(i); - } - last_char_class = current_char_class; - } - if(word_start) - finish_word(words.size()); - }; - std::size_t retval_size = 0; - bool first = true; - find_words([&](util::string_view word) - { - if(!first) - retval_size++; // separating '_' - first = false; - retval_size += word.size(); - }); - std::string retval; - retval.reserve(retval_size); - first = true; - find_words([&](util::string_view word) - { - if(!first) - retval += '_'; - first = false; - retval += word; - }); - for(char &ch : retval) - { - if(is_uppercase_letter(ch)) - ch = ch - 'A' + 'a'; // to lowercase - } - static constexpr const char *const reserved_words[] = { - "alignas", - "alignof", - "and", - "and_eq", - "asm", - "atomic_cancel", - "atomic_commit", - "atomic_noexcept", - "auto", - "bitand", - "bitor", - "bool", - "break", - "case", - "catch", - "char", - "char16_t", - "char32_t", - "class", - "compl", - "concept", - "concepts", - "const", - "const_cast", - "constexpr", - "continue", - "decltype", - "default", - "delete", - "do", - "double", - "dynamic_cast", - "else", - "enum", - "explicit", - "export", - "extern", - "false", - "float", - "for", - "friend", - "goto", - "if", - "import", - "inline", - "int", - "long", - "module", - "modules", - "mutable", - "namespace", - "new", - "noexcept", - "not", - "not_eq", - "nullptr", - "operator", - "or", - "or_eq", - "private", - "protected", - "public", - "register", - "reinterpret_cast", - "requires", - "return", - "short", - "signed", - "sizeof", - "static", - "static_assert", - "static_cast", - "struct", - "switch", - "synchronized", - "template", - "this", - "thread_local", - "throw", - "true", - "try", - "typedef", - "typeid", - "typename", - "union", - "unsigned", - "using", - "virtual", - "void", - "volatile", - "wchar_t", - "while", - "xor", - "xor_eq", - }; - for(const char *reserved_word : reserved_words) - { - if(retval == reserved_word) - { - retval += '_'; - break; - } - } - return retval; -} - -#if 0 -#warning testing Generator::get_name_from_words -struct Generator::Tester -{ - struct Test_runner - { - Test_runner() - { - test(); - std::exit(1); - } - }; - static Test_runner test_runner; - static void test() - { - for(auto &input : { - "abc def", "AbcDef", "ABCDef", "'abc, def'", - }) - { - std::cout << "\"" << input << "\" -> " << get_name_from_words(input) - << std::endl; - } - } -}; - -Generator::Tester::Test_runner Generator::Tester::test_runner; -#endif - -std::string Generator::get_member_name_from_operand( - const ast::Instructions::Instruction::Operands::Operand &operand) -{ - if(!operand.name.empty()) - 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_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_member_name_from_enumerant( - const ast::Operand_kinds::Operand_kind::Enumerants::Enumerant &enumerant) -{ - return get_name_from_words(enumerant.enumerant + " parameters"); -} - -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)) - return operand_kind.kind + "_with_parameters"; - return operand_kind.kind; -} - -void Generator::write_struct_nonstatic_members_and_constructors(Generator_state &state, - const std::string &struct_name, - const std::string *member_types, - const std::string *member_names, - std::size_t member_count) -{ - for(std::size_t i = 0; i < member_count; i++) - state << indent << member_types[i] << " " << member_names[i] << ";\n"; - state << indent << struct_name << "()\n"; - { - auto push_indent = state.pushed_indent(); - for(std::size_t i = 0; i < member_count; i++) - { - state << indent; - if(i == 0) - state << ": "; - else - state << " "; - state << member_names[i] << "()"; - if(i != member_count - 1) - state << ","; - state << "\n"; - } - } - state << indent(R"({ -} -)"); - if(member_count != 0) - { - state << indent; - if(member_count == 1) - state << "explicit "; - state << struct_name << "("; - for(std::size_t i = 0; i < member_count; i++) - { - state << member_types[i] << " " << member_names[i]; - if(i != member_count - 1) - state << ", "; - } - state << ")\n"; - { - auto push_indent = state.pushed_indent(); - for(std::size_t i = 0; i < member_count; i++) - { - state << indent; - if(i == 0) - state << ": "; - else - state << " "; - state << member_names[i] << "(std::move(" << member_names[i] << "))"; - if(i != member_count - 1) - state << ","; - state << "\n"; - } - } - state << indent(R"({ -} -)"); - } -} - -std::vector - Generator::get_unique_enumerants( - std::vector enumerants) -{ - std::unordered_set values; - std::size_t output_index = 0; - for(std::size_t input_index = 0; input_index < enumerants.size(); input_index++) - { - if(std::get<1>(values.insert(enumerants[input_index].value))) - { - if(output_index != input_index) - enumerants[output_index] = std::move(enumerants[input_index]); - output_index++; - } - } - enumerants.erase(enumerants.begin() + output_index, enumerants.end()); - return enumerants; -} - -struct Spirv_header_generator final : public Generator -{ - Spirv_header_generator() : Generator("spirv.h") - { - } - enum class Enum_priority - { - default_priority = 0, - capability = 1, - }; - static Enum_priority get_enum_priority(const std::string &enum_name) noexcept - { - if(enum_name == capability_enum_name) - return Enum_priority::capability; - return Enum_priority::default_priority; - } - static bool compare_enum_names(const std::string &l, const std::string &r) noexcept - { - auto l_priority = get_enum_priority(l); - auto r_priority = get_enum_priority(r); - if(l_priority > r_priority) - return true; // higher priority sorts first - if(l_priority < r_priority) - 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) - { - 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 - { - Generator_state state(this, generator_args, top_level); - state.open_output_file(); - write_file_comments(state, top_level.copyright); - write_file_guard_start(state); - 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; -typedef Word Id; -enum class Op : Word; -constexpr Word magic_number = )") - << unsigned_hex_integer_literal(top_level.magic_number, 8) - << indent(true, - ";\n" - "constexpr std::uint32_t major_version = ") - << unsigned_dec_integer_literal(top_level.major_version) - << indent(true, - ";\n" - "constexpr std::uint32_t minor_version = ") - << unsigned_dec_integer_literal(top_level.minor_version) - << indent(true, - ";\n" - "constexpr std::uint32_t revision = ") - << unsigned_dec_integer_literal(top_level.revision) << ";\n"; - auto extensions_set = get_extensions(top_level); - std::vector extensions_list; - extensions_list.reserve(extensions_set.size()); - for(auto &extension : extensions_set) - extensions_list.push_back(extension); - std::sort(extensions_list.begin(), extensions_list.end()); - state << indent( - "\n" - "enum class ") - << extension_enum_name << indent(true, - " : std::size_t\n" - "{\n"); - { - auto push_indent = state.pushed_indent(); - for(auto &extension : extensions_list) - state << indent << get_enumerant_name(extension_enum_name, extension, false) - << ",\n"; - } - state << indent( - "};\n" - "\n" - "vulkan_cpu_util_generate_enum_traits(") - << extension_enum_name; - { - auto push_indent = state.pushed_indent(); - for(auto &extension : extensions_list) - state << ",\n" << indent << extension_enum_name - << "::" << get_enumerant_name(extension_enum_name, extension, false); - state << ");\n"; - } - state << indent( - "\n" - "constexpr const char *get_enumerant_name(") - << extension_enum_name << indent(true, - " v) noexcept\n" - "{\n"); - { - auto push_indent = state.pushed_indent(); - state << indent( - "switch(v)\n" - "{\n"); - for(auto &extension : extensions_list) - { - state << indent("case ") << extension_enum_name - << "::" << get_enumerant_name(extension_enum_name, extension, false) - << indent(true, - ":\n" - "`return \"") - << extension << "\";\n"; - } - state << indent( - "}\n" - "return \"\";\n"); - } - state << "}\n"; - std::vector operand_kinds; - operand_kinds.reserve(top_level.operand_kinds.operand_kinds.size()); - for(auto &operand_kind : top_level.operand_kinds.operand_kinds) - operand_kinds.push_back(&operand_kind); - std::sort( - operand_kinds.begin(), - operand_kinds.end(), - [](const ast::Operand_kinds::Operand_kind *a, const ast::Operand_kinds::Operand_kind *b) - { - return compare_operand_kinds(*a, *b); - }); - 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); - state << "\n" - "enum class " - << get_enum_name(*operand_kind) << " : Word\n" - "{\n"; - { - auto push_indent = state.pushed_indent(); - for(auto &enumerant : enumerants.enumerants) - { - state << indent - << get_enumerant_name(operand_kind->kind, enumerant.enumerant, false) - << " = "; - if(is_bit_enum) - state << unsigned_hex_integer_literal(enumerant.value); - else - state << unsigned_dec_integer_literal(enumerant.value); - state << ",\n"; - } - } - state << "};\n" - "\n" - "vulkan_cpu_util_generate_enum_traits(" - << get_enum_name(*operand_kind); - { - auto push_indent = state.pushed_indent(); - for(auto &enumerant : unique_enumerants) - 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(" - << get_enum_name(*operand_kind) << " v) noexcept\n" - "{\n"; - { - auto push_indent = state.pushed_indent(); - state << indent( - "switch(v)\n" - "{\n"); - for(auto &enumerant : unique_enumerants) - { - state << indent("case ") << get_enum_name(*operand_kind) << "::" - << get_enumerant_name(operand_kind->kind, enumerant.enumerant, false) - << indent(true, - ":\n" - "`return \"") - << enumerant.enumerant << "\";\n"; - } - state << indent( - "}\n" - "return \"\";\n"); - } - state << "}\n"; - state << "\n" - "constexpr util::Enum_set<" - << capability_enum_name << "> get_directly_required_capability_set(" - << get_enum_name(*operand_kind) << " v) noexcept\n" - "{\n"; - { - auto push_indent = state.pushed_indent(); - state << indent( - "switch(v)\n" - "{\n"); - for(auto &enumerant : unique_enumerants) - { - state << indent("case ") << get_enum_name(*operand_kind) << "::" - << get_enumerant_name(operand_kind->kind, enumerant.enumerant, false) - << indent(true, - ":\n" - "`return ") - << enumerant.capabilities << ";\n"; - } - state << indent( - "}\n" - "return {};\n"); - } - state << "}\n" - "\n" - "constexpr util::Enum_set<" - << extension_enum_name << "> get_directly_required_extension_set(" - << get_enum_name(*operand_kind) << " v) noexcept\n" - "{\n"; - { - auto push_indent = state.pushed_indent(); - state << indent( - "switch(v)\n" - "{\n"); - for(auto &enumerant : unique_enumerants) - { - state << indent("case ") << get_enum_name(*operand_kind) << "::" - << get_enumerant_name(operand_kind->kind, enumerant.enumerant, false) - << indent(true, - ":\n" - "`return ") - << enumerant.extensions << ";\n"; - } - state << indent( - "}\n" - "return {};\n"); - } - state << "}\n"; - break; - } - case ast::Operand_kinds::Operand_kind::Category::composite: - { - auto &bases = - util::get(operand_kind->value); - state << "\n" - "struct " - << 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, - member_types.data(), - member_names.data(), - bases.values.size()); - push_indent.finish(); - state << "};\n"; - break; - } - case ast::Operand_kinds::Operand_kind::Category::id: - { - auto &doc = util::get(operand_kind->value); - state << "\n" - "/** "; - bool was_last_star = false; - for(char ch : doc.value) - { - if(was_last_star && ch == '/') - state << ' '; - was_last_star = (ch == '*'); - state << ch; - } - state << " */\n" - "typedef Id " - << operand_kind->kind << ";\n"; - break; - } - case ast::Operand_kinds::Operand_kind::Category::literal: - { - auto &doc = util::get(operand_kind->value); - auto literal_kind = - ast::Operand_kinds::Operand_kind::get_literal_kind_from_json_name( - operand_kind->kind); - if(!literal_kind) - throw Generate_error("bad literal kind"); - auto base_type = "std::vector"; - switch(*literal_kind) - { - case ast::Operand_kinds::Operand_kind::Literal_kind::literal_integer: - // TODO: fix after determining if LiteralInteger can be multiple words - base_type = "std::uint32_t"; - break; - case ast::Operand_kinds::Operand_kind::Literal_kind::literal_string: - base_type = "std::string"; - break; - case ast::Operand_kinds::Operand_kind::Literal_kind:: - literal_context_dependent_number: - break; - case ast::Operand_kinds::Operand_kind::Literal_kind::literal_ext_inst_integer: - base_type = "Word"; - break; - case ast::Operand_kinds::Operand_kind::Literal_kind:: - literal_spec_constant_op_integer: - base_type = "Op"; - break; - } - state << "\n" - "/** "; - bool was_last_star = false; - for(char ch : doc.value) - { - if(was_last_star && ch == '/') - state << ' '; - was_last_star = (ch == '*'); - state << ch; - } - state << " */\n" - "typedef " - << base_type << " " << operand_kind->kind << ";\n"; - break; - } - } - } - 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"; - } - if(is_bit_enum) - { - auto struct_name = get_operand_with_parameters_name(state, *operand_kind); - state << indent(R"( -struct )") << struct_name << indent(true, R"( -{ -)"); - std::vector member_types; - std::vector member_names; - member_types.push_back(get_enum_name(*operand_kind)); - member_names.push_back("value"); - for(auto &enumerant : unique_enumerants) - { - if(enumerant.parameters.empty()) - continue; - member_types.push_back( - "util::optional<" - + get_enumerant_parameters_struct_name( - operand_kind->kind, enumerant.enumerant, false) - + ">"); - member_names.push_back(get_member_name_from_enumerant(enumerant)); - } - auto push_indent = state.pushed_indent(); - write_struct_nonstatic_members_and_constructors(state, - struct_name, - member_types.data(), - member_names.data(), - member_types.size()); - push_indent.finish(); - state << "};\n"; - } - else - { - 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; - } - } - std::vector instructions; - instructions.reserve(top_level.instructions.instructions.size()); - for(auto &instruction : top_level.instructions.instructions) - instructions.push_back(&instruction); - std::sort( - instructions.begin(), - instructions.end(), - [](const ast::Instructions::Instruction *a, const ast::Instructions::Instruction *b) - { - return a->opcode < b->opcode; - }); - state << "\n" - "enum class " - << op_enum_name << " : Word\n" - "{\n"; - { - auto push_indent = state.pushed_indent(); - for(auto &instruction : top_level.instructions.instructions) - { - state << indent << get_enumerant_name(op_enum_name, instruction.opname, true) - << " = " << unsigned_dec_integer_literal(instruction.opcode) << ",\n"; - } - } - state << "};\n"; - state << "\n" - "vulkan_cpu_util_generate_enum_traits(" - << op_enum_name; - { - auto push_indent = state.pushed_indent(); - for(auto &instruction : top_level.instructions.instructions) - state << ",\n" << indent << op_enum_name - << "::" << get_enumerant_name(op_enum_name, instruction.opname, true); - state << ");\n"; - } - state << "\n" - "constexpr const char *get_enumerant_name(" - << op_enum_name << " v) noexcept\n" - "{\n"; - { - auto push_indent = state.pushed_indent(); - state << indent( - "switch(v)\n" - "{\n"); - for(auto &instruction : top_level.instructions.instructions) - { - state << indent("case ") << op_enum_name - << "::" << get_enumerant_name(op_enum_name, instruction.opname, true) - << indent(true, - ":\n" - "return \"") - << instruction.opname << "\";\n"; - } - state << indent( - "}\n" - "return \"\";\n"); - } - state << "}\n" - "\n" - "constexpr util::Enum_set<" - << capability_enum_name << "> get_directly_required_capability_set(" << op_enum_name - << " v) noexcept\n" - "{\n"; - { - auto push_indent = state.pushed_indent(); - state << indent( - "switch(v)\n" - "{\n"); - for(auto &instruction : top_level.instructions.instructions) - { - state << indent("case ") << op_enum_name - << "::" << get_enumerant_name(op_enum_name, instruction.opname, true) - << indent(true, - ":\n" - "return ") - << instruction.capabilities << ";\n"; - } - state << indent( - "}\n" - "return {};\n"); - } - state << "}\n" - "\n" - "constexpr util::Enum_set<" - << extension_enum_name << "> get_directly_required_extension_set(" << op_enum_name - << " v) noexcept\n" - "{\n"; - { - auto push_indent = state.pushed_indent(); - state << indent( - "switch(v)\n" - "{\n"); - for(auto &instruction : top_level.instructions.instructions) - { - state << indent("case ") << op_enum_name - << "::" << get_enumerant_name(op_enum_name, instruction.opname, true) - << ":\n"; - auto push_indent2 = state.pushed_indent(); - state << indent("return ") << instruction.extensions << ";\n"; - } - state << indent( - "}\n" - "return {};\n"); - } - state << "}\n"; - for(auto &instruction : top_level.instructions.instructions) - { - auto struct_name = get_enumerant_name(op_enum_name, instruction.opname, true); - state << "\n" - "struct " - << struct_name << "\n" - "{\n"; - { - auto push_indent = state.pushed_indent(); - state << indent("static constexpr ") << op_enum_name << " get_opcode() noexcept\n" - << indent("{\n"); - { - auto push_indent2 = state.pushed_indent(); - state << indent("return ") << op_enum_name - << "::" << get_enumerant_name(op_enum_name, instruction.opname, true) - << ";\n"; - } - state << indent("}\n"); - std::vector member_names; - std::vector member_types; - member_names.reserve(instruction.operands.operands.size()); - member_types.reserve(instruction.operands.operands.size()); - for(auto &operand : instruction.operands.operands) - { - std::string member_type; - switch(operand.quantifier) - { - case ast::Instructions::Instruction::Operands::Operand::Quantifier::none: - { - member_type = get_operand_with_parameters_name(state, operand); - break; - } - case ast::Instructions::Instruction::Operands::Operand::Quantifier::optional: - { - member_type = "util::optional<" - + get_operand_with_parameters_name(state, operand) + ">"; - break; - } - case ast::Instructions::Instruction::Operands::Operand::Quantifier::variable: - { - member_type = - "std::vector<" + get_operand_with_parameters_name(state, operand) + ">"; - break; - } - } - member_types.push_back(std::move(member_type)); - member_names.push_back(get_member_name_from_operand(operand)); - } - write_struct_nonstatic_members_and_constructors(state, - struct_name, - member_types.data(), - member_names.data(), - member_types.size()); - } - state << "};\n"; - } - write_namespaces_end(state, spirv_namespace_names); - write_file_guard_end(state); - } -}; - -struct Spirv_source_generator final : public Generator -{ - Spirv_source_generator() : Generator("spirv.cpp") - { - } - virtual void run(Generator_args &generator_args, const ast::Top_level &top_level) const override - { - Generator_state state(this, generator_args, top_level); - state.open_output_file(); - write_file_comments(state, top_level.copyright); - state << "#include \"spirv.h\"\n"; - } -}; - -struct Parser_header_generator final : public Generator -{ - Parser_header_generator() : Generator("parser.h") - { - } - static std::string get_dump_operand_function_name(std::string kind) - { - return "dump_operand_" + std::move(kind); - } - static std::string get_dump_operand_function_name( - const ast::Operand_kinds::Operand_kind &operand_kind) - { - return get_dump_operand_function_name(operand_kind.kind); - } - static std::string get_dump_operand_function_name( - const ast::Operand_kinds::Operand_kind::Enumerants::Enumerant::Parameters::Parameter - ¶meter) - { - return get_dump_operand_function_name(parameter.kind); - } - static std::string get_parse_operand_function_name(std::string kind) - { - return "parse_operand_" + std::move(kind); - } - static std::string get_parse_operand_function_name( - const ast::Operand_kinds::Operand_kind &operand_kind) - { - return get_parse_operand_function_name(operand_kind.kind); - } - static std::string get_parse_operand_function_name( - const ast::Instructions::Instruction::Operands::Operand &operand) - { - return get_parse_operand_function_name(operand.kind); - } - static std::string get_parse_operand_function_name( - const ast::Operand_kinds::Operand_kind::Enumerants::Enumerant::Parameters::Parameter - ¶meter) - { - return get_parse_operand_function_name(parameter.kind); - } - static std::string get_parse_instruction_function_name(std::string opname) - { - return "parse_instruction_" + get_enumerant_name(op_enum_name, opname, true); - } - virtual void run(Generator_args &generator_args, const ast::Top_level &top_level) const override - { - Generator_state state(this, generator_args, top_level); - state.open_output_file(); - write_file_comments(state, top_level.copyright); - write_file_guard_start(state); - state << R"(#include "spirv.h" -#include -#include -#include "util/optional.h" -#include "json/json.h" -#include - -)"; - write_namespaces_start(state, spirv_namespace_names); - state << indent(R"(struct Parse_error -{ -`std::size_t word_index; -`std::size_t instruction_word_index; -`std::string message; -`Parse_error(std::size_t word_index, std::size_t instruction_word_index, std::string message) noexcept -``: word_index(word_index), -`` instruction_word_index(instruction_word_index), -`` message(std::move(message)) -`{ -`} -`virtual ~Parse_error() = default; -}; - -)"); - state << "struct Parse_semantics_generic\n" - "{\n"; - { - auto push_indent = state.pushed_indent(); - state << indent(R"(virtual ~Parse_semantics_generic() = default; -virtual std::unique_ptr handle_error(std::size_t word_index, std::size_t instruction_word_index, std::string message) = 0; -virtual void handle_spirv_version(unsigned major, unsigned minor) = 0; -virtual void handle_generator_magic_number(Word value) = 0; -virtual void handle_id_bound(Word id_bound) = 0; -)"); - for(auto &instruction : top_level.instructions.instructions) - { - auto struct_name = get_enumerant_name(op_enum_name, instruction.opname, true); - state << indent("virtual void handle_instruction(") << struct_name - << " instruction) = 0;\n"; - } - } - state << indent(R"(}; - -struct Parse_dump final : public Parse_semantics_generic -{ -`std::ostream &os; -`explicit constexpr Parse_dump(std::ostream &os) noexcept : os(os) -`{ -`} -)"); - { - auto push_indent = state.pushed_indent(); - state << indent( - R"(virtual std::unique_ptr handle_error(std::size_t word_index, std::size_t instruction_word_index, std::string message) override; -virtual void handle_spirv_version(unsigned major, unsigned minor) override; -virtual void handle_generator_magic_number(Word value) override; -virtual void handle_id_bound(Word id_bound) override; -)"); - for(auto &instruction : top_level.instructions.instructions) - { - auto struct_name = get_enumerant_name(op_enum_name, instruction.opname, true); - state << indent("virtual void handle_instruction(") << struct_name - << " instruction) override;\n"; - } - for(auto &operand_kind : top_level.operand_kinds.operand_kinds) - { - auto dump_function_name = get_dump_operand_function_name(operand_kind); - state << indent("void ") << dump_function_name << "(const " - << get_operand_with_parameters_name(state, operand_kind) << " &value);\n"; - state << indent("void ") << dump_function_name << "(const util::optional<" - << get_operand_with_parameters_name(state, operand_kind) << "> &value);\n"; - state << indent("void ") << dump_function_name << "(const std::vector<" - << get_operand_with_parameters_name(state, operand_kind) << "> &values);\n"; - } - } - state << "};\n" - "\n" - "template \n" - "struct Parser\n" - "{\n"; - { - auto push_indent = state.pushed_indent(); - for(auto &operand_kind : top_level.operand_kinds.operand_kinds) - { - auto parse_function_name = get_parse_operand_function_name(operand_kind); - state - << indent(R"(static std::unique_ptr )") << parse_function_name - << indent( - true, - R"((const Word *words, std::size_t word_count, Semantics &semantics, std::size_t error_instruction_index, std::size_t &word_index, )") - << get_operand_with_parameters_name(state, operand_kind) << indent(true, - R"( &value) -{ -`if(word_index >= word_count) -``return semantics.handle_error(error_instruction_index + word_index, error_instruction_index, "instruction missing operand"); -)"); - auto push_indent = state.pushed_indent(); - switch(operand_kind.category) - { - case ast::Operand_kinds::Operand_kind::Category::bit_enum: - { - auto enum_name = get_enum_name(operand_kind); - if(get_operand_has_any_parameters(state, operand_kind)) - { - state << indent(R"(value.value = static_cast<)") << enum_name - << indent(true, R"(>(words[word_index++]); -)"); - auto &enumerants = util::get( - operand_kind.value); - for(auto &enumerant : enumerants.enumerants) - { - if(enumerant.parameters.empty()) - continue; - auto enumerant_member_name = get_member_name_from_enumerant(enumerant); - auto enumerant_name = - get_enumerant_name(operand_kind.kind, enumerant.enumerant, false); - state - << indent( - R"(if((static_cast(value.value) & static_cast()") - << enum_name << "::" << enumerant_name - << indent(true, R"()) == static_cast()") << enum_name - << "::" << enumerant_name << indent(true, R"()) -{ -`value.)") << enumerant_member_name - << indent(true, R"(.emplace(); -)"); - bool first = true; - for(auto ¶meter : enumerant.parameters.parameters) - { - auto parameter_member_name = - get_member_name_from_parameter(parameter); - auto parameter_parse_function = - get_parse_operand_function_name(parameter); - state << indent(1); - if(first) - { - state << indent(true, "auto "); - first = false; - } - state << indent(true, "parse_error = ") << parameter_parse_function - << "(words, word_count, semantics, error_instruction_index, " - "word_index, value." - << enumerant_member_name << "->" << parameter_member_name - << indent(true, R"(); -`if(parse_error) -``return parse_error; -)"); - } - state << indent(R"(} -)"); - } - } - else - { - state << indent(R"(value = static_cast<)") << enum_name - << indent(true, R"(>(words[word_index++]); -)"); - } - break; - } - case ast::Operand_kinds::Operand_kind::Category::value_enum: - { - auto enum_name = get_enum_name(operand_kind); - if(get_operand_has_any_parameters(state, operand_kind)) - { - state << indent(R"(value.value = static_cast<)") << enum_name - << indent(true, R"(>(words[word_index++]); -switch(value.value) -{ -)"); - auto &enumerants = util::get( - operand_kind.value); - for(auto &enumerant : enumerants.enumerants) - { - auto enumerant_name = - get_enumerant_name(operand_kind.kind, enumerant.enumerant, false); - state << indent("case ") << enum_name << "::" << enumerant_name - << indent(true, R"(: -)"); - if(enumerant.parameters.empty()) - { - state << indent(R"(`break; -)"); - continue; - } - auto enumerant_parameters_struct_name = - get_enumerant_parameters_struct_name( - operand_kind.kind, enumerant.enumerant, false); - state << indent(R"({ -`value.parameters.emplace<)") << enumerant_parameters_struct_name - << indent(true, R"(>(); -`auto ¶meters = util::get<)") << enumerant_parameters_struct_name - << indent(true, R"(>(value.parameters); -)"); - bool first = true; - for(auto ¶meter : enumerant.parameters.parameters) - { - auto parameter_member_name = - get_member_name_from_parameter(parameter); - auto parameter_parse_function = - get_parse_operand_function_name(parameter); - state << indent(1); - if(first) - { - state << indent(true, "auto "); - first = false; - } - state << indent(true, "parse_error = ") << parameter_parse_function - << "(words, word_count, semantics, error_instruction_index, " - "word_index, parameters." - << parameter_member_name << indent(true, R"(); -`if(parse_error) -``return parse_error; -)"); - } - state << indent(R"(`break; -} -)"); - } - state << indent(R"(default: -`word_index--; -`return semantics.handle_error(error_instruction_index + word_index, error_instruction_index, "invalid enum value"); -} -)"); - } - else - { - state << indent(R"(value = static_cast<)") << enum_name - << indent(true, R"(>(words[word_index]); -if(util::Enum_traits<)") << enum_name - << indent(true, R"(>::find_value(value) == util::Enum_traits<)") - << enum_name << indent(true, R"(>::npos) -`return semantics.handle_error(error_instruction_index + word_index, error_instruction_index, "invalid enum value"); -word_index++; -)"); - } - break; - } - case ast::Operand_kinds::Operand_kind::Category::composite: - { - auto &bases = - util::get(operand_kind.value); - for(std::size_t i = 0; i < bases.values.size(); i++) - { - state << indent; - if(i == 0) - state << indent(true, "auto "); - state << indent(true, "parse_error = ") - << get_parse_operand_function_name(bases.values[i]) - << "(words, word_count, semantics, error_instruction_index, " - "word_index, value." - << json::ast::Number_value::append_unsigned_integer_to_string(i + 1, - "part_") - << indent(true, R"(); -if(parse_error) -`return parse_error; -)"); - } - break; - } - case ast::Operand_kinds::Operand_kind::Category::id: - { - state << indent(R"(value = static_cast(words[word_index++]); -)"); - break; - } - case ast::Operand_kinds::Operand_kind::Category::literal: - { - auto literal_kind = - ast::Operand_kinds::Operand_kind::get_literal_kind_from_json_name( - operand_kind.kind); - if(!literal_kind) - throw Generate_error("bad literal kind"); - switch(*literal_kind) - { - case ast::Operand_kinds::Operand_kind::Literal_kind::literal_integer: - // TODO: fix after determining if LiteralInteger can be multiple words - state << indent(R"(value = words[word_index++]; -)"); - break; - case ast::Operand_kinds::Operand_kind::Literal_kind::literal_string: - state << indent( - R"(value.clear(); -bool done = false; -while(!done) -{ -`if(word_index >= word_count) -``return semantics.handle_error(error_instruction_index + word_index, error_instruction_index, "string missing terminating null"); -`Word word = words[word_index++]; -`for(std::size_t i = 0; i < 4; i++) -`{ -``unsigned char ch = word & 0xFFU; -``word >>= 8; -``if(ch == '\0') -``{ -```done = true; -```if(word != 0) -````return semantics.handle_error(error_instruction_index + word_index, error_instruction_index, "string has non-zero padding"); -``} -``else -``{ -```value += ch; -``} -`} -} -)"); - break; - case ast::Operand_kinds::Operand_kind::Literal_kind:: - literal_context_dependent_number: - state << indent( - R"(static_assert(std::is_same &>::value, "missing parse code for operand kind"); -value.clear(); -value.reserve(word_count - word_index); -while(word_index < word_count) -`value.push_back(words[word_index++]); -)"); - break; - case ast::Operand_kinds::Operand_kind::Literal_kind::literal_ext_inst_integer: - state << indent(R"(value = words[word_index++]; -)"); - break; - case ast::Operand_kinds::Operand_kind::Literal_kind:: - literal_spec_constant_op_integer: - state << indent(R"(value = static_cast<)") << op_enum_name - << indent(true, R"(>(words[word_index++]); -)"); - break; - } - break; - } - } - push_indent.finish(); - state << indent(R"(`return nullptr; -} -)"); - } - for(auto &instruction : top_level.instructions.instructions) - { - auto struct_name = get_enumerant_name(op_enum_name, instruction.opname, true); - auto parse_function_name = get_parse_instruction_function_name(instruction.opname); - state - << indent(R"(static std::unique_ptr )") << parse_function_name - << indent( - true, - R"((const Word *words, std::size_t word_count, Semantics &semantics, std::size_t error_instruction_index) -{ -`std::size_t word_index = 1; // skip opcode -)"); - auto push_indent2 = state.pushed_indent(); - state << indent << struct_name << " instruction;\n"; - if(!instruction.operands.empty()) - state << indent("std::unique_ptr parse_error;\n"); - for(auto &operand : instruction.operands.operands) - { - auto parse_operand_function_name = get_parse_operand_function_name(operand); - auto member_name = get_member_name_from_operand(operand); - switch(operand.quantifier) - { - case ast::Instructions::Instruction::Operands::Operand::Quantifier::none: - { - state - << indent(R"(parse_error = )") << parse_operand_function_name - << indent( - true, - R"((words, word_count, semantics, error_instruction_index, word_index, instruction.)") - << member_name << indent(true, R"(); -if(parse_error) -`return parse_error; -)"); - break; - } - case ast::Instructions::Instruction::Operands::Operand::Quantifier::optional: - { - state - << indent(R"(if(word_index < word_count) -{ -`instruction.)") << member_name - << indent(true, R"(.emplace(); -`parse_error = )") << parse_operand_function_name - << indent( - true, - R"((words, word_count, semantics, error_instruction_index, word_index, *instruction.)") - << member_name << indent(true, R"(); -`if(parse_error) -``return parse_error; -} -)"); - break; - } - case ast::Instructions::Instruction::Operands::Operand::Quantifier::variable: - { - state - << indent(R"(while(word_index < word_count) -{ -`instruction.)") << member_name - << indent(true, R"(.emplace_back(); -`parse_error = )") << parse_operand_function_name - << indent( - true, - R"((words, word_count, semantics, error_instruction_index, word_index, instruction.)") - << member_name << indent(true, R"(.back()); -`if(parse_error) -``return parse_error; -} -)"); - } - } - } - push_indent2.finish(); - state << indent(R"(`if(word_index < word_count) -``return semantics.handle_error(error_instruction_index + word_index, error_instruction_index, "extra words at end of instruction"); -`semantics.handle_instruction(std::move(instruction)); -`return nullptr; -} -)"); - } - state << indent( - R"(static std::unique_ptr parse_instruction(const Word *words, std::size_t word_count, Semantics &semantics, std::size_t error_instruction_index) -{ -`Op op = static_cast(words[0] & 0xFFFFU); -`switch(op) -`{ -)"); - for(auto &instruction : top_level.instructions.instructions) - { - auto push_indent2 = state.pushed_indent(2); - auto enumerant_name = get_enumerant_name(op_enum_name, instruction.opname, true); - auto parse_function_name = get_parse_instruction_function_name(instruction.opname); - state << indent("case ") << op_enum_name << "::" << enumerant_name - << indent(true, R"(: -`return )") << parse_function_name - << indent(true, R"((words, word_count, semantics, error_instruction_index); -)"); - } - state << indent(R"(`} -`return semantics.handle_error(error_instruction_index, error_instruction_index, json::ast::Number_value::append_unsigned_integer_to_string(static_cast(op), "unknown instruction: 0x", 0x10)); -} -static std::unique_ptr parse(const Word *words, std::size_t word_count, Semantics &semantics) -{ -`std::size_t word_index = 0; -`if(word_index >= word_count) -``return semantics.handle_error(word_index, 0, "hit EOF when parsing magic number"); -`if(words[word_index] != magic_number) -``return semantics.handle_error(word_index, 0, "invalid magic number"); -`word_index++; -`if(word_index >= word_count) -``return semantics.handle_error(word_index, 0, "hit EOF when parsing SPIR-V version"); -`if(words[word_index] & ~0xFFFF00UL) -``return semantics.handle_error(word_index, 0, "invalid SPIR-V version"); -`auto input_major_version = words[word_index] >> 16; -`auto input_minor_version = (words[word_index] >> 8) & 0xFFU; -`semantics.handle_spirv_version(input_major_version, input_minor_version); -`if(input_major_version != major_version || input_minor_version > minor_version) -``return semantics.handle_error(word_index, 0, "SPIR-V version not supported"); -`word_index++; -`if(word_index >= word_count) -``return semantics.handle_error(word_index, 0, "hit EOF when parsing generator's magic number"); -`semantics.handle_generator_magic_number(words[word_index++]); -`if(word_index >= word_count) -``return semantics.handle_error(word_index, 0, "hit EOF when parsing id bound"); -`semantics.handle_id_bound(words[word_index++]); -`if(word_index >= word_count) -``return semantics.handle_error(word_index, 0, "hit EOF when parsing SPIR-V shader header"); -`if(words[word_index] != 0) -``return semantics.handle_error(word_index, 0, "nonzero reserved word in SPIR-V shader header"); -`word_index++; -`// now we've finished reading the shader header, the rest of the shader is just instructions -`while(word_index < word_count) -`{ -``auto instruction_word_count = words[word_index] >> 16; -``if(instruction_word_count == 0) -```return semantics.handle_error(word_index, word_index, "invalid instruction"); -``if(word_index + instruction_word_count > word_count) -```return semantics.handle_error(word_index, word_index, "instruction longer than rest of shader"); -``auto parse_error = parse_instruction(words + word_index, instruction_word_count, semantics, word_index); -``if(parse_error) -```return parse_error; -``word_index += instruction_word_count; -`} -`return nullptr; -} -)"); - } - state << "};\n"; - write_namespaces_end(state, spirv_namespace_names); - write_file_guard_end(state); - } -}; - -struct Parser_source_generator final : public Generator -{ - Parser_source_generator() : Generator("parser.cpp") - { - } - virtual void run(Generator_args &generator_args, const ast::Top_level &top_level) const override - { - Generator_state state(this, generator_args, top_level); - state.open_output_file(); - write_file_comments(state, top_level.copyright); - state << "#include \"parser.h\"\n" - "#include \n" - "\n"; - write_namespaces_start(state, spirv_namespace_names); - state << indent(R"(namespace -{ -/** instantiate Parser with Parse_semantics_generic to help catch bugs */ -[[gnu::unused]] auto parser_test(const Word *words, std::size_t word_count, Parse_semantics_generic &semantics) -{ -`return Parser<>::parse(words, word_count, semantics); -} -} - -std::unique_ptr Parse_dump::handle_error(std::size_t word_index, std::size_t instruction_word_index, std::string message) -{ -`return std::unique_ptr(new Parse_error(word_index, instruction_word_index, std::move(message))); -} - -void Parse_dump::handle_spirv_version(unsigned major, unsigned minor) -{ -`os << "SPIR-V version " << major << "." << minor << "\n"; -} - -void Parse_dump::handle_generator_magic_number(Word value) -{ -`os << "generator magic number: " << json::ast::Number_value::append_unsigned_integer_to_string(value, "0x", 0x10) << "\n"; -} - -void Parse_dump::handle_id_bound(Word id_bound) -{ -`os << "id bound: " << json::ast::Number_value::unsigned_integer_to_string(id_bound) << "\n"; -} -)"); - for(auto &operand_kind : top_level.operand_kinds.operand_kinds) - { - auto dump_function_name = - Parser_header_generator::get_dump_operand_function_name(operand_kind); - { - state << indent(R"( -void Parse_dump::)") << dump_function_name - << "(const " << get_operand_with_parameters_name(state, operand_kind) - << R"( &value) -{ -)"; - auto push_indent = state.pushed_indent(); - switch(operand_kind.category) - { - case ast::Operand_kinds::Operand_kind::Category::bit_enum: - { - bool operand_has_any_parameters = - get_operand_has_any_parameters(state, operand_kind); - state << indent(R"(Word bits = static_cast(value)") - << (operand_has_any_parameters ? ".value" : "") << indent(true, R"(); -bool first = true; -)"); - auto enum_name = get_enum_name(operand_kind); - auto &enumerants = - util::get(operand_kind.value); - const ast::Operand_kinds::Operand_kind::Enumerants::Enumerant *zero_enumerant = - nullptr; - for(auto &enumerant : enumerants.enumerants) - { - if(enumerant.value == 0) - { - zero_enumerant = &enumerant; - continue; - } - auto enumerant_name = - get_enumerant_name(operand_kind.kind, enumerant.enumerant, false); - auto scoped_enumerant_name = enum_name + "::" + enumerant_name; - state << indent(R"(if((bits & static_cast()") << scoped_enumerant_name - << indent(true, R"()) == static_cast()") - << scoped_enumerant_name << indent(true, R"()) -{ -`bits &= ~static_cast()") - << scoped_enumerant_name << indent(true, R"(); -`if(first) -``first = false; -`else -``os << " | "; -`os << get_enumerant_name()") << scoped_enumerant_name - << indent(true, R"(); -)"); - if(!enumerant.parameters.empty()) - { - auto enumerant_member_name = get_member_name_from_enumerant(enumerant); - state << indent(R"(`os << "("; -`if(value.)") << enumerant_member_name - << indent(true, R"() -`{ -``auto ¶meters = *value.)") << enumerant_member_name - << indent(true, R"(; -)"); - bool first = true; - for(auto ¶meter : enumerant.parameters.parameters) - { - if(first) - first = false; - else - state << indent(R"(``os << ", "; -)"); - state << indent(2) - << Parser_header_generator::get_dump_operand_function_name( - parameter) - << "(parameters." << get_member_name_from_parameter(parameter) - << ");\n"; - } - state << indent(R"a(`} -`os << ")"; -)a"); - } - state << indent(R"(} -)"); - } - std::string zero_enumerant_name_code; - if(zero_enumerant) - { - zero_enumerant_name_code = - "get_enumerant_name(" + enum_name + "::" - + get_enumerant_name( - operand_kind.kind, zero_enumerant->enumerant, false) - + ")"; - } - else - { - zero_enumerant_name_code = "\"0\""; - } - state << indent(R"(if(bits != 0) -{ -`if(!first) -``os << " | "; -`os << json::ast::Number_value::append_unsigned_integer_to_string(bits, "0x", 0x10); -} -else if(first) -{ -`os << )") << zero_enumerant_name_code - << indent(true, R"(; -} -)"); - break; - } - case ast::Operand_kinds::Operand_kind::Category::value_enum: - { - auto enum_name = get_enum_name(operand_kind); - if(get_operand_has_any_parameters(state, operand_kind)) - { - state << indent(R"(switch(value.value) -{ -)"); - auto &enumerants = util::get( - operand_kind.value); - bool any_parameterless_enumerants = false; - for(auto &enumerant : enumerants.enumerants) - { - if(!enumerant.parameters.empty()) - continue; - any_parameterless_enumerants = true; - state << indent("case ") << enum_name - << "::" << get_enumerant_name( - operand_kind.kind, enumerant.enumerant, false) - << ":\n"; - } - if(any_parameterless_enumerants) - { - state << indent(R"(`os << get_enumerant_name(value.value); -`break; -)"); - } - for(auto &enumerant : enumerants.enumerants) - { - if(enumerant.parameters.empty()) - continue; - auto enumerant_name = - get_enumerant_name(operand_kind.kind, enumerant.enumerant, false); - auto scoped_enumerant_name = enum_name + "::" + enumerant_name; - auto enumerant_parameters_struct_name = - get_enumerant_parameters_struct_name( - operand_kind.kind, enumerant.enumerant, false); - state << indent("case ") << scoped_enumerant_name << indent(true, R"(: -{ -`os << get_enumerant_name()") << scoped_enumerant_name - << indent(true, R"() << "("; -`auto *parameters = util::get_if<)") - << enumerant_parameters_struct_name - << indent(true, R"(>(&value.parameters); -`if(parameters) -`{ -)"); - bool first = true; - for(auto ¶meter : enumerant.parameters.parameters) - { - if(first) - first = false; - else - state << indent(R"(``os << ", "; -)"); - state << indent(2) - << Parser_header_generator::get_dump_operand_function_name( - parameter) - << "(parameters->" - << get_member_name_from_parameter(parameter) << ");\n"; - } - state << indent(R"a(`} -`os << ")"; -`break; -} -)a"); - } - state << indent(R"(default: -`os << json::ast::Number_value::unsigned_integer_to_string(static_cast(value.value)); -} -)"); - } - else - { - state << indent(R"(if(util::Enum_traits<)") << enum_name - << indent(true, R"(>::find_value(value) == util::Enum_traits<)") - << enum_name << indent(true, R"(>::npos) -`os << json::ast::Number_value::unsigned_integer_to_string(static_cast(value)); -else -`os << get_enumerant_name(value); -)"); - } - break; - } - case ast::Operand_kinds::Operand_kind::Category::composite: - { - auto &bases = - util::get(operand_kind.value); - state << indent("os << \"{\";\n"); - for(std::size_t i = 0; i < bases.values.size(); i++) - { - if(i != 0) - { - state << indent("os << \", \";\n"); - } - state << indent << Parser_header_generator::get_dump_operand_function_name( - bases.values[i]) - << "(value." - << json::ast::Number_value::append_unsigned_integer_to_string(i + 1, - "part_") - << ");\n"; - } - state << indent("os << \"}\";\n"); - break; - } - case ast::Operand_kinds::Operand_kind::Category::id: - { - state << indent( - R"(os << json::ast::Number_value::append_unsigned_integer_to_string(value, "#"); -)"); - break; - } - case ast::Operand_kinds::Operand_kind::Category::literal: - { - auto literal_kind = - ast::Operand_kinds::Operand_kind::get_literal_kind_from_json_name( - operand_kind.kind); - if(!literal_kind) - throw Generate_error("bad literal kind"); - switch(*literal_kind) - { - case ast::Operand_kinds::Operand_kind::Literal_kind::literal_integer: - state << indent( - R"(os << json::ast::Number_value::append_unsigned_integer_to_string(value, "0x"); -)"); - break; - case ast::Operand_kinds::Operand_kind::Literal_kind::literal_string: - state << indent( - R"(json::ast::String_value::write(os, value); -)"); - break; - case ast::Operand_kinds::Operand_kind::Literal_kind:: - literal_context_dependent_number: - state << indent( - R"(static_assert(std::is_same &>::value, "missing dump code for operand kind"); -auto separator = ""; -os << "{"; -for(Word word : value) -{ -`os << separator; -`separator = ", "; -`os << json::ast::Number_value::append_unsigned_integer_to_string(word, "0x", 0x10, 8); -} -os << "}"; -)"); - break; - case ast::Operand_kinds::Operand_kind::Literal_kind::literal_ext_inst_integer: - state << indent( - R"(os << json::ast::Number_value::append_unsigned_integer_to_string(value, "0x"); -)"); - break; - case ast::Operand_kinds::Operand_kind::Literal_kind:: - literal_spec_constant_op_integer: - state << indent(R"(if(util::Enum_traits<)") << op_enum_name - << indent(true, R"(>::find_value(value) == util::Enum_traits<)") - << op_enum_name << indent(true, R"(>::npos) -`os << json::ast::Number_value::unsigned_integer_to_string(static_cast(value)); -else -`os << get_enumerant_name(value); -)"); - break; - } - break; - } - } - push_indent.finish(); - state << indent("}\n"); - } - state << indent(R"( -void Parse_dump::)") - << dump_function_name << "(const util::optional<" - << get_operand_with_parameters_name(state, operand_kind) - << indent(true, R"(> &value) -{ -`if(value) -)") << indent(2) << dump_function_name - << indent(true, R"((*value); -`else -``os << "nullopt"; -} - -void Parse_dump::)") - << dump_function_name << "(const std::vector<" - << get_operand_with_parameters_name(state, operand_kind) - << indent(true, R"(> &values) -{ -`auto separator = ""; -`os << "{"; -`for(auto &value : values) -`{ -``os << separator; -``separator = ", "; -)") << indent(2) << dump_function_name - << indent(true, R"((value); -`} -`os << "}"; -} -)"); - } - for(auto &instruction : top_level.instructions.instructions) - { - auto struct_name = get_enumerant_name(op_enum_name, instruction.opname, true); - state << indent( - "\n" - "void Parse_dump::handle_instruction(") - << struct_name << indent(true, R"( instruction) -{ -`os << ")") << instruction.opname - << indent(true, R"(\n"; -)"); - for(auto &operand : instruction.operands.operands) - { - auto push_indent = state.pushed_indent(); - auto member_name = get_member_name_from_operand(operand); - state << indent("os << \" ") << member_name << indent(true, R"(:"; -)") << indent << Parser_header_generator::get_dump_operand_function_name(operand.kind) - << indent(true, R"((instruction.)") << member_name << indent(true, R"(); -os << "\n"; -)"); - } - state << indent("}\n"); - } - write_namespaces_end(state, spirv_namespace_names); - } -}; - -std::unique_ptr Generators::make_spirv_header_generator() -{ - return std::unique_ptr(new Spirv_header_generator); -} - -std::unique_ptr Generators::make_spirv_source_generator() -{ - return std::unique_ptr(new Spirv_source_generator); -} - -std::unique_ptr Generators::make_parser_header_generator() -{ - return std::unique_ptr(new Parser_header_generator); -} - -std::unique_ptr Generators::make_parser_source_generator() -{ - return std::unique_ptr(new Parser_source_generator); -} - -std::vector> Generators::make_all_generators() -{ - std::unique_ptr generators_array[] = { - make_spirv_header_generator(), - make_spirv_source_generator(), - make_parser_header_generator(), - make_parser_source_generator(), - }; - // use array then move because you can't move out of an std::initializer_list - std::vector> retval; - retval.reserve(sizeof(generators_array) / sizeof(generators_array[0])); - for(auto &generator : generators_array) - retval.push_back(std::move(generator)); - return retval; -} -} -} -} diff --git a/src/generate_spirv_parser/generate-old.h b/src/generate_spirv_parser/generate-old.h deleted file mode 100644 index 1a40f76..0000000 --- a/src/generate_spirv_parser/generate-old.h +++ /dev/null @@ -1,474 +0,0 @@ -/* - * Copyright 2017 Jacob Lifshay - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ - -#ifndef GENERATE_SPIRV_PARSER_GENERATE_OLD_H_ -#define GENERATE_SPIRV_PARSER_GENERATE_OLD_H_ - -#include "ast.h" -#include "util/string_view.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace vulkan_cpu -{ -namespace generate_spirv_parser -{ -namespace generate -{ -struct Generate_error : public std::runtime_error -{ - using runtime_error::runtime_error; -}; - -class Generator -{ -private: - struct Tester; - -public: - struct Generator_args - { - std::string output_directory; - explicit Generator_args(std::string output_directory) noexcept - : output_directory(std::move(output_directory)) - { - } - Generator_args(Generator_args &&) = default; - Generator_args &operator=(Generator_args &&) = default; - Generator_args(const Generator_args &) = delete; - Generator_args &operator=(const Generator_args &) = delete; - }; - -protected: - class Push_indent; - struct Generator_state - { - Generator_args &generator_args; - std::size_t indent_level; - std::string full_output_file_name; - std::string guard_macro_name; - std::ofstream os; - const ast::Top_level &top_level; - std::unordered_map operand_kind_map; - std::unordered_map - operand_has_any_parameters_map; - explicit Generator_state(const Generator *generator, - Generator_args &generator_args, - const ast::Top_level &top_level); - void open_output_file(); - template ())> - Generator_state &operator<<(T &&v) - { - os << std::forward(v); - return *this; - } - Generator_state &operator<<(const ast::Capabilities &v) - { - write_capabilities_set(*this, v); - return *this; - } - Generator_state &operator<<(const ast::Extensions &v) - { - write_extensions_set(*this, v); - return *this; - } - Push_indent pushed_indent(std::ptrdiff_t amount = 1) noexcept; - }; - class Push_indent final - { - Push_indent(const Push_indent &) = delete; - Push_indent &operator=(const Push_indent &) = delete; - - private: - Generator_state *state; - std::ptrdiff_t amount; - - public: - explicit Push_indent(Generator_state &state, std::ptrdiff_t amount = 1) noexcept - : state(&state), - amount(amount) - { - state.indent_level += amount; - } - Push_indent(Push_indent &&rt) noexcept : state(rt.state), amount(rt.amount) - { - rt.state = nullptr; - } - void finish() noexcept - { - assert(state); - state->indent_level -= amount; - state = nullptr; - } - ~Push_indent() - { - if(state) - state->indent_level -= amount; - } - }; - // translates initial '`' (backtick) characters to indentations - struct Indent_interpreted_text - { - const char *text; - std::ptrdiff_t indent_offset; - bool start_indented; - constexpr explicit Indent_interpreted_text(const char *text, - std::ptrdiff_t indent_offset, - bool start_indented) noexcept - : text(text), - indent_offset(indent_offset), - start_indented(start_indented) - { - } - friend Generator_state &operator<<(Generator_state &state, Indent_interpreted_text v) - { - write_indent_interpreted_text(state, v.text, v.indent_offset, v.start_indented); - return state; - } - }; - struct Indent_t - { - std::ptrdiff_t offset; - explicit Indent_t() = default; - constexpr Indent_t operator()(std::ptrdiff_t additional_offset) const noexcept - { - return Indent_t{offset + additional_offset}; - } - constexpr Indent_interpreted_text operator()(const char *text) const noexcept - { - return Indent_interpreted_text(text, offset, false); - } - constexpr Indent_interpreted_text operator()(bool start_indented, const char *text) const - noexcept - { - return Indent_interpreted_text(text, offset, start_indented); - } - friend Generator_state &operator<<(Generator_state &state, Indent_t indent) - { - write_indent(state, indent.offset); - return state; - } - }; - static constexpr auto indent = Indent_t{0}; - enum class Integer_literal_base - { - dec = 0, - hex, - oct - }; - struct Unsigned_integer_literal - { - std::uint64_t value; - Integer_literal_base base; - std::size_t minimum_digit_count; - constexpr Unsigned_integer_literal(std::uint64_t value, - Integer_literal_base base, - std::size_t minimum_digit_count = 1) noexcept - : value(value), - base(base), - minimum_digit_count(minimum_digit_count) - { - } - friend Generator_state &operator<<(Generator_state &state, Unsigned_integer_literal v) - { - write_unsigned_integer_literal(state, v.value, v.base, v.minimum_digit_count); - return state; - } - }; - static constexpr Unsigned_integer_literal unsigned_dec_integer_literal( - std::uint64_t value) noexcept - { - return Unsigned_integer_literal(value, Integer_literal_base::dec); - } - static constexpr Unsigned_integer_literal unsigned_hex_integer_literal( - std::uint64_t value, std::size_t minimum_digit_count = 1) noexcept - { - return Unsigned_integer_literal(value, Integer_literal_base::hex, minimum_digit_count); - } - static constexpr Unsigned_integer_literal unsigned_oct_integer_literal( - std::uint64_t value, std::size_t minimum_digit_count = 1) noexcept - { - return Unsigned_integer_literal(value, Integer_literal_base::oct, minimum_digit_count); - } - struct Signed_integer_literal - { - std::int64_t value; - constexpr explicit Signed_integer_literal(std::int64_t value) noexcept : value(value) - { - } - friend Generator_state &operator<<(Generator_state &state, Signed_integer_literal v) - { - write_signed_integer_literal(state, v.value); - return state; - } - }; - static constexpr Signed_integer_literal signed_integer_literal(std::int64_t value) noexcept - { - return Signed_integer_literal(value); - } - -protected: - const char *const output_base_file_name; - -protected: - static std::string get_guard_macro_name_from_file_name(std::string file_name); - static std::string get_enumerant_name(util::string_view enumeration_name, - std::string enumerant_name, - bool input_name_should_have_prefix) - { - return get_enumerant_name(enumeration_name.data(), - enumeration_name.size(), - std::move(enumerant_name), - input_name_should_have_prefix); - } - static std::string get_enumerant_name(const char *enumeration_name, - std::size_t enumeration_name_size, - std::string enumerant_name, - bool input_name_should_have_prefix); - static void write_indent_absolute(Generator_state &state, std::size_t amount); - static void write_indent(Generator_state &state, std::ptrdiff_t offset) - { - write_indent_absolute(state, state.indent_level + offset); - } - static void write_indent_interpreted_text(Generator_state &state, - const char *text, - std::ptrdiff_t offset, - bool start_indented); - static void write_automatically_generated_file_warning(Generator_state &state); - static void write_copyright_comment(Generator_state &state, const ast::Copyright ©right); - static void write_file_comments(Generator_state &state, const ast::Copyright ©right) - { - write_automatically_generated_file_warning(state); - write_copyright_comment(state, copyright); - } - static void write_file_guard_start(Generator_state &state); - static void write_file_guard_end(Generator_state &state); - static void write_namespace_start(Generator_state &state, const char *namespace_name); - static void write_namespace_start(Generator_state &state, const std::string &namespace_name); - -private: - static void write_namespace_end(Generator_state &state); - -protected: - static void write_namespace_end(Generator_state &state, const char *namespace_name) - { - write_namespace_end(state); - } - static void write_namespace_end(Generator_state &state, const std::string &namespace_name) - { - write_namespace_end(state); - } - static void write_namespaces_start(Generator_state &state, - const char *const *namespace_names, - std::size_t namespace_name_count) - { - for(std::size_t i = 0; i < namespace_name_count; i++) - write_namespace_start(state, namespace_names[i]); - } - static void write_namespaces_start(Generator_state &state, - const std::string *namespace_names, - std::size_t namespace_name_count) - { - for(std::size_t i = 0; i < namespace_name_count; i++) - write_namespace_start(state, namespace_names[i]); - } - static void write_namespaces_end(Generator_state &state, - const char *const *namespace_names, - std::size_t namespace_name_count) - { - for(std::size_t i = 0; i < namespace_name_count; i++) - write_namespace_end(state, namespace_names[namespace_name_count - i - 1]); - state << '\n'; - } - static void write_namespaces_end(Generator_state &state, - const std::string *namespace_names, - std::size_t namespace_name_count) - { - for(std::size_t i = 0; i < namespace_name_count; i++) - write_namespace_end(state, namespace_names[namespace_name_count - i - 1]); - state << '\n'; - } - template - static void write_namespaces_start(Generator_state &state, const T(&namespace_names)[N]) - { - write_namespaces_start(state, namespace_names, N); - } - template - static void write_namespaces_end(Generator_state &state, const T(&namespace_names)[N]) - { - write_namespaces_end(state, namespace_names, N); - } - static void write_namespaces_start(Generator_state &state, - std::initializer_list namespace_names) - { - write_namespaces_start(state, namespace_names.begin(), namespace_names.size()); - } - static void write_namespaces_start(Generator_state &state, - std::initializer_list namespace_names) - { - write_namespaces_start(state, namespace_names.begin(), namespace_names.size()); - } - static void write_namespaces_end(Generator_state &state, - std::initializer_list namespace_names) - { - write_namespaces_end(state, namespace_names.begin(), namespace_names.size()); - } - static void write_namespaces_end(Generator_state &state, - std::initializer_list namespace_names) - { - write_namespaces_end(state, namespace_names.begin(), namespace_names.size()); - } - static void write_unsigned_integer_literal(Generator_state &state, - std::uint64_t value, - Integer_literal_base base, - std::size_t minimum_digit_count); - static void write_signed_integer_literal(Generator_state &state, std::int64_t value); - -private: - struct Get_extensions_visitor; - -protected: - static std::unordered_set get_extensions(const ast::Top_level &top_level); - 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_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 std::string get_member_name_from_enumerant( - const ast::Operand_kinds::Operand_kind::Enumerants::Enumerant - &enumerant); - static const ast::Operand_kinds::Operand_kind &get_operand_kind_from_string( - Generator_state &state, const std::string &operand_kind_str) - { - auto *retval = state.operand_kind_map[operand_kind_str]; - if(!retval) - throw Generate_error("operand kind not found: " + operand_kind_str); - return *retval; - } - static bool get_operand_has_any_parameters(Generator_state &state, - const ast::Operand_kinds::Operand_kind &operand_kind) - { - 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) - { - 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_operand_with_parameters_name( - Generator_state &state, const ast::Operand_kinds::Operand_kind &operand_kind); - static std::string get_operand_with_parameters_name(Generator_state &state, - const std::string &operand_kind_str) - { - return get_operand_with_parameters_name( - state, get_operand_kind_from_string(state, operand_kind_str)); - } - static std::string get_operand_with_parameters_name( - Generator_state &state, const ast::Instructions::Instruction::Operands::Operand &operand) - { - return get_operand_with_parameters_name(state, - get_operand_kind_from_string(state, operand.kind)); - } - 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, - const std::string *member_names, - std::size_t member_count); - static std::vector - get_unique_enumerants( - std::vector enumerants); - -protected: - static constexpr const char *vulkan_cpu_namespace_name = "vulkan_cpu"; - static constexpr const char *spirv_namespace_name = "spirv"; - static constexpr const char *spirv_namespace_names[] = { - vulkan_cpu_namespace_name, spirv_namespace_name, - }; - static constexpr const char *capability_enum_name = "Capability"; - static constexpr const char *extension_enum_name = "Extension"; - static constexpr const char *op_enum_name = "Op"; - -public: - explicit Generator(const char *output_base_file_name) noexcept - : output_base_file_name(output_base_file_name) - { - } - virtual void run(Generator_args &generator_args, const ast::Top_level &top_level) const = 0; - void run(Generator_args &&generator_args, const ast::Top_level &top_level) const - { - run(generator_args, top_level); - } - -public: - virtual ~Generator() = default; -}; - -inline Generator::Push_indent Generator::Generator_state::pushed_indent( - std::ptrdiff_t amount) noexcept -{ - return Push_indent(*this, amount); -} - -struct Spirv_header_generator; -struct Spirv_source_generator; -struct Parser_header_generator; -struct Parser_source_generator; - -struct Generators -{ - static std::unique_ptr make_spirv_header_generator(); - static std::unique_ptr make_spirv_source_generator(); - static std::unique_ptr make_parser_header_generator(); - static std::unique_ptr make_parser_source_generator(); - static std::vector> make_all_generators(); -}; -} -} -} - -#endif /* GENERATE_SPIRV_PARSER_GENERATE_OLD_H_ */