1 //===-- Language.cpp -------------------------------------------------*- C++
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 //===----------------------------------------------------------------------===//
14 #include "lldb/Target/Language.h"
16 #include "lldb/Core/PluginManager.h"
17 #include "lldb/Symbol/SymbolFile.h"
18 #include "lldb/Symbol/TypeList.h"
19 #include "lldb/Target/Target.h"
20 #include "lldb/Utility/Stream.h"
22 #include "llvm/Support/Threading.h"
25 using namespace lldb_private;
26 using namespace lldb_private::formatters;
28 typedef std::unique_ptr<Language> LanguageUP;
29 typedef std::map<lldb::LanguageType, LanguageUP> LanguagesMap;
31 static LanguagesMap &GetLanguagesMap() {
32 static LanguagesMap *g_map = nullptr;
33 static llvm::once_flag g_initialize;
35 llvm::call_once(g_initialize, [] {
36 g_map = new LanguagesMap(); // NOTE: INTENTIONAL LEAK due to global
42 static std::mutex &GetLanguagesMutex() {
43 static std::mutex *g_mutex = nullptr;
44 static llvm::once_flag g_initialize;
46 llvm::call_once(g_initialize, [] {
47 g_mutex = new std::mutex(); // NOTE: INTENTIONAL LEAK due to global
54 Language *Language::FindPlugin(lldb::LanguageType language) {
55 std::lock_guard<std::mutex> guard(GetLanguagesMutex());
56 LanguagesMap &map(GetLanguagesMap());
57 auto iter = map.find(language), end = map.end();
59 return iter->second.get();
61 Language *language_ptr = nullptr;
62 LanguageCreateInstance create_callback;
64 for (uint32_t idx = 0;
66 PluginManager::GetLanguageCreateCallbackAtIndex(idx)) != nullptr;
68 language_ptr = create_callback(language);
71 map[language] = std::unique_ptr<Language>(language_ptr);
79 Language *Language::FindPlugin(llvm::StringRef file_path) {
80 Language *result = nullptr;
81 ForEach([&result, file_path](Language *language) {
82 if (language->IsSourceFile(file_path)) {
91 Language *Language::FindPlugin(LanguageType language,
92 llvm::StringRef file_path) {
93 Language *result = FindPlugin(language);
94 // Finding a language by file path is slower, we so we use this as the
97 result = FindPlugin(file_path);
101 void Language::ForEach(std::function<bool(Language *)> callback) {
102 // If we want to iterate over all languages, we first have to complete the
104 static llvm::once_flag g_initialize;
105 llvm::call_once(g_initialize, [] {
106 for (unsigned lang = eLanguageTypeUnknown; lang < eNumLanguageTypes;
108 FindPlugin(static_cast<lldb::LanguageType>(lang));
112 std::lock_guard<std::mutex> guard(GetLanguagesMutex());
113 LanguagesMap &map(GetLanguagesMap());
114 for (const auto &entry : map) {
115 if (!callback(entry.second.get()))
120 bool Language::IsTopLevelFunction(Function &function) { return false; }
122 lldb::TypeCategoryImplSP Language::GetFormatters() { return nullptr; }
124 HardcodedFormatters::HardcodedFormatFinder Language::GetHardcodedFormats() {
128 HardcodedFormatters::HardcodedSummaryFinder Language::GetHardcodedSummaries() {
132 HardcodedFormatters::HardcodedSyntheticFinder
133 Language::GetHardcodedSynthetics() {
137 HardcodedFormatters::HardcodedValidatorFinder
138 Language::GetHardcodedValidators() {
142 std::vector<ConstString>
143 Language::GetPossibleFormattersMatches(ValueObject &valobj,
144 lldb::DynamicValueType use_dynamic) {
148 lldb_private::formatters::StringPrinter::EscapingHelper
149 Language::GetStringPrinterEscapingHelper(
150 lldb_private::formatters::StringPrinter::GetPrintableElementType
152 return StringPrinter::GetDefaultEscapingHelper(elem_type);
155 struct language_name_pair {
160 struct language_name_pair language_names[] = {
161 // To allow GetNameForLanguageType to be a simple array lookup, the first
162 // part of this array must follow enum LanguageType exactly.
163 {"unknown", eLanguageTypeUnknown},
164 {"c89", eLanguageTypeC89},
165 {"c", eLanguageTypeC},
166 {"ada83", eLanguageTypeAda83},
167 {"c++", eLanguageTypeC_plus_plus},
168 {"cobol74", eLanguageTypeCobol74},
169 {"cobol85", eLanguageTypeCobol85},
170 {"fortran77", eLanguageTypeFortran77},
171 {"fortran90", eLanguageTypeFortran90},
172 {"pascal83", eLanguageTypePascal83},
173 {"modula2", eLanguageTypeModula2},
174 {"java", eLanguageTypeJava},
175 {"c99", eLanguageTypeC99},
176 {"ada95", eLanguageTypeAda95},
177 {"fortran95", eLanguageTypeFortran95},
178 {"pli", eLanguageTypePLI},
179 {"objective-c", eLanguageTypeObjC},
180 {"objective-c++", eLanguageTypeObjC_plus_plus},
181 {"upc", eLanguageTypeUPC},
182 {"d", eLanguageTypeD},
183 {"python", eLanguageTypePython},
184 {"opencl", eLanguageTypeOpenCL},
185 {"go", eLanguageTypeGo},
186 {"modula3", eLanguageTypeModula3},
187 {"haskell", eLanguageTypeHaskell},
188 {"c++03", eLanguageTypeC_plus_plus_03},
189 {"c++11", eLanguageTypeC_plus_plus_11},
190 {"ocaml", eLanguageTypeOCaml},
191 {"rust", eLanguageTypeRust},
192 {"c11", eLanguageTypeC11},
193 {"swift", eLanguageTypeSwift},
194 {"julia", eLanguageTypeJulia},
195 {"dylan", eLanguageTypeDylan},
196 {"c++14", eLanguageTypeC_plus_plus_14},
197 {"fortran03", eLanguageTypeFortran03},
198 {"fortran08", eLanguageTypeFortran08},
200 {"mipsassem", eLanguageTypeMipsAssembler},
201 {"renderscript", eLanguageTypeExtRenderScript},
202 // Now synonyms, in arbitrary order
203 {"objc", eLanguageTypeObjC},
204 {"objc++", eLanguageTypeObjC_plus_plus},
205 {"pascal", eLanguageTypePascal83}};
207 static uint32_t num_languages =
208 sizeof(language_names) / sizeof(struct language_name_pair);
210 LanguageType Language::GetLanguageTypeFromString(llvm::StringRef string) {
211 for (const auto &L : language_names) {
212 if (string.equals_lower(L.name))
213 return static_cast<LanguageType>(L.type);
216 return eLanguageTypeUnknown;
219 const char *Language::GetNameForLanguageType(LanguageType language) {
220 if (language < num_languages)
221 return language_names[language].name;
223 return language_names[eLanguageTypeUnknown].name;
226 void Language::PrintAllLanguages(Stream &s, const char *prefix,
227 const char *suffix) {
228 for (uint32_t i = 1; i < num_languages; i++) {
229 s.Printf("%s%s%s", prefix, language_names[i].name, suffix);
233 void Language::ForAllLanguages(
234 std::function<bool(lldb::LanguageType)> callback) {
235 for (uint32_t i = 1; i < num_languages; i++) {
236 if (!callback(language_names[i].type))
241 bool Language::LanguageIsCPlusPlus(LanguageType language) {
243 case eLanguageTypeC_plus_plus:
244 case eLanguageTypeC_plus_plus_03:
245 case eLanguageTypeC_plus_plus_11:
246 case eLanguageTypeC_plus_plus_14:
247 case eLanguageTypeObjC_plus_plus:
254 bool Language::LanguageIsObjC(LanguageType language) {
256 case eLanguageTypeObjC:
257 case eLanguageTypeObjC_plus_plus:
264 bool Language::LanguageIsC(LanguageType language) {
267 case eLanguageTypeC89:
268 case eLanguageTypeC99:
269 case eLanguageTypeC11:
276 bool Language::LanguageIsCFamily(LanguageType language) {
279 case eLanguageTypeC89:
280 case eLanguageTypeC99:
281 case eLanguageTypeC11:
282 case eLanguageTypeC_plus_plus:
283 case eLanguageTypeC_plus_plus_03:
284 case eLanguageTypeC_plus_plus_11:
285 case eLanguageTypeC_plus_plus_14:
286 case eLanguageTypeObjC_plus_plus:
287 case eLanguageTypeObjC:
294 bool Language::LanguageIsPascal(LanguageType language) {
296 case eLanguageTypePascal83:
303 LanguageType Language::GetPrimaryLanguage(LanguageType language) {
305 case eLanguageTypeC_plus_plus:
306 case eLanguageTypeC_plus_plus_03:
307 case eLanguageTypeC_plus_plus_11:
308 case eLanguageTypeC_plus_plus_14:
309 return eLanguageTypeC_plus_plus;
311 case eLanguageTypeC89:
312 case eLanguageTypeC99:
313 case eLanguageTypeC11:
314 return eLanguageTypeC;
315 case eLanguageTypeObjC:
316 case eLanguageTypeObjC_plus_plus:
317 return eLanguageTypeObjC;
318 case eLanguageTypePascal83:
319 case eLanguageTypeCobol74:
320 case eLanguageTypeCobol85:
321 case eLanguageTypeFortran77:
322 case eLanguageTypeFortran90:
323 case eLanguageTypeFortran95:
324 case eLanguageTypeFortran03:
325 case eLanguageTypeFortran08:
326 case eLanguageTypeAda83:
327 case eLanguageTypeAda95:
328 case eLanguageTypeModula2:
329 case eLanguageTypeJava:
330 case eLanguageTypePLI:
331 case eLanguageTypeUPC:
333 case eLanguageTypePython:
334 case eLanguageTypeOpenCL:
335 case eLanguageTypeGo:
336 case eLanguageTypeModula3:
337 case eLanguageTypeHaskell:
338 case eLanguageTypeOCaml:
339 case eLanguageTypeRust:
340 case eLanguageTypeSwift:
341 case eLanguageTypeJulia:
342 case eLanguageTypeDylan:
343 case eLanguageTypeMipsAssembler:
344 case eLanguageTypeExtRenderScript:
345 case eLanguageTypeUnknown:
351 std::set<lldb::LanguageType> Language::GetSupportedLanguages() {
352 std::set<lldb::LanguageType> supported_languages;
353 ForEach([&](Language *lang) {
354 supported_languages.emplace(lang->GetLanguageType());
357 return supported_languages;
360 void Language::GetLanguagesSupportingTypeSystems(
361 std::set<lldb::LanguageType> &languages,
362 std::set<lldb::LanguageType> &languages_for_expressions) {
365 while (TypeSystemEnumerateSupportedLanguages enumerate = PluginManager::
366 GetTypeSystemEnumerateSupportedLanguagesCallbackAtIndex(idx++)) {
367 (*enumerate)(languages, languages_for_expressions);
371 void Language::GetLanguagesSupportingREPLs(
372 std::set<lldb::LanguageType> &languages) {
375 while (REPLEnumerateSupportedLanguages enumerate =
376 PluginManager::GetREPLEnumerateSupportedLanguagesCallbackAtIndex(
378 (*enumerate)(languages);
382 std::unique_ptr<Language::TypeScavenger> Language::GetTypeScavenger() {
386 const char *Language::GetLanguageSpecificTypeLookupHelp() { return nullptr; }
388 size_t Language::TypeScavenger::Find(ExecutionContextScope *exe_scope,
389 const char *key, ResultSet &results,
391 if (!exe_scope || !exe_scope->CalculateTarget().get())
400 size_t old_size = results.size();
402 if (this->Find_Impl(exe_scope, key, results))
403 return results.size() - old_size;
407 bool Language::ImageListTypeScavenger::Find_Impl(
408 ExecutionContextScope *exe_scope, const char *key, ResultSet &results) {
411 Target *target = exe_scope->CalculateTarget().get();
413 const auto &images(target->GetImages());
414 ConstString cs_key(key);
415 llvm::DenseSet<SymbolFile *> searched_sym_files;
417 images.FindTypes(nullptr, cs_key, false, UINT32_MAX, searched_sym_files,
419 for (const auto &match : matches.Types()) {
421 CompilerType compiler_type(match->GetFullCompilerType());
422 compiler_type = AdjustForInclusion(compiler_type);
425 std::unique_ptr<Language::TypeScavenger::Result> scavengeresult(
426 new Result(compiler_type));
427 results.insert(std::move(scavengeresult));
436 bool Language::GetFormatterPrefixSuffix(ValueObject &valobj,
437 ConstString type_hint,
439 std::string &suffix) {
443 DumpValueObjectOptions::DeclPrintingHelper Language::GetDeclPrintingHelper() {
447 LazyBool Language::IsLogicalTrue(ValueObject &valobj, Status &error) {
448 return eLazyBoolCalculate;
451 bool Language::IsNilReference(ValueObject &valobj) { return false; }
453 bool Language::IsUninitializedReference(ValueObject &valobj) { return false; }
455 bool Language::GetFunctionDisplayName(const SymbolContext *sc,
456 const ExecutionContext *exe_ctx,
457 FunctionNameRepresentation representation,
462 void Language::GetExceptionResolverDescription(bool catch_on, bool throw_on,
464 GetDefaultExceptionResolverDescription(catch_on, throw_on, s);
467 void Language::GetDefaultExceptionResolverDescription(bool catch_on,
470 s.Printf("Exception breakpoint (catch: %s throw: %s)",
471 catch_on ? "on" : "off", throw_on ? "on" : "off");
474 Language::Language() {}
477 Language::~Language() {}