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.isX86() && (Host.isOSDarwin() || 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 // Verify that both CPU implementer and CPU part are checked:
109 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x40\n"
112 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\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"
128 // MSM8992/4 weirdness
129 StringRef MSM8992ProcCpuInfo = R"(
130 Processor : AArch64 Processor rev 3 (aarch64)
137 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
138 CPU implementer : 0x41
144 Hardware : Qualcomm Technologies, Inc MSM8992
147 EXPECT_EQ(sys::detail::getHostCPUNameForARM(MSM8992ProcCpuInfo),
150 // Exynos big.LITTLE weirdness
151 const std::string ExynosProcCpuInfo = R"(
153 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
154 CPU implementer : 0x41
160 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
161 CPU implementer : 0x53
165 // Verify default for Exynos.
166 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo +
167 "CPU variant : 0xc\n"
171 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo +
172 "CPU variant : 0x1\n"
176 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo +
177 "CPU variant : 0x1\n"
181 const std::string ThunderX2T99ProcCpuInfo = R"(
184 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics
185 CPU implementer : 0x43
191 // Verify different versions of ThunderX2T99.
192 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo +
193 "CPU implementer : 0x42\n"
197 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo +
198 "CPU implementer : 0x42\n"
199 "CPU part : 0x0516"),
202 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo +
203 "CPU implementer : 0x43\n"
207 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo +
208 "CPU implementer : 0x43\n"
209 "CPU part : 0x0516"),
212 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo +
213 "CPU implementer : 0x42\n"
217 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo +
218 "CPU implementer : 0x42\n"
222 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo +
223 "CPU implementer : 0x43\n"
227 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo +
228 "CPU implementer : 0x43\n"
232 // Verify ThunderXT88.
233 const std::string ThunderXT88ProcCpuInfo = R"(
236 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
237 CPU implementer : 0x43
243 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderXT88ProcCpuInfo +
244 "CPU implementer : 0x43\n"
248 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderXT88ProcCpuInfo +
249 "CPU implementer : 0x43\n"
253 // Verify HiSilicon processors.
254 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x48\n"
259 const std::string A64FXProcCpuInfo = R"(
262 Features : fp asimd evtstrm sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm fcma dcpop sve
263 CPU implementer : 0x46
269 EXPECT_EQ(sys::detail::getHostCPUNameForARM(A64FXProcCpuInfo), "a64fx");
271 // Verify Nvidia Carmel.
272 const std::string CarmelProcCpuInfo = R"(
274 model name : ARMv8 Processor rev 0 (v8l)
276 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm dcpop
277 CPU implementer : 0x4e
284 EXPECT_EQ(sys::detail::getHostCPUNameForARM(CarmelProcCpuInfo), "carmel");
286 // Snapdragon mixed implementer quirk
287 const std::string Snapdragon865ProcCPUInfo = R"(
290 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp
291 CPU implementer : 0x51
303 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp
304 CPU implementer : 0x41
310 EXPECT_EQ(sys::detail::getHostCPUNameForARM(Snapdragon865ProcCPUInfo), "cortex-a77");
313 #if defined(__APPLE__) || defined(_AIX)
314 static bool runAndGetCommandOutput(
315 const char *ExePath, ArrayRef<llvm::StringRef> argv,
316 std::unique_ptr<char[]> &Buffer, off_t &Size) {
317 bool Success = false;
318 [ExePath, argv, &Buffer, &Size, &Success] {
319 using namespace llvm::sys;
320 SmallString<128> TestDirectory;
321 ASSERT_NO_ERROR(fs::createUniqueDirectory("host_test", TestDirectory));
323 SmallString<128> OutputFile(TestDirectory);
324 path::append(OutputFile, "out");
325 StringRef OutputPath = OutputFile.str();
327 const Optional<StringRef> Redirects[] = {
328 /*STDIN=*/None, /*STDOUT=*/OutputPath, /*STDERR=*/None};
329 int RetCode = ExecuteAndWait(ExePath, argv, /*env=*/llvm::None, Redirects);
330 ASSERT_EQ(0, RetCode);
333 ASSERT_NO_ERROR(fs::openFileForRead(OutputPath, FD));
334 Size = ::lseek(FD, 0, SEEK_END);
336 ::lseek(FD, 0, SEEK_SET);
337 Buffer = std::make_unique<char[]>(Size);
338 ASSERT_EQ(::read(FD, Buffer.get(), Size), Size);
341 ASSERT_NO_ERROR(fs::remove(OutputPath));
342 ASSERT_NO_ERROR(fs::remove(TestDirectory.str()));
348 TEST_F(HostTest, DummyRunAndGetCommandOutputUse) {
349 // Suppress defined-but-not-used warnings when the tests using the helper are
351 (void) runAndGetCommandOutput;
355 #if defined(__APPLE__)
356 TEST_F(HostTest, getMacOSHostVersion) {
357 using namespace llvm::sys;
358 llvm::Triple HostTriple(getProcessTriple());
359 if (!HostTriple.isMacOSX())
362 const char *SwVersPath = "/usr/bin/sw_vers";
363 StringRef argv[] = {SwVersPath, "-productVersion"};
364 std::unique_ptr<char[]> Buffer;
366 ASSERT_EQ(runAndGetCommandOutput(SwVersPath, argv, Buffer, Size), true);
367 StringRef SystemVersion(Buffer.get(), Size);
369 // Ensure that the two versions match.
370 unsigned SystemMajor, SystemMinor, SystemMicro;
371 ASSERT_EQ(llvm::Triple((Twine("x86_64-apple-macos") + SystemVersion))
372 .getMacOSXVersion(SystemMajor, SystemMinor, SystemMicro),
374 unsigned HostMajor, HostMinor, HostMicro;
375 ASSERT_EQ(HostTriple.getMacOSXVersion(HostMajor, HostMinor, HostMicro), true);
377 if (SystemMajor > 10) {
378 // Don't compare the 'Minor' and 'Micro' versions, as they're always '0' for
379 // the 'Darwin' triples on 11.x.
380 ASSERT_EQ(SystemMajor, HostMajor);
382 // Don't compare the 'Micro' version, as it's always '0' for the 'Darwin'
384 ASSERT_EQ(std::tie(SystemMajor, SystemMinor), std::tie(HostMajor, HostMinor));
390 TEST_F(HostTest, AIXVersionDetect) {
391 using namespace llvm::sys;
393 llvm::Triple HostTriple(getProcessTriple());
394 ASSERT_EQ(HostTriple.getOS(), Triple::AIX);
396 llvm::Triple ConfiguredHostTriple(LLVM_HOST_TRIPLE);
397 ASSERT_EQ(ConfiguredHostTriple.getOS(), Triple::AIX);
399 const char *ExePath = "/usr/bin/oslevel";
400 StringRef argv[] = {ExePath};
401 std::unique_ptr<char[]> Buffer;
403 ASSERT_EQ(runAndGetCommandOutput(ExePath, argv, Buffer, Size), true);
404 StringRef SystemVersion(Buffer.get(), Size);
406 unsigned SystemMajor, SystemMinor, SystemMicro;
407 llvm::Triple((Twine("powerpc-ibm-aix") + SystemVersion))
408 .getOSVersion(SystemMajor, SystemMinor, SystemMicro);
410 // Ensure that the host triple version (major) and release (minor) numbers,
411 // unless explicitly configured, match with those of the current system.
412 if (!ConfiguredHostTriple.getOSMajorVersion()) {
413 unsigned HostMajor, HostMinor, HostMicro;
414 HostTriple.getOSVersion(HostMajor, HostMinor, HostMicro);
415 ASSERT_EQ(std::tie(SystemMajor, SystemMinor),
416 std::tie(HostMajor, HostMinor));
419 llvm::Triple TargetTriple(getDefaultTargetTriple());
420 if (TargetTriple.getOS() != Triple::AIX)
423 // Ensure that the target triple version (major) and release (minor) numbers
424 // match with those of the current system.
425 llvm::Triple ConfiguredTargetTriple(LLVM_DEFAULT_TARGET_TRIPLE);
426 if (ConfiguredTargetTriple.getOSMajorVersion())
427 return; // The version was configured explicitly; skip.
429 unsigned TargetMajor, TargetMinor, TargetMicro;
430 TargetTriple.getOSVersion(TargetMajor, TargetMinor, TargetMicro);
431 ASSERT_EQ(std::tie(SystemMajor, SystemMinor),
432 std::tie(TargetMajor, TargetMinor));