xref: /llvm-project/llvm/utils/UpdateTestChecks/asm.py (revision 2f62803ea458f83dcfc307cffa7f1ebf09eb9655)
1from __future__ import print_function
2import re
3import sys
4
5from . import common
6
7if sys.version_info[0] > 2:
8
9    class string:
10        expandtabs = str.expandtabs
11
12else:
13    import string
14
15# RegEx: this is where the magic happens.
16
17##### Assembly parser
18
19ASM_FUNCTION_X86_RE = re.compile(
20    r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*(@"?(?P=func)"?| -- Begin function (?P=func))\n(?:\s*\.?Lfunc_begin[^:\n]*:\n)?'
21    r"(?:\.L(?P=func)\$local:\n)?"  # drop .L<func>$local:
22    r"(?:\s*\.type\s+\.L(?P=func)\$local,@function\n)?"  # drop .type .L<func>$local
23    r"(?:[ \t]*(?:\.cfi_startproc|\.cfi_personality|\.cfi_lsda|\.seh_proc|\.seh_handler)\b[^\n]*\n)*"  # drop optional cfi
24    r"(?P<body>^##?[ \t]+[^:]+:.*?)\s*"
25    r"^\s*(?:[^:\n]+?:\s*\n\s*\.size|\.cfi_endproc|\.globl|\.comm|\.(?:sub)?section|#+ -- End function)",
26    flags=(re.M | re.S),
27)
28
29ASM_FUNCTION_ARM_RE = re.compile(
30    r"^(?P<func>[0-9a-zA-Z_$]+):\n"  # f: (name of function)
31    r"(?:\.L(?P=func)\$local:\n)?"  # drop .L<func>$local:
32    r"(?:\s*\.type\s+\.L(?P=func)\$local,@function\n)?"  # drop .type .L<func>$local
33    r"\s+\.fnstart\n"  # .fnstart
34    r"(?P<body>.*?)"  # (body of the function)
35    r"^.Lfunc_end[0-9]+:",  # .Lfunc_end0: or # -- End function
36    flags=(re.M | re.S),
37)
38
39ASM_FUNCTION_AARCH64_RE = re.compile(
40    r'^_?(?P<func>[^:]+):[ \t]*\/\/[ \t]*@"?(?P=func)"?( (Function|Tail Call))?\n'
41    r"(?:[ \t]+.cfi_startproc\n)?"  # drop optional cfi noise
42    r"(?P<body>.*?)\n"
43    # This list is incomplete
44    r"^\s*(\.Lfunc_end[0-9]+|// -- End function)",
45    flags=(re.M | re.S),
46)
47
48ASM_FUNCTION_AMDGPU_RE = re.compile(
49    r'^_?(?P<func>[^:]+):[ \t]*;+[ \t]*@"?(?P=func)"?\n[^:]*?'
50    r"(?P<body>.*?)\n"  # (body of the function)
51    # This list is incomplete
52    r"^\s*(\.Lfunc_end[0-9]+:\n|\.section)",
53    flags=(re.M | re.S),
54)
55
56ASM_FUNCTION_BPF_RE = re.compile(
57    r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@"?(?P=func)"?\n'
58    r"(?:[ \t]+.cfi_startproc\n|.seh_proc[^\n]+\n)?"  # drop optional cfi
59    r"(?P<body>.*?)\s*"
60    r".Lfunc_end[0-9]+:\n",
61    flags=(re.M | re.S),
62)
63
64ASM_FUNCTION_HEXAGON_RE = re.compile(
65    r'^_?(?P<func>[^:]+):[ \t]*//[ \t]*@"?(?P=func)"?\n[^:]*?'
66    r"(?P<body>.*?)\n"  # (body of the function)
67    # This list is incomplete
68    r".Lfunc_end[0-9]+:\n",
69    flags=(re.M | re.S),
70)
71
72ASM_FUNCTION_M68K_RE = re.compile(
73    r'^_?(?P<func>[^:]+):[ \t]*;[ \t]*@"?(?P=func)"?\n'
74    r'(?:\.L(?P=func)\$local:\n)?'  # drop .L<func>$local:
75    r'(?:[ \t]+\.type[ \t]+\.L(?P=func)\$local,@function\n)?' # drop .type .L<func>$local,@function
76    r'(?P<body>.*?)\s*' # (body of the function)
77    r'.Lfunc_end[0-9]+:\n',
78    flags=(re.M | re.S))
79
80ASM_FUNCTION_MIPS_RE = re.compile(
81    r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@"?(?P=func)"?\n[^:]*?'  # f: (name of func)
82    r"(?:\s*\.?Ltmp[^:\n]*:\n)?[^:]*?"  # optional .Ltmp<N> for EH
83    r"(?:^[ \t]+\.(frame|f?mask|set).*?\n)+"  # Mips+LLVM standard asm prologue
84    r"(?P<body>.*?)\n"  # (body of the function)
85    # Mips+LLVM standard asm epilogue
86    r"(?:(^[ \t]+\.set[^\n]*?\n)*^[ \t]+\.end.*?\n)"
87    r"(\$|\.L)func_end[0-9]+:\n",  # $func_end0: (mips32 - O32) or
88    # .Lfunc_end0: (mips64 - NewABI)
89    flags=(re.M | re.S),
90)
91
92ASM_FUNCTION_MSP430_RE = re.compile(
93    r'^_?(?P<func>[^:]+):[ \t]*;+[ \t]*@"?(?P=func)"?\n[^:]*?'
94    r"(?P<body>.*?)\n"
95    r"(\$|\.L)func_end[0-9]+:\n",  # $func_end0:
96    flags=(re.M | re.S),
97)
98
99ASM_FUNCTION_AVR_RE = re.compile(
100    r'^_?(?P<func>[^:]+):[ \t]*;+[ \t]*@"?(?P=func)"?\n[^:]*?'
101    r"(?P<body>.*?)\n"
102    r".Lfunc_end[0-9]+:\n",
103    flags=(re.M | re.S),
104)
105
106ASM_FUNCTION_PPC_RE = re.compile(
107    r"#[ \-\t]*Begin function (?P<func>[^.:]+)\n"
108    r".*?"
109    r'^[_.]?(?P=func):(?:[ \t]*#+[ \t]*@"?(?P=func)"?)?\n'
110    r"(?:^[^#]*\n)*"
111    r"(?P<body>.*?)\n"
112    # This list is incomplete
113    r"(?:^[ \t]*(?:\.(?:long|quad|v?byte)[ \t]+[^\n]+)\n)*"
114    r"(?:\.Lfunc_end|L\.\.(?P=func))[0-9]+:\n",
115    flags=(re.M | re.S),
116)
117
118ASM_FUNCTION_RISCV_RE = re.compile(
119    r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@"?(?P=func)"?\n'
120    r"(?:\s*\.?L(?P=func)\$local:\n)?"  # optional .L<func>$local: due to -fno-semantic-interposition
121    r"(?:\s*\.type\s+\.?L(?P=func)\$local,@function\n)?"  # optional .type .L<func>$local
122    r"(?:\s*\.?Lfunc_begin[^:\n]*:\n)?[^:]*?"
123    r"(?P<body>^##?[ \t]+[^:]+:.*?)\s*"
124    r".Lfunc_end[0-9]+:\n",
125    flags=(re.M | re.S),
126)
127
128ASM_FUNCTION_LANAI_RE = re.compile(
129    r'^_?(?P<func>[^:]+):[ \t]*!+[ \t]*@"?(?P=func)"?\n'
130    r"(?:[ \t]+.cfi_startproc\n)?"  # drop optional cfi noise
131    r"(?P<body>.*?)\s*"
132    r".Lfunc_end[0-9]+:\n",
133    flags=(re.M | re.S),
134)
135
136ASM_FUNCTION_SPARC_RE = re.compile(
137    r'^_?(?P<func>[^:]+):[ \t]*!+[ \t]*@"?(?P=func)"?\n'
138    r"(?P<body>.*?)\s*"
139    r".Lfunc_end[0-9]+:\n",
140    flags=(re.M | re.S),
141)
142
143ASM_FUNCTION_SYSTEMZ_RE = re.compile(
144    r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@"?(?P=func)"?\n'
145    r"(?:[ \t]+.cfi_startproc\n)?"
146    r"(?P<body>.*?)\n"
147    r".Lfunc_end[0-9]+:\n",
148    flags=(re.M | re.S),
149)
150
151ASM_FUNCTION_AARCH64_DARWIN_RE = re.compile(
152    r'^_(?P<func>[^:]+):[ \t]*;[ \t]@"?(?P=func)"?\n'
153    r"([ \t]*.cfi_startproc\n[\s]*)?"
154    r"(?P<body>.*?)"
155    r"([ \t]*.cfi_endproc\n[\s]*)?"
156    r"^[ \t]*;[ \t]--[ \t]End[ \t]function",
157    flags=(re.M | re.S),
158)
159
160ASM_FUNCTION_ARM_DARWIN_RE = re.compile(
161    r"@[ \t]--[ \t]Begin[ \t]function[ \t](?P<func>[^ \t]+?)\n"
162    r"^[ \t]*\.globl[ \t]*_(?P=func)[ \t]*"
163    r"(?P<directives>.*?)"
164    r"^_(?P=func):\n[ \t]*"
165    r"(?P<body>.*?)"
166    r"^[ \t]*@[ \t]--[ \t]End[ \t]function",
167    flags=(re.M | re.S),
168)
169
170ASM_FUNCTION_ARM_MACHO_RE = re.compile(
171    r"^_(?P<func>[^:]+):[ \t]*\n"
172    r"([ \t]*.cfi_startproc\n[ \t]*)?"
173    r"(?P<body>.*?)\n"
174    r"[ \t]*\.cfi_endproc\n",
175    flags=(re.M | re.S),
176)
177
178ASM_FUNCTION_THUMBS_DARWIN_RE = re.compile(
179    r"^_(?P<func>[^:]+):\n" r"(?P<body>.*?)\n" r"[ \t]*\.data_region\n",
180    flags=(re.M | re.S),
181)
182
183ASM_FUNCTION_THUMB_DARWIN_RE = re.compile(
184    r"^_(?P<func>[^:]+):\n" r"(?P<body>.*?)\n" r"^[ \t]*@[ \t]--[ \t]End[ \t]function",
185    flags=(re.M | re.S),
186)
187
188ASM_FUNCTION_ARM_IOS_RE = re.compile(
189    r"^_(?P<func>[^:]+):\n" r"(?P<body>.*?)" r"^[ \t]*@[ \t]--[ \t]End[ \t]function",
190    flags=(re.M | re.S),
191)
192
193ASM_FUNCTION_WASM_RE = re.compile(
194    r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@"?(?P=func)"?\n'
195    r"(?P<body>.*?)\n"
196    r"^\s*(\.Lfunc_end[0-9]+:\n|end_function)",
197    flags=(re.M | re.S),
198)
199
200ASM_FUNCTION_VE_RE = re.compile(
201    r"^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@(?P=func)\n"
202    r"(?:\s*\.?L(?P=func)\$local:\n)?"  # optional .L<func>$local: due to -fno-semantic-interposition
203    r"(?:\s*\.type\s+\.?L(?P=func)\$local,@function\n)?"  # optional .type .L<func>$local
204    r"(?:\s*\.?Lfunc_begin[^:\n]*:\n)?[^:]*?"
205    r"(?P<body>^##?[ \t]+[^:]+:.*?)\s*"
206    r".Lfunc_end[0-9]+:\n",
207    flags=(re.M | re.S),
208)
209
210ASM_FUNCTION_CSKY_RE = re.compile(
211    r"^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@(?P=func)\n(?:\s*\.?Lfunc_begin[^:\n]*:\n)?[^:]*?"
212    r"(?P<body>^##?[ \t]+[^:]+:.*?)\s*"
213    r".Lfunc_end[0-9]+:\n",
214    flags=(re.M | re.S),
215)
216
217ASM_FUNCTION_NVPTX_RE = re.compile(
218    # function attributes and retval
219    # .visible .func (.param .align 16 .b8 func_retval0[32])
220    # r'^(\.visible\s+)?\.func\s+(\([^\)]*\)\s*)?'
221    r"^(\.(func|visible|weak|entry|noreturn|extern)\s+)+(\([^\)]*\)\s*)?"
222    # function name
223    r"(?P<func>[^\(\n]+)"
224    # function name separator (opening brace)
225    r"(?P<func_name_separator>\()"
226    # function parameters
227    # (
228    #   .param .align 16 .b8 callee_St8x4_param_0[32]
229    # ) // -- Begin function callee_St8x4
230    r"[^\)]*\)(\s*//[^\n]*)?\n"
231    # function body
232    r"(?P<body>.*?)\n"
233    # function body end marker
234    r"\s*// -- End function",
235    flags=(re.M | re.S),
236)
237
238ASM_FUNCTION_LOONGARCH_RE = re.compile(
239    r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@"?(?P=func)"?\n'
240    r"(?:\s*\.?Lfunc_begin[^:\n]*:\n)?[^:]*?"
241    r"(?P<body>^##?[ \t]+[^:]+:.*?)\s*"
242    r".Lfunc_end[0-9]+:\n",
243    flags=(re.M | re.S),
244)
245
246SCRUB_X86_SHUFFLES_RE = re.compile(
247    r"^(\s*\w+) [^#\n]+#+ ((?:[xyz]mm\d+|mem)( \{%k\d+\}( \{z\})?)? = .*)$", flags=re.M
248)
249
250SCRUB_X86_SHUFFLES_NO_MEM_RE = re.compile(
251    r"^(\s*\w+) [^#\n]+#+ ((?:[xyz]mm\d+|mem)( \{%k\d+\}( \{z\})?)? = (?!.*(?:mem)).*)$",
252    flags=re.M,
253)
254
255SCRUB_X86_SPILL_RELOAD_RE = re.compile(
256    r"-?\d+\(%([er])[sb]p\)(.*(?:Spill|Reload))$", flags=re.M
257)
258SCRUB_X86_SP_RE = re.compile(r"\d+\(%(esp|rsp)\)")
259SCRUB_X86_RIP_RE = re.compile(r"[.\w]+\(%rip\)")
260SCRUB_X86_LCP_RE = re.compile(r"\.?LCPI[0-9]+_[0-9]+")
261SCRUB_X86_RET_RE = re.compile(r"ret[l|q]")
262
263
264def scrub_asm_x86(asm, args):
265    # Scrub runs of whitespace out of the assembly, but leave the leading
266    # whitespace in place.
267    asm = common.SCRUB_WHITESPACE_RE.sub(r" ", asm)
268    # Expand the tabs used for indentation.
269    asm = string.expandtabs(asm, 2)
270
271    # Detect shuffle asm comments and hide the operands in favor of the comments.
272    if getattr(args, "no_x86_scrub_mem_shuffle", True):
273        asm = SCRUB_X86_SHUFFLES_NO_MEM_RE.sub(r"\1 {{.*#+}} \2", asm)
274    else:
275        asm = SCRUB_X86_SHUFFLES_RE.sub(r"\1 {{.*#+}} \2", asm)
276
277    # Detect stack spills and reloads and hide their exact offset and whether
278    # they used the stack pointer or frame pointer.
279    asm = SCRUB_X86_SPILL_RELOAD_RE.sub(r"{{[-0-9]+}}(%\1{{[sb]}}p)\2", asm)
280    if getattr(args, "x86_scrub_sp", True):
281        # Generically match the stack offset of a memory operand.
282        asm = SCRUB_X86_SP_RE.sub(r"{{[0-9]+}}(%\1)", asm)
283    if getattr(args, "x86_scrub_rip", False):
284        # Generically match a RIP-relative memory operand.
285        asm = SCRUB_X86_RIP_RE.sub(r"{{.*}}(%rip)", asm)
286    # Generically match a LCP symbol.
287    asm = SCRUB_X86_LCP_RE.sub(r"{{\.?LCPI[0-9]+_[0-9]+}}", asm)
288    if getattr(args, "extra_scrub", False):
289        # Avoid generating different checks for 32- and 64-bit because of 'retl' vs 'retq'.
290        asm = SCRUB_X86_RET_RE.sub(r"ret{{[l|q]}}", asm)
291    # Strip kill operands inserted into the asm.
292    asm = common.SCRUB_KILL_COMMENT_RE.sub("", asm)
293    # Strip trailing whitespace.
294    asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r"", asm)
295    return asm
296
297
298def scrub_asm_amdgpu(asm, args):
299    # Scrub runs of whitespace out of the assembly, but leave the leading
300    # whitespace in place.
301    asm = common.SCRUB_WHITESPACE_RE.sub(r" ", asm)
302    # Expand the tabs used for indentation.
303    asm = string.expandtabs(asm, 2)
304    # Strip trailing whitespace.
305    asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r"", asm)
306    return asm
307
308
309def scrub_asm_arm_eabi(asm, args):
310    # Scrub runs of whitespace out of the assembly, but leave the leading
311    # whitespace in place.
312    asm = common.SCRUB_WHITESPACE_RE.sub(r" ", asm)
313    # Expand the tabs used for indentation.
314    asm = string.expandtabs(asm, 2)
315    # Strip kill operands inserted into the asm.
316    asm = common.SCRUB_KILL_COMMENT_RE.sub("", asm)
317    # Strip trailing whitespace.
318    asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r"", asm)
319    return asm
320
321
322def scrub_asm_bpf(asm, args):
323    # Scrub runs of whitespace out of the assembly, but leave the leading
324    # whitespace in place.
325    asm = common.SCRUB_WHITESPACE_RE.sub(r" ", asm)
326    # Expand the tabs used for indentation.
327    asm = string.expandtabs(asm, 2)
328    # Strip trailing whitespace.
329    asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r"", asm)
330    return asm
331
332
333def scrub_asm_hexagon(asm, args):
334    # Scrub runs of whitespace out of the assembly, but leave the leading
335    # whitespace in place.
336    asm = common.SCRUB_WHITESPACE_RE.sub(r" ", asm)
337    # Expand the tabs used for indentation.
338    asm = string.expandtabs(asm, 2)
339    # Strip trailing whitespace.
340    asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r"", asm)
341    return asm
342
343
344def scrub_asm_powerpc(asm, args):
345    # Scrub runs of whitespace out of the assembly, but leave the leading
346    # whitespace in place.
347    asm = common.SCRUB_WHITESPACE_RE.sub(r" ", asm)
348    # Expand the tabs used for indentation.
349    asm = string.expandtabs(asm, 2)
350    # Strip unimportant comments, but leave the token '#' in place.
351    asm = common.SCRUB_LOOP_COMMENT_RE.sub(r"#", asm)
352    # Strip trailing whitespace.
353    asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r"", asm)
354    # Strip the tailing token '#', except the line only has token '#'.
355    asm = common.SCRUB_TAILING_COMMENT_TOKEN_RE.sub(r"", asm)
356    return asm
357
358
359def scrub_asm_m68k(asm, args):
360    # Scrub runs of whitespace out of the assembly, but leave the leading
361    # whitespace in place.
362    asm = common.SCRUB_WHITESPACE_RE.sub(r" ", asm)
363    # Expand the tabs used for indentation.
364    asm = string.expandtabs(asm, 2)
365    # Strip trailing whitespace.
366    asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r"", asm)
367    return asm
368
369
370def scrub_asm_mips(asm, args):
371    # Scrub runs of whitespace out of the assembly, but leave the leading
372    # whitespace in place.
373    asm = common.SCRUB_WHITESPACE_RE.sub(r" ", asm)
374    # Expand the tabs used for indentation.
375    asm = string.expandtabs(asm, 2)
376    # Strip trailing whitespace.
377    asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r"", asm)
378    return asm
379
380
381def scrub_asm_msp430(asm, args):
382    # Scrub runs of whitespace out of the assembly, but leave the leading
383    # whitespace in place.
384    asm = common.SCRUB_WHITESPACE_RE.sub(r" ", asm)
385    # Expand the tabs used for indentation.
386    asm = string.expandtabs(asm, 2)
387    # Strip trailing whitespace.
388    asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r"", asm)
389    return asm
390
391
392def scrub_asm_avr(asm, args):
393    # Scrub runs of whitespace out of the assembly, but leave the leading
394    # whitespace in place.
395    asm = common.SCRUB_WHITESPACE_RE.sub(r" ", asm)
396    # Expand the tabs used for indentation.
397    asm = string.expandtabs(asm, 2)
398    # Strip trailing whitespace.
399    asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r"", asm)
400    return asm
401
402
403def scrub_asm_riscv(asm, args):
404    # Scrub runs of whitespace out of the assembly, but leave the leading
405    # whitespace in place.
406    asm = common.SCRUB_WHITESPACE_RE.sub(r" ", asm)
407    # Expand the tabs used for indentation.
408    asm = string.expandtabs(asm, 2)
409    # Strip trailing whitespace.
410    asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r"", asm)
411    return asm
412
413
414def scrub_asm_lanai(asm, args):
415    # Scrub runs of whitespace out of the assembly, but leave the leading
416    # whitespace in place.
417    asm = common.SCRUB_WHITESPACE_RE.sub(r" ", asm)
418    # Expand the tabs used for indentation.
419    asm = string.expandtabs(asm, 2)
420    # Strip trailing whitespace.
421    asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r"", asm)
422    return asm
423
424
425def scrub_asm_sparc(asm, args):
426    # Scrub runs of whitespace out of the assembly, but leave the leading
427    # whitespace in place.
428    asm = common.SCRUB_WHITESPACE_RE.sub(r" ", asm)
429    # Expand the tabs used for indentation.
430    asm = string.expandtabs(asm, 2)
431    # Strip trailing whitespace.
432    asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r"", asm)
433    return asm
434
435
436def scrub_asm_systemz(asm, args):
437    # Scrub runs of whitespace out of the assembly, but leave the leading
438    # whitespace in place.
439    asm = common.SCRUB_WHITESPACE_RE.sub(r" ", asm)
440    # Expand the tabs used for indentation.
441    asm = string.expandtabs(asm, 2)
442    # Strip trailing whitespace.
443    asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r"", asm)
444    return asm
445
446
447def scrub_asm_wasm(asm, args):
448    # Scrub runs of whitespace out of the assembly, but leave the leading
449    # whitespace in place.
450    asm = common.SCRUB_WHITESPACE_RE.sub(r" ", asm)
451    # Expand the tabs used for indentation.
452    asm = string.expandtabs(asm, 2)
453    # Strip trailing whitespace.
454    asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r"", asm)
455    return asm
456
457
458def scrub_asm_ve(asm, args):
459    # Scrub runs of whitespace out of the assembly, but leave the leading
460    # whitespace in place.
461    asm = common.SCRUB_WHITESPACE_RE.sub(r" ", asm)
462    # Expand the tabs used for indentation.
463    asm = string.expandtabs(asm, 2)
464    # Strip trailing whitespace.
465    asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r"", asm)
466    return asm
467
468
469def scrub_asm_csky(asm, args):
470    # Scrub runs of whitespace out of the assembly, but leave the leading
471    # whitespace in place.
472    asm = common.SCRUB_WHITESPACE_RE.sub(r" ", asm)
473    # Expand the tabs used for indentation.
474    asm = string.expandtabs(asm, 2)
475    # Strip kill operands inserted into the asm.
476    asm = common.SCRUB_KILL_COMMENT_RE.sub("", asm)
477    # Strip trailing whitespace.
478    asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r"", asm)
479    return asm
480
481
482def scrub_asm_nvptx(asm, args):
483    # Scrub runs of whitespace out of the assembly, but leave the leading
484    # whitespace in place.
485    asm = common.SCRUB_WHITESPACE_RE.sub(r" ", asm)
486    # Expand the tabs used for indentation.
487    asm = string.expandtabs(asm, 2)
488    # Strip trailing whitespace.
489    asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r"", asm)
490    return asm
491
492
493def scrub_asm_loongarch(asm, args):
494    # Scrub runs of whitespace out of the assembly, but leave the leading
495    # whitespace in place.
496    asm = common.SCRUB_WHITESPACE_RE.sub(r" ", asm)
497    # Expand the tabs used for indentation.
498    asm = string.expandtabs(asm, 2)
499    # Strip trailing whitespace.
500    asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r"", asm)
501    return asm
502
503
504# Returns a tuple of a scrub function and a function regex. Scrub function is
505# used to alter function body in some way, for example, remove trailing spaces.
506# Function regex is used to match function name, body, etc. in raw llc output.
507def get_run_handler(triple):
508    target_handlers = {
509        "i686": (scrub_asm_x86, ASM_FUNCTION_X86_RE),
510        "x86": (scrub_asm_x86, ASM_FUNCTION_X86_RE),
511        "i386": (scrub_asm_x86, ASM_FUNCTION_X86_RE),
512        "arm64_32-apple-ios": (scrub_asm_arm_eabi, ASM_FUNCTION_AARCH64_DARWIN_RE),
513        "arm64_32-apple-watchos2.0.0": (
514            scrub_asm_arm_eabi,
515            ASM_FUNCTION_AARCH64_DARWIN_RE,
516        ),
517        "aarch64": (scrub_asm_arm_eabi, ASM_FUNCTION_AARCH64_RE),
518        "aarch64-apple-darwin": (scrub_asm_arm_eabi, ASM_FUNCTION_AARCH64_DARWIN_RE),
519        "aarch64-apple-ios": (scrub_asm_arm_eabi, ASM_FUNCTION_AARCH64_DARWIN_RE),
520        "bpf": (scrub_asm_bpf, ASM_FUNCTION_BPF_RE),
521        "bpfel": (scrub_asm_bpf, ASM_FUNCTION_BPF_RE),
522        "bpfeb": (scrub_asm_bpf, ASM_FUNCTION_BPF_RE),
523        "hexagon": (scrub_asm_hexagon, ASM_FUNCTION_HEXAGON_RE),
524        "r600": (scrub_asm_amdgpu, ASM_FUNCTION_AMDGPU_RE),
525        "amdgcn": (scrub_asm_amdgpu, ASM_FUNCTION_AMDGPU_RE),
526        "arm": (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
527        "arm64": (scrub_asm_arm_eabi, ASM_FUNCTION_AARCH64_RE),
528        "arm64e": (scrub_asm_arm_eabi, ASM_FUNCTION_AARCH64_DARWIN_RE),
529        "arm64ec": (scrub_asm_arm_eabi, ASM_FUNCTION_AARCH64_RE),
530        "arm64-apple-ios": (scrub_asm_arm_eabi, ASM_FUNCTION_AARCH64_DARWIN_RE),
531        "armv7-apple-ios": (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_IOS_RE),
532        "armv7-apple-darwin": (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_DARWIN_RE),
533        "thumb": (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
534        "thumb-macho": (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_MACHO_RE),
535        "thumbv5-macho": (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_MACHO_RE),
536        "thumbv7s-apple-darwin": (scrub_asm_arm_eabi, ASM_FUNCTION_THUMBS_DARWIN_RE),
537        "thumbv7-apple-darwin": (scrub_asm_arm_eabi, ASM_FUNCTION_THUMB_DARWIN_RE),
538        "thumbv7-apple-ios": (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_IOS_RE),
539        "m68k": (scrub_asm_m68k, ASM_FUNCTION_M68K_RE),
540        "mips": (scrub_asm_mips, ASM_FUNCTION_MIPS_RE),
541        "msp430": (scrub_asm_msp430, ASM_FUNCTION_MSP430_RE),
542        "avr": (scrub_asm_avr, ASM_FUNCTION_AVR_RE),
543        "ppc32": (scrub_asm_powerpc, ASM_FUNCTION_PPC_RE),
544        "ppc64": (scrub_asm_powerpc, ASM_FUNCTION_PPC_RE),
545        "powerpc": (scrub_asm_powerpc, ASM_FUNCTION_PPC_RE),
546        "riscv32": (scrub_asm_riscv, ASM_FUNCTION_RISCV_RE),
547        "riscv64": (scrub_asm_riscv, ASM_FUNCTION_RISCV_RE),
548        "lanai": (scrub_asm_lanai, ASM_FUNCTION_LANAI_RE),
549        "sparc": (scrub_asm_sparc, ASM_FUNCTION_SPARC_RE),
550        "s390x": (scrub_asm_systemz, ASM_FUNCTION_SYSTEMZ_RE),
551        "wasm32": (scrub_asm_wasm, ASM_FUNCTION_WASM_RE),
552        "wasm64": (scrub_asm_wasm, ASM_FUNCTION_WASM_RE),
553        "ve": (scrub_asm_ve, ASM_FUNCTION_VE_RE),
554        "csky": (scrub_asm_csky, ASM_FUNCTION_CSKY_RE),
555        "nvptx": (scrub_asm_nvptx, ASM_FUNCTION_NVPTX_RE),
556        "loongarch32": (scrub_asm_loongarch, ASM_FUNCTION_LOONGARCH_RE),
557        "loongarch64": (scrub_asm_loongarch, ASM_FUNCTION_LOONGARCH_RE),
558    }
559    handler = None
560    best_prefix = ""
561    for prefix, s in target_handlers.items():
562        if triple.startswith(prefix) and len(prefix) > len(best_prefix):
563            handler = s
564            best_prefix = prefix
565
566    if handler is None:
567        raise KeyError("Triple %r is not supported" % (triple))
568
569    return handler
570
571
572##### Generator of assembly CHECK lines
573
574
575def add_checks(
576    output_lines,
577    comment_marker,
578    prefix_list,
579    func_dict,
580    func_name,
581    global_vars_seen_dict,
582    is_filtered,
583):
584    # Label format is based on ASM string.
585    check_label_format = "{} %s-LABEL: %s%s%s%s".format(comment_marker)
586    return common.add_checks(
587        output_lines,
588        comment_marker,
589        prefix_list,
590        func_dict,
591        func_name,
592        check_label_format,
593        True,
594        False,
595        1,
596        global_vars_seen_dict,
597        is_filtered=is_filtered,
598    )
599