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             return true;
245         default:
246             return false;
247     }
248 }
249 
250 bool
251 Language::LanguageIsObjC (LanguageType language)
252 {
253     switch (language)
254     {
255         case eLanguageTypeObjC:
256         case eLanguageTypeObjC_plus_plus:
257             return true;
258         default:
259             return false;
260     }
261 }
262 
263 bool
264 Language::LanguageIsC (LanguageType language)
265 {
266     switch (language)
267     {
268         case eLanguageTypeC:
269         case eLanguageTypeC89:
270         case eLanguageTypeC99:
271         case eLanguageTypeC11:
272             return true;
273         default:
274             return false;
275     }
276 }
277 
278 bool
279 Language::LanguageIsPascal (LanguageType language)
280 {
281     switch (language)
282     {
283         case eLanguageTypePascal83:
284             return true;
285         default:
286             return false;
287     }
288 }
289 
290 void
291 Language::GetLanguagesSupportingTypeSystems (std::set<lldb::LanguageType> &languages,
292                                              std::set<lldb::LanguageType> &languages_for_expressions)
293 {
294     uint32_t idx = 0;
295 
296     while (TypeSystemEnumerateSupportedLanguages enumerate = PluginManager::GetTypeSystemEnumerateSupportedLanguagesCallbackAtIndex(idx++))
297     {
298         (*enumerate)(languages, languages_for_expressions);
299     }
300 }
301 
302 void
303 Language::GetLanguagesSupportingREPLs (std::set<lldb::LanguageType> &languages)
304 {
305     uint32_t idx = 0;
306 
307     while (REPLEnumerateSupportedLanguages enumerate = PluginManager::GetREPLEnumerateSupportedLanguagesCallbackAtIndex(idx++))
308     {
309         (*enumerate)(languages);
310     }
311 }
312 
313 std::unique_ptr<Language::TypeScavenger>
314 Language::GetTypeScavenger ()
315 {
316     return nullptr;
317 }
318 
319 size_t
320 Language::TypeScavenger::Find (ExecutionContextScope *exe_scope,
321                                const char *key,
322                                ResultSet &results,
323                                bool append)
324 {
325     if (!exe_scope || !exe_scope->CalculateTarget().get())
326         return false;
327 
328     if (!key || !key[0])
329         return false;
330 
331     if (!append)
332         results.clear();
333 
334     size_t old_size = results.size();
335 
336     if (this->Find_Impl(exe_scope, key, results))
337         return results.size() - old_size;
338     return 0;
339 }
340 
341 bool
342 Language::GetFormatterPrefixSuffix (ValueObject& valobj, ConstString type_hint,
343                                     std::string& prefix, std::string& suffix)
344 {
345     return false;
346 }
347 
348 DumpValueObjectOptions::DeclPrintingHelper
349 Language::GetDeclPrintingHelper ()
350 {
351     return nullptr;
352 }
353 
354 LazyBool
355 Language::IsLogicalTrue (ValueObject& valobj,
356                          Error& error)
357 {
358     return eLazyBoolCalculate;
359 }
360 
361 bool
362 Language::IsNilReference (ValueObject& valobj)
363 {
364     return false;
365 }
366 
367 bool
368 Language::IsUninitializedReference (ValueObject& valobj)
369 {
370     return false;
371 }
372 
373 bool
374 Language::GetFunctionDisplayName (const SymbolContext *sc,
375                                   const ExecutionContext *exe_ctx,
376                                   FunctionNameRepresentation representation,
377                                   Stream& s)
378 {
379     return false;
380 }
381 
382 //----------------------------------------------------------------------
383 // Constructor
384 //----------------------------------------------------------------------
385 Language::Language()
386 {
387 }
388 
389 //----------------------------------------------------------------------
390 // Destructor
391 //----------------------------------------------------------------------
392 Language::~Language()
393 {
394 }
395