blob: 923efd5bbef4eee2f2495555f0a93354e87032da [file] [log] [blame]
Fangrui Song6ceb7d82018-01-30 00:40:05 +00001import re
Fangrui Song19c9b1c2018-02-10 05:01:33 +00002import sys
Fangrui Song6ceb7d82018-01-30 00:40:05 +00003
4from . import common
5
Fangrui Song19c9b1c2018-02-10 05:01:33 +00006if sys.version_info[0] > 2:
7 class string:
8 expandtabs = str.expandtabs
9else:
10 import string
11
Fangrui Song6ceb7d82018-01-30 00:40:05 +000012# RegEx: this is where the magic happens.
13
Fangrui Song19c9b1c2018-02-10 05:01:33 +000014##### Assembly parser
15
Fangrui Song6ceb7d82018-01-30 00:40:05 +000016ASM_FUNCTION_X86_RE = re.compile(
Chandler Carruth0bc0c532018-07-13 10:29:23 +000017 r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@(?P=func)\n(?:\s*.Lfunc_begin[^:\n]*:\n)?[^:]*?'
Fangrui Song6ceb7d82018-01-30 00:40:05 +000018 r'(?P<body>^##?[ \t]+[^:]+:.*?)\s*'
19 r'^\s*(?:[^:\n]+?:\s*\n\s*\.size|\.cfi_endproc|\.globl|\.comm|\.(?:sub)?section|#+ -- End function)',
20 flags=(re.M | re.S))
21
22ASM_FUNCTION_ARM_RE = re.compile(
23 r'^(?P<func>[0-9a-zA-Z_]+):\n' # f: (name of function)
24 r'\s+\.fnstart\n' # .fnstart
25 r'(?P<body>.*?)\n' # (body of the function)
26 r'.Lfunc_end[0-9]+:', # .Lfunc_end0: or # -- End function
27 flags=(re.M | re.S))
28
29ASM_FUNCTION_AARCH64_RE = re.compile(
30 r'^_?(?P<func>[^:]+):[ \t]*\/\/[ \t]*@(?P=func)\n'
Sanjay Patelfba895e2018-04-20 17:16:23 +000031 r'(?:[ \t]+.cfi_startproc\n)?' # drop optional cfi noise
Fangrui Song6ceb7d82018-01-30 00:40:05 +000032 r'(?P<body>.*?)\n'
33 # This list is incomplete
34 r'.Lfunc_end[0-9]+:\n',
35 flags=(re.M | re.S))
36
Roman Lebedevc71ad5d2018-06-11 09:20:21 +000037ASM_FUNCTION_AMDGPU_RE = re.compile(
38 r'^_?(?P<func>[^:]+):[ \t]*;+[ \t]*@(?P=func)\n[^:]*?'
39 r'(?P<body>.*?)\n' # (body of the function)
40 # This list is incomplete
41 r'.Lfunc_end[0-9]+:\n',
42 flags=(re.M | re.S))
43
Fangrui Song6ceb7d82018-01-30 00:40:05 +000044ASM_FUNCTION_MIPS_RE = re.compile(
45 r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@(?P=func)\n[^:]*?' # f: (name of func)
46 r'(?:^[ \t]+\.(frame|f?mask|set).*?\n)+' # Mips+LLVM standard asm prologue
47 r'(?P<body>.*?)\n' # (body of the function)
48 r'(?:^[ \t]+\.(set|end).*?\n)+' # Mips+LLVM standard asm epilogue
49 r'(\$|\.L)func_end[0-9]+:\n', # $func_end0: (mips32 - O32) or
50 # .Lfunc_end0: (mips64 - NewABI)
51 flags=(re.M | re.S))
52
53ASM_FUNCTION_PPC_RE = re.compile(
54 r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@(?P=func)\n'
Nemanja Ivanovic3dfd21e2018-10-26 03:30:28 +000055 r'.*?'
Fangrui Song6ceb7d82018-01-30 00:40:05 +000056 r'\.Lfunc_begin[0-9]+:\n'
57 r'(?:[ \t]+.cfi_startproc\n)?'
58 r'(?:\.Lfunc_[gl]ep[0-9]+:\n(?:[ \t]+.*?\n)*)*'
59 r'(?P<body>.*?)\n'
60 # This list is incomplete
61 r'(?:^[ \t]*(?:\.long[ \t]+[^\n]+|\.quad[ \t]+[^\n]+)\n)*'
62 r'.Lfunc_end[0-9]+:\n',
63 flags=(re.M | re.S))
64
65ASM_FUNCTION_RISCV_RE = re.compile(
66 r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@(?P=func)\n[^:]*?'
67 r'(?P<body>^##?[ \t]+[^:]+:.*?)\s*'
68 r'.Lfunc_end[0-9]+:\n',
69 flags=(re.M | re.S))
70
Daniel Cederman63faaa52018-04-20 07:59:13 +000071ASM_FUNCTION_SPARC_RE = re.compile(
72 r'^_?(?P<func>[^:]+):[ \t]*!+[ \t]*@(?P=func)\n'
73 r'(?P<body>.*?)\s*'
74 r'.Lfunc_end[0-9]+:\n',
75 flags=(re.M | re.S))
76
Fangrui Song6ceb7d82018-01-30 00:40:05 +000077ASM_FUNCTION_SYSTEMZ_RE = re.compile(
78 r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@(?P=func)\n'
79 r'[ \t]+.cfi_startproc\n'
80 r'(?P<body>.*?)\n'
81 r'.Lfunc_end[0-9]+:\n',
82 flags=(re.M | re.S))
83
84
85SCRUB_LOOP_COMMENT_RE = re.compile(
86 r'# =>This Inner Loop Header:.*|# in Loop:.*', flags=re.M)
87
88SCRUB_X86_SHUFFLES_RE = (
89 re.compile(
90 r'^(\s*\w+) [^#\n]+#+ ((?:[xyz]mm\d+|mem)( \{%k\d+\}( \{z\})?)? = .*)$',
91 flags=re.M))
Chandler Carruth6f461782018-04-03 09:57:05 +000092SCRUB_X86_SPILL_RELOAD_RE = (
93 re.compile(
94 r'-?\d+\(%([er])[sb]p\)(.*(?:Spill|Reload))$',
95 flags=re.M))
Fangrui Song6ceb7d82018-01-30 00:40:05 +000096SCRUB_X86_SP_RE = re.compile(r'\d+\(%(esp|rsp)\)')
97SCRUB_X86_RIP_RE = re.compile(r'[.\w]+\(%rip\)')
98SCRUB_X86_LCP_RE = re.compile(r'\.LCPI[0-9]+_[0-9]+')
99SCRUB_X86_RET_RE = re.compile(r'ret[l|q]')
100
101def scrub_asm_x86(asm, args):
102 # Scrub runs of whitespace out of the assembly, but leave the leading
103 # whitespace in place.
104 asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm)
105 # Expand the tabs used for indentation.
106 asm = string.expandtabs(asm, 2)
107 # Detect shuffle asm comments and hide the operands in favor of the comments.
108 asm = SCRUB_X86_SHUFFLES_RE.sub(r'\1 {{.*#+}} \2', asm)
Chandler Carruth6f461782018-04-03 09:57:05 +0000109 # Detect stack spills and reloads and hide their exact offset and whether
110 # they used the stack pointer or frame pointer.
Chandler Carruth7e78daa2018-04-03 10:28:56 +0000111 asm = SCRUB_X86_SPILL_RELOAD_RE.sub(r'{{[-0-9]+}}(%\1{{[sb]}}p)\2', asm)
Fangrui Song6ceb7d82018-01-30 00:40:05 +0000112 # Generically match the stack offset of a memory operand.
113 asm = SCRUB_X86_SP_RE.sub(r'{{[0-9]+}}(%\1)', asm)
Reid Klecknerd3db9452018-07-23 21:14:35 +0000114 if getattr(args, 'x86_scrub_rip', False):
115 # Generically match a RIP-relative memory operand.
116 asm = SCRUB_X86_RIP_RE.sub(r'{{.*}}(%rip)', asm)
Fangrui Song6ceb7d82018-01-30 00:40:05 +0000117 # Generically match a LCP symbol.
118 asm = SCRUB_X86_LCP_RE.sub(r'{{\.LCPI.*}}', asm)
Simon Pilgrimd0ebabd2018-06-01 13:37:01 +0000119 if getattr(args, 'extra_scrub', False):
Fangrui Song6ceb7d82018-01-30 00:40:05 +0000120 # Avoid generating different checks for 32- and 64-bit because of 'retl' vs 'retq'.
121 asm = SCRUB_X86_RET_RE.sub(r'ret{{[l|q]}}', asm)
122 # Strip kill operands inserted into the asm.
123 asm = common.SCRUB_KILL_COMMENT_RE.sub('', asm)
124 # Strip trailing whitespace.
125 asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
126 return asm
127
Roman Lebedevc71ad5d2018-06-11 09:20:21 +0000128def scrub_asm_amdgpu(asm, args):
129 # Scrub runs of whitespace out of the assembly, but leave the leading
130 # whitespace in place.
131 asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm)
132 # Expand the tabs used for indentation.
133 asm = string.expandtabs(asm, 2)
134 # Strip trailing whitespace.
135 asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
136 return asm
137
Fangrui Song6ceb7d82018-01-30 00:40:05 +0000138def scrub_asm_arm_eabi(asm, args):
139 # Scrub runs of whitespace out of the assembly, but leave the leading
140 # whitespace in place.
141 asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm)
142 # Expand the tabs used for indentation.
143 asm = string.expandtabs(asm, 2)
144 # Strip kill operands inserted into the asm.
145 asm = common.SCRUB_KILL_COMMENT_RE.sub('', asm)
146 # Strip trailing whitespace.
147 asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
148 return asm
149
150def scrub_asm_powerpc64(asm, args):
151 # Scrub runs of whitespace out of the assembly, but leave the leading
152 # whitespace in place.
153 asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm)
154 # Expand the tabs used for indentation.
155 asm = string.expandtabs(asm, 2)
156 # Stripe unimportant comments
157 asm = SCRUB_LOOP_COMMENT_RE.sub(r'', asm)
158 # Strip trailing whitespace.
159 asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
160 return asm
161
162def scrub_asm_mips(asm, args):
163 # Scrub runs of whitespace out of the assembly, but leave the leading
164 # whitespace in place.
165 asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm)
166 # Expand the tabs used for indentation.
167 asm = string.expandtabs(asm, 2)
168 # Strip trailing whitespace.
169 asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
170 return asm
171
172def scrub_asm_riscv(asm, args):
173 # Scrub runs of whitespace out of the assembly, but leave the leading
174 # whitespace in place.
175 asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm)
176 # Expand the tabs used for indentation.
177 asm = string.expandtabs(asm, 2)
178 # Strip trailing whitespace.
179 asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
180 return asm
181
Daniel Cederman63faaa52018-04-20 07:59:13 +0000182def scrub_asm_sparc(asm, args):
183 # Scrub runs of whitespace out of the assembly, but leave the leading
184 # whitespace in place.
185 asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm)
186 # Expand the tabs used for indentation.
187 asm = string.expandtabs(asm, 2)
188 # Strip trailing whitespace.
189 asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
190 return asm
191
Fangrui Song6ceb7d82018-01-30 00:40:05 +0000192def scrub_asm_systemz(asm, args):
193 # Scrub runs of whitespace out of the assembly, but leave the leading
194 # whitespace in place.
195 asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm)
196 # Expand the tabs used for indentation.
197 asm = string.expandtabs(asm, 2)
198 # Strip trailing whitespace.
199 asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
200 return asm
201
202
203def build_function_body_dictionary_for_triple(args, raw_tool_output, triple, prefixes, func_dict):
204 target_handlers = {
205 'x86_64': (scrub_asm_x86, ASM_FUNCTION_X86_RE),
206 'i686': (scrub_asm_x86, ASM_FUNCTION_X86_RE),
207 'x86': (scrub_asm_x86, ASM_FUNCTION_X86_RE),
208 'i386': (scrub_asm_x86, ASM_FUNCTION_X86_RE),
209 'aarch64': (scrub_asm_arm_eabi, ASM_FUNCTION_AARCH64_RE),
Roman Lebedevc71ad5d2018-06-11 09:20:21 +0000210 'r600': (scrub_asm_amdgpu, ASM_FUNCTION_AMDGPU_RE),
211 'amdgcn': (scrub_asm_amdgpu, ASM_FUNCTION_AMDGPU_RE),
Fangrui Song6ceb7d82018-01-30 00:40:05 +0000212 'arm-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
213 'thumb-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
214 'thumbv6': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
215 'thumbv6-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
216 'thumbv6t2': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
217 'thumbv6t2-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
218 'thumbv6m': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
219 'thumbv6m-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
220 'thumbv7': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
221 'thumbv7-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
222 'thumbv7m': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
223 'thumbv7m-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
224 'thumbv8-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
225 'thumbv8m.base': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
226 'thumbv8m.main': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
227 'armv6': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
228 'armv7': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
229 'armv7-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
230 'armeb-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
231 'armv7eb-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
232 'armv7eb': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
233 'mips': (scrub_asm_mips, ASM_FUNCTION_MIPS_RE),
234 'powerpc64': (scrub_asm_powerpc64, ASM_FUNCTION_PPC_RE),
235 'powerpc64le': (scrub_asm_powerpc64, ASM_FUNCTION_PPC_RE),
236 'riscv32': (scrub_asm_riscv, ASM_FUNCTION_RISCV_RE),
237 'riscv64': (scrub_asm_riscv, ASM_FUNCTION_RISCV_RE),
Daniel Cederman63faaa52018-04-20 07:59:13 +0000238 'sparc': (scrub_asm_sparc, ASM_FUNCTION_SPARC_RE),
239 'sparcv9': (scrub_asm_sparc, ASM_FUNCTION_SPARC_RE),
Fangrui Song6ceb7d82018-01-30 00:40:05 +0000240 's390x': (scrub_asm_systemz, ASM_FUNCTION_SYSTEMZ_RE),
241 }
242 handlers = None
243 for prefix, s in target_handlers.items():
244 if triple.startswith(prefix):
245 handlers = s
246 break
247 else:
248 raise KeyError('Triple %r is not supported' % (triple))
249
250 scrubber, function_re = handlers
251 common.build_function_body_dictionary(
252 function_re, scrubber, [args], raw_tool_output, prefixes,
253 func_dict, args.verbose)
Fangrui Song19c9b1c2018-02-10 05:01:33 +0000254
255##### Generator of assembly CHECK lines
256
Simon Pilgrima9e09242018-04-05 09:50:58 +0000257def add_asm_checks(output_lines, comment_marker, prefix_list, func_dict, func_name):
258 # Label format is based on ASM string.
259 check_label_format = '{} %s-LABEL: %s:'.format(comment_marker)
Simon Pilgrimd79c5392018-04-06 12:36:27 +0000260 common.add_checks(output_lines, comment_marker, prefix_list, func_dict, func_name, check_label_format, True, False)