| """ | |
| Platform-agnostic helper to query for CPU features. | |
| """ | |
| import re | |
| class CPUFeature: | |
| def __init__(self, linux_cpu_info_flag: str = None, darwin_sysctl_key: str = None): | |
| self.cpu_info_flag = linux_cpu_info_flag | |
| self.sysctl_key = darwin_sysctl_key | |
| def __str__(self): | |
| for arch_class in ALL_ARCHS: | |
| for feat_var in dir(arch_class): | |
| if self == getattr(arch_class, feat_var): | |
| return f"{arch_class.__name__}.{feat_var}" | |
| raise AssertionError("unreachable") | |
| def is_supported(self, triple, cmd_runner): | |
| if re.match(".*-.*-linux", triple): | |
| err_msg, res = self._is_supported_linux(cmd_runner) | |
| elif re.match(".*-apple-.*", triple): | |
| err_msg, res = self._is_supported_darwin(cmd_runner) | |
| else: | |
| err_msg, res = None, False | |
| if err_msg: | |
| print(f"CPU feature check failed: {err_msg}") | |
| return res | |
| def _is_supported_linux(self, cmd_runner): | |
| if not self.cpu_info_flag: | |
| return f"Unspecified cpuinfo flag for {self}", False | |
| cmd = "cat /proc/cpuinfo" | |
| err, retcode, output = cmd_runner(cmd) | |
| if err.Fail() or retcode != 0: | |
| return output, False | |
| # Assume that every processor presents the same features. | |
| # Look for the first "Features: ...." line. Features are space separated. | |
| if m := re.search(r"Features\s*: (.*)\n", output): | |
| features = m.group(1).split() | |
| return None, (self.cpu_info_flag in features) | |
| return 'No "Features:" line found in /proc/cpuinfo', False | |
| def _is_supported_darwin(self, cmd_runner): | |
| if not self.sysctl_key: | |
| return f"Unspecified sysctl key for {self}", False | |
| cmd = f"sysctl -n {self.sysctl_key}" | |
| err, retcode, output = cmd_runner(cmd) | |
| if err.Fail() or retcode != 0: | |
| return output, False | |
| return None, (output.strip() == "1") | |
| class AArch64: | |
| FPMR = CPUFeature("fpmr") | |
| POE = CPUFeature("poe") | |
| GCS = CPUFeature("gcs") | |
| MTE = CPUFeature("mte", "hw.optional.arm.FEAT_MTE4") | |
| MTE_STORE_ONLY = CPUFeature("mtestoreonly") | |
| PTR_AUTH = CPUFeature("paca", "hw.optional.arm.FEAT_PAuth2") | |
| SME = CPUFeature("sme", "hw.optional.arm.FEAT_SME") | |
| SME_FA64 = CPUFeature("smefa64") | |
| SME2 = CPUFeature("sme2", "hw.optional.arm.FEAT_SME2") | |
| SVE = CPUFeature("sve") | |
| class Loong: | |
| LASX = CPUFeature("lasx") | |
| LSX = CPUFeature("lsx") | |
| ALL_ARCHS = [AArch64, Loong] |