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 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 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 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 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 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 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 } 309 { 310 ArchSpec A("arm64-apple-ios"); 311 ArchSpec B("arm64-apple-ios-simulator"); 312 ASSERT_FALSE(A.IsExactMatch(B)); 313 ASSERT_FALSE(A.IsCompatibleMatch(B)); 314 ASSERT_FALSE(B.IsCompatibleMatch(A)); 315 ASSERT_FALSE(B.IsCompatibleMatch(A)); 316 } 317 { 318 ArchSpec A("arm64-*-*"); 319 ArchSpec B("arm64-apple-ios"); 320 ASSERT_FALSE(A.IsExactMatch(B)); 321 // FIXME: This looks unintuitive and we should investigate whether 322 // this is the desired behavior. 323 ASSERT_FALSE(A.IsCompatibleMatch(B)); 324 } 325 { 326 ArchSpec A("x86_64-*-*"); 327 ArchSpec B("x86_64-apple-ios-simulator"); 328 ASSERT_FALSE(A.IsExactMatch(B)); 329 // FIXME: See above, though the extra environment complicates things. 330 ASSERT_FALSE(A.IsCompatibleMatch(B)); 331 } 332 { 333 ArchSpec A("x86_64"); 334 ArchSpec B("x86_64-apple-macosx10.14"); 335 // FIXME: The exact match also looks unintuitive. 336 ASSERT_TRUE(A.IsExactMatch(B)); 337 ASSERT_TRUE(A.IsCompatibleMatch(B)); 338 } 339 { 340 ArchSpec A("x86_64"); 341 ArchSpec B("x86_64-apple-ios12.0.0-macabi"); 342 // FIXME: The exact match also looks unintuitive. 343 ASSERT_TRUE(A.IsExactMatch(B)); 344 ASSERT_TRUE(A.IsCompatibleMatch(B)); 345 } 346 { 347 ArchSpec A("x86_64-apple-ios12.0.0"); 348 ArchSpec B("x86_64-apple-ios12.0.0-macabi"); 349 ASSERT_FALSE(A.IsExactMatch(B)); 350 ASSERT_FALSE(A.IsCompatibleMatch(B)); 351 } 352 { 353 ArchSpec A("x86_64-apple-macosx10.14.2"); 354 ArchSpec B("x86_64-apple-ios12.0.0-macabi"); 355 ASSERT_FALSE(A.IsExactMatch(B)); 356 ASSERT_TRUE(A.IsCompatibleMatch(B)); 357 } 358 { 359 ArchSpec A("x86_64-apple-macosx10.14.2"); 360 ArchSpec B("x86_64-apple-ios12.0.0-macabi"); 361 // ios-macabi wins. 362 A.MergeFrom(B); 363 ASSERT_TRUE(A.IsExactMatch(B)); 364 } 365 { 366 ArchSpec A("x86_64-apple-macosx10.14.2"); 367 ArchSpec B("x86_64-apple-ios12.0.0-macabi"); 368 ArchSpec C(B); 369 // ios-macabi wins. 370 B.MergeFrom(A); 371 ASSERT_TRUE(B.IsExactMatch(C)); 372 } 373 } 374 375 TEST(ArchSpecTest, OperatorBool) { 376 EXPECT_FALSE(ArchSpec()); 377 EXPECT_TRUE(ArchSpec("x86_64-pc-linux")); 378 } 379 380 TEST(ArchSpecTest, TripleComponentsWereSpecified) { 381 { 382 ArchSpec A(""); 383 ArchSpec B("-"); 384 ArchSpec C("--"); 385 ArchSpec D("---"); 386 387 ASSERT_FALSE(A.TripleVendorWasSpecified()); 388 ASSERT_FALSE(A.TripleOSWasSpecified()); 389 ASSERT_FALSE(A.TripleEnvironmentWasSpecified()); 390 391 ASSERT_FALSE(B.TripleVendorWasSpecified()); 392 ASSERT_FALSE(B.TripleOSWasSpecified()); 393 ASSERT_FALSE(B.TripleEnvironmentWasSpecified()); 394 395 ASSERT_FALSE(C.TripleVendorWasSpecified()); 396 ASSERT_FALSE(C.TripleOSWasSpecified()); 397 ASSERT_FALSE(C.TripleEnvironmentWasSpecified()); 398 399 ASSERT_FALSE(D.TripleVendorWasSpecified()); 400 ASSERT_FALSE(D.TripleOSWasSpecified()); 401 ASSERT_FALSE(D.TripleEnvironmentWasSpecified()); 402 } 403 { 404 // TODO: llvm::Triple::normalize treats the missing components from these 405 // triples as specified unknown components instead of unspecified 406 // components. We need to either change the behavior in llvm or work around 407 // this in lldb. 408 ArchSpec A("armv7"); 409 ArchSpec B("armv7-"); 410 ArchSpec C("armv7--"); 411 ArchSpec D("armv7---"); 412 413 ASSERT_FALSE(A.TripleVendorWasSpecified()); 414 ASSERT_FALSE(A.TripleOSWasSpecified()); 415 ASSERT_FALSE(A.TripleEnvironmentWasSpecified()); 416 417 ASSERT_TRUE(B.TripleVendorWasSpecified()); 418 ASSERT_FALSE(B.TripleOSWasSpecified()); 419 ASSERT_FALSE(B.TripleEnvironmentWasSpecified()); 420 421 ASSERT_TRUE(C.TripleVendorWasSpecified()); 422 ASSERT_TRUE(C.TripleOSWasSpecified()); 423 ASSERT_FALSE(C.TripleEnvironmentWasSpecified()); 424 425 ASSERT_TRUE(D.TripleVendorWasSpecified()); 426 ASSERT_TRUE(D.TripleOSWasSpecified()); 427 ASSERT_TRUE(D.TripleEnvironmentWasSpecified()); 428 } 429 { 430 ArchSpec A("x86_64-unknown"); 431 ArchSpec B("powerpc-unknown-linux"); 432 ArchSpec C("i386-pc-windows-msvc"); 433 ArchSpec D("aarch64-unknown-linux-android"); 434 435 ASSERT_TRUE(A.TripleVendorWasSpecified()); 436 ASSERT_FALSE(A.TripleOSWasSpecified()); 437 ASSERT_FALSE(A.TripleEnvironmentWasSpecified()); 438 439 ASSERT_TRUE(B.TripleVendorWasSpecified()); 440 ASSERT_TRUE(B.TripleOSWasSpecified()); 441 ASSERT_FALSE(B.TripleEnvironmentWasSpecified()); 442 443 ASSERT_TRUE(C.TripleVendorWasSpecified()); 444 ASSERT_TRUE(C.TripleOSWasSpecified()); 445 ASSERT_TRUE(C.TripleEnvironmentWasSpecified()); 446 447 ASSERT_TRUE(D.TripleVendorWasSpecified()); 448 ASSERT_TRUE(D.TripleOSWasSpecified()); 449 ASSERT_TRUE(D.TripleEnvironmentWasSpecified()); 450 } 451 } 452 453 TEST(ArchSpecTest, YAML) { 454 std::string buffer; 455 llvm::raw_string_ostream os(buffer); 456 457 // Serialize. 458 llvm::yaml::Output yout(os); 459 std::vector<ArchSpec> archs = {ArchSpec("x86_64-pc-linux"), 460 ArchSpec("x86_64-apple-macosx10.12"), 461 ArchSpec("i686-pc-windows")}; 462 yout << archs; 463 os.flush(); 464 465 // Deserialize. 466 std::vector<ArchSpec> deserialized; 467 llvm::yaml::Input yin(buffer); 468 yin >> deserialized; 469 470 EXPECT_EQ(archs, deserialized); 471 } 472