xref: /llvm-project/llvm/test/lit.cfg.py (revision f76f534e8c81c01d7ee2c8ab36cb28b9542531ca)
1# -*- Python -*-
2
3# Configuration file for the 'lit' test runner.
4
5import os
6import sys
7import re
8import platform
9import subprocess
10
11import lit.util
12import lit.formats
13from lit.llvm import llvm_config
14from lit.llvm.subst import FindTool
15from lit.llvm.subst import ToolSubst
16
17# name: The name of this test suite.
18config.name = "LLVM"
19
20# testFormat: The test format to use to interpret tests.
21config.test_format = lit.formats.ShTest(not llvm_config.use_lit_shell)
22
23# suffixes: A list of file extensions to treat as test files. This is overriden
24# by individual lit.local.cfg files in the test subdirectories.
25config.suffixes = [".ll", ".c", ".test", ".txt", ".s", ".mir", ".yaml", ".spv"]
26
27# excludes: A list of directories to exclude from the testsuite. The 'Inputs'
28# subdirectories contain auxiliary inputs for various tests in their parent
29# directories.
30config.excludes = ["Inputs", "CMakeLists.txt", "README.txt", "LICENSE.txt"]
31
32# test_source_root: The root path where tests are located.
33config.test_source_root = os.path.dirname(__file__)
34
35# test_exec_root: The root path where tests should be run.
36config.test_exec_root = os.path.join(config.llvm_obj_root, "test")
37
38# Tweak the PATH to include the tools dir.
39llvm_config.with_environment("PATH", config.llvm_tools_dir, append_path=True)
40
41# Propagate some variables from the host environment.
42llvm_config.with_system_environment(["HOME", "INCLUDE", "LIB", "TMP", "TEMP"])
43
44
45# Set up OCAMLPATH to include newly built OCaml libraries.
46top_ocaml_lib = os.path.join(config.llvm_lib_dir, "ocaml")
47llvm_ocaml_lib = os.path.join(top_ocaml_lib, "llvm")
48
49llvm_config.with_system_environment("OCAMLPATH")
50llvm_config.with_environment("OCAMLPATH", top_ocaml_lib, append_path=True)
51llvm_config.with_environment("OCAMLPATH", llvm_ocaml_lib, append_path=True)
52
53llvm_config.with_system_environment("CAML_LD_LIBRARY_PATH")
54llvm_config.with_environment("CAML_LD_LIBRARY_PATH", llvm_ocaml_lib, append_path=True)
55
56# Set up OCAMLRUNPARAM to enable backtraces in OCaml tests.
57llvm_config.with_environment("OCAMLRUNPARAM", "b")
58
59# Provide the path to asan runtime lib 'libclang_rt.asan_osx_dynamic.dylib' if
60# available. This is darwin specific since it's currently only needed on darwin.
61
62
63def get_asan_rtlib():
64    if (
65        not "Address" in config.llvm_use_sanitizer
66        or not "Darwin" in config.host_os
67        or not "x86" in config.host_triple
68    ):
69        return ""
70    try:
71        import glob
72    except:
73        print("glob module not found, skipping get_asan_rtlib() lookup")
74        return ""
75    # The libclang_rt.asan_osx_dynamic.dylib path is obtained using the relative
76    # path from the host cc.
77    host_lib_dir = os.path.join(os.path.dirname(config.host_cc), "../lib")
78    asan_dylib_dir_pattern = (
79        host_lib_dir + "/clang/*/lib/darwin/libclang_rt.asan_osx_dynamic.dylib"
80    )
81    found_dylibs = glob.glob(asan_dylib_dir_pattern)
82    if len(found_dylibs) != 1:
83        return ""
84    return found_dylibs[0]
85
86
87llvm_config.use_default_substitutions()
88
89# Add site-specific substitutions.
90config.substitutions.append(("%llvmshlibdir", config.llvm_shlib_dir))
91config.substitutions.append(("%shlibext", config.llvm_shlib_ext))
92config.substitutions.append(("%pluginext", config.llvm_plugin_ext))
93config.substitutions.append(("%exeext", config.llvm_exe_ext))
94
95
96lli_args = []
97# The target triple used by default by lli is the process target triple (some
98# triple appropriate for generating code for the current process) but because
99# we don't support COFF in MCJIT well enough for the tests, force ELF format on
100# Windows.  FIXME: the process target triple should be used here, but this is
101# difficult to obtain on Windows.
102if re.search(r"cygwin|windows-gnu|windows-msvc", config.host_triple):
103    lli_args = ["-mtriple=" + config.host_triple + "-elf"]
104
105llc_args = []
106
107# Similarly, have a macro to use llc with DWARF even when the host is Windows
108if re.search(r"windows-msvc", config.target_triple):
109    llc_args = [" -mtriple=" + config.target_triple.replace("-msvc", "-gnu")]
110
111# Provide the path to asan runtime lib if available. On darwin, this lib needs
112# to be loaded via DYLD_INSERT_LIBRARIES before libLTO.dylib in case the files
113# to be linked contain instrumented sanitizer code.
114ld64_cmd = config.ld64_executable
115asan_rtlib = get_asan_rtlib()
116if asan_rtlib:
117    ld64_cmd = "DYLD_INSERT_LIBRARIES={} {}".format(asan_rtlib, ld64_cmd)
118if config.osx_sysroot:
119    ld64_cmd = "{} -syslibroot {}".format(ld64_cmd, config.osx_sysroot)
120
121ocamlc_command = "%s ocamlc -cclib -L%s %s" % (
122    config.ocamlfind_executable,
123    config.llvm_lib_dir,
124    config.ocaml_flags,
125)
126ocamlopt_command = "true"
127if config.have_ocamlopt:
128    ocamlopt_command = "%s ocamlopt -cclib -L%s -cclib -Wl,-rpath,%s %s" % (
129        config.ocamlfind_executable,
130        config.llvm_lib_dir,
131        config.llvm_lib_dir,
132        config.ocaml_flags,
133    )
134
135opt_viewer_cmd = "%s %s/tools/opt-viewer/opt-viewer.py" % (
136    sys.executable,
137    config.llvm_src_root,
138)
139
140llvm_original_di_preservation_cmd = os.path.join(
141    config.llvm_src_root, "utils", "llvm-original-di-preservation.py"
142)
143config.substitutions.append(
144    (
145        "%llvm-original-di-preservation",
146        "'%s' %s" % (config.python_executable, llvm_original_di_preservation_cmd),
147    )
148)
149
150llvm_locstats_tool = os.path.join(config.llvm_tools_dir, "llvm-locstats")
151config.substitutions.append(
152    ("%llvm-locstats", "'%s' %s" % (config.python_executable, llvm_locstats_tool))
153)
154config.llvm_locstats_used = os.path.exists(llvm_locstats_tool)
155
156tools = [
157    ToolSubst("%llvm", FindTool("llvm"), unresolved="ignore"),
158    ToolSubst("%lli", FindTool("lli"), post=".", extra_args=lli_args),
159    ToolSubst("%llc_dwarf", FindTool("llc"), extra_args=llc_args),
160    ToolSubst("%gold", config.gold_executable, unresolved="ignore"),
161    ToolSubst("%ld64", ld64_cmd, unresolved="ignore"),
162    ToolSubst("%ocamlc", ocamlc_command, unresolved="ignore"),
163    ToolSubst("%ocamlopt", ocamlopt_command, unresolved="ignore"),
164    ToolSubst("%opt-viewer", opt_viewer_cmd),
165    ToolSubst("%llvm-objcopy", FindTool("llvm-objcopy")),
166    ToolSubst("%llvm-strip", FindTool("llvm-strip")),
167    ToolSubst("%llvm-install-name-tool", FindTool("llvm-install-name-tool")),
168    ToolSubst("%llvm-bitcode-strip", FindTool("llvm-bitcode-strip")),
169    ToolSubst("%split-file", FindTool("split-file")),
170]
171
172# FIXME: Why do we have both `lli` and `%lli` that do slightly different things?
173tools.extend(
174    [
175        "dsymutil",
176        "lli",
177        "lli-child-target",
178        "llvm-ar",
179        "llvm-as",
180        "llvm-addr2line",
181        "llvm-bcanalyzer",
182        "llvm-bitcode-strip",
183        "llvm-cgdata",
184        "llvm-config",
185        "llvm-cov",
186        "llvm-ctxprof-util",
187        "llvm-cxxdump",
188        "llvm-cvtres",
189        "llvm-debuginfod-find",
190        "llvm-debuginfo-analyzer",
191        "llvm-diff",
192        "llvm-dis",
193        "llvm-dwarfdump",
194        "llvm-dwarfutil",
195        "llvm-dwp",
196        "llvm-dlltool",
197        "llvm-exegesis",
198        "llvm-extract",
199        "llvm-isel-fuzzer",
200        "llvm-ifs",
201        "llvm-install-name-tool",
202        "llvm-jitlink",
203        "llvm-opt-fuzzer",
204        "llvm-lib",
205        "llvm-link",
206        "llvm-lto",
207        "llvm-lto2",
208        "llvm-mc",
209        "llvm-mca",
210        "llvm-modextract",
211        "llvm-nm",
212        "llvm-objcopy",
213        "llvm-objdump",
214        "llvm-otool",
215        "llvm-pdbutil",
216        "llvm-profdata",
217        "llvm-profgen",
218        "llvm-ranlib",
219        "llvm-rc",
220        "llvm-readelf",
221        "llvm-readobj",
222        "llvm-rtdyld",
223        "llvm-sim",
224        "llvm-size",
225        "llvm-split",
226        "llvm-stress",
227        "llvm-strings",
228        "llvm-strip",
229        "llvm-tblgen",
230        "llvm-readtapi",
231        "llvm-undname",
232        "llvm-windres",
233        "llvm-c-test",
234        "llvm-cxxfilt",
235        "llvm-xray",
236        "yaml2obj",
237        "obj2yaml",
238        "yaml-bench",
239        "verify-uselistorder",
240        "bugpoint",
241        "llc",
242        "llvm-symbolizer",
243        "opt",
244        "sancov",
245        "sanstats",
246        "llvm-remarkutil",
247    ]
248)
249
250# The following tools are optional
251tools.extend(
252    [
253        ToolSubst("llvm-mt", unresolved="ignore"),
254        ToolSubst("llvm-debuginfod", unresolved="ignore"),
255        ToolSubst("Kaleidoscope-Ch3", unresolved="ignore"),
256        ToolSubst("Kaleidoscope-Ch4", unresolved="ignore"),
257        ToolSubst("Kaleidoscope-Ch5", unresolved="ignore"),
258        ToolSubst("Kaleidoscope-Ch6", unresolved="ignore"),
259        ToolSubst("Kaleidoscope-Ch7", unresolved="ignore"),
260        ToolSubst("Kaleidoscope-Ch8", unresolved="ignore"),
261        ToolSubst("LLJITWithThinLTOSummaries", unresolved="ignore"),
262        ToolSubst("LLJITWithRemoteDebugging", unresolved="ignore"),
263        ToolSubst("OrcV2CBindingsBasicUsage", unresolved="ignore"),
264        ToolSubst("OrcV2CBindingsAddObjectFile", unresolved="ignore"),
265        ToolSubst("OrcV2CBindingsRemovableCode", unresolved="ignore"),
266        ToolSubst("OrcV2CBindingsLazy", unresolved="ignore"),
267        ToolSubst("OrcV2CBindingsVeryLazy", unresolved="ignore"),
268        ToolSubst("dxil-dis", unresolved="ignore"),
269    ]
270)
271
272# Find (major, minor) version of ptxas
273def ptxas_version(ptxas):
274    ptxas_cmd = subprocess.Popen([ptxas, "--version"], stdout=subprocess.PIPE)
275    ptxas_out = ptxas_cmd.stdout.read().decode("ascii")
276    ptxas_cmd.wait()
277    match = re.search(r"release (\d+)\.(\d+)", ptxas_out)
278    if match:
279        return (int(match.group(1)), int(match.group(2)))
280    print("couldn't determine ptxas version")
281    return None
282
283
284# Enable %ptxas and %ptxas-verify tools.
285# %ptxas-verify defaults to sm_60 architecture. It can be overriden
286# by specifying required one, for instance: %ptxas-verify -arch=sm_80.
287def enable_ptxas(ptxas_executable):
288    version = ptxas_version(ptxas_executable)
289    if version:
290        # ptxas is supposed to be backward compatible with previous
291        # versions, so add a feature for every known version prior to
292        # the current one.
293        ptxas_known_versions = [
294            (9, 0),
295            (9, 1),
296            (9, 2),
297            (10, 0),
298            (10, 1),
299            (10, 2),
300            (11, 0),
301            (11, 1),
302            (11, 2),
303            (11, 3),
304            (11, 4),
305            (11, 5),
306            (11, 6),
307            (11, 7),
308            (11, 8),
309            (12, 0),
310            (12, 1),
311            (12, 2),
312            (12, 3),
313            (12, 4),
314            (12, 5),
315            (12, 6),
316            (12, 8),
317        ]
318
319        def version_int(ver):
320            return ver[0] * 100 + ver[1]
321
322        # ignore ptxas if its version is below the minimum supported
323        # version
324        min_version = ptxas_known_versions[0]
325        if version_int(version) < version_int(min_version):
326            print(
327                "Warning: ptxas version {}.{} is not supported".format(
328                    version[0], version[1]
329                )
330            )
331            return
332
333        for known_version in ptxas_known_versions:
334            if version_int(known_version) <= version_int(version):
335                major, minor = known_version
336                config.available_features.add("ptxas-{}.{}".format(major, minor))
337
338    config.available_features.add("ptxas")
339    tools.extend(
340        [
341            ToolSubst("%ptxas", ptxas_executable),
342            ToolSubst("%ptxas-verify", "{} -arch=sm_60 -c -".format(ptxas_executable)),
343        ]
344    )
345
346
347ptxas_executable = (
348    os.environ.get("LLVM_PTXAS_EXECUTABLE", None) or config.ptxas_executable
349)
350if ptxas_executable:
351    enable_ptxas(ptxas_executable)
352
353llvm_config.add_tool_substitutions(tools, config.llvm_tools_dir)
354
355# Targets
356
357config.targets = frozenset(config.targets_to_build.split())
358
359for arch in config.targets_to_build.split():
360    config.available_features.add(arch.lower() + "-registered-target")
361
362# Features
363known_arches = ["x86_64", "mips64", "ppc64", "aarch64"]
364if config.host_ldflags.find("-m32") < 0 and any(
365    config.llvm_host_triple.startswith(x) for x in known_arches
366):
367    config.available_features.add("llvm-64-bits")
368
369config.available_features.add("host-byteorder-" + sys.byteorder + "-endian")
370if config.target_triple:
371    if re.match(
372        r"(aarch64_be|arc|armeb|bpfeb|lanai|m68k|mips|mips64|powerpc|powerpc64|sparc|sparcv9|s390x|s390|tce|thumbeb)-.*",
373        config.target_triple,
374    ):
375        config.available_features.add("target-byteorder-big-endian")
376    else:
377        config.available_features.add("target-byteorder-little-endian")
378
379if sys.platform in ["win32"]:
380    # ExecutionEngine, no weak symbols in COFF.
381    config.available_features.add("uses_COFF")
382else:
383    # Others/can-execute.txt
384    config.available_features.add("can-execute")
385
386# Loadable module
387if config.has_plugins:
388    config.available_features.add("plugins")
389
390if config.build_examples:
391    config.available_features.add("examples")
392
393if config.linked_bye_extension:
394    config.substitutions.append(("%llvmcheckext", "CHECK-EXT"))
395    config.substitutions.append(("%loadbye", ""))
396    config.substitutions.append(("%loadnewpmbye", ""))
397else:
398    config.substitutions.append(("%llvmcheckext", "CHECK-NOEXT"))
399    config.substitutions.append(
400        (
401            "%loadbye",
402            "-load={}/Bye{}".format(config.llvm_shlib_dir, config.llvm_shlib_ext),
403        )
404    )
405    config.substitutions.append(
406        (
407            "%loadnewpmbye",
408            "-load-pass-plugin={}/Bye{}".format(
409                config.llvm_shlib_dir, config.llvm_shlib_ext
410            ),
411        )
412    )
413
414if config.linked_exampleirtransforms_extension:
415    config.substitutions.append(("%loadexampleirtransforms", ""))
416else:
417    config.substitutions.append(
418        (
419            "%loadexampleirtransforms",
420            "-load-pass-plugin={}/ExampleIRTransforms{}".format(
421                config.llvm_shlib_dir, config.llvm_shlib_ext
422            ),
423        )
424    )
425
426# Static libraries are not built if BUILD_SHARED_LIBS is ON.
427if not config.build_shared_libs and not config.link_llvm_dylib:
428    config.available_features.add("static-libs")
429
430if config.link_llvm_dylib:
431    config.available_features.add("llvm-dylib")
432    config.substitutions.append(
433        (
434            # libLLVM.so.19.0git
435            "%llvmdylib",
436            "{}/libLLVM{}.{}".format(
437                config.llvm_shlib_dir, config.llvm_shlib_ext, config.llvm_dylib_version
438            )
439        )
440    )
441
442if config.have_tf_aot:
443    config.available_features.add("have_tf_aot")
444
445if config.have_tflite:
446    config.available_features.add("have_tflite")
447
448if config.llvm_inliner_model_autogenerated:
449    config.available_features.add("llvm_inliner_model_autogenerated")
450
451if config.llvm_raevict_model_autogenerated:
452    config.available_features.add("llvm_raevict_model_autogenerated")
453
454
455def have_cxx_shared_library():
456    readobj_exe = lit.util.which("llvm-readobj", config.llvm_tools_dir)
457    if not readobj_exe:
458        print("llvm-readobj not found")
459        return False
460
461    try:
462        readobj_cmd = subprocess.Popen(
463            [readobj_exe, "--needed-libs", readobj_exe], stdout=subprocess.PIPE
464        )
465    except OSError:
466        print("could not exec llvm-readobj")
467        return False
468
469    readobj_out = readobj_cmd.stdout.read().decode("ascii")
470    readobj_cmd.wait()
471
472    regex = re.compile(r"(libc\+\+|libstdc\+\+|msvcp).*\.(so|dylib|dll)")
473    needed_libs = False
474    for line in readobj_out.splitlines():
475        if "NeededLibraries [" in line:
476            needed_libs = True
477        if "]" in line:
478            needed_libs = False
479        if needed_libs and regex.search(line.lower()):
480            return True
481    return False
482
483
484if have_cxx_shared_library():
485    config.available_features.add("cxx-shared-library")
486
487if config.libcxx_used:
488    config.available_features.add("libcxx-used")
489
490# LLVM can be configured with an empty default triple
491# Some tests are "generic" and require a valid default triple
492if config.target_triple:
493    config.available_features.add("default_triple")
494    # Direct object generation
495    if not config.target_triple.startswith(("nvptx", "xcore")):
496        config.available_features.add("object-emission")
497
498if config.have_llvm_driver:
499    config.available_features.add("llvm-driver")
500
501import subprocess
502
503
504def have_ld_plugin_support():
505    if not os.path.exists(
506        os.path.join(config.llvm_shlib_dir, "LLVMgold" + config.llvm_shlib_ext)
507    ):
508        return False
509
510    ld_cmd = subprocess.Popen(
511        [config.gold_executable, "--help"], stdout=subprocess.PIPE, env={"LANG": "C"}
512    )
513    ld_out = ld_cmd.stdout.read().decode()
514    ld_cmd.wait()
515
516    if not "-plugin" in ld_out:
517        return False
518
519    # check that the used emulations are supported.
520    emu_line = [l for l in ld_out.split("\n") if "supported emulations" in l]
521    if len(emu_line) != 1:
522        return False
523    emu_line = emu_line[0]
524    fields = emu_line.split(":")
525    if len(fields) != 3:
526        return False
527    emulations = fields[2].split()
528    if "elf_x86_64" not in emulations:
529        return False
530    if "elf32ppc" in emulations:
531        config.available_features.add("ld_emu_elf32ppc")
532
533    ld_version = subprocess.Popen(
534        [config.gold_executable, "--version"], stdout=subprocess.PIPE, env={"LANG": "C"}
535    )
536    if not "GNU gold" in ld_version.stdout.read().decode():
537        return False
538    ld_version.wait()
539
540    return True
541
542
543if have_ld_plugin_support():
544    config.available_features.add("ld_plugin")
545
546
547def have_ld64_plugin_support():
548    if not os.path.exists(
549        os.path.join(config.llvm_shlib_dir, "libLTO" + config.llvm_shlib_ext)
550    ):
551        return False
552
553    if config.ld64_executable == "":
554        return False
555
556    ld_cmd = subprocess.Popen([config.ld64_executable, "-v"], stderr=subprocess.PIPE)
557    ld_out = ld_cmd.stderr.read().decode()
558    ld_cmd.wait()
559
560    if "ld64" not in ld_out or "LTO" not in ld_out:
561        return False
562
563    return True
564
565
566if have_ld64_plugin_support():
567    config.available_features.add("ld64_plugin")
568
569# Ask llvm-config about asserts
570llvm_config.feature_config(
571    [
572        ("--assertion-mode", {"ON": "asserts"}),
573        ("--build-mode", {"[Dd][Ee][Bb][Uu][Gg]": "debug"}),
574    ]
575)
576
577if "darwin" == sys.platform:
578    cmd = ["sysctl", "hw.optional.fma"]
579    sysctl_cmd = subprocess.Popen(cmd, stdout=subprocess.PIPE)
580
581    # Non zero return, probably a permission issue
582    if sysctl_cmd.wait():
583        print(
584            'Warning: sysctl exists but calling "{}" failed, defaulting to no fma3.'.format(
585                " ".join(cmd)
586            )
587        )
588    else:
589        result = sysctl_cmd.stdout.read().decode("ascii")
590        if "hw.optional.fma: 1" in result:
591            config.available_features.add("fma3")
592
593if not hasattr(sys, "getwindowsversion") or sys.getwindowsversion().build >= 17063:
594    config.available_features.add("unix-sockets")
595
596# .debug_frame is not emitted for targeting Windows x64, aarch64/arm64, AIX, or Apple Silicon Mac.
597if not re.match(
598    r"^(x86_64|aarch64|arm64|powerpc|powerpc64).*-(windows-gnu|windows-msvc|aix)",
599    config.target_triple,
600) and not re.match(r"^arm64(e)?-apple-(macos|darwin)", config.target_triple):
601    config.available_features.add("debug_frame")
602
603if config.enable_backtrace:
604    config.available_features.add("backtrace")
605
606if config.enable_threads:
607    config.available_features.add("thread_support")
608
609if config.have_libxml2:
610    config.available_features.add("libxml2")
611
612if config.have_curl:
613    config.available_features.add("curl")
614
615if config.have_httplib:
616    config.available_features.add("httplib")
617
618if config.have_opt_viewer_modules:
619    config.available_features.add("have_opt_viewer_modules")
620
621if config.expensive_checks:
622    config.available_features.add("expensive_checks")
623
624if "MemoryWithOrigins" in config.llvm_use_sanitizer:
625    config.available_features.add("use_msan_with_origins")
626
627
628# Some tools support an environment variable "OBJECT_MODE" on AIX OS, which
629# controls the kind of objects they will support. If there is no "OBJECT_MODE"
630# environment variable specified, the default behaviour is to support 32-bit
631# objects only. In order to not affect most test cases, which expect to support
632# 32-bit and 64-bit objects by default, set the environment variable
633# "OBJECT_MODE" to 'any' by default on AIX OS.
634if "system-aix" in config.available_features:
635    config.environment["OBJECT_MODE"] = "any"
636
637if config.has_logf128:
638    config.available_features.add("has_logf128")
639