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