[MIPS GlobalISel] Select MSA vector generic and builtin add
[llvm-complete.git] / utils / UpdateTestChecks / asm.py
blob81556d65802c9c9a68d50ffdbf82e4091d1727e4
1 from __future__ import print_function
2 import re
3 import sys
5 from . import common
7 if sys.version_info[0] > 2:
8 class string:
9 expandtabs = str.expandtabs
10 else:
11 import string
13 # RegEx: this is where the magic happens.
15 ##### Assembly parser
17 ASM_FUNCTION_X86_RE = re.compile(
18 r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@(?P=func)\n(?:\s*\.?Lfunc_begin[^:\n]*:\n)?[^:]*?'
19 r'(?P<body>^##?[ \t]+[^:]+:.*?)\s*'
20 r'^\s*(?:[^:\n]+?:\s*\n\s*\.size|\.cfi_endproc|\.globl|\.comm|\.(?:sub)?section|#+ -- End function)',
21 flags=(re.M | re.S))
23 ASM_FUNCTION_ARM_RE = re.compile(
24 r'^(?P<func>[0-9a-zA-Z_]+):\n' # f: (name of function)
25 r'\s+\.fnstart\n' # .fnstart
26 r'(?P<body>.*?)\n' # (body of the function)
27 r'.Lfunc_end[0-9]+:', # .Lfunc_end0: or # -- End function
28 flags=(re.M | re.S))
30 ASM_FUNCTION_AARCH64_RE = re.compile(
31 r'^_?(?P<func>[^:]+):[ \t]*\/\/[ \t]*@(?P=func)\n'
32 r'(?:[ \t]+.cfi_startproc\n)?' # drop optional cfi noise
33 r'(?P<body>.*?)\n'
34 # This list is incomplete
35 r'.Lfunc_end[0-9]+:\n',
36 flags=(re.M | re.S))
38 ASM_FUNCTION_AMDGPU_RE = re.compile(
39 r'^_?(?P<func>[^:]+):[ \t]*;+[ \t]*@(?P=func)\n[^:]*?'
40 r'(?P<body>.*?)\n' # (body of the function)
41 # This list is incomplete
42 r'^\s*(\.Lfunc_end[0-9]+:\n|\.section)',
43 flags=(re.M | re.S))
45 ASM_FUNCTION_HEXAGON_RE = re.compile(
46 r'^_?(?P<func>[^:]+):[ \t]*//[ \t]*@(?P=func)\n[^:]*?'
47 r'(?P<body>.*?)\n' # (body of the function)
48 # This list is incomplete
49 r'.Lfunc_end[0-9]+:\n',
50 flags=(re.M | re.S))
52 ASM_FUNCTION_MIPS_RE = re.compile(
53 r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@(?P=func)\n[^:]*?' # f: (name of func)
54 r'(?:^[ \t]+\.(frame|f?mask|set).*?\n)+' # Mips+LLVM standard asm prologue
55 r'(?P<body>.*?)\n' # (body of the function)
56 r'(?:^[ \t]+\.(set|end).*?\n)+' # Mips+LLVM standard asm epilogue
57 r'(\$|\.L)func_end[0-9]+:\n', # $func_end0: (mips32 - O32) or
58 # .Lfunc_end0: (mips64 - NewABI)
59 flags=(re.M | re.S))
61 ASM_FUNCTION_MSP430_RE = re.compile(
62 r'^_?(?P<func>[^:]+):[ \t]*;+[ \t]*@(?P=func)\n[^:]*?'
63 r'(?P<body>.*?)\n'
64 r'(\$|\.L)func_end[0-9]+:\n', # $func_end0:
65 flags=(re.M | re.S))
67 ASM_FUNCTION_PPC_RE = re.compile(
68 r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@(?P=func)\n'
69 r'.*?'
70 r'\.Lfunc_begin[0-9]+:\n'
71 r'(?:[ \t]+.cfi_startproc\n)?'
72 r'(?:\.Lfunc_[gl]ep[0-9]+:\n(?:[ \t]+.*?\n)*)*'
73 r'(?P<body>.*?)\n'
74 # This list is incomplete
75 r'(?:^[ \t]*(?:\.long[ \t]+[^\n]+|\.quad[ \t]+[^\n]+)\n)*'
76 r'.Lfunc_end[0-9]+:\n',
77 flags=(re.M | re.S))
79 ASM_FUNCTION_RISCV_RE = re.compile(
80 r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@(?P=func)\n(?:\s*\.?Lfunc_begin[^:\n]*:\n)?[^:]*?'
81 r'(?P<body>^##?[ \t]+[^:]+:.*?)\s*'
82 r'.Lfunc_end[0-9]+:\n',
83 flags=(re.M | re.S))
85 ASM_FUNCTION_LANAI_RE = re.compile(
86 r'^_?(?P<func>[^:]+):[ \t]*!+[ \t]*@(?P=func)\n'
87 r'(?:[ \t]+.cfi_startproc\n)?' # drop optional cfi noise
88 r'(?P<body>.*?)\s*'
89 r'.Lfunc_end[0-9]+:\n',
90 flags=(re.M | re.S))
92 ASM_FUNCTION_SPARC_RE = re.compile(
93 r'^_?(?P<func>[^:]+):[ \t]*!+[ \t]*@(?P=func)\n'
94 r'(?P<body>.*?)\s*'
95 r'.Lfunc_end[0-9]+:\n',
96 flags=(re.M | re.S))
98 ASM_FUNCTION_SYSTEMZ_RE = re.compile(
99 r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@(?P=func)\n'
100 r'[ \t]+.cfi_startproc\n'
101 r'(?P<body>.*?)\n'
102 r'.Lfunc_end[0-9]+:\n',
103 flags=(re.M | re.S))
105 ASM_FUNCTION_AARCH64_DARWIN_RE = re.compile(
106 r'^_(?P<func>[^:]+):[ \t]*;[ \t]@(?P=func)\n'
107 r'([ \t]*.cfi_startproc\n[\s]*)?'
108 r'(?P<body>.*?)'
109 r'([ \t]*.cfi_endproc\n[\s]*)?'
110 r'^[ \t]*;[ \t]--[ \t]End[ \t]function',
111 flags=(re.M | re.S))
113 ASM_FUNCTION_ARM_DARWIN_RE = re.compile(
114 r'^[ \t]*\.globl[ \t]*_(?P<func>[^ \t])[ \t]*@[ \t]--[ \t]Begin[ \t]function[ \t](?P=func)'
115 r'(?P<directives>.*?)'
116 r'^_(?P=func):\n[ \t]*'
117 r'(?P<body>.*?)'
118 r'^[ \t]*@[ \t]--[ \t]End[ \t]function',
119 flags=(re.M | re.S ))
121 ASM_FUNCTION_ARM_MACHO_RE = re.compile(
122 r'^_(?P<func>[^:]+):[ \t]*\n'
123 r'([ \t]*.cfi_startproc\n[ \t]*)?'
124 r'(?P<body>.*?)\n'
125 r'[ \t]*\.cfi_endproc\n',
126 flags=(re.M | re.S))
128 ASM_FUNCTION_ARM_IOS_RE = re.compile(
129 r'^_(?P<func>[^:]+):[ \t]*\n'
130 r'^Lfunc_begin(?P<id>[0-9][1-9]*):\n'
131 r'(?P<body>.*?)'
132 r'^Lfunc_end(?P=id):\n'
133 r'^[ \t]*@[ \t]--[ \t]End[ \t]function',
134 flags=(re.M | re.S))
136 ASM_FUNCTION_WASM32_RE = re.compile(
137 r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@(?P=func)\n'
138 r'(?P<body>.*?)\n'
139 r'^\s*(\.Lfunc_end[0-9]+:\n|end_function)',
140 flags=(re.M | re.S))
143 SCRUB_LOOP_COMMENT_RE = re.compile(
144 r'# =>This Inner Loop Header:.*|# in Loop:.*', flags=re.M)
146 SCRUB_X86_SHUFFLES_RE = (
147 re.compile(
148 r'^(\s*\w+) [^#\n]+#+ ((?:[xyz]mm\d+|mem)( \{%k\d+\}( \{z\})?)? = .*)$',
149 flags=re.M))
150 SCRUB_X86_SPILL_RELOAD_RE = (
151 re.compile(
152 r'-?\d+\(%([er])[sb]p\)(.*(?:Spill|Reload))$',
153 flags=re.M))
154 SCRUB_X86_SP_RE = re.compile(r'\d+\(%(esp|rsp)\)')
155 SCRUB_X86_RIP_RE = re.compile(r'[.\w]+\(%rip\)')
156 SCRUB_X86_LCP_RE = re.compile(r'\.LCPI[0-9]+_[0-9]+')
157 SCRUB_X86_RET_RE = re.compile(r'ret[l|q]')
159 def scrub_asm_x86(asm, args):
160 # Scrub runs of whitespace out of the assembly, but leave the leading
161 # whitespace in place.
162 asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm)
163 # Expand the tabs used for indentation.
164 asm = string.expandtabs(asm, 2)
165 # Detect shuffle asm comments and hide the operands in favor of the comments.
166 asm = SCRUB_X86_SHUFFLES_RE.sub(r'\1 {{.*#+}} \2', asm)
167 # Detect stack spills and reloads and hide their exact offset and whether
168 # they used the stack pointer or frame pointer.
169 asm = SCRUB_X86_SPILL_RELOAD_RE.sub(r'{{[-0-9]+}}(%\1{{[sb]}}p)\2', asm)
170 # Generically match the stack offset of a memory operand.
171 asm = SCRUB_X86_SP_RE.sub(r'{{[0-9]+}}(%\1)', asm)
172 if getattr(args, 'x86_scrub_rip', False):
173 # Generically match a RIP-relative memory operand.
174 asm = SCRUB_X86_RIP_RE.sub(r'{{.*}}(%rip)', asm)
175 # Generically match a LCP symbol.
176 asm = SCRUB_X86_LCP_RE.sub(r'{{\.LCPI.*}}', asm)
177 if getattr(args, 'extra_scrub', False):
178 # Avoid generating different checks for 32- and 64-bit because of 'retl' vs 'retq'.
179 asm = SCRUB_X86_RET_RE.sub(r'ret{{[l|q]}}', asm)
180 # Strip kill operands inserted into the asm.
181 asm = common.SCRUB_KILL_COMMENT_RE.sub('', asm)
182 # Strip trailing whitespace.
183 asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
184 return asm
186 def scrub_asm_amdgpu(asm, args):
187 # Scrub runs of whitespace out of the assembly, but leave the leading
188 # whitespace in place.
189 asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm)
190 # Expand the tabs used for indentation.
191 asm = string.expandtabs(asm, 2)
192 # Strip trailing whitespace.
193 asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
194 return asm
196 def scrub_asm_arm_eabi(asm, args):
197 # Scrub runs of whitespace out of the assembly, but leave the leading
198 # whitespace in place.
199 asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm)
200 # Expand the tabs used for indentation.
201 asm = string.expandtabs(asm, 2)
202 # Strip kill operands inserted into the asm.
203 asm = common.SCRUB_KILL_COMMENT_RE.sub('', asm)
204 # Strip trailing whitespace.
205 asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
206 return asm
208 def scrub_asm_hexagon(asm, args):
209 # Scrub runs of whitespace out of the assembly, but leave the leading
210 # whitespace in place.
211 asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm)
212 # Expand the tabs used for indentation.
213 asm = string.expandtabs(asm, 2)
214 # Strip trailing whitespace.
215 asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
216 return asm
218 def scrub_asm_powerpc(asm, args):
219 # Scrub runs of whitespace out of the assembly, but leave the leading
220 # whitespace in place.
221 asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm)
222 # Expand the tabs used for indentation.
223 asm = string.expandtabs(asm, 2)
224 # Stripe unimportant comments, but leave the token '#' in place.
225 asm = SCRUB_LOOP_COMMENT_RE.sub(r'#', asm)
226 # Strip trailing whitespace.
227 asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
228 return asm
230 def scrub_asm_mips(asm, args):
231 # Scrub runs of whitespace out of the assembly, but leave the leading
232 # whitespace in place.
233 asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm)
234 # Expand the tabs used for indentation.
235 asm = string.expandtabs(asm, 2)
236 # Strip trailing whitespace.
237 asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
238 return asm
240 def scrub_asm_msp430(asm, args):
241 # Scrub runs of whitespace out of the assembly, but leave the leading
242 # whitespace in place.
243 asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm)
244 # Expand the tabs used for indentation.
245 asm = string.expandtabs(asm, 2)
246 # Strip trailing whitespace.
247 asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
248 return asm
250 def scrub_asm_riscv(asm, args):
251 # Scrub runs of whitespace out of the assembly, but leave the leading
252 # whitespace in place.
253 asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm)
254 # Expand the tabs used for indentation.
255 asm = string.expandtabs(asm, 2)
256 # Strip trailing whitespace.
257 asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
258 return asm
260 def scrub_asm_lanai(asm, args):
261 # Scrub runs of whitespace out of the assembly, but leave the leading
262 # whitespace in place.
263 asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm)
264 # Expand the tabs used for indentation.
265 asm = string.expandtabs(asm, 2)
266 # Strip trailing whitespace.
267 asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
268 return asm
270 def scrub_asm_sparc(asm, args):
271 # Scrub runs of whitespace out of the assembly, but leave the leading
272 # whitespace in place.
273 asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm)
274 # Expand the tabs used for indentation.
275 asm = string.expandtabs(asm, 2)
276 # Strip trailing whitespace.
277 asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
278 return asm
280 def scrub_asm_systemz(asm, args):
281 # Scrub runs of whitespace out of the assembly, but leave the leading
282 # whitespace in place.
283 asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm)
284 # Expand the tabs used for indentation.
285 asm = string.expandtabs(asm, 2)
286 # Strip trailing whitespace.
287 asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
288 return asm
290 def scrub_asm_wasm32(asm, args):
291 # Scrub runs of whitespace out of the assembly, but leave the leading
292 # whitespace in place.
293 asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm)
294 # Expand the tabs used for indentation.
295 asm = string.expandtabs(asm, 2)
296 # Strip trailing whitespace.
297 asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
298 return asm
300 def get_triple_from_march(march):
301 triples = {
302 'amdgcn': 'amdgcn',
303 'r600': 'r600',
304 'mips': 'mips',
305 'sparc': 'sparc',
306 'hexagon': 'hexagon',
308 for prefix, triple in triples.items():
309 if march.startswith(prefix):
310 return triple
311 print("Cannot find a triple. Assume 'x86'", file=sys.stderr)
312 return 'x86'
314 def build_function_body_dictionary_for_triple(args, raw_tool_output, triple, prefixes, func_dict):
315 target_handlers = {
316 'i686': (scrub_asm_x86, ASM_FUNCTION_X86_RE),
317 'x86': (scrub_asm_x86, ASM_FUNCTION_X86_RE),
318 'i386': (scrub_asm_x86, ASM_FUNCTION_X86_RE),
319 'aarch64': (scrub_asm_arm_eabi, ASM_FUNCTION_AARCH64_RE),
320 'aarch64-apple-darwin': (scrub_asm_arm_eabi, ASM_FUNCTION_AARCH64_DARWIN_RE),
321 'hexagon': (scrub_asm_hexagon, ASM_FUNCTION_HEXAGON_RE),
322 'r600': (scrub_asm_amdgpu, ASM_FUNCTION_AMDGPU_RE),
323 'amdgcn': (scrub_asm_amdgpu, ASM_FUNCTION_AMDGPU_RE),
324 'arm': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
325 'arm64': (scrub_asm_arm_eabi, ASM_FUNCTION_AARCH64_RE),
326 'arm64-apple-ios': (scrub_asm_arm_eabi, ASM_FUNCTION_AARCH64_DARWIN_RE),
327 'armv7-apple-ios' : (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_IOS_RE),
328 'armv7-apple-darwin': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_DARWIN_RE),
329 'thumb': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
330 'thumb-macho': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_MACHO_RE),
331 'thumbv5-macho': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_MACHO_RE),
332 'thumbv7-apple-ios' : (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_IOS_RE),
333 'mips': (scrub_asm_mips, ASM_FUNCTION_MIPS_RE),
334 'msp430': (scrub_asm_msp430, ASM_FUNCTION_MSP430_RE),
335 'ppc32': (scrub_asm_powerpc, ASM_FUNCTION_PPC_RE),
336 'powerpc': (scrub_asm_powerpc, ASM_FUNCTION_PPC_RE),
337 'riscv32': (scrub_asm_riscv, ASM_FUNCTION_RISCV_RE),
338 'riscv64': (scrub_asm_riscv, ASM_FUNCTION_RISCV_RE),
339 'lanai': (scrub_asm_lanai, ASM_FUNCTION_LANAI_RE),
340 'sparc': (scrub_asm_sparc, ASM_FUNCTION_SPARC_RE),
341 's390x': (scrub_asm_systemz, ASM_FUNCTION_SYSTEMZ_RE),
342 'wasm32': (scrub_asm_wasm32, ASM_FUNCTION_WASM32_RE),
344 handler = None
345 best_prefix = ''
346 for prefix, s in target_handlers.items():
347 if triple.startswith(prefix) and len(prefix) > len(best_prefix):
348 handler = s
349 best_prefix = prefix
351 if handler is None:
352 raise KeyError('Triple %r is not supported' % (triple))
354 scrubber, function_re = handler
355 common.build_function_body_dictionary(
356 function_re, scrubber, [args], raw_tool_output, prefixes,
357 func_dict, args.verbose)
359 ##### Generator of assembly CHECK lines
361 def add_asm_checks(output_lines, comment_marker, prefix_list, func_dict, func_name):
362 # Label format is based on ASM string.
363 check_label_format = '{} %s-LABEL: %s:'.format(comment_marker)
364 common.add_checks(output_lines, comment_marker, prefix_list, func_dict, func_name, check_label_format, True, False)