1//===-- ArchSpecTest.cpp --------------------------------------------------===//
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 "gtest/gtest.h"
10
11#include "lldb/Utility/ArchSpec.h"
12#include "llvm/BinaryFormat/ELF.h"
13#include "llvm/BinaryFormat/MachO.h"
14
15using namespace lldb;
16using namespace lldb_private;
17
18TEST(ArchSpecTest, TestParseMachCPUDashSubtypeTripleSimple) {
19
20 // Success conditions. Valid cpu/subtype combinations using both - and .
21 ArchSpec AS;
22 EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-10", AS));
23 EXPECT_EQ(12u, AS.GetMachOCPUType());
24 EXPECT_EQ(10u, AS.GetMachOCPUSubType());
25
26 AS = ArchSpec();
27 EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-15", AS));
28 EXPECT_EQ(12u, AS.GetMachOCPUType());
29 EXPECT_EQ(15u, AS.GetMachOCPUSubType());
30
31 AS = ArchSpec();
32 EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12.15", AS));
33 EXPECT_EQ(12u, AS.GetMachOCPUType());
34 EXPECT_EQ(15u, AS.GetMachOCPUSubType());
35
36 // Failure conditions.
37
38 // Valid string, unknown cpu/subtype.
39 AS = ArchSpec();
40 EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("13.11", AS));
41 EXPECT_EQ(0u, AS.GetMachOCPUType());
42 EXPECT_EQ(0u, AS.GetMachOCPUSubType());
43
44 // Missing / invalid cpu or subtype
45 AS = ArchSpec();
46 EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("13", AS));
47
48 AS = ArchSpec();
49 EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("13.A", AS));
50
51 AS = ArchSpec();
52 EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("A.13", AS));
53
54 // Empty string.
55 AS = ArchSpec();
56 EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("", AS));
57}
58
59TEST(ArchSpecTest, TestParseMachCPUDashSubtypeTripleExtra) {
60 ArchSpec AS;
61 EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-15-vendor-os", AS));
62 EXPECT_EQ(12u, AS.GetMachOCPUType());
63 EXPECT_EQ(15u, AS.GetMachOCPUSubType());
64 EXPECT_EQ("vendor", AS.GetTriple().getVendorName());
65 EXPECT_EQ("os", AS.GetTriple().getOSName());
66
67 AS = ArchSpec();
68 EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-10-vendor-os-name", AS));
69 EXPECT_EQ(12u, AS.GetMachOCPUType());
70 EXPECT_EQ(10u, AS.GetMachOCPUSubType());
71 EXPECT_EQ("vendor", AS.GetTriple().getVendorName());
72 EXPECT_EQ("os", AS.GetTriple().getOSName());
73
74 AS = ArchSpec();
75 EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-15-vendor.os-name", AS));
76 EXPECT_EQ(12u, AS.GetMachOCPUType());
77 EXPECT_EQ(15u, AS.GetMachOCPUSubType());
78 EXPECT_EQ("vendor.os", AS.GetTriple().getVendorName());
79 EXPECT_EQ("name", AS.GetTriple().getOSName());
80
81 // These there should parse correctly, but the vendor / OS should be defaulted
82 // since they are unrecognized.
83 AS = ArchSpec();
84 EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-10-vendor", AS));
85 EXPECT_EQ(12u, AS.GetMachOCPUType());
86 EXPECT_EQ(10u, AS.GetMachOCPUSubType());
87 EXPECT_EQ("apple", AS.GetTriple().getVendorName());
88 EXPECT_EQ("", AS.GetTriple().getOSName());
89
90 AS = ArchSpec();
91 EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("12.10.10", AS));
92
93 AS = ArchSpec();
94 EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("12-10.10", AS));
95}
96
97TEST(ArchSpecTest, TestSetTriple) {
98 ArchSpec AS;
99
100 // Various flavors of valid triples.
101 EXPECT_TRUE(AS.SetTriple("12-10-apple-darwin"));
102 EXPECT_EQ(uint32_t(llvm::MachO::CPU_TYPE_ARM), AS.GetMachOCPUType());
103 EXPECT_EQ(10u, AS.GetMachOCPUSubType());
104 EXPECT_TRUE(llvm::StringRef(AS.GetTriple().str())
105 .consume_front("armv7f-apple-darwin"));
106 EXPECT_EQ(ArchSpec::eCore_arm_armv7f, AS.GetCore());
107
108 AS = ArchSpec();
109 EXPECT_TRUE(AS.SetTriple("18.100-apple-darwin"));
110 EXPECT_EQ(uint32_t(llvm::MachO::CPU_TYPE_POWERPC), AS.GetMachOCPUType());
111 EXPECT_EQ(100u, AS.GetMachOCPUSubType());
112 EXPECT_TRUE(llvm::StringRef(AS.GetTriple().str())
113 .consume_front("powerpc-apple-darwin"));
114 EXPECT_EQ(ArchSpec::eCore_ppc_ppc970, AS.GetCore());
115
116 AS = ArchSpec();
117 EXPECT_TRUE(AS.SetTriple("i686-pc-windows"));
118 EXPECT_EQ(llvm::Triple::x86, AS.GetTriple().getArch());
119 EXPECT_EQ(llvm::Triple::PC, AS.GetTriple().getVendor());
120 EXPECT_EQ(llvm::Triple::Win32, AS.GetTriple().getOS());
121 EXPECT_TRUE(
122 llvm::StringRef(AS.GetTriple().str()).consume_front("i686-pc-windows"));
123 EXPECT_STREQ("i686", AS.GetArchitectureName());
124 EXPECT_EQ(ArchSpec::eCore_x86_32_i686, AS.GetCore());
125
126 AS = ArchSpec();
127 EXPECT_TRUE(AS.SetTriple("msp430---elf"));
128 EXPECT_EQ(llvm::Triple::msp430, AS.GetTriple().getArch());
129 EXPECT_STREQ("msp430", AS.GetArchitectureName());
130 EXPECT_EQ(ArchSpec::eCore_msp430, AS.GetCore());
131
132 // Various flavors of invalid triples.
133 AS = ArchSpec();
134 EXPECT_FALSE(AS.SetTriple("unknown-unknown-unknown"));
135
136 AS = ArchSpec();
137 EXPECT_FALSE(AS.SetTriple("unknown"));
138
139 AS = ArchSpec();
140 EXPECT_FALSE(AS.SetTriple(""));
141}
142
143TEST(ArchSpecTest, MergeFrom) {
144 {
145 ArchSpec A;
146 ArchSpec B("x86_64-pc-linux");
147
148 EXPECT_FALSE(A.IsValid());
149 ASSERT_TRUE(B.IsValid());
150 EXPECT_EQ(llvm::Triple::ArchType::x86_64, B.GetTriple().getArch());
151 EXPECT_EQ(llvm::Triple::VendorType::PC, B.GetTriple().getVendor());
152 EXPECT_EQ(llvm::Triple::OSType::Linux, B.GetTriple().getOS());
153 EXPECT_EQ(ArchSpec::eCore_x86_64_x86_64, B.GetCore());
154
155 A.MergeFrom(other: B);
156 ASSERT_TRUE(A.IsValid());
157 EXPECT_EQ(llvm::Triple::ArchType::x86_64, A.GetTriple().getArch());
158 EXPECT_EQ(llvm::Triple::VendorType::PC, A.GetTriple().getVendor());
159 EXPECT_EQ(llvm::Triple::OSType::Linux, A.GetTriple().getOS());
160 EXPECT_EQ(ArchSpec::eCore_x86_64_x86_64, A.GetCore());
161 }
162 {
163 ArchSpec A("aarch64");
164 ArchSpec B("aarch64--linux-android");
165
166 ArchSpec C("arm64_32");
167 ArchSpec D("arm64_32--watchos");
168
169 EXPECT_TRUE(A.IsValid());
170 EXPECT_TRUE(B.IsValid());
171 EXPECT_TRUE(C.IsValid());
172 EXPECT_TRUE(D.IsValid());
173
174 EXPECT_EQ(llvm::Triple::ArchType::aarch64, B.GetTriple().getArch());
175 EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor,
176 B.GetTriple().getVendor());
177 EXPECT_EQ(llvm::Triple::OSType::Linux, B.GetTriple().getOS());
178 EXPECT_EQ(llvm::Triple::EnvironmentType::Android,
179 B.GetTriple().getEnvironment());
180
181 A.MergeFrom(other: B);
182 EXPECT_EQ(llvm::Triple::ArchType::aarch64, A.GetTriple().getArch());
183 EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor,
184 A.GetTriple().getVendor());
185 EXPECT_EQ(llvm::Triple::OSType::Linux, A.GetTriple().getOS());
186 EXPECT_EQ(llvm::Triple::EnvironmentType::Android,
187 A.GetTriple().getEnvironment());
188
189 EXPECT_EQ(llvm::Triple::ArchType::aarch64_32, D.GetTriple().getArch());
190 EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor,
191 D.GetTriple().getVendor());
192 EXPECT_EQ(llvm::Triple::OSType::WatchOS, D.GetTriple().getOS());
193
194 C.MergeFrom(other: D);
195 EXPECT_EQ(llvm::Triple::ArchType::aarch64_32, C.GetTriple().getArch());
196 EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor,
197 C.GetTriple().getVendor());
198 EXPECT_EQ(llvm::Triple::OSType::WatchOS, C.GetTriple().getOS());
199 }
200 {
201 ArchSpec A, B;
202 A.SetArchitecture(arch_type: eArchTypeELF, cpu: llvm::ELF::EM_ARM,
203 LLDB_INVALID_CPUTYPE, os: llvm::ELF::ELFOSABI_NONE);
204 B.SetArchitecture(arch_type: eArchTypeELF, cpu: llvm::ELF::EM_ARM,
205 LLDB_INVALID_CPUTYPE, os: llvm::ELF::ELFOSABI_LINUX);
206
207 EXPECT_TRUE(A.IsValid());
208 EXPECT_TRUE(B.IsValid());
209
210 EXPECT_EQ(llvm::Triple::ArchType::arm, B.GetTriple().getArch());
211 EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor,
212 B.GetTriple().getVendor());
213 EXPECT_EQ(llvm::Triple::OSType::Linux, B.GetTriple().getOS());
214 EXPECT_EQ(llvm::Triple::EnvironmentType::UnknownEnvironment,
215 B.GetTriple().getEnvironment());
216
217 A.MergeFrom(other: B);
218 EXPECT_EQ(llvm::Triple::ArchType::arm, A.GetTriple().getArch());
219 EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor,
220 A.GetTriple().getVendor());
221 EXPECT_EQ(llvm::Triple::OSType::Linux, A.GetTriple().getOS());
222 EXPECT_EQ(llvm::Triple::EnvironmentType::UnknownEnvironment,
223 A.GetTriple().getEnvironment());
224 }
225 {
226 ArchSpec A("arm--linux-eabihf");
227 ArchSpec B("armv8l--linux-gnueabihf");
228
229 EXPECT_TRUE(A.IsValid());
230 EXPECT_TRUE(B.IsValid());
231
232 EXPECT_EQ(llvm::Triple::ArchType::arm, A.GetTriple().getArch());
233 EXPECT_EQ(llvm::Triple::ArchType::arm, B.GetTriple().getArch());
234
235 EXPECT_EQ(ArchSpec::eCore_arm_generic, A.GetCore());
236 EXPECT_EQ(ArchSpec::eCore_arm_armv8l, B.GetCore());
237
238 EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor,
239 A.GetTriple().getVendor());
240 EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor,
241 B.GetTriple().getVendor());
242
243 EXPECT_EQ(llvm::Triple::OSType::Linux, A.GetTriple().getOS());
244 EXPECT_EQ(llvm::Triple::OSType::Linux, B.GetTriple().getOS());
245
246 EXPECT_EQ(llvm::Triple::EnvironmentType::EABIHF,
247 A.GetTriple().getEnvironment());
248 EXPECT_EQ(llvm::Triple::EnvironmentType::GNUEABIHF,
249 B.GetTriple().getEnvironment());
250
251 A.MergeFrom(other: B);
252 EXPECT_EQ(llvm::Triple::ArchType::arm, A.GetTriple().getArch());
253 EXPECT_EQ(ArchSpec::eCore_arm_armv8l, A.GetCore());
254 EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor,
255 A.GetTriple().getVendor());
256 EXPECT_EQ(llvm::Triple::OSType::Linux, A.GetTriple().getOS());
257 EXPECT_EQ(llvm::Triple::EnvironmentType::EABIHF,
258 A.GetTriple().getEnvironment());
259 }
260}
261
262TEST(ArchSpecTest, MergeFromMachOUnknown) {
263 class MyArchSpec : public ArchSpec {
264 public:
265 MyArchSpec() {
266 this->SetTriple("unknown-mach-64");
267 this->m_core = ArchSpec::eCore_uknownMach64;
268 this->m_byte_order = eByteOrderLittle;
269 this->m_flags = 0;
270 }
271 };
272
273 MyArchSpec A;
274 ASSERT_TRUE(A.IsValid());
275 MyArchSpec B;
276 ASSERT_TRUE(B.IsValid());
277 A.MergeFrom(other: B);
278 ASSERT_EQ(A.GetCore(), ArchSpec::eCore_uknownMach64);
279}
280
281TEST(ArchSpecTest, Compatibility) {
282 {
283 ArchSpec A("x86_64-apple-macosx10.12");
284 ArchSpec B("x86_64-apple-macosx10.12");
285 ASSERT_TRUE(A.IsExactMatch(B));
286 ASSERT_TRUE(A.IsCompatibleMatch(B));
287 }
288 {
289 // The version information is auxiliary to support availability but
290 // doesn't affect compatibility.
291 ArchSpec A("x86_64-apple-macosx10.11");
292 ArchSpec B("x86_64-apple-macosx10.12");
293 ASSERT_TRUE(A.IsExactMatch(B));
294 ASSERT_TRUE(A.IsCompatibleMatch(B));
295 }
296 {
297 ArchSpec A("x86_64-apple-macosx10.13");
298 ArchSpec B("x86_64h-apple-macosx10.13");
299 ASSERT_FALSE(A.IsExactMatch(B));
300 ASSERT_TRUE(A.IsCompatibleMatch(B));
301 }
302 {
303 ArchSpec A("x86_64-apple-macosx");
304 ArchSpec B("x86_64-apple-ios-simulator");
305 ASSERT_FALSE(A.IsExactMatch(B));
306 ASSERT_FALSE(A.IsCompatibleMatch(B));
307 }
308 {
309 ArchSpec A("x86_64-*-*");
310 ArchSpec B("x86_64-apple-ios-simulator");
311 ASSERT_FALSE(A.IsExactMatch(B));
312 ASSERT_FALSE(A.IsCompatibleMatch(B));
313 ASSERT_FALSE(B.IsExactMatch(A));
314 ASSERT_FALSE(B.IsCompatibleMatch(A));
315 }
316 {
317 ArchSpec A("x86_64-apple-ios");
318 ArchSpec B("x86_64-apple-ios-simulator");
319 ASSERT_FALSE(A.IsExactMatch(B));
320 ASSERT_FALSE(A.IsCompatibleMatch(B));
321 ASSERT_FALSE(B.IsExactMatch(A));
322 ASSERT_FALSE(B.IsCompatibleMatch(A));
323 }
324 {
325 // FIXME: This is surprisingly not equivalent to "x86_64-*-*".
326 ArchSpec A("x86_64");
327 ArchSpec B("x86_64-apple-ios-simulator");
328 ASSERT_FALSE(A.IsExactMatch(B));
329 ASSERT_TRUE(A.IsCompatibleMatch(B));
330 ASSERT_FALSE(B.IsExactMatch(A));
331 ASSERT_TRUE(B.IsCompatibleMatch(A));
332 }
333 {
334 ArchSpec A("arm64-apple-ios");
335 ArchSpec B("arm64-apple-ios-simulator");
336 ASSERT_FALSE(A.IsExactMatch(B));
337 ASSERT_FALSE(A.IsCompatibleMatch(B));
338 ASSERT_FALSE(B.IsCompatibleMatch(A));
339 ASSERT_FALSE(B.IsCompatibleMatch(A));
340 }
341 {
342 ArchSpec A("arm64-*-*");
343 ArchSpec B("arm64-apple-ios");
344 ASSERT_FALSE(A.IsExactMatch(B));
345 // FIXME: This looks unintuitive and we should investigate whether
346 // this is the desired behavior.
347 ASSERT_FALSE(A.IsCompatibleMatch(B));
348 }
349 {
350 ArchSpec A("x86_64-*-*");
351 ArchSpec B("x86_64-apple-ios-simulator");
352 ASSERT_FALSE(A.IsExactMatch(B));
353 // FIXME: See above, though the extra environment complicates things.
354 ASSERT_FALSE(A.IsCompatibleMatch(B));
355 }
356 {
357 ArchSpec A("x86_64");
358 ArchSpec B("x86_64-apple-macosx10.14");
359 // FIXME: The exact match also looks unintuitive.
360 ASSERT_TRUE(A.IsExactMatch(B));
361 ASSERT_TRUE(A.IsCompatibleMatch(B));
362 }
363 {
364 ArchSpec A("x86_64");
365 ArchSpec B("x86_64-apple-ios12.0.0-macabi");
366 // FIXME: The exact match also looks unintuitive.
367 ASSERT_TRUE(A.IsExactMatch(B));
368 ASSERT_TRUE(A.IsCompatibleMatch(B));
369 }
370 {
371 ArchSpec A("x86_64-apple-ios12.0.0");
372 ArchSpec B("x86_64-apple-ios12.0.0-macabi");
373 ASSERT_FALSE(A.IsExactMatch(B));
374 ASSERT_FALSE(A.IsCompatibleMatch(B));
375 }
376 {
377 ArchSpec A("x86_64-apple-macosx10.14.2");
378 ArchSpec B("x86_64-apple-ios12.0.0-macabi");
379 ASSERT_FALSE(A.IsExactMatch(B));
380 ASSERT_TRUE(A.IsCompatibleMatch(B));
381 }
382 {
383 ArchSpec A("x86_64-apple-macosx10.14.2");
384 ArchSpec B("x86_64-apple-ios12.0.0-macabi");
385 // ios-macabi wins.
386 A.MergeFrom(other: B);
387 ASSERT_TRUE(A.IsExactMatch(B));
388 }
389 {
390 ArchSpec A("x86_64-apple-macosx10.14.2");
391 ArchSpec B("x86_64-apple-ios12.0.0-macabi");
392 ArchSpec C(B);
393 // ios-macabi wins.
394 B.MergeFrom(other: A);
395 ASSERT_TRUE(B.IsExactMatch(C));
396 }
397}
398
399TEST(ArchSpecTest, OperatorBool) {
400 EXPECT_FALSE(ArchSpec());
401 EXPECT_TRUE(ArchSpec("x86_64-pc-linux"));
402}
403
404TEST(ArchSpecTest, TripleComponentsWereSpecified) {
405 {
406 ArchSpec A("");
407 ArchSpec B("-");
408 ArchSpec C("--");
409 ArchSpec D("---");
410
411 ASSERT_FALSE(A.TripleVendorWasSpecified());
412 ASSERT_FALSE(A.TripleOSWasSpecified());
413 ASSERT_FALSE(A.TripleEnvironmentWasSpecified());
414
415 ASSERT_FALSE(B.TripleVendorWasSpecified());
416 ASSERT_FALSE(B.TripleOSWasSpecified());
417 ASSERT_FALSE(B.TripleEnvironmentWasSpecified());
418
419 ASSERT_FALSE(C.TripleVendorWasSpecified());
420 ASSERT_FALSE(C.TripleOSWasSpecified());
421 ASSERT_FALSE(C.TripleEnvironmentWasSpecified());
422
423 ASSERT_FALSE(D.TripleVendorWasSpecified());
424 ASSERT_FALSE(D.TripleOSWasSpecified());
425 ASSERT_FALSE(D.TripleEnvironmentWasSpecified());
426 }
427 {
428 // TODO: llvm::Triple::normalize treats the missing components from these
429 // triples as specified unknown components instead of unspecified
430 // components. We need to either change the behavior in llvm or work around
431 // this in lldb.
432 ArchSpec A("armv7");
433 ArchSpec B("armv7-");
434 ArchSpec C("armv7--");
435 ArchSpec D("armv7---");
436
437 ASSERT_FALSE(A.TripleVendorWasSpecified());
438 ASSERT_FALSE(A.TripleOSWasSpecified());
439 ASSERT_FALSE(A.TripleEnvironmentWasSpecified());
440
441 ASSERT_TRUE(B.TripleVendorWasSpecified());
442 ASSERT_FALSE(B.TripleOSWasSpecified());
443 ASSERT_FALSE(B.TripleEnvironmentWasSpecified());
444
445 ASSERT_TRUE(C.TripleVendorWasSpecified());
446 ASSERT_TRUE(C.TripleOSWasSpecified());
447 ASSERT_FALSE(C.TripleEnvironmentWasSpecified());
448
449 ASSERT_TRUE(D.TripleVendorWasSpecified());
450 ASSERT_TRUE(D.TripleOSWasSpecified());
451 ASSERT_TRUE(D.TripleEnvironmentWasSpecified());
452 }
453 {
454 ArchSpec A("x86_64-unknown");
455 ArchSpec B("powerpc-unknown-linux");
456 ArchSpec C("i386-pc-windows-msvc");
457 ArchSpec D("aarch64-unknown-linux-android");
458
459 ASSERT_TRUE(A.TripleVendorWasSpecified());
460 ASSERT_FALSE(A.TripleOSWasSpecified());
461 ASSERT_FALSE(A.TripleEnvironmentWasSpecified());
462
463 ASSERT_TRUE(B.TripleVendorWasSpecified());
464 ASSERT_TRUE(B.TripleOSWasSpecified());
465 ASSERT_FALSE(B.TripleEnvironmentWasSpecified());
466
467 ASSERT_TRUE(C.TripleVendorWasSpecified());
468 ASSERT_TRUE(C.TripleOSWasSpecified());
469 ASSERT_TRUE(C.TripleEnvironmentWasSpecified());
470
471 ASSERT_TRUE(D.TripleVendorWasSpecified());
472 ASSERT_TRUE(D.TripleOSWasSpecified());
473 ASSERT_TRUE(D.TripleEnvironmentWasSpecified());
474 }
475}
476

source code of lldb/unittests/Utility/ArchSpecTest.cpp