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