Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Target/Language.cpp
39587 views
1
//===-- Language.cpp ------------------------------------------------------===//
2
//
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
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include <functional>
10
#include <map>
11
#include <mutex>
12
13
#include "lldb/Target/Language.h"
14
15
#include "lldb/Core/PluginManager.h"
16
#include "lldb/Interpreter/OptionValueProperties.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"
21
22
#include "llvm/BinaryFormat/Dwarf.h"
23
#include "llvm/Support/Threading.h"
24
25
using namespace lldb;
26
using namespace lldb_private;
27
using namespace lldb_private::formatters;
28
29
typedef std::unique_ptr<Language> LanguageUP;
30
typedef std::map<lldb::LanguageType, LanguageUP> LanguagesMap;
31
32
#define LLDB_PROPERTIES_language
33
#include "TargetProperties.inc"
34
35
enum {
36
#define LLDB_PROPERTIES_language
37
#include "TargetPropertiesEnum.inc"
38
};
39
40
LanguageProperties &Language::GetGlobalLanguageProperties() {
41
static LanguageProperties g_settings;
42
return g_settings;
43
}
44
45
llvm::StringRef LanguageProperties::GetSettingName() {
46
static constexpr llvm::StringLiteral g_setting_name("language");
47
return g_setting_name;
48
}
49
50
LanguageProperties::LanguageProperties() {
51
m_collection_sp = std::make_shared<OptionValueProperties>(GetSettingName());
52
m_collection_sp->Initialize(g_language_properties);
53
}
54
55
bool LanguageProperties::GetEnableFilterForLineBreakpoints() const {
56
const uint32_t idx = ePropertyEnableFilterForLineBreakpoints;
57
return GetPropertyAtIndexAs<bool>(
58
idx, g_language_properties[idx].default_uint_value != 0);
59
}
60
61
static LanguagesMap &GetLanguagesMap() {
62
static LanguagesMap *g_map = nullptr;
63
static llvm::once_flag g_initialize;
64
65
llvm::call_once(g_initialize, [] {
66
g_map = new LanguagesMap(); // NOTE: INTENTIONAL LEAK due to global
67
// destructor chain
68
});
69
70
return *g_map;
71
}
72
static std::mutex &GetLanguagesMutex() {
73
static std::mutex *g_mutex = nullptr;
74
static llvm::once_flag g_initialize;
75
76
llvm::call_once(g_initialize, [] {
77
g_mutex = new std::mutex(); // NOTE: INTENTIONAL LEAK due to global
78
// destructor chain
79
});
80
81
return *g_mutex;
82
}
83
84
Language *Language::FindPlugin(lldb::LanguageType language) {
85
std::lock_guard<std::mutex> guard(GetLanguagesMutex());
86
LanguagesMap &map(GetLanguagesMap());
87
auto iter = map.find(language), end = map.end();
88
if (iter != end)
89
return iter->second.get();
90
91
Language *language_ptr = nullptr;
92
LanguageCreateInstance create_callback;
93
94
for (uint32_t idx = 0;
95
(create_callback =
96
PluginManager::GetLanguageCreateCallbackAtIndex(idx)) != nullptr;
97
++idx) {
98
language_ptr = create_callback(language);
99
100
if (language_ptr) {
101
map[language] = std::unique_ptr<Language>(language_ptr);
102
return language_ptr;
103
}
104
}
105
106
return nullptr;
107
}
108
109
Language *Language::FindPlugin(llvm::StringRef file_path) {
110
Language *result = nullptr;
111
ForEach([&result, file_path](Language *language) {
112
if (language->IsSourceFile(file_path)) {
113
result = language;
114
return false;
115
}
116
return true;
117
});
118
return result;
119
}
120
121
Language *Language::FindPlugin(LanguageType language,
122
llvm::StringRef file_path) {
123
Language *result = FindPlugin(language);
124
// Finding a language by file path is slower, we so we use this as the
125
// fallback.
126
if (!result)
127
result = FindPlugin(file_path);
128
return result;
129
}
130
131
void Language::ForEach(std::function<bool(Language *)> callback) {
132
// If we want to iterate over all languages, we first have to complete the
133
// LanguagesMap.
134
static llvm::once_flag g_initialize;
135
llvm::call_once(g_initialize, [] {
136
for (unsigned lang = eLanguageTypeUnknown; lang < eNumLanguageTypes;
137
++lang) {
138
FindPlugin(static_cast<lldb::LanguageType>(lang));
139
}
140
});
141
142
// callback may call a method in Language that attempts to acquire the same
143
// lock (such as Language::ForEach or Language::FindPlugin). To avoid a
144
// deadlock, we do not use callback while holding the lock.
145
std::vector<Language *> loaded_plugins;
146
{
147
std::lock_guard<std::mutex> guard(GetLanguagesMutex());
148
LanguagesMap &map(GetLanguagesMap());
149
for (const auto &entry : map) {
150
if (entry.second)
151
loaded_plugins.push_back(entry.second.get());
152
}
153
}
154
155
for (auto *lang : loaded_plugins) {
156
if (!callback(lang))
157
break;
158
}
159
}
160
161
bool Language::IsTopLevelFunction(Function &function) { return false; }
162
163
lldb::TypeCategoryImplSP Language::GetFormatters() { return nullptr; }
164
165
HardcodedFormatters::HardcodedFormatFinder Language::GetHardcodedFormats() {
166
return {};
167
}
168
169
HardcodedFormatters::HardcodedSummaryFinder Language::GetHardcodedSummaries() {
170
return {};
171
}
172
173
HardcodedFormatters::HardcodedSyntheticFinder
174
Language::GetHardcodedSynthetics() {
175
return {};
176
}
177
178
std::vector<FormattersMatchCandidate>
179
Language::GetPossibleFormattersMatches(ValueObject &valobj,
180
lldb::DynamicValueType use_dynamic) {
181
return {};
182
}
183
184
struct language_name_pair {
185
const char *name;
186
LanguageType type;
187
};
188
189
struct language_name_pair language_names[] = {
190
// To allow GetNameForLanguageType to be a simple array lookup, the first
191
// part of this array must follow enum LanguageType exactly.
192
{"unknown", eLanguageTypeUnknown},
193
{"c89", eLanguageTypeC89},
194
{"c", eLanguageTypeC},
195
{"ada83", eLanguageTypeAda83},
196
{"c++", eLanguageTypeC_plus_plus},
197
{"cobol74", eLanguageTypeCobol74},
198
{"cobol85", eLanguageTypeCobol85},
199
{"fortran77", eLanguageTypeFortran77},
200
{"fortran90", eLanguageTypeFortran90},
201
{"pascal83", eLanguageTypePascal83},
202
{"modula2", eLanguageTypeModula2},
203
{"java", eLanguageTypeJava},
204
{"c99", eLanguageTypeC99},
205
{"ada95", eLanguageTypeAda95},
206
{"fortran95", eLanguageTypeFortran95},
207
{"pli", eLanguageTypePLI},
208
{"objective-c", eLanguageTypeObjC},
209
{"objective-c++", eLanguageTypeObjC_plus_plus},
210
{"upc", eLanguageTypeUPC},
211
{"d", eLanguageTypeD},
212
{"python", eLanguageTypePython},
213
{"opencl", eLanguageTypeOpenCL},
214
{"go", eLanguageTypeGo},
215
{"modula3", eLanguageTypeModula3},
216
{"haskell", eLanguageTypeHaskell},
217
{"c++03", eLanguageTypeC_plus_plus_03},
218
{"c++11", eLanguageTypeC_plus_plus_11},
219
{"ocaml", eLanguageTypeOCaml},
220
{"rust", eLanguageTypeRust},
221
{"c11", eLanguageTypeC11},
222
{"swift", eLanguageTypeSwift},
223
{"julia", eLanguageTypeJulia},
224
{"dylan", eLanguageTypeDylan},
225
{"c++14", eLanguageTypeC_plus_plus_14},
226
{"fortran03", eLanguageTypeFortran03},
227
{"fortran08", eLanguageTypeFortran08},
228
{"renderscript", eLanguageTypeRenderScript},
229
{"bliss", eLanguageTypeBLISS},
230
{"kotlin", eLanguageTypeKotlin},
231
{"zig", eLanguageTypeZig},
232
{"crystal", eLanguageTypeCrystal},
233
{"<invalid language>",
234
static_cast<LanguageType>(
235
0x0029)}, // Not yet taken by any language in the DWARF spec
236
// and thus has no entry in LanguageType
237
{"c++17", eLanguageTypeC_plus_plus_17},
238
{"c++20", eLanguageTypeC_plus_plus_20},
239
{"c17", eLanguageTypeC17},
240
{"fortran18", eLanguageTypeFortran18},
241
{"ada2005", eLanguageTypeAda2005},
242
{"ada2012", eLanguageTypeAda2012},
243
{"HIP", eLanguageTypeHIP},
244
{"assembly", eLanguageTypeAssembly},
245
{"c-sharp", eLanguageTypeC_sharp},
246
{"mojo", eLanguageTypeMojo},
247
// Vendor Extensions
248
{"assembler", eLanguageTypeMipsAssembler},
249
// Now synonyms, in arbitrary order
250
{"objc", eLanguageTypeObjC},
251
{"objc++", eLanguageTypeObjC_plus_plus},
252
{"pascal", eLanguageTypePascal83}};
253
254
static uint32_t num_languages =
255
sizeof(language_names) / sizeof(struct language_name_pair);
256
257
LanguageType Language::GetLanguageTypeFromString(llvm::StringRef string) {
258
for (const auto &L : language_names) {
259
if (string.equals_insensitive(L.name))
260
return static_cast<LanguageType>(L.type);
261
}
262
263
return eLanguageTypeUnknown;
264
}
265
266
const char *Language::GetNameForLanguageType(LanguageType language) {
267
if (language < num_languages)
268
return language_names[language].name;
269
else
270
return language_names[eLanguageTypeUnknown].name;
271
}
272
273
void Language::PrintSupportedLanguagesForExpressions(Stream &s,
274
llvm::StringRef prefix,
275
llvm::StringRef suffix) {
276
auto supported = Language::GetLanguagesSupportingTypeSystemsForExpressions();
277
for (size_t idx = 0; idx < num_languages; ++idx) {
278
auto const &lang = language_names[idx];
279
if (supported[lang.type])
280
s << prefix << lang.name << suffix;
281
}
282
}
283
284
void Language::PrintAllLanguages(Stream &s, const char *prefix,
285
const char *suffix) {
286
for (uint32_t i = 1; i < num_languages; i++) {
287
s.Printf("%s%s%s", prefix, language_names[i].name, suffix);
288
}
289
}
290
291
void Language::ForAllLanguages(
292
std::function<bool(lldb::LanguageType)> callback) {
293
for (uint32_t i = 1; i < num_languages; i++) {
294
if (!callback(language_names[i].type))
295
break;
296
}
297
}
298
299
bool Language::LanguageIsCPlusPlus(LanguageType language) {
300
switch (language) {
301
case eLanguageTypeC_plus_plus:
302
case eLanguageTypeC_plus_plus_03:
303
case eLanguageTypeC_plus_plus_11:
304
case eLanguageTypeC_plus_plus_14:
305
case eLanguageTypeC_plus_plus_17:
306
case eLanguageTypeC_plus_plus_20:
307
case eLanguageTypeObjC_plus_plus:
308
return true;
309
default:
310
return false;
311
}
312
}
313
314
bool Language::LanguageIsObjC(LanguageType language) {
315
switch (language) {
316
case eLanguageTypeObjC:
317
case eLanguageTypeObjC_plus_plus:
318
return true;
319
default:
320
return false;
321
}
322
}
323
324
bool Language::LanguageIsC(LanguageType language) {
325
switch (language) {
326
case eLanguageTypeC:
327
case eLanguageTypeC89:
328
case eLanguageTypeC99:
329
case eLanguageTypeC11:
330
return true;
331
default:
332
return false;
333
}
334
}
335
336
bool Language::LanguageIsCFamily(LanguageType language) {
337
switch (language) {
338
case eLanguageTypeC:
339
case eLanguageTypeC89:
340
case eLanguageTypeC99:
341
case eLanguageTypeC11:
342
case eLanguageTypeC_plus_plus:
343
case eLanguageTypeC_plus_plus_03:
344
case eLanguageTypeC_plus_plus_11:
345
case eLanguageTypeC_plus_plus_14:
346
case eLanguageTypeC_plus_plus_17:
347
case eLanguageTypeC_plus_plus_20:
348
case eLanguageTypeObjC_plus_plus:
349
case eLanguageTypeObjC:
350
return true;
351
default:
352
return false;
353
}
354
}
355
356
bool Language::LanguageIsPascal(LanguageType language) {
357
switch (language) {
358
case eLanguageTypePascal83:
359
return true;
360
default:
361
return false;
362
}
363
}
364
365
LanguageType Language::GetPrimaryLanguage(LanguageType language) {
366
switch (language) {
367
case eLanguageTypeC_plus_plus:
368
case eLanguageTypeC_plus_plus_03:
369
case eLanguageTypeC_plus_plus_11:
370
case eLanguageTypeC_plus_plus_14:
371
case eLanguageTypeC_plus_plus_17:
372
case eLanguageTypeC_plus_plus_20:
373
return eLanguageTypeC_plus_plus;
374
case eLanguageTypeC:
375
case eLanguageTypeC89:
376
case eLanguageTypeC99:
377
case eLanguageTypeC11:
378
return eLanguageTypeC;
379
case eLanguageTypeObjC:
380
case eLanguageTypeObjC_plus_plus:
381
return eLanguageTypeObjC;
382
case eLanguageTypePascal83:
383
case eLanguageTypeCobol74:
384
case eLanguageTypeCobol85:
385
case eLanguageTypeFortran77:
386
case eLanguageTypeFortran90:
387
case eLanguageTypeFortran95:
388
case eLanguageTypeFortran03:
389
case eLanguageTypeFortran08:
390
case eLanguageTypeAda83:
391
case eLanguageTypeAda95:
392
case eLanguageTypeModula2:
393
case eLanguageTypeJava:
394
case eLanguageTypePLI:
395
case eLanguageTypeUPC:
396
case eLanguageTypeD:
397
case eLanguageTypePython:
398
case eLanguageTypeOpenCL:
399
case eLanguageTypeGo:
400
case eLanguageTypeModula3:
401
case eLanguageTypeHaskell:
402
case eLanguageTypeOCaml:
403
case eLanguageTypeRust:
404
case eLanguageTypeSwift:
405
case eLanguageTypeJulia:
406
case eLanguageTypeDylan:
407
case eLanguageTypeMipsAssembler:
408
case eLanguageTypeMojo:
409
case eLanguageTypeUnknown:
410
default:
411
return language;
412
}
413
}
414
415
std::set<lldb::LanguageType> Language::GetSupportedLanguages() {
416
std::set<lldb::LanguageType> supported_languages;
417
ForEach([&](Language *lang) {
418
supported_languages.emplace(lang->GetLanguageType());
419
return true;
420
});
421
return supported_languages;
422
}
423
424
LanguageSet Language::GetLanguagesSupportingTypeSystems() {
425
return PluginManager::GetAllTypeSystemSupportedLanguagesForTypes();
426
}
427
428
LanguageSet Language::GetLanguagesSupportingTypeSystemsForExpressions() {
429
return PluginManager::GetAllTypeSystemSupportedLanguagesForExpressions();
430
}
431
432
LanguageSet Language::GetLanguagesSupportingREPLs() {
433
return PluginManager::GetREPLAllTypeSystemSupportedLanguages();
434
}
435
436
std::unique_ptr<Language::TypeScavenger> Language::GetTypeScavenger() {
437
return nullptr;
438
}
439
440
const char *Language::GetLanguageSpecificTypeLookupHelp() { return nullptr; }
441
442
size_t Language::TypeScavenger::Find(ExecutionContextScope *exe_scope,
443
const char *key, ResultSet &results,
444
bool append) {
445
if (!exe_scope || !exe_scope->CalculateTarget().get())
446
return false;
447
448
if (!key || !key[0])
449
return false;
450
451
if (!append)
452
results.clear();
453
454
size_t old_size = results.size();
455
456
if (this->Find_Impl(exe_scope, key, results))
457
return results.size() - old_size;
458
return 0;
459
}
460
461
bool Language::ImageListTypeScavenger::Find_Impl(
462
ExecutionContextScope *exe_scope, const char *key, ResultSet &results) {
463
bool result = false;
464
465
Target *target = exe_scope->CalculateTarget().get();
466
if (target) {
467
const auto &images(target->GetImages());
468
TypeQuery query(key);
469
TypeResults type_results;
470
images.FindTypes(nullptr, query, type_results);
471
for (const auto &match : type_results.GetTypeMap().Types()) {
472
if (match) {
473
CompilerType compiler_type(match->GetFullCompilerType());
474
compiler_type = AdjustForInclusion(compiler_type);
475
if (!compiler_type)
476
continue;
477
std::unique_ptr<Language::TypeScavenger::Result> scavengeresult(
478
new Result(compiler_type));
479
results.insert(std::move(scavengeresult));
480
result = true;
481
}
482
}
483
}
484
485
return result;
486
}
487
488
std::pair<llvm::StringRef, llvm::StringRef>
489
Language::GetFormatterPrefixSuffix(llvm::StringRef type_hint) {
490
return std::pair<llvm::StringRef, llvm::StringRef>();
491
}
492
493
bool Language::DemangledNameContainsPath(llvm::StringRef path,
494
ConstString demangled) const {
495
// The base implementation does a simple contains comparision:
496
if (path.empty())
497
return false;
498
return demangled.GetStringRef().contains(path);
499
}
500
501
DumpValueObjectOptions::DeclPrintingHelper Language::GetDeclPrintingHelper() {
502
return nullptr;
503
}
504
505
LazyBool Language::IsLogicalTrue(ValueObject &valobj, Status &error) {
506
return eLazyBoolCalculate;
507
}
508
509
bool Language::IsNilReference(ValueObject &valobj) { return false; }
510
511
bool Language::IsUninitializedReference(ValueObject &valobj) { return false; }
512
513
bool Language::GetFunctionDisplayName(const SymbolContext *sc,
514
const ExecutionContext *exe_ctx,
515
FunctionNameRepresentation representation,
516
Stream &s) {
517
return false;
518
}
519
520
void Language::GetExceptionResolverDescription(bool catch_on, bool throw_on,
521
Stream &s) {
522
GetDefaultExceptionResolverDescription(catch_on, throw_on, s);
523
}
524
525
void Language::GetDefaultExceptionResolverDescription(bool catch_on,
526
bool throw_on,
527
Stream &s) {
528
s.Printf("Exception breakpoint (catch: %s throw: %s)",
529
catch_on ? "on" : "off", throw_on ? "on" : "off");
530
}
531
// Constructor
532
Language::Language() = default;
533
534
// Destructor
535
Language::~Language() = default;
536
537
SourceLanguage::SourceLanguage(lldb::LanguageType language_type) {
538
auto lname =
539
llvm::dwarf::toDW_LNAME((llvm::dwarf::SourceLanguage)language_type);
540
if (!lname)
541
return;
542
name = lname->first;
543
version = lname->second;
544
}
545
546
lldb::LanguageType SourceLanguage::AsLanguageType() const {
547
if (auto lang = llvm::dwarf::toDW_LANG((llvm::dwarf::SourceLanguageName)name,
548
version))
549
return (lldb::LanguageType)*lang;
550
return lldb::eLanguageTypeUnknown;
551
}
552
553
llvm::StringRef SourceLanguage::GetDescription() const {
554
LanguageType type = AsLanguageType();
555
if (type)
556
return Language::GetNameForLanguageType(type);
557
return llvm::dwarf::LanguageDescription(
558
(llvm::dwarf::SourceLanguageName)name);
559
}
560
bool SourceLanguage::IsC() const { return name == llvm::dwarf::DW_LNAME_C; }
561
562
bool SourceLanguage::IsObjC() const {
563
return name == llvm::dwarf::DW_LNAME_ObjC;
564
}
565
566
bool SourceLanguage::IsCPlusPlus() const {
567
return name == llvm::dwarf::DW_LNAME_C_plus_plus;
568
}
569
570