#include "llvm/TargetParser/Host.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Triple.h"
#include "llvm/TargetParser/X86TargetParser.h"
#include <string.h>
#ifdef LLVM_ON_UNIX
#include "Unix/Host.inc"
#include <sched.h>
#endif
#ifdef _WIN32
#include "Windows/Host.inc"
#endif
#ifdef _MSC_VER
#include <intrin.h>
#endif
#ifdef __MVS__
#include "llvm/Support/BCD.h"
#endif
#if defined(__APPLE__)
#include <mach/host_info.h>
#include <mach/mach.h>
#include <mach/mach_host.h>
#include <mach/machine.h>
#include <sys/param.h>
#include <sys/sysctl.h>
#endif
#ifdef _AIX
#include <sys/systemcfg.h>
#endif
#if defined(__sun__) && defined(__svr4__)
#include <kstat.h>
#endif
#if defined(__GNUC__) || defined(__clang__)
#if (defined(__i386__) || defined(__x86_64__)) && !defined(_MSC_VER)
#include <cpuid.h>
#endif
#endif
#define DEBUG_TYPE …
usingnamespacellvm;
static std::unique_ptr<llvm::MemoryBuffer>
LLVM_ATTRIBUTE_UNUSED getProcCpuinfoContent() { … }
StringRef sys::detail::getHostCPUNameForPowerPC(StringRef ProcCpuinfoContent) { … }
StringRef sys::detail::getHostCPUNameForARM(StringRef ProcCpuinfoContent) { … }
namespace {
StringRef getCPUNameFromS390Model(unsigned int Id, bool HaveVectorSupport) { … }
}
StringRef sys::detail::getHostCPUNameForS390x(StringRef ProcCpuinfoContent) { … }
StringRef sys::detail::getHostCPUNameForRISCV(StringRef ProcCpuinfoContent) { … }
StringRef sys::detail::getHostCPUNameForBPF() { … }
#if defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || \
defined(_M_X64)
static bool getX86CpuIDAndInfo(unsigned value, unsigned *rEAX, unsigned *rEBX,
unsigned *rECX, unsigned *rEDX) { … }
namespace llvm {
namespace sys {
namespace detail {
namespace x86 {
VendorSignatures getVendorSignature(unsigned *MaxLeaf) { … }
}
}
}
}
usingnamespacellvm::sys::detail::x86;
static bool getX86CpuIDAndInfoEx(unsigned value, unsigned subleaf,
unsigned *rEAX, unsigned *rEBX, unsigned *rECX,
unsigned *rEDX) { … }
static bool getX86XCR0(unsigned *rEAX, unsigned *rEDX) { … }
static void detectX86FamilyModel(unsigned EAX, unsigned *Family,
unsigned *Model) { … }
#define testFeature …
static StringRef getIntelProcessorTypeAndSubtype(unsigned Family,
unsigned Model,
const unsigned *Features,
unsigned *Type,
unsigned *Subtype) { … }
static const char *getAMDProcessorTypeAndSubtype(unsigned Family,
unsigned Model,
const unsigned *Features,
unsigned *Type,
unsigned *Subtype) { … }
#undef testFeature
static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf,
unsigned *Features) { … }
StringRef sys::getHostCPUName() { … }
#elif defined(__APPLE__) && defined(__powerpc__)
StringRef sys::getHostCPUName() {
host_basic_info_data_t hostInfo;
mach_msg_type_number_t infoCount;
infoCount = HOST_BASIC_INFO_COUNT;
mach_port_t hostPort = mach_host_self();
host_info(hostPort, HOST_BASIC_INFO, (host_info_t)&hostInfo,
&infoCount);
mach_port_deallocate(mach_task_self(), hostPort);
if (hostInfo.cpu_type != CPU_TYPE_POWERPC)
return "generic";
switch (hostInfo.cpu_subtype) {
case CPU_SUBTYPE_POWERPC_601:
return "601";
case CPU_SUBTYPE_POWERPC_602:
return "602";
case CPU_SUBTYPE_POWERPC_603:
return "603";
case CPU_SUBTYPE_POWERPC_603e:
return "603e";
case CPU_SUBTYPE_POWERPC_603ev:
return "603ev";
case CPU_SUBTYPE_POWERPC_604:
return "604";
case CPU_SUBTYPE_POWERPC_604e:
return "604e";
case CPU_SUBTYPE_POWERPC_620:
return "620";
case CPU_SUBTYPE_POWERPC_750:
return "750";
case CPU_SUBTYPE_POWERPC_7400:
return "7400";
case CPU_SUBTYPE_POWERPC_7450:
return "7450";
case CPU_SUBTYPE_POWERPC_970:
return "970";
default:;
}
return "generic";
}
#elif defined(__linux__) && defined(__powerpc__)
StringRef sys::getHostCPUName() {
std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
StringRef Content = P ? P->getBuffer() : "";
return detail::getHostCPUNameForPowerPC(Content);
}
#elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__))
StringRef sys::getHostCPUName() {
std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
StringRef Content = P ? P->getBuffer() : "";
return detail::getHostCPUNameForARM(Content);
}
#elif defined(__linux__) && defined(__s390x__)
StringRef sys::getHostCPUName() {
std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
StringRef Content = P ? P->getBuffer() : "";
return detail::getHostCPUNameForS390x(Content);
}
#elif defined(__MVS__)
StringRef sys::getHostCPUName() {
int *StartToCVTOffset = reinterpret_cast<int *>(0x10);
int ReadValue = *StartToCVTOffset;
ReadValue = (ReadValue & 0x7FFFFFFF);
char *CVT = reinterpret_cast<char *>(ReadValue);
uint16_t Id = *(uint16_t *)&CVT[-6];
Id = decodePackedBCD<uint16_t>(Id, false);
bool HaveVectorSupport = CVT[244] & 0x80;
return getCPUNameFromS390Model(Id, HaveVectorSupport);
}
#elif defined(__APPLE__) && (defined(__arm__) || defined(__aarch64__))
#define CPUFAMILY_ARM_SWIFT …
#define CPUFAMILY_ARM_CYCLONE …
#define CPUFAMILY_ARM_TYPHOON …
#define CPUFAMILY_ARM_TWISTER …
#define CPUFAMILY_ARM_HURRICANE …
#define CPUFAMILY_ARM_MONSOON_MISTRAL …
#define CPUFAMILY_ARM_VORTEX_TEMPEST …
#define CPUFAMILY_ARM_LIGHTNING_THUNDER …
#define CPUFAMILY_ARM_FIRESTORM_ICESTORM …
#define CPUFAMILY_ARM_BLIZZARD_AVALANCHE …
#define CPUFAMILY_ARM_EVEREST_SAWTOOTH …
StringRef sys::getHostCPUName() {
uint32_t Family;
size_t Length = sizeof(Family);
sysctlbyname("hw.cpufamily", &Family, &Length, NULL, 0);
switch (Family) {
case CPUFAMILY_ARM_SWIFT:
return "swift";
case CPUFAMILY_ARM_CYCLONE:
return "apple-a7";
case CPUFAMILY_ARM_TYPHOON:
return "apple-a8";
case CPUFAMILY_ARM_TWISTER:
return "apple-a9";
case CPUFAMILY_ARM_HURRICANE:
return "apple-a10";
case CPUFAMILY_ARM_MONSOON_MISTRAL:
return "apple-a11";
case CPUFAMILY_ARM_VORTEX_TEMPEST:
return "apple-a12";
case CPUFAMILY_ARM_LIGHTNING_THUNDER:
return "apple-a13";
case CPUFAMILY_ARM_FIRESTORM_ICESTORM:
return "apple-m1";
case CPUFAMILY_ARM_BLIZZARD_AVALANCHE:
return "apple-m2";
case CPUFAMILY_ARM_EVEREST_SAWTOOTH:
return "apple-m3";
default:
return "apple-m3";
}
}
#elif defined(_AIX)
StringRef sys::getHostCPUName() {
switch (_system_configuration.implementation) {
case POWER_4:
if (_system_configuration.version == PV_4_3)
return "970";
return "pwr4";
case POWER_5:
if (_system_configuration.version == PV_5)
return "pwr5";
return "pwr5x";
case POWER_6:
if (_system_configuration.version == PV_6_Compat)
return "pwr6";
return "pwr6x";
case POWER_7:
return "pwr7";
case POWER_8:
return "pwr8";
case POWER_9:
return "pwr9";
#ifdef POWER_10
case POWER_10:
#else
case 0x40000:
#endif
return "pwr10";
#ifdef POWER_11
case POWER_11:
#else
case 0x80000:
#endif
return "pwr11";
default:
return "generic";
}
}
#elif defined(__loongarch__)
StringRef sys::getHostCPUName() {
uint32_t processor_id;
__asm__("cpucfg %[prid], $zero\n\t" : [prid] "=r"(processor_id));
switch (processor_id & 0xf000) {
case 0xc000:
return "la464";
case 0xd000:
return "la664";
default:
break;
}
return "generic";
}
#elif defined(__riscv)
StringRef sys::getHostCPUName() {
#if defined(__linux__)
std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
StringRef Content = P ? P->getBuffer() : "";
StringRef Name = detail::getHostCPUNameForRISCV(Content);
if (!Name.empty())
return Name;
#endif
#if __riscv_xlen == 64
return "generic-rv64";
#elif __riscv_xlen == 32
return "generic-rv32";
#else
#error "Unhandled value of __riscv_xlen"
#endif
}
#elif defined(__sparc__)
#if defined(__linux__)
StringRef sys::detail::getHostCPUNameForSPARC(StringRef ProcCpuinfoContent) {
SmallVector<StringRef> Lines;
ProcCpuinfoContent.split(Lines, "\n");
StringRef Cpu;
for (unsigned I = 0, E = Lines.size(); I != E; ++I) {
if (Lines[I].starts_with("cpu")) {
Cpu = Lines[I].substr(5).ltrim("\t :");
break;
}
}
return StringSwitch<const char *>(Cpu)
.StartsWith("SuperSparc", "supersparc")
.StartsWith("HyperSparc", "hypersparc")
.StartsWith("SpitFire", "ultrasparc")
.StartsWith("BlackBird", "ultrasparc")
.StartsWith("Sabre", " ultrasparc")
.StartsWith("Hummingbird", "ultrasparc")
.StartsWith("Cheetah", "ultrasparc3")
.StartsWith("Jalapeno", "ultrasparc3")
.StartsWith("Jaguar", "ultrasparc3")
.StartsWith("Panther", "ultrasparc3")
.StartsWith("Serrano", "ultrasparc3")
.StartsWith("UltraSparc T1", "niagara")
.StartsWith("UltraSparc T2", "niagara2")
.StartsWith("UltraSparc T3", "niagara3")
.StartsWith("UltraSparc T4", "niagara4")
.StartsWith("UltraSparc T5", "niagara4")
.StartsWith("LEON", "leon3")
.StartsWith("SPARC-M7", "niagara4" )
.StartsWith("SPARC-S7", "niagara4" )
.StartsWith("SPARC-M8", "niagara4" )
.Default("generic");
}
#endif
StringRef sys::getHostCPUName() {
#if defined(__linux__)
std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
StringRef Content = P ? P->getBuffer() : "";
return detail::getHostCPUNameForSPARC(Content);
#elif defined(__sun__) && defined(__svr4__)
char *buf = NULL;
kstat_ctl_t *kc;
kstat_t *ksp;
kstat_named_t *brand = NULL;
kc = kstat_open();
if (kc != NULL) {
ksp = kstat_lookup(kc, const_cast<char *>("cpu_info"), -1, NULL);
if (ksp != NULL && kstat_read(kc, ksp, NULL) != -1 &&
ksp->ks_type == KSTAT_TYPE_NAMED)
brand =
(kstat_named_t *)kstat_data_lookup(ksp, const_cast<char *>("brand"));
if (brand != NULL && brand->data_type == KSTAT_DATA_STRING)
buf = KSTAT_NAMED_STR_PTR(brand);
}
kstat_close(kc);
return StringSwitch<const char *>(buf)
.Case("TMS390S10", "supersparc")
.Case("TMS390Z50", "supersparc")
.Case("TMS390Z55",
"supersparc")
.Case("MB86904", "supersparc")
.Case("MB86907", "supersparc")
.Case("RT623", "hypersparc")
.Case("RT625", "hypersparc")
.Case("RT626", "hypersparc")
.Case("UltraSPARC-I", "ultrasparc")
.Case("UltraSPARC-II", "ultrasparc")
.Case("UltraSPARC-IIe", "ultrasparc")
.Case("UltraSPARC-IIi", "ultrasparc")
.Case("SPARC64-III", "ultrasparc")
.Case("SPARC64-IV", "ultrasparc")
.Case("UltraSPARC-III", "ultrasparc3")
.Case("UltraSPARC-III+", "ultrasparc3")
.Case("UltraSPARC-IIIi", "ultrasparc3")
.Case("UltraSPARC-IIIi+", "ultrasparc3")
.Case("UltraSPARC-IV", "ultrasparc3")
.Case("UltraSPARC-IV+", "ultrasparc3")
.Case("SPARC64-V", "ultrasparc3")
.Case("SPARC64-VI", "ultrasparc3")
.Case("SPARC64-VII", "ultrasparc3")
.Case("UltraSPARC-T1", "niagara")
.Case("UltraSPARC-T2", "niagara2")
.Case("UltraSPARC-T2", "niagara2")
.Case("UltraSPARC-T2+", "niagara2")
.Case("SPARC-T3", "niagara3")
.Case("SPARC-T4", "niagara4")
.Case("SPARC-T5", "niagara4")
.Case("SPARC-M7", "niagara4" )
.Case("SPARC-S7", "niagara4" )
.Case("SPARC-M8", "niagara4" )
.Default("generic");
#else
return "generic";
#endif
}
#else
StringRef sys::getHostCPUName() { return "generic"; }
namespace llvm {
namespace sys {
namespace detail {
namespace x86 {
VendorSignatures getVendorSignature(unsigned *MaxLeaf) {
return VendorSignatures::UNKNOWN;
}
}
}
}
}
#endif
#if defined(__i386__) || defined(_M_IX86) || \
defined(__x86_64__) || defined(_M_X64)
const StringMap<bool> sys::getHostCPUFeatures() { … }
#elif defined(__linux__) && (defined(__arm__) || defined(__aarch64__))
const StringMap<bool> sys::getHostCPUFeatures() {
StringMap<bool> Features;
std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent();
if (!P)
return Features;
SmallVector<StringRef, 32> Lines;
P->getBuffer().split(Lines, "\n");
SmallVector<StringRef, 32> CPUFeatures;
for (unsigned I = 0, E = Lines.size(); I != E; ++I)
if (Lines[I].starts_with("Features")) {
Lines[I].split(CPUFeatures, ' ');
break;
}
#if defined(__aarch64__)
enum { CAP_AES = 0x1, CAP_PMULL = 0x2, CAP_SHA1 = 0x4, CAP_SHA2 = 0x8 };
uint32_t crypto = 0;
#endif
for (unsigned I = 0, E = CPUFeatures.size(); I != E; ++I) {
StringRef LLVMFeatureStr = StringSwitch<StringRef>(CPUFeatures[I])
#if defined(__aarch64__)
.Case("asimd", "neon")
.Case("fp", "fp-armv8")
.Case("crc32", "crc")
.Case("atomics", "lse")
.Case("sve", "sve")
.Case("sve2", "sve2")
#else
.Case("half", "fp16")
.Case("neon", "neon")
.Case("vfpv3", "vfp3")
.Case("vfpv3d16", "vfp3d16")
.Case("vfpv4", "vfp4")
.Case("idiva", "hwdiv-arm")
.Case("idivt", "hwdiv")
#endif
.Default("");
#if defined(__aarch64__)
if (CPUFeatures[I] == "aes")
crypto |= CAP_AES;
else if (CPUFeatures[I] == "pmull")
crypto |= CAP_PMULL;
else if (CPUFeatures[I] == "sha1")
crypto |= CAP_SHA1;
else if (CPUFeatures[I] == "sha2")
crypto |= CAP_SHA2;
#endif
if (LLVMFeatureStr != "")
Features[LLVMFeatureStr] = true;
}
#if defined(__aarch64__)
if (crypto == (CAP_AES | CAP_PMULL | CAP_SHA1 | CAP_SHA2))
Features["crypto"] = true;
#endif
return Features;
}
#elif defined(_WIN32) && (defined(__aarch64__) || defined(_M_ARM64))
const StringMap<bool> sys::getHostCPUFeatures() {
StringMap<bool> Features;
if (IsProcessorFeaturePresent(PF_ARM_NEON_INSTRUCTIONS_AVAILABLE))
Features["neon"] = true;
if (IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE))
Features["crc"] = true;
if (IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE))
Features["crypto"] = true;
return Features;
}
#elif defined(__linux__) && defined(__loongarch__)
#include <sys/auxv.h>
const StringMap<bool> sys::getHostCPUFeatures() {
unsigned long hwcap = getauxval(AT_HWCAP);
bool HasFPU = hwcap & (1UL << 3);
uint32_t cpucfg2 = 0x2;
__asm__("cpucfg %[cpucfg2], %[cpucfg2]\n\t" : [cpucfg2] "+r"(cpucfg2));
StringMap<bool> Features;
Features["f"] = HasFPU && (cpucfg2 & (1U << 1));
Features["d"] = HasFPU && (cpucfg2 & (1U << 2));
Features["lsx"] = hwcap & (1UL << 4);
Features["lasx"] = hwcap & (1UL << 5);
Features["lvz"] = hwcap & (1UL << 9);
return Features;
}
#elif defined(__linux__) && defined(__riscv)
struct RISCVHwProbe {
int64_t Key;
uint64_t Value;
};
const StringMap<bool> sys::getHostCPUFeatures() {
RISCVHwProbe Query[]{{3, 0},
{4, 0}};
int Ret = syscall(258, Query,
std::size(Query), 0,
0, 0);
if (Ret != 0)
return {};
StringMap<bool> Features;
uint64_t BaseMask = Query[0].Value;
if (BaseMask & 1) {
Features["i"] = true;
Features["m"] = true;
Features["a"] = true;
}
uint64_t ExtMask = Query[1].Value;
Features["f"] = ExtMask & (1 << 0);
Features["d"] = ExtMask & (1 << 0);
Features["c"] = ExtMask & (1 << 1);
Features["v"] = ExtMask & (1 << 2);
Features["zba"] = ExtMask & (1 << 3);
Features["zbb"] = ExtMask & (1 << 4);
Features["zbs"] = ExtMask & (1 << 5);
Features["zicboz"] = ExtMask & (1 << 6);
Features["zbc"] = ExtMask & (1 << 7);
Features["zbkb"] = ExtMask & (1 << 8);
Features["zbkc"] = ExtMask & (1 << 9);
Features["zbkx"] = ExtMask & (1 << 10);
Features["zknd"] = ExtMask & (1 << 11);
Features["zkne"] = ExtMask & (1 << 12);
Features["zknh"] = ExtMask & (1 << 13);
Features["zksed"] = ExtMask & (1 << 14);
Features["zksh"] = ExtMask & (1 << 15);
Features["zkt"] = ExtMask & (1 << 16);
Features["zvbb"] = ExtMask & (1 << 17);
Features["zvbc"] = ExtMask & (1 << 18);
Features["zvkb"] = ExtMask & (1 << 19);
Features["zvkg"] = ExtMask & (1 << 20);
Features["zvkned"] = ExtMask & (1 << 21);
Features["zvknha"] = ExtMask & (1 << 22);
Features["zvknhb"] = ExtMask & (1 << 23);
Features["zvksed"] = ExtMask & (1 << 24);
Features["zvksh"] = ExtMask & (1 << 25);
Features["zvkt"] = ExtMask & (1 << 26);
Features["zfh"] = ExtMask & (1 << 27);
Features["zfhmin"] = ExtMask & (1 << 28);
Features["zihintntl"] = ExtMask & (1 << 29);
Features["zvfh"] = ExtMask & (1 << 30);
Features["zvfhmin"] = ExtMask & (1ULL << 31);
Features["zfa"] = ExtMask & (1ULL << 32);
Features["ztso"] = ExtMask & (1ULL << 33);
Features["zicond"] = ExtMask & (1ULL << 35);
Features["zihintpause"] =
ExtMask & (1ULL << 36);
return Features;
}
#else
const StringMap<bool> sys::getHostCPUFeatures() { return {}; }
#endif
#if __APPLE__
static Triple withHostArch(Triple T) {
#if defined(__arm__)
T.setArch(Triple::arm);
T.setArchName("arm");
#elif defined(__arm64e__)
T.setArch(Triple::aarch64, Triple::AArch64SubArch_arm64e);
T.setArchName("arm64e");
#elif defined(__aarch64__)
T.setArch(Triple::aarch64);
T.setArchName("arm64");
#elif defined(__x86_64h__)
T.setArch(Triple::x86_64);
T.setArchName("x86_64h");
#elif defined(__x86_64__)
T.setArch(Triple::x86_64);
T.setArchName("x86_64");
#elif defined(__i386__)
T.setArch(Triple::x86);
T.setArchName("i386");
#elif defined(__powerpc__)
T.setArch(Triple::ppc);
T.setArchName("powerpc");
#else
# error "Unimplemented host arch fixup"
#endif
return T;
}
#endif
std::string sys::getProcessTriple() { … }
void sys::printDefaultTargetAndDetectedCPU(raw_ostream &OS) { … }