| # -*- Python -*- | 
 |  | 
 | # Configuration file for the 'lit' test runner. | 
 |  | 
 | import os | 
 | import sys | 
 | import re | 
 | import platform | 
 | import subprocess | 
 |  | 
 | import lit.util | 
 | import lit.formats | 
 | from lit.llvm import llvm_config | 
 | from lit.llvm.subst import FindTool | 
 | from lit.llvm.subst import ToolSubst | 
 |  | 
 | # name: The name of this test suite. | 
 | config.name = "LLVM" | 
 |  | 
 | # testFormat: The test format to use to interpret tests. | 
 | config.test_format = lit.formats.ShTest(not llvm_config.use_lit_shell) | 
 |  | 
 | # suffixes: A list of file extensions to treat as test files. This is overriden | 
 | # by individual lit.local.cfg files in the test subdirectories. | 
 | config.suffixes = [".ll", ".c", ".test", ".txt", ".s", ".mir", ".yaml", ".spv"] | 
 |  | 
 | # excludes: A list of directories to exclude from the testsuite. The 'Inputs' | 
 | # subdirectories contain auxiliary inputs for various tests in their parent | 
 | # directories. | 
 | config.excludes = ["Inputs", "CMakeLists.txt", "README.txt", "LICENSE.txt"] | 
 |  | 
 | # test_source_root: The root path where tests are located. | 
 | config.test_source_root = os.path.dirname(__file__) | 
 |  | 
 | # test_exec_root: The root path where tests should be run. | 
 | config.test_exec_root = os.path.join(config.llvm_obj_root, "test") | 
 |  | 
 | # Tweak the PATH to include the tools dir. | 
 | llvm_config.with_environment("PATH", config.llvm_tools_dir, append_path=True) | 
 |  | 
 | # Propagate some variables from the host environment. | 
 | llvm_config.with_system_environment(["HOME", "INCLUDE", "LIB", "TMP", "TEMP"]) | 
 |  | 
 |  | 
 | # Set up OCAMLPATH to include newly built OCaml libraries. | 
 | top_ocaml_lib = os.path.join(config.llvm_lib_dir, "ocaml") | 
 | llvm_ocaml_lib = os.path.join(top_ocaml_lib, "llvm") | 
 |  | 
 | llvm_config.with_system_environment("OCAMLPATH") | 
 | llvm_config.with_environment("OCAMLPATH", top_ocaml_lib, append_path=True) | 
 | llvm_config.with_environment("OCAMLPATH", llvm_ocaml_lib, append_path=True) | 
 |  | 
 | llvm_config.with_system_environment("CAML_LD_LIBRARY_PATH") | 
 | llvm_config.with_environment("CAML_LD_LIBRARY_PATH", llvm_ocaml_lib, append_path=True) | 
 |  | 
 | # Set up OCAMLRUNPARAM to enable backtraces in OCaml tests. | 
 | llvm_config.with_environment("OCAMLRUNPARAM", "b") | 
 |  | 
 | # Provide the path to asan runtime lib 'libclang_rt.asan_osx_dynamic.dylib' if | 
 | # available. This is darwin specific since it's currently only needed on darwin. | 
 |  | 
 |  | 
 | def get_asan_rtlib(): | 
 |     if ( | 
 |         not "Address" in config.llvm_use_sanitizer | 
 |         or not "Darwin" in config.host_os | 
 |         or not "x86" in config.host_triple | 
 |     ): | 
 |         return "" | 
 |     try: | 
 |         import glob | 
 |     except: | 
 |         print("glob module not found, skipping get_asan_rtlib() lookup") | 
 |         return "" | 
 |     # The libclang_rt.asan_osx_dynamic.dylib path is obtained using the relative | 
 |     # path from the host cc. | 
 |     host_lib_dir = os.path.join(os.path.dirname(config.host_cc), "../lib") | 
 |     asan_dylib_dir_pattern = ( | 
 |         host_lib_dir + "/clang/*/lib/darwin/libclang_rt.asan_osx_dynamic.dylib" | 
 |     ) | 
 |     found_dylibs = glob.glob(asan_dylib_dir_pattern) | 
 |     if len(found_dylibs) != 1: | 
 |         return "" | 
 |     return found_dylibs[0] | 
 |  | 
 |  | 
 | llvm_config.use_default_substitutions() | 
 |  | 
 | # Add site-specific substitutions. | 
 | config.substitutions.append(("%llvmshlibdir", config.llvm_shlib_dir)) | 
 | config.substitutions.append(("%shlibext", config.llvm_shlib_ext)) | 
 | config.substitutions.append(("%pluginext", config.llvm_plugin_ext)) | 
 | config.substitutions.append(("%exeext", config.llvm_exe_ext)) | 
 |  | 
 |  | 
 | lli_args = [] | 
 | # The target triple used by default by lli is the process target triple (some | 
 | # triple appropriate for generating code for the current process) but because | 
 | # we don't support COFF in MCJIT well enough for the tests, force ELF format on | 
 | # Windows.  FIXME: the process target triple should be used here, but this is | 
 | # difficult to obtain on Windows. | 
 | if re.search(r"cygwin|windows-gnu|windows-msvc", config.host_triple): | 
 |     lli_args = ["-mtriple=" + config.host_triple + "-elf"] | 
 |  | 
 | llc_args = [] | 
 |  | 
 | # Similarly, have a macro to use llc with DWARF even when the host is Windows | 
 | if re.search(r"windows-msvc", config.target_triple): | 
 |     llc_args = [" -mtriple=" + config.target_triple.replace("-msvc", "-gnu")] | 
 |  | 
 | # Provide the path to asan runtime lib if available. On darwin, this lib needs | 
 | # to be loaded via DYLD_INSERT_LIBRARIES before libLTO.dylib in case the files | 
 | # to be linked contain instrumented sanitizer code. | 
 | ld64_cmd = config.ld64_executable | 
 | asan_rtlib = get_asan_rtlib() | 
 | if asan_rtlib: | 
 |     ld64_cmd = "DYLD_INSERT_LIBRARIES={} {}".format(asan_rtlib, ld64_cmd) | 
 | if config.osx_sysroot: | 
 |     ld64_cmd = "{} -syslibroot {}".format(ld64_cmd, config.osx_sysroot) | 
 |  | 
 | ocamlc_command = "%s ocamlc -cclib -L%s %s" % ( | 
 |     config.ocamlfind_executable, | 
 |     config.llvm_lib_dir, | 
 |     config.ocaml_flags, | 
 | ) | 
 | ocamlopt_command = "true" | 
 | if config.have_ocamlopt: | 
 |     ocamlopt_command = "%s ocamlopt -cclib -L%s -cclib -Wl,-rpath,%s %s" % ( | 
 |         config.ocamlfind_executable, | 
 |         config.llvm_lib_dir, | 
 |         config.llvm_lib_dir, | 
 |         config.ocaml_flags, | 
 |     ) | 
 |  | 
 | opt_viewer_cmd = "%s %s/tools/opt-viewer/opt-viewer.py" % ( | 
 |     sys.executable, | 
 |     config.llvm_src_root, | 
 | ) | 
 |  | 
 | llvm_original_di_preservation_cmd = os.path.join( | 
 |     config.llvm_src_root, "utils", "llvm-original-di-preservation.py" | 
 | ) | 
 | config.substitutions.append( | 
 |     ( | 
 |         "%llvm-original-di-preservation", | 
 |         "'%s' %s" % (config.python_executable, llvm_original_di_preservation_cmd), | 
 |     ) | 
 | ) | 
 |  | 
 | llvm_locstats_tool = os.path.join(config.llvm_tools_dir, "llvm-locstats") | 
 | config.substitutions.append( | 
 |     ("%llvm-locstats", "'%s' %s" % (config.python_executable, llvm_locstats_tool)) | 
 | ) | 
 | config.llvm_locstats_used = os.path.exists(llvm_locstats_tool) | 
 |  | 
 | tools = [ | 
 |     ToolSubst("%llvm", FindTool("llvm"), unresolved="ignore"), | 
 |     ToolSubst("%lli", FindTool("lli"), post=".", extra_args=lli_args), | 
 |     ToolSubst("%llc_dwarf", FindTool("llc"), extra_args=llc_args), | 
 |     ToolSubst("%gold", config.gold_executable, unresolved="ignore"), | 
 |     ToolSubst("%ld64", ld64_cmd, unresolved="ignore"), | 
 |     ToolSubst("%ocamlc", ocamlc_command, unresolved="ignore"), | 
 |     ToolSubst("%ocamlopt", ocamlopt_command, unresolved="ignore"), | 
 |     ToolSubst("%opt-viewer", opt_viewer_cmd), | 
 |     ToolSubst("%llvm-objcopy", FindTool("llvm-objcopy")), | 
 |     ToolSubst("%llvm-strip", FindTool("llvm-strip")), | 
 |     ToolSubst("%llvm-install-name-tool", FindTool("llvm-install-name-tool")), | 
 |     ToolSubst("%llvm-bitcode-strip", FindTool("llvm-bitcode-strip")), | 
 |     ToolSubst("%split-file", FindTool("split-file")), | 
 | ] | 
 |  | 
 | # FIXME: Why do we have both `lli` and `%lli` that do slightly different things? | 
 | tools.extend( | 
 |     [ | 
 |         "dsymutil", | 
 |         "lli", | 
 |         "lli-child-target", | 
 |         "llvm-ar", | 
 |         "llvm-as", | 
 |         "llvm-addr2line", | 
 |         "llvm-bcanalyzer", | 
 |         "llvm-bitcode-strip", | 
 |         "llvm-cgdata", | 
 |         "llvm-config", | 
 |         "llvm-cov", | 
 |         "llvm-ctxprof-util", | 
 |         "llvm-cxxdump", | 
 |         "llvm-cvtres", | 
 |         "llvm-debuginfod-find", | 
 |         "llvm-debuginfo-analyzer", | 
 |         "llvm-diff", | 
 |         "llvm-dis", | 
 |         "llvm-dwarfdump", | 
 |         "llvm-dwarfutil", | 
 |         "llvm-dwp", | 
 |         "llvm-dlltool", | 
 |         "llvm-exegesis", | 
 |         "llvm-extract", | 
 |         "llvm-isel-fuzzer", | 
 |         "llvm-ifs", | 
 |         "llvm-install-name-tool", | 
 |         "llvm-jitlink", | 
 |         "llvm-opt-fuzzer", | 
 |         "llvm-lib", | 
 |         "llvm-link", | 
 |         "llvm-lto", | 
 |         "llvm-lto2", | 
 |         "llvm-mc", | 
 |         "llvm-mca", | 
 |         "llvm-modextract", | 
 |         "llvm-nm", | 
 |         "llvm-objcopy", | 
 |         "llvm-objdump", | 
 |         "llvm-otool", | 
 |         "llvm-pdbutil", | 
 |         "llvm-profdata", | 
 |         "llvm-profgen", | 
 |         "llvm-ranlib", | 
 |         "llvm-rc", | 
 |         "llvm-readelf", | 
 |         "llvm-readobj", | 
 |         "llvm-rtdyld", | 
 |         "llvm-sim", | 
 |         "llvm-size", | 
 |         "llvm-split", | 
 |         "llvm-stress", | 
 |         "llvm-strings", | 
 |         "llvm-strip", | 
 |         "llvm-tblgen", | 
 |         "llvm-readtapi", | 
 |         "llvm-undname", | 
 |         "llvm-windres", | 
 |         "llvm-c-test", | 
 |         "llvm-cxxfilt", | 
 |         "llvm-xray", | 
 |         "yaml2obj", | 
 |         "obj2yaml", | 
 |         "yaml-bench", | 
 |         "verify-uselistorder", | 
 |         "bugpoint", | 
 |         "llc", | 
 |         "llvm-symbolizer", | 
 |         "opt", | 
 |         "sancov", | 
 |         "sanstats", | 
 |         "llvm-remarkutil", | 
 |     ] | 
 | ) | 
 |  | 
 | # The following tools are optional | 
 | tools.extend( | 
 |     [ | 
 |         ToolSubst("llvm-mt", unresolved="ignore"), | 
 |         ToolSubst("llvm-debuginfod", unresolved="ignore"), | 
 |         ToolSubst("Kaleidoscope-Ch3", unresolved="ignore"), | 
 |         ToolSubst("Kaleidoscope-Ch4", unresolved="ignore"), | 
 |         ToolSubst("Kaleidoscope-Ch5", unresolved="ignore"), | 
 |         ToolSubst("Kaleidoscope-Ch6", unresolved="ignore"), | 
 |         ToolSubst("Kaleidoscope-Ch7", unresolved="ignore"), | 
 |         ToolSubst("Kaleidoscope-Ch8", unresolved="ignore"), | 
 |         ToolSubst("LLJITWithThinLTOSummaries", unresolved="ignore"), | 
 |         ToolSubst("LLJITWithRemoteDebugging", unresolved="ignore"), | 
 |         ToolSubst("OrcV2CBindingsBasicUsage", unresolved="ignore"), | 
 |         ToolSubst("OrcV2CBindingsAddObjectFile", unresolved="ignore"), | 
 |         ToolSubst("OrcV2CBindingsRemovableCode", unresolved="ignore"), | 
 |         ToolSubst("OrcV2CBindingsLazy", unresolved="ignore"), | 
 |         ToolSubst("OrcV2CBindingsVeryLazy", unresolved="ignore"), | 
 |         ToolSubst("dxil-dis", unresolved="ignore"), | 
 |     ] | 
 | ) | 
 |  | 
 | # Find (major, minor) version of ptxas | 
 | def ptxas_version(ptxas): | 
 |     ptxas_cmd = subprocess.Popen([ptxas, "--version"], stdout=subprocess.PIPE) | 
 |     ptxas_out = ptxas_cmd.stdout.read().decode("ascii") | 
 |     ptxas_cmd.wait() | 
 |     match = re.search(r"release (\d+)\.(\d+)", ptxas_out) | 
 |     if match: | 
 |         return (int(match.group(1)), int(match.group(2))) | 
 |     print("couldn't determine ptxas version") | 
 |     return None | 
 |  | 
 |  | 
 | # Enable %ptxas and %ptxas-verify tools. | 
 | # %ptxas-verify defaults to sm_60 architecture. It can be overriden | 
 | # by specifying required one, for instance: %ptxas-verify -arch=sm_80. | 
 | def enable_ptxas(ptxas_executable): | 
 |     version = ptxas_version(ptxas_executable) | 
 |     if version: | 
 |         # ptxas is supposed to be backward compatible with previous | 
 |         # versions, so add a feature for every known version prior to | 
 |         # the current one. | 
 |         ptxas_known_versions = [ | 
 |             (9, 0), | 
 |             (9, 1), | 
 |             (9, 2), | 
 |             (10, 0), | 
 |             (10, 1), | 
 |             (10, 2), | 
 |             (11, 0), | 
 |             (11, 1), | 
 |             (11, 2), | 
 |             (11, 3), | 
 |             (11, 4), | 
 |             (11, 5), | 
 |             (11, 6), | 
 |             (11, 7), | 
 |             (11, 8), | 
 |             (12, 0), | 
 |             (12, 1), | 
 |             (12, 2), | 
 |             (12, 3), | 
 |             (12, 4), | 
 |             (12, 5), | 
 |             (12, 6), | 
 |             (12, 8), | 
 |         ] | 
 |  | 
 |         def version_int(ver): | 
 |             return ver[0] * 100 + ver[1] | 
 |  | 
 |         # ignore ptxas if its version is below the minimum supported | 
 |         # version | 
 |         min_version = ptxas_known_versions[0] | 
 |         if version_int(version) < version_int(min_version): | 
 |             print( | 
 |                 "Warning: ptxas version {}.{} is not supported".format( | 
 |                     version[0], version[1] | 
 |                 ) | 
 |             ) | 
 |             return | 
 |  | 
 |         for known_version in ptxas_known_versions: | 
 |             if version_int(known_version) <= version_int(version): | 
 |                 major, minor = known_version | 
 |                 config.available_features.add("ptxas-{}.{}".format(major, minor)) | 
 |  | 
 |     config.available_features.add("ptxas") | 
 |     tools.extend( | 
 |         [ | 
 |             ToolSubst("%ptxas", ptxas_executable), | 
 |             ToolSubst("%ptxas-verify", "{} -arch=sm_60 -c -".format(ptxas_executable)), | 
 |         ] | 
 |     ) | 
 |  | 
 |  | 
 | ptxas_executable = ( | 
 |     os.environ.get("LLVM_PTXAS_EXECUTABLE", None) or config.ptxas_executable | 
 | ) | 
 | if ptxas_executable: | 
 |     enable_ptxas(ptxas_executable) | 
 |  | 
 | llvm_config.add_tool_substitutions(tools, config.llvm_tools_dir) | 
 |  | 
 | # Targets | 
 |  | 
 | config.targets = frozenset(config.targets_to_build.split()) | 
 |  | 
 | for arch in config.targets_to_build.split(): | 
 |     config.available_features.add(arch.lower() + "-registered-target") | 
 |  | 
 | # Features | 
 | known_arches = ["x86_64", "mips64", "ppc64", "aarch64"] | 
 | if config.host_ldflags.find("-m32") < 0 and any( | 
 |     config.llvm_host_triple.startswith(x) for x in known_arches | 
 | ): | 
 |     config.available_features.add("llvm-64-bits") | 
 |  | 
 | config.available_features.add("host-byteorder-" + sys.byteorder + "-endian") | 
 | if config.target_triple: | 
 |     if re.match( | 
 |         r"(aarch64_be|arc|armeb|bpfeb|lanai|m68k|mips|mips64|powerpc|powerpc64|sparc|sparcv9|s390x|s390|tce|thumbeb)-.*", | 
 |         config.target_triple, | 
 |     ): | 
 |         config.available_features.add("target-byteorder-big-endian") | 
 |     else: | 
 |         config.available_features.add("target-byteorder-little-endian") | 
 |  | 
 | if sys.platform in ["win32"]: | 
 |     # ExecutionEngine, no weak symbols in COFF. | 
 |     config.available_features.add("uses_COFF") | 
 | else: | 
 |     # Others/can-execute.txt | 
 |     config.available_features.add("can-execute") | 
 |  | 
 | # Loadable module | 
 | if config.has_plugins: | 
 |     config.available_features.add("plugins") | 
 |  | 
 | if config.build_examples: | 
 |     config.available_features.add("examples") | 
 |  | 
 | if config.linked_bye_extension: | 
 |     config.substitutions.append(("%llvmcheckext", "CHECK-EXT")) | 
 |     config.substitutions.append(("%loadbye", "")) | 
 |     config.substitutions.append(("%loadnewpmbye", "")) | 
 | else: | 
 |     config.substitutions.append(("%llvmcheckext", "CHECK-NOEXT")) | 
 |     config.substitutions.append( | 
 |         ( | 
 |             "%loadbye", | 
 |             "-load={}/Bye{}".format(config.llvm_shlib_dir, config.llvm_shlib_ext), | 
 |         ) | 
 |     ) | 
 |     config.substitutions.append( | 
 |         ( | 
 |             "%loadnewpmbye", | 
 |             "-load-pass-plugin={}/Bye{}".format( | 
 |                 config.llvm_shlib_dir, config.llvm_shlib_ext | 
 |             ), | 
 |         ) | 
 |     ) | 
 |  | 
 | if config.linked_exampleirtransforms_extension: | 
 |     config.substitutions.append(("%loadexampleirtransforms", "")) | 
 | else: | 
 |     config.substitutions.append( | 
 |         ( | 
 |             "%loadexampleirtransforms", | 
 |             "-load-pass-plugin={}/ExampleIRTransforms{}".format( | 
 |                 config.llvm_shlib_dir, config.llvm_shlib_ext | 
 |             ), | 
 |         ) | 
 |     ) | 
 |  | 
 | # Static libraries are not built if BUILD_SHARED_LIBS is ON. | 
 | if not config.build_shared_libs and not config.link_llvm_dylib: | 
 |     config.available_features.add("static-libs") | 
 |  | 
 | if config.link_llvm_dylib: | 
 |     config.available_features.add("llvm-dylib") | 
 |     config.substitutions.append( | 
 |         ( | 
 |             # libLLVM.so.19.0git | 
 |             "%llvmdylib", | 
 |             "{}/libLLVM{}.{}".format( | 
 |                 config.llvm_shlib_dir, config.llvm_shlib_ext, config.llvm_dylib_version | 
 |             ) | 
 |         ) | 
 |     ) | 
 |  | 
 | if config.have_tf_aot: | 
 |     config.available_features.add("have_tf_aot") | 
 |  | 
 | if config.have_tflite: | 
 |     config.available_features.add("have_tflite") | 
 |  | 
 | if config.llvm_inliner_model_autogenerated: | 
 |     config.available_features.add("llvm_inliner_model_autogenerated") | 
 |  | 
 | if config.llvm_raevict_model_autogenerated: | 
 |     config.available_features.add("llvm_raevict_model_autogenerated") | 
 |  | 
 |  | 
 | def have_cxx_shared_library(): | 
 |     readobj_exe = lit.util.which("llvm-readobj", config.llvm_tools_dir) | 
 |     if not readobj_exe: | 
 |         print("llvm-readobj not found") | 
 |         return False | 
 |  | 
 |     try: | 
 |         readobj_cmd = subprocess.Popen( | 
 |             [readobj_exe, "--needed-libs", readobj_exe], stdout=subprocess.PIPE | 
 |         ) | 
 |     except OSError: | 
 |         print("could not exec llvm-readobj") | 
 |         return False | 
 |  | 
 |     readobj_out = readobj_cmd.stdout.read().decode("ascii") | 
 |     readobj_cmd.wait() | 
 |  | 
 |     regex = re.compile(r"(libc\+\+|libstdc\+\+|msvcp).*\.(so|dylib|dll)") | 
 |     needed_libs = False | 
 |     for line in readobj_out.splitlines(): | 
 |         if "NeededLibraries [" in line: | 
 |             needed_libs = True | 
 |         if "]" in line: | 
 |             needed_libs = False | 
 |         if needed_libs and regex.search(line.lower()): | 
 |             return True | 
 |     return False | 
 |  | 
 |  | 
 | if have_cxx_shared_library(): | 
 |     config.available_features.add("cxx-shared-library") | 
 |  | 
 | if config.libcxx_used: | 
 |     config.available_features.add("libcxx-used") | 
 |  | 
 | # LLVM can be configured with an empty default triple | 
 | # Some tests are "generic" and require a valid default triple | 
 | if config.target_triple: | 
 |     config.available_features.add("default_triple") | 
 |     # Direct object generation | 
 |     if not config.target_triple.startswith(("nvptx", "xcore")): | 
 |         config.available_features.add("object-emission") | 
 |  | 
 | if config.have_llvm_driver: | 
 |     config.available_features.add("llvm-driver") | 
 |  | 
 | import subprocess | 
 |  | 
 |  | 
 | def have_ld_plugin_support(): | 
 |     if not os.path.exists( | 
 |         os.path.join(config.llvm_shlib_dir, "LLVMgold" + config.llvm_shlib_ext) | 
 |     ): | 
 |         return False | 
 |  | 
 |     ld_cmd = subprocess.Popen( | 
 |         [config.gold_executable, "--help"], stdout=subprocess.PIPE, env={"LANG": "C"} | 
 |     ) | 
 |     ld_out = ld_cmd.stdout.read().decode() | 
 |     ld_cmd.wait() | 
 |  | 
 |     if not "-plugin" in ld_out: | 
 |         return False | 
 |  | 
 |     # check that the used emulations are supported. | 
 |     emu_line = [l for l in ld_out.split("\n") if "supported emulations" in l] | 
 |     if len(emu_line) != 1: | 
 |         return False | 
 |     emu_line = emu_line[0] | 
 |     fields = emu_line.split(":") | 
 |     if len(fields) != 3: | 
 |         return False | 
 |     emulations = fields[2].split() | 
 |     if "elf_x86_64" not in emulations: | 
 |         return False | 
 |     if "elf32ppc" in emulations: | 
 |         config.available_features.add("ld_emu_elf32ppc") | 
 |  | 
 |     ld_version = subprocess.Popen( | 
 |         [config.gold_executable, "--version"], stdout=subprocess.PIPE, env={"LANG": "C"} | 
 |     ) | 
 |     if not "GNU gold" in ld_version.stdout.read().decode(): | 
 |         return False | 
 |     ld_version.wait() | 
 |  | 
 |     return True | 
 |  | 
 |  | 
 | if have_ld_plugin_support(): | 
 |     config.available_features.add("ld_plugin") | 
 |  | 
 |  | 
 | def have_ld64_plugin_support(): | 
 |     if not os.path.exists( | 
 |         os.path.join(config.llvm_shlib_dir, "libLTO" + config.llvm_shlib_ext) | 
 |     ): | 
 |         return False | 
 |  | 
 |     if config.ld64_executable == "": | 
 |         return False | 
 |  | 
 |     ld_cmd = subprocess.Popen([config.ld64_executable, "-v"], stderr=subprocess.PIPE) | 
 |     ld_out = ld_cmd.stderr.read().decode() | 
 |     ld_cmd.wait() | 
 |  | 
 |     if "ld64" not in ld_out or "LTO" not in ld_out: | 
 |         return False | 
 |  | 
 |     return True | 
 |  | 
 |  | 
 | if have_ld64_plugin_support(): | 
 |     config.available_features.add("ld64_plugin") | 
 |  | 
 | def host_unwind_supports_jit(): | 
 |     # Do we expect the host machine to support JIT registration of clang's | 
 |     # default unwind info format for the host (e.g. eh-frames, compact-unwind, | 
 |     # etc.). | 
 |  | 
 |     # Linux and the BSDs use DWARF eh-frames and all known unwinders support | 
 |     # register_frame at minimum. | 
 |     if platform.system() in [ "Linux", "FreeBSD", "NetBSD" ]: | 
 |         return True | 
 |  | 
 |     # Windows does not support frame info without the ORC runtime. | 
 |     if platform.system() == "Windows": | 
 |         return False | 
 |  | 
 |     # On Darwin/x86-64 clang produces both eh-frames and compact-unwind, and | 
 |     # libunwind supports register_frame. On Darwin/arm64 clang produces | 
 |     # compact-unwind only, and JIT'd registration is not available before | 
 |     # macOS 14.0. | 
 |     if platform.system() == "Darwin": | 
 |  | 
 |         assert ( | 
 |             "arm64" in config.host_triple | 
 |             or "x86_64" in config.host_triple | 
 |         ) | 
 |  | 
 |         if "x86_64" in config.host_triple: | 
 |             return True | 
 |  | 
 |         # Must be arm64. Check the macOS version. | 
 |         try: | 
 |             osx_version = subprocess.check_output( | 
 |                 ["sw_vers", "-productVersion"], universal_newlines=True | 
 |             ) | 
 |             osx_version = tuple(int(x) for x in osx_version.split(".")) | 
 |             if len(osx_version) == 2: | 
 |                 osx_version = (osx_version[0], osx_version[1], 0) | 
 |             if osx_version >= (14, 0): | 
 |                 return True | 
 |         except: | 
 |             pass | 
 |  | 
 |         return False | 
 |  | 
 |     return False | 
 |  | 
 | if host_unwind_supports_jit(): | 
 |     config.available_features.add("host-unwind-supports-jit") | 
 |  | 
 | # Ask llvm-config about asserts | 
 | llvm_config.feature_config( | 
 |     [ | 
 |         ("--assertion-mode", {"ON": "asserts"}), | 
 |         ("--build-mode", {"[Dd][Ee][Bb][Uu][Gg]": "debug"}), | 
 |     ] | 
 | ) | 
 |  | 
 | if "darwin" == sys.platform: | 
 |     cmd = ["sysctl", "hw.optional.fma"] | 
 |     sysctl_cmd = subprocess.Popen(cmd, stdout=subprocess.PIPE) | 
 |  | 
 |     # Non zero return, probably a permission issue | 
 |     if sysctl_cmd.wait(): | 
 |         print( | 
 |             'Warning: sysctl exists but calling "{}" failed, defaulting to no fma3.'.format( | 
 |                 " ".join(cmd) | 
 |             ) | 
 |         ) | 
 |     else: | 
 |         result = sysctl_cmd.stdout.read().decode("ascii") | 
 |         if "hw.optional.fma: 1" in result: | 
 |             config.available_features.add("fma3") | 
 |  | 
 | if not hasattr(sys, "getwindowsversion") or sys.getwindowsversion().build >= 17063: | 
 |     config.available_features.add("unix-sockets") | 
 |  | 
 | # .debug_frame is not emitted for targeting Windows x64, aarch64/arm64, AIX, or Apple Silicon Mac. | 
 | if not re.match( | 
 |     r"^(x86_64|aarch64|arm64|powerpc|powerpc64).*-(windows-gnu|windows-msvc|aix)", | 
 |     config.target_triple, | 
 | ) and not re.match(r"^arm64(e)?-apple-(macos|darwin)", config.target_triple): | 
 |     config.available_features.add("debug_frame") | 
 |  | 
 | if config.enable_backtrace: | 
 |     config.available_features.add("backtrace") | 
 |  | 
 | if config.enable_threads: | 
 |     config.available_features.add("thread_support") | 
 |  | 
 | if config.have_libxml2: | 
 |     config.available_features.add("libxml2") | 
 |  | 
 | if config.have_curl: | 
 |     config.available_features.add("curl") | 
 |  | 
 | if config.have_httplib: | 
 |     config.available_features.add("httplib") | 
 |  | 
 | if config.have_opt_viewer_modules: | 
 |     config.available_features.add("have_opt_viewer_modules") | 
 |  | 
 | if config.expensive_checks: | 
 |     config.available_features.add("expensive_checks") | 
 |  | 
 | if "MemoryWithOrigins" in config.llvm_use_sanitizer: | 
 |     config.available_features.add("use_msan_with_origins") | 
 |  | 
 |  | 
 | # Some tools support an environment variable "OBJECT_MODE" on AIX OS, which | 
 | # controls the kind of objects they will support. If there is no "OBJECT_MODE" | 
 | # environment variable specified, the default behaviour is to support 32-bit | 
 | # objects only. In order to not affect most test cases, which expect to support | 
 | # 32-bit and 64-bit objects by default, set the environment variable | 
 | # "OBJECT_MODE" to 'any' by default on AIX OS. | 
 | if "system-aix" in config.available_features: | 
 |     config.environment["OBJECT_MODE"] = "any" | 
 |  | 
 | if config.has_logf128: | 
 |     config.available_features.add("has_logf128") |