1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
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/Symbol/SymbolFile.h" |
19 | #include "lldb/Symbol/TypeList.h" |
20 | #include "lldb/Target/Target.h" |
21 | #include "lldb/Utility/Stream.h" |
22 | |
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 | static LanguagesMap &GetLanguagesMap() { |
33 | static LanguagesMap *g_map = nullptr; |
34 | static llvm::once_flag g_initialize; |
35 | |
36 | llvm::call_once(g_initialize, [] { |
37 | g_map = new LanguagesMap(); |
38 | |
39 | }); |
40 | |
41 | return *g_map; |
42 | } |
43 | static std::mutex &GetLanguagesMutex() { |
44 | static std::mutex *g_mutex = nullptr; |
| 2 | | 'g_mutex' initialized to a null pointer value | |
|
45 | static llvm::once_flag g_initialize; |
46 | |
47 | llvm::call_once(g_initialize, [] { |
48 | g_mutex = new std::mutex(); |
49 | |
50 | }); |
51 | |
52 | return *g_mutex; |
| 3 | | Returning null reference |
|
53 | } |
54 | |
55 | Language *Language::FindPlugin(lldb::LanguageType language) { |
56 | std::lock_guard<std::mutex> guard(GetLanguagesMutex()); |
57 | LanguagesMap &map(GetLanguagesMap()); |
58 | auto iter = map.find(language), end = map.end(); |
59 | if (iter != end) |
60 | return iter->second.get(); |
61 | |
62 | Language *language_ptr = nullptr; |
63 | LanguageCreateInstance create_callback; |
64 | |
65 | for (uint32_t idx = 0; |
66 | (create_callback = |
67 | PluginManager::GetLanguageCreateCallbackAtIndex(idx)) != nullptr; |
68 | ++idx) { |
69 | language_ptr = create_callback(language); |
70 | |
71 | if (language_ptr) { |
72 | map[language] = std::unique_ptr<Language>(language_ptr); |
73 | return language_ptr; |
74 | } |
75 | } |
76 | |
77 | return nullptr; |
78 | } |
79 | |
80 | void Language::ForEach(std::function<bool(Language *)> callback) { |
81 | std::lock_guard<std::mutex> guard(GetLanguagesMutex()); |
| 1 | Calling 'GetLanguagesMutex' | |
|
82 | LanguagesMap &map(GetLanguagesMap()); |
83 | for (const auto &entry : map) { |
84 | if (!callback(entry.second.get())) |
85 | break; |
86 | } |
87 | } |
88 | |
89 | bool Language::IsTopLevelFunction(Function &function) { return false; } |
90 | |
91 | lldb::TypeCategoryImplSP Language::GetFormatters() { return nullptr; } |
92 | |
93 | HardcodedFormatters::HardcodedFormatFinder Language::GetHardcodedFormats() { |
94 | return {}; |
95 | } |
96 | |
97 | HardcodedFormatters::HardcodedSummaryFinder Language::GetHardcodedSummaries() { |
98 | return {}; |
99 | } |
100 | |
101 | HardcodedFormatters::HardcodedSyntheticFinder |
102 | Language::GetHardcodedSynthetics() { |
103 | return {}; |
104 | } |
105 | |
106 | HardcodedFormatters::HardcodedValidatorFinder |
107 | Language::GetHardcodedValidators() { |
108 | return {}; |
109 | } |
110 | |
111 | std::vector<ConstString> |
112 | Language::GetPossibleFormattersMatches(ValueObject &valobj, |
113 | lldb::DynamicValueType use_dynamic) { |
114 | return {}; |
115 | } |
116 | |
117 | lldb_private::formatters::StringPrinter::EscapingHelper |
118 | Language::GetStringPrinterEscapingHelper( |
119 | lldb_private::formatters::StringPrinter::GetPrintableElementType |
120 | elem_type) { |
121 | return StringPrinter::GetDefaultEscapingHelper(elem_type); |
122 | } |
123 | |
124 | struct language_name_pair { |
125 | const char *name; |
126 | LanguageType type; |
127 | }; |
128 | |
129 | struct language_name_pair language_names[] = { |
130 | |
131 | |
132 | {"unknown", eLanguageTypeUnknown}, |
133 | {"c89", eLanguageTypeC89}, |
134 | {"c", eLanguageTypeC}, |
135 | {"ada83", eLanguageTypeAda83}, |
136 | {"c++", eLanguageTypeC_plus_plus}, |
137 | {"cobol74", eLanguageTypeCobol74}, |
138 | {"cobol85", eLanguageTypeCobol85}, |
139 | {"fortran77", eLanguageTypeFortran77}, |
140 | {"fortran90", eLanguageTypeFortran90}, |
141 | {"pascal83", eLanguageTypePascal83}, |
142 | {"modula2", eLanguageTypeModula2}, |
143 | {"java", eLanguageTypeJava}, |
144 | {"c99", eLanguageTypeC99}, |
145 | {"ada95", eLanguageTypeAda95}, |
146 | {"fortran95", eLanguageTypeFortran95}, |
147 | {"pli", eLanguageTypePLI}, |
148 | {"objective-c", eLanguageTypeObjC}, |
149 | {"objective-c++", eLanguageTypeObjC_plus_plus}, |
150 | {"upc", eLanguageTypeUPC}, |
151 | {"d", eLanguageTypeD}, |
152 | {"python", eLanguageTypePython}, |
153 | {"opencl", eLanguageTypeOpenCL}, |
154 | {"go", eLanguageTypeGo}, |
155 | {"modula3", eLanguageTypeModula3}, |
156 | {"haskell", eLanguageTypeHaskell}, |
157 | {"c++03", eLanguageTypeC_plus_plus_03}, |
158 | {"c++11", eLanguageTypeC_plus_plus_11}, |
159 | {"ocaml", eLanguageTypeOCaml}, |
160 | {"rust", eLanguageTypeRust}, |
161 | {"c11", eLanguageTypeC11}, |
162 | {"swift", eLanguageTypeSwift}, |
163 | {"julia", eLanguageTypeJulia}, |
164 | {"dylan", eLanguageTypeDylan}, |
165 | {"c++14", eLanguageTypeC_plus_plus_14}, |
166 | {"fortran03", eLanguageTypeFortran03}, |
167 | {"fortran08", eLanguageTypeFortran08}, |
168 | |
169 | {"mipsassem", eLanguageTypeMipsAssembler}, |
170 | {"renderscript", eLanguageTypeExtRenderScript}, |
171 | |
172 | {"objc", eLanguageTypeObjC}, |
173 | {"objc++", eLanguageTypeObjC_plus_plus}, |
174 | {"pascal", eLanguageTypePascal83}}; |
175 | |
176 | static uint32_t num_languages = |
177 | sizeof(language_names) / sizeof(struct language_name_pair); |
178 | |
179 | LanguageType Language::GetLanguageTypeFromString(llvm::StringRef string) { |
180 | for (const auto &L : language_names) { |
181 | if (string.equals_lower(L.name)) |
182 | return static_cast<LanguageType>(L.type); |
183 | } |
184 | |
185 | return eLanguageTypeUnknown; |
186 | } |
187 | |
188 | const char *Language::GetNameForLanguageType(LanguageType language) { |
189 | if (language < num_languages) |
190 | return language_names[language].name; |
191 | else |
192 | return language_names[eLanguageTypeUnknown].name; |
193 | } |
194 | |
195 | void Language::PrintAllLanguages(Stream &s, const char *prefix, |
196 | const char *suffix) { |
197 | for (uint32_t i = 1; i < num_languages; i++) { |
198 | s.Printf("%s%s%s", prefix, language_names[i].name, suffix); |
199 | } |
200 | } |
201 | |
202 | void Language::ForAllLanguages( |
203 | std::function<bool(lldb::LanguageType)> callback) { |
204 | for (uint32_t i = 1; i < num_languages; i++) { |
205 | if (!callback(language_names[i].type)) |
206 | break; |
207 | } |
208 | } |
209 | |
210 | bool Language::LanguageIsCPlusPlus(LanguageType language) { |
211 | switch (language) { |
212 | case eLanguageTypeC_plus_plus: |
213 | case eLanguageTypeC_plus_plus_03: |
214 | case eLanguageTypeC_plus_plus_11: |
215 | case eLanguageTypeC_plus_plus_14: |
216 | case eLanguageTypeObjC_plus_plus: |
217 | return true; |
218 | default: |
219 | return false; |
220 | } |
221 | } |
222 | |
223 | bool Language::LanguageIsObjC(LanguageType language) { |
224 | switch (language) { |
225 | case eLanguageTypeObjC: |
226 | case eLanguageTypeObjC_plus_plus: |
227 | return true; |
228 | default: |
229 | return false; |
230 | } |
231 | } |
232 | |
233 | bool Language::LanguageIsC(LanguageType language) { |
234 | switch (language) { |
235 | case eLanguageTypeC: |
236 | case eLanguageTypeC89: |
237 | case eLanguageTypeC99: |
238 | case eLanguageTypeC11: |
239 | return true; |
240 | default: |
241 | return false; |
242 | } |
243 | } |
244 | |
245 | bool Language::LanguageIsPascal(LanguageType language) { |
246 | switch (language) { |
247 | case eLanguageTypePascal83: |
248 | return true; |
249 | default: |
250 | return false; |
251 | } |
252 | } |
253 | |
254 | LanguageType Language::GetPrimaryLanguage(LanguageType language) { |
255 | switch (language) { |
256 | case eLanguageTypeC_plus_plus: |
257 | case eLanguageTypeC_plus_plus_03: |
258 | case eLanguageTypeC_plus_plus_11: |
259 | case eLanguageTypeC_plus_plus_14: |
260 | return eLanguageTypeC_plus_plus; |
261 | case eLanguageTypeC: |
262 | case eLanguageTypeC89: |
263 | case eLanguageTypeC99: |
264 | case eLanguageTypeC11: |
265 | return eLanguageTypeC; |
266 | case eLanguageTypeObjC: |
267 | case eLanguageTypeObjC_plus_plus: |
268 | return eLanguageTypeObjC; |
269 | case eLanguageTypePascal83: |
270 | case eLanguageTypeCobol74: |
271 | case eLanguageTypeCobol85: |
272 | case eLanguageTypeFortran77: |
273 | case eLanguageTypeFortran90: |
274 | case eLanguageTypeFortran95: |
275 | case eLanguageTypeFortran03: |
276 | case eLanguageTypeFortran08: |
277 | case eLanguageTypeAda83: |
278 | case eLanguageTypeAda95: |
279 | case eLanguageTypeModula2: |
280 | case eLanguageTypeJava: |
281 | case eLanguageTypePLI: |
282 | case eLanguageTypeUPC: |
283 | case eLanguageTypeD: |
284 | case eLanguageTypePython: |
285 | case eLanguageTypeOpenCL: |
286 | case eLanguageTypeGo: |
287 | case eLanguageTypeModula3: |
288 | case eLanguageTypeHaskell: |
289 | case eLanguageTypeOCaml: |
290 | case eLanguageTypeRust: |
291 | case eLanguageTypeSwift: |
292 | case eLanguageTypeJulia: |
293 | case eLanguageTypeDylan: |
294 | case eLanguageTypeMipsAssembler: |
295 | case eLanguageTypeExtRenderScript: |
296 | case eLanguageTypeUnknown: |
297 | default: |
298 | return language; |
299 | } |
300 | } |
301 | |
302 | void Language::GetLanguagesSupportingTypeSystems( |
303 | std::set<lldb::LanguageType> &languages, |
304 | std::set<lldb::LanguageType> &languages_for_expressions) { |
305 | uint32_t idx = 0; |
306 | |
307 | while (TypeSystemEnumerateSupportedLanguages enumerate = PluginManager:: |
308 | GetTypeSystemEnumerateSupportedLanguagesCallbackAtIndex(idx++)) { |
309 | (*enumerate)(languages, languages_for_expressions); |
310 | } |
311 | } |
312 | |
313 | void Language::GetLanguagesSupportingREPLs( |
314 | std::set<lldb::LanguageType> &languages) { |
315 | uint32_t idx = 0; |
316 | |
317 | while (REPLEnumerateSupportedLanguages enumerate = |
318 | PluginManager::GetREPLEnumerateSupportedLanguagesCallbackAtIndex( |
319 | idx++)) { |
320 | (*enumerate)(languages); |
321 | } |
322 | } |
323 | |
324 | std::unique_ptr<Language::TypeScavenger> Language::GetTypeScavenger() { |
325 | return nullptr; |
326 | } |
327 | |
328 | const char *Language::GetLanguageSpecificTypeLookupHelp() { return nullptr; } |
329 | |
330 | size_t Language::TypeScavenger::Find(ExecutionContextScope *exe_scope, |
331 | const char *key, ResultSet &results, |
332 | bool append) { |
333 | if (!exe_scope || !exe_scope->CalculateTarget().get()) |
334 | return false; |
335 | |
336 | if (!key || !key[0]) |
337 | return false; |
338 | |
339 | if (!append) |
340 | results.clear(); |
341 | |
342 | size_t old_size = results.size(); |
343 | |
344 | if (this->Find_Impl(exe_scope, key, results)) |
345 | return results.size() - old_size; |
346 | return 0; |
347 | } |
348 | |
349 | bool Language::ImageListTypeScavenger::Find_Impl( |
350 | ExecutionContextScope *exe_scope, const char *key, ResultSet &results) { |
351 | bool result = false; |
352 | |
353 | Target *target = exe_scope->CalculateTarget().get(); |
354 | if (target) { |
355 | const auto &images(target->GetImages()); |
356 | SymbolContext null_sc; |
357 | ConstString cs_key(key); |
358 | llvm::DenseSet<SymbolFile *> searched_sym_files; |
359 | TypeList matches; |
360 | images.FindTypes(null_sc, cs_key, false, UINT32_MAX(4294967295U), searched_sym_files, |
361 | matches); |
362 | for (const auto &match : matches.Types()) { |
363 | if (match.get()) { |
364 | CompilerType compiler_type(match->GetFullCompilerType()); |
365 | compiler_type = AdjustForInclusion(compiler_type); |
366 | if (!compiler_type) |
367 | continue; |
368 | std::unique_ptr<Language::TypeScavenger::Result> scavengeresult( |
369 | new Result(compiler_type)); |
370 | results.insert(std::move(scavengeresult)); |
371 | result = true; |
372 | } |
373 | } |
374 | } |
375 | |
376 | return result; |
377 | } |
378 | |
379 | bool Language::GetFormatterPrefixSuffix(ValueObject &valobj, |
380 | ConstString type_hint, |
381 | std::string &prefix, |
382 | std::string &suffix) { |
383 | return false; |
384 | } |
385 | |
386 | DumpValueObjectOptions::DeclPrintingHelper Language::GetDeclPrintingHelper() { |
387 | return nullptr; |
388 | } |
389 | |
390 | LazyBool Language::IsLogicalTrue(ValueObject &valobj, Status &error) { |
391 | return eLazyBoolCalculate; |
392 | } |
393 | |
394 | bool Language::IsNilReference(ValueObject &valobj) { return false; } |
395 | |
396 | bool Language::IsUninitializedReference(ValueObject &valobj) { return false; } |
397 | |
398 | bool Language::GetFunctionDisplayName(const SymbolContext *sc, |
399 | const ExecutionContext *exe_ctx, |
400 | FunctionNameRepresentation representation, |
401 | Stream &s) { |
402 | return false; |
403 | } |
404 | |
405 | void Language::GetExceptionResolverDescription(bool catch_on, bool throw_on, |
406 | Stream &s) { |
407 | GetDefaultExceptionResolverDescription(catch_on, throw_on, s); |
408 | } |
409 | |
410 | void Language::GetDefaultExceptionResolverDescription(bool catch_on, |
411 | bool throw_on, |
412 | Stream &s) { |
413 | s.Printf("Exception breakpoint (catch: %s throw: %s)", |
414 | catch_on ? "on" : "off", throw_on ? "on" : "off"); |
415 | } |
416 | |
417 | |
418 | |
419 | Language::Language() {} |
420 | |
421 | |
422 | |
423 | |
424 | Language::~Language() {} |