Lokasi ngalangkungan proxy:   [ UP ]  
[Ngawartoskeun bug]   [Panyetelan cookie]                
Skip to content

Commit 19ac6f8

Browse files
author
Zachary Turner
committed
[lit] Improve tool substitution in lit.
This addresses two sources of inconsistency in test configuration files. 1. Substitution boundaries. Previously you would specify a substitution, such as 'lli', and then additionally a set of characters that should fail to match before and after the tool. This was used, for example, so that matches that are parts of full paths would not be replaced. But not all tools did this, and those that did would often re-invent the set of characters themselves, leading to inconsistency. Now, every tool substitution defaults to using a sane set of reasonable defaults and you have to explicitly opt out of it. This actually fixed a few latent bugs that were never being surfaced, but only on accident. 2. There was no standard way for the system to decide how to locate a tool. Sometimes you have an explicit path, sometimes we would search for it and build up a path ourselves, and sometimes we would build up a full command line. Furthermore, there was no standardized way to handle missing tools. Do we warn, fail, ignore, etc? All of this is now encapsulated in the ToolSubst class. You either specify an exact command to run, or an instance of FindTool('<tool-name>') and everything else just works. Furthermore, you can specify an action to take if the tool cannot be resolved. Differential Revision: https://reviews.llvm.org/D38565 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@315085 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent e959bd0 commit 19ac6f8

5 files changed

Lines changed: 232 additions & 141 deletions

File tree

test/lit.cfg.py

Lines changed: 52 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
import lit.util
1212
import lit.formats
1313
from lit.llvm import llvm_config
14-
from lit.llvm import ToolFilter
14+
from lit.llvm.subst import FindTool
15+
from lit.llvm.subst import ToolSubst
1516

1617
# name: The name of this test suite.
1718
config.name = 'LLVM'
@@ -82,31 +83,30 @@ def get_asan_rtlib():
8283
return found_dylibs[0]
8384

8485

85-
lli = 'lli'
86+
llvm_config.use_default_substitutions()
87+
88+
# Add site-specific substitutions.
89+
config.substitutions.append(('%llvmshlibdir', config.llvm_shlib_dir))
90+
config.substitutions.append(('%shlibext', config.llvm_shlib_ext))
91+
config.substitutions.append(('%exeext', config.llvm_exe_ext))
92+
config.substitutions.append(('%host_cc', config.host_cc))
93+
94+
95+
lli_args = []
8696
# The target triple used by default by lli is the process target triple (some
8797
# triple appropriate for generating code for the current process) but because
8898
# we don't support COFF in MCJIT well enough for the tests, force ELF format on
8999
# Windows. FIXME: the process target triple should be used here, but this is
90100
# difficult to obtain on Windows.
91101
if re.search(r'cygwin|mingw32|windows-gnu|windows-msvc|win32', config.host_triple):
92-
lli += ' -mtriple=' + config.host_triple + '-elf'
93-
config.substitutions.append(('%lli', lli))
102+
lli_args = ['-mtriple=' + config.host_triple + '-elf']
103+
104+
llc_args = []
94105

95106
# Similarly, have a macro to use llc with DWARF even when the host is win32.
96-
llc_dwarf = 'llc'
97107
if re.search(r'win32', config.target_triple):
98-
llc_dwarf += ' -mtriple=' + \
99-
config.target_triple.replace('-win32', '-mingw32')
100-
config.substitutions.append(('%llc_dwarf', llc_dwarf))
101-
102-
# Add site-specific substitutions.
103-
config.substitutions.append(('%gold', config.gold_executable))
104-
config.substitutions.append(('%go', config.go_executable))
105-
config.substitutions.append(('%llvmshlibdir', config.llvm_shlib_dir))
106-
config.substitutions.append(('%shlibext', config.llvm_shlib_ext))
107-
config.substitutions.append(('%exeext', config.llvm_exe_ext))
108-
config.substitutions.append(('%python', config.python_executable))
109-
config.substitutions.append(('%host_cc', config.host_cc))
108+
llc_args = [' -mtriple=' +
109+
config.target_triple.replace('-win32', '-mingw32')]
110110

111111
# Provide the path to asan runtime lib if available. On darwin, this lib needs
112112
# to be loaded via DYLD_INSERT_LIBRARIES before libLTO.dylib in case the files
@@ -115,65 +115,50 @@ def get_asan_rtlib():
115115
asan_rtlib = get_asan_rtlib()
116116
if asan_rtlib:
117117
ld64_cmd = 'DYLD_INSERT_LIBRARIES={} {}'.format(asan_rtlib, ld64_cmd)
118-
config.substitutions.append(('%ld64', ld64_cmd))
119118

120-
# OCaml substitutions.
121-
# Support tests for both native and bytecode builds.
122-
config.substitutions.append(('%ocamlc',
123-
'%s ocamlc -cclib -L%s %s' %
124-
(config.ocamlfind_executable, config.llvm_lib_dir, config.ocaml_flags)))
119+
ocamlc_command = '%s ocamlc -cclib -L%s %s' % (
120+
config.ocamlfind_executable, config.llvm_lib_dir, config.ocaml_flags)
121+
ocamlopt_command = 'true'
125122
if config.have_ocamlopt:
126-
config.substitutions.append(('%ocamlopt',
127-
'%s ocamlopt -cclib -L%s -cclib -Wl,-rpath,%s %s' %
128-
(config.ocamlfind_executable, config.llvm_lib_dir, config.llvm_lib_dir, config.ocaml_flags)))
129-
else:
130-
config.substitutions.append(('%ocamlopt', 'true'))
131-
132-
# For each occurrence of an llvm tool name as its own word, replace it
133-
# with the full path to the build directory holding that tool. This
134-
# ensures that we are testing the tools just built and not some random
135-
# tools that might happen to be in the user's PATH. Thus this list
136-
# includes every tool placed in $(LLVM_OBJ_ROOT)/$(BuildMode)/bin
137-
# (llvm_tools_dir in lit parlance).
138-
139-
# Avoid matching RUN line fragments that are actually part of
140-
# path names or options or whatever.
141-
# The regex is a pre-assertion to avoid matching a preceding
142-
# dot, hyphen, carat, or slash (.foo, -foo, etc.). Some patterns
143-
# also have a post-assertion to not match a trailing hyphen (foo-).
144-
JUNKCHARS = r".-^/<"
145-
146-
required_tools = [
147-
'lli', 'llvm-ar', 'llvm-as', 'llvm-bcanalyzer', 'llvm-config', 'llvm-cov',
123+
ocamlopt_command = '%s ocamlopt -cclib -L%s -cclib -Wl,-rpath,%s %s' % (
124+
config.ocamlfind_executable, config.llvm_lib_dir, config.llvm_lib_dir, config.ocaml_flags)
125+
126+
127+
tools = [
128+
ToolSubst('%lli', FindTool('lli'), post='.', extra_args=lli_args),
129+
ToolSubst('%llc_dwarf', FindTool('llc'), extra_args=llc_args),
130+
ToolSubst('%go', config.go_executable, unresolved='ignore'),
131+
ToolSubst('%gold', config.gold_executable, unresolved='ignore'),
132+
ToolSubst('%ld64', ld64_cmd, unresolved='ignore'),
133+
ToolSubst('%ocamlc', ocamlc_command, unresolved='ignore'),
134+
ToolSubst('%ocamlopt', ocamlopt_command, unresolved='ignore'),
135+
]
136+
137+
# FIXME: Why do we have both `lli` and `%lli` that do slightly different things?
138+
tools.extend([
139+
'lli', 'lli-child-target', 'llvm-ar', 'llvm-as', 'llvm-bcanalyzer', 'llvm-config', 'llvm-cov',
148140
'llvm-cxxdump', 'llvm-cvtres', 'llvm-diff', 'llvm-dis', 'llvm-dsymutil',
149141
'llvm-dwarfdump', 'llvm-extract', 'llvm-isel-fuzzer', 'llvm-lib',
150142
'llvm-link', 'llvm-lto', 'llvm-lto2', 'llvm-mc', 'llvm-mcmarkup',
151143
'llvm-modextract', 'llvm-nm', 'llvm-objcopy', 'llvm-objdump',
152144
'llvm-pdbutil', 'llvm-profdata', 'llvm-ranlib', 'llvm-readobj',
153145
'llvm-rtdyld', 'llvm-size', 'llvm-split', 'llvm-strings', 'llvm-tblgen',
154146
'llvm-c-test', 'llvm-cxxfilt', 'llvm-xray', 'yaml2obj', 'obj2yaml',
155-
'FileCheck', 'yaml-bench', 'verify-uselistorder',
156-
ToolFilter('bugpoint', post='-'),
157-
ToolFilter('llc', pre=JUNKCHARS),
158-
ToolFilter('llvm-symbolizer', pre=JUNKCHARS),
159-
ToolFilter('opt', JUNKCHARS),
160-
ToolFilter('sancov', pre=JUNKCHARS),
161-
ToolFilter('sanstats', pre=JUNKCHARS),
162-
# Handle these specially as they are strings searched for during testing.
163-
ToolFilter(r'\| \bcount\b', verbatim=True),
164-
ToolFilter(r'\| \bnot\b', verbatim=True)]
165-
166-
llvm_config.add_tool_substitutions(required_tools, config.llvm_tools_dir)
167-
168-
# For tools that are optional depending on the config, we won't warn
169-
# if they're missing.
170-
171-
optional_tools = [
172-
'llvm-go', 'llvm-mt', 'Kaleidoscope-Ch3', 'Kaleidoscope-Ch4',
173-
'Kaleidoscope-Ch5', 'Kaleidoscope-Ch6', 'Kaleidoscope-Ch7',
174-
'Kaleidoscope-Ch8']
175-
llvm_config.add_tool_substitutions(optional_tools, config.llvm_tools_dir,
176-
warn_missing=False)
147+
'yaml-bench', 'verify-uselistorder',
148+
'bugpoint', 'llc', 'llvm-symbolizer', 'opt', 'sancov', 'sanstats'])
149+
150+
# The following tools are optional
151+
tools.extend([
152+
ToolSubst('llvm-go', unresolved='ignore'),
153+
ToolSubst('llvm-mt', unresolved='ignore'),
154+
ToolSubst('Kaleidoscope-Ch3', unresolved='ignore'),
155+
ToolSubst('Kaleidoscope-Ch4', unresolved='ignore'),
156+
ToolSubst('Kaleidoscope-Ch5', unresolved='ignore'),
157+
ToolSubst('Kaleidoscope-Ch6', unresolved='ignore'),
158+
ToolSubst('Kaleidoscope-Ch7', unresolved='ignore'),
159+
ToolSubst('Kaleidoscope-Ch8', unresolved='ignore')])
160+
161+
llvm_config.add_tool_substitutions(tools, config.llvm_tools_dir)
177162

178163
# Targets
179164

utils/lit/lit/llvm/__init__.py

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,9 @@
11
from lit.llvm import config
2-
import lit.util
3-
import re
42

53
llvm_config = None
64

7-
class ToolFilter(object):
8-
"""
9-
String-like class used to build regex substitution patterns for
10-
llvm tools. Handles things like adding word-boundary patterns,
11-
and filtering characters from the beginning an end of a tool name
12-
"""
13-
14-
def __init__(self, name, pre=None, post=None, verbatim=False):
15-
"""
16-
Construct a ToolFilter.
17-
18-
name: the literal name of the substitution to look for.
19-
20-
pre: If specified, the substitution will not find matches where
21-
the character immediately preceding the word-boundary that begins
22-
`name` is any of the characters in the string `pre`.
23-
24-
post: If specified, the substitution will not find matches where
25-
the character immediately after the word-boundary that ends `name`
26-
is any of the characters specified in the string `post`.
27-
28-
verbatim: If True, `name` is an exact regex that is passed to the
29-
underlying substitution
30-
"""
31-
if verbatim:
32-
self.regex = name
33-
return
34-
35-
def not_in(chars, where=''):
36-
if not chars:
37-
return ''
38-
pattern_str = '|'.join(re.escape(x) for x in chars)
39-
return r'(?{}!({}))'.format(where, pattern_str)
40-
41-
self.regex = not_in(pre, '<') + r'\b' + name + r'\b' + not_in(post)
42-
43-
def __str__(self):
44-
return self.regex
45-
465

476
def initialize(lit_config, test_config):
487
global llvm_config
498

509
llvm_config = config.LLVMConfig(lit_config, test_config)
51-

utils/lit/lit/llvm/config.py

Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import sys
66

77
import lit.util
8+
from lit.llvm.subst import FindTool
9+
from lit.llvm.subst import ToolSubst
810

911

1012
def binary_feature(on, feature, off_prefix):
@@ -225,41 +227,47 @@ def make_msabi_triple(self, triple):
225227
# -win32 is not supported for non-x86 targets; use a default.
226228
return 'i686-pc-win32'
227229

228-
def add_tool_substitutions(self, tools, search_dirs, warn_missing=True):
230+
def add_tool_substitutions(self, tools, search_dirs=None):
231+
if not search_dirs:
232+
search_dirs = [self.config.llvm_tools_dir]
233+
229234
if lit.util.is_string(search_dirs):
230235
search_dirs = [search_dirs]
231236

237+
tools = [x if isinstance(x, ToolSubst) else ToolSubst(x)
238+
for x in tools]
239+
232240
search_dirs = os.pathsep.join(search_dirs)
241+
substitutions = []
242+
233243
for tool in tools:
234-
# Extract the tool name from the pattern. This relies on the tool
235-
# name being surrounded by \b word match operators. If the
236-
# pattern starts with "| ", include it in the string to be
237-
# substituted.
238-
if lit.util.is_string(tool):
239-
tool = lit.util.make_word_regex(tool)
240-
else:
241-
tool = str(tool)
244+
match = tool.resolve(self, search_dirs)
242245

243-
tool_match = re.match(r"^(\\)?((\| )?)\W+b([0-9A-Za-z-_\.]+)\\b\W*$",
244-
tool)
245-
if not tool_match:
246+
# Either no match occurred, or there was an unresolved match that
247+
# is ignored.
248+
if not match:
246249
continue
247250

248-
tool_pipe = tool_match.group(2)
249-
tool_name = tool_match.group(4)
250-
tool_path = lit.util.which(tool_name, search_dirs)
251-
if not tool_path:
252-
if warn_missing:
253-
# Warn, but still provide a substitution.
254-
self.lit_config.note(
255-
'Did not find ' + tool_name + ' in %s' % search_dirs)
256-
tool_path = self.config.llvm_tools_dir + '/' + tool_name
257-
258-
if tool_name == 'llc' and os.environ.get('LLVM_ENABLE_MACHINE_VERIFIER') == '1':
259-
tool_path += ' -verify-machineinstrs'
260-
if tool_name == 'llvm-go':
261-
exe = getattr(self.config, 'go_executable', None)
262-
if exe:
263-
tool_path += ' go=' + exe
264-
265-
self.config.substitutions.append((tool, tool_pipe + tool_path))
251+
subst_key, tool_pipe, command = match
252+
253+
# An unresolved match occurred that can't be ignored. Fail without
254+
# adding any of the previously-discovered substitutions.
255+
if not command:
256+
return False
257+
258+
substitutions.append((subst_key, tool_pipe + command))
259+
260+
self.config.substitutions.extend(substitutions)
261+
return True
262+
263+
def use_default_substitutions(self):
264+
tool_patterns = [
265+
ToolSubst('FileCheck', unresolved='fatal'),
266+
# Handle these specially as they are strings searched for during testing.
267+
ToolSubst(r'\| \bcount\b', command=FindTool(
268+
'count'), verbatim=True, unresolved='fatal'),
269+
ToolSubst(r'\| \bnot\b', command=FindTool('not'), verbatim=True, unresolved='fatal')]
270+
271+
self.config.substitutions.append(('%python', sys.executable))
272+
self.add_tool_substitutions(
273+
tool_patterns, [self.config.llvm_tools_dir])

0 commit comments

Comments
 (0)