1 //========- unittests/Support/Host.cpp - Host.cpp tests --------------========//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Support/Host.h"
10 #include "llvm/ADT/SmallVector.h"
11 #include "llvm/ADT/Triple.h"
12 #include "llvm/Config/config.h"
13 #include "llvm/Support/FileSystem.h"
14 #include "llvm/Support/Path.h"
15 #include "llvm/Support/Program.h"
16 #include "llvm/Support/Threading.h"
18 #include "gtest/gtest.h"
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()); \
33 class HostTest
: public testing::Test
{
37 bool isSupportedArchAndOS() {
38 // Initially this is only testing detection of the number of
39 // physical cores, which is currently only supported/tested on
41 return (Host
.isOSWindows() && llvm_is_multithreaded()) ||
42 Host
.isOSDarwin() || (Host
.isX86() && Host
.isOSLinux()) ||
43 (Host
.isOSLinux() && !Host
.isAndroid()) ||
44 (Host
.isSystemZ() && Host
.isOSzOS());
47 HostTest() : Host(Triple::normalize(sys::getProcessTriple())) {}
50 TEST_F(HostTest
, NumPhysicalCoresSupported
) {
51 if (!isSupportedArchAndOS())
53 int Num
= sys::getHostNumPhysicalCores();
57 TEST_F(HostTest
, NumPhysicalCoresUnsupported
) {
58 if (isSupportedArchAndOS())
60 int Num
= sys::getHostNumPhysicalCores();
64 TEST(getLinuxHostCPUName
, ARM
) {
65 StringRef CortexA9ProcCpuinfo
= R
"(
67 model name : ARMv7 Processor rev 10 (v7l)
69 Features : half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpd32
70 CPU implementer : 0x41
77 model name : ARMv7 Processor rev 10 (v7l)
79 Features : half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpd32
80 CPU implementer : 0x41
86 Hardware : Generic OMAP4 (Flattened Device Tree)
88 Serial : 0000000000000000
91 EXPECT_EQ(sys::detail::getHostCPUNameForARM(CortexA9ProcCpuinfo
),
93 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n"
96 // Verify that both CPU implementer and CPU part are checked:
97 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x40\n"
100 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n"
105 TEST(getLinuxHostCPUName
, AArch64
) {
106 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n"
110 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n"
113 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n"
116 // Verify that both CPU implementer and CPU part are checked:
117 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x40\n"
120 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n"
123 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n"
126 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n"
129 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n"
132 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n"
136 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0xc0\n"
140 // MSM8992/4 weirdness
141 StringRef MSM8992ProcCpuInfo
= R
"(
142 Processor : AArch64 Processor rev 3 (aarch64)
149 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
150 CPU implementer : 0x41
156 Hardware : Qualcomm Technologies, Inc MSM8992
159 EXPECT_EQ(sys::detail::getHostCPUNameForARM(MSM8992ProcCpuInfo
),
162 // Exynos big.LITTLE weirdness
163 const std::string ExynosProcCpuInfo
= R
"(
165 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
166 CPU implementer : 0x41
172 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
173 CPU implementer : 0x53
177 // Verify default for Exynos.
178 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo
+
179 "CPU variant : 0xc\n"
183 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo
+
184 "CPU variant : 0x1\n"
188 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo
+
189 "CPU variant : 0x1\n"
193 const std::string ThunderX2T99ProcCpuInfo
= R
"(
196 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics
197 CPU implementer : 0x43
203 // Verify different versions of ThunderX2T99.
204 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
205 "CPU implementer : 0x42\n"
209 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
210 "CPU implementer : 0x42\n"
211 "CPU part : 0x0516"),
214 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
215 "CPU implementer : 0x43\n"
219 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
220 "CPU implementer : 0x43\n"
221 "CPU part : 0x0516"),
224 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
225 "CPU implementer : 0x42\n"
229 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
230 "CPU implementer : 0x42\n"
234 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
235 "CPU implementer : 0x43\n"
239 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
240 "CPU implementer : 0x43\n"
244 // Verify ThunderXT88.
245 const std::string ThunderXT88ProcCpuInfo
= R
"(
248 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
249 CPU implementer : 0x43
255 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderXT88ProcCpuInfo
+
256 "CPU implementer : 0x43\n"
260 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderXT88ProcCpuInfo
+
261 "CPU implementer : 0x43\n"
265 // Verify HiSilicon processors.
266 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x48\n"
271 const std::string A64FXProcCpuInfo
= R
"(
274 Features : fp asimd evtstrm sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm fcma dcpop sve
275 CPU implementer : 0x46
281 EXPECT_EQ(sys::detail::getHostCPUNameForARM(A64FXProcCpuInfo
), "a64fx");
283 // Verify Nvidia Carmel.
284 const std::string CarmelProcCpuInfo
= R
"(
286 model name : ARMv8 Processor rev 0 (v8l)
288 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm dcpop
289 CPU implementer : 0x4e
296 EXPECT_EQ(sys::detail::getHostCPUNameForARM(CarmelProcCpuInfo
), "carmel");
298 // Snapdragon mixed implementer quirk
299 const std::string Snapdragon865ProcCPUInfo
= R
"(
302 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp
303 CPU implementer : 0x51
315 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp
316 CPU implementer : 0x41
322 EXPECT_EQ(sys::detail::getHostCPUNameForARM(Snapdragon865ProcCPUInfo
), "cortex-a77");
325 TEST(getLinuxHostCPUName
, s390x
) {
326 SmallVector
<std::string
> ModelIDs(
327 {"3931", "8561", "3906", "2964", "2827", "2817", "2097", "2064"});
328 SmallVector
<std::string
> VectorSupport({"", "vx"});
329 SmallVector
<StringRef
> ExpectedCPUs
;
332 ExpectedCPUs
.push_back("zEC12");
333 ExpectedCPUs
.push_back("z16");
336 ExpectedCPUs
.push_back("zEC12");
337 ExpectedCPUs
.push_back("z15");
340 ExpectedCPUs
.push_back("zEC12");
341 ExpectedCPUs
.push_back("z14");
344 ExpectedCPUs
.push_back("zEC12");
345 ExpectedCPUs
.push_back("z13");
348 ExpectedCPUs
.push_back("zEC12");
349 ExpectedCPUs
.push_back("zEC12");
352 ExpectedCPUs
.push_back("z196");
353 ExpectedCPUs
.push_back("z196");
356 ExpectedCPUs
.push_back("z10");
357 ExpectedCPUs
.push_back("z10");
360 ExpectedCPUs
.push_back("generic");
361 ExpectedCPUs
.push_back("generic");
363 const std::string DummyBaseVectorInfo
=
364 "features : esan3 zarch stfle msa ldisp eimm dfp edat etf3eh highgprs "
366 const std::string DummyBaseMachineInfo
=
367 "processor 0: version = FF, identification = 059C88, machine = ";
370 for (size_t I
= 0; I
< ModelIDs
.size(); I
++) {
371 for (size_t J
= 0; J
< VectorSupport
.size(); J
++) {
372 const std::string DummyCPUInfo
= DummyBaseVectorInfo
+ VectorSupport
[J
] +
373 "\n" + DummyBaseMachineInfo
+
375 EXPECT_EQ(sys::detail::getHostCPUNameForS390x(DummyCPUInfo
),
376 ExpectedCPUs
[CheckIndex
++]);
381 TEST(getLinuxHostCPUName
, RISCV
) {
382 const StringRef SifiveU74MCProcCPUInfo
= R
"(
387 uarch : sifive,u74-mc
389 EXPECT_EQ(sys::detail::getHostCPUNameForRISCV(SifiveU74MCProcCPUInfo
),
392 sys::detail::getHostCPUNameForRISCV("uarch : sifive,bullet0\n"),
396 static bool runAndGetCommandOutput(
397 const char *ExePath
, ArrayRef
<llvm::StringRef
> argv
,
398 std::unique_ptr
<char[]> &Buffer
, off_t
&Size
) {
399 bool Success
= false;
400 [ExePath
, argv
, &Buffer
, &Size
, &Success
] {
401 using namespace llvm::sys
;
402 SmallString
<128> TestDirectory
;
403 ASSERT_NO_ERROR(fs::createUniqueDirectory("host_test", TestDirectory
));
405 SmallString
<128> OutputFile(TestDirectory
);
406 path::append(OutputFile
, "out");
407 StringRef OutputPath
= OutputFile
.str();
409 const Optional
<StringRef
> Redirects
[] = {
410 /*STDIN=*/None
, /*STDOUT=*/OutputPath
, /*STDERR=*/None
};
411 int RetCode
= ExecuteAndWait(ExePath
, argv
, /*env=*/llvm::None
, Redirects
);
412 ASSERT_EQ(0, RetCode
);
415 ASSERT_NO_ERROR(fs::openFileForRead(OutputPath
, FD
));
416 Size
= ::lseek(FD
, 0, SEEK_END
);
418 ::lseek(FD
, 0, SEEK_SET
);
419 Buffer
= std::make_unique
<char[]>(Size
);
420 ASSERT_EQ(::read(FD
, Buffer
.get(), Size
), Size
);
423 ASSERT_NO_ERROR(fs::remove(OutputPath
));
424 ASSERT_NO_ERROR(fs::remove(TestDirectory
.str()));
430 TEST_F(HostTest
, DummyRunAndGetCommandOutputUse
) {
431 // Suppress defined-but-not-used warnings when the tests using the helper are
433 (void)&runAndGetCommandOutput
;
436 TEST_F(HostTest
, getMacOSHostVersion
) {
437 llvm::Triple
HostTriple(llvm::sys::getProcessTriple());
438 if (!HostTriple
.isMacOSX())
441 const char *SwVersPath
= "/usr/bin/sw_vers";
442 StringRef argv
[] = {SwVersPath
, "-productVersion"};
443 std::unique_ptr
<char[]> Buffer
;
445 ASSERT_EQ(runAndGetCommandOutput(SwVersPath
, argv
, Buffer
, Size
), true);
446 StringRef SystemVersionStr
= StringRef(Buffer
.get(), Size
).rtrim();
448 // Ensure that the two versions match.
449 VersionTuple SystemVersion
;
450 ASSERT_EQ(llvm::Triple((Twine("x86_64-apple-macos") + SystemVersionStr
))
451 .getMacOSXVersion(SystemVersion
),
453 VersionTuple HostVersion
;
454 ASSERT_EQ(HostTriple
.getMacOSXVersion(HostVersion
), true);
456 if (SystemVersion
.getMajor() > 10) {
457 // Don't compare the 'Minor' and 'Micro' versions, as they're always '0' for
458 // the 'Darwin' triples on 11.x.
459 ASSERT_EQ(SystemVersion
.getMajor(), HostVersion
.getMajor());
461 // Don't compare the 'Micro' version, as it's always '0' for the 'Darwin'
463 ASSERT_EQ(SystemVersion
.getMajor(), HostVersion
.getMajor());
464 ASSERT_EQ(SystemVersion
.getMinor(), HostVersion
.getMinor());
468 // Helper to return AIX system version. Must return void to use ASSERT_*.
469 static void getAIXSystemVersion(VersionTuple
&SystemVersion
) {
470 const char *ExePath
= "/usr/bin/oslevel";
471 StringRef argv
[] = {ExePath
};
472 std::unique_ptr
<char[]> Buffer
;
474 ASSERT_EQ(runAndGetCommandOutput(ExePath
, argv
, Buffer
, Size
), true);
475 StringRef SystemVersionStr
= StringRef(Buffer
.get(), Size
).rtrim();
478 llvm::Triple((Twine("powerpc-ibm-aix") + SystemVersionStr
))
482 TEST_F(HostTest
, AIXHostVersionDetect
) {
483 llvm::Triple
HostTriple(llvm::sys::getProcessTriple());
484 if (HostTriple
.getOS() != Triple::AIX
)
487 llvm::Triple
ConfiguredHostTriple(LLVM_HOST_TRIPLE
);
488 ASSERT_EQ(ConfiguredHostTriple
.getOS(), Triple::AIX
);
490 VersionTuple SystemVersion
;
491 getAIXSystemVersion(SystemVersion
);
493 // Ensure that the host triple version (major) and release (minor) numbers,
494 // unless explicitly configured, match with those of the current system.
495 auto SysMajor
= SystemVersion
.getMajor();
496 auto SysMinor
= SystemVersion
.getMinor();
497 VersionTuple HostVersion
= HostTriple
.getOSVersion();
498 if (ConfiguredHostTriple
.getOSMajorVersion()) {
499 // Explicitly configured, force a match. We do it this way so the
500 // asserts are always executed.
501 SysMajor
= HostVersion
.getMajor();
502 SysMinor
= HostVersion
.getMinor();
504 ASSERT_EQ(SysMajor
, HostVersion
.getMajor());
505 ASSERT_EQ(SysMinor
, HostVersion
.getMinor());
508 TEST_F(HostTest
, AIXTargetVersionDetect
) {
509 llvm::Triple
TargetTriple(llvm::sys::getDefaultTargetTriple());
510 if (TargetTriple
.getOS() != Triple::AIX
)
513 // Ensure that the target triple version (major) and release (minor) numbers
514 // match with those of the current system.
515 llvm::Triple
ConfiguredTargetTriple(LLVM_DEFAULT_TARGET_TRIPLE
);
516 if (ConfiguredTargetTriple
.getOSMajorVersion())
517 GTEST_SKIP(); // The version was configured explicitly; skip.
519 VersionTuple SystemVersion
;
520 getAIXSystemVersion(SystemVersion
);
521 VersionTuple TargetVersion
= TargetTriple
.getOSVersion();
522 ASSERT_EQ(SystemVersion
.getMajor(), TargetVersion
.getMajor());
523 ASSERT_EQ(SystemVersion
.getMinor(), TargetVersion
.getMinor());
526 TEST_F(HostTest
, AIXHostCPUDetect
) {
527 llvm::Triple
HostTriple(llvm::sys::getProcessTriple());
528 if (HostTriple
.getOS() != Triple::AIX
)
531 // Return a value based on the current processor implementation mode.
532 const char *ExePath
= "/usr/sbin/getsystype";
533 StringRef argv
[] = {ExePath
, "-i"};
534 std::unique_ptr
<char[]> Buffer
;
536 ASSERT_EQ(runAndGetCommandOutput(ExePath
, argv
, Buffer
, Size
), true);
537 StringRef
CPU(Buffer
.get(), Size
);
538 StringRef MCPU
= StringSwitch
<const char *>(CPU
)
539 .Case("POWER 4\n", "pwr4")
540 .Case("POWER 5\n", "pwr5")
541 .Case("POWER 6\n", "pwr6")
542 .Case("POWER 7\n", "pwr7")
543 .Case("POWER 8\n", "pwr8")
544 .Case("POWER 9\n", "pwr9")
545 .Case("POWER 10\n", "pwr10")
548 StringRef HostCPU
= sys::getHostCPUName();
550 // Just do the comparison on the base implementation mode.
551 if (HostCPU
== "970")
552 HostCPU
= StringRef("pwr4");
554 HostCPU
= HostCPU
.rtrim('x');
556 EXPECT_EQ(HostCPU
, MCPU
);