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