xref: /llvm-project/lldb/unittests/Utility/ArchSpecTest.cpp (revision 6d6288ae977bfdb08dc2b731f34d9b1ebfc68748)
1 //===-- ArchSpecTest.cpp ----------------------------------------*- C++ -*-===//
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/MachO.h"
13 
14 using namespace lldb;
15 using namespace lldb_private;
16 
17 TEST(ArchSpecTest, TestParseMachCPUDashSubtypeTripleSimple) {
18 
19   // Success conditions.  Valid cpu/subtype combinations using both - and .
20   ArchSpec AS;
21   EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-10", AS));
22   EXPECT_EQ(12u, AS.GetMachOCPUType());
23   EXPECT_EQ(10u, AS.GetMachOCPUSubType());
24 
25   AS = ArchSpec();
26   EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-15", AS));
27   EXPECT_EQ(12u, AS.GetMachOCPUType());
28   EXPECT_EQ(15u, AS.GetMachOCPUSubType());
29 
30   AS = ArchSpec();
31   EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12.15", AS));
32   EXPECT_EQ(12u, AS.GetMachOCPUType());
33   EXPECT_EQ(15u, AS.GetMachOCPUSubType());
34 
35   // Failure conditions.
36 
37   // Valid string, unknown cpu/subtype.
38   AS = ArchSpec();
39   EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("13.11", AS));
40   EXPECT_EQ(0u, AS.GetMachOCPUType());
41   EXPECT_EQ(0u, AS.GetMachOCPUSubType());
42 
43   // Missing / invalid cpu or subtype
44   AS = ArchSpec();
45   EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("13", AS));
46 
47   AS = ArchSpec();
48   EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("13.A", AS));
49 
50   AS = ArchSpec();
51   EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("A.13", AS));
52 
53   // Empty string.
54   AS = ArchSpec();
55   EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("", AS));
56 }
57 
58 TEST(ArchSpecTest, TestParseMachCPUDashSubtypeTripleExtra) {
59   ArchSpec AS;
60   EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-15-vendor-os", AS));
61   EXPECT_EQ(12u, AS.GetMachOCPUType());
62   EXPECT_EQ(15u, AS.GetMachOCPUSubType());
63   EXPECT_EQ("vendor", AS.GetTriple().getVendorName());
64   EXPECT_EQ("os", AS.GetTriple().getOSName());
65 
66   AS = ArchSpec();
67   EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-10-vendor-os-name", AS));
68   EXPECT_EQ(12u, AS.GetMachOCPUType());
69   EXPECT_EQ(10u, AS.GetMachOCPUSubType());
70   EXPECT_EQ("vendor", AS.GetTriple().getVendorName());
71   EXPECT_EQ("os", AS.GetTriple().getOSName());
72 
73   AS = ArchSpec();
74   EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-15-vendor.os-name", AS));
75   EXPECT_EQ(12u, AS.GetMachOCPUType());
76   EXPECT_EQ(15u, AS.GetMachOCPUSubType());
77   EXPECT_EQ("vendor.os", AS.GetTriple().getVendorName());
78   EXPECT_EQ("name", AS.GetTriple().getOSName());
79 
80   // These there should parse correctly, but the vendor / OS should be defaulted
81   // since they are unrecognized.
82   AS = ArchSpec();
83   EXPECT_TRUE(ParseMachCPUDashSubtypeTriple("12-10-vendor", AS));
84   EXPECT_EQ(12u, AS.GetMachOCPUType());
85   EXPECT_EQ(10u, AS.GetMachOCPUSubType());
86   EXPECT_EQ("apple", AS.GetTriple().getVendorName());
87   EXPECT_EQ("", AS.GetTriple().getOSName());
88 
89   AS = ArchSpec();
90   EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("12.10.10", AS));
91 
92   AS = ArchSpec();
93   EXPECT_FALSE(ParseMachCPUDashSubtypeTriple("12-10.10", AS));
94 }
95 
96 TEST(ArchSpecTest, TestSetTriple) {
97   ArchSpec AS;
98 
99   // Various flavors of valid triples.
100   EXPECT_TRUE(AS.SetTriple("12-10-apple-darwin"));
101   EXPECT_EQ(uint32_t(llvm::MachO::CPU_TYPE_ARM), AS.GetMachOCPUType());
102   EXPECT_EQ(10u, AS.GetMachOCPUSubType());
103   EXPECT_TRUE(llvm::StringRef(AS.GetTriple().str())
104                   .consume_front("armv7f-apple-darwin"));
105   EXPECT_EQ(ArchSpec::eCore_arm_armv7f, AS.GetCore());
106 
107   AS = ArchSpec();
108   EXPECT_TRUE(AS.SetTriple("18.100-apple-darwin"));
109   EXPECT_EQ(uint32_t(llvm::MachO::CPU_TYPE_POWERPC), AS.GetMachOCPUType());
110   EXPECT_EQ(100u, AS.GetMachOCPUSubType());
111   EXPECT_TRUE(llvm::StringRef(AS.GetTriple().str())
112                   .consume_front("powerpc-apple-darwin"));
113   EXPECT_EQ(ArchSpec::eCore_ppc_ppc970, AS.GetCore());
114 
115   AS = ArchSpec();
116   EXPECT_TRUE(AS.SetTriple("i686-pc-windows"));
117   EXPECT_EQ(llvm::Triple::x86, AS.GetTriple().getArch());
118   EXPECT_EQ(llvm::Triple::PC, AS.GetTriple().getVendor());
119   EXPECT_EQ(llvm::Triple::Win32, AS.GetTriple().getOS());
120   EXPECT_TRUE(
121       llvm::StringRef(AS.GetTriple().str()).consume_front("i686-pc-windows"));
122   EXPECT_STREQ("i686", AS.GetArchitectureName());
123   EXPECT_EQ(ArchSpec::eCore_x86_32_i686, AS.GetCore());
124 
125   // Various flavors of invalid triples.
126   AS = ArchSpec();
127   EXPECT_FALSE(AS.SetTriple("unknown-unknown-unknown"));
128 
129   AS = ArchSpec();
130   EXPECT_FALSE(AS.SetTriple("unknown"));
131 
132   AS = ArchSpec();
133   EXPECT_FALSE(AS.SetTriple(""));
134 }
135 
136 TEST(ArchSpecTest, MergeFrom) {
137   {
138     ArchSpec A;
139     ArchSpec B("x86_64-pc-linux");
140 
141     EXPECT_FALSE(A.IsValid());
142     ASSERT_TRUE(B.IsValid());
143     EXPECT_EQ(llvm::Triple::ArchType::x86_64, B.GetTriple().getArch());
144     EXPECT_EQ(llvm::Triple::VendorType::PC, B.GetTriple().getVendor());
145     EXPECT_EQ(llvm::Triple::OSType::Linux, B.GetTriple().getOS());
146     EXPECT_EQ(ArchSpec::eCore_x86_64_x86_64, B.GetCore());
147 
148     A.MergeFrom(B);
149     ASSERT_TRUE(A.IsValid());
150     EXPECT_EQ(llvm::Triple::ArchType::x86_64, A.GetTriple().getArch());
151     EXPECT_EQ(llvm::Triple::VendorType::PC, A.GetTriple().getVendor());
152     EXPECT_EQ(llvm::Triple::OSType::Linux, A.GetTriple().getOS());
153     EXPECT_EQ(ArchSpec::eCore_x86_64_x86_64, A.GetCore());
154   }
155   {
156     ArchSpec A("aarch64");
157     ArchSpec B("aarch64--linux-android");
158 
159     EXPECT_TRUE(A.IsValid());
160     EXPECT_TRUE(B.IsValid());
161 
162     EXPECT_EQ(llvm::Triple::ArchType::aarch64, B.GetTriple().getArch());
163     EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor,
164               B.GetTriple().getVendor());
165     EXPECT_EQ(llvm::Triple::OSType::Linux, B.GetTriple().getOS());
166     EXPECT_EQ(llvm::Triple::EnvironmentType::Android,
167               B.GetTriple().getEnvironment());
168 
169     A.MergeFrom(B);
170     EXPECT_EQ(llvm::Triple::ArchType::aarch64, A.GetTriple().getArch());
171     EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor,
172               A.GetTriple().getVendor());
173     EXPECT_EQ(llvm::Triple::OSType::Linux, A.GetTriple().getOS());
174     EXPECT_EQ(llvm::Triple::EnvironmentType::Android,
175               A.GetTriple().getEnvironment());
176   }
177 }
178 
179 TEST(ArchSpecTest, MergeFromMachOUnknown) {
180   class MyArchSpec : public ArchSpec {
181   public:
182     MyArchSpec() {
183       this->SetTriple("unknown-mach-64");
184       this->m_core = ArchSpec::eCore_uknownMach64;
185       this->m_byte_order = eByteOrderLittle;
186       this->m_flags = 0;
187     }
188   };
189 
190   MyArchSpec A;
191   ASSERT_TRUE(A.IsValid());
192   MyArchSpec B;
193   ASSERT_TRUE(B.IsValid());
194   A.MergeFrom(B);
195   ASSERT_EQ(A.GetCore(), ArchSpec::eCore_uknownMach64);
196 }
197 
198 TEST(ArchSpecTest, Compatibility) {
199   {
200     ArchSpec A("x86_64-apple-macosx10.12");
201     ArchSpec B("x86_64-apple-macosx10.12");
202     ASSERT_TRUE(A.IsExactMatch(B));
203     ASSERT_TRUE(A.IsCompatibleMatch(B));
204   }
205   {
206     // The version information is auxiliary to support availablity but
207     // doesn't affect compatibility.
208     ArchSpec A("x86_64-apple-macosx10.11");
209     ArchSpec B("x86_64-apple-macosx10.12");
210     ASSERT_TRUE(A.IsExactMatch(B));
211     ASSERT_TRUE(A.IsCompatibleMatch(B));
212   }
213   {
214     ArchSpec A("x86_64-apple-macosx10.13");
215     ArchSpec B("x86_64h-apple-macosx10.13");
216     ASSERT_FALSE(A.IsExactMatch(B));
217     ASSERT_TRUE(A.IsCompatibleMatch(B));
218   }
219   {
220     ArchSpec A("x86_64-apple-macosx");
221     ArchSpec B("x86_64-apple-ios-simulator");
222     ASSERT_FALSE(A.IsExactMatch(B));
223     ASSERT_FALSE(A.IsCompatibleMatch(B));
224   }
225   {
226     ArchSpec A("x86_64-*-*");
227     ArchSpec B("x86_64-apple-ios-simulator");
228     ASSERT_FALSE(A.IsExactMatch(B));
229     ASSERT_FALSE(A.IsCompatibleMatch(B));
230   }
231   {
232     ArchSpec A("arm64-*-*");
233     ArchSpec B("arm64-apple-ios");
234     ASSERT_FALSE(A.IsExactMatch(B));
235     // FIXME: This looks unintuitive and we should investigate whether
236     // this is the desired behavior.
237     ASSERT_FALSE(A.IsCompatibleMatch(B));
238   }
239   {
240     ArchSpec A("x86_64-*-*");
241     ArchSpec B("x86_64-apple-ios-simulator");
242     ASSERT_FALSE(A.IsExactMatch(B));
243     // FIXME: See above, though the extra environment complicates things.
244     ASSERT_FALSE(A.IsCompatibleMatch(B));
245   }
246   {
247     ArchSpec A("x86_64");
248     ArchSpec B("x86_64-apple-macosx10.14");
249     // FIXME: The exact match also looks unintuitive.
250     ASSERT_TRUE(A.IsExactMatch(B));
251     ASSERT_TRUE(A.IsCompatibleMatch(B));
252   }
253 }
254 
255 TEST(ArchSpecTest, OperatorBool) {
256   EXPECT_FALSE(ArchSpec());
257   EXPECT_TRUE(ArchSpec("x86_64-pc-linux"));
258 }
259 
260 TEST(ArchSpecTest, TripleComponentsWereSpecified) {
261   {
262     ArchSpec A("");
263     ArchSpec B("-");
264     ArchSpec C("--");
265     ArchSpec D("---");
266 
267     ASSERT_FALSE(A.TripleVendorWasSpecified());
268     ASSERT_FALSE(A.TripleOSWasSpecified());
269     ASSERT_FALSE(A.TripleEnvironmentWasSpecified());
270 
271     ASSERT_FALSE(B.TripleVendorWasSpecified());
272     ASSERT_FALSE(B.TripleOSWasSpecified());
273     ASSERT_FALSE(B.TripleEnvironmentWasSpecified());
274 
275     ASSERT_FALSE(C.TripleVendorWasSpecified());
276     ASSERT_FALSE(C.TripleOSWasSpecified());
277     ASSERT_FALSE(C.TripleEnvironmentWasSpecified());
278 
279     ASSERT_FALSE(D.TripleVendorWasSpecified());
280     ASSERT_FALSE(D.TripleOSWasSpecified());
281     ASSERT_FALSE(D.TripleEnvironmentWasSpecified());
282   }
283   {
284     // TODO: llvm::Triple::normalize treats the missing components from these
285     // triples as specified unknown components instead of unspecified
286     // components. We need to either change the behavior in llvm or work around
287     // this in lldb.
288     ArchSpec A("armv7");
289     ArchSpec B("armv7-");
290     ArchSpec C("armv7--");
291     ArchSpec D("armv7---");
292 
293     ASSERT_FALSE(A.TripleVendorWasSpecified());
294     ASSERT_FALSE(A.TripleOSWasSpecified());
295     ASSERT_FALSE(A.TripleEnvironmentWasSpecified());
296 
297     ASSERT_TRUE(B.TripleVendorWasSpecified());
298     ASSERT_FALSE(B.TripleOSWasSpecified());
299     ASSERT_FALSE(B.TripleEnvironmentWasSpecified());
300 
301     ASSERT_TRUE(C.TripleVendorWasSpecified());
302     ASSERT_TRUE(C.TripleOSWasSpecified());
303     ASSERT_FALSE(C.TripleEnvironmentWasSpecified());
304 
305     ASSERT_TRUE(D.TripleVendorWasSpecified());
306     ASSERT_TRUE(D.TripleOSWasSpecified());
307     ASSERT_TRUE(D.TripleEnvironmentWasSpecified());
308   }
309   {
310     ArchSpec A("x86_64-unknown");
311     ArchSpec B("powerpc-unknown-linux");
312     ArchSpec C("i386-pc-windows-msvc");
313     ArchSpec D("aarch64-unknown-linux-android");
314 
315     ASSERT_TRUE(A.TripleVendorWasSpecified());
316     ASSERT_FALSE(A.TripleOSWasSpecified());
317     ASSERT_FALSE(A.TripleEnvironmentWasSpecified());
318 
319     ASSERT_TRUE(B.TripleVendorWasSpecified());
320     ASSERT_TRUE(B.TripleOSWasSpecified());
321     ASSERT_FALSE(B.TripleEnvironmentWasSpecified());
322 
323     ASSERT_TRUE(C.TripleVendorWasSpecified());
324     ASSERT_TRUE(C.TripleOSWasSpecified());
325     ASSERT_TRUE(C.TripleEnvironmentWasSpecified());
326 
327     ASSERT_TRUE(D.TripleVendorWasSpecified());
328     ASSERT_TRUE(D.TripleOSWasSpecified());
329     ASSERT_TRUE(D.TripleEnvironmentWasSpecified());
330   }
331 }
332