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"
144 // MSM8992/4 weirdness
145 StringRef MSM8992ProcCpuInfo
= R
"(
146 Processor : AArch64 Processor rev 3 (aarch64)
153 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
154 CPU implementer : 0x41
160 Hardware : Qualcomm Technologies, Inc MSM8992
163 EXPECT_EQ(sys::detail::getHostCPUNameForARM(MSM8992ProcCpuInfo
),
166 // Exynos big.LITTLE weirdness
167 const std::string ExynosProcCpuInfo
= R
"(
169 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
170 CPU implementer : 0x41
176 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
177 CPU implementer : 0x53
181 // Verify default for Exynos.
182 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo
+
183 "CPU variant : 0xc\n"
187 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo
+
188 "CPU variant : 0x1\n"
192 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo
+
193 "CPU variant : 0x1\n"
197 const std::string ThunderX2T99ProcCpuInfo
= R
"(
200 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics
201 CPU implementer : 0x43
207 // Verify different versions of ThunderX2T99.
208 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
209 "CPU implementer : 0x42\n"
213 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
214 "CPU implementer : 0x42\n"
215 "CPU part : 0x0516"),
218 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
219 "CPU implementer : 0x43\n"
223 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
224 "CPU implementer : 0x43\n"
225 "CPU part : 0x0516"),
228 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
229 "CPU implementer : 0x42\n"
233 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
234 "CPU implementer : 0x42\n"
238 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
239 "CPU implementer : 0x43\n"
243 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo
+
244 "CPU implementer : 0x43\n"
248 // Verify ThunderXT88.
249 const std::string ThunderXT88ProcCpuInfo
= R
"(
252 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
253 CPU implementer : 0x43
259 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderXT88ProcCpuInfo
+
260 "CPU implementer : 0x43\n"
264 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderXT88ProcCpuInfo
+
265 "CPU implementer : 0x43\n"
269 // Verify HiSilicon processors.
270 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x48\n"
275 const std::string A64FXProcCpuInfo
= R
"(
278 Features : fp asimd evtstrm sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm fcma dcpop sve
279 CPU implementer : 0x46
285 EXPECT_EQ(sys::detail::getHostCPUNameForARM(A64FXProcCpuInfo
), "a64fx");
287 // Verify Nvidia Carmel.
288 const std::string CarmelProcCpuInfo
= R
"(
290 model name : ARMv8 Processor rev 0 (v8l)
292 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm dcpop
293 CPU implementer : 0x4e
300 EXPECT_EQ(sys::detail::getHostCPUNameForARM(CarmelProcCpuInfo
), "carmel");
302 // Snapdragon mixed implementer quirk
303 const std::string Snapdragon865ProcCPUInfo
= R
"(
306 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp
307 CPU implementer : 0x51
319 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp
320 CPU implementer : 0x41
326 EXPECT_EQ(sys::detail::getHostCPUNameForARM(Snapdragon865ProcCPUInfo
), "cortex-a77");
329 TEST(getLinuxHostCPUName
, s390x
) {
330 SmallVector
<std::string
> ModelIDs(
331 {"3931", "8561", "3906", "2964", "2827", "2817", "2097", "2064"});
332 SmallVector
<std::string
> VectorSupport({"", "vx"});
333 SmallVector
<StringRef
> ExpectedCPUs
;
336 ExpectedCPUs
.push_back("zEC12");
337 ExpectedCPUs
.push_back("z16");
340 ExpectedCPUs
.push_back("zEC12");
341 ExpectedCPUs
.push_back("z15");
344 ExpectedCPUs
.push_back("zEC12");
345 ExpectedCPUs
.push_back("z14");
348 ExpectedCPUs
.push_back("zEC12");
349 ExpectedCPUs
.push_back("z13");
352 ExpectedCPUs
.push_back("zEC12");
353 ExpectedCPUs
.push_back("zEC12");
356 ExpectedCPUs
.push_back("z196");
357 ExpectedCPUs
.push_back("z196");
360 ExpectedCPUs
.push_back("z10");
361 ExpectedCPUs
.push_back("z10");
364 ExpectedCPUs
.push_back("generic");
365 ExpectedCPUs
.push_back("generic");
367 const std::string DummyBaseVectorInfo
=
368 "features : esan3 zarch stfle msa ldisp eimm dfp edat etf3eh highgprs "
370 const std::string DummyBaseMachineInfo
=
371 "processor 0: version = FF, identification = 059C88, machine = ";
374 for (size_t I
= 0; I
< ModelIDs
.size(); I
++) {
375 for (size_t J
= 0; J
< VectorSupport
.size(); J
++) {
376 const std::string DummyCPUInfo
= DummyBaseVectorInfo
+ VectorSupport
[J
] +
377 "\n" + DummyBaseMachineInfo
+
379 EXPECT_EQ(sys::detail::getHostCPUNameForS390x(DummyCPUInfo
),
380 ExpectedCPUs
[CheckIndex
++]);
385 TEST(getLinuxHostCPUName
, RISCV
) {
386 const StringRef SifiveU74MCProcCPUInfo
= R
"(
391 uarch : sifive,u74-mc
393 EXPECT_EQ(sys::detail::getHostCPUNameForRISCV(SifiveU74MCProcCPUInfo
),
396 sys::detail::getHostCPUNameForRISCV("uarch : sifive,bullet0\n"),
400 static bool runAndGetCommandOutput(
401 const char *ExePath
, ArrayRef
<llvm::StringRef
> argv
,
402 std::unique_ptr
<char[]> &Buffer
, off_t
&Size
) {
403 bool Success
= false;
404 [ExePath
, argv
, &Buffer
, &Size
, &Success
] {
405 using namespace llvm::sys
;
406 SmallString
<128> TestDirectory
;
407 ASSERT_NO_ERROR(fs::createUniqueDirectory("host_test", TestDirectory
));
409 SmallString
<128> OutputFile(TestDirectory
);
410 path::append(OutputFile
, "out");
411 StringRef OutputPath
= OutputFile
.str();
413 const std::optional
<StringRef
> Redirects
[] = {
414 /*STDIN=*/std::nullopt
, /*STDOUT=*/OutputPath
, /*STDERR=*/std::nullopt
};
416 ExecuteAndWait(ExePath
, argv
, /*env=*/std::nullopt
, Redirects
);
417 ASSERT_EQ(0, RetCode
);
420 ASSERT_NO_ERROR(fs::openFileForRead(OutputPath
, FD
));
421 Size
= ::lseek(FD
, 0, SEEK_END
);
423 ::lseek(FD
, 0, SEEK_SET
);
424 Buffer
= std::make_unique
<char[]>(Size
);
425 ASSERT_EQ(::read(FD
, Buffer
.get(), Size
), Size
);
428 ASSERT_NO_ERROR(fs::remove(OutputPath
));
429 ASSERT_NO_ERROR(fs::remove(TestDirectory
.str()));
435 TEST(HostTest
, DummyRunAndGetCommandOutputUse
) {
436 // Suppress defined-but-not-used warnings when the tests using the helper are
438 (void)&runAndGetCommandOutput
;
441 TEST(HostTest
, getMacOSHostVersion
) {
442 llvm::Triple
HostTriple(llvm::sys::getProcessTriple());
443 if (!HostTriple
.isMacOSX())
446 const char *SwVersPath
= "/usr/bin/sw_vers";
447 StringRef argv
[] = {SwVersPath
, "-productVersion"};
448 std::unique_ptr
<char[]> Buffer
;
450 ASSERT_EQ(runAndGetCommandOutput(SwVersPath
, argv
, Buffer
, Size
), true);
451 StringRef SystemVersionStr
= StringRef(Buffer
.get(), Size
).rtrim();
453 // Ensure that the two versions match.
454 VersionTuple SystemVersion
;
455 ASSERT_EQ(llvm::Triple((Twine("x86_64-apple-macos") + SystemVersionStr
))
456 .getMacOSXVersion(SystemVersion
),
458 VersionTuple HostVersion
;
459 ASSERT_EQ(HostTriple
.getMacOSXVersion(HostVersion
), true);
461 if (SystemVersion
.getMajor() > 10) {
462 // Don't compare the 'Minor' and 'Micro' versions, as they're always '0' for
463 // the 'Darwin' triples on 11.x.
464 ASSERT_EQ(SystemVersion
.getMajor(), HostVersion
.getMajor());
466 // Don't compare the 'Micro' version, as it's always '0' for the 'Darwin'
468 ASSERT_EQ(SystemVersion
.getMajor(), HostVersion
.getMajor());
469 ASSERT_EQ(SystemVersion
.getMinor(), HostVersion
.getMinor());
473 // Helper to return AIX system version. Must return void to use ASSERT_*.
474 static void getAIXSystemVersion(VersionTuple
&SystemVersion
) {
475 const char *ExePath
= "/usr/bin/oslevel";
476 StringRef argv
[] = {ExePath
};
477 std::unique_ptr
<char[]> Buffer
;
479 ASSERT_EQ(runAndGetCommandOutput(ExePath
, argv
, Buffer
, Size
), true);
480 StringRef SystemVersionStr
= StringRef(Buffer
.get(), Size
).rtrim();
483 llvm::Triple((Twine("powerpc-ibm-aix") + SystemVersionStr
))
487 TEST(HostTest
, AIXHostVersionDetect
) {
488 llvm::Triple
HostTriple(llvm::sys::getProcessTriple());
489 if (HostTriple
.getOS() != Triple::AIX
)
492 llvm::Triple
ConfiguredHostTriple(LLVM_HOST_TRIPLE
);
493 ASSERT_EQ(ConfiguredHostTriple
.getOS(), Triple::AIX
);
495 VersionTuple SystemVersion
;
496 getAIXSystemVersion(SystemVersion
);
498 // Ensure that the host triple version (major) and release (minor) numbers,
499 // unless explicitly configured, match with those of the current system.
500 auto SysMajor
= SystemVersion
.getMajor();
501 auto SysMinor
= SystemVersion
.getMinor();
502 VersionTuple HostVersion
= HostTriple
.getOSVersion();
503 if (ConfiguredHostTriple
.getOSMajorVersion()) {
504 // Explicitly configured, force a match. We do it this way so the
505 // asserts are always executed.
506 SysMajor
= HostVersion
.getMajor();
507 SysMinor
= HostVersion
.getMinor();
509 ASSERT_EQ(SysMajor
, HostVersion
.getMajor());
510 ASSERT_EQ(SysMinor
, HostVersion
.getMinor());
513 TEST(HostTest
, AIXTargetVersionDetect
) {
514 llvm::Triple
TargetTriple(llvm::sys::getDefaultTargetTriple());
515 if (TargetTriple
.getOS() != Triple::AIX
)
518 // Ensure that the target triple version (major) and release (minor) numbers
519 // match with those of the current system.
520 llvm::Triple
ConfiguredTargetTriple(LLVM_DEFAULT_TARGET_TRIPLE
);
521 if (ConfiguredTargetTriple
.getOSMajorVersion())
522 GTEST_SKIP(); // The version was configured explicitly; skip.
524 VersionTuple SystemVersion
;
525 getAIXSystemVersion(SystemVersion
);
526 VersionTuple TargetVersion
= TargetTriple
.getOSVersion();
527 ASSERT_EQ(SystemVersion
.getMajor(), TargetVersion
.getMajor());
528 ASSERT_EQ(SystemVersion
.getMinor(), TargetVersion
.getMinor());
531 TEST(HostTest
, AIXHostCPUDetect
) {
532 llvm::Triple
HostTriple(llvm::sys::getProcessTriple());
533 if (HostTriple
.getOS() != Triple::AIX
)
536 // Return a value based on the current processor implementation mode.
537 const char *ExePath
= "/usr/sbin/getsystype";
538 StringRef argv
[] = {ExePath
, "-i"};
539 std::unique_ptr
<char[]> Buffer
;
541 ASSERT_EQ(runAndGetCommandOutput(ExePath
, argv
, Buffer
, Size
), true);
542 StringRef
CPU(Buffer
.get(), Size
);
543 StringRef MCPU
= StringSwitch
<const char *>(CPU
)
544 .Case("POWER 4\n", "pwr4")
545 .Case("POWER 5\n", "pwr5")
546 .Case("POWER 6\n", "pwr6")
547 .Case("POWER 7\n", "pwr7")
548 .Case("POWER 8\n", "pwr8")
549 .Case("POWER 9\n", "pwr9")
550 .Case("POWER 10\n", "pwr10")
551 .Case("POWER 11\n", "pwr11")
554 StringRef HostCPU
= sys::getHostCPUName();
556 // Just do the comparison on the base implementation mode.
557 if (HostCPU
== "970")
558 HostCPU
= StringRef("pwr4");
560 HostCPU
= HostCPU
.rtrim('x');
562 EXPECT_EQ(HostCPU
, MCPU
);