diff options
author | Andrey Tuganov <andreyt@google.com> | 2017-03-15 17:28:24 -0400 |
---|---|---|
committer | David Neto <dneto@google.com> | 2017-03-16 15:29:17 -0400 |
commit | c804c125c568914aabf4d734cf85923611bdfd21 (patch) | |
tree | ca7452d1e51b861435eb8f0ee327d65b6b28d539 /utils | |
parent | b0116331718113de20af5b0a1cc869ccc95b13fa (diff) |
Autogenererating enum-string mappings from grammar
Autogenerating the following code:
- extension enum
- extension-to-string
- string-to-extension
- capability-to-string
Capability mapping table will not compile if incomplete.
TODO: Use "spirv-latest-version.h" instead of 1.1.
Added function to generate capability tables for tests.
Diffstat (limited to 'utils')
-rwxr-xr-x | utils/generate_grammar_tables.py | 124 |
1 files changed, 123 insertions, 1 deletions
diff --git a/utils/generate_grammar_tables.py b/utils/generate_grammar_tables.py index 823fcbff..7ee70e39 100755 --- a/utils/generate_grammar_tables.py +++ b/utils/generate_grammar_tables.py @@ -348,6 +348,111 @@ def generate_operand_kind_table(enums): return '\n\n'.join(enum_entries + (table,)) +def get_extension_list(operands): + """Returns extensions as an alphabetically sorted list of strings.""" + enumerants = sum([item.get('enumerants', []) for item in operands + if item.get('category') in ['ValueEnum']], []) + + extensions = sum([item.get('extensions', []) for item in enumerants + if item.get('extensions')], []) + + return sorted(set(extensions)) + + +def get_capability_list(operands): + """Returns capabilities as a list of strings in the order of appearance.""" + enumerants = sum([item.get('enumerants', []) for item in operands + if item.get('kind') in ['Capability']], []) + return [item.get('enumerant') for item in enumerants] + + +def generate_extension_enum(operands): + """Returns enumeration containing extensions declared in the grammar.""" + extensions = get_extension_list(operands) + return ',\n'.join(['k' + extension for extension in extensions]) + + +def generate_extension_to_string_table(operands): + """Returns extension to string mapping table.""" + extensions = get_extension_list(operands) + entry_template = ' {{Extension::k{extension},\n "{extension}"}}' + table_entries = [entry_template.format(extension=extension) + for extension in extensions] + table_template = '{{\n{enums}\n}}' + return table_template.format(enums=',\n'.join(table_entries)) + + +def generate_string_to_extension_table(operands): + """Returns string to extension mapping table.""" + extensions = get_extension_list(operands) + entry_template = ' {{"{extension}",\n Extension::k{extension}}}' + table_entries = [entry_template.format(extension=extension) + for extension in extensions] + table_template = '{{\n{enums}\n}}' + return table_template.format(enums=',\n'.join(table_entries)) + + +def generate_capability_to_string_table(operands): + """Returns capability to string mapping table.""" + capabilities = get_capability_list(operands) + entry_template = ' {{SpvCapability{capability},\n "{capability}"}}' + table_entries = [entry_template.format(capability=capability) + for capability in capabilities] + table_template = '{{\n{enums}\n}}' + return table_template.format(enums=',\n'.join(table_entries)) + + +def generate_extension_to_string_mapping(operands): + """Returns mapping function from extensions to corresponding strings.""" + extensions = get_extension_list(operands) + function = 'std::string ExtensionToString(Extension extension) {\n' + function += ' switch (extension) {\n' + template = ' case Extension::k{extension}:\n' \ + ' return "{extension}";\n' + function += ''.join([template.format(extension=extension) + for extension in extensions]) + function += ' };\n\n return "";\n}' + return function + + +def generate_string_to_extension_mapping(operands): + """Returns mapping function from strings to corresponding extensions.""" + function = 'bool GetExtensionFromString(' \ + 'const std::string& str, Extension* extension) {\n ' \ + 'static const std::unordered_map<std::string, Extension> mapping =\n' + function += generate_string_to_extension_table(operands) + function += ';\n\n' + function += ' const auto it = mapping.find(str);\n\n' \ + ' if (it == mapping.end()) return false;\n\n' \ + ' *extension = it->second;\n return true;\n}' + return function + + +def generate_capability_to_string_mapping(operands): + """Returns mapping function from capabilities to corresponding strings.""" + capabilities = get_capability_list(operands) + function = 'std::string CapabilityToString(SpvCapability capability) {\n' + function += ' switch (capability) {\n' + template = ' case SpvCapability{capability}:\n' \ + ' return "{capability}";\n' + function += ''.join([template.format(capability=capability) + for capability in capabilities]) + function += ' case SpvCapabilityMax:\n' \ + ' assert(0 && "Attempting to convert SpvCapabilityMax to string");\n' \ + ' return "";\n' + function += ' };\n\n return "";\n}' + return function + + +def generate_all_string_enum_mappings(operands): + """Returns all string-to-enum / enum-to-string mapping tables.""" + tables = [] + tables.append(generate_extension_to_string_mapping(operands)) + tables.append(generate_string_to_extension_mapping(operands)) + tables.append(generate_capability_to_string_mapping(operands)) + return '\n\n'.join(tables) + + def main(): import argparse parser = argparse.ArgumentParser(description='Generate SPIR-V info tables') @@ -375,6 +480,12 @@ def main(): parser.add_argument('--operand-kinds-output', metavar='<path>', type=str, required=False, default=None, help='output file for operand kinds') + parser.add_argument('--extension-enum-output', metavar='<path>', + type=str, required=False, default=None, + help='output file for extension enumeration') + parser.add_argument('--enum-string-mapping-output', metavar='<path>', + type=str, required=False, default=None, + help='output file for enum-string mappings') args = parser.parse_args() if (args.core_insts_output is None) != \ @@ -394,7 +505,9 @@ def main(): exit(1) if all([args.core_insts_output is None, args.glsl_insts_output is None, - args.opencl_insts_output is None]): + args.opencl_insts_output is None, + args.extension_enum_output is None, + args.enum_string_mapping_output is None]): print('error: at least one output should be specified.') exit(1) @@ -407,6 +520,15 @@ def main(): file=open(args.core_insts_output, 'w')) print(generate_operand_kind_table(grammar['operand_kinds']), file=open(args.operand_kinds_output, 'w')) + if args.extension_enum_output is not None: + make_path_to_file(args.extension_enum_output) + print(generate_extension_enum(grammar['operand_kinds']), + file=open(args.extension_enum_output, 'w')) + if args.enum_string_mapping_output is not None: + make_path_to_file(args.enum_string_mapping_output) + print(generate_all_string_enum_mappings( + grammar['operand_kinds']), + file=open(args.enum_string_mapping_output, 'w')) if args.extinst_glsl_grammar is not None: with open(args.extinst_glsl_grammar) as json_file: |