xref: /llvm-project/lldb/unittests/Utility/ArchSpecTest.cpp (revision de252e7777c1c6b45626a58aa34ea99dee58cc40)
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 
15 using namespace lldb;
16 using namespace lldb_private;
17 
18 TEST(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 
59 TEST(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 
97 TEST(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   AS = ArchSpec();
133   EXPECT_TRUE(AS.SetTriple("amd64-unknown-openbsd"));
134   EXPECT_EQ(llvm::Triple::x86_64, AS.GetTriple().getArch());
135   EXPECT_STREQ("amd64", AS.GetArchitectureName());
136   EXPECT_EQ(ArchSpec::eCore_x86_64_amd64, AS.GetCore());
137 
138   // Various flavors of invalid triples.
139   AS = ArchSpec();
140   EXPECT_FALSE(AS.SetTriple("unknown-unknown-unknown"));
141 
142   AS = ArchSpec();
143   EXPECT_FALSE(AS.SetTriple("unknown"));
144 
145   AS = ArchSpec();
146   EXPECT_FALSE(AS.SetTriple(""));
147 }
148 
149 TEST(ArchSpecTest, MergeFrom) {
150   {
151     ArchSpec A;
152     ArchSpec B("x86_64-pc-linux");
153 
154     EXPECT_FALSE(A.IsValid());
155     ASSERT_TRUE(B.IsValid());
156     EXPECT_EQ(llvm::Triple::ArchType::x86_64, B.GetTriple().getArch());
157     EXPECT_EQ(llvm::Triple::VendorType::PC, B.GetTriple().getVendor());
158     EXPECT_EQ(llvm::Triple::OSType::Linux, B.GetTriple().getOS());
159     EXPECT_EQ(ArchSpec::eCore_x86_64_x86_64, B.GetCore());
160 
161     A.MergeFrom(B);
162     ASSERT_TRUE(A.IsValid());
163     EXPECT_EQ(llvm::Triple::ArchType::x86_64, A.GetTriple().getArch());
164     EXPECT_EQ(llvm::Triple::VendorType::PC, A.GetTriple().getVendor());
165     EXPECT_EQ(llvm::Triple::OSType::Linux, A.GetTriple().getOS());
166     EXPECT_EQ(ArchSpec::eCore_x86_64_x86_64, A.GetCore());
167   }
168   {
169     ArchSpec A("aarch64");
170     ArchSpec B("aarch64--linux-android");
171 
172     ArchSpec C("arm64_32");
173     ArchSpec D("arm64_32--watchos");
174 
175     EXPECT_TRUE(A.IsValid());
176     EXPECT_TRUE(B.IsValid());
177     EXPECT_TRUE(C.IsValid());
178     EXPECT_TRUE(D.IsValid());
179 
180     EXPECT_EQ(llvm::Triple::ArchType::aarch64, B.GetTriple().getArch());
181     EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor,
182               B.GetTriple().getVendor());
183     EXPECT_EQ(llvm::Triple::OSType::Linux, B.GetTriple().getOS());
184     EXPECT_EQ(llvm::Triple::EnvironmentType::Android,
185               B.GetTriple().getEnvironment());
186 
187     A.MergeFrom(B);
188     EXPECT_EQ(llvm::Triple::ArchType::aarch64, A.GetTriple().getArch());
189     EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor,
190               A.GetTriple().getVendor());
191     EXPECT_EQ(llvm::Triple::OSType::Linux, A.GetTriple().getOS());
192     EXPECT_EQ(llvm::Triple::EnvironmentType::Android,
193               A.GetTriple().getEnvironment());
194 
195     EXPECT_EQ(llvm::Triple::ArchType::aarch64_32, D.GetTriple().getArch());
196     EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor,
197               D.GetTriple().getVendor());
198     EXPECT_EQ(llvm::Triple::OSType::WatchOS, D.GetTriple().getOS());
199 
200     C.MergeFrom(D);
201     EXPECT_EQ(llvm::Triple::ArchType::aarch64_32, C.GetTriple().getArch());
202     EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor,
203               C.GetTriple().getVendor());
204     EXPECT_EQ(llvm::Triple::OSType::WatchOS, C.GetTriple().getOS());
205   }
206   {
207     ArchSpec A, B;
208     A.SetArchitecture(eArchTypeELF, llvm::ELF::EM_ARM,
209                       LLDB_INVALID_CPUTYPE, llvm::ELF::ELFOSABI_NONE);
210     B.SetArchitecture(eArchTypeELF, llvm::ELF::EM_ARM,
211                       LLDB_INVALID_CPUTYPE, llvm::ELF::ELFOSABI_LINUX);
212 
213     EXPECT_TRUE(A.IsValid());
214     EXPECT_TRUE(B.IsValid());
215 
216     EXPECT_EQ(llvm::Triple::ArchType::arm, B.GetTriple().getArch());
217     EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor,
218               B.GetTriple().getVendor());
219     EXPECT_EQ(llvm::Triple::OSType::Linux, B.GetTriple().getOS());
220     EXPECT_EQ(llvm::Triple::EnvironmentType::UnknownEnvironment,
221               B.GetTriple().getEnvironment());
222 
223     A.MergeFrom(B);
224     EXPECT_EQ(llvm::Triple::ArchType::arm, A.GetTriple().getArch());
225     EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor,
226               A.GetTriple().getVendor());
227     EXPECT_EQ(llvm::Triple::OSType::Linux, A.GetTriple().getOS());
228     EXPECT_EQ(llvm::Triple::EnvironmentType::UnknownEnvironment,
229               A.GetTriple().getEnvironment());
230   }
231   {
232     ArchSpec A("arm--linux-eabihf");
233     ArchSpec B("armv8l--linux-gnueabihf");
234 
235     EXPECT_TRUE(A.IsValid());
236     EXPECT_TRUE(B.IsValid());
237 
238     EXPECT_EQ(llvm::Triple::ArchType::arm, A.GetTriple().getArch());
239     EXPECT_EQ(llvm::Triple::ArchType::arm, B.GetTriple().getArch());
240 
241     EXPECT_EQ(ArchSpec::eCore_arm_generic, A.GetCore());
242     EXPECT_EQ(ArchSpec::eCore_arm_armv8l, B.GetCore());
243 
244     EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor,
245               A.GetTriple().getVendor());
246     EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor,
247               B.GetTriple().getVendor());
248 
249     EXPECT_EQ(llvm::Triple::OSType::Linux, A.GetTriple().getOS());
250     EXPECT_EQ(llvm::Triple::OSType::Linux, B.GetTriple().getOS());
251 
252     EXPECT_EQ(llvm::Triple::EnvironmentType::EABIHF,
253               A.GetTriple().getEnvironment());
254     EXPECT_EQ(llvm::Triple::EnvironmentType::GNUEABIHF,
255               B.GetTriple().getEnvironment());
256 
257     A.MergeFrom(B);
258     EXPECT_EQ(llvm::Triple::ArchType::arm, A.GetTriple().getArch());
259     EXPECT_EQ(ArchSpec::eCore_arm_armv8l, A.GetCore());
260     EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor,
261               A.GetTriple().getVendor());
262     EXPECT_EQ(llvm::Triple::OSType::Linux, A.GetTriple().getOS());
263     EXPECT_EQ(llvm::Triple::EnvironmentType::EABIHF,
264               A.GetTriple().getEnvironment());
265   }
266 }
267 
268 TEST(ArchSpecTest, MergeFromMachOUnknown) {
269   class MyArchSpec : public ArchSpec {
270   public:
271     MyArchSpec() {
272       this->SetTriple("unknown-mach-64");
273       this->m_core = ArchSpec::eCore_uknownMach64;
274       this->m_byte_order = eByteOrderLittle;
275       this->m_flags = 0;
276     }
277   };
278 
279   MyArchSpec A;
280   ASSERT_TRUE(A.IsValid());
281   MyArchSpec B;
282   ASSERT_TRUE(B.IsValid());
283   A.MergeFrom(B);
284   ASSERT_EQ(A.GetCore(), ArchSpec::eCore_uknownMach64);
285 }
286 
287 TEST(ArchSpecTest, Compatibility) {
288   {
289     ArchSpec A("x86_64-apple-macosx10.12");
290     ArchSpec B("x86_64-apple-macosx10.12");
291     ASSERT_TRUE(A.IsExactMatch(B));
292     ASSERT_TRUE(A.IsCompatibleMatch(B));
293   }
294   {
295     // The version information is auxiliary to support availability but
296     // doesn't affect compatibility.
297     ArchSpec A("x86_64-apple-macosx10.11");
298     ArchSpec B("x86_64-apple-macosx10.12");
299     ASSERT_TRUE(A.IsExactMatch(B));
300     ASSERT_TRUE(A.IsCompatibleMatch(B));
301   }
302   {
303     ArchSpec A("x86_64-apple-macosx10.13");
304     ArchSpec B("x86_64h-apple-macosx10.13");
305     ASSERT_FALSE(A.IsExactMatch(B));
306     ASSERT_TRUE(A.IsCompatibleMatch(B));
307   }
308   {
309     ArchSpec A("x86_64-apple-macosx");
310     ArchSpec B("x86_64-apple-ios-simulator");
311     ASSERT_FALSE(A.IsExactMatch(B));
312     ASSERT_FALSE(A.IsCompatibleMatch(B));
313   }
314   {
315     ArchSpec A("x86_64-*-*");
316     ArchSpec B("x86_64-apple-ios-simulator");
317     ASSERT_FALSE(A.IsExactMatch(B));
318     ASSERT_FALSE(A.IsCompatibleMatch(B));
319     ASSERT_FALSE(B.IsExactMatch(A));
320     ASSERT_FALSE(B.IsCompatibleMatch(A));
321   }
322   {
323     ArchSpec A("x86_64-apple-ios");
324     ArchSpec B("x86_64-apple-ios-simulator");
325     ASSERT_FALSE(A.IsExactMatch(B));
326     ASSERT_FALSE(A.IsCompatibleMatch(B));
327     ASSERT_FALSE(B.IsExactMatch(A));
328     ASSERT_FALSE(B.IsCompatibleMatch(A));
329   }
330   {
331     // FIXME: This is surprisingly not equivalent to "x86_64-*-*".
332     ArchSpec A("x86_64");
333     ArchSpec B("x86_64-apple-ios-simulator");
334     ASSERT_FALSE(A.IsExactMatch(B));
335     ASSERT_TRUE(A.IsCompatibleMatch(B));
336     ASSERT_FALSE(B.IsExactMatch(A));
337     ASSERT_TRUE(B.IsCompatibleMatch(A));
338   }
339   {
340     ArchSpec A("arm64-apple-ios");
341     ArchSpec B("arm64-apple-ios-simulator");
342     ASSERT_FALSE(A.IsExactMatch(B));
343     ASSERT_FALSE(A.IsCompatibleMatch(B));
344     ASSERT_FALSE(B.IsCompatibleMatch(A));
345     ASSERT_FALSE(B.IsCompatibleMatch(A));
346   }
347   {
348     ArchSpec A("arm64-*-*");
349     ArchSpec B("arm64-apple-ios");
350     ASSERT_FALSE(A.IsExactMatch(B));
351     // FIXME: This looks unintuitive and we should investigate whether
352     // this is the desired behavior.
353     ASSERT_FALSE(A.IsCompatibleMatch(B));
354   }
355   {
356     ArchSpec A("x86_64-*-*");
357     ArchSpec B("x86_64-apple-ios-simulator");
358     ASSERT_FALSE(A.IsExactMatch(B));
359     // FIXME: See above, though the extra environment complicates things.
360     ASSERT_FALSE(A.IsCompatibleMatch(B));
361   }
362   {
363     ArchSpec A("x86_64");
364     ArchSpec B("x86_64-apple-macosx10.14");
365     // FIXME: The exact match also looks unintuitive.
366     ASSERT_TRUE(A.IsExactMatch(B));
367     ASSERT_TRUE(A.IsCompatibleMatch(B));
368   }
369   {
370     ArchSpec A("x86_64");
371     ArchSpec B("x86_64-apple-ios12.0.0-macabi");
372     // FIXME: The exact match also looks unintuitive.
373     ASSERT_TRUE(A.IsExactMatch(B));
374     ASSERT_TRUE(A.IsCompatibleMatch(B));
375   }
376   {
377     ArchSpec A("x86_64-apple-ios12.0.0");
378     ArchSpec B("x86_64-apple-ios12.0.0-macabi");
379     ASSERT_FALSE(A.IsExactMatch(B));
380     ASSERT_FALSE(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     ASSERT_FALSE(A.IsExactMatch(B));
386     ASSERT_TRUE(A.IsCompatibleMatch(B));
387   }
388   {
389     ArchSpec A("x86_64-apple-macosx10.14.2");
390     ArchSpec B("x86_64-apple-ios12.0.0-macabi");
391     // ios-macabi wins.
392     A.MergeFrom(B);
393     ASSERT_TRUE(A.IsExactMatch(B));
394   }
395   {
396     ArchSpec A("x86_64-apple-macosx10.14.2");
397     ArchSpec B("x86_64-apple-ios12.0.0-macabi");
398     ArchSpec C(B);
399     // ios-macabi wins.
400     B.MergeFrom(A);
401     ASSERT_TRUE(B.IsExactMatch(C));
402   }
403 }
404 
405 TEST(ArchSpecTest, OperatorBool) {
406   EXPECT_FALSE(ArchSpec());
407   EXPECT_TRUE(ArchSpec("x86_64-pc-linux"));
408 }
409 
410 TEST(ArchSpecTest, TripleComponentsWereSpecified) {
411   {
412     ArchSpec A("");
413     ArchSpec B("-");
414     ArchSpec C("--");
415     ArchSpec D("---");
416 
417     ASSERT_FALSE(A.TripleVendorWasSpecified());
418     ASSERT_FALSE(A.TripleOSWasSpecified());
419     ASSERT_FALSE(A.TripleEnvironmentWasSpecified());
420 
421     ASSERT_FALSE(B.TripleVendorWasSpecified());
422     ASSERT_FALSE(B.TripleOSWasSpecified());
423     ASSERT_FALSE(B.TripleEnvironmentWasSpecified());
424 
425     ASSERT_FALSE(C.TripleVendorWasSpecified());
426     ASSERT_FALSE(C.TripleOSWasSpecified());
427     ASSERT_FALSE(C.TripleEnvironmentWasSpecified());
428 
429     ASSERT_FALSE(D.TripleVendorWasSpecified());
430     ASSERT_FALSE(D.TripleOSWasSpecified());
431     ASSERT_FALSE(D.TripleEnvironmentWasSpecified());
432   }
433   {
434     // TODO: llvm::Triple::normalize treats the missing components from these
435     // triples as specified unknown components instead of unspecified
436     // components. We need to either change the behavior in llvm or work around
437     // this in lldb.
438     ArchSpec A("armv7");
439     ArchSpec B("armv7-");
440     ArchSpec C("armv7--");
441     ArchSpec D("armv7---");
442 
443     ASSERT_FALSE(A.TripleVendorWasSpecified());
444     ASSERT_FALSE(A.TripleOSWasSpecified());
445     ASSERT_FALSE(A.TripleEnvironmentWasSpecified());
446 
447     ASSERT_TRUE(B.TripleVendorWasSpecified());
448     ASSERT_FALSE(B.TripleOSWasSpecified());
449     ASSERT_FALSE(B.TripleEnvironmentWasSpecified());
450 
451     ASSERT_TRUE(C.TripleVendorWasSpecified());
452     ASSERT_TRUE(C.TripleOSWasSpecified());
453     ASSERT_FALSE(C.TripleEnvironmentWasSpecified());
454 
455     ASSERT_TRUE(D.TripleVendorWasSpecified());
456     ASSERT_TRUE(D.TripleOSWasSpecified());
457     ASSERT_TRUE(D.TripleEnvironmentWasSpecified());
458   }
459   {
460     ArchSpec A("x86_64-unknown");
461     ArchSpec B("powerpc-unknown-linux");
462     ArchSpec C("i386-pc-windows-msvc");
463     ArchSpec D("aarch64-unknown-linux-android");
464 
465     ASSERT_TRUE(A.TripleVendorWasSpecified());
466     ASSERT_FALSE(A.TripleOSWasSpecified());
467     ASSERT_FALSE(A.TripleEnvironmentWasSpecified());
468 
469     ASSERT_TRUE(B.TripleVendorWasSpecified());
470     ASSERT_TRUE(B.TripleOSWasSpecified());
471     ASSERT_FALSE(B.TripleEnvironmentWasSpecified());
472 
473     ASSERT_TRUE(C.TripleVendorWasSpecified());
474     ASSERT_TRUE(C.TripleOSWasSpecified());
475     ASSERT_TRUE(C.TripleEnvironmentWasSpecified());
476 
477     ASSERT_TRUE(D.TripleVendorWasSpecified());
478     ASSERT_TRUE(D.TripleOSWasSpecified());
479     ASSERT_TRUE(D.TripleEnvironmentWasSpecified());
480   }
481 }
482