LLDB  mainline
TypeSystem.cpp
Go to the documentation of this file.
1 //===-- TypeSystem.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 //
10 // TypeSystem.cpp
11 // lldb
12 //
13 // Created by Ryan Brown on 3/29/15.
14 //
15 //
16 
17 #include "lldb/Symbol/TypeSystem.h"
18 
19 #include <set>
20 
23 #include "lldb/Target/Language.h"
24 
25 using namespace lldb_private;
26 using namespace lldb;
27 
28 /// A 64-bit SmallBitVector is only small up to 64-7 bits, and the
29 /// setBitsInMask interface wants to write full bytes.
30 static const size_t g_num_small_bitvector_bits = 64 - 8;
32  "Languages bit vector is no longer small on 64 bit systems");
34 
35 llvm::Optional<LanguageType> LanguageSet::GetSingularLanguage() {
36  if (bitvector.count() == 1)
37  return (LanguageType)bitvector.find_first();
38  return {};
39 }
40 
41 void LanguageSet::Insert(LanguageType language) { bitvector.set(language); }
42 size_t LanguageSet::Size() const { return bitvector.count(); }
43 bool LanguageSet::Empty() const { return bitvector.none(); }
44 bool LanguageSet::operator[](unsigned i) const { return bitvector[i]; }
45 
47 
48 static lldb::TypeSystemSP CreateInstanceHelper(lldb::LanguageType language,
49  Module *module, Target *target) {
50  uint32_t i = 0;
51  TypeSystemCreateInstance create_callback;
52  while ((create_callback = PluginManager::GetTypeSystemCreateCallbackAtIndex(
53  i++)) != nullptr) {
54  lldb::TypeSystemSP type_system_sp =
55  create_callback(language, module, target);
56  if (type_system_sp)
57  return type_system_sp;
58  }
59 
60  return lldb::TypeSystemSP();
61 }
62 
63 lldb::TypeSystemSP TypeSystem::CreateInstance(lldb::LanguageType language,
64  Module *module) {
65  return CreateInstanceHelper(language, module, nullptr);
66 }
67 
68 lldb::TypeSystemSP TypeSystem::CreateInstance(lldb::LanguageType language,
69  Target *target) {
70  return CreateInstanceHelper(language, nullptr, target);
71 }
72 
73 #ifndef NDEBUG
75 #endif
76 
78  return false;
79 }
80 
82  uint64_t size) {
83  return CompilerType();
84 }
85 
88  return CompilerType();
89 }
90 
93  return CompilerType();
94 }
95 
97  return CompilerType();
98 }
99 
101  return CompilerType();
102 }
103 
106  return CompilerType();
107 }
108 
111  return CompilerType();
112 }
113 
115  const char *name,
116  const CompilerDeclContext &decl_ctx,
117  uint32_t opaque_payload) {
118  return CompilerType();
119 }
120 
122  return CompilerType();
123 }
124 
126  return CompilerType(this, type);
127 }
128 
130  return 0;
131 }
132 
136 }
137 
139  size_t idx) {
140  return CompilerType();
141 }
142 
143 llvm::Optional<CompilerType::IntegralTemplateArgument>
145  size_t idx) {
146  return llvm::None;
147 }
148 
150  return eLazyBoolCalculate;
151 }
152 
154  return false;
155 }
156 
158  return ConstString();
159 }
160 
162  return CompilerDeclContext();
163 }
164 
166  return CompilerType();
167 }
168 
169 size_t TypeSystem::DeclGetFunctionNumArguments(void *opaque_decl) { return 0; }
170 
172  size_t arg_idx) {
173  return CompilerType();
174 }
175 
176 std::vector<CompilerDecl>
178  bool ignore_imported_decls) {
179  return std::vector<CompilerDecl>();
180 }
181 
182 #pragma mark TypeSystemMap
183 
185  : m_mutex(), m_map(), m_clear_in_progress(false) {}
186 
188 
190  collection map;
191  {
192  std::lock_guard<std::mutex> guard(m_mutex);
193  map = m_map;
194  m_clear_in_progress = true;
195  }
196  std::set<TypeSystem *> visited;
197  for (auto pair : map) {
198  TypeSystem *type_system = pair.second.get();
199  if (type_system && !visited.count(type_system)) {
200  visited.insert(type_system);
201  type_system->Finalize();
202  }
203  }
204  map.clear();
205  {
206  std::lock_guard<std::mutex> guard(m_mutex);
207  m_map.clear();
208  m_clear_in_progress = false;
209  }
210 }
211 
212 void TypeSystemMap::ForEach(std::function<bool(TypeSystem *)> const &callback) {
213  std::lock_guard<std::mutex> guard(m_mutex);
214  // Use a std::set so we only call the callback once for each unique
215  // TypeSystem instance
216  std::set<TypeSystem *> visited;
217  for (auto pair : m_map) {
218  TypeSystem *type_system = pair.second.get();
219  if (type_system && !visited.count(type_system)) {
220  visited.insert(type_system);
221  if (!callback(type_system))
222  break;
223  }
224  }
225 }
226 
227 llvm::Expected<TypeSystem &>
229  Module *module, bool can_create) {
230  llvm::Error error = llvm::Error::success();
231  assert(!error); // Check the success value when assertions are enabled
232  std::lock_guard<std::mutex> guard(m_mutex);
233  if (m_clear_in_progress) {
234  error = llvm::make_error<llvm::StringError>(
235  "Unable to get TypeSystem because TypeSystemMap is being cleared",
236  llvm::inconvertibleErrorCode());
237  } else {
238  collection::iterator pos = m_map.find(language);
239  if (pos != m_map.end()) {
240  auto *type_system = pos->second.get();
241  if (type_system) {
242  llvm::consumeError(std::move(error));
243  return *type_system;
244  }
245  error = llvm::make_error<llvm::StringError>(
246  "TypeSystem for language " +
247  llvm::StringRef(Language::GetNameForLanguageType(language)) +
248  " doesn't exist",
249  llvm::inconvertibleErrorCode());
250  return std::move(error);
251  }
252 
253  for (const auto &pair : m_map) {
254  if (pair.second && pair.second->SupportsLanguage(language)) {
255  // Add a new mapping for "language" to point to an already existing
256  // TypeSystem that supports this language
257  m_map[language] = pair.second;
258  if (pair.second.get()) {
259  llvm::consumeError(std::move(error));
260  return *pair.second.get();
261  }
262  error = llvm::make_error<llvm::StringError>(
263  "TypeSystem for language " +
264  llvm::StringRef(Language::GetNameForLanguageType(language)) +
265  " doesn't exist",
266  llvm::inconvertibleErrorCode());
267  return std::move(error);
268  }
269  }
270 
271  if (!can_create) {
272  error = llvm::make_error<llvm::StringError>(
273  "Unable to find type system for language " +
274  llvm::StringRef(Language::GetNameForLanguageType(language)),
275  llvm::inconvertibleErrorCode());
276  } else {
277  // Cache even if we get a shared pointer that contains a null type system
278  // back
279  auto type_system_sp = TypeSystem::CreateInstance(language, module);
280  m_map[language] = type_system_sp;
281  if (type_system_sp.get()) {
282  llvm::consumeError(std::move(error));
283  return *type_system_sp.get();
284  }
285  error = llvm::make_error<llvm::StringError>(
286  "TypeSystem for language " +
287  llvm::StringRef(Language::GetNameForLanguageType(language)) +
288  " doesn't exist",
289  llvm::inconvertibleErrorCode());
290  }
291  }
292 
293  return std::move(error);
294 }
295 
296 llvm::Expected<TypeSystem &>
298  Target *target, bool can_create) {
299  llvm::Error error = llvm::Error::success();
300  assert(!error); // Check the success value when assertions are enabled
301  std::lock_guard<std::mutex> guard(m_mutex);
302  if (m_clear_in_progress) {
303  error = llvm::make_error<llvm::StringError>(
304  "Unable to get TypeSystem because TypeSystemMap is being cleared",
305  llvm::inconvertibleErrorCode());
306  } else {
307  collection::iterator pos = m_map.find(language);
308  if (pos != m_map.end()) {
309  auto *type_system = pos->second.get();
310  if (type_system) {
311  llvm::consumeError(std::move(error));
312  return *type_system;
313  }
314  error = llvm::make_error<llvm::StringError>(
315  "TypeSystem for language " +
316  llvm::StringRef(Language::GetNameForLanguageType(language)) +
317  " doesn't exist",
318  llvm::inconvertibleErrorCode());
319  return std::move(error);
320  }
321 
322  for (const auto &pair : m_map) {
323  if (pair.second && pair.second->SupportsLanguage(language)) {
324  // Add a new mapping for "language" to point to an already existing
325  // TypeSystem that supports this language
326  m_map[language] = pair.second;
327  if (pair.second.get()) {
328  llvm::consumeError(std::move(error));
329  return *pair.second.get();
330  }
331  error = llvm::make_error<llvm::StringError>(
332  "TypeSystem for language " +
333  llvm::StringRef(Language::GetNameForLanguageType(language)) +
334  " doesn't exist",
335  llvm::inconvertibleErrorCode());
336  return std::move(error);
337  }
338  }
339 
340  if (!can_create) {
341  error = llvm::make_error<llvm::StringError>(
342  "Unable to find type system for language " +
343  llvm::StringRef(Language::GetNameForLanguageType(language)),
344  llvm::inconvertibleErrorCode());
345  } else {
346  // Cache even if we get a shared pointer that contains a null type system
347  // back
348  auto type_system_sp = TypeSystem::CreateInstance(language, target);
349  m_map[language] = type_system_sp;
350  if (type_system_sp.get()) {
351  llvm::consumeError(std::move(error));
352  return *type_system_sp.get();
353  }
354  error = llvm::make_error<llvm::StringError>(
355  "TypeSystem for language " +
356  llvm::StringRef(Language::GetNameForLanguageType(language)) +
357  " doesn't exist",
358  llvm::inconvertibleErrorCode());
359  }
360  }
361 
362  return std::move(error);
363 }
virtual bool IsAnonymousType(lldb::opaque_compiler_type_t type)
Definition: TypeSystem.cpp:77
static TypeSystemCreateInstance GetTypeSystemCreateCallbackAtIndex(uint32_t idx)
virtual CompilerType AddVolatileModifier(lldb::opaque_compiler_type_t type)
Definition: TypeSystem.cpp:105
virtual bool IsMeaninglessWithoutDynamicResolution(void *type)
Definition: TypeSystem.cpp:153
A class that represents a running process on the host machine.
Represents a generic declaration context in a program.
void Insert(lldb::LanguageType language)
Definition: TypeSystem.cpp:41
llvm::Error Error
virtual CompilerType CreateTypedef(lldb::opaque_compiler_type_t type, const char *name, const CompilerDeclContext &decl_ctx, uint32_t opaque_payload)
Definition: TypeSystem.cpp:114
virtual CompilerType GetLValueReferenceType(lldb::opaque_compiler_type_t type)
Definition: TypeSystem.cpp:87
void * opaque_compiler_type_t
Definition: lldb-types.h:90
virtual bool Verify(lldb::opaque_compiler_type_t type)=0
Verify the integrity of the type to catch CompilerTypes that mix and match invalid TypeSystem/Opaque ...
Definition: TypeSystem.cpp:74
llvm::Optional< lldb::LanguageType > GetSingularLanguage()
If the set contains a single language only, return it.
Definition: TypeSystem.cpp:35
virtual lldb::TemplateArgumentKind GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, size_t idx)
Definition: TypeSystem.cpp:134
llvm::SmallBitVector bitvector
Definition: TypeSystem.h:41
virtual CompilerType DeclGetFunctionReturnType(void *opaque_decl)
Definition: TypeSystem.cpp:165
static const size_t g_num_small_bitvector_bits
A 64-bit SmallBitVector is only small up to 64-7 bits, and the setBitsInMask interface wants to write...
Definition: TypeSystem.cpp:30
LanguageType
Programming language type.
virtual CompilerType GetTypeForFormatters(void *type)
Definition: TypeSystem.cpp:125
virtual CompilerType GetArrayType(lldb::opaque_compiler_type_t type, uint64_t size)
Definition: TypeSystem.cpp:81
virtual CompilerType GetAtomicType(lldb::opaque_compiler_type_t type)
Definition: TypeSystem.cpp:96
A class that describes an executable image and its associated object and symbol files.
Definition: Module.h:75
virtual CompilerType DeclGetFunctionArgumentType(void *opaque_decl, size_t arg_idx)
Definition: TypeSystem.cpp:171
static lldb::TypeSystemSP CreateInstanceHelper(lldb::LanguageType language, Module *module, Target *target)
Definition: TypeSystem.cpp:48
static lldb::TypeSystemSP CreateInstance(lldb::LanguageType language, Module *module)
Definition: TypeSystem.cpp:63
virtual CompilerDeclContext DeclGetDeclContext(void *opaque_decl)
Definition: TypeSystem.cpp:161
virtual llvm::Optional< CompilerType::IntegralTemplateArgument > GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx)
Definition: TypeSystem.cpp:144
llvm::Expected< TypeSystem & > GetTypeSystemForLanguage(lldb::LanguageType language, Module *module, bool can_create)
Definition: TypeSystem.cpp:228
Interface for representing a type system.
Definition: TypeSystem.h:71
virtual void Finalize()
Definition: TypeSystem.h:87
virtual CompilerType AddRestrictModifier(lldb::opaque_compiler_type_t type)
Definition: TypeSystem.cpp:110
virtual CompilerType AddConstModifier(lldb::opaque_compiler_type_t type)
Definition: TypeSystem.cpp:100
A uniqued constant string class.
Definition: ConstString.h:40
Definition: SBAddress.h:15
Represents a generic type in a programming language.
Definition: CompilerType.h:33
bool operator[](unsigned i) const
Definition: TypeSystem.cpp:44
virtual ConstString DeclGetMangledName(void *opaque_decl)
Definition: TypeSystem.cpp:157
virtual size_t DeclGetFunctionNumArguments(void *opaque_decl)
Definition: TypeSystem.cpp:169
virtual CompilerType GetTypeTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx)
Definition: TypeSystem.cpp:138
std::map< lldb::LanguageType, lldb::TypeSystemSP > collection
Definition: TypeSystem.h:520
void ForEach(std::function< bool(TypeSystem *)> const &callback)
Definition: TypeSystem.cpp:212
static const char * GetNameForLanguageType(lldb::LanguageType language)
Definition: Language.cpp:206
virtual CompilerType GetRValueReferenceType(lldb::opaque_compiler_type_t type)
Definition: TypeSystem.cpp:92
virtual std::vector< CompilerDecl > DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name, const bool ignore_imported_decls)
Definition: TypeSystem.cpp:177
virtual CompilerType GetBuiltinTypeByName(ConstString name)
Definition: TypeSystem.cpp:121
std::mutex m_mutex
A mutex to keep this object happy in multi-threaded environments.
Definition: TypeSystem.h:521
virtual size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type)
Definition: TypeSystem.cpp:129
virtual LazyBool ShouldPrintAsOneLiner(void *type, ValueObject *valobj)
Definition: TypeSystem.cpp:149