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