1 //========- unittests/Support/Host.cpp - Host.cpp tests --------------========// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/TargetParser/Host.h" 10 #include "llvm/ADT/SmallVector.h" 11 #include "llvm/Config/config.h" 12 #include "llvm/Support/FileSystem.h" 13 #include "llvm/Support/Path.h" 14 #include "llvm/Support/Program.h" 15 #include "llvm/Support/Threading.h" 16 #include "llvm/TargetParser/Triple.h" 17 18 #include "gtest/gtest.h" 19 20 #define ASSERT_NO_ERROR(x) \ 21 if (std::error_code ASSERT_NO_ERROR_ec = x) { \ 22 SmallString<128> MessageStorage; \ 23 raw_svector_ostream Message(MessageStorage); \ 24 Message << #x ": did not return errc::success.\n" \ 25 << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \ 26 << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \ 27 GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \ 28 } else { \ 29 } 30 31 using namespace llvm; 32 33 TEST(getLinuxHostCPUName, ARM) { 34 StringRef CortexA9ProcCpuinfo = R"( 35 processor : 0 36 model name : ARMv7 Processor rev 10 (v7l) 37 BogoMIPS : 1393.66 38 Features : half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpd32 39 CPU implementer : 0x41 40 CPU architecture: 7 41 CPU variant : 0x2 42 CPU part : 0xc09 43 CPU revision : 10 44 45 processor : 1 46 model name : ARMv7 Processor rev 10 (v7l) 47 BogoMIPS : 1393.66 48 Features : half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpd32 49 CPU implementer : 0x41 50 CPU architecture: 7 51 CPU variant : 0x2 52 CPU part : 0xc09 53 CPU revision : 10 54 55 Hardware : Generic OMAP4 (Flattened Device Tree) 56 Revision : 0000 57 Serial : 0000000000000000 58 )"; 59 60 EXPECT_EQ(sys::detail::getHostCPUNameForARM(CortexA9ProcCpuinfo), 61 "cortex-a9"); 62 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n" 63 "CPU part : 0xc0f"), 64 "cortex-a15"); 65 // Verify that both CPU implementer and CPU part are checked: 66 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x40\n" 67 "CPU part : 0xc0f"), 68 "generic"); 69 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n" 70 "CPU part : 0x06f"), 71 "krait"); 72 } 73 74 TEST(getLinuxHostCPUName, AArch64) { 75 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n" 76 "CPU part : 0xd03"), 77 "cortex-a53"); 78 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n" 79 "CPU part : 0xd05"), 80 "cortex-a55"); 81 82 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n" 83 "CPU part : 0xd40"), 84 "neoverse-v1"); 85 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n" 86 "CPU part : 0xd0c"), 87 "neoverse-n1"); 88 // Verify that both CPU implementer and CPU part are checked: 89 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x40\n" 90 "CPU part : 0xd03"), 91 "generic"); 92 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n" 93 "CPU part : 0x201"), 94 "kryo"); 95 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n" 96 "CPU part : 0x800"), 97 "cortex-a73"); 98 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n" 99 "CPU part : 0x801"), 100 "cortex-a73"); 101 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n" 102 "CPU part : 0xd46"), 103 "cortex-a510"); 104 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n" 105 "CPU part : 0xd47"), 106 "cortex-a710"); 107 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n" 108 "CPU part : 0xd48"), 109 "cortex-x2"); 110 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n" 111 "CPU part : 0xc00"), 112 "falkor"); 113 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n" 114 "CPU part : 0xc01"), 115 "saphira"); 116 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x6d\n" 117 "CPU part : 0xd49"), 118 "neoverse-n2"); 119 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0xc0\n" 120 "CPU part : 0xac3"), 121 "ampere1"); 122 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0xc0\n" 123 "CPU part : 0xac4"), 124 "ampere1a"); 125 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0xc0\n" 126 "CPU part : 0xac5"), 127 "ampere1b"); 128 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n" 129 "CPU part : 0x001"), 130 "oryon-1"); 131 132 // MSM8992/4 weirdness 133 StringRef MSM8992ProcCpuInfo = R"( 134 Processor : AArch64 Processor rev 3 (aarch64) 135 processor : 0 136 processor : 1 137 processor : 2 138 processor : 3 139 processor : 4 140 processor : 5 141 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 142 CPU implementer : 0x41 143 CPU architecture: 8 144 CPU variant : 0x0 145 CPU part : 0xd03 146 CPU revision : 3 147 148 Hardware : Qualcomm Technologies, Inc MSM8992 149 )"; 150 151 EXPECT_EQ(sys::detail::getHostCPUNameForARM(MSM8992ProcCpuInfo), 152 "cortex-a53"); 153 154 // Exynos big.LITTLE weirdness 155 const std::string ExynosProcCpuInfo = R"( 156 processor : 0 157 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 158 CPU implementer : 0x41 159 CPU architecture: 8 160 CPU variant : 0x0 161 CPU part : 0xd05 162 163 processor : 1 164 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 165 CPU implementer : 0x53 166 CPU architecture: 8 167 )"; 168 169 // Verify default for Exynos. 170 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo + 171 "CPU variant : 0xc\n" 172 "CPU part : 0xafe"), 173 "exynos-m3"); 174 // Verify Exynos M3. 175 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo + 176 "CPU variant : 0x1\n" 177 "CPU part : 0x002"), 178 "exynos-m3"); 179 // Verify Exynos M4. 180 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo + 181 "CPU variant : 0x1\n" 182 "CPU part : 0x003"), 183 "exynos-m4"); 184 185 const std::string ThunderX2T99ProcCpuInfo = R"( 186 processor : 0 187 BogoMIPS : 400.00 188 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics 189 CPU implementer : 0x43 190 CPU architecture: 8 191 CPU variant : 0x1 192 CPU part : 0x0af 193 )"; 194 195 // Verify different versions of ThunderX2T99. 196 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo + 197 "CPU implementer : 0x42\n" 198 "CPU part : 0x516"), 199 "thunderx2t99"); 200 201 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo + 202 "CPU implementer : 0x42\n" 203 "CPU part : 0x0516"), 204 "thunderx2t99"); 205 206 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo + 207 "CPU implementer : 0x43\n" 208 "CPU part : 0x516"), 209 "thunderx2t99"); 210 211 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo + 212 "CPU implementer : 0x43\n" 213 "CPU part : 0x0516"), 214 "thunderx2t99"); 215 216 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo + 217 "CPU implementer : 0x42\n" 218 "CPU part : 0xaf"), 219 "thunderx2t99"); 220 221 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo + 222 "CPU implementer : 0x42\n" 223 "CPU part : 0x0af"), 224 "thunderx2t99"); 225 226 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo + 227 "CPU implementer : 0x43\n" 228 "CPU part : 0xaf"), 229 "thunderx2t99"); 230 231 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo + 232 "CPU implementer : 0x43\n" 233 "CPU part : 0x0af"), 234 "thunderx2t99"); 235 236 // Verify ThunderXT88. 237 const std::string ThunderXT88ProcCpuInfo = R"( 238 processor : 0 239 BogoMIPS : 200.00 240 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 241 CPU implementer : 0x43 242 CPU architecture: 8 243 CPU variant : 0x1 244 CPU part : 0x0a1 245 )"; 246 247 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderXT88ProcCpuInfo + 248 "CPU implementer : 0x43\n" 249 "CPU part : 0x0a1"), 250 "thunderxt88"); 251 252 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderXT88ProcCpuInfo + 253 "CPU implementer : 0x43\n" 254 "CPU part : 0xa1"), 255 "thunderxt88"); 256 257 // Verify HiSilicon processors. 258 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x48\n" 259 "CPU part : 0xd01"), 260 "tsv110"); 261 262 // Verify A64FX. 263 const std::string A64FXProcCpuInfo = R"( 264 processor : 0 265 BogoMIPS : 200.00 266 Features : fp asimd evtstrm sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm fcma dcpop sve 267 CPU implementer : 0x46 268 CPU architecture: 8 269 CPU variant : 0x1 270 CPU part : 0x001 271 )"; 272 273 EXPECT_EQ(sys::detail::getHostCPUNameForARM(A64FXProcCpuInfo), "a64fx"); 274 275 // Verify Nvidia Carmel. 276 const std::string CarmelProcCpuInfo = R"( 277 processor : 0 278 model name : ARMv8 Processor rev 0 (v8l) 279 BogoMIPS : 62.50 280 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm dcpop 281 CPU implementer : 0x4e 282 CPU architecture: 8 283 CPU variant : 0x0 284 CPU part : 0x004 285 CPU revision : 0 286 )"; 287 288 EXPECT_EQ(sys::detail::getHostCPUNameForARM(CarmelProcCpuInfo), "carmel"); 289 290 // Snapdragon mixed implementer quirk 291 const std::string Snapdragon865ProcCPUInfo = R"( 292 processor : 0 293 BogoMIPS : 38.40 294 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp 295 CPU implementer : 0x51 296 CPU architecture: 8 297 CPU variant : 0xd 298 CPU part : 0x805 299 CPU revision : 14 300 processor : 1 301 processor : 2 302 processor : 3 303 processor : 4 304 processor : 5 305 processor : 6 306 BogoMIPS : 38.40 307 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp 308 CPU implementer : 0x41 309 CPU architecture: 8 310 CPU variant : 0x1 311 CPU part : 0xd0d 312 CPU revision : 0 313 )"; 314 EXPECT_EQ(sys::detail::getHostCPUNameForARM(Snapdragon865ProcCPUInfo), "cortex-a77"); 315 } 316 317 TEST(getLinuxHostCPUName, s390x) { 318 SmallVector<std::string> ModelIDs( 319 {"3931", "8561", "3906", "2964", "2827", "2817", "2097", "2064"}); 320 SmallVector<std::string> VectorSupport({"", "vx"}); 321 SmallVector<StringRef> ExpectedCPUs; 322 323 // Model Id: 3931 324 ExpectedCPUs.push_back("zEC12"); 325 ExpectedCPUs.push_back("z16"); 326 327 // Model Id: 8561 328 ExpectedCPUs.push_back("zEC12"); 329 ExpectedCPUs.push_back("z15"); 330 331 // Model Id: 3906 332 ExpectedCPUs.push_back("zEC12"); 333 ExpectedCPUs.push_back("z14"); 334 335 // Model Id: 2964 336 ExpectedCPUs.push_back("zEC12"); 337 ExpectedCPUs.push_back("z13"); 338 339 // Model Id: 2827 340 ExpectedCPUs.push_back("zEC12"); 341 ExpectedCPUs.push_back("zEC12"); 342 343 // Model Id: 2817 344 ExpectedCPUs.push_back("z196"); 345 ExpectedCPUs.push_back("z196"); 346 347 // Model Id: 2097 348 ExpectedCPUs.push_back("z10"); 349 ExpectedCPUs.push_back("z10"); 350 351 // Model Id: 2064 352 ExpectedCPUs.push_back("generic"); 353 ExpectedCPUs.push_back("generic"); 354 355 const std::string DummyBaseVectorInfo = 356 "features : esan3 zarch stfle msa ldisp eimm dfp edat etf3eh highgprs " 357 "te "; 358 const std::string DummyBaseMachineInfo = 359 "processor 0: version = FF, identification = 059C88, machine = "; 360 361 int CheckIndex = 0; 362 for (size_t I = 0; I < ModelIDs.size(); I++) { 363 for (size_t J = 0; J < VectorSupport.size(); J++) { 364 const std::string DummyCPUInfo = DummyBaseVectorInfo + VectorSupport[J] + 365 "\n" + DummyBaseMachineInfo + 366 ModelIDs[I]; 367 EXPECT_EQ(sys::detail::getHostCPUNameForS390x(DummyCPUInfo), 368 ExpectedCPUs[CheckIndex++]); 369 } 370 } 371 } 372 373 TEST(getLinuxHostCPUName, RISCV) { 374 const StringRef SifiveU74MCProcCPUInfo = R"( 375 processor : 0 376 hart : 2 377 isa : rv64imafdc 378 mmu : sv39 379 uarch : sifive,u74-mc 380 )"; 381 EXPECT_EQ(sys::detail::getHostCPUNameForRISCV(SifiveU74MCProcCPUInfo), 382 "sifive-u74"); 383 EXPECT_EQ( 384 sys::detail::getHostCPUNameForRISCV("uarch : sifive,bullet0\n"), 385 "sifive-u74"); 386 } 387 388 static bool runAndGetCommandOutput( 389 const char *ExePath, ArrayRef<llvm::StringRef> argv, 390 std::unique_ptr<char[]> &Buffer, off_t &Size) { 391 bool Success = false; 392 [ExePath, argv, &Buffer, &Size, &Success] { 393 using namespace llvm::sys; 394 SmallString<128> TestDirectory; 395 ASSERT_NO_ERROR(fs::createUniqueDirectory("host_test", TestDirectory)); 396 397 SmallString<128> OutputFile(TestDirectory); 398 path::append(OutputFile, "out"); 399 StringRef OutputPath = OutputFile.str(); 400 401 const std::optional<StringRef> Redirects[] = { 402 /*STDIN=*/std::nullopt, /*STDOUT=*/OutputPath, /*STDERR=*/std::nullopt}; 403 int RetCode = 404 ExecuteAndWait(ExePath, argv, /*env=*/std::nullopt, Redirects); 405 ASSERT_EQ(0, RetCode); 406 407 int FD = 0; 408 ASSERT_NO_ERROR(fs::openFileForRead(OutputPath, FD)); 409 Size = ::lseek(FD, 0, SEEK_END); 410 ASSERT_NE(-1, Size); 411 ::lseek(FD, 0, SEEK_SET); 412 Buffer = std::make_unique<char[]>(Size); 413 ASSERT_EQ(::read(FD, Buffer.get(), Size), Size); 414 ::close(FD); 415 416 ASSERT_NO_ERROR(fs::remove(OutputPath)); 417 ASSERT_NO_ERROR(fs::remove(TestDirectory.str())); 418 Success = true; 419 }(); 420 return Success; 421 } 422 423 TEST(HostTest, DummyRunAndGetCommandOutputUse) { 424 // Suppress defined-but-not-used warnings when the tests using the helper are 425 // disabled. 426 (void)&runAndGetCommandOutput; 427 } 428 429 TEST(HostTest, getMacOSHostVersion) { 430 llvm::Triple HostTriple(llvm::sys::getProcessTriple()); 431 if (!HostTriple.isMacOSX()) 432 GTEST_SKIP(); 433 434 const char *SwVersPath = "/usr/bin/sw_vers"; 435 StringRef argv[] = {SwVersPath, "-productVersion"}; 436 std::unique_ptr<char[]> Buffer; 437 off_t Size; 438 ASSERT_EQ(runAndGetCommandOutput(SwVersPath, argv, Buffer, Size), true); 439 StringRef SystemVersionStr = StringRef(Buffer.get(), Size).rtrim(); 440 441 // Ensure that the two versions match. 442 VersionTuple SystemVersion; 443 ASSERT_EQ(llvm::Triple((Twine("x86_64-apple-macos") + SystemVersionStr)) 444 .getMacOSXVersion(SystemVersion), 445 true); 446 VersionTuple HostVersion; 447 ASSERT_EQ(HostTriple.getMacOSXVersion(HostVersion), true); 448 449 if (SystemVersion.getMajor() > 10) { 450 // Don't compare the 'Minor' and 'Micro' versions, as they're always '0' for 451 // the 'Darwin' triples on 11.x. 452 ASSERT_EQ(SystemVersion.getMajor(), HostVersion.getMajor()); 453 } else { 454 // Don't compare the 'Micro' version, as it's always '0' for the 'Darwin' 455 // triples. 456 ASSERT_EQ(SystemVersion.getMajor(), HostVersion.getMajor()); 457 ASSERT_EQ(SystemVersion.getMinor(), HostVersion.getMinor()); 458 } 459 } 460 461 // Helper to return AIX system version. Must return void to use ASSERT_*. 462 static void getAIXSystemVersion(VersionTuple &SystemVersion) { 463 const char *ExePath = "/usr/bin/oslevel"; 464 StringRef argv[] = {ExePath}; 465 std::unique_ptr<char[]> Buffer; 466 off_t Size; 467 ASSERT_EQ(runAndGetCommandOutput(ExePath, argv, Buffer, Size), true); 468 StringRef SystemVersionStr = StringRef(Buffer.get(), Size).rtrim(); 469 470 SystemVersion = 471 llvm::Triple((Twine("powerpc-ibm-aix") + SystemVersionStr)) 472 .getOSVersion(); 473 } 474 475 TEST(HostTest, AIXHostVersionDetect) { 476 llvm::Triple HostTriple(llvm::sys::getProcessTriple()); 477 if (HostTriple.getOS() != Triple::AIX) 478 GTEST_SKIP(); 479 480 llvm::Triple ConfiguredHostTriple(LLVM_HOST_TRIPLE); 481 ASSERT_EQ(ConfiguredHostTriple.getOS(), Triple::AIX); 482 483 VersionTuple SystemVersion; 484 getAIXSystemVersion(SystemVersion); 485 486 // Ensure that the host triple version (major) and release (minor) numbers, 487 // unless explicitly configured, match with those of the current system. 488 auto SysMajor = SystemVersion.getMajor(); 489 auto SysMinor = SystemVersion.getMinor(); 490 VersionTuple HostVersion = HostTriple.getOSVersion(); 491 if (ConfiguredHostTriple.getOSMajorVersion()) { 492 // Explicitly configured, force a match. We do it this way so the 493 // asserts are always executed. 494 SysMajor = HostVersion.getMajor(); 495 SysMinor = HostVersion.getMinor(); 496 } 497 ASSERT_EQ(SysMajor, HostVersion.getMajor()); 498 ASSERT_EQ(SysMinor, HostVersion.getMinor()); 499 } 500 501 TEST(HostTest, AIXTargetVersionDetect) { 502 llvm::Triple TargetTriple(llvm::sys::getDefaultTargetTriple()); 503 if (TargetTriple.getOS() != Triple::AIX) 504 GTEST_SKIP(); 505 506 // Ensure that the target triple version (major) and release (minor) numbers 507 // match with those of the current system. 508 llvm::Triple ConfiguredTargetTriple(LLVM_DEFAULT_TARGET_TRIPLE); 509 if (ConfiguredTargetTriple.getOSMajorVersion()) 510 GTEST_SKIP(); // The version was configured explicitly; skip. 511 512 VersionTuple SystemVersion; 513 getAIXSystemVersion(SystemVersion); 514 VersionTuple TargetVersion = TargetTriple.getOSVersion(); 515 ASSERT_EQ(SystemVersion.getMajor(), TargetVersion.getMajor()); 516 ASSERT_EQ(SystemVersion.getMinor(), TargetVersion.getMinor()); 517 } 518 519 TEST(HostTest, AIXHostCPUDetect) { 520 llvm::Triple HostTriple(llvm::sys::getProcessTriple()); 521 if (HostTriple.getOS() != Triple::AIX) 522 GTEST_SKIP(); 523 524 // Return a value based on the current processor implementation mode. 525 const char *ExePath = "/usr/sbin/getsystype"; 526 StringRef argv[] = {ExePath, "-i"}; 527 std::unique_ptr<char[]> Buffer; 528 off_t Size; 529 ASSERT_EQ(runAndGetCommandOutput(ExePath, argv, Buffer, Size), true); 530 StringRef CPU(Buffer.get(), Size); 531 StringRef MCPU = StringSwitch<const char *>(CPU) 532 .Case("POWER 4\n", "pwr4") 533 .Case("POWER 5\n", "pwr5") 534 .Case("POWER 6\n", "pwr6") 535 .Case("POWER 7\n", "pwr7") 536 .Case("POWER 8\n", "pwr8") 537 .Case("POWER 9\n", "pwr9") 538 .Case("POWER 10\n", "pwr10") 539 .Default("unknown"); 540 541 StringRef HostCPU = sys::getHostCPUName(); 542 543 // Just do the comparison on the base implementation mode. 544 if (HostCPU == "970") 545 HostCPU = StringRef("pwr4"); 546 else 547 HostCPU = HostCPU.rtrim('x'); 548 549 EXPECT_EQ(HostCPU, MCPU); 550 } 551