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