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