1 //===-- Language.cpp ------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
13 #include "lldb/Target/Language.h"
15 #include "lldb/Core/PluginManager.h"
16 #include "lldb/Symbol/SymbolFile.h"
17 #include "lldb/Symbol/TypeList.h"
18 #include "lldb/Target/Target.h"
19 #include "lldb/Utility/Stream.h"
21 #include "llvm/Support/Threading.h"
24 using namespace lldb_private
;
25 using namespace lldb_private::formatters
;
27 typedef std::unique_ptr
<Language
> LanguageUP
;
28 typedef std::map
<lldb::LanguageType
, LanguageUP
> LanguagesMap
;
30 static LanguagesMap
&GetLanguagesMap() {
31 static LanguagesMap
*g_map
= nullptr;
32 static llvm::once_flag g_initialize
;
34 llvm::call_once(g_initialize
, [] {
35 g_map
= new LanguagesMap(); // NOTE: INTENTIONAL LEAK due to global
41 static std::mutex
&GetLanguagesMutex() {
42 static std::mutex
*g_mutex
= nullptr;
43 static llvm::once_flag g_initialize
;
45 llvm::call_once(g_initialize
, [] {
46 g_mutex
= new std::mutex(); // NOTE: INTENTIONAL LEAK due to global
53 Language
*Language::FindPlugin(lldb::LanguageType language
) {
54 std::lock_guard
<std::mutex
> guard(GetLanguagesMutex());
55 LanguagesMap
&map(GetLanguagesMap());
56 auto iter
= map
.find(language
), end
= map
.end();
58 return iter
->second
.get();
60 Language
*language_ptr
= nullptr;
61 LanguageCreateInstance create_callback
;
63 for (uint32_t idx
= 0;
65 PluginManager::GetLanguageCreateCallbackAtIndex(idx
)) != nullptr;
67 language_ptr
= create_callback(language
);
70 map
[language
] = std::unique_ptr
<Language
>(language_ptr
);
78 Language
*Language::FindPlugin(llvm::StringRef file_path
) {
79 Language
*result
= nullptr;
80 ForEach([&result
, file_path
](Language
*language
) {
81 if (language
->IsSourceFile(file_path
)) {
90 Language
*Language::FindPlugin(LanguageType language
,
91 llvm::StringRef file_path
) {
92 Language
*result
= FindPlugin(language
);
93 // Finding a language by file path is slower, we so we use this as the
96 result
= FindPlugin(file_path
);
100 void Language::ForEach(std::function
<bool(Language
*)> callback
) {
101 // If we want to iterate over all languages, we first have to complete the
103 static llvm::once_flag g_initialize
;
104 llvm::call_once(g_initialize
, [] {
105 for (unsigned lang
= eLanguageTypeUnknown
; lang
< eNumLanguageTypes
;
107 FindPlugin(static_cast<lldb::LanguageType
>(lang
));
111 // callback may call a method in Language that attempts to acquire the same
112 // lock (such as Language::ForEach or Language::FindPlugin). To avoid a
113 // deadlock, we do not use callback while holding the lock.
114 std::vector
<Language
*> loaded_plugins
;
116 std::lock_guard
<std::mutex
> guard(GetLanguagesMutex());
117 LanguagesMap
&map(GetLanguagesMap());
118 for (const auto &entry
: map
) {
120 loaded_plugins
.push_back(entry
.second
.get());
124 for (auto *lang
: loaded_plugins
) {
130 bool Language::IsTopLevelFunction(Function
&function
) { return false; }
132 lldb::TypeCategoryImplSP
Language::GetFormatters() { return nullptr; }
134 HardcodedFormatters::HardcodedFormatFinder
Language::GetHardcodedFormats() {
138 HardcodedFormatters::HardcodedSummaryFinder
Language::GetHardcodedSummaries() {
142 HardcodedFormatters::HardcodedSyntheticFinder
143 Language::GetHardcodedSynthetics() {
147 std::vector
<FormattersMatchCandidate
>
148 Language::GetPossibleFormattersMatches(ValueObject
&valobj
,
149 lldb::DynamicValueType use_dynamic
) {
153 struct language_name_pair
{
158 struct language_name_pair language_names
[] = {
159 // To allow GetNameForLanguageType to be a simple array lookup, the first
160 // part of this array must follow enum LanguageType exactly.
161 {"unknown", eLanguageTypeUnknown
},
162 {"c89", eLanguageTypeC89
},
163 {"c", eLanguageTypeC
},
164 {"ada83", eLanguageTypeAda83
},
165 {"c++", eLanguageTypeC_plus_plus
},
166 {"cobol74", eLanguageTypeCobol74
},
167 {"cobol85", eLanguageTypeCobol85
},
168 {"fortran77", eLanguageTypeFortran77
},
169 {"fortran90", eLanguageTypeFortran90
},
170 {"pascal83", eLanguageTypePascal83
},
171 {"modula2", eLanguageTypeModula2
},
172 {"java", eLanguageTypeJava
},
173 {"c99", eLanguageTypeC99
},
174 {"ada95", eLanguageTypeAda95
},
175 {"fortran95", eLanguageTypeFortran95
},
176 {"pli", eLanguageTypePLI
},
177 {"objective-c", eLanguageTypeObjC
},
178 {"objective-c++", eLanguageTypeObjC_plus_plus
},
179 {"upc", eLanguageTypeUPC
},
180 {"d", eLanguageTypeD
},
181 {"python", eLanguageTypePython
},
182 {"opencl", eLanguageTypeOpenCL
},
183 {"go", eLanguageTypeGo
},
184 {"modula3", eLanguageTypeModula3
},
185 {"haskell", eLanguageTypeHaskell
},
186 {"c++03", eLanguageTypeC_plus_plus_03
},
187 {"c++11", eLanguageTypeC_plus_plus_11
},
188 {"ocaml", eLanguageTypeOCaml
},
189 {"rust", eLanguageTypeRust
},
190 {"c11", eLanguageTypeC11
},
191 {"swift", eLanguageTypeSwift
},
192 {"julia", eLanguageTypeJulia
},
193 {"dylan", eLanguageTypeDylan
},
194 {"c++14", eLanguageTypeC_plus_plus_14
},
195 {"fortran03", eLanguageTypeFortran03
},
196 {"fortran08", eLanguageTypeFortran08
},
197 {"renderscript", eLanguageTypeRenderScript
},
198 {"bliss", eLanguageTypeBLISS
},
199 {"kotlin", eLanguageTypeKotlin
},
200 {"zig", eLanguageTypeZig
},
201 {"crystal", eLanguageTypeCrystal
},
202 {"<invalid language>",
203 static_cast<LanguageType
>(
204 0x0029)}, // Not yet taken by any language in the DWARF spec
205 // and thus has no entry in LanguageType
206 {"c++17", eLanguageTypeC_plus_plus_17
},
207 {"c++20", eLanguageTypeC_plus_plus_20
},
208 {"c17", eLanguageTypeC17
},
209 {"fortran18", eLanguageTypeFortran18
},
210 {"ada2005", eLanguageTypeAda2005
},
211 {"ada2012", eLanguageTypeAda2012
},
212 {"HIP", eLanguageTypeHIP
},
213 {"assembly", eLanguageTypeAssembly
},
214 {"c-sharp", eLanguageTypeC_sharp
},
215 {"mojo", eLanguageTypeMojo
},
217 {"assembler", eLanguageTypeMipsAssembler
},
218 // Now synonyms, in arbitrary order
219 {"objc", eLanguageTypeObjC
},
220 {"objc++", eLanguageTypeObjC_plus_plus
},
221 {"pascal", eLanguageTypePascal83
}};
223 static uint32_t num_languages
=
224 sizeof(language_names
) / sizeof(struct language_name_pair
);
226 LanguageType
Language::GetLanguageTypeFromString(llvm::StringRef string
) {
227 for (const auto &L
: language_names
) {
228 if (string
.equals_insensitive(L
.name
))
229 return static_cast<LanguageType
>(L
.type
);
232 return eLanguageTypeUnknown
;
235 const char *Language::GetNameForLanguageType(LanguageType language
) {
236 if (language
< num_languages
)
237 return language_names
[language
].name
;
239 return language_names
[eLanguageTypeUnknown
].name
;
242 void Language::PrintSupportedLanguagesForExpressions(Stream
&s
,
243 llvm::StringRef prefix
,
244 llvm::StringRef suffix
) {
245 auto supported
= Language::GetLanguagesSupportingTypeSystemsForExpressions();
246 for (size_t idx
= 0; idx
< num_languages
; ++idx
) {
247 auto const &lang
= language_names
[idx
];
248 if (supported
[lang
.type
])
249 s
<< prefix
<< lang
.name
<< suffix
;
253 void Language::PrintAllLanguages(Stream
&s
, const char *prefix
,
254 const char *suffix
) {
255 for (uint32_t i
= 1; i
< num_languages
; i
++) {
256 s
.Printf("%s%s%s", prefix
, language_names
[i
].name
, suffix
);
260 void Language::ForAllLanguages(
261 std::function
<bool(lldb::LanguageType
)> callback
) {
262 for (uint32_t i
= 1; i
< num_languages
; i
++) {
263 if (!callback(language_names
[i
].type
))
268 bool Language::LanguageIsCPlusPlus(LanguageType language
) {
270 case eLanguageTypeC_plus_plus
:
271 case eLanguageTypeC_plus_plus_03
:
272 case eLanguageTypeC_plus_plus_11
:
273 case eLanguageTypeC_plus_plus_14
:
274 case eLanguageTypeC_plus_plus_17
:
275 case eLanguageTypeC_plus_plus_20
:
276 case eLanguageTypeObjC_plus_plus
:
283 bool Language::LanguageIsObjC(LanguageType language
) {
285 case eLanguageTypeObjC
:
286 case eLanguageTypeObjC_plus_plus
:
293 bool Language::LanguageIsC(LanguageType language
) {
296 case eLanguageTypeC89
:
297 case eLanguageTypeC99
:
298 case eLanguageTypeC11
:
305 bool Language::LanguageIsCFamily(LanguageType language
) {
308 case eLanguageTypeC89
:
309 case eLanguageTypeC99
:
310 case eLanguageTypeC11
:
311 case eLanguageTypeC_plus_plus
:
312 case eLanguageTypeC_plus_plus_03
:
313 case eLanguageTypeC_plus_plus_11
:
314 case eLanguageTypeC_plus_plus_14
:
315 case eLanguageTypeC_plus_plus_17
:
316 case eLanguageTypeC_plus_plus_20
:
317 case eLanguageTypeObjC_plus_plus
:
318 case eLanguageTypeObjC
:
325 bool Language::LanguageIsPascal(LanguageType language
) {
327 case eLanguageTypePascal83
:
334 LanguageType
Language::GetPrimaryLanguage(LanguageType language
) {
336 case eLanguageTypeC_plus_plus
:
337 case eLanguageTypeC_plus_plus_03
:
338 case eLanguageTypeC_plus_plus_11
:
339 case eLanguageTypeC_plus_plus_14
:
340 case eLanguageTypeC_plus_plus_17
:
341 case eLanguageTypeC_plus_plus_20
:
342 return eLanguageTypeC_plus_plus
;
344 case eLanguageTypeC89
:
345 case eLanguageTypeC99
:
346 case eLanguageTypeC11
:
347 return eLanguageTypeC
;
348 case eLanguageTypeObjC
:
349 case eLanguageTypeObjC_plus_plus
:
350 return eLanguageTypeObjC
;
351 case eLanguageTypePascal83
:
352 case eLanguageTypeCobol74
:
353 case eLanguageTypeCobol85
:
354 case eLanguageTypeFortran77
:
355 case eLanguageTypeFortran90
:
356 case eLanguageTypeFortran95
:
357 case eLanguageTypeFortran03
:
358 case eLanguageTypeFortran08
:
359 case eLanguageTypeAda83
:
360 case eLanguageTypeAda95
:
361 case eLanguageTypeModula2
:
362 case eLanguageTypeJava
:
363 case eLanguageTypePLI
:
364 case eLanguageTypeUPC
:
366 case eLanguageTypePython
:
367 case eLanguageTypeOpenCL
:
368 case eLanguageTypeGo
:
369 case eLanguageTypeModula3
:
370 case eLanguageTypeHaskell
:
371 case eLanguageTypeOCaml
:
372 case eLanguageTypeRust
:
373 case eLanguageTypeSwift
:
374 case eLanguageTypeJulia
:
375 case eLanguageTypeDylan
:
376 case eLanguageTypeMipsAssembler
:
377 case eLanguageTypeMojo
:
378 case eLanguageTypeUnknown
:
384 std::set
<lldb::LanguageType
> Language::GetSupportedLanguages() {
385 std::set
<lldb::LanguageType
> supported_languages
;
386 ForEach([&](Language
*lang
) {
387 supported_languages
.emplace(lang
->GetLanguageType());
390 return supported_languages
;
393 LanguageSet
Language::GetLanguagesSupportingTypeSystems() {
394 return PluginManager::GetAllTypeSystemSupportedLanguagesForTypes();
397 LanguageSet
Language::GetLanguagesSupportingTypeSystemsForExpressions() {
398 return PluginManager::GetAllTypeSystemSupportedLanguagesForExpressions();
401 LanguageSet
Language::GetLanguagesSupportingREPLs() {
402 return PluginManager::GetREPLAllTypeSystemSupportedLanguages();
405 std::unique_ptr
<Language::TypeScavenger
> Language::GetTypeScavenger() {
409 const char *Language::GetLanguageSpecificTypeLookupHelp() { return nullptr; }
411 size_t Language::TypeScavenger::Find(ExecutionContextScope
*exe_scope
,
412 const char *key
, ResultSet
&results
,
414 if (!exe_scope
|| !exe_scope
->CalculateTarget().get())
423 size_t old_size
= results
.size();
425 if (this->Find_Impl(exe_scope
, key
, results
))
426 return results
.size() - old_size
;
430 bool Language::ImageListTypeScavenger::Find_Impl(
431 ExecutionContextScope
*exe_scope
, const char *key
, ResultSet
&results
) {
434 Target
*target
= exe_scope
->CalculateTarget().get();
436 const auto &images(target
->GetImages());
437 ConstString
cs_key(key
);
438 llvm::DenseSet
<SymbolFile
*> searched_sym_files
;
440 images
.FindTypes(nullptr, cs_key
, false, UINT32_MAX
, searched_sym_files
,
442 for (const auto &match
: matches
.Types()) {
444 CompilerType
compiler_type(match
->GetFullCompilerType());
445 compiler_type
= AdjustForInclusion(compiler_type
);
448 std::unique_ptr
<Language::TypeScavenger::Result
> scavengeresult(
449 new Result(compiler_type
));
450 results
.insert(std::move(scavengeresult
));
459 std::pair
<llvm::StringRef
, llvm::StringRef
>
460 Language::GetFormatterPrefixSuffix(llvm::StringRef type_hint
) {
461 return std::pair
<llvm::StringRef
, llvm::StringRef
>();
464 bool Language::DemangledNameContainsPath(llvm::StringRef path
,
465 ConstString demangled
) const {
466 // The base implementation does a simple contains comparision:
469 return demangled
.GetStringRef().contains(path
);
472 DumpValueObjectOptions::DeclPrintingHelper
Language::GetDeclPrintingHelper() {
476 LazyBool
Language::IsLogicalTrue(ValueObject
&valobj
, Status
&error
) {
477 return eLazyBoolCalculate
;
480 bool Language::IsNilReference(ValueObject
&valobj
) { return false; }
482 bool Language::IsUninitializedReference(ValueObject
&valobj
) { return false; }
484 bool Language::GetFunctionDisplayName(const SymbolContext
*sc
,
485 const ExecutionContext
*exe_ctx
,
486 FunctionNameRepresentation representation
,
491 void Language::GetExceptionResolverDescription(bool catch_on
, bool throw_on
,
493 GetDefaultExceptionResolverDescription(catch_on
, throw_on
, s
);
496 void Language::GetDefaultExceptionResolverDescription(bool catch_on
,
499 s
.Printf("Exception breakpoint (catch: %s throw: %s)",
500 catch_on
? "on" : "off", throw_on
? "on" : "off");
503 Language::Language() = default;
506 Language::~Language() = default;