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