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