OSDN Git Service

0ece3e131f5a654cb48e9cfa5301b94eab7a29eb
[android-x86/external-llvm.git] / utils / UpdateTestChecks / asm.py
1 import re
2 import sys
3
4 from . import common
5
6 if sys.version_info[0] > 2:
7   class string:
8     expandtabs = str.expandtabs
9 else:
10   import string
11
12 # RegEx: this is where the magic happens.
13
14 ##### Assembly parser
15
16 ASM_FUNCTION_X86_RE = re.compile(
17     r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@(?P=func)\n[^:]*?'
18     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
22 ASM_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
29 ASM_FUNCTION_AARCH64_RE = re.compile(
30      r'^_?(?P<func>[^:]+):[ \t]*\/\/[ \t]*@(?P=func)\n'
31      r'(?:[ \t]+.cfi_startproc\n)?'  # drop optional cfi noise 
32      r'(?P<body>.*?)\n'
33      # This list is incomplete
34      r'.Lfunc_end[0-9]+:\n',
35      flags=(re.M | re.S))
36
37 ASM_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
44 ASM_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
53 ASM_FUNCTION_PPC_RE = re.compile(
54     r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@(?P=func)\n'
55     r'\.Lfunc_begin[0-9]+:\n'
56     r'(?:[ \t]+.cfi_startproc\n)?'
57     r'(?:\.Lfunc_[gl]ep[0-9]+:\n(?:[ \t]+.*?\n)*)*'
58     r'(?P<body>.*?)\n'
59     # This list is incomplete
60     r'(?:^[ \t]*(?:\.long[ \t]+[^\n]+|\.quad[ \t]+[^\n]+)\n)*'
61     r'.Lfunc_end[0-9]+:\n',
62     flags=(re.M | re.S))
63
64 ASM_FUNCTION_RISCV_RE = re.compile(
65     r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@(?P=func)\n[^:]*?'
66     r'(?P<body>^##?[ \t]+[^:]+:.*?)\s*'
67     r'.Lfunc_end[0-9]+:\n',
68     flags=(re.M | re.S))
69
70 ASM_FUNCTION_SPARC_RE = re.compile(
71     r'^_?(?P<func>[^:]+):[ \t]*!+[ \t]*@(?P=func)\n'
72     r'(?P<body>.*?)\s*'
73     r'.Lfunc_end[0-9]+:\n',
74     flags=(re.M | re.S))
75
76 ASM_FUNCTION_SYSTEMZ_RE = re.compile(
77     r'^_?(?P<func>[^:]+):[ \t]*#+[ \t]*@(?P=func)\n'
78     r'[ \t]+.cfi_startproc\n'
79     r'(?P<body>.*?)\n'
80     r'.Lfunc_end[0-9]+:\n',
81     flags=(re.M | re.S))
82
83
84 SCRUB_LOOP_COMMENT_RE = re.compile(
85     r'# =>This Inner Loop Header:.*|# in Loop:.*', flags=re.M)
86
87 SCRUB_X86_SHUFFLES_RE = (
88     re.compile(
89         r'^(\s*\w+) [^#\n]+#+ ((?:[xyz]mm\d+|mem)( \{%k\d+\}( \{z\})?)? = .*)$',
90         flags=re.M))
91 SCRUB_X86_SPILL_RELOAD_RE = (
92     re.compile(
93         r'-?\d+\(%([er])[sb]p\)(.*(?:Spill|Reload))$',
94         flags=re.M))
95 SCRUB_X86_SP_RE = re.compile(r'\d+\(%(esp|rsp)\)')
96 SCRUB_X86_RIP_RE = re.compile(r'[.\w]+\(%rip\)')
97 SCRUB_X86_LCP_RE = re.compile(r'\.LCPI[0-9]+_[0-9]+')
98 SCRUB_X86_RET_RE = re.compile(r'ret[l|q]')
99
100 def scrub_asm_x86(asm, args):
101   # Scrub runs of whitespace out of the assembly, but leave the leading
102   # whitespace in place.
103   asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm)
104   # Expand the tabs used for indentation.
105   asm = string.expandtabs(asm, 2)
106   # Detect shuffle asm comments and hide the operands in favor of the comments.
107   asm = SCRUB_X86_SHUFFLES_RE.sub(r'\1 {{.*#+}} \2', asm)
108   # Detect stack spills and reloads and hide their exact offset and whether
109   # they used the stack pointer or frame pointer.
110   asm = SCRUB_X86_SPILL_RELOAD_RE.sub(r'{{[-0-9]+}}(%\1{{[sb]}}p)\2', asm)
111   # Generically match the stack offset of a memory operand.
112   asm = SCRUB_X86_SP_RE.sub(r'{{[0-9]+}}(%\1)', asm)
113   if getattr(args, 'x86_scrub_rip', False):
114     # Generically match a RIP-relative memory operand.
115     asm = SCRUB_X86_RIP_RE.sub(r'{{.*}}(%rip)', asm)
116   # Generically match a LCP symbol.
117   asm = SCRUB_X86_LCP_RE.sub(r'{{\.LCPI.*}}', asm)
118   if getattr(args, 'extra_scrub', False):
119     # Avoid generating different checks for 32- and 64-bit because of 'retl' vs 'retq'.
120     asm = SCRUB_X86_RET_RE.sub(r'ret{{[l|q]}}', asm)
121   # Strip kill operands inserted into the asm.
122   asm = common.SCRUB_KILL_COMMENT_RE.sub('', asm)
123   # Strip trailing whitespace.
124   asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
125   return asm
126
127 def scrub_asm_amdgpu(asm, args):
128   # Scrub runs of whitespace out of the assembly, but leave the leading
129   # whitespace in place.
130   asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm)
131   # Expand the tabs used for indentation.
132   asm = string.expandtabs(asm, 2)
133   # Strip trailing whitespace.
134   asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
135   return asm
136
137 def scrub_asm_arm_eabi(asm, args):
138   # Scrub runs of whitespace out of the assembly, but leave the leading
139   # whitespace in place.
140   asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm)
141   # Expand the tabs used for indentation.
142   asm = string.expandtabs(asm, 2)
143   # Strip kill operands inserted into the asm.
144   asm = common.SCRUB_KILL_COMMENT_RE.sub('', asm)
145   # Strip trailing whitespace.
146   asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
147   return asm
148
149 def scrub_asm_powerpc64(asm, args):
150   # Scrub runs of whitespace out of the assembly, but leave the leading
151   # whitespace in place.
152   asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm)
153   # Expand the tabs used for indentation.
154   asm = string.expandtabs(asm, 2)
155   # Stripe unimportant comments
156   asm = SCRUB_LOOP_COMMENT_RE.sub(r'', asm)
157   # Strip trailing whitespace.
158   asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
159   return asm
160
161 def scrub_asm_mips(asm, args):
162   # Scrub runs of whitespace out of the assembly, but leave the leading
163   # whitespace in place.
164   asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm)
165   # Expand the tabs used for indentation.
166   asm = string.expandtabs(asm, 2)
167   # Strip trailing whitespace.
168   asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
169   return asm
170
171 def scrub_asm_riscv(asm, args):
172   # Scrub runs of whitespace out of the assembly, but leave the leading
173   # whitespace in place.
174   asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm)
175   # Expand the tabs used for indentation.
176   asm = string.expandtabs(asm, 2)
177   # Strip trailing whitespace.
178   asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
179   return asm
180
181 def scrub_asm_sparc(asm, args):
182   # Scrub runs of whitespace out of the assembly, but leave the leading
183   # whitespace in place.
184   asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm)
185   # Expand the tabs used for indentation.
186   asm = string.expandtabs(asm, 2)
187   # Strip trailing whitespace.
188   asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
189   return asm
190
191 def scrub_asm_systemz(asm, args):
192   # Scrub runs of whitespace out of the assembly, but leave the leading
193   # whitespace in place.
194   asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm)
195   # Expand the tabs used for indentation.
196   asm = string.expandtabs(asm, 2)
197   # Strip trailing whitespace.
198   asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm)
199   return asm
200
201
202 def build_function_body_dictionary_for_triple(args, raw_tool_output, triple, prefixes, func_dict):
203   target_handlers = {
204       'x86_64': (scrub_asm_x86, ASM_FUNCTION_X86_RE),
205       'i686': (scrub_asm_x86, ASM_FUNCTION_X86_RE),
206       'x86': (scrub_asm_x86, ASM_FUNCTION_X86_RE),
207       'i386': (scrub_asm_x86, ASM_FUNCTION_X86_RE),
208       'aarch64': (scrub_asm_arm_eabi, ASM_FUNCTION_AARCH64_RE),
209       'r600': (scrub_asm_amdgpu, ASM_FUNCTION_AMDGPU_RE),
210       'amdgcn': (scrub_asm_amdgpu, ASM_FUNCTION_AMDGPU_RE),
211       'arm-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
212       'thumb-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
213       'thumbv6': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
214       'thumbv6-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
215       'thumbv6t2': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
216       'thumbv6t2-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
217       'thumbv6m': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
218       'thumbv6m-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
219       'thumbv7': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
220       'thumbv7-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
221       'thumbv7m': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
222       'thumbv7m-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
223       'thumbv8-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
224       'thumbv8m.base': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
225       'thumbv8m.main': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
226       'armv6': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
227       'armv7': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
228       'armv7-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
229       'armeb-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
230       'armv7eb-eabi': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
231       'armv7eb': (scrub_asm_arm_eabi, ASM_FUNCTION_ARM_RE),
232       'mips': (scrub_asm_mips, ASM_FUNCTION_MIPS_RE),
233       'powerpc64': (scrub_asm_powerpc64, ASM_FUNCTION_PPC_RE),
234       'powerpc64le': (scrub_asm_powerpc64, ASM_FUNCTION_PPC_RE),
235       'riscv32': (scrub_asm_riscv, ASM_FUNCTION_RISCV_RE),
236       'riscv64': (scrub_asm_riscv, ASM_FUNCTION_RISCV_RE),
237       'sparc': (scrub_asm_sparc, ASM_FUNCTION_SPARC_RE),
238       'sparcv9': (scrub_asm_sparc, ASM_FUNCTION_SPARC_RE),
239       's390x': (scrub_asm_systemz, ASM_FUNCTION_SYSTEMZ_RE),
240   }
241   handlers = None
242   for prefix, s in target_handlers.items():
243     if triple.startswith(prefix):
244       handlers = s
245       break
246   else:
247     raise KeyError('Triple %r is not supported' % (triple))
248
249   scrubber, function_re = handlers
250   common.build_function_body_dictionary(
251           function_re, scrubber, [args], raw_tool_output, prefixes,
252           func_dict, args.verbose)
253
254 ##### Generator of assembly CHECK lines
255
256 def add_asm_checks(output_lines, comment_marker, prefix_list, func_dict, func_name):
257   # Label format is based on ASM string.
258   check_label_format = '{} %s-LABEL: %s:'.format(comment_marker)
259   common.add_checks(output_lines, comment_marker, prefix_list, func_dict, func_name, check_label_format, True, False)