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