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