def get_spirv_grammar_from_json_spec():
- """Extracts operand kind and instruction grammar from SPIR-V JSON spec.
+ """Extracts operand kind and instruction grammar from SPIR-V JSON spec.
Returns:
- A list containing all operand kinds' grammar
- A list containing all instructions' grammar
"""
- response = requests.get(SPIRV_JSON_SPEC_URL)
- spec = response.content
+ response = requests.get(SPIRV_JSON_SPEC_URL)
+ spec = response.content
- import json
- spirv = json.loads(spec)
+ import json
+ spirv = json.loads(spec)
- return spirv['operand_kinds'], spirv['instructions']
+ return spirv['operand_kinds'], spirv['instructions']
def split_list_into_sublists(items, offset):
- """Split the list of items into multiple sublists.
+ """Split the list of items into multiple sublists.
This is to make sure the string composed from each sublist won't exceed
80 characters.
- items: a list of strings
- offset: the offset in calculating each sublist's length
"""
- chuncks = []
- chunk = []
- chunk_len = 0
+ chuncks = []
+ chunk = []
+ chunk_len = 0
- for item in items:
- chunk_len += len(item) + 2
- if chunk_len > 80:
- chuncks.append(chunk)
- chunk = []
- chunk_len = len(item) + 2
- chunk.append(item)
+ for item in items:
+ chunk_len += len(item) + 2
+ if chunk_len > 80:
+ chuncks.append(chunk)
+ chunk = []
+ chunk_len = len(item) + 2
+ chunk.append(item)
- if len(chunk) != 0:
- chuncks.append(chunk)
+ if len(chunk) != 0:
+ chuncks.append(chunk)
- return chuncks
+ return chuncks
def gen_operand_kind_enum_attr(operand_kind):
- """Generates the TableGen EnumAttr definition for the given operand kind.
+ """Generates the TableGen EnumAttr definition for the given operand kind.
Returns:
- The operand kind's name
- A string containing the TableGen EnumAttr definition
"""
- if 'enumerants' not in operand_kind:
- return '', ''
-
- kind_name = operand_kind['kind']
- kind_acronym = ''.join([c for c in kind_name if c >= 'A' and c <= 'Z'])
- kind_cases = [(case['enumerant'], case['value'])
- for case in operand_kind['enumerants']]
- max_len = max([len(symbol) for (symbol, _) in kind_cases])
-
- # Generate the definition for each enum case
- fmt_str = 'def SPV_{acronym}_{symbol} {colon:>{offset}} '\
- 'EnumAttrCase<"{symbol}">;'
- case_defs = [fmt_str.format(acronym=kind_acronym, symbol=case[0],
- colon=':', offset=(max_len + 1 - len(case[0])))
- for case in kind_cases]
- case_defs = '\n'.join(case_defs)
-
- # Generate the list of enum case names
- fmt_str = 'SPV_{acronym}_{symbol}';
- case_names = [fmt_str.format(acronym=kind_acronym,symbol=case[0])
- for case in kind_cases]
-
- # Split them into sublists and concatenate into multiple lines
- case_names = split_list_into_sublists(case_names, 6)
- case_names = ['{:6}'.format('') + ', '.join(sublist)
- for sublist in case_names]
- case_names = ',\n'.join(case_names)
-
- # Generate the enum attribute definition
- enum_attr = 'def SPV_{name}Attr :\n '\
- 'EnumAttr<"{name}", "valid SPIR-V {name}", [\n{cases}\n ]>;'.format(
- name=kind_name, cases=case_names)
- return kind_name, case_defs + '\n' + enum_attr
+ if 'enumerants' not in operand_kind:
+ return '', ''
+
+ kind_name = operand_kind['kind']
+ kind_acronym = ''.join([c for c in kind_name if c >= 'A' and c <= 'Z'])
+ kind_cases = [(case['enumerant'], case['value'])
+ for case in operand_kind['enumerants']]
+ max_len = max([len(symbol) for (symbol, _) in kind_cases])
+
+ # Generate the definition for each enum case
+ fmt_str = 'def SPV_{acronym}_{symbol} {colon:>{offset}} '\
+ 'EnumAttrCase<"{symbol}">;'
+ case_defs = [fmt_str.format(acronym=kind_acronym, symbol=case[0],
+ colon=':', offset=(max_len + 1 - len(case[0])))
+ for case in kind_cases]
+ case_defs = '\n'.join(case_defs)
+
+ # Generate the list of enum case names
+ fmt_str = 'SPV_{acronym}_{symbol}';
+ case_names = [fmt_str.format(acronym=kind_acronym,symbol=case[0])
+ for case in kind_cases]
+
+ # Split them into sublists and concatenate into multiple lines
+ case_names = split_list_into_sublists(case_names, 6)
+ case_names = ['{:6}'.format('') + ', '.join(sublist)
+ for sublist in case_names]
+ case_names = ',\n'.join(case_names)
+
+ # Generate the enum attribute definition
+ enum_attr = 'def SPV_{name}Attr :\n '\
+ 'EnumAttr<"{name}", "valid SPIR-V {name}", [\n{cases}\n ]>;'.format(
+ name=kind_name, cases=case_names)
+ return kind_name, case_defs + '\n' + enum_attr
def update_td_enum_attrs(path, operand_kinds, filter_list):
- """Updates SPIRBase.td with new generated enum definitions.
+ """Updates SPIRBase.td with new generated enum definitions.
Arguments:
- path: the path to SPIRBase.td
- operand_kinds: a list containing all operand kinds' grammar
- filter_list: a list containing new enums to add
"""
- with open(path, 'r') as f:
- content = f.read()
+ with open(path, 'r') as f:
+ content = f.read()
- content = content.split(AUTOGEN_ENUM_SECTION_MARKER)
- assert len(content) == 3
+ content = content.split(AUTOGEN_ENUM_SECTION_MARKER)
+ assert len(content) == 3
- # Extend filter list with existing enum definitions
- import re
- existing_kinds = [
- k[8:-4] for k in re.findall('def SPV_\w+Attr', content[1])]
- filter_list.extend(existing_kinds)
+ # Extend filter list with existing enum definitions
+ import re
+ existing_kinds = [
+ k[8:-4] for k in re.findall('def SPV_\w+Attr', content[1])]
+ filter_list.extend(existing_kinds)
- # Generate definitions for all enums in filter list
- defs = [gen_operand_kind_enum_attr(kind)
- for kind in operand_kinds if kind['kind'] in filter_list]
- # Sort alphabetically according to enum name
- defs.sort(key=lambda enum : enum[0])
- # Only keep the definitions from now on
- defs = [enum[1] for enum in defs]
+ # Generate definitions for all enums in filter list
+ defs = [gen_operand_kind_enum_attr(kind)
+ for kind in operand_kinds if kind['kind'] in filter_list]
+ # Sort alphabetically according to enum name
+ defs.sort(key=lambda enum : enum[0])
+ # Only keep the definitions from now on
+ defs = [enum[1] for enum in defs]
- # Substitute the old section
- content = content[0] + AUTOGEN_ENUM_SECTION_MARKER + '\n\n' + \
- '\n\n'.join(defs) + "\n\n// End " + AUTOGEN_ENUM_SECTION_MARKER \
- + content[2];
+ # Substitute the old section
+ content = content[0] + AUTOGEN_ENUM_SECTION_MARKER + '\n\n' + \
+ '\n\n'.join(defs) + "\n\n// End " + AUTOGEN_ENUM_SECTION_MARKER \
+ + content[2];
- with open(path, 'w') as f:
- f.write(content)
+ with open(path, 'w') as f:
+ f.write(content)
if __name__ == '__main__':
- import argparse
+ import argparse
- cli_parser = argparse.ArgumentParser(
- description='Update SPIR-V dialect definitions using SPIR-V spec')
- cli_parser.add_argument('--base-td-path', dest='base_td_path', type=str,
- help='Path to SPIRVBase.td')
- cli_parser.add_argument('--new-enum', dest='new_enum', type=str,
- help='SPIR-V enum to be added to SPIRVBase.td')
- args = cli_parser.parse_args()
+ cli_parser = argparse.ArgumentParser(
+ description='Update SPIR-V dialect definitions using SPIR-V spec')
+ cli_parser.add_argument('--base-td-path', dest='base_td_path', type=str,
+ help='Path to SPIRVBase.td')
+ cli_parser.add_argument('--new-enum', dest='new_enum', type=str,
+ help='SPIR-V enum to be added to SPIRVBase.td')
+ args = cli_parser.parse_args()
- operand_kinds, _ = get_spirv_grammar_from_json_spec()
+ operand_kinds, _ = get_spirv_grammar_from_json_spec()
- update_td_enum_attrs(args.base_td_path, operand_kinds, [args.new_enum])
+ update_td_enum_attrs(args.base_td_path, operand_kinds, [args.new_enum])