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