1e5dd7070Spatrick#!/usr/bin/env python3 2e5dd7070Spatrick 3e5dd7070Spatrick# This script was committed on 20/11/2019 and it would probably make sense to remove 4e5dd7070Spatrick# it after the next release branches. 5e5dd7070Spatrick 6e5dd7070Spatrick# This script is pipe based and converts an arm_neon.td (or arm_fp16.td) file 7e5dd7070Spatrick# using the old single-char type modifiers to an equivalent new-style form where 8e5dd7070Spatrick# each modifier is orthogonal and they can be composed. 9e5dd7070Spatrick# 10*12c85518Srobert# It was used to directly generate the .td files on main, so if you have any 11e5dd7070Spatrick# local additions I would suggest implementing any modifiers here, and running 12e5dd7070Spatrick# it over your entire pre-merge .td files rather than trying to resolve any 13e5dd7070Spatrick# conflicts manually. 14e5dd7070Spatrick 15e5dd7070Spatrickimport re, sys 16e5dd7070SpatrickMOD_MAP = { 17e5dd7070Spatrick 'v': 'v', 18e5dd7070Spatrick 'x': 'S', 19e5dd7070Spatrick 'u': 'U', 20e5dd7070Spatrick 'd': '.', 21e5dd7070Spatrick 'g': 'q', 22e5dd7070Spatrick 'j': 'Q', 23e5dd7070Spatrick 'w': '>Q', 24e5dd7070Spatrick 'n': '>', 25e5dd7070Spatrick 'h': '<', 26e5dd7070Spatrick 'q': '<Q', 27e5dd7070Spatrick 'e': '<U', 28e5dd7070Spatrick 'm': '<q', 29e5dd7070Spatrick 'i': 'I', 30e5dd7070Spatrick 'l': 'IU>', 31e5dd7070Spatrick 's': '1', 32e5dd7070Spatrick 'z': '1<', 33e5dd7070Spatrick 'r': '1>', 34e5dd7070Spatrick 'b': '1U', 35e5dd7070Spatrick '$': '1S', 36e5dd7070Spatrick 'k': 'Q', 37e5dd7070Spatrick '2': '2', 38e5dd7070Spatrick '3': '3', 39e5dd7070Spatrick '4': '4', 40e5dd7070Spatrick 'B': '2Q', 41e5dd7070Spatrick 'C': '3Q', 42e5dd7070Spatrick 'D': '4Q', 43e5dd7070Spatrick 'p': '*', 44e5dd7070Spatrick 'c': 'c*', 45e5dd7070Spatrick '7': '<<q', 46e5dd7070Spatrick '8': '<<', 47e5dd7070Spatrick '9': '<<Q', 48e5dd7070Spatrick 't': 'p' 49e5dd7070Spatrick } 50e5dd7070Spatrick 51e5dd7070Spatrick 52e5dd7070Spatrickdef typespec_elt_size(typespec): 53e5dd7070Spatrick if 'c' in typespec: 54e5dd7070Spatrick return 8 55e5dd7070Spatrick elif 's' in typespec or 'h' in typespec: 56e5dd7070Spatrick return 16 57e5dd7070Spatrick elif 'i' in typespec or 'f' in typespec: 58e5dd7070Spatrick return 32 59e5dd7070Spatrick elif 'l' in typespec or 'd' in typespec: 60e5dd7070Spatrick return 64 61e5dd7070Spatrick elif 'k' in typespec: 62e5dd7070Spatrick return 128 63e5dd7070Spatrick 64e5dd7070Spatrickdef get_resize(cur, desired): 65e5dd7070Spatrick res = '' 66e5dd7070Spatrick while cur < desired: 67e5dd7070Spatrick res += '>' 68e5dd7070Spatrick cur *= 2 69e5dd7070Spatrick while cur > desired: 70e5dd7070Spatrick res += '<' 71e5dd7070Spatrick cur /= 2 72e5dd7070Spatrick return res 73e5dd7070Spatrick 74e5dd7070Spatrick 75e5dd7070Spatrickdef remap_protocol(proto, typespec, name): 76e5dd7070Spatrick key_type = 0 77e5dd7070Spatrick 78e5dd7070Spatrick # Conversions like to see the integer type so they know signedness. 79e5dd7070Spatrick if 'vcvt' in name and '_f' in name and name != 'vcvt_f32_f64' and name != 'vcvt_f64_f32': 80e5dd7070Spatrick key_type = 1 81e5dd7070Spatrick default_width = typespec_elt_size(typespec) 82e5dd7070Spatrick inconsistent_width = False 83e5dd7070Spatrick for elt in typespec: 84e5dd7070Spatrick new_width = typespec_elt_size(elt) 85e5dd7070Spatrick if new_width and new_width != default_width: 86e5dd7070Spatrick inconsistent_width = True 87e5dd7070Spatrick 88e5dd7070Spatrick res = '' 89e5dd7070Spatrick for i, c in enumerate(proto): 90e5dd7070Spatrick # void and pointers make for bad discriminators in CGBuiltin.cpp. 91e5dd7070Spatrick if c in 'vcp': 92e5dd7070Spatrick key_type += 1 93e5dd7070Spatrick 94e5dd7070Spatrick if c in MOD_MAP: 95e5dd7070Spatrick cur_mod = MOD_MAP[c] 96e5dd7070Spatrick elif inconsistent_width: 97e5dd7070Spatrick # Otherwise it's a fixed output width modifier. 98e5dd7070Spatrick sys.stderr.write(f'warning: {name} uses fixed output size but has inconsistent input widths: {proto} {typespec}\n') 99e5dd7070Spatrick 100e5dd7070Spatrick if c == 'Y': 101e5dd7070Spatrick # y: scalar of half float 102e5dd7070Spatrick resize = get_resize(default_width, 16) 103e5dd7070Spatrick cur_mod = f'1F{resize}' 104e5dd7070Spatrick elif c == 'y': 105e5dd7070Spatrick # y: scalar of float 106e5dd7070Spatrick resize = get_resize(default_width, 32) 107e5dd7070Spatrick cur_mod = f'1F{resize}' 108e5dd7070Spatrick elif c == 'o': 109e5dd7070Spatrick # o: scalar of double 110e5dd7070Spatrick resize = get_resize(default_width, 64) 111e5dd7070Spatrick cur_mod = f'1F{resize}' 112e5dd7070Spatrick elif c == 'I': 113e5dd7070Spatrick # I: scalar of 32-bit signed 114e5dd7070Spatrick resize = get_resize(default_width, 32) 115e5dd7070Spatrick cur_mod = f'1S{resize}' 116e5dd7070Spatrick elif c == 'L': 117e5dd7070Spatrick # L: scalar of 64-bit signed 118e5dd7070Spatrick resize = get_resize(default_width, 64) 119e5dd7070Spatrick cur_mod = f'1S{resize}' 120e5dd7070Spatrick elif c == 'U': 121e5dd7070Spatrick # I: scalar of 32-bit unsigned 122e5dd7070Spatrick resize = get_resize(default_width, 32) 123e5dd7070Spatrick cur_mod = f'1U{resize}' 124e5dd7070Spatrick elif c == 'O': 125e5dd7070Spatrick # O: scalar of 64-bit unsigned 126e5dd7070Spatrick resize = get_resize(default_width, 64) 127e5dd7070Spatrick cur_mod = f'1U{resize}' 128e5dd7070Spatrick elif c == 'f': 129e5dd7070Spatrick # f: float (int args) 130e5dd7070Spatrick resize = get_resize(default_width, 32) 131e5dd7070Spatrick cur_mod = f'F{resize}' 132e5dd7070Spatrick elif c == 'F': 133e5dd7070Spatrick # F: double (int args) 134e5dd7070Spatrick resize = get_resize(default_width, 64) 135e5dd7070Spatrick cur_mod = f'F{resize}' 136e5dd7070Spatrick elif c == 'H': 137e5dd7070Spatrick # H: half (int args) 138e5dd7070Spatrick resize = get_resize(default_width, 16) 139e5dd7070Spatrick cur_mod = f'F{resize}' 140e5dd7070Spatrick elif c == '0': 141e5dd7070Spatrick # 0: half (int args), ignore 'Q' size modifier. 142e5dd7070Spatrick resize = get_resize(default_width, 16) 143e5dd7070Spatrick cur_mod = f'Fq{resize}' 144e5dd7070Spatrick elif c == '1': 145e5dd7070Spatrick # 1: half (int args), force 'Q' size modifier. 146e5dd7070Spatrick resize = get_resize(default_width, 16) 147e5dd7070Spatrick cur_mod = f'FQ{resize}' 148e5dd7070Spatrick 149e5dd7070Spatrick if len(cur_mod) == 0: 150e5dd7070Spatrick raise Exception(f'WTF: {c} in {name}') 151e5dd7070Spatrick 152e5dd7070Spatrick if key_type != 0 and key_type == i: 153e5dd7070Spatrick cur_mod += '!' 154e5dd7070Spatrick 155e5dd7070Spatrick if len(cur_mod) == 1: 156e5dd7070Spatrick res += cur_mod 157e5dd7070Spatrick else: 158e5dd7070Spatrick res += '(' + cur_mod + ')' 159e5dd7070Spatrick 160e5dd7070Spatrick return res 161e5dd7070Spatrick 162e5dd7070Spatrickdef replace_insts(m): 163e5dd7070Spatrick start, end = m.span('proto') 164e5dd7070Spatrick start -= m.start() 165e5dd7070Spatrick end -= m.start() 166e5dd7070Spatrick new_proto = remap_protocol(m['proto'], m['kinds'], m['name']) 167e5dd7070Spatrick return m.group()[:start] + new_proto + m.group()[end:] 168e5dd7070Spatrick 169e5dd7070SpatrickINST = re.compile(r'Inst<"(?P<name>.*?)",\s*"(?P<proto>.*?)",\s*"(?P<kinds>.*?)"') 170e5dd7070Spatrick 171e5dd7070Spatricknew_td = INST.sub(replace_insts, sys.stdin.read()) 172e5dd7070Spatricksys.stdout.write(new_td) 173