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 #include "llvm/BinaryFormat/ELF.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 // Various flavors of invalid triples. 127 AS = ArchSpec(); 128 EXPECT_FALSE(AS.SetTriple("unknown-unknown-unknown")); 129 130 AS = ArchSpec(); 131 EXPECT_FALSE(AS.SetTriple("unknown")); 132 133 AS = ArchSpec(); 134 EXPECT_FALSE(AS.SetTriple("")); 135 } 136 137 TEST(ArchSpecTest, MergeFrom) { 138 { 139 ArchSpec A; 140 ArchSpec B("x86_64-pc-linux"); 141 142 EXPECT_FALSE(A.IsValid()); 143 ASSERT_TRUE(B.IsValid()); 144 EXPECT_EQ(llvm::Triple::ArchType::x86_64, B.GetTriple().getArch()); 145 EXPECT_EQ(llvm::Triple::VendorType::PC, B.GetTriple().getVendor()); 146 EXPECT_EQ(llvm::Triple::OSType::Linux, B.GetTriple().getOS()); 147 EXPECT_EQ(ArchSpec::eCore_x86_64_x86_64, B.GetCore()); 148 149 A.MergeFrom(B); 150 ASSERT_TRUE(A.IsValid()); 151 EXPECT_EQ(llvm::Triple::ArchType::x86_64, A.GetTriple().getArch()); 152 EXPECT_EQ(llvm::Triple::VendorType::PC, A.GetTriple().getVendor()); 153 EXPECT_EQ(llvm::Triple::OSType::Linux, A.GetTriple().getOS()); 154 EXPECT_EQ(ArchSpec::eCore_x86_64_x86_64, A.GetCore()); 155 } 156 { 157 ArchSpec A("aarch64"); 158 ArchSpec B("aarch64--linux-android"); 159 160 ArchSpec C("arm64_32"); 161 ArchSpec D("arm64_32--watchos"); 162 163 EXPECT_TRUE(A.IsValid()); 164 EXPECT_TRUE(B.IsValid()); 165 EXPECT_TRUE(C.IsValid()); 166 EXPECT_TRUE(D.IsValid()); 167 168 EXPECT_EQ(llvm::Triple::ArchType::aarch64, B.GetTriple().getArch()); 169 EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor, 170 B.GetTriple().getVendor()); 171 EXPECT_EQ(llvm::Triple::OSType::Linux, B.GetTriple().getOS()); 172 EXPECT_EQ(llvm::Triple::EnvironmentType::Android, 173 B.GetTriple().getEnvironment()); 174 175 A.MergeFrom(B); 176 EXPECT_EQ(llvm::Triple::ArchType::aarch64, A.GetTriple().getArch()); 177 EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor, 178 A.GetTriple().getVendor()); 179 EXPECT_EQ(llvm::Triple::OSType::Linux, A.GetTriple().getOS()); 180 EXPECT_EQ(llvm::Triple::EnvironmentType::Android, 181 A.GetTriple().getEnvironment()); 182 183 EXPECT_EQ(llvm::Triple::ArchType::aarch64_32, D.GetTriple().getArch()); 184 EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor, 185 D.GetTriple().getVendor()); 186 EXPECT_EQ(llvm::Triple::OSType::WatchOS, D.GetTriple().getOS()); 187 188 C.MergeFrom(D); 189 EXPECT_EQ(llvm::Triple::ArchType::aarch64_32, C.GetTriple().getArch()); 190 EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor, 191 C.GetTriple().getVendor()); 192 EXPECT_EQ(llvm::Triple::OSType::WatchOS, C.GetTriple().getOS()); 193 } 194 { 195 ArchSpec A, B; 196 A.SetArchitecture(eArchTypeELF, llvm::ELF::EM_ARM, 197 LLDB_INVALID_CPUTYPE, llvm::ELF::ELFOSABI_NONE); 198 B.SetArchitecture(eArchTypeELF, llvm::ELF::EM_ARM, 199 LLDB_INVALID_CPUTYPE, llvm::ELF::ELFOSABI_LINUX); 200 201 EXPECT_TRUE(A.IsValid()); 202 EXPECT_TRUE(B.IsValid()); 203 204 EXPECT_EQ(llvm::Triple::ArchType::arm, B.GetTriple().getArch()); 205 EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor, 206 B.GetTriple().getVendor()); 207 EXPECT_EQ(llvm::Triple::OSType::Linux, B.GetTriple().getOS()); 208 EXPECT_EQ(llvm::Triple::EnvironmentType::UnknownEnvironment, 209 B.GetTriple().getEnvironment()); 210 211 A.MergeFrom(B); 212 EXPECT_EQ(llvm::Triple::ArchType::arm, A.GetTriple().getArch()); 213 EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor, 214 A.GetTriple().getVendor()); 215 EXPECT_EQ(llvm::Triple::OSType::Linux, A.GetTriple().getOS()); 216 EXPECT_EQ(llvm::Triple::EnvironmentType::UnknownEnvironment, 217 A.GetTriple().getEnvironment()); 218 } 219 } 220 221 TEST(ArchSpecTest, MergeFromMachOUnknown) { 222 class MyArchSpec : public ArchSpec { 223 public: 224 MyArchSpec() { 225 this->SetTriple("unknown-mach-64"); 226 this->m_core = ArchSpec::eCore_uknownMach64; 227 this->m_byte_order = eByteOrderLittle; 228 this->m_flags = 0; 229 } 230 }; 231 232 MyArchSpec A; 233 ASSERT_TRUE(A.IsValid()); 234 MyArchSpec B; 235 ASSERT_TRUE(B.IsValid()); 236 A.MergeFrom(B); 237 ASSERT_EQ(A.GetCore(), ArchSpec::eCore_uknownMach64); 238 } 239 240 TEST(ArchSpecTest, Compatibility) { 241 { 242 ArchSpec A("x86_64-apple-macosx10.12"); 243 ArchSpec B("x86_64-apple-macosx10.12"); 244 ASSERT_TRUE(A.IsExactMatch(B)); 245 ASSERT_TRUE(A.IsCompatibleMatch(B)); 246 } 247 { 248 // The version information is auxiliary to support availablity but 249 // doesn't affect compatibility. 250 ArchSpec A("x86_64-apple-macosx10.11"); 251 ArchSpec B("x86_64-apple-macosx10.12"); 252 ASSERT_TRUE(A.IsExactMatch(B)); 253 ASSERT_TRUE(A.IsCompatibleMatch(B)); 254 } 255 { 256 ArchSpec A("x86_64-apple-macosx10.13"); 257 ArchSpec B("x86_64h-apple-macosx10.13"); 258 ASSERT_FALSE(A.IsExactMatch(B)); 259 ASSERT_TRUE(A.IsCompatibleMatch(B)); 260 } 261 { 262 ArchSpec A("x86_64-apple-macosx"); 263 ArchSpec B("x86_64-apple-ios-simulator"); 264 ASSERT_FALSE(A.IsExactMatch(B)); 265 ASSERT_FALSE(A.IsCompatibleMatch(B)); 266 } 267 { 268 ArchSpec A("x86_64-*-*"); 269 ArchSpec B("x86_64-apple-ios-simulator"); 270 ASSERT_FALSE(A.IsExactMatch(B)); 271 ASSERT_FALSE(A.IsCompatibleMatch(B)); 272 } 273 { 274 ArchSpec A("arm64-*-*"); 275 ArchSpec B("arm64-apple-ios"); 276 ASSERT_FALSE(A.IsExactMatch(B)); 277 // FIXME: This looks unintuitive and we should investigate whether 278 // this is the desired behavior. 279 ASSERT_FALSE(A.IsCompatibleMatch(B)); 280 } 281 { 282 ArchSpec A("x86_64-*-*"); 283 ArchSpec B("x86_64-apple-ios-simulator"); 284 ASSERT_FALSE(A.IsExactMatch(B)); 285 // FIXME: See above, though the extra environment complicates things. 286 ASSERT_FALSE(A.IsCompatibleMatch(B)); 287 } 288 { 289 ArchSpec A("x86_64"); 290 ArchSpec B("x86_64-apple-macosx10.14"); 291 // FIXME: The exact match also looks unintuitive. 292 ASSERT_TRUE(A.IsExactMatch(B)); 293 ASSERT_TRUE(A.IsCompatibleMatch(B)); 294 } 295 } 296 297 TEST(ArchSpecTest, OperatorBool) { 298 EXPECT_FALSE(ArchSpec()); 299 EXPECT_TRUE(ArchSpec("x86_64-pc-linux")); 300 } 301 302 TEST(ArchSpecTest, TripleComponentsWereSpecified) { 303 { 304 ArchSpec A(""); 305 ArchSpec B("-"); 306 ArchSpec C("--"); 307 ArchSpec D("---"); 308 309 ASSERT_FALSE(A.TripleVendorWasSpecified()); 310 ASSERT_FALSE(A.TripleOSWasSpecified()); 311 ASSERT_FALSE(A.TripleEnvironmentWasSpecified()); 312 313 ASSERT_FALSE(B.TripleVendorWasSpecified()); 314 ASSERT_FALSE(B.TripleOSWasSpecified()); 315 ASSERT_FALSE(B.TripleEnvironmentWasSpecified()); 316 317 ASSERT_FALSE(C.TripleVendorWasSpecified()); 318 ASSERT_FALSE(C.TripleOSWasSpecified()); 319 ASSERT_FALSE(C.TripleEnvironmentWasSpecified()); 320 321 ASSERT_FALSE(D.TripleVendorWasSpecified()); 322 ASSERT_FALSE(D.TripleOSWasSpecified()); 323 ASSERT_FALSE(D.TripleEnvironmentWasSpecified()); 324 } 325 { 326 // TODO: llvm::Triple::normalize treats the missing components from these 327 // triples as specified unknown components instead of unspecified 328 // components. We need to either change the behavior in llvm or work around 329 // this in lldb. 330 ArchSpec A("armv7"); 331 ArchSpec B("armv7-"); 332 ArchSpec C("armv7--"); 333 ArchSpec D("armv7---"); 334 335 ASSERT_FALSE(A.TripleVendorWasSpecified()); 336 ASSERT_FALSE(A.TripleOSWasSpecified()); 337 ASSERT_FALSE(A.TripleEnvironmentWasSpecified()); 338 339 ASSERT_TRUE(B.TripleVendorWasSpecified()); 340 ASSERT_FALSE(B.TripleOSWasSpecified()); 341 ASSERT_FALSE(B.TripleEnvironmentWasSpecified()); 342 343 ASSERT_TRUE(C.TripleVendorWasSpecified()); 344 ASSERT_TRUE(C.TripleOSWasSpecified()); 345 ASSERT_FALSE(C.TripleEnvironmentWasSpecified()); 346 347 ASSERT_TRUE(D.TripleVendorWasSpecified()); 348 ASSERT_TRUE(D.TripleOSWasSpecified()); 349 ASSERT_TRUE(D.TripleEnvironmentWasSpecified()); 350 } 351 { 352 ArchSpec A("x86_64-unknown"); 353 ArchSpec B("powerpc-unknown-linux"); 354 ArchSpec C("i386-pc-windows-msvc"); 355 ArchSpec D("aarch64-unknown-linux-android"); 356 357 ASSERT_TRUE(A.TripleVendorWasSpecified()); 358 ASSERT_FALSE(A.TripleOSWasSpecified()); 359 ASSERT_FALSE(A.TripleEnvironmentWasSpecified()); 360 361 ASSERT_TRUE(B.TripleVendorWasSpecified()); 362 ASSERT_TRUE(B.TripleOSWasSpecified()); 363 ASSERT_FALSE(B.TripleEnvironmentWasSpecified()); 364 365 ASSERT_TRUE(C.TripleVendorWasSpecified()); 366 ASSERT_TRUE(C.TripleOSWasSpecified()); 367 ASSERT_TRUE(C.TripleEnvironmentWasSpecified()); 368 369 ASSERT_TRUE(D.TripleVendorWasSpecified()); 370 ASSERT_TRUE(D.TripleOSWasSpecified()); 371 ASSERT_TRUE(D.TripleEnvironmentWasSpecified()); 372 } 373 } 374