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/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"
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 TEST(getLinuxHostCPUName
, ARM
) {
34 StringRef CortexA9ProcCpuinfo
= R
"(
36 model name : ARMv7 Processor rev 10 (v7l)
38 Features : half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpd32
39 CPU implementer : 0x41
46 model name : ARMv7 Processor rev 10 (v7l)
48 Features : half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpd32
49 CPU implementer : 0x41
55 Hardware : Generic OMAP4 (Flattened Device Tree)
57 Serial : 0000000000000000
60 EXPECT_EQ(sys::detail::getHostCPUNameForARM(CortexA9ProcCpuinfo
),
62 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n"
65 // Verify that both CPU implementer and CPU part are checked:
66 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x40\n"
69 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n"
74 TEST(getLinuxHostCPUName
, AArch64
) {
75 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n"
78 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n"
82 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n"
85 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n"
88 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n"
91 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n"
94 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n"
97 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n"
100 // Verify that both CPU implementer and CPU part are checked:
101 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x40\n"
104 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n"
107 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n"
110 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n"
113 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n"
116 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n"
119 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n"
122 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n"
125 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n"
128 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x6d\n"
131 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0xc0\n"
134 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0xc0\n"
137 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0xc0\n"
140 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n"
143 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x46\n"
146 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x61\n"
150 // MSM8992/4 weirdness
151 StringRef MSM8992ProcCpuInfo
= R
"(
152 Processor : AArch64 Processor rev 3 (aarch64)
159 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
160 CPU implementer : 0x41
166 Hardware : Qualcomm Technologies, Inc MSM8992
169 EXPECT_EQ(sys::detail::getHostCPUNameForARM(MSM8992ProcCpuInfo
),
172 // Exynos big.LITTLE weirdness
173 const std::string ExynosProcCpuInfo
= R
"(
175 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
176 CPU implementer : 0x41
182 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
183 CPU implementer : 0x53
187 // Verify default for Exynos.
188 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo
+
189 "CPU variant : 0xc\n"
193 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo
+
194 "CPU variant : 0x1\n"
198 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo
+
199 "CPU variant : 0x1\n"
203 const std::string ThunderX2T99ProcCpuInfo
= R
"(
206 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics
207 CPU implementer : 0x43
213 // Verify different versions of ThunderX2T99.
214 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
215 "CPU implementer : 0x42\n"
219 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
220 "CPU implementer : 0x42\n"
221 "CPU part : 0x0516"),
224 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
225 "CPU implementer : 0x43\n"
229 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
230 "CPU implementer : 0x43\n"
231 "CPU part : 0x0516"),
234 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
235 "CPU implementer : 0x42\n"
239 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
240 "CPU implementer : 0x42\n"
244 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
245 "CPU implementer : 0x43\n"
249 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
250 "CPU implementer : 0x43\n"
254 // Verify ThunderXT88.
255 const std::string ThunderXT88ProcCpuInfo
= R
"(
258 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
259 CPU implementer : 0x43
265 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderXT88ProcCpuInfo
+
266 "CPU implementer : 0x43\n"
270 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderXT88ProcCpuInfo
+
271 "CPU implementer : 0x43\n"
275 // Verify HiSilicon processors.
276 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x48\n"
281 const std::string A64FXProcCpuInfo
= R
"(
284 Features : fp asimd evtstrm sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm fcma dcpop sve
285 CPU implementer : 0x46
291 EXPECT_EQ(sys::detail::getHostCPUNameForARM(A64FXProcCpuInfo
), "a64fx");
293 // Verify Nvidia Carmel.
294 const std::string CarmelProcCpuInfo
= R
"(
296 model name : ARMv8 Processor rev 0 (v8l)
298 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm dcpop
299 CPU implementer : 0x4e
306 EXPECT_EQ(sys::detail::getHostCPUNameForARM(CarmelProcCpuInfo
), "carmel");
308 // Snapdragon mixed implementer quirk
309 const std::string Snapdragon865ProcCPUInfo
= R
"(
312 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp
313 CPU implementer : 0x51
325 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp
326 CPU implementer : 0x41
332 EXPECT_EQ(sys::detail::getHostCPUNameForARM(Snapdragon865ProcCPUInfo
), "cortex-a77");
335 TEST(getLinuxHostCPUName
, s390x
) {
336 SmallVector
<std::string
> ModelIDs(
337 {"3931", "8561", "3906", "2964", "2827", "2817", "2097", "2064"});
338 SmallVector
<std::string
> VectorSupport({"", "vx"});
339 SmallVector
<StringRef
> ExpectedCPUs
;
342 ExpectedCPUs
.push_back("zEC12");
343 ExpectedCPUs
.push_back("z16");
346 ExpectedCPUs
.push_back("zEC12");
347 ExpectedCPUs
.push_back("z15");
350 ExpectedCPUs
.push_back("zEC12");
351 ExpectedCPUs
.push_back("z14");
354 ExpectedCPUs
.push_back("zEC12");
355 ExpectedCPUs
.push_back("z13");
358 ExpectedCPUs
.push_back("zEC12");
359 ExpectedCPUs
.push_back("zEC12");
362 ExpectedCPUs
.push_back("z196");
363 ExpectedCPUs
.push_back("z196");
366 ExpectedCPUs
.push_back("z10");
367 ExpectedCPUs
.push_back("z10");
370 ExpectedCPUs
.push_back("generic");
371 ExpectedCPUs
.push_back("generic");
373 const std::string DummyBaseVectorInfo
=
374 "features : esan3 zarch stfle msa ldisp eimm dfp edat etf3eh highgprs "
376 const std::string DummyBaseMachineInfo
=
377 "processor 0: version = FF, identification = 059C88, machine = ";
380 for (size_t I
= 0; I
< ModelIDs
.size(); I
++) {
381 for (size_t J
= 0; J
< VectorSupport
.size(); J
++) {
382 const std::string DummyCPUInfo
= DummyBaseVectorInfo
+ VectorSupport
[J
] +
383 "\n" + DummyBaseMachineInfo
+
385 EXPECT_EQ(sys::detail::getHostCPUNameForS390x(DummyCPUInfo
),
386 ExpectedCPUs
[CheckIndex
++]);
391 TEST(getLinuxHostCPUName
, RISCV
) {
392 const StringRef SifiveU74MCProcCPUInfo
= R
"(
397 uarch : sifive,u74-mc
399 EXPECT_EQ(sys::detail::getHostCPUNameForRISCV(SifiveU74MCProcCPUInfo
),
402 sys::detail::getHostCPUNameForRISCV("uarch : sifive,bullet0\n"),
406 static bool runAndGetCommandOutput(
407 const char *ExePath
, ArrayRef
<llvm::StringRef
> argv
,
408 std::unique_ptr
<char[]> &Buffer
, off_t
&Size
) {
409 bool Success
= false;
410 [ExePath
, argv
, &Buffer
, &Size
, &Success
] {
411 using namespace llvm::sys
;
412 SmallString
<128> TestDirectory
;
413 ASSERT_NO_ERROR(fs::createUniqueDirectory("host_test", TestDirectory
));
415 SmallString
<128> OutputFile(TestDirectory
);
416 path::append(OutputFile
, "out");
417 StringRef OutputPath
= OutputFile
.str();
419 const std::optional
<StringRef
> Redirects
[] = {
420 /*STDIN=*/std::nullopt
, /*STDOUT=*/OutputPath
, /*STDERR=*/std::nullopt
};
422 ExecuteAndWait(ExePath
, argv
, /*env=*/std::nullopt
, Redirects
);
423 ASSERT_EQ(0, RetCode
);
426 ASSERT_NO_ERROR(fs::openFileForRead(OutputPath
, FD
));
427 Size
= ::lseek(FD
, 0, SEEK_END
);
429 ::lseek(FD
, 0, SEEK_SET
);
430 Buffer
= std::make_unique
<char[]>(Size
);
431 ASSERT_EQ(::read(FD
, Buffer
.get(), Size
), Size
);
434 ASSERT_NO_ERROR(fs::remove(OutputPath
));
435 ASSERT_NO_ERROR(fs::remove(TestDirectory
.str()));
441 TEST(HostTest
, DummyRunAndGetCommandOutputUse
) {
442 // Suppress defined-but-not-used warnings when the tests using the helper are
444 (void)&runAndGetCommandOutput
;
447 TEST(HostTest
, getMacOSHostVersion
) {
448 llvm::Triple
HostTriple(llvm::sys::getProcessTriple());
449 if (!HostTriple
.isMacOSX())
452 const char *SwVersPath
= "/usr/bin/sw_vers";
453 StringRef argv
[] = {SwVersPath
, "-productVersion"};
454 std::unique_ptr
<char[]> Buffer
;
456 ASSERT_EQ(runAndGetCommandOutput(SwVersPath
, argv
, Buffer
, Size
), true);
457 StringRef SystemVersionStr
= StringRef(Buffer
.get(), Size
).rtrim();
459 // Ensure that the two versions match.
460 VersionTuple SystemVersion
;
461 ASSERT_EQ(llvm::Triple((Twine("x86_64-apple-macos") + SystemVersionStr
))
462 .getMacOSXVersion(SystemVersion
),
464 VersionTuple HostVersion
;
465 ASSERT_EQ(HostTriple
.getMacOSXVersion(HostVersion
), true);
467 if (SystemVersion
.getMajor() > 10) {
468 // Don't compare the 'Minor' and 'Micro' versions, as they're always '0' for
469 // the 'Darwin' triples on 11.x.
470 ASSERT_EQ(SystemVersion
.getMajor(), HostVersion
.getMajor());
472 // Don't compare the 'Micro' version, as it's always '0' for the 'Darwin'
474 ASSERT_EQ(SystemVersion
.getMajor(), HostVersion
.getMajor());
475 ASSERT_EQ(SystemVersion
.getMinor(), HostVersion
.getMinor());
479 // Helper to return AIX system version. Must return void to use ASSERT_*.
480 static void getAIXSystemVersion(VersionTuple
&SystemVersion
) {
481 const char *ExePath
= "/usr/bin/oslevel";
482 StringRef argv
[] = {ExePath
};
483 std::unique_ptr
<char[]> Buffer
;
485 ASSERT_EQ(runAndGetCommandOutput(ExePath
, argv
, Buffer
, Size
), true);
486 StringRef SystemVersionStr
= StringRef(Buffer
.get(), Size
).rtrim();
489 llvm::Triple((Twine("powerpc-ibm-aix") + SystemVersionStr
))
493 TEST(HostTest
, AIXHostVersionDetect
) {
494 llvm::Triple
HostTriple(llvm::sys::getProcessTriple());
495 if (HostTriple
.getOS() != Triple::AIX
)
498 llvm::Triple
ConfiguredHostTriple(LLVM_HOST_TRIPLE
);
499 ASSERT_EQ(ConfiguredHostTriple
.getOS(), Triple::AIX
);
501 VersionTuple SystemVersion
;
502 getAIXSystemVersion(SystemVersion
);
504 // Ensure that the host triple version (major) and release (minor) numbers,
505 // unless explicitly configured, match with those of the current system.
506 auto SysMajor
= SystemVersion
.getMajor();
507 auto SysMinor
= SystemVersion
.getMinor();
508 VersionTuple HostVersion
= HostTriple
.getOSVersion();
509 if (ConfiguredHostTriple
.getOSMajorVersion()) {
510 // Explicitly configured, force a match. We do it this way so the
511 // asserts are always executed.
512 SysMajor
= HostVersion
.getMajor();
513 SysMinor
= HostVersion
.getMinor();
515 ASSERT_EQ(SysMajor
, HostVersion
.getMajor());
516 ASSERT_EQ(SysMinor
, HostVersion
.getMinor());
519 TEST(HostTest
, AIXTargetVersionDetect
) {
520 llvm::Triple
TargetTriple(llvm::sys::getDefaultTargetTriple());
521 if (TargetTriple
.getOS() != Triple::AIX
)
524 // Ensure that the target triple version (major) and release (minor) numbers
525 // match with those of the current system.
526 llvm::Triple
ConfiguredTargetTriple(LLVM_DEFAULT_TARGET_TRIPLE
);
527 if (ConfiguredTargetTriple
.getOSMajorVersion())
528 GTEST_SKIP(); // The version was configured explicitly; skip.
530 VersionTuple SystemVersion
;
531 getAIXSystemVersion(SystemVersion
);
532 VersionTuple TargetVersion
= TargetTriple
.getOSVersion();
533 ASSERT_EQ(SystemVersion
.getMajor(), TargetVersion
.getMajor());
534 ASSERT_EQ(SystemVersion
.getMinor(), TargetVersion
.getMinor());
537 TEST(HostTest
, AIXHostCPUDetect
) {
538 llvm::Triple
HostTriple(llvm::sys::getProcessTriple());
539 if (HostTriple
.getOS() != Triple::AIX
)
542 // Return a value based on the current processor implementation mode.
543 const char *ExePath
= "/usr/sbin/getsystype";
544 StringRef argv
[] = {ExePath
, "-i"};
545 std::unique_ptr
<char[]> Buffer
;
547 ASSERT_EQ(runAndGetCommandOutput(ExePath
, argv
, Buffer
, Size
), true);
548 StringRef
CPU(Buffer
.get(), Size
);
549 StringRef MCPU
= StringSwitch
<const char *>(CPU
)
550 .Case("POWER 4\n", "pwr4")
551 .Case("POWER 5\n", "pwr5")
552 .Case("POWER 6\n", "pwr6")
553 .Case("POWER 7\n", "pwr7")
554 .Case("POWER 8\n", "pwr8")
555 .Case("POWER 9\n", "pwr9")
556 .Case("POWER 10\n", "pwr10")
557 .Case("POWER 11\n", "pwr11")
560 StringRef HostCPU
= sys::getHostCPUName();
562 // Just do the comparison on the base implementation mode.
563 if (HostCPU
== "970")
564 HostCPU
= StringRef("pwr4");
566 HostCPU
= HostCPU
.rtrim('x');
568 EXPECT_EQ(HostCPU
, MCPU
);