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/Config/llvm-config.h"
11 #include "llvm/ADT/SmallVector.h"
12 #include "llvm/ADT/Triple.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
.isPPC64() && Host
.isOSLinux()) ||
44 (Host
.isSystemZ() && (Host
.isOSLinux() || Host
.isOSzOS()));
47 HostTest() : Host(Triple::normalize(sys::getProcessTriple())) {}
50 TEST_F(HostTest
, NumPhysicalCores
) {
51 int Num
= sys::getHostNumPhysicalCores();
53 if (isSupportedArchAndOS())
59 TEST(getLinuxHostCPUName
, ARM
) {
60 StringRef CortexA9ProcCpuinfo
= R
"(
62 model name : ARMv7 Processor rev 10 (v7l)
64 Features : half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpd32
65 CPU implementer : 0x41
72 model name : ARMv7 Processor rev 10 (v7l)
74 Features : half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpd32
75 CPU implementer : 0x41
81 Hardware : Generic OMAP4 (Flattened Device Tree)
83 Serial : 0000000000000000
86 EXPECT_EQ(sys::detail::getHostCPUNameForARM(CortexA9ProcCpuinfo
),
88 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n"
91 // Verify that both CPU implementer and CPU part are checked:
92 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x40\n"
95 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n"
100 TEST(getLinuxHostCPUName
, AArch64
) {
101 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n"
105 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n"
108 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n"
111 // Verify that both CPU implementer and CPU part are checked:
112 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x40\n"
115 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n"
118 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n"
121 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n"
124 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n"
127 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n"
131 // MSM8992/4 weirdness
132 StringRef MSM8992ProcCpuInfo
= R
"(
133 Processor : AArch64 Processor rev 3 (aarch64)
140 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
141 CPU implementer : 0x41
147 Hardware : Qualcomm Technologies, Inc MSM8992
150 EXPECT_EQ(sys::detail::getHostCPUNameForARM(MSM8992ProcCpuInfo
),
153 // Exynos big.LITTLE weirdness
154 const std::string ExynosProcCpuInfo
= R
"(
156 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
157 CPU implementer : 0x41
163 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
164 CPU implementer : 0x53
168 // Verify default for Exynos.
169 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo
+
170 "CPU variant : 0xc\n"
174 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo
+
175 "CPU variant : 0x1\n"
179 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo
+
180 "CPU variant : 0x1\n"
184 const std::string ThunderX2T99ProcCpuInfo
= R
"(
187 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics
188 CPU implementer : 0x43
194 // Verify different versions of ThunderX2T99.
195 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
196 "CPU implementer : 0x42\n"
200 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
201 "CPU implementer : 0x42\n"
202 "CPU part : 0x0516"),
205 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
206 "CPU implementer : 0x43\n"
210 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
211 "CPU implementer : 0x43\n"
212 "CPU part : 0x0516"),
215 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
216 "CPU implementer : 0x42\n"
220 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
221 "CPU implementer : 0x42\n"
225 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
226 "CPU implementer : 0x43\n"
230 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
231 "CPU implementer : 0x43\n"
235 // Verify ThunderXT88.
236 const std::string ThunderXT88ProcCpuInfo
= R
"(
239 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
240 CPU implementer : 0x43
246 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderXT88ProcCpuInfo
+
247 "CPU implementer : 0x43\n"
251 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderXT88ProcCpuInfo
+
252 "CPU implementer : 0x43\n"
256 // Verify HiSilicon processors.
257 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x48\n"
262 const std::string A64FXProcCpuInfo
= R
"(
265 Features : fp asimd evtstrm sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm fcma dcpop sve
266 CPU implementer : 0x46
272 EXPECT_EQ(sys::detail::getHostCPUNameForARM(A64FXProcCpuInfo
), "a64fx");
274 // Verify Nvidia Carmel.
275 const std::string CarmelProcCpuInfo
= R
"(
277 model name : ARMv8 Processor rev 0 (v8l)
279 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm dcpop
280 CPU implementer : 0x4e
287 EXPECT_EQ(sys::detail::getHostCPUNameForARM(CarmelProcCpuInfo
), "carmel");
289 // Snapdragon mixed implementer quirk
290 const std::string Snapdragon865ProcCPUInfo
= R
"(
293 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp
294 CPU implementer : 0x51
306 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp
307 CPU implementer : 0x41
313 EXPECT_EQ(sys::detail::getHostCPUNameForARM(Snapdragon865ProcCPUInfo
), "cortex-a77");
316 TEST(getLinuxHostCPUName
, s390x
) {
317 SmallVector
<std::string
> ModelIDs(
318 {"3931", "8561", "3906", "2964", "2827", "2817", "2097", "2064"});
319 SmallVector
<std::string
> VectorSupport({"", "vx"});
320 SmallVector
<StringRef
> ExpectedCPUs
;
323 ExpectedCPUs
.push_back("zEC12");
324 ExpectedCPUs
.push_back("arch14");
327 ExpectedCPUs
.push_back("zEC12");
328 ExpectedCPUs
.push_back("z15");
331 ExpectedCPUs
.push_back("zEC12");
332 ExpectedCPUs
.push_back("z14");
335 ExpectedCPUs
.push_back("zEC12");
336 ExpectedCPUs
.push_back("z13");
339 ExpectedCPUs
.push_back("zEC12");
340 ExpectedCPUs
.push_back("zEC12");
343 ExpectedCPUs
.push_back("z196");
344 ExpectedCPUs
.push_back("z196");
347 ExpectedCPUs
.push_back("z10");
348 ExpectedCPUs
.push_back("z10");
351 ExpectedCPUs
.push_back("generic");
352 ExpectedCPUs
.push_back("generic");
354 const std::string DummyBaseVectorInfo
=
355 "features : esan3 zarch stfle msa ldisp eimm dfp edat etf3eh highgprs "
357 const std::string DummyBaseMachineInfo
=
358 "processor 0: version = FF, identification = 059C88, machine = ";
361 for (size_t I
= 0; I
< ModelIDs
.size(); I
++) {
362 for (size_t J
= 0; J
< VectorSupport
.size(); J
++) {
363 const std::string DummyCPUInfo
= DummyBaseVectorInfo
+ VectorSupport
[J
] +
364 "\n" + DummyBaseMachineInfo
+
366 EXPECT_EQ(sys::detail::getHostCPUNameForS390x(DummyCPUInfo
),
367 ExpectedCPUs
[CheckIndex
++]);
372 static bool runAndGetCommandOutput(
373 const char *ExePath
, ArrayRef
<llvm::StringRef
> argv
,
374 std::unique_ptr
<char[]> &Buffer
, off_t
&Size
) {
375 bool Success
= false;
376 [ExePath
, argv
, &Buffer
, &Size
, &Success
] {
377 using namespace llvm::sys
;
378 SmallString
<128> TestDirectory
;
379 ASSERT_NO_ERROR(fs::createUniqueDirectory("host_test", TestDirectory
));
381 SmallString
<128> OutputFile(TestDirectory
);
382 path::append(OutputFile
, "out");
383 StringRef OutputPath
= OutputFile
.str();
385 const Optional
<StringRef
> Redirects
[] = {
386 /*STDIN=*/None
, /*STDOUT=*/OutputPath
, /*STDERR=*/None
};
387 int RetCode
= ExecuteAndWait(ExePath
, argv
, /*env=*/llvm::None
, Redirects
);
388 ASSERT_EQ(0, RetCode
);
391 ASSERT_NO_ERROR(fs::openFileForRead(OutputPath
, FD
));
392 Size
= ::lseek(FD
, 0, SEEK_END
);
394 ::lseek(FD
, 0, SEEK_SET
);
395 Buffer
= std::make_unique
<char[]>(Size
);
396 ASSERT_EQ(::read(FD
, Buffer
.get(), Size
), Size
);
399 ASSERT_NO_ERROR(fs::remove(OutputPath
));
400 ASSERT_NO_ERROR(fs::remove(TestDirectory
.str()));
406 TEST_F(HostTest
, DummyRunAndGetCommandOutputUse
) {
407 // Suppress defined-but-not-used warnings when the tests using the helper are
409 (void)&runAndGetCommandOutput
;
412 TEST_F(HostTest
, getMacOSHostVersion
) {
413 llvm::Triple
HostTriple(llvm::sys::getProcessTriple());
414 if (!HostTriple
.isMacOSX())
417 const char *SwVersPath
= "/usr/bin/sw_vers";
418 StringRef argv
[] = {SwVersPath
, "-productVersion"};
419 std::unique_ptr
<char[]> Buffer
;
421 ASSERT_EQ(runAndGetCommandOutput(SwVersPath
, argv
, Buffer
, Size
), true);
422 StringRef SystemVersionStr
= StringRef(Buffer
.get(), Size
).rtrim();
424 // Ensure that the two versions match.
425 VersionTuple SystemVersion
;
426 ASSERT_EQ(llvm::Triple((Twine("x86_64-apple-macos") + SystemVersionStr
))
427 .getMacOSXVersion(SystemVersion
),
429 VersionTuple HostVersion
;
430 ASSERT_EQ(HostTriple
.getMacOSXVersion(HostVersion
), true);
432 if (SystemVersion
.getMajor() > 10) {
433 // Don't compare the 'Minor' and 'Micro' versions, as they're always '0' for
434 // the 'Darwin' triples on 11.x.
435 ASSERT_EQ(SystemVersion
.getMajor(), HostVersion
.getMajor());
437 // Don't compare the 'Micro' version, as it's always '0' for the 'Darwin'
439 ASSERT_EQ(SystemVersion
.getMajor(), HostVersion
.getMajor());
440 ASSERT_EQ(SystemVersion
.getMinor(), HostVersion
.getMinor());
444 TEST_F(HostTest
, AIXVersionDetect
) {
445 llvm::Triple
HostTriple(llvm::sys::getProcessTriple());
446 if (HostTriple
.getOS() != Triple::AIX
)
449 llvm::Triple
ConfiguredHostTriple(LLVM_HOST_TRIPLE
);
450 ASSERT_EQ(ConfiguredHostTriple
.getOS(), Triple::AIX
);
452 const char *ExePath
= "/usr/bin/oslevel";
453 StringRef argv
[] = {ExePath
};
454 std::unique_ptr
<char[]> Buffer
;
456 ASSERT_EQ(runAndGetCommandOutput(ExePath
, argv
, Buffer
, Size
), true);
457 StringRef SystemVersionStr
= StringRef(Buffer
.get(), Size
).rtrim();
459 VersionTuple SystemVersion
=
460 llvm::Triple((Twine("powerpc-ibm-aix") + SystemVersionStr
))
463 // Ensure that the host triple version (major) and release (minor) numbers,
464 // unless explicitly configured, match with those of the current system.
465 if (!ConfiguredHostTriple
.getOSMajorVersion()) {
466 VersionTuple HostVersion
= HostTriple
.getOSVersion();
467 ASSERT_EQ(SystemVersion
.getMajor(), HostVersion
.getMajor());
468 ASSERT_EQ(SystemVersion
.getMinor(), HostVersion
.getMinor());
471 llvm::Triple
TargetTriple(llvm::sys::getDefaultTargetTriple());
472 if (TargetTriple
.getOS() != Triple::AIX
)
475 // Ensure that the target triple version (major) and release (minor) numbers
476 // match with those of the current system.
477 llvm::Triple
ConfiguredTargetTriple(LLVM_DEFAULT_TARGET_TRIPLE
);
478 if (ConfiguredTargetTriple
.getOSMajorVersion())
479 return; // The version was configured explicitly; skip.
481 VersionTuple TargetVersion
= TargetTriple
.getOSVersion();
482 ASSERT_EQ(SystemVersion
.getMajor(), TargetVersion
.getMajor());
483 ASSERT_EQ(SystemVersion
.getMinor(), TargetVersion
.getMinor());
486 TEST_F(HostTest
, AIXHostCPUDetect
) {
487 llvm::Triple
HostTriple(llvm::sys::getProcessTriple());
488 if (HostTriple
.getOS() != Triple::AIX
)
491 // Return a value based on the current processor implementation mode.
492 const char *ExePath
= "/usr/sbin/getsystype";
493 StringRef argv
[] = {ExePath
, "-i"};
494 std::unique_ptr
<char[]> Buffer
;
496 ASSERT_EQ(runAndGetCommandOutput(ExePath
, argv
, Buffer
, Size
), true);
497 StringRef
CPU(Buffer
.get(), Size
);
498 StringRef MCPU
= StringSwitch
<const char *>(CPU
)
499 .Case("POWER 4\n", "pwr4")
500 .Case("POWER 5\n", "pwr5")
501 .Case("POWER 6\n", "pwr6")
502 .Case("POWER 7\n", "pwr7")
503 .Case("POWER 8\n", "pwr8")
504 .Case("POWER 9\n", "pwr9")
505 .Case("POWER 10\n", "pwr10")
508 StringRef HostCPU
= sys::getHostCPUName();
510 // Just do the comparison on the base implementation mode.
511 if (HostCPU
== "970")
512 HostCPU
= StringRef("pwr4");
514 HostCPU
= HostCPU
.rtrim('x');
516 EXPECT_EQ(HostCPU
, MCPU
);