11273af23SJacques Pienaar# -*- Python -*- 21273af23SJacques Pienaar 31273af23SJacques Pienaarimport os 41273af23SJacques Pienaarimport platform 51273af23SJacques Pienaarimport re 6beff2bacSKasper Nielsenimport shutil 71273af23SJacques Pienaarimport subprocess 81273af23SJacques Pienaarimport tempfile 91273af23SJacques Pienaar 101273af23SJacques Pienaarimport lit.formats 111273af23SJacques Pienaarimport lit.util 121273af23SJacques Pienaar 131273af23SJacques Pienaarfrom lit.llvm import llvm_config 141273af23SJacques Pienaarfrom lit.llvm.subst import ToolSubst 151273af23SJacques Pienaarfrom lit.llvm.subst import FindTool 161273af23SJacques Pienaar 171273af23SJacques Pienaar# Configuration file for the 'lit' test runner. 181273af23SJacques Pienaar 191273af23SJacques Pienaar# name: The name of this test suite. 20f9008e63STobias Hietaconfig.name = "MLIR" 211273af23SJacques Pienaar 2218e55052SConnie Zhu# TODO: Consolidate the logic for turning on the internal shell by default for all LLVM test suites. 2318e55052SConnie Zhu# See https://github.com/llvm/llvm-project/issues/106636 for more details. 2418e55052SConnie Zhu# 25a9f30097SMehdi Amini# We prefer the lit internal shell which provides a better user experience on failures 26a9f30097SMehdi Amini# unless the user explicitly disables it with LIT_USE_INTERNAL_SHELL=0 env var. 27a9f30097SMehdi Aminiuse_lit_shell = True 28a9f30097SMehdi Aminilit_shell_env = os.environ.get("LIT_USE_INTERNAL_SHELL") 29a9f30097SMehdi Aminiif lit_shell_env: 3018e55052SConnie Zhu use_lit_shell = lit.util.pythonize_bool(lit_shell_env) 31a9f30097SMehdi Amini 32a9f30097SMehdi Aminiconfig.test_format = lit.formats.ShTest(execute_external=not use_lit_shell) 331273af23SJacques Pienaar 341273af23SJacques Pienaar# suffixes: A list of file extensions to treat as test files. 35f9008e63STobias Hietaconfig.suffixes = [ 36f9008e63STobias Hieta ".td", 37f9008e63STobias Hieta ".mlir", 38f9008e63STobias Hieta ".toy", 39f9008e63STobias Hieta ".ll", 40f9008e63STobias Hieta ".tc", 41f9008e63STobias Hieta ".py", 42f9008e63STobias Hieta ".yaml", 43f9008e63STobias Hieta ".test", 44f9008e63STobias Hieta ".pdll", 45f9008e63STobias Hieta ".c", 46f9008e63STobias Hieta] 471273af23SJacques Pienaar 481273af23SJacques Pienaar# test_source_root: The root path where tests are located. 491273af23SJacques Pienaarconfig.test_source_root = os.path.dirname(__file__) 501273af23SJacques Pienaar 511273af23SJacques Pienaar# test_exec_root: The root path where tests should be run. 52f9008e63STobias Hietaconfig.test_exec_root = os.path.join(config.mlir_obj_root, "test") 531273af23SJacques Pienaar 54f9008e63STobias Hietaconfig.substitutions.append(("%PATH%", config.environment["PATH"])) 55f9008e63STobias Hietaconfig.substitutions.append(("%shlibext", config.llvm_shlib_ext)) 56d5e4e702SSergio Afonsoconfig.substitutions.append(("%llvm_src_root", config.llvm_src_root)) 57175a3df9SStephen Neuendorfferconfig.substitutions.append(("%mlir_src_root", config.mlir_src_root)) 58ac5d32b1SMehdi Aminiconfig.substitutions.append(("%host_cxx", config.host_cxx)) 59ac5d32b1SMehdi Aminiconfig.substitutions.append(("%host_cc", config.host_cc)) 601273af23SJacques Pienaar 619048ea28SMarkus Böck 62783ac3b6SBenjamin Maxwell# Searches for a runtime library with the given name and returns the found path. 639048ea28SMarkus Böck# Correctly handles the platforms shared library directory and naming conventions. 64783ac3b6SBenjamin Maxwelldef find_runtime(name): 65f9008e63STobias Hieta path = "" 66f9008e63STobias Hieta for prefix in ["", "lib"]: 67f9008e63STobias Hieta path = os.path.join( 68f9008e63STobias Hieta config.llvm_shlib_dir, f"{prefix}{name}{config.llvm_shlib_ext}" 69f9008e63STobias Hieta ) 709048ea28SMarkus Böck if os.path.isfile(path): 719048ea28SMarkus Böck break 72783ac3b6SBenjamin Maxwell return path 73783ac3b6SBenjamin Maxwell 74783ac3b6SBenjamin Maxwell 75783ac3b6SBenjamin Maxwell# Searches for a runtime library with the given name and returns a tool 76783ac3b6SBenjamin Maxwell# substitution of the same name and the found path. 77783ac3b6SBenjamin Maxwelldef add_runtime(name): 78783ac3b6SBenjamin Maxwell return ToolSubst(f"%{name}", find_runtime(name)) 799048ea28SMarkus Böck 809048ea28SMarkus Böck 81beff2bacSKasper Nielsen# Provide the path to asan runtime lib 'libclang_rt.asan_osx_dynamic.dylib' if 82beff2bacSKasper Nielsen# available. This is darwin specific since it's currently only needed on darwin. 83beff2bacSKasper Nielsen# Stolen from llvm/test/lit.cfg.py with a few modifications 84beff2bacSKasper Nielsendef get_asan_rtlib(): 85*d3446240SMatthias Gehre if not "asan" in config.available_features: 86beff2bacSKasper Nielsen return "" 87*d3446240SMatthias Gehre 88*d3446240SMatthias Gehre if "Darwin" in config.host_os: 89beff2bacSKasper Nielsen # Find the asan rt lib 90beff2bacSKasper Nielsen resource_dir = ( 91beff2bacSKasper Nielsen subprocess.check_output([config.host_cc.strip(), "-print-resource-dir"]) 92beff2bacSKasper Nielsen .decode("utf-8") 93beff2bacSKasper Nielsen .strip() 94beff2bacSKasper Nielsen ) 95beff2bacSKasper Nielsen return os.path.join( 96beff2bacSKasper Nielsen resource_dir, "lib", "darwin", "libclang_rt.asan_osx_dynamic.dylib" 97beff2bacSKasper Nielsen ) 98*d3446240SMatthias Gehre if "Linux" in config.host_os: 99*d3446240SMatthias Gehre return ( 100*d3446240SMatthias Gehre subprocess.check_output( 101*d3446240SMatthias Gehre [ 102*d3446240SMatthias Gehre config.host_cxx.strip(), 103*d3446240SMatthias Gehre f"-print-file-name=libclang_rt.asan-{config.host_arch}.so", 104*d3446240SMatthias Gehre ] 105*d3446240SMatthias Gehre ) 106*d3446240SMatthias Gehre .decode("utf-8") 107*d3446240SMatthias Gehre .strip() 108*d3446240SMatthias Gehre ) 109*d3446240SMatthias Gehre 110*d3446240SMatthias Gehre return "" 111beff2bacSKasper Nielsen 112beff2bacSKasper Nielsen 113beff2bacSKasper Nielsen# On macOS, we can't do the DYLD_INSERT_LIBRARIES trick with a shim python 114beff2bacSKasper Nielsen# binary as the ASan interceptors get loaded too late. Also, when SIP is 115beff2bacSKasper Nielsen# enabled, we can't inject libraries into system binaries at all, so we need a 116beff2bacSKasper Nielsen# copy of the "real" python to work with. 117beff2bacSKasper Nielsen# Stolen from lldb/test/API/lit.cfg.py with a few modifications 118beff2bacSKasper Nielsendef find_real_python_interpreter(): 119beff2bacSKasper Nielsen # If we're running in a virtual environment, we have to copy Python into 120beff2bacSKasper Nielsen # the virtual environment for it to work. 121beff2bacSKasper Nielsen if sys.prefix != sys.base_prefix: 122beff2bacSKasper Nielsen copied_python = os.path.join(sys.prefix, "bin", "copied-python") 123beff2bacSKasper Nielsen else: 124f79bacb4SLuohao Wang copied_python = os.path.join(config.mlir_obj_root, "copied-python") 125beff2bacSKasper Nielsen 126beff2bacSKasper Nielsen # Avoid doing any work if we already copied the binary. 127beff2bacSKasper Nielsen if os.path.isfile(copied_python): 128beff2bacSKasper Nielsen return copied_python 129beff2bacSKasper Nielsen 130beff2bacSKasper Nielsen # Find the "real" python binary. 131beff2bacSKasper Nielsen real_python = ( 132beff2bacSKasper Nielsen subprocess.check_output( 133beff2bacSKasper Nielsen [ 134beff2bacSKasper Nielsen config.python_executable, 135beff2bacSKasper Nielsen os.path.join( 136beff2bacSKasper Nielsen os.path.dirname(os.path.realpath(__file__)), 137beff2bacSKasper Nielsen "get_darwin_real_python.py", 138beff2bacSKasper Nielsen ), 139beff2bacSKasper Nielsen ] 140beff2bacSKasper Nielsen ) 141beff2bacSKasper Nielsen .decode("utf-8") 142beff2bacSKasper Nielsen .strip() 143beff2bacSKasper Nielsen ) 144beff2bacSKasper Nielsen 145beff2bacSKasper Nielsen shutil.copy(real_python, copied_python) 146beff2bacSKasper Nielsen 147beff2bacSKasper Nielsen # Now make sure the copied Python works. The Python in Xcode has a relative 148beff2bacSKasper Nielsen # RPATH and cannot be copied. 149beff2bacSKasper Nielsen try: 150beff2bacSKasper Nielsen # We don't care about the output, just make sure it runs. 151beff2bacSKasper Nielsen subprocess.check_call([copied_python, "-V"]) 152beff2bacSKasper Nielsen except subprocess.CalledProcessError: 153beff2bacSKasper Nielsen # The copied Python didn't work. Assume we're dealing with the Python 154beff2bacSKasper Nielsen # interpreter in Xcode. Given that this is not a system binary SIP 155beff2bacSKasper Nielsen # won't prevent us form injecting the interceptors, but when running in 156beff2bacSKasper Nielsen # a virtual environment, we can't use it directly. Create a symlink 157beff2bacSKasper Nielsen # instead. 158beff2bacSKasper Nielsen os.remove(copied_python) 159beff2bacSKasper Nielsen os.symlink(real_python, copied_python) 160beff2bacSKasper Nielsen 161beff2bacSKasper Nielsen # The copied Python works. 162beff2bacSKasper Nielsen return copied_python 163beff2bacSKasper Nielsen 164beff2bacSKasper Nielsen 165f9008e63STobias Hietallvm_config.with_system_environment(["HOME", "INCLUDE", "LIB", "TMP", "TEMP"]) 1661273af23SJacques Pienaar 1671273af23SJacques Pienaarllvm_config.use_default_substitutions() 1681273af23SJacques Pienaar 1691273af23SJacques Pienaar# excludes: A list of directories to exclude from the testsuite. The 'Inputs' 1701273af23SJacques Pienaar# subdirectories contain auxiliary inputs for various tests in their parent 1711273af23SJacques Pienaar# directories. 172f9008e63STobias Hietaconfig.excludes = [ 173f9008e63STobias Hieta "Inputs", 174f9008e63STobias Hieta "CMakeLists.txt", 175f9008e63STobias Hieta "README.txt", 176f9008e63STobias Hieta "LICENSE.txt", 177f9008e63STobias Hieta "lit.cfg.py", 178f9008e63STobias Hieta "lit.site.cfg.py", 179beff2bacSKasper Nielsen "get_darwin_real_python.py", 180f9008e63STobias Hieta] 1811273af23SJacques Pienaar 1821273af23SJacques Pienaar# Tweak the PATH to include the tools dir. 183f9008e63STobias Hietallvm_config.with_environment("PATH", config.mlir_tools_dir, append_path=True) 184f9008e63STobias Hietallvm_config.with_environment("PATH", config.llvm_tools_dir, append_path=True) 1851273af23SJacques Pienaar 1861273af23SJacques Pienaartool_dirs = [config.mlir_tools_dir, config.llvm_tools_dir] 1871273af23SJacques Pienaartools = [ 188f9008e63STobias Hieta "mlir-tblgen", 189f9008e63STobias Hieta "mlir-translate", 190f9008e63STobias Hieta "mlir-lsp-server", 191f9008e63STobias Hieta "mlir-capi-execution-engine-test", 192f9008e63STobias Hieta "mlir-capi-ir-test", 1931337622aSThéo Degioanni "mlir-capi-irdl-test", 194f9008e63STobias Hieta "mlir-capi-llvm-test", 195f9008e63STobias Hieta "mlir-capi-pass-test", 196f9008e63STobias Hieta "mlir-capi-pdl-test", 197f9008e63STobias Hieta "mlir-capi-quant-test", 1985f8c46b8SFehr Mathieu "mlir-capi-rewrite-test", 199f9008e63STobias Hieta "mlir-capi-sparse-tensor-test", 200f9008e63STobias Hieta "mlir-capi-transform-test", 20191f11611SOleksandr "Alex" Zinenko "mlir-capi-transform-interpreter-test", 2027fb89bfbSVitaly Buka "mlir-capi-translation-test", 203eb206e9eSAndrea Faulds "mlir-runner", 204f9008e63STobias Hieta add_runtime("mlir_runner_utils"), 205f9008e63STobias Hieta add_runtime("mlir_c_runner_utils"), 206f9008e63STobias Hieta add_runtime("mlir_async_runtime"), 207fe355a44SAlexander Shaposhnikov add_runtime("mlir_float16_utils"), 208f9008e63STobias Hieta "mlir-linalg-ods-yaml-gen", 209f9008e63STobias Hieta "mlir-reduce", 210f9008e63STobias Hieta "mlir-pdll", 211f9008e63STobias Hieta "not", 2121273af23SJacques Pienaar] 21338b71d6bSMehdi Amini 2149048ea28SMarkus Böckif config.enable_vulkan_runner: 215e7e3c45bSAndrea Faulds tools.extend([add_runtime("mlir_vulkan_runtime")]) 2169048ea28SMarkus Böck 2179048ea28SMarkus Böckif config.enable_rocm_runner: 218f9008e63STobias Hieta tools.extend([add_runtime("mlir_rocm_runtime")]) 2199048ea28SMarkus Böck 2209048ea28SMarkus Böckif config.enable_cuda_runner: 221f9008e63STobias Hieta tools.extend([add_runtime("mlir_cuda_runtime")]) 2225c6d8a74SChristian Sigg 2237fc792cbSSang Ik Leeif config.enable_sycl_runner: 2247fc792cbSSang Ik Lee tools.extend([add_runtime("mlir_sycl_runtime")]) 2257fc792cbSSang Ik Lee 2260e39b134SAndrea Fauldsif config.enable_spirv_cpu_runner: 2270e39b134SAndrea Faulds tools.extend([add_runtime("mlir_spirv_cpu_runtime")]) 2280e39b134SAndrea Faulds 229e280c287SBenjamin Maxwellif config.mlir_run_arm_sve_tests or config.mlir_run_arm_sme_tests: 230e280c287SBenjamin Maxwell tools.extend([add_runtime("mlir_arm_runner_utils")]) 231e280c287SBenjamin Maxwell 232783ac3b6SBenjamin Maxwellif config.mlir_run_arm_sme_tests: 233783ac3b6SBenjamin Maxwell config.substitutions.append( 234783ac3b6SBenjamin Maxwell ( 235783ac3b6SBenjamin Maxwell "%arm_sme_abi_shlib", 236783ac3b6SBenjamin Maxwell # Use passed Arm SME ABI routines, if not present default to stubs. 237783ac3b6SBenjamin Maxwell config.arm_sme_abi_routines_shlib or find_runtime("mlir_arm_sme_abi_stubs"), 238783ac3b6SBenjamin Maxwell ) 239783ac3b6SBenjamin Maxwell ) 240783ac3b6SBenjamin Maxwell 24138b71d6bSMehdi Amini# The following tools are optional 242f9008e63STobias Hietatools.extend( 243f9008e63STobias Hieta [ 244f9008e63STobias Hieta ToolSubst("toyc-ch1", unresolved="ignore"), 245f9008e63STobias Hieta ToolSubst("toyc-ch2", unresolved="ignore"), 246f9008e63STobias Hieta ToolSubst("toyc-ch3", unresolved="ignore"), 247f9008e63STobias Hieta ToolSubst("toyc-ch4", unresolved="ignore"), 248f9008e63STobias Hieta ToolSubst("toyc-ch5", unresolved="ignore"), 249f9008e63STobias Hieta ToolSubst("toyc-ch6", unresolved="ignore"), 250f9008e63STobias Hieta ToolSubst("toyc-ch7", unresolved="ignore"), 2514cb2ef4fSOleksandr "Alex" Zinenko ToolSubst("transform-opt-ch2", unresolved="ignore"), 2524cb2ef4fSOleksandr "Alex" Zinenko ToolSubst("transform-opt-ch3", unresolved="ignore"), 2534cb2ef4fSOleksandr "Alex" Zinenko ToolSubst("transform-opt-ch4", unresolved="ignore"), 254619ee20bSOleksandr "Alex" Zinenko ToolSubst("mlir-transform-opt", unresolved="ignore"), 255f9008e63STobias Hieta ToolSubst("%mlir_lib_dir", config.mlir_lib_dir, unresolved="ignore"), 256f9008e63STobias Hieta ToolSubst("%mlir_src_dir", config.mlir_src_root, unresolved="ignore"), 257f9008e63STobias Hieta ] 258f9008e63STobias Hieta) 259bce0c642SMehdi Amini 260bce0c642SMehdi Aminipython_executable = config.python_executable 261beff2bacSKasper Nielsen# Python configuration with sanitizer requires some magic preloading. This will only work on clang/linux/darwin. 262beff2bacSKasper Nielsen# TODO: detect Windows situation (or mark these tests as unsupported on these platforms). 263beff2bacSKasper Nielsenif "asan" in config.available_features: 264beff2bacSKasper Nielsen if "Linux" in config.host_os: 265*d3446240SMatthias Gehre python_executable = ( 266*d3446240SMatthias Gehre f"env LD_PRELOAD={get_asan_rtlib()} {config.python_executable}" 267*d3446240SMatthias Gehre ) 268beff2bacSKasper Nielsen if "Darwin" in config.host_os: 269beff2bacSKasper Nielsen # Ensure we use a non-shim Python executable, for the `DYLD_INSERT_LIBRARIES` 270beff2bacSKasper Nielsen # env variable to take effect 271beff2bacSKasper Nielsen real_python_executable = find_real_python_interpreter() 272beff2bacSKasper Nielsen if real_python_executable: 273beff2bacSKasper Nielsen python_executable = real_python_executable 274beff2bacSKasper Nielsen lit_config.note( 275beff2bacSKasper Nielsen "Using {} instead of {}".format( 276beff2bacSKasper Nielsen python_executable, config.python_executable 277beff2bacSKasper Nielsen ) 278beff2bacSKasper Nielsen ) 279beff2bacSKasper Nielsen 280beff2bacSKasper Nielsen asan_rtlib = get_asan_rtlib() 281beff2bacSKasper Nielsen lit_config.note("Using ASan rtlib {}".format(asan_rtlib)) 282beff2bacSKasper Nielsen config.environment["MallocNanoZone"] = "0" 283beff2bacSKasper Nielsen config.environment["ASAN_OPTIONS"] = "detect_stack_use_after_return=1" 284beff2bacSKasper Nielsen config.environment["DYLD_INSERT_LIBRARIES"] = asan_rtlib 285beff2bacSKasper Nielsen 286beff2bacSKasper Nielsen 287057863a9SStella Stamenova# On Windows the path to python could contains spaces in which case it needs to be provided in quotes. 288057863a9SStella Stamenova# This is the equivalent of how %python is setup in llvm/utils/lit/lit/llvm/config.py. 289057863a9SStella Stamenovaelif "Windows" in config.host_os: 290057863a9SStella Stamenova python_executable = '"%s"' % (python_executable) 291f9008e63STobias Hietatools.extend( 292f9008e63STobias Hieta [ 293f9008e63STobias Hieta ToolSubst("%PYTHON", python_executable, unresolved="ignore"), 294f9008e63STobias Hieta ] 295f9008e63STobias Hieta) 296bce0c642SMehdi Amini 297a6d09d4bSMehdi Aminiif "MLIR_OPT_CHECK_IR_ROUNDTRIP" in os.environ: 298f9008e63STobias Hieta tools.extend( 299f9008e63STobias Hieta [ 300f9008e63STobias Hieta ToolSubst("mlir-opt", "mlir-opt --verify-roundtrip", unresolved="fatal"), 301f9008e63STobias Hieta ] 302f9008e63STobias Hieta ) 30300480189SBenjamin Kramerelse: 30400480189SBenjamin Kramer tools.extend(["mlir-opt"]) 305a6d09d4bSMehdi Amini 3061273af23SJacques Pienaarllvm_config.add_tool_substitutions(tools, tool_dirs) 30795371ce9SMehdi Amini 30895371ce9SMehdi Amini 30995371ce9SMehdi Amini# FileCheck -enable-var-scope is enabled by default in MLIR test 31095371ce9SMehdi Amini# This option avoids to accidentally reuse variable across -LABEL match, 31195371ce9SMehdi Amini# it can be explicitly opted-in by prefixing the variable name with $ 312f9008e63STobias Hietaconfig.environment["FILECHECK_OPTS"] = "-enable-var-scope --allow-unused-prefixes=false" 313bc14c77aSMehdi Amini 314722475a3SStella Laurenzo# Add the python path for both the source and binary tree. 315722475a3SStella Laurenzo# Note that presently, the python sources come from the source tree and the 316722475a3SStella Laurenzo# binaries come from the build tree. This should be unified to the build tree 317722475a3SStella Laurenzo# by copying/linking sources to build. 318722475a3SStella Laurenzoif config.enable_bindings_python: 3198c212a3fSMaksim Levental config.environment["PYTHONPATH"] = os.getenv("MLIR_LIT_PYTHONPATH", "") 320f9008e63STobias Hieta llvm_config.with_environment( 321f9008e63STobias Hieta "PYTHONPATH", 322f9008e63STobias Hieta [ 323f9008e63STobias Hieta os.path.join(config.mlir_obj_root, "python_packages", "mlir_core"), 324f9008e63STobias Hieta os.path.join(config.mlir_obj_root, "python_packages", "mlir_test"), 325f9008e63STobias Hieta ], 326f9008e63STobias Hieta append_path=True, 327f9008e63STobias Hieta ) 3280f9e6451SMehdi Amini 3290f9e6451SMehdi Aminiif config.enable_assertions: 330f9008e63STobias Hieta config.available_features.add("asserts") 3310f9e6451SMehdi Aminielse: 332f9008e63STobias Hieta config.available_features.add("noasserts") 333f9008e63STobias Hieta 334ca98e0ddSRainer Orth 335ca98e0ddSRainer Orthdef have_host_jit_feature_support(feature_name): 336eb206e9eSAndrea Faulds mlir_runner_exe = lit.util.which("mlir-runner", config.mlir_tools_dir) 337ca98e0ddSRainer Orth 338eb206e9eSAndrea Faulds if not mlir_runner_exe: 339ca98e0ddSRainer Orth return False 340ca98e0ddSRainer Orth 341ca98e0ddSRainer Orth try: 342eb206e9eSAndrea Faulds mlir_runner_cmd = subprocess.Popen( 343eb206e9eSAndrea Faulds [mlir_runner_exe, "--host-supports-" + feature_name], 344f9008e63STobias Hieta stdout=subprocess.PIPE, 345f9008e63STobias Hieta ) 346ca98e0ddSRainer Orth except OSError: 347eb206e9eSAndrea Faulds print("could not exec mlir-runner") 348ca98e0ddSRainer Orth return False 349ca98e0ddSRainer Orth 350eb206e9eSAndrea Faulds mlir_runner_out = mlir_runner_cmd.stdout.read().decode("ascii") 351eb206e9eSAndrea Faulds mlir_runner_cmd.wait() 352ca98e0ddSRainer Orth 353eb206e9eSAndrea Faulds return "true" in mlir_runner_out 354ca98e0ddSRainer Orth 355f9008e63STobias Hieta 356f9008e63STobias Hietaif have_host_jit_feature_support("jit"): 357f9008e63STobias Hieta config.available_features.add("host-supports-jit") 35843752a2aSFabian Mora 3598178a3adStyb0807if config.run_nvptx_tests: 36043752a2aSFabian Mora config.available_features.add("host-supports-nvptx") 36143752a2aSFabian Mora 36243752a2aSFabian Moraif config.run_rocm_tests: 36343752a2aSFabian Mora config.available_features.add("host-supports-amdgpu") 3647d69095fSMubashar Ahmad 3657d69095fSMubashar Ahmadif config.arm_emulator_executable: 3667d69095fSMubashar Ahmad config.available_features.add("arm-emulator") 367