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 *string) { 175 for (uint32_t i = 0; i < num_languages; i++) { 176 if (strcasecmp(language_names[i].name, string) == 0) 177 return (LanguageType)language_names[i].type; 178 } 179 return eLanguageTypeUnknown; 180 } 181 182 const char *Language::GetNameForLanguageType(LanguageType language) { 183 if (language < num_languages) 184 return language_names[language].name; 185 else 186 return language_names[eLanguageTypeUnknown].name; 187 } 188 189 void Language::PrintAllLanguages(Stream &s, const char *prefix, 190 const char *suffix) { 191 for (uint32_t i = 1; i < num_languages; i++) { 192 s.Printf("%s%s%s", prefix, language_names[i].name, suffix); 193 } 194 } 195 196 void Language::ForAllLanguages( 197 std::function<bool(lldb::LanguageType)> callback) { 198 for (uint32_t i = 1; i < num_languages; i++) { 199 if (!callback(language_names[i].type)) 200 break; 201 } 202 } 203 204 bool Language::LanguageIsCPlusPlus(LanguageType language) { 205 switch (language) { 206 case eLanguageTypeC_plus_plus: 207 case eLanguageTypeC_plus_plus_03: 208 case eLanguageTypeC_plus_plus_11: 209 case eLanguageTypeC_plus_plus_14: 210 case eLanguageTypeObjC_plus_plus: 211 return true; 212 default: 213 return false; 214 } 215 } 216 217 bool Language::LanguageIsObjC(LanguageType language) { 218 switch (language) { 219 case eLanguageTypeObjC: 220 case eLanguageTypeObjC_plus_plus: 221 return true; 222 default: 223 return false; 224 } 225 } 226 227 bool Language::LanguageIsC(LanguageType language) { 228 switch (language) { 229 case eLanguageTypeC: 230 case eLanguageTypeC89: 231 case eLanguageTypeC99: 232 case eLanguageTypeC11: 233 return true; 234 default: 235 return false; 236 } 237 } 238 239 bool Language::LanguageIsPascal(LanguageType language) { 240 switch (language) { 241 case eLanguageTypePascal83: 242 return true; 243 default: 244 return false; 245 } 246 } 247 248 LanguageType Language::GetPrimaryLanguage(LanguageType language) { 249 switch (language) { 250 case eLanguageTypeC_plus_plus: 251 case eLanguageTypeC_plus_plus_03: 252 case eLanguageTypeC_plus_plus_11: 253 case eLanguageTypeC_plus_plus_14: 254 return eLanguageTypeC_plus_plus; 255 case eLanguageTypeC: 256 case eLanguageTypeC89: 257 case eLanguageTypeC99: 258 case eLanguageTypeC11: 259 return eLanguageTypeC; 260 case eLanguageTypeObjC: 261 case eLanguageTypeObjC_plus_plus: 262 return eLanguageTypeObjC; 263 case eLanguageTypePascal83: 264 case eLanguageTypeCobol74: 265 case eLanguageTypeCobol85: 266 case eLanguageTypeFortran77: 267 case eLanguageTypeFortran90: 268 case eLanguageTypeFortran95: 269 case eLanguageTypeFortran03: 270 case eLanguageTypeFortran08: 271 case eLanguageTypeAda83: 272 case eLanguageTypeAda95: 273 case eLanguageTypeModula2: 274 case eLanguageTypeJava: 275 case eLanguageTypePLI: 276 case eLanguageTypeUPC: 277 case eLanguageTypeD: 278 case eLanguageTypePython: 279 case eLanguageTypeOpenCL: 280 case eLanguageTypeGo: 281 case eLanguageTypeModula3: 282 case eLanguageTypeHaskell: 283 case eLanguageTypeOCaml: 284 case eLanguageTypeRust: 285 case eLanguageTypeSwift: 286 case eLanguageTypeJulia: 287 case eLanguageTypeDylan: 288 case eLanguageTypeMipsAssembler: 289 case eLanguageTypeExtRenderScript: 290 case eLanguageTypeUnknown: 291 default: 292 return language; 293 } 294 } 295 296 void Language::GetLanguagesSupportingTypeSystems( 297 std::set<lldb::LanguageType> &languages, 298 std::set<lldb::LanguageType> &languages_for_expressions) { 299 uint32_t idx = 0; 300 301 while (TypeSystemEnumerateSupportedLanguages enumerate = PluginManager:: 302 GetTypeSystemEnumerateSupportedLanguagesCallbackAtIndex(idx++)) { 303 (*enumerate)(languages, languages_for_expressions); 304 } 305 } 306 307 void Language::GetLanguagesSupportingREPLs( 308 std::set<lldb::LanguageType> &languages) { 309 uint32_t idx = 0; 310 311 while (REPLEnumerateSupportedLanguages enumerate = 312 PluginManager::GetREPLEnumerateSupportedLanguagesCallbackAtIndex( 313 idx++)) { 314 (*enumerate)(languages); 315 } 316 } 317 318 std::unique_ptr<Language::TypeScavenger> Language::GetTypeScavenger() { 319 return nullptr; 320 } 321 322 const char *Language::GetLanguageSpecificTypeLookupHelp() { return nullptr; } 323 324 size_t Language::TypeScavenger::Find(ExecutionContextScope *exe_scope, 325 const char *key, ResultSet &results, 326 bool append) { 327 if (!exe_scope || !exe_scope->CalculateTarget().get()) 328 return false; 329 330 if (!key || !key[0]) 331 return false; 332 333 if (!append) 334 results.clear(); 335 336 size_t old_size = results.size(); 337 338 if (this->Find_Impl(exe_scope, key, results)) 339 return results.size() - old_size; 340 return 0; 341 } 342 343 bool Language::GetFormatterPrefixSuffix(ValueObject &valobj, 344 ConstString type_hint, 345 std::string &prefix, 346 std::string &suffix) { 347 return false; 348 } 349 350 DumpValueObjectOptions::DeclPrintingHelper Language::GetDeclPrintingHelper() { 351 return nullptr; 352 } 353 354 LazyBool Language::IsLogicalTrue(ValueObject &valobj, Error &error) { 355 return eLazyBoolCalculate; 356 } 357 358 bool Language::IsNilReference(ValueObject &valobj) { return false; } 359 360 bool Language::IsUninitializedReference(ValueObject &valobj) { return false; } 361 362 bool Language::GetFunctionDisplayName(const SymbolContext *sc, 363 const ExecutionContext *exe_ctx, 364 FunctionNameRepresentation representation, 365 Stream &s) { 366 return false; 367 } 368 369 void Language::GetExceptionResolverDescription(bool catch_on, bool throw_on, 370 Stream &s) { 371 GetDefaultExceptionResolverDescription(catch_on, throw_on, s); 372 } 373 374 void Language::GetDefaultExceptionResolverDescription(bool catch_on, 375 bool throw_on, 376 Stream &s) { 377 s.Printf("Exception breakpoint (catch: %s throw: %s)", 378 catch_on ? "on" : "off", throw_on ? "on" : "off"); 379 } 380 //---------------------------------------------------------------------- 381 // Constructor 382 //---------------------------------------------------------------------- 383 Language::Language() {} 384 385 //---------------------------------------------------------------------- 386 // Destructor 387 //---------------------------------------------------------------------- 388 Language::~Language() {} 389