1//========- unittests/Support/Host.cpp - Host.cpp tests --------------========//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
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"
17
18#include "gtest/gtest.h"
19
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()); \
28 } else { \
29 }
30
31using namespace llvm;
32
33TEST(getLinuxHostCPUName, ARM) {
34 StringRef CortexA9ProcCpuinfo = R"(
35processor : 0
36model name : ARMv7 Processor rev 10 (v7l)
37BogoMIPS : 1393.66
38Features : half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpd32
39CPU implementer : 0x41
40CPU architecture: 7
41CPU variant : 0x2
42CPU part : 0xc09
43CPU revision : 10
44
45processor : 1
46model name : ARMv7 Processor rev 10 (v7l)
47BogoMIPS : 1393.66
48Features : half thumb fastmult vfp edsp thumbee neon vfpv3 tls vfpd32
49CPU implementer : 0x41
50CPU architecture: 7
51CPU variant : 0x2
52CPU part : 0xc09
53CPU revision : 10
54
55Hardware : Generic OMAP4 (Flattened Device Tree)
56Revision : 0000
57Serial : 0000000000000000
58)";
59
60 EXPECT_EQ(sys::detail::getHostCPUNameForARM(CortexA9ProcCpuinfo),
61 "cortex-a9");
62 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n"
63 "CPU part : 0xc0f"),
64 "cortex-a15");
65 // Verify that both CPU implementer and CPU part are checked:
66 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x40\n"
67 "CPU part : 0xc0f"),
68 "generic");
69 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n"
70 "CPU part : 0x06f"),
71 "krait");
72}
73
74TEST(getLinuxHostCPUName, AArch64) {
75 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n"
76 "CPU part : 0xd03"),
77 "cortex-a53");
78 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n"
79 "CPU part : 0xd05"),
80 "cortex-a55");
81
82 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n"
83 "CPU part : 0xd40"),
84 "neoverse-v1");
85 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n"
86 "CPU part : 0xd0c"),
87 "neoverse-n1");
88 // Verify that both CPU implementer and CPU part are checked:
89 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x40\n"
90 "CPU part : 0xd03"),
91 "generic");
92 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n"
93 "CPU part : 0x201"),
94 "kryo");
95 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n"
96 "CPU part : 0x800"),
97 "cortex-a73");
98 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n"
99 "CPU part : 0x801"),
100 "cortex-a73");
101 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n"
102 "CPU part : 0xd46"),
103 "cortex-a510");
104 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n"
105 "CPU part : 0xd47"),
106 "cortex-a710");
107 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x41\n"
108 "CPU part : 0xd48"),
109 "cortex-x2");
110 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n"
111 "CPU part : 0xc00"),
112 "falkor");
113 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n"
114 "CPU part : 0xc01"),
115 "saphira");
116 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x6d\n"
117 "CPU part : 0xd49"),
118 "neoverse-n2");
119 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0xc0\n"
120 "CPU part : 0xac3"),
121 "ampere1");
122 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0xc0\n"
123 "CPU part : 0xac4"),
124 "ampere1a");
125 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0xc0\n"
126 "CPU part : 0xac5"),
127 "ampere1b");
128
129 // MSM8992/4 weirdness
130 StringRef MSM8992ProcCpuInfo = R"(
131Processor : AArch64 Processor rev 3 (aarch64)
132processor : 0
133processor : 1
134processor : 2
135processor : 3
136processor : 4
137processor : 5
138Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
139CPU implementer : 0x41
140CPU architecture: 8
141CPU variant : 0x0
142CPU part : 0xd03
143CPU revision : 3
144
145Hardware : Qualcomm Technologies, Inc MSM8992
146)";
147
148 EXPECT_EQ(sys::detail::getHostCPUNameForARM(MSM8992ProcCpuInfo),
149 "cortex-a53");
150
151 // Exynos big.LITTLE weirdness
152 const std::string ExynosProcCpuInfo = R"(
153processor : 0
154Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
155CPU implementer : 0x41
156CPU architecture: 8
157CPU variant : 0x0
158CPU part : 0xd05
159
160processor : 1
161Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
162CPU implementer : 0x53
163CPU architecture: 8
164)";
165
166 // Verify default for Exynos.
167 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo +
168 "CPU variant : 0xc\n"
169 "CPU part : 0xafe"),
170 "exynos-m3");
171 // Verify Exynos M3.
172 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo +
173 "CPU variant : 0x1\n"
174 "CPU part : 0x002"),
175 "exynos-m3");
176 // Verify Exynos M4.
177 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo +
178 "CPU variant : 0x1\n"
179 "CPU part : 0x003"),
180 "exynos-m4");
181
182 const std::string ThunderX2T99ProcCpuInfo = R"(
183processor : 0
184BogoMIPS : 400.00
185Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics
186CPU implementer : 0x43
187CPU architecture: 8
188CPU variant : 0x1
189CPU part : 0x0af
190)";
191
192 // Verify different versions of ThunderX2T99.
193 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo +
194 "CPU implementer : 0x42\n"
195 "CPU part : 0x516"),
196 "thunderx2t99");
197
198 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo +
199 "CPU implementer : 0x42\n"
200 "CPU part : 0x0516"),
201 "thunderx2t99");
202
203 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo +
204 "CPU implementer : 0x43\n"
205 "CPU part : 0x516"),
206 "thunderx2t99");
207
208 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo +
209 "CPU implementer : 0x43\n"
210 "CPU part : 0x0516"),
211 "thunderx2t99");
212
213 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo +
214 "CPU implementer : 0x42\n"
215 "CPU part : 0xaf"),
216 "thunderx2t99");
217
218 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo +
219 "CPU implementer : 0x42\n"
220 "CPU part : 0x0af"),
221 "thunderx2t99");
222
223 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo +
224 "CPU implementer : 0x43\n"
225 "CPU part : 0xaf"),
226 "thunderx2t99");
227
228 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderX2T99ProcCpuInfo +
229 "CPU implementer : 0x43\n"
230 "CPU part : 0x0af"),
231 "thunderx2t99");
232
233 // Verify ThunderXT88.
234 const std::string ThunderXT88ProcCpuInfo = R"(
235processor : 0
236BogoMIPS : 200.00
237Features : fp asimd evtstrm aes pmull sha1 sha2 crc32
238CPU implementer : 0x43
239CPU architecture: 8
240CPU variant : 0x1
241CPU part : 0x0a1
242)";
243
244 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderXT88ProcCpuInfo +
245 "CPU implementer : 0x43\n"
246 "CPU part : 0x0a1"),
247 "thunderxt88");
248
249 EXPECT_EQ(sys::detail::getHostCPUNameForARM(ThunderXT88ProcCpuInfo +
250 "CPU implementer : 0x43\n"
251 "CPU part : 0xa1"),
252 "thunderxt88");
253
254 // Verify HiSilicon processors.
255 EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x48\n"
256 "CPU part : 0xd01"),
257 "tsv110");
258
259 // Verify A64FX.
260 const std::string A64FXProcCpuInfo = R"(
261processor : 0
262BogoMIPS : 200.00
263Features : fp asimd evtstrm sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm fcma dcpop sve
264CPU implementer : 0x46
265CPU architecture: 8
266CPU variant : 0x1
267CPU part : 0x001
268)";
269
270 EXPECT_EQ(sys::detail::getHostCPUNameForARM(A64FXProcCpuInfo), "a64fx");
271
272 // Verify Nvidia Carmel.
273 const std::string CarmelProcCpuInfo = R"(
274processor : 0
275model name : ARMv8 Processor rev 0 (v8l)
276BogoMIPS : 62.50
277Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm dcpop
278CPU implementer : 0x4e
279CPU architecture: 8
280CPU variant : 0x0
281CPU part : 0x004
282CPU revision : 0
283)";
284
285 EXPECT_EQ(sys::detail::getHostCPUNameForARM(CarmelProcCpuInfo), "carmel");
286
287 // Snapdragon mixed implementer quirk
288 const std::string Snapdragon865ProcCPUInfo = R"(
289processor : 0
290BogoMIPS : 38.40
291Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp
292CPU implementer : 0x51
293CPU architecture: 8
294CPU variant : 0xd
295CPU part : 0x805
296CPU revision : 14
297processor : 1
298processor : 2
299processor : 3
300processor : 4
301processor : 5
302processor : 6
303BogoMIPS : 38.40
304Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp
305CPU implementer : 0x41
306CPU architecture: 8
307CPU variant : 0x1
308CPU part : 0xd0d
309CPU revision : 0
310)";
311 EXPECT_EQ(sys::detail::getHostCPUNameForARM(Snapdragon865ProcCPUInfo), "cortex-a77");
312}
313
314TEST(getLinuxHostCPUName, s390x) {
315 SmallVector<std::string> ModelIDs(
316 {"3931", "8561", "3906", "2964", "2827", "2817", "2097", "2064"});
317 SmallVector<std::string> VectorSupport({"", "vx"});
318 SmallVector<StringRef> ExpectedCPUs;
319
320 // Model Id: 3931
321 ExpectedCPUs.push_back(Elt: "zEC12");
322 ExpectedCPUs.push_back(Elt: "z16");
323
324 // Model Id: 8561
325 ExpectedCPUs.push_back(Elt: "zEC12");
326 ExpectedCPUs.push_back(Elt: "z15");
327
328 // Model Id: 3906
329 ExpectedCPUs.push_back(Elt: "zEC12");
330 ExpectedCPUs.push_back(Elt: "z14");
331
332 // Model Id: 2964
333 ExpectedCPUs.push_back(Elt: "zEC12");
334 ExpectedCPUs.push_back(Elt: "z13");
335
336 // Model Id: 2827
337 ExpectedCPUs.push_back(Elt: "zEC12");
338 ExpectedCPUs.push_back(Elt: "zEC12");
339
340 // Model Id: 2817
341 ExpectedCPUs.push_back(Elt: "z196");
342 ExpectedCPUs.push_back(Elt: "z196");
343
344 // Model Id: 2097
345 ExpectedCPUs.push_back(Elt: "z10");
346 ExpectedCPUs.push_back(Elt: "z10");
347
348 // Model Id: 2064
349 ExpectedCPUs.push_back(Elt: "generic");
350 ExpectedCPUs.push_back(Elt: "generic");
351
352 const std::string DummyBaseVectorInfo =
353 "features : esan3 zarch stfle msa ldisp eimm dfp edat etf3eh highgprs "
354 "te ";
355 const std::string DummyBaseMachineInfo =
356 "processor 0: version = FF, identification = 059C88, machine = ";
357
358 int CheckIndex = 0;
359 for (size_t I = 0; I < ModelIDs.size(); I++) {
360 for (size_t J = 0; J < VectorSupport.size(); J++) {
361 const std::string DummyCPUInfo = DummyBaseVectorInfo + VectorSupport[J] +
362 "\n" + DummyBaseMachineInfo +
363 ModelIDs[I];
364 EXPECT_EQ(sys::detail::getHostCPUNameForS390x(DummyCPUInfo),
365 ExpectedCPUs[CheckIndex++]);
366 }
367 }
368}
369
370TEST(getLinuxHostCPUName, RISCV) {
371 const StringRef SifiveU74MCProcCPUInfo = R"(
372processor : 0
373hart : 2
374isa : rv64imafdc
375mmu : sv39
376uarch : sifive,u74-mc
377)";
378 EXPECT_EQ(sys::detail::getHostCPUNameForRISCV(SifiveU74MCProcCPUInfo),
379 "sifive-u74");
380 EXPECT_EQ(
381 sys::detail::getHostCPUNameForRISCV("uarch : sifive,bullet0\n"),
382 "sifive-u74");
383}
384
385static bool runAndGetCommandOutput(
386 const char *ExePath, ArrayRef<llvm::StringRef> argv,
387 std::unique_ptr<char[]> &Buffer, off_t &Size) {
388 bool Success = false;
389 [ExePath, argv, &Buffer, &Size, &Success] {
390 using namespace llvm::sys;
391 SmallString<128> TestDirectory;
392 ASSERT_NO_ERROR(fs::createUniqueDirectory("host_test", TestDirectory));
393
394 SmallString<128> OutputFile(TestDirectory);
395 path::append(path&: OutputFile, a: "out");
396 StringRef OutputPath = OutputFile.str();
397
398 const std::optional<StringRef> Redirects[] = {
399 /*STDIN=*/std::nullopt, /*STDOUT=*/OutputPath, /*STDERR=*/std::nullopt};
400 int RetCode =
401 ExecuteAndWait(Program: ExePath, Args: argv, /*env=*/Env: std::nullopt, Redirects);
402 ASSERT_EQ(0, RetCode);
403
404 int FD = 0;
405 ASSERT_NO_ERROR(fs::openFileForRead(OutputPath, FD));
406 Size = ::lseek(fd: FD, offset: 0, SEEK_END);
407 ASSERT_NE(-1, Size);
408 ::lseek(fd: FD, offset: 0, SEEK_SET);
409 Buffer = std::make_unique<char[]>(num: Size);
410 ASSERT_EQ(::read(FD, Buffer.get(), Size), Size);
411 ::close(fd: FD);
412
413 ASSERT_NO_ERROR(fs::remove(OutputPath));
414 ASSERT_NO_ERROR(fs::remove(TestDirectory.str()));
415 Success = true;
416 }();
417 return Success;
418}
419
420TEST(HostTest, DummyRunAndGetCommandOutputUse) {
421 // Suppress defined-but-not-used warnings when the tests using the helper are
422 // disabled.
423 (void)&runAndGetCommandOutput;
424}
425
426TEST(HostTest, getMacOSHostVersion) {
427 llvm::Triple HostTriple(llvm::sys::getProcessTriple());
428 if (!HostTriple.isMacOSX())
429 GTEST_SKIP();
430
431 const char *SwVersPath = "/usr/bin/sw_vers";
432 StringRef argv[] = {SwVersPath, "-productVersion"};
433 std::unique_ptr<char[]> Buffer;
434 off_t Size;
435 ASSERT_EQ(runAndGetCommandOutput(SwVersPath, argv, Buffer, Size), true);
436 StringRef SystemVersionStr = StringRef(Buffer.get(), Size).rtrim();
437
438 // Ensure that the two versions match.
439 VersionTuple SystemVersion;
440 ASSERT_EQ(llvm::Triple((Twine("x86_64-apple-macos") + SystemVersionStr))
441 .getMacOSXVersion(SystemVersion),
442 true);
443 VersionTuple HostVersion;
444 ASSERT_EQ(HostTriple.getMacOSXVersion(HostVersion), true);
445
446 if (SystemVersion.getMajor() > 10) {
447 // Don't compare the 'Minor' and 'Micro' versions, as they're always '0' for
448 // the 'Darwin' triples on 11.x.
449 ASSERT_EQ(SystemVersion.getMajor(), HostVersion.getMajor());
450 } else {
451 // Don't compare the 'Micro' version, as it's always '0' for the 'Darwin'
452 // triples.
453 ASSERT_EQ(SystemVersion.getMajor(), HostVersion.getMajor());
454 ASSERT_EQ(SystemVersion.getMinor(), HostVersion.getMinor());
455 }
456}
457
458// Helper to return AIX system version. Must return void to use ASSERT_*.
459static void getAIXSystemVersion(VersionTuple &SystemVersion) {
460 const char *ExePath = "/usr/bin/oslevel";
461 StringRef argv[] = {ExePath};
462 std::unique_ptr<char[]> Buffer;
463 off_t Size;
464 ASSERT_EQ(runAndGetCommandOutput(ExePath, argv, Buffer, Size), true);
465 StringRef SystemVersionStr = StringRef(Buffer.get(), Size).rtrim();
466
467 SystemVersion =
468 llvm::Triple((Twine("powerpc-ibm-aix") + SystemVersionStr))
469 .getOSVersion();
470}
471
472TEST(HostTest, AIXHostVersionDetect) {
473 llvm::Triple HostTriple(llvm::sys::getProcessTriple());
474 if (HostTriple.getOS() != Triple::AIX)
475 GTEST_SKIP();
476
477 llvm::Triple ConfiguredHostTriple(LLVM_HOST_TRIPLE);
478 ASSERT_EQ(ConfiguredHostTriple.getOS(), Triple::AIX);
479
480 VersionTuple SystemVersion;
481 getAIXSystemVersion(SystemVersion);
482
483 // Ensure that the host triple version (major) and release (minor) numbers,
484 // unless explicitly configured, match with those of the current system.
485 auto SysMajor = SystemVersion.getMajor();
486 auto SysMinor = SystemVersion.getMinor();
487 VersionTuple HostVersion = HostTriple.getOSVersion();
488 if (ConfiguredHostTriple.getOSMajorVersion()) {
489 // Explicitly configured, force a match. We do it this way so the
490 // asserts are always executed.
491 SysMajor = HostVersion.getMajor();
492 SysMinor = HostVersion.getMinor();
493 }
494 ASSERT_EQ(SysMajor, HostVersion.getMajor());
495 ASSERT_EQ(SysMinor, HostVersion.getMinor());
496}
497
498TEST(HostTest, AIXTargetVersionDetect) {
499 llvm::Triple TargetTriple(llvm::sys::getDefaultTargetTriple());
500 if (TargetTriple.getOS() != Triple::AIX)
501 GTEST_SKIP();
502
503 // Ensure that the target triple version (major) and release (minor) numbers
504 // match with those of the current system.
505 llvm::Triple ConfiguredTargetTriple(LLVM_DEFAULT_TARGET_TRIPLE);
506 if (ConfiguredTargetTriple.getOSMajorVersion())
507 GTEST_SKIP(); // The version was configured explicitly; skip.
508
509 VersionTuple SystemVersion;
510 getAIXSystemVersion(SystemVersion);
511 VersionTuple TargetVersion = TargetTriple.getOSVersion();
512 ASSERT_EQ(SystemVersion.getMajor(), TargetVersion.getMajor());
513 ASSERT_EQ(SystemVersion.getMinor(), TargetVersion.getMinor());
514}
515
516TEST(HostTest, AIXHostCPUDetect) {
517 llvm::Triple HostTriple(llvm::sys::getProcessTriple());
518 if (HostTriple.getOS() != Triple::AIX)
519 GTEST_SKIP();
520
521 // Return a value based on the current processor implementation mode.
522 const char *ExePath = "/usr/sbin/getsystype";
523 StringRef argv[] = {ExePath, "-i"};
524 std::unique_ptr<char[]> Buffer;
525 off_t Size;
526 ASSERT_EQ(runAndGetCommandOutput(ExePath, argv, Buffer, Size), true);
527 StringRef CPU(Buffer.get(), Size);
528 StringRef MCPU = StringSwitch<const char *>(CPU)
529 .Case(S: "POWER 4\n", Value: "pwr4")
530 .Case(S: "POWER 5\n", Value: "pwr5")
531 .Case(S: "POWER 6\n", Value: "pwr6")
532 .Case(S: "POWER 7\n", Value: "pwr7")
533 .Case(S: "POWER 8\n", Value: "pwr8")
534 .Case(S: "POWER 9\n", Value: "pwr9")
535 .Case(S: "POWER 10\n", Value: "pwr10")
536 .Default(Value: "unknown");
537
538 StringRef HostCPU = sys::getHostCPUName();
539
540 // Just do the comparison on the base implementation mode.
541 if (HostCPU == "970")
542 HostCPU = StringRef("pwr4");
543 else
544 HostCPU = HostCPU.rtrim(Char: 'x');
545
546 EXPECT_EQ(HostCPU, MCPU);
547}
548

source code of llvm/unittests/TargetParser/Host.cpp