1 //===-- Language.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 <functional> 10 #include <map> 11 #include <mutex> 12 13 #include "lldb/Target/Language.h" 14 15 #include "lldb/Core/PluginManager.h" 16 #include "lldb/Symbol/SymbolFile.h" 17 #include "lldb/Symbol/TypeList.h" 18 #include "lldb/Target/Target.h" 19 #include "lldb/Utility/Stream.h" 20 21 #include "llvm/Support/Threading.h" 22 23 using namespace lldb; 24 using namespace lldb_private; 25 using namespace lldb_private::formatters; 26 27 typedef std::unique_ptr<Language> LanguageUP; 28 typedef std::map<lldb::LanguageType, LanguageUP> LanguagesMap; 29 30 static LanguagesMap &GetLanguagesMap() { 31 static LanguagesMap *g_map = nullptr; 32 static llvm::once_flag g_initialize; 33 34 llvm::call_once(g_initialize, [] { 35 g_map = new LanguagesMap(); // NOTE: INTENTIONAL LEAK due to global 36 // destructor chain 37 }); 38 39 return *g_map; 40 } 41 static std::mutex &GetLanguagesMutex() { 42 static std::mutex *g_mutex = nullptr; 43 static llvm::once_flag g_initialize; 44 45 llvm::call_once(g_initialize, [] { 46 g_mutex = new std::mutex(); // NOTE: INTENTIONAL LEAK due to global 47 // destructor chain 48 }); 49 50 return *g_mutex; 51 } 52 53 Language *Language::FindPlugin(lldb::LanguageType language) { 54 std::lock_guard<std::mutex> guard(GetLanguagesMutex()); 55 LanguagesMap &map(GetLanguagesMap()); 56 auto iter = map.find(language), end = map.end(); 57 if (iter != end) 58 return iter->second.get(); 59 60 Language *language_ptr = nullptr; 61 LanguageCreateInstance create_callback; 62 63 for (uint32_t idx = 0; 64 (create_callback = 65 PluginManager::GetLanguageCreateCallbackAtIndex(idx)) != nullptr; 66 ++idx) { 67 language_ptr = create_callback(language); 68 69 if (language_ptr) { 70 map[language] = std::unique_ptr<Language>(language_ptr); 71 return language_ptr; 72 } 73 } 74 75 return nullptr; 76 } 77 78 Language *Language::FindPlugin(llvm::StringRef file_path) { 79 Language *result = nullptr; 80 ForEach([&result, file_path](Language *language) { 81 if (language->IsSourceFile(file_path)) { 82 result = language; 83 return false; 84 } 85 return true; 86 }); 87 return result; 88 } 89 90 Language *Language::FindPlugin(LanguageType language, 91 llvm::StringRef file_path) { 92 Language *result = FindPlugin(language); 93 // Finding a language by file path is slower, we so we use this as the 94 // fallback. 95 if (!result) 96 result = FindPlugin(file_path); 97 return result; 98 } 99 100 void Language::ForEach(std::function<bool(Language *)> callback) { 101 // If we want to iterate over all languages, we first have to complete the 102 // LanguagesMap. 103 static llvm::once_flag g_initialize; 104 llvm::call_once(g_initialize, [] { 105 for (unsigned lang = eLanguageTypeUnknown; lang < eNumLanguageTypes; 106 ++lang) { 107 FindPlugin(static_cast<lldb::LanguageType>(lang)); 108 } 109 }); 110 111 // callback may call a method in Language that attempts to acquire the same 112 // lock (such as Language::ForEach or Language::FindPlugin). To avoid a 113 // deadlock, we do not use callback while holding the lock. 114 std::vector<Language *> loaded_plugins; 115 { 116 std::lock_guard<std::mutex> guard(GetLanguagesMutex()); 117 LanguagesMap &map(GetLanguagesMap()); 118 for (const auto &entry : map) { 119 if (entry.second) 120 loaded_plugins.push_back(entry.second.get()); 121 } 122 } 123 124 for (auto *lang : loaded_plugins) { 125 if (!callback(lang)) 126 break; 127 } 128 } 129 130 bool Language::IsTopLevelFunction(Function &function) { return false; } 131 132 lldb::TypeCategoryImplSP Language::GetFormatters() { return nullptr; } 133 134 HardcodedFormatters::HardcodedFormatFinder Language::GetHardcodedFormats() { 135 return {}; 136 } 137 138 HardcodedFormatters::HardcodedSummaryFinder Language::GetHardcodedSummaries() { 139 return {}; 140 } 141 142 HardcodedFormatters::HardcodedSyntheticFinder 143 Language::GetHardcodedSynthetics() { 144 return {}; 145 } 146 147 std::vector<FormattersMatchCandidate> 148 Language::GetPossibleFormattersMatches(ValueObject &valobj, 149 lldb::DynamicValueType use_dynamic) { 150 return {}; 151 } 152 153 struct language_name_pair { 154 const char *name; 155 LanguageType type; 156 }; 157 158 struct language_name_pair language_names[] = { 159 // To allow GetNameForLanguageType to be a simple array lookup, the first 160 // part of this array must follow enum LanguageType exactly. 161 {"unknown", eLanguageTypeUnknown}, 162 {"c89", eLanguageTypeC89}, 163 {"c", eLanguageTypeC}, 164 {"ada83", eLanguageTypeAda83}, 165 {"c++", eLanguageTypeC_plus_plus}, 166 {"cobol74", eLanguageTypeCobol74}, 167 {"cobol85", eLanguageTypeCobol85}, 168 {"fortran77", eLanguageTypeFortran77}, 169 {"fortran90", eLanguageTypeFortran90}, 170 {"pascal83", eLanguageTypePascal83}, 171 {"modula2", eLanguageTypeModula2}, 172 {"java", eLanguageTypeJava}, 173 {"c99", eLanguageTypeC99}, 174 {"ada95", eLanguageTypeAda95}, 175 {"fortran95", eLanguageTypeFortran95}, 176 {"pli", eLanguageTypePLI}, 177 {"objective-c", eLanguageTypeObjC}, 178 {"objective-c++", eLanguageTypeObjC_plus_plus}, 179 {"upc", eLanguageTypeUPC}, 180 {"d", eLanguageTypeD}, 181 {"python", eLanguageTypePython}, 182 {"opencl", eLanguageTypeOpenCL}, 183 {"go", eLanguageTypeGo}, 184 {"modula3", eLanguageTypeModula3}, 185 {"haskell", eLanguageTypeHaskell}, 186 {"c++03", eLanguageTypeC_plus_plus_03}, 187 {"c++11", eLanguageTypeC_plus_plus_11}, 188 {"ocaml", eLanguageTypeOCaml}, 189 {"rust", eLanguageTypeRust}, 190 {"c11", eLanguageTypeC11}, 191 {"swift", eLanguageTypeSwift}, 192 {"julia", eLanguageTypeJulia}, 193 {"dylan", eLanguageTypeDylan}, 194 {"c++14", eLanguageTypeC_plus_plus_14}, 195 {"fortran03", eLanguageTypeFortran03}, 196 {"fortran08", eLanguageTypeFortran08}, 197 // Vendor Extensions 198 {"assembler", eLanguageTypeMipsAssembler}, 199 {"renderscript", eLanguageTypeExtRenderScript}, 200 // Now synonyms, in arbitrary order 201 {"objc", eLanguageTypeObjC}, 202 {"objc++", eLanguageTypeObjC_plus_plus}, 203 {"pascal", eLanguageTypePascal83}}; 204 205 static uint32_t num_languages = 206 sizeof(language_names) / sizeof(struct language_name_pair); 207 208 LanguageType Language::GetLanguageTypeFromString(llvm::StringRef string) { 209 for (const auto &L : language_names) { 210 if (string.equals_insensitive(L.name)) 211 return static_cast<LanguageType>(L.type); 212 } 213 214 return eLanguageTypeUnknown; 215 } 216 217 const char *Language::GetNameForLanguageType(LanguageType language) { 218 if (language < num_languages) 219 return language_names[language].name; 220 else 221 return language_names[eLanguageTypeUnknown].name; 222 } 223 224 void Language::PrintSupportedLanguagesForExpressions(Stream &s, 225 llvm::StringRef prefix, 226 llvm::StringRef suffix) { 227 auto supported = Language::GetLanguagesSupportingTypeSystemsForExpressions(); 228 for (size_t idx = 0; idx < num_languages; ++idx) { 229 auto const &lang = language_names[idx]; 230 if (supported[lang.type]) 231 s << prefix << lang.name << suffix; 232 } 233 } 234 235 void Language::PrintAllLanguages(Stream &s, const char *prefix, 236 const char *suffix) { 237 for (uint32_t i = 1; i < num_languages; i++) { 238 s.Printf("%s%s%s", prefix, language_names[i].name, suffix); 239 } 240 } 241 242 void Language::ForAllLanguages( 243 std::function<bool(lldb::LanguageType)> callback) { 244 for (uint32_t i = 1; i < num_languages; i++) { 245 if (!callback(language_names[i].type)) 246 break; 247 } 248 } 249 250 bool Language::LanguageIsCPlusPlus(LanguageType language) { 251 switch (language) { 252 case eLanguageTypeC_plus_plus: 253 case eLanguageTypeC_plus_plus_03: 254 case eLanguageTypeC_plus_plus_11: 255 case eLanguageTypeC_plus_plus_14: 256 case eLanguageTypeObjC_plus_plus: 257 return true; 258 default: 259 return false; 260 } 261 } 262 263 bool Language::LanguageIsObjC(LanguageType language) { 264 switch (language) { 265 case eLanguageTypeObjC: 266 case eLanguageTypeObjC_plus_plus: 267 return true; 268 default: 269 return false; 270 } 271 } 272 273 bool Language::LanguageIsC(LanguageType language) { 274 switch (language) { 275 case eLanguageTypeC: 276 case eLanguageTypeC89: 277 case eLanguageTypeC99: 278 case eLanguageTypeC11: 279 return true; 280 default: 281 return false; 282 } 283 } 284 285 bool Language::LanguageIsCFamily(LanguageType language) { 286 switch (language) { 287 case eLanguageTypeC: 288 case eLanguageTypeC89: 289 case eLanguageTypeC99: 290 case eLanguageTypeC11: 291 case eLanguageTypeC_plus_plus: 292 case eLanguageTypeC_plus_plus_03: 293 case eLanguageTypeC_plus_plus_11: 294 case eLanguageTypeC_plus_plus_14: 295 case eLanguageTypeObjC_plus_plus: 296 case eLanguageTypeObjC: 297 return true; 298 default: 299 return false; 300 } 301 } 302 303 bool Language::LanguageIsPascal(LanguageType language) { 304 switch (language) { 305 case eLanguageTypePascal83: 306 return true; 307 default: 308 return false; 309 } 310 } 311 312 LanguageType Language::GetPrimaryLanguage(LanguageType language) { 313 switch (language) { 314 case eLanguageTypeC_plus_plus: 315 case eLanguageTypeC_plus_plus_03: 316 case eLanguageTypeC_plus_plus_11: 317 case eLanguageTypeC_plus_plus_14: 318 return eLanguageTypeC_plus_plus; 319 case eLanguageTypeC: 320 case eLanguageTypeC89: 321 case eLanguageTypeC99: 322 case eLanguageTypeC11: 323 return eLanguageTypeC; 324 case eLanguageTypeObjC: 325 case eLanguageTypeObjC_plus_plus: 326 return eLanguageTypeObjC; 327 case eLanguageTypePascal83: 328 case eLanguageTypeCobol74: 329 case eLanguageTypeCobol85: 330 case eLanguageTypeFortran77: 331 case eLanguageTypeFortran90: 332 case eLanguageTypeFortran95: 333 case eLanguageTypeFortran03: 334 case eLanguageTypeFortran08: 335 case eLanguageTypeAda83: 336 case eLanguageTypeAda95: 337 case eLanguageTypeModula2: 338 case eLanguageTypeJava: 339 case eLanguageTypePLI: 340 case eLanguageTypeUPC: 341 case eLanguageTypeD: 342 case eLanguageTypePython: 343 case eLanguageTypeOpenCL: 344 case eLanguageTypeGo: 345 case eLanguageTypeModula3: 346 case eLanguageTypeHaskell: 347 case eLanguageTypeOCaml: 348 case eLanguageTypeRust: 349 case eLanguageTypeSwift: 350 case eLanguageTypeJulia: 351 case eLanguageTypeDylan: 352 case eLanguageTypeMipsAssembler: 353 case eLanguageTypeExtRenderScript: 354 case eLanguageTypeUnknown: 355 default: 356 return language; 357 } 358 } 359 360 std::set<lldb::LanguageType> Language::GetSupportedLanguages() { 361 std::set<lldb::LanguageType> supported_languages; 362 ForEach([&](Language *lang) { 363 supported_languages.emplace(lang->GetLanguageType()); 364 return true; 365 }); 366 return supported_languages; 367 } 368 369 LanguageSet Language::GetLanguagesSupportingTypeSystems() { 370 return PluginManager::GetAllTypeSystemSupportedLanguagesForTypes(); 371 } 372 373 LanguageSet Language::GetLanguagesSupportingTypeSystemsForExpressions() { 374 return PluginManager::GetAllTypeSystemSupportedLanguagesForExpressions(); 375 } 376 377 LanguageSet Language::GetLanguagesSupportingREPLs() { 378 return PluginManager::GetREPLAllTypeSystemSupportedLanguages(); 379 } 380 381 std::unique_ptr<Language::TypeScavenger> Language::GetTypeScavenger() { 382 return nullptr; 383 } 384 385 const char *Language::GetLanguageSpecificTypeLookupHelp() { return nullptr; } 386 387 size_t Language::TypeScavenger::Find(ExecutionContextScope *exe_scope, 388 const char *key, ResultSet &results, 389 bool append) { 390 if (!exe_scope || !exe_scope->CalculateTarget().get()) 391 return false; 392 393 if (!key || !key[0]) 394 return false; 395 396 if (!append) 397 results.clear(); 398 399 size_t old_size = results.size(); 400 401 if (this->Find_Impl(exe_scope, key, results)) 402 return results.size() - old_size; 403 return 0; 404 } 405 406 bool Language::ImageListTypeScavenger::Find_Impl( 407 ExecutionContextScope *exe_scope, const char *key, ResultSet &results) { 408 bool result = false; 409 410 Target *target = exe_scope->CalculateTarget().get(); 411 if (target) { 412 const auto &images(target->GetImages()); 413 ConstString cs_key(key); 414 llvm::DenseSet<SymbolFile *> searched_sym_files; 415 TypeList matches; 416 images.FindTypes(nullptr, cs_key, false, UINT32_MAX, searched_sym_files, 417 matches); 418 for (const auto &match : matches.Types()) { 419 if (match) { 420 CompilerType compiler_type(match->GetFullCompilerType()); 421 compiler_type = AdjustForInclusion(compiler_type); 422 if (!compiler_type) 423 continue; 424 std::unique_ptr<Language::TypeScavenger::Result> scavengeresult( 425 new Result(compiler_type)); 426 results.insert(std::move(scavengeresult)); 427 result = true; 428 } 429 } 430 } 431 432 return result; 433 } 434 435 bool Language::GetFormatterPrefixSuffix(ValueObject &valobj, 436 ConstString type_hint, 437 std::string &prefix, 438 std::string &suffix) { 439 return false; 440 } 441 442 bool Language::DemangledNameContainsPath(llvm::StringRef path, 443 ConstString demangled) const { 444 // The base implementation does a simple contains comparision: 445 if (path.empty()) 446 return false; 447 return demangled.GetStringRef().contains(path); 448 } 449 450 DumpValueObjectOptions::DeclPrintingHelper Language::GetDeclPrintingHelper() { 451 return nullptr; 452 } 453 454 LazyBool Language::IsLogicalTrue(ValueObject &valobj, Status &error) { 455 return eLazyBoolCalculate; 456 } 457 458 bool Language::IsNilReference(ValueObject &valobj) { return false; } 459 460 bool Language::IsUninitializedReference(ValueObject &valobj) { return false; } 461 462 bool Language::GetFunctionDisplayName(const SymbolContext *sc, 463 const ExecutionContext *exe_ctx, 464 FunctionNameRepresentation representation, 465 Stream &s) { 466 return false; 467 } 468 469 void Language::GetExceptionResolverDescription(bool catch_on, bool throw_on, 470 Stream &s) { 471 GetDefaultExceptionResolverDescription(catch_on, throw_on, s); 472 } 473 474 void Language::GetDefaultExceptionResolverDescription(bool catch_on, 475 bool throw_on, 476 Stream &s) { 477 s.Printf("Exception breakpoint (catch: %s throw: %s)", 478 catch_on ? "on" : "off", throw_on ? "on" : "off"); 479 } 480 // Constructor 481 Language::Language() = default; 482 483 // Destructor 484 Language::~Language() = default; 485