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 std::lock_guard<std::mutex> guard(GetLanguagesMutex()); 112 LanguagesMap &map(GetLanguagesMap()); 113 for (const auto &entry : map) { 114 if (!callback(entry.second.get())) 115 break; 116 } 117 } 118 119 bool Language::IsTopLevelFunction(Function &function) { return false; } 120 121 lldb::TypeCategoryImplSP Language::GetFormatters() { return nullptr; } 122 123 HardcodedFormatters::HardcodedFormatFinder Language::GetHardcodedFormats() { 124 return {}; 125 } 126 127 HardcodedFormatters::HardcodedSummaryFinder Language::GetHardcodedSummaries() { 128 return {}; 129 } 130 131 HardcodedFormatters::HardcodedSyntheticFinder 132 Language::GetHardcodedSynthetics() { 133 return {}; 134 } 135 136 std::vector<ConstString> 137 Language::GetPossibleFormattersMatches(ValueObject &valobj, 138 lldb::DynamicValueType use_dynamic) { 139 return {}; 140 } 141 142 struct language_name_pair { 143 const char *name; 144 LanguageType type; 145 }; 146 147 struct language_name_pair language_names[] = { 148 // To allow GetNameForLanguageType to be a simple array lookup, the first 149 // part of this array must follow enum LanguageType exactly. 150 {"unknown", eLanguageTypeUnknown}, 151 {"c89", eLanguageTypeC89}, 152 {"c", eLanguageTypeC}, 153 {"ada83", eLanguageTypeAda83}, 154 {"c++", eLanguageTypeC_plus_plus}, 155 {"cobol74", eLanguageTypeCobol74}, 156 {"cobol85", eLanguageTypeCobol85}, 157 {"fortran77", eLanguageTypeFortran77}, 158 {"fortran90", eLanguageTypeFortran90}, 159 {"pascal83", eLanguageTypePascal83}, 160 {"modula2", eLanguageTypeModula2}, 161 {"java", eLanguageTypeJava}, 162 {"c99", eLanguageTypeC99}, 163 {"ada95", eLanguageTypeAda95}, 164 {"fortran95", eLanguageTypeFortran95}, 165 {"pli", eLanguageTypePLI}, 166 {"objective-c", eLanguageTypeObjC}, 167 {"objective-c++", eLanguageTypeObjC_plus_plus}, 168 {"upc", eLanguageTypeUPC}, 169 {"d", eLanguageTypeD}, 170 {"python", eLanguageTypePython}, 171 {"opencl", eLanguageTypeOpenCL}, 172 {"go", eLanguageTypeGo}, 173 {"modula3", eLanguageTypeModula3}, 174 {"haskell", eLanguageTypeHaskell}, 175 {"c++03", eLanguageTypeC_plus_plus_03}, 176 {"c++11", eLanguageTypeC_plus_plus_11}, 177 {"ocaml", eLanguageTypeOCaml}, 178 {"rust", eLanguageTypeRust}, 179 {"c11", eLanguageTypeC11}, 180 {"swift", eLanguageTypeSwift}, 181 {"julia", eLanguageTypeJulia}, 182 {"dylan", eLanguageTypeDylan}, 183 {"c++14", eLanguageTypeC_plus_plus_14}, 184 {"fortran03", eLanguageTypeFortran03}, 185 {"fortran08", eLanguageTypeFortran08}, 186 // Vendor Extensions 187 {"assembler", eLanguageTypeMipsAssembler}, 188 {"renderscript", eLanguageTypeExtRenderScript}, 189 // Now synonyms, in arbitrary order 190 {"objc", eLanguageTypeObjC}, 191 {"objc++", eLanguageTypeObjC_plus_plus}, 192 {"pascal", eLanguageTypePascal83}}; 193 194 static uint32_t num_languages = 195 sizeof(language_names) / sizeof(struct language_name_pair); 196 197 LanguageType Language::GetLanguageTypeFromString(llvm::StringRef string) { 198 for (const auto &L : language_names) { 199 if (string.equals_insensitive(L.name)) 200 return static_cast<LanguageType>(L.type); 201 } 202 203 return eLanguageTypeUnknown; 204 } 205 206 const char *Language::GetNameForLanguageType(LanguageType language) { 207 if (language < num_languages) 208 return language_names[language].name; 209 else 210 return language_names[eLanguageTypeUnknown].name; 211 } 212 213 void Language::PrintAllLanguages(Stream &s, const char *prefix, 214 const char *suffix) { 215 for (uint32_t i = 1; i < num_languages; i++) { 216 s.Printf("%s%s%s", prefix, language_names[i].name, suffix); 217 } 218 } 219 220 void Language::ForAllLanguages( 221 std::function<bool(lldb::LanguageType)> callback) { 222 for (uint32_t i = 1; i < num_languages; i++) { 223 if (!callback(language_names[i].type)) 224 break; 225 } 226 } 227 228 bool Language::LanguageIsCPlusPlus(LanguageType language) { 229 switch (language) { 230 case eLanguageTypeC_plus_plus: 231 case eLanguageTypeC_plus_plus_03: 232 case eLanguageTypeC_plus_plus_11: 233 case eLanguageTypeC_plus_plus_14: 234 case eLanguageTypeObjC_plus_plus: 235 return true; 236 default: 237 return false; 238 } 239 } 240 241 bool Language::LanguageIsObjC(LanguageType language) { 242 switch (language) { 243 case eLanguageTypeObjC: 244 case eLanguageTypeObjC_plus_plus: 245 return true; 246 default: 247 return false; 248 } 249 } 250 251 bool Language::LanguageIsC(LanguageType language) { 252 switch (language) { 253 case eLanguageTypeC: 254 case eLanguageTypeC89: 255 case eLanguageTypeC99: 256 case eLanguageTypeC11: 257 return true; 258 default: 259 return false; 260 } 261 } 262 263 bool Language::LanguageIsCFamily(LanguageType language) { 264 switch (language) { 265 case eLanguageTypeC: 266 case eLanguageTypeC89: 267 case eLanguageTypeC99: 268 case eLanguageTypeC11: 269 case eLanguageTypeC_plus_plus: 270 case eLanguageTypeC_plus_plus_03: 271 case eLanguageTypeC_plus_plus_11: 272 case eLanguageTypeC_plus_plus_14: 273 case eLanguageTypeObjC_plus_plus: 274 case eLanguageTypeObjC: 275 return true; 276 default: 277 return false; 278 } 279 } 280 281 bool Language::LanguageIsPascal(LanguageType language) { 282 switch (language) { 283 case eLanguageTypePascal83: 284 return true; 285 default: 286 return false; 287 } 288 } 289 290 LanguageType Language::GetPrimaryLanguage(LanguageType language) { 291 switch (language) { 292 case eLanguageTypeC_plus_plus: 293 case eLanguageTypeC_plus_plus_03: 294 case eLanguageTypeC_plus_plus_11: 295 case eLanguageTypeC_plus_plus_14: 296 return eLanguageTypeC_plus_plus; 297 case eLanguageTypeC: 298 case eLanguageTypeC89: 299 case eLanguageTypeC99: 300 case eLanguageTypeC11: 301 return eLanguageTypeC; 302 case eLanguageTypeObjC: 303 case eLanguageTypeObjC_plus_plus: 304 return eLanguageTypeObjC; 305 case eLanguageTypePascal83: 306 case eLanguageTypeCobol74: 307 case eLanguageTypeCobol85: 308 case eLanguageTypeFortran77: 309 case eLanguageTypeFortran90: 310 case eLanguageTypeFortran95: 311 case eLanguageTypeFortran03: 312 case eLanguageTypeFortran08: 313 case eLanguageTypeAda83: 314 case eLanguageTypeAda95: 315 case eLanguageTypeModula2: 316 case eLanguageTypeJava: 317 case eLanguageTypePLI: 318 case eLanguageTypeUPC: 319 case eLanguageTypeD: 320 case eLanguageTypePython: 321 case eLanguageTypeOpenCL: 322 case eLanguageTypeGo: 323 case eLanguageTypeModula3: 324 case eLanguageTypeHaskell: 325 case eLanguageTypeOCaml: 326 case eLanguageTypeRust: 327 case eLanguageTypeSwift: 328 case eLanguageTypeJulia: 329 case eLanguageTypeDylan: 330 case eLanguageTypeMipsAssembler: 331 case eLanguageTypeExtRenderScript: 332 case eLanguageTypeUnknown: 333 default: 334 return language; 335 } 336 } 337 338 std::set<lldb::LanguageType> Language::GetSupportedLanguages() { 339 std::set<lldb::LanguageType> supported_languages; 340 ForEach([&](Language *lang) { 341 supported_languages.emplace(lang->GetLanguageType()); 342 return true; 343 }); 344 return supported_languages; 345 } 346 347 LanguageSet Language::GetLanguagesSupportingTypeSystems() { 348 return PluginManager::GetAllTypeSystemSupportedLanguagesForTypes(); 349 } 350 351 LanguageSet Language::GetLanguagesSupportingTypeSystemsForExpressions() { 352 return PluginManager::GetAllTypeSystemSupportedLanguagesForExpressions(); 353 } 354 355 LanguageSet Language::GetLanguagesSupportingREPLs() { 356 return PluginManager::GetREPLAllTypeSystemSupportedLanguages(); 357 } 358 359 std::unique_ptr<Language::TypeScavenger> Language::GetTypeScavenger() { 360 return nullptr; 361 } 362 363 const char *Language::GetLanguageSpecificTypeLookupHelp() { return nullptr; } 364 365 size_t Language::TypeScavenger::Find(ExecutionContextScope *exe_scope, 366 const char *key, ResultSet &results, 367 bool append) { 368 if (!exe_scope || !exe_scope->CalculateTarget().get()) 369 return false; 370 371 if (!key || !key[0]) 372 return false; 373 374 if (!append) 375 results.clear(); 376 377 size_t old_size = results.size(); 378 379 if (this->Find_Impl(exe_scope, key, results)) 380 return results.size() - old_size; 381 return 0; 382 } 383 384 bool Language::ImageListTypeScavenger::Find_Impl( 385 ExecutionContextScope *exe_scope, const char *key, ResultSet &results) { 386 bool result = false; 387 388 Target *target = exe_scope->CalculateTarget().get(); 389 if (target) { 390 const auto &images(target->GetImages()); 391 ConstString cs_key(key); 392 llvm::DenseSet<SymbolFile *> searched_sym_files; 393 TypeList matches; 394 images.FindTypes(nullptr, cs_key, false, UINT32_MAX, searched_sym_files, 395 matches); 396 for (const auto &match : matches.Types()) { 397 if (match) { 398 CompilerType compiler_type(match->GetFullCompilerType()); 399 compiler_type = AdjustForInclusion(compiler_type); 400 if (!compiler_type) 401 continue; 402 std::unique_ptr<Language::TypeScavenger::Result> scavengeresult( 403 new Result(compiler_type)); 404 results.insert(std::move(scavengeresult)); 405 result = true; 406 } 407 } 408 } 409 410 return result; 411 } 412 413 bool Language::GetFormatterPrefixSuffix(ValueObject &valobj, 414 ConstString type_hint, 415 std::string &prefix, 416 std::string &suffix) { 417 return false; 418 } 419 420 DumpValueObjectOptions::DeclPrintingHelper Language::GetDeclPrintingHelper() { 421 return nullptr; 422 } 423 424 LazyBool Language::IsLogicalTrue(ValueObject &valobj, Status &error) { 425 return eLazyBoolCalculate; 426 } 427 428 bool Language::IsNilReference(ValueObject &valobj) { return false; } 429 430 bool Language::IsUninitializedReference(ValueObject &valobj) { return false; } 431 432 bool Language::GetFunctionDisplayName(const SymbolContext *sc, 433 const ExecutionContext *exe_ctx, 434 FunctionNameRepresentation representation, 435 Stream &s) { 436 return false; 437 } 438 439 void Language::GetExceptionResolverDescription(bool catch_on, bool throw_on, 440 Stream &s) { 441 GetDefaultExceptionResolverDescription(catch_on, throw_on, s); 442 } 443 444 void Language::GetDefaultExceptionResolverDescription(bool catch_on, 445 bool throw_on, 446 Stream &s) { 447 s.Printf("Exception breakpoint (catch: %s throw: %s)", 448 catch_on ? "on" : "off", throw_on ? "on" : "off"); 449 } 450 // Constructor 451 Language::Language() = default; 452 453 // Destructor 454 Language::~Language() = default; 455