File: | build/source/llvm/include/llvm/ADT/SmallBitVector.h |
Warning: | line 97, column 5 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===-- PluginManager.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 | #include "lldb/Core/PluginManager.h" | |||
10 | ||||
11 | #include "lldb/Core/Debugger.h" | |||
12 | #include "lldb/Host/FileSystem.h" | |||
13 | #include "lldb/Host/HostInfo.h" | |||
14 | #include "lldb/Interpreter/OptionValueProperties.h" | |||
15 | #include "lldb/Target/Process.h" | |||
16 | #include "lldb/Utility/ConstString.h" | |||
17 | #include "lldb/Utility/FileSpec.h" | |||
18 | #include "lldb/Utility/Status.h" | |||
19 | #include "lldb/Utility/StringList.h" | |||
20 | #include "llvm/ADT/StringRef.h" | |||
21 | #include "llvm/Support/DynamicLibrary.h" | |||
22 | #include "llvm/Support/FileSystem.h" | |||
23 | #include "llvm/Support/raw_ostream.h" | |||
24 | #include <cassert> | |||
25 | #include <map> | |||
26 | #include <memory> | |||
27 | #include <mutex> | |||
28 | #include <string> | |||
29 | #include <utility> | |||
30 | #include <vector> | |||
31 | #if defined(_WIN32) | |||
32 | #include "lldb/Host/windows/PosixApi.h" | |||
33 | #endif | |||
34 | ||||
35 | using namespace lldb; | |||
36 | using namespace lldb_private; | |||
37 | ||||
38 | typedef bool (*PluginInitCallback)(); | |||
39 | typedef void (*PluginTermCallback)(); | |||
40 | ||||
41 | struct PluginInfo { | |||
42 | PluginInfo() = default; | |||
43 | ||||
44 | llvm::sys::DynamicLibrary library; | |||
45 | PluginInitCallback plugin_init_callback = nullptr; | |||
46 | PluginTermCallback plugin_term_callback = nullptr; | |||
47 | }; | |||
48 | ||||
49 | typedef std::map<FileSpec, PluginInfo> PluginTerminateMap; | |||
50 | ||||
51 | static std::recursive_mutex &GetPluginMapMutex() { | |||
52 | static std::recursive_mutex g_plugin_map_mutex; | |||
53 | return g_plugin_map_mutex; | |||
54 | } | |||
55 | ||||
56 | static PluginTerminateMap &GetPluginMap() { | |||
57 | static PluginTerminateMap g_plugin_map; | |||
58 | return g_plugin_map; | |||
59 | } | |||
60 | ||||
61 | static bool PluginIsLoaded(const FileSpec &plugin_file_spec) { | |||
62 | std::lock_guard<std::recursive_mutex> guard(GetPluginMapMutex()); | |||
63 | PluginTerminateMap &plugin_map = GetPluginMap(); | |||
64 | return plugin_map.find(plugin_file_spec) != plugin_map.end(); | |||
65 | } | |||
66 | ||||
67 | static void SetPluginInfo(const FileSpec &plugin_file_spec, | |||
68 | const PluginInfo &plugin_info) { | |||
69 | std::lock_guard<std::recursive_mutex> guard(GetPluginMapMutex()); | |||
70 | PluginTerminateMap &plugin_map = GetPluginMap(); | |||
71 | assert(plugin_map.find(plugin_file_spec) == plugin_map.end())(static_cast <bool> (plugin_map.find(plugin_file_spec) == plugin_map.end()) ? void (0) : __assert_fail ("plugin_map.find(plugin_file_spec) == plugin_map.end()" , "lldb/source/Core/PluginManager.cpp", 71, __extension__ __PRETTY_FUNCTION__ )); | |||
72 | plugin_map[plugin_file_spec] = plugin_info; | |||
73 | } | |||
74 | ||||
75 | template <typename FPtrTy> static FPtrTy CastToFPtr(void *VPtr) { | |||
76 | return reinterpret_cast<FPtrTy>(VPtr); | |||
77 | } | |||
78 | ||||
79 | static FileSystem::EnumerateDirectoryResult | |||
80 | LoadPluginCallback(void *baton, llvm::sys::fs::file_type ft, | |||
81 | llvm::StringRef path) { | |||
82 | Status error; | |||
83 | ||||
84 | namespace fs = llvm::sys::fs; | |||
85 | // If we have a regular file, a symbolic link or unknown file type, try and | |||
86 | // process the file. We must handle unknown as sometimes the directory | |||
87 | // enumeration might be enumerating a file system that doesn't have correct | |||
88 | // file type information. | |||
89 | if (ft == fs::file_type::regular_file || ft == fs::file_type::symlink_file || | |||
90 | ft == fs::file_type::type_unknown) { | |||
91 | FileSpec plugin_file_spec(path); | |||
92 | FileSystem::Instance().Resolve(plugin_file_spec); | |||
93 | ||||
94 | if (PluginIsLoaded(plugin_file_spec)) | |||
95 | return FileSystem::eEnumerateDirectoryResultNext; | |||
96 | else { | |||
97 | PluginInfo plugin_info; | |||
98 | ||||
99 | std::string pluginLoadError; | |||
100 | plugin_info.library = llvm::sys::DynamicLibrary::getPermanentLibrary( | |||
101 | plugin_file_spec.GetPath().c_str(), &pluginLoadError); | |||
102 | if (plugin_info.library.isValid()) { | |||
103 | bool success = false; | |||
104 | plugin_info.plugin_init_callback = CastToFPtr<PluginInitCallback>( | |||
105 | plugin_info.library.getAddressOfSymbol("LLDBPluginInitialize")); | |||
106 | if (plugin_info.plugin_init_callback) { | |||
107 | // Call the plug-in "bool LLDBPluginInitialize(void)" function | |||
108 | success = plugin_info.plugin_init_callback(); | |||
109 | } | |||
110 | ||||
111 | if (success) { | |||
112 | // It is ok for the "LLDBPluginTerminate" symbol to be nullptr | |||
113 | plugin_info.plugin_term_callback = CastToFPtr<PluginTermCallback>( | |||
114 | plugin_info.library.getAddressOfSymbol("LLDBPluginTerminate")); | |||
115 | } else { | |||
116 | // The initialize function returned FALSE which means the plug-in | |||
117 | // might not be compatible, or might be too new or too old, or might | |||
118 | // not want to run on this machine. Set it to a default-constructed | |||
119 | // instance to invalidate it. | |||
120 | plugin_info = PluginInfo(); | |||
121 | } | |||
122 | ||||
123 | // Regardless of success or failure, cache the plug-in load in our | |||
124 | // plug-in info so we don't try to load it again and again. | |||
125 | SetPluginInfo(plugin_file_spec, plugin_info); | |||
126 | ||||
127 | return FileSystem::eEnumerateDirectoryResultNext; | |||
128 | } | |||
129 | } | |||
130 | } | |||
131 | ||||
132 | if (ft == fs::file_type::directory_file || | |||
133 | ft == fs::file_type::symlink_file || ft == fs::file_type::type_unknown) { | |||
134 | // Try and recurse into anything that a directory or symbolic link. We must | |||
135 | // also do this for unknown as sometimes the directory enumeration might be | |||
136 | // enumerating a file system that doesn't have correct file type | |||
137 | // information. | |||
138 | return FileSystem::eEnumerateDirectoryResultEnter; | |||
139 | } | |||
140 | ||||
141 | return FileSystem::eEnumerateDirectoryResultNext; | |||
142 | } | |||
143 | ||||
144 | void PluginManager::Initialize() { | |||
145 | const bool find_directories = true; | |||
146 | const bool find_files = true; | |||
147 | const bool find_other = true; | |||
148 | char dir_path[PATH_MAX4096]; | |||
149 | if (FileSpec dir_spec = HostInfo::GetSystemPluginDir()) { | |||
150 | if (FileSystem::Instance().Exists(dir_spec) && | |||
151 | dir_spec.GetPath(dir_path, sizeof(dir_path))) { | |||
152 | FileSystem::Instance().EnumerateDirectory(dir_path, find_directories, | |||
153 | find_files, find_other, | |||
154 | LoadPluginCallback, nullptr); | |||
155 | } | |||
156 | } | |||
157 | ||||
158 | if (FileSpec dir_spec = HostInfo::GetUserPluginDir()) { | |||
159 | if (FileSystem::Instance().Exists(dir_spec) && | |||
160 | dir_spec.GetPath(dir_path, sizeof(dir_path))) { | |||
161 | FileSystem::Instance().EnumerateDirectory(dir_path, find_directories, | |||
162 | find_files, find_other, | |||
163 | LoadPluginCallback, nullptr); | |||
164 | } | |||
165 | } | |||
166 | } | |||
167 | ||||
168 | void PluginManager::Terminate() { | |||
169 | std::lock_guard<std::recursive_mutex> guard(GetPluginMapMutex()); | |||
170 | PluginTerminateMap &plugin_map = GetPluginMap(); | |||
171 | ||||
172 | PluginTerminateMap::const_iterator pos, end = plugin_map.end(); | |||
173 | for (pos = plugin_map.begin(); pos != end; ++pos) { | |||
174 | // Call the plug-in "void LLDBPluginTerminate (void)" function if there is | |||
175 | // one (if the symbol was not nullptr). | |||
176 | if (pos->second.library.isValid()) { | |||
177 | if (pos->second.plugin_term_callback) | |||
178 | pos->second.plugin_term_callback(); | |||
179 | } | |||
180 | } | |||
181 | plugin_map.clear(); | |||
182 | } | |||
183 | ||||
184 | template <typename Callback> struct PluginInstance { | |||
185 | typedef Callback CallbackType; | |||
186 | ||||
187 | PluginInstance() = default; | |||
188 | PluginInstance(llvm::StringRef name, llvm::StringRef description, | |||
189 | Callback create_callback, | |||
190 | DebuggerInitializeCallback debugger_init_callback = nullptr) | |||
191 | : name(name), description(description), create_callback(create_callback), | |||
192 | debugger_init_callback(debugger_init_callback) {} | |||
193 | ||||
194 | llvm::StringRef name; | |||
195 | llvm::StringRef description; | |||
196 | Callback create_callback; | |||
197 | DebuggerInitializeCallback debugger_init_callback; | |||
198 | }; | |||
199 | ||||
200 | template <typename Instance> class PluginInstances { | |||
201 | public: | |||
202 | template <typename... Args> | |||
203 | bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, | |||
204 | typename Instance::CallbackType callback, | |||
205 | Args &&...args) { | |||
206 | if (!callback) | |||
207 | return false; | |||
208 | assert(!name.empty())(static_cast <bool> (!name.empty()) ? void (0) : __assert_fail ("!name.empty()", "lldb/source/Core/PluginManager.cpp", 208, __extension__ __PRETTY_FUNCTION__)); | |||
209 | Instance instance = | |||
210 | Instance(name, description, callback, std::forward<Args>(args)...); | |||
211 | m_instances.push_back(instance); | |||
212 | return false; | |||
213 | } | |||
214 | ||||
215 | bool UnregisterPlugin(typename Instance::CallbackType callback) { | |||
216 | if (!callback) | |||
217 | return false; | |||
218 | auto pos = m_instances.begin(); | |||
219 | auto end = m_instances.end(); | |||
220 | for (; pos != end; ++pos) { | |||
221 | if (pos->create_callback == callback) { | |||
222 | m_instances.erase(pos); | |||
223 | return true; | |||
224 | } | |||
225 | } | |||
226 | return false; | |||
227 | } | |||
228 | ||||
229 | typename Instance::CallbackType GetCallbackAtIndex(uint32_t idx) { | |||
230 | if (Instance *instance = GetInstanceAtIndex(idx)) | |||
231 | return instance->create_callback; | |||
232 | return nullptr; | |||
233 | } | |||
234 | ||||
235 | llvm::StringRef GetDescriptionAtIndex(uint32_t idx) { | |||
236 | if (Instance *instance = GetInstanceAtIndex(idx)) | |||
237 | return instance->description; | |||
238 | return ""; | |||
239 | } | |||
240 | ||||
241 | llvm::StringRef GetNameAtIndex(uint32_t idx) { | |||
242 | if (Instance *instance = GetInstanceAtIndex(idx)) | |||
243 | return instance->name; | |||
244 | return ""; | |||
245 | } | |||
246 | ||||
247 | typename Instance::CallbackType GetCallbackForName(llvm::StringRef name) { | |||
248 | if (name.empty()) | |||
249 | return nullptr; | |||
250 | for (auto &instance : m_instances) { | |||
251 | if (name == instance.name) | |||
252 | return instance.create_callback; | |||
253 | } | |||
254 | return nullptr; | |||
255 | } | |||
256 | ||||
257 | void PerformDebuggerCallback(Debugger &debugger) { | |||
258 | for (auto &instance : m_instances) { | |||
259 | if (instance.debugger_init_callback) | |||
260 | instance.debugger_init_callback(debugger); | |||
261 | } | |||
262 | } | |||
263 | ||||
264 | const std::vector<Instance> &GetInstances() const { return m_instances; } | |||
265 | std::vector<Instance> &GetInstances() { return m_instances; } | |||
266 | ||||
267 | Instance *GetInstanceAtIndex(uint32_t idx) { | |||
268 | if (idx < m_instances.size()) | |||
269 | return &m_instances[idx]; | |||
270 | return nullptr; | |||
271 | } | |||
272 | ||||
273 | private: | |||
274 | std::vector<Instance> m_instances; | |||
275 | }; | |||
276 | ||||
277 | #pragma mark ABI | |||
278 | ||||
279 | typedef PluginInstance<ABICreateInstance> ABIInstance; | |||
280 | typedef PluginInstances<ABIInstance> ABIInstances; | |||
281 | ||||
282 | static ABIInstances &GetABIInstances() { | |||
283 | static ABIInstances g_instances; | |||
284 | return g_instances; | |||
285 | } | |||
286 | ||||
287 | bool PluginManager::RegisterPlugin(llvm::StringRef name, | |||
288 | llvm::StringRef description, | |||
289 | ABICreateInstance create_callback) { | |||
290 | return GetABIInstances().RegisterPlugin(name, description, create_callback); | |||
291 | } | |||
292 | ||||
293 | bool PluginManager::UnregisterPlugin(ABICreateInstance create_callback) { | |||
294 | return GetABIInstances().UnregisterPlugin(create_callback); | |||
295 | } | |||
296 | ||||
297 | ABICreateInstance PluginManager::GetABICreateCallbackAtIndex(uint32_t idx) { | |||
298 | return GetABIInstances().GetCallbackAtIndex(idx); | |||
299 | } | |||
300 | ||||
301 | #pragma mark Architecture | |||
302 | ||||
303 | typedef PluginInstance<ArchitectureCreateInstance> ArchitectureInstance; | |||
304 | typedef std::vector<ArchitectureInstance> ArchitectureInstances; | |||
305 | ||||
306 | static ArchitectureInstances &GetArchitectureInstances() { | |||
307 | static ArchitectureInstances g_instances; | |||
308 | return g_instances; | |||
309 | } | |||
310 | ||||
311 | void PluginManager::RegisterPlugin(llvm::StringRef name, | |||
312 | llvm::StringRef description, | |||
313 | ArchitectureCreateInstance create_callback) { | |||
314 | GetArchitectureInstances().push_back({name, description, create_callback}); | |||
315 | } | |||
316 | ||||
317 | void PluginManager::UnregisterPlugin( | |||
318 | ArchitectureCreateInstance create_callback) { | |||
319 | auto &instances = GetArchitectureInstances(); | |||
320 | ||||
321 | for (auto pos = instances.begin(), end = instances.end(); pos != end; ++pos) { | |||
322 | if (pos->create_callback == create_callback) { | |||
323 | instances.erase(pos); | |||
324 | return; | |||
325 | } | |||
326 | } | |||
327 | llvm_unreachable("Plugin not found")::llvm::llvm_unreachable_internal("Plugin not found", "lldb/source/Core/PluginManager.cpp" , 327); | |||
328 | } | |||
329 | ||||
330 | std::unique_ptr<Architecture> | |||
331 | PluginManager::CreateArchitectureInstance(const ArchSpec &arch) { | |||
332 | for (const auto &instances : GetArchitectureInstances()) { | |||
333 | if (auto plugin_up = instances.create_callback(arch)) | |||
334 | return plugin_up; | |||
335 | } | |||
336 | return nullptr; | |||
337 | } | |||
338 | ||||
339 | #pragma mark Disassembler | |||
340 | ||||
341 | typedef PluginInstance<DisassemblerCreateInstance> DisassemblerInstance; | |||
342 | typedef PluginInstances<DisassemblerInstance> DisassemblerInstances; | |||
343 | ||||
344 | static DisassemblerInstances &GetDisassemblerInstances() { | |||
345 | static DisassemblerInstances g_instances; | |||
346 | return g_instances; | |||
347 | } | |||
348 | ||||
349 | bool PluginManager::RegisterPlugin(llvm::StringRef name, | |||
350 | llvm::StringRef description, | |||
351 | DisassemblerCreateInstance create_callback) { | |||
352 | return GetDisassemblerInstances().RegisterPlugin(name, description, | |||
353 | create_callback); | |||
354 | } | |||
355 | ||||
356 | bool PluginManager::UnregisterPlugin( | |||
357 | DisassemblerCreateInstance create_callback) { | |||
358 | return GetDisassemblerInstances().UnregisterPlugin(create_callback); | |||
359 | } | |||
360 | ||||
361 | DisassemblerCreateInstance | |||
362 | PluginManager::GetDisassemblerCreateCallbackAtIndex(uint32_t idx) { | |||
363 | return GetDisassemblerInstances().GetCallbackAtIndex(idx); | |||
364 | } | |||
365 | ||||
366 | DisassemblerCreateInstance | |||
367 | PluginManager::GetDisassemblerCreateCallbackForPluginName( | |||
368 | llvm::StringRef name) { | |||
369 | return GetDisassemblerInstances().GetCallbackForName(name); | |||
370 | } | |||
371 | ||||
372 | #pragma mark DynamicLoader | |||
373 | ||||
374 | typedef PluginInstance<DynamicLoaderCreateInstance> DynamicLoaderInstance; | |||
375 | typedef PluginInstances<DynamicLoaderInstance> DynamicLoaderInstances; | |||
376 | ||||
377 | static DynamicLoaderInstances &GetDynamicLoaderInstances() { | |||
378 | static DynamicLoaderInstances g_instances; | |||
379 | return g_instances; | |||
380 | } | |||
381 | ||||
382 | bool PluginManager::RegisterPlugin( | |||
383 | llvm::StringRef name, llvm::StringRef description, | |||
384 | DynamicLoaderCreateInstance create_callback, | |||
385 | DebuggerInitializeCallback debugger_init_callback) { | |||
386 | return GetDynamicLoaderInstances().RegisterPlugin( | |||
387 | name, description, create_callback, debugger_init_callback); | |||
388 | } | |||
389 | ||||
390 | bool PluginManager::UnregisterPlugin( | |||
391 | DynamicLoaderCreateInstance create_callback) { | |||
392 | return GetDynamicLoaderInstances().UnregisterPlugin(create_callback); | |||
393 | } | |||
394 | ||||
395 | DynamicLoaderCreateInstance | |||
396 | PluginManager::GetDynamicLoaderCreateCallbackAtIndex(uint32_t idx) { | |||
397 | return GetDynamicLoaderInstances().GetCallbackAtIndex(idx); | |||
398 | } | |||
399 | ||||
400 | DynamicLoaderCreateInstance | |||
401 | PluginManager::GetDynamicLoaderCreateCallbackForPluginName( | |||
402 | llvm::StringRef name) { | |||
403 | return GetDynamicLoaderInstances().GetCallbackForName(name); | |||
404 | } | |||
405 | ||||
406 | #pragma mark JITLoader | |||
407 | ||||
408 | typedef PluginInstance<JITLoaderCreateInstance> JITLoaderInstance; | |||
409 | typedef PluginInstances<JITLoaderInstance> JITLoaderInstances; | |||
410 | ||||
411 | static JITLoaderInstances &GetJITLoaderInstances() { | |||
412 | static JITLoaderInstances g_instances; | |||
413 | return g_instances; | |||
414 | } | |||
415 | ||||
416 | bool PluginManager::RegisterPlugin( | |||
417 | llvm::StringRef name, llvm::StringRef description, | |||
418 | JITLoaderCreateInstance create_callback, | |||
419 | DebuggerInitializeCallback debugger_init_callback) { | |||
420 | return GetJITLoaderInstances().RegisterPlugin( | |||
421 | name, description, create_callback, debugger_init_callback); | |||
422 | } | |||
423 | ||||
424 | bool PluginManager::UnregisterPlugin(JITLoaderCreateInstance create_callback) { | |||
425 | return GetJITLoaderInstances().UnregisterPlugin(create_callback); | |||
426 | } | |||
427 | ||||
428 | JITLoaderCreateInstance | |||
429 | PluginManager::GetJITLoaderCreateCallbackAtIndex(uint32_t idx) { | |||
430 | return GetJITLoaderInstances().GetCallbackAtIndex(idx); | |||
431 | } | |||
432 | ||||
433 | #pragma mark EmulateInstruction | |||
434 | ||||
435 | typedef PluginInstance<EmulateInstructionCreateInstance> | |||
436 | EmulateInstructionInstance; | |||
437 | typedef PluginInstances<EmulateInstructionInstance> EmulateInstructionInstances; | |||
438 | ||||
439 | static EmulateInstructionInstances &GetEmulateInstructionInstances() { | |||
440 | static EmulateInstructionInstances g_instances; | |||
441 | return g_instances; | |||
442 | } | |||
443 | ||||
444 | bool PluginManager::RegisterPlugin( | |||
445 | llvm::StringRef name, llvm::StringRef description, | |||
446 | EmulateInstructionCreateInstance create_callback) { | |||
447 | return GetEmulateInstructionInstances().RegisterPlugin(name, description, | |||
448 | create_callback); | |||
449 | } | |||
450 | ||||
451 | bool PluginManager::UnregisterPlugin( | |||
452 | EmulateInstructionCreateInstance create_callback) { | |||
453 | return GetEmulateInstructionInstances().UnregisterPlugin(create_callback); | |||
454 | } | |||
455 | ||||
456 | EmulateInstructionCreateInstance | |||
457 | PluginManager::GetEmulateInstructionCreateCallbackAtIndex(uint32_t idx) { | |||
458 | return GetEmulateInstructionInstances().GetCallbackAtIndex(idx); | |||
459 | } | |||
460 | ||||
461 | EmulateInstructionCreateInstance | |||
462 | PluginManager::GetEmulateInstructionCreateCallbackForPluginName( | |||
463 | llvm::StringRef name) { | |||
464 | return GetEmulateInstructionInstances().GetCallbackForName(name); | |||
465 | } | |||
466 | ||||
467 | #pragma mark OperatingSystem | |||
468 | ||||
469 | typedef PluginInstance<OperatingSystemCreateInstance> OperatingSystemInstance; | |||
470 | typedef PluginInstances<OperatingSystemInstance> OperatingSystemInstances; | |||
471 | ||||
472 | static OperatingSystemInstances &GetOperatingSystemInstances() { | |||
473 | static OperatingSystemInstances g_instances; | |||
474 | return g_instances; | |||
475 | } | |||
476 | ||||
477 | bool PluginManager::RegisterPlugin( | |||
478 | llvm::StringRef name, llvm::StringRef description, | |||
479 | OperatingSystemCreateInstance create_callback, | |||
480 | DebuggerInitializeCallback debugger_init_callback) { | |||
481 | return GetOperatingSystemInstances().RegisterPlugin( | |||
482 | name, description, create_callback, debugger_init_callback); | |||
483 | } | |||
484 | ||||
485 | bool PluginManager::UnregisterPlugin( | |||
486 | OperatingSystemCreateInstance create_callback) { | |||
487 | return GetOperatingSystemInstances().UnregisterPlugin(create_callback); | |||
488 | } | |||
489 | ||||
490 | OperatingSystemCreateInstance | |||
491 | PluginManager::GetOperatingSystemCreateCallbackAtIndex(uint32_t idx) { | |||
492 | return GetOperatingSystemInstances().GetCallbackAtIndex(idx); | |||
493 | } | |||
494 | ||||
495 | OperatingSystemCreateInstance | |||
496 | PluginManager::GetOperatingSystemCreateCallbackForPluginName( | |||
497 | llvm::StringRef name) { | |||
498 | return GetOperatingSystemInstances().GetCallbackForName(name); | |||
499 | } | |||
500 | ||||
501 | #pragma mark Language | |||
502 | ||||
503 | typedef PluginInstance<LanguageCreateInstance> LanguageInstance; | |||
504 | typedef PluginInstances<LanguageInstance> LanguageInstances; | |||
505 | ||||
506 | static LanguageInstances &GetLanguageInstances() { | |||
507 | static LanguageInstances g_instances; | |||
508 | return g_instances; | |||
509 | } | |||
510 | ||||
511 | bool PluginManager::RegisterPlugin(llvm::StringRef name, | |||
512 | llvm::StringRef description, | |||
513 | LanguageCreateInstance create_callback) { | |||
514 | return GetLanguageInstances().RegisterPlugin(name, description, | |||
515 | create_callback); | |||
516 | } | |||
517 | ||||
518 | bool PluginManager::UnregisterPlugin(LanguageCreateInstance create_callback) { | |||
519 | return GetLanguageInstances().UnregisterPlugin(create_callback); | |||
520 | } | |||
521 | ||||
522 | LanguageCreateInstance | |||
523 | PluginManager::GetLanguageCreateCallbackAtIndex(uint32_t idx) { | |||
524 | return GetLanguageInstances().GetCallbackAtIndex(idx); | |||
525 | } | |||
526 | ||||
527 | #pragma mark LanguageRuntime | |||
528 | ||||
529 | struct LanguageRuntimeInstance | |||
530 | : public PluginInstance<LanguageRuntimeCreateInstance> { | |||
531 | LanguageRuntimeInstance( | |||
532 | llvm::StringRef name, llvm::StringRef description, | |||
533 | CallbackType create_callback, | |||
534 | DebuggerInitializeCallback debugger_init_callback, | |||
535 | LanguageRuntimeGetCommandObject command_callback, | |||
536 | LanguageRuntimeGetExceptionPrecondition precondition_callback) | |||
537 | : PluginInstance<LanguageRuntimeCreateInstance>( | |||
538 | name, description, create_callback, debugger_init_callback), | |||
539 | command_callback(command_callback), | |||
540 | precondition_callback(precondition_callback) {} | |||
541 | ||||
542 | LanguageRuntimeGetCommandObject command_callback; | |||
543 | LanguageRuntimeGetExceptionPrecondition precondition_callback; | |||
544 | }; | |||
545 | ||||
546 | typedef PluginInstances<LanguageRuntimeInstance> LanguageRuntimeInstances; | |||
547 | ||||
548 | static LanguageRuntimeInstances &GetLanguageRuntimeInstances() { | |||
549 | static LanguageRuntimeInstances g_instances; | |||
550 | return g_instances; | |||
551 | } | |||
552 | ||||
553 | bool PluginManager::RegisterPlugin( | |||
554 | llvm::StringRef name, llvm::StringRef description, | |||
555 | LanguageRuntimeCreateInstance create_callback, | |||
556 | LanguageRuntimeGetCommandObject command_callback, | |||
557 | LanguageRuntimeGetExceptionPrecondition precondition_callback) { | |||
558 | return GetLanguageRuntimeInstances().RegisterPlugin( | |||
559 | name, description, create_callback, nullptr, command_callback, | |||
560 | precondition_callback); | |||
561 | } | |||
562 | ||||
563 | bool PluginManager::UnregisterPlugin( | |||
564 | LanguageRuntimeCreateInstance create_callback) { | |||
565 | return GetLanguageRuntimeInstances().UnregisterPlugin(create_callback); | |||
566 | } | |||
567 | ||||
568 | LanguageRuntimeCreateInstance | |||
569 | PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(uint32_t idx) { | |||
570 | return GetLanguageRuntimeInstances().GetCallbackAtIndex(idx); | |||
571 | } | |||
572 | ||||
573 | LanguageRuntimeGetCommandObject | |||
574 | PluginManager::GetLanguageRuntimeGetCommandObjectAtIndex(uint32_t idx) { | |||
575 | const auto &instances = GetLanguageRuntimeInstances().GetInstances(); | |||
576 | if (idx < instances.size()) | |||
577 | return instances[idx].command_callback; | |||
578 | return nullptr; | |||
579 | } | |||
580 | ||||
581 | LanguageRuntimeGetExceptionPrecondition | |||
582 | PluginManager::GetLanguageRuntimeGetExceptionPreconditionAtIndex(uint32_t idx) { | |||
583 | const auto &instances = GetLanguageRuntimeInstances().GetInstances(); | |||
584 | if (idx < instances.size()) | |||
585 | return instances[idx].precondition_callback; | |||
586 | return nullptr; | |||
587 | } | |||
588 | ||||
589 | #pragma mark SystemRuntime | |||
590 | ||||
591 | typedef PluginInstance<SystemRuntimeCreateInstance> SystemRuntimeInstance; | |||
592 | typedef PluginInstances<SystemRuntimeInstance> SystemRuntimeInstances; | |||
593 | ||||
594 | static SystemRuntimeInstances &GetSystemRuntimeInstances() { | |||
595 | static SystemRuntimeInstances g_instances; | |||
596 | return g_instances; | |||
597 | } | |||
598 | ||||
599 | bool PluginManager::RegisterPlugin( | |||
600 | llvm::StringRef name, llvm::StringRef description, | |||
601 | SystemRuntimeCreateInstance create_callback) { | |||
602 | return GetSystemRuntimeInstances().RegisterPlugin(name, description, | |||
603 | create_callback); | |||
604 | } | |||
605 | ||||
606 | bool PluginManager::UnregisterPlugin( | |||
607 | SystemRuntimeCreateInstance create_callback) { | |||
608 | return GetSystemRuntimeInstances().UnregisterPlugin(create_callback); | |||
609 | } | |||
610 | ||||
611 | SystemRuntimeCreateInstance | |||
612 | PluginManager::GetSystemRuntimeCreateCallbackAtIndex(uint32_t idx) { | |||
613 | return GetSystemRuntimeInstances().GetCallbackAtIndex(idx); | |||
614 | } | |||
615 | ||||
616 | #pragma mark ObjectFile | |||
617 | ||||
618 | struct ObjectFileInstance : public PluginInstance<ObjectFileCreateInstance> { | |||
619 | ObjectFileInstance( | |||
620 | llvm::StringRef name, llvm::StringRef description, | |||
621 | CallbackType create_callback, | |||
622 | ObjectFileCreateMemoryInstance create_memory_callback, | |||
623 | ObjectFileGetModuleSpecifications get_module_specifications, | |||
624 | ObjectFileSaveCore save_core, | |||
625 | DebuggerInitializeCallback debugger_init_callback) | |||
626 | : PluginInstance<ObjectFileCreateInstance>( | |||
627 | name, description, create_callback, debugger_init_callback), | |||
628 | create_memory_callback(create_memory_callback), | |||
629 | get_module_specifications(get_module_specifications), | |||
630 | save_core(save_core) {} | |||
631 | ||||
632 | ObjectFileCreateMemoryInstance create_memory_callback; | |||
633 | ObjectFileGetModuleSpecifications get_module_specifications; | |||
634 | ObjectFileSaveCore save_core; | |||
635 | }; | |||
636 | typedef PluginInstances<ObjectFileInstance> ObjectFileInstances; | |||
637 | ||||
638 | static ObjectFileInstances &GetObjectFileInstances() { | |||
639 | static ObjectFileInstances g_instances; | |||
640 | return g_instances; | |||
641 | } | |||
642 | ||||
643 | bool PluginManager::RegisterPlugin( | |||
644 | llvm::StringRef name, llvm::StringRef description, | |||
645 | ObjectFileCreateInstance create_callback, | |||
646 | ObjectFileCreateMemoryInstance create_memory_callback, | |||
647 | ObjectFileGetModuleSpecifications get_module_specifications, | |||
648 | ObjectFileSaveCore save_core, | |||
649 | DebuggerInitializeCallback debugger_init_callback) { | |||
650 | return GetObjectFileInstances().RegisterPlugin( | |||
651 | name, description, create_callback, create_memory_callback, | |||
652 | get_module_specifications, save_core, debugger_init_callback); | |||
653 | } | |||
654 | ||||
655 | bool PluginManager::UnregisterPlugin(ObjectFileCreateInstance create_callback) { | |||
656 | return GetObjectFileInstances().UnregisterPlugin(create_callback); | |||
657 | } | |||
658 | ||||
659 | ObjectFileCreateInstance | |||
660 | PluginManager::GetObjectFileCreateCallbackAtIndex(uint32_t idx) { | |||
661 | return GetObjectFileInstances().GetCallbackAtIndex(idx); | |||
662 | } | |||
663 | ||||
664 | ObjectFileCreateMemoryInstance | |||
665 | PluginManager::GetObjectFileCreateMemoryCallbackAtIndex(uint32_t idx) { | |||
666 | const auto &instances = GetObjectFileInstances().GetInstances(); | |||
667 | if (idx < instances.size()) | |||
668 | return instances[idx].create_memory_callback; | |||
669 | return nullptr; | |||
670 | } | |||
671 | ||||
672 | ObjectFileGetModuleSpecifications | |||
673 | PluginManager::GetObjectFileGetModuleSpecificationsCallbackAtIndex( | |||
674 | uint32_t idx) { | |||
675 | const auto &instances = GetObjectFileInstances().GetInstances(); | |||
676 | if (idx < instances.size()) | |||
677 | return instances[idx].get_module_specifications; | |||
678 | return nullptr; | |||
679 | } | |||
680 | ||||
681 | ObjectFileCreateMemoryInstance | |||
682 | PluginManager::GetObjectFileCreateMemoryCallbackForPluginName( | |||
683 | llvm::StringRef name) { | |||
684 | const auto &instances = GetObjectFileInstances().GetInstances(); | |||
685 | for (auto &instance : instances) { | |||
686 | if (instance.name == name) | |||
687 | return instance.create_memory_callback; | |||
688 | } | |||
689 | return nullptr; | |||
690 | } | |||
691 | ||||
692 | Status PluginManager::SaveCore(const lldb::ProcessSP &process_sp, | |||
693 | const FileSpec &outfile, | |||
694 | lldb::SaveCoreStyle &core_style, | |||
695 | llvm::StringRef plugin_name) { | |||
696 | if (plugin_name.empty()) { | |||
697 | // Try saving core directly from the process plugin first. | |||
698 | llvm::Expected<bool> ret = process_sp->SaveCore(outfile.GetPath()); | |||
699 | if (!ret) | |||
700 | return Status(ret.takeError()); | |||
701 | if (ret.get()) | |||
702 | return Status(); | |||
703 | } | |||
704 | ||||
705 | // Fall back to object plugins. | |||
706 | Status error; | |||
707 | auto &instances = GetObjectFileInstances().GetInstances(); | |||
708 | for (auto &instance : instances) { | |||
709 | if (plugin_name.empty() || instance.name == plugin_name) { | |||
710 | if (instance.save_core && | |||
711 | instance.save_core(process_sp, outfile, core_style, error)) | |||
712 | return error; | |||
713 | } | |||
714 | } | |||
715 | error.SetErrorString( | |||
716 | "no ObjectFile plugins were able to save a core for this process"); | |||
717 | return error; | |||
718 | } | |||
719 | ||||
720 | #pragma mark ObjectContainer | |||
721 | ||||
722 | struct ObjectContainerInstance | |||
723 | : public PluginInstance<ObjectContainerCreateInstance> { | |||
724 | ObjectContainerInstance( | |||
725 | llvm::StringRef name, llvm::StringRef description, | |||
726 | CallbackType create_callback, | |||
727 | ObjectContainerCreateMemoryInstance create_memory_callback, | |||
728 | ObjectFileGetModuleSpecifications get_module_specifications) | |||
729 | : PluginInstance<ObjectContainerCreateInstance>(name, description, | |||
730 | create_callback), | |||
731 | create_memory_callback(create_memory_callback), | |||
732 | get_module_specifications(get_module_specifications) {} | |||
733 | ||||
734 | ObjectContainerCreateMemoryInstance create_memory_callback; | |||
735 | ObjectFileGetModuleSpecifications get_module_specifications; | |||
736 | }; | |||
737 | typedef PluginInstances<ObjectContainerInstance> ObjectContainerInstances; | |||
738 | ||||
739 | static ObjectContainerInstances &GetObjectContainerInstances() { | |||
740 | static ObjectContainerInstances g_instances; | |||
741 | return g_instances; | |||
742 | } | |||
743 | ||||
744 | bool PluginManager::RegisterPlugin( | |||
745 | llvm::StringRef name, llvm::StringRef description, | |||
746 | ObjectContainerCreateInstance create_callback, | |||
747 | ObjectFileGetModuleSpecifications get_module_specifications, | |||
748 | ObjectContainerCreateMemoryInstance create_memory_callback) { | |||
749 | return GetObjectContainerInstances().RegisterPlugin( | |||
750 | name, description, create_callback, create_memory_callback, | |||
751 | get_module_specifications); | |||
752 | } | |||
753 | ||||
754 | bool PluginManager::UnregisterPlugin( | |||
755 | ObjectContainerCreateInstance create_callback) { | |||
756 | return GetObjectContainerInstances().UnregisterPlugin(create_callback); | |||
757 | } | |||
758 | ||||
759 | ObjectContainerCreateInstance | |||
760 | PluginManager::GetObjectContainerCreateCallbackAtIndex(uint32_t idx) { | |||
761 | return GetObjectContainerInstances().GetCallbackAtIndex(idx); | |||
762 | } | |||
763 | ||||
764 | ObjectContainerCreateMemoryInstance | |||
765 | PluginManager::GetObjectContainerCreateMemoryCallbackAtIndex(uint32_t idx) { | |||
766 | const auto &instances = GetObjectContainerInstances().GetInstances(); | |||
767 | if (idx < instances.size()) | |||
768 | return instances[idx].create_memory_callback; | |||
769 | return nullptr; | |||
770 | } | |||
771 | ||||
772 | ObjectFileGetModuleSpecifications | |||
773 | PluginManager::GetObjectContainerGetModuleSpecificationsCallbackAtIndex( | |||
774 | uint32_t idx) { | |||
775 | const auto &instances = GetObjectContainerInstances().GetInstances(); | |||
776 | if (idx < instances.size()) | |||
777 | return instances[idx].get_module_specifications; | |||
778 | return nullptr; | |||
779 | } | |||
780 | ||||
781 | #pragma mark Platform | |||
782 | ||||
783 | typedef PluginInstance<PlatformCreateInstance> PlatformInstance; | |||
784 | typedef PluginInstances<PlatformInstance> PlatformInstances; | |||
785 | ||||
786 | static PlatformInstances &GetPlatformInstances() { | |||
787 | static PlatformInstances g_platform_instances; | |||
788 | return g_platform_instances; | |||
789 | } | |||
790 | ||||
791 | bool PluginManager::RegisterPlugin( | |||
792 | llvm::StringRef name, llvm::StringRef description, | |||
793 | PlatformCreateInstance create_callback, | |||
794 | DebuggerInitializeCallback debugger_init_callback) { | |||
795 | return GetPlatformInstances().RegisterPlugin( | |||
796 | name, description, create_callback, debugger_init_callback); | |||
797 | } | |||
798 | ||||
799 | bool PluginManager::UnregisterPlugin(PlatformCreateInstance create_callback) { | |||
800 | return GetPlatformInstances().UnregisterPlugin(create_callback); | |||
801 | } | |||
802 | ||||
803 | llvm::StringRef PluginManager::GetPlatformPluginNameAtIndex(uint32_t idx) { | |||
804 | return GetPlatformInstances().GetNameAtIndex(idx); | |||
805 | } | |||
806 | ||||
807 | llvm::StringRef | |||
808 | PluginManager::GetPlatformPluginDescriptionAtIndex(uint32_t idx) { | |||
809 | return GetPlatformInstances().GetDescriptionAtIndex(idx); | |||
810 | } | |||
811 | ||||
812 | PlatformCreateInstance | |||
813 | PluginManager::GetPlatformCreateCallbackAtIndex(uint32_t idx) { | |||
814 | return GetPlatformInstances().GetCallbackAtIndex(idx); | |||
815 | } | |||
816 | ||||
817 | PlatformCreateInstance | |||
818 | PluginManager::GetPlatformCreateCallbackForPluginName(llvm::StringRef name) { | |||
819 | return GetPlatformInstances().GetCallbackForName(name); | |||
820 | } | |||
821 | ||||
822 | void PluginManager::AutoCompletePlatformName(llvm::StringRef name, | |||
823 | CompletionRequest &request) { | |||
824 | for (const auto &instance : GetPlatformInstances().GetInstances()) { | |||
825 | if (instance.name.startswith(name)) | |||
826 | request.AddCompletion(instance.name); | |||
827 | } | |||
828 | } | |||
829 | ||||
830 | #pragma mark Process | |||
831 | ||||
832 | typedef PluginInstance<ProcessCreateInstance> ProcessInstance; | |||
833 | typedef PluginInstances<ProcessInstance> ProcessInstances; | |||
834 | ||||
835 | static ProcessInstances &GetProcessInstances() { | |||
836 | static ProcessInstances g_instances; | |||
837 | return g_instances; | |||
838 | } | |||
839 | ||||
840 | bool PluginManager::RegisterPlugin( | |||
841 | llvm::StringRef name, llvm::StringRef description, | |||
842 | ProcessCreateInstance create_callback, | |||
843 | DebuggerInitializeCallback debugger_init_callback) { | |||
844 | return GetProcessInstances().RegisterPlugin( | |||
845 | name, description, create_callback, debugger_init_callback); | |||
846 | } | |||
847 | ||||
848 | bool PluginManager::UnregisterPlugin(ProcessCreateInstance create_callback) { | |||
849 | return GetProcessInstances().UnregisterPlugin(create_callback); | |||
850 | } | |||
851 | ||||
852 | llvm::StringRef PluginManager::GetProcessPluginNameAtIndex(uint32_t idx) { | |||
853 | return GetProcessInstances().GetNameAtIndex(idx); | |||
854 | } | |||
855 | ||||
856 | llvm::StringRef PluginManager::GetProcessPluginDescriptionAtIndex(uint32_t idx) { | |||
857 | return GetProcessInstances().GetDescriptionAtIndex(idx); | |||
858 | } | |||
859 | ||||
860 | ProcessCreateInstance | |||
861 | PluginManager::GetProcessCreateCallbackAtIndex(uint32_t idx) { | |||
862 | return GetProcessInstances().GetCallbackAtIndex(idx); | |||
863 | } | |||
864 | ||||
865 | ProcessCreateInstance | |||
866 | PluginManager::GetProcessCreateCallbackForPluginName(llvm::StringRef name) { | |||
867 | return GetProcessInstances().GetCallbackForName(name); | |||
868 | } | |||
869 | ||||
870 | void PluginManager::AutoCompleteProcessName(llvm::StringRef name, | |||
871 | CompletionRequest &request) { | |||
872 | for (const auto &instance : GetProcessInstances().GetInstances()) { | |||
873 | if (instance.name.startswith(name)) | |||
874 | request.AddCompletion(instance.name, instance.description); | |||
875 | } | |||
876 | } | |||
877 | ||||
878 | #pragma mark RegisterTypeBuilder | |||
879 | ||||
880 | struct RegisterTypeBuilderInstance | |||
881 | : public PluginInstance<RegisterTypeBuilderCreateInstance> { | |||
882 | RegisterTypeBuilderInstance(llvm::StringRef name, llvm::StringRef description, | |||
883 | CallbackType create_callback) | |||
884 | : PluginInstance<RegisterTypeBuilderCreateInstance>(name, description, | |||
885 | create_callback) {} | |||
886 | }; | |||
887 | ||||
888 | typedef PluginInstances<RegisterTypeBuilderInstance> | |||
889 | RegisterTypeBuilderInstances; | |||
890 | ||||
891 | static RegisterTypeBuilderInstances &GetRegisterTypeBuilderInstances() { | |||
892 | static RegisterTypeBuilderInstances g_instances; | |||
893 | return g_instances; | |||
894 | } | |||
895 | ||||
896 | bool PluginManager::RegisterPlugin( | |||
897 | llvm::StringRef name, llvm::StringRef description, | |||
898 | RegisterTypeBuilderCreateInstance create_callback) { | |||
899 | return GetRegisterTypeBuilderInstances().RegisterPlugin(name, description, | |||
900 | create_callback); | |||
901 | } | |||
902 | ||||
903 | bool PluginManager::UnregisterPlugin( | |||
904 | RegisterTypeBuilderCreateInstance create_callback) { | |||
905 | return GetRegisterTypeBuilderInstances().UnregisterPlugin(create_callback); | |||
906 | } | |||
907 | ||||
908 | lldb::RegisterTypeBuilderSP | |||
909 | PluginManager::GetRegisterTypeBuilder(Target &target) { | |||
910 | const auto &instances = GetRegisterTypeBuilderInstances().GetInstances(); | |||
911 | // We assume that RegisterTypeBuilderClang is the only instance of this plugin | |||
912 | // type and is always present. | |||
913 | assert(instances.size())(static_cast <bool> (instances.size()) ? void (0) : __assert_fail ("instances.size()", "lldb/source/Core/PluginManager.cpp", 913 , __extension__ __PRETTY_FUNCTION__)); | |||
914 | return instances[0].create_callback(target); | |||
915 | } | |||
916 | ||||
917 | #pragma mark ScriptInterpreter | |||
918 | ||||
919 | struct ScriptInterpreterInstance | |||
920 | : public PluginInstance<ScriptInterpreterCreateInstance> { | |||
921 | ScriptInterpreterInstance(llvm::StringRef name, llvm::StringRef description, | |||
922 | CallbackType create_callback, | |||
923 | lldb::ScriptLanguage language) | |||
924 | : PluginInstance<ScriptInterpreterCreateInstance>(name, description, | |||
925 | create_callback), | |||
926 | language(language) {} | |||
927 | ||||
928 | lldb::ScriptLanguage language = lldb::eScriptLanguageNone; | |||
929 | }; | |||
930 | ||||
931 | typedef PluginInstances<ScriptInterpreterInstance> ScriptInterpreterInstances; | |||
932 | ||||
933 | static ScriptInterpreterInstances &GetScriptInterpreterInstances() { | |||
934 | static ScriptInterpreterInstances g_instances; | |||
935 | return g_instances; | |||
936 | } | |||
937 | ||||
938 | bool PluginManager::RegisterPlugin( | |||
939 | llvm::StringRef name, llvm::StringRef description, | |||
940 | lldb::ScriptLanguage script_language, | |||
941 | ScriptInterpreterCreateInstance create_callback) { | |||
942 | return GetScriptInterpreterInstances().RegisterPlugin( | |||
943 | name, description, create_callback, script_language); | |||
944 | } | |||
945 | ||||
946 | bool PluginManager::UnregisterPlugin( | |||
947 | ScriptInterpreterCreateInstance create_callback) { | |||
948 | return GetScriptInterpreterInstances().UnregisterPlugin(create_callback); | |||
949 | } | |||
950 | ||||
951 | ScriptInterpreterCreateInstance | |||
952 | PluginManager::GetScriptInterpreterCreateCallbackAtIndex(uint32_t idx) { | |||
953 | return GetScriptInterpreterInstances().GetCallbackAtIndex(idx); | |||
954 | } | |||
955 | ||||
956 | lldb::ScriptInterpreterSP | |||
957 | PluginManager::GetScriptInterpreterForLanguage(lldb::ScriptLanguage script_lang, | |||
958 | Debugger &debugger) { | |||
959 | const auto &instances = GetScriptInterpreterInstances().GetInstances(); | |||
960 | ScriptInterpreterCreateInstance none_instance = nullptr; | |||
961 | for (const auto &instance : instances) { | |||
962 | if (instance.language == lldb::eScriptLanguageNone) | |||
963 | none_instance = instance.create_callback; | |||
964 | ||||
965 | if (script_lang == instance.language) | |||
966 | return instance.create_callback(debugger); | |||
967 | } | |||
968 | ||||
969 | // If we didn't find one, return the ScriptInterpreter for the null language. | |||
970 | assert(none_instance != nullptr)(static_cast <bool> (none_instance != nullptr) ? void ( 0) : __assert_fail ("none_instance != nullptr", "lldb/source/Core/PluginManager.cpp" , 970, __extension__ __PRETTY_FUNCTION__)); | |||
971 | return none_instance(debugger); | |||
972 | } | |||
973 | ||||
974 | #pragma mark StructuredDataPlugin | |||
975 | ||||
976 | struct StructuredDataPluginInstance | |||
977 | : public PluginInstance<StructuredDataPluginCreateInstance> { | |||
978 | StructuredDataPluginInstance( | |||
979 | llvm::StringRef name, llvm::StringRef description, | |||
980 | CallbackType create_callback, | |||
981 | DebuggerInitializeCallback debugger_init_callback, | |||
982 | StructuredDataFilterLaunchInfo filter_callback) | |||
983 | : PluginInstance<StructuredDataPluginCreateInstance>( | |||
984 | name, description, create_callback, debugger_init_callback), | |||
985 | filter_callback(filter_callback) {} | |||
986 | ||||
987 | StructuredDataFilterLaunchInfo filter_callback = nullptr; | |||
988 | }; | |||
989 | ||||
990 | typedef PluginInstances<StructuredDataPluginInstance> | |||
991 | StructuredDataPluginInstances; | |||
992 | ||||
993 | static StructuredDataPluginInstances &GetStructuredDataPluginInstances() { | |||
994 | static StructuredDataPluginInstances g_instances; | |||
995 | return g_instances; | |||
996 | } | |||
997 | ||||
998 | bool PluginManager::RegisterPlugin( | |||
999 | llvm::StringRef name, llvm::StringRef description, | |||
1000 | StructuredDataPluginCreateInstance create_callback, | |||
1001 | DebuggerInitializeCallback debugger_init_callback, | |||
1002 | StructuredDataFilterLaunchInfo filter_callback) { | |||
1003 | return GetStructuredDataPluginInstances().RegisterPlugin( | |||
1004 | name, description, create_callback, debugger_init_callback, | |||
1005 | filter_callback); | |||
1006 | } | |||
1007 | ||||
1008 | bool PluginManager::UnregisterPlugin( | |||
1009 | StructuredDataPluginCreateInstance create_callback) { | |||
1010 | return GetStructuredDataPluginInstances().UnregisterPlugin(create_callback); | |||
1011 | } | |||
1012 | ||||
1013 | StructuredDataPluginCreateInstance | |||
1014 | PluginManager::GetStructuredDataPluginCreateCallbackAtIndex(uint32_t idx) { | |||
1015 | return GetStructuredDataPluginInstances().GetCallbackAtIndex(idx); | |||
1016 | } | |||
1017 | ||||
1018 | StructuredDataFilterLaunchInfo | |||
1019 | PluginManager::GetStructuredDataFilterCallbackAtIndex( | |||
1020 | uint32_t idx, bool &iteration_complete) { | |||
1021 | const auto &instances = GetStructuredDataPluginInstances().GetInstances(); | |||
1022 | if (idx < instances.size()) { | |||
1023 | iteration_complete = false; | |||
1024 | return instances[idx].filter_callback; | |||
1025 | } else { | |||
1026 | iteration_complete = true; | |||
1027 | } | |||
1028 | return nullptr; | |||
1029 | } | |||
1030 | ||||
1031 | #pragma mark SymbolFile | |||
1032 | ||||
1033 | typedef PluginInstance<SymbolFileCreateInstance> SymbolFileInstance; | |||
1034 | typedef PluginInstances<SymbolFileInstance> SymbolFileInstances; | |||
1035 | ||||
1036 | static SymbolFileInstances &GetSymbolFileInstances() { | |||
1037 | static SymbolFileInstances g_instances; | |||
1038 | return g_instances; | |||
1039 | } | |||
1040 | ||||
1041 | bool PluginManager::RegisterPlugin( | |||
1042 | llvm::StringRef name, llvm::StringRef description, | |||
1043 | SymbolFileCreateInstance create_callback, | |||
1044 | DebuggerInitializeCallback debugger_init_callback) { | |||
1045 | return GetSymbolFileInstances().RegisterPlugin( | |||
1046 | name, description, create_callback, debugger_init_callback); | |||
1047 | } | |||
1048 | ||||
1049 | bool PluginManager::UnregisterPlugin(SymbolFileCreateInstance create_callback) { | |||
1050 | return GetSymbolFileInstances().UnregisterPlugin(create_callback); | |||
1051 | } | |||
1052 | ||||
1053 | SymbolFileCreateInstance | |||
1054 | PluginManager::GetSymbolFileCreateCallbackAtIndex(uint32_t idx) { | |||
1055 | return GetSymbolFileInstances().GetCallbackAtIndex(idx); | |||
1056 | } | |||
1057 | ||||
1058 | #pragma mark SymbolVendor | |||
1059 | ||||
1060 | typedef PluginInstance<SymbolVendorCreateInstance> SymbolVendorInstance; | |||
1061 | typedef PluginInstances<SymbolVendorInstance> SymbolVendorInstances; | |||
1062 | ||||
1063 | static SymbolVendorInstances &GetSymbolVendorInstances() { | |||
1064 | static SymbolVendorInstances g_instances; | |||
1065 | return g_instances; | |||
1066 | } | |||
1067 | ||||
1068 | bool PluginManager::RegisterPlugin(llvm::StringRef name, | |||
1069 | llvm::StringRef description, | |||
1070 | SymbolVendorCreateInstance create_callback) { | |||
1071 | return GetSymbolVendorInstances().RegisterPlugin(name, description, | |||
1072 | create_callback); | |||
1073 | } | |||
1074 | ||||
1075 | bool PluginManager::UnregisterPlugin( | |||
1076 | SymbolVendorCreateInstance create_callback) { | |||
1077 | return GetSymbolVendorInstances().UnregisterPlugin(create_callback); | |||
1078 | } | |||
1079 | ||||
1080 | SymbolVendorCreateInstance | |||
1081 | PluginManager::GetSymbolVendorCreateCallbackAtIndex(uint32_t idx) { | |||
1082 | return GetSymbolVendorInstances().GetCallbackAtIndex(idx); | |||
1083 | } | |||
1084 | ||||
1085 | #pragma mark Trace | |||
1086 | ||||
1087 | struct TraceInstance | |||
1088 | : public PluginInstance<TraceCreateInstanceFromBundle> { | |||
1089 | TraceInstance( | |||
1090 | llvm::StringRef name, llvm::StringRef description, | |||
1091 | CallbackType create_callback_from_bundle, | |||
1092 | TraceCreateInstanceForLiveProcess create_callback_for_live_process, | |||
1093 | llvm::StringRef schema, DebuggerInitializeCallback debugger_init_callback) | |||
1094 | : PluginInstance<TraceCreateInstanceFromBundle>( | |||
1095 | name, description, create_callback_from_bundle, | |||
1096 | debugger_init_callback), | |||
1097 | schema(schema), | |||
1098 | create_callback_for_live_process(create_callback_for_live_process) {} | |||
1099 | ||||
1100 | llvm::StringRef schema; | |||
1101 | TraceCreateInstanceForLiveProcess create_callback_for_live_process; | |||
1102 | }; | |||
1103 | ||||
1104 | typedef PluginInstances<TraceInstance> TraceInstances; | |||
1105 | ||||
1106 | static TraceInstances &GetTracePluginInstances() { | |||
1107 | static TraceInstances g_instances; | |||
1108 | return g_instances; | |||
1109 | } | |||
1110 | ||||
1111 | bool PluginManager::RegisterPlugin( | |||
1112 | llvm::StringRef name, llvm::StringRef description, | |||
1113 | TraceCreateInstanceFromBundle create_callback_from_bundle, | |||
1114 | TraceCreateInstanceForLiveProcess create_callback_for_live_process, | |||
1115 | llvm::StringRef schema, DebuggerInitializeCallback debugger_init_callback) { | |||
1116 | return GetTracePluginInstances().RegisterPlugin( | |||
1117 | name, description, create_callback_from_bundle, | |||
1118 | create_callback_for_live_process, schema, debugger_init_callback); | |||
1119 | } | |||
1120 | ||||
1121 | bool PluginManager::UnregisterPlugin( | |||
1122 | TraceCreateInstanceFromBundle create_callback_from_bundle) { | |||
1123 | return GetTracePluginInstances().UnregisterPlugin( | |||
1124 | create_callback_from_bundle); | |||
1125 | } | |||
1126 | ||||
1127 | TraceCreateInstanceFromBundle | |||
1128 | PluginManager::GetTraceCreateCallback(llvm::StringRef plugin_name) { | |||
1129 | return GetTracePluginInstances().GetCallbackForName(plugin_name); | |||
1130 | } | |||
1131 | ||||
1132 | TraceCreateInstanceForLiveProcess | |||
1133 | PluginManager::GetTraceCreateCallbackForLiveProcess(llvm::StringRef plugin_name) { | |||
1134 | for (const TraceInstance &instance : GetTracePluginInstances().GetInstances()) | |||
1135 | if (instance.name == plugin_name) | |||
1136 | return instance.create_callback_for_live_process; | |||
1137 | return nullptr; | |||
1138 | } | |||
1139 | ||||
1140 | llvm::StringRef PluginManager::GetTraceSchema(llvm::StringRef plugin_name) { | |||
1141 | for (const TraceInstance &instance : GetTracePluginInstances().GetInstances()) | |||
1142 | if (instance.name == plugin_name) | |||
1143 | return instance.schema; | |||
1144 | return llvm::StringRef(); | |||
1145 | } | |||
1146 | ||||
1147 | llvm::StringRef PluginManager::GetTraceSchema(size_t index) { | |||
1148 | if (TraceInstance *instance = | |||
1149 | GetTracePluginInstances().GetInstanceAtIndex(index)) | |||
1150 | return instance->schema; | |||
1151 | return llvm::StringRef(); | |||
1152 | } | |||
1153 | ||||
1154 | #pragma mark TraceExporter | |||
1155 | ||||
1156 | struct TraceExporterInstance | |||
1157 | : public PluginInstance<TraceExporterCreateInstance> { | |||
1158 | TraceExporterInstance( | |||
1159 | llvm::StringRef name, llvm::StringRef description, | |||
1160 | TraceExporterCreateInstance create_instance, | |||
1161 | ThreadTraceExportCommandCreator create_thread_trace_export_command) | |||
1162 | : PluginInstance<TraceExporterCreateInstance>(name, description, | |||
1163 | create_instance), | |||
1164 | create_thread_trace_export_command(create_thread_trace_export_command) { | |||
1165 | } | |||
1166 | ||||
1167 | ThreadTraceExportCommandCreator create_thread_trace_export_command; | |||
1168 | }; | |||
1169 | ||||
1170 | typedef PluginInstances<TraceExporterInstance> TraceExporterInstances; | |||
1171 | ||||
1172 | static TraceExporterInstances &GetTraceExporterInstances() { | |||
1173 | static TraceExporterInstances g_instances; | |||
1174 | return g_instances; | |||
1175 | } | |||
1176 | ||||
1177 | bool PluginManager::RegisterPlugin( | |||
1178 | llvm::StringRef name, llvm::StringRef description, | |||
1179 | TraceExporterCreateInstance create_callback, | |||
1180 | ThreadTraceExportCommandCreator create_thread_trace_export_command) { | |||
1181 | return GetTraceExporterInstances().RegisterPlugin( | |||
1182 | name, description, create_callback, create_thread_trace_export_command); | |||
1183 | } | |||
1184 | ||||
1185 | TraceExporterCreateInstance | |||
1186 | PluginManager::GetTraceExporterCreateCallback(llvm::StringRef plugin_name) { | |||
1187 | return GetTraceExporterInstances().GetCallbackForName(plugin_name); | |||
1188 | } | |||
1189 | ||||
1190 | bool PluginManager::UnregisterPlugin( | |||
1191 | TraceExporterCreateInstance create_callback) { | |||
1192 | return GetTraceExporterInstances().UnregisterPlugin(create_callback); | |||
1193 | } | |||
1194 | ||||
1195 | ThreadTraceExportCommandCreator | |||
1196 | PluginManager::GetThreadTraceExportCommandCreatorAtIndex(uint32_t index) { | |||
1197 | if (TraceExporterInstance *instance = | |||
1198 | GetTraceExporterInstances().GetInstanceAtIndex(index)) | |||
1199 | return instance->create_thread_trace_export_command; | |||
1200 | return nullptr; | |||
1201 | } | |||
1202 | ||||
1203 | llvm::StringRef | |||
1204 | PluginManager::GetTraceExporterPluginNameAtIndex(uint32_t index) { | |||
1205 | return GetTraceExporterInstances().GetNameAtIndex(index); | |||
1206 | } | |||
1207 | ||||
1208 | #pragma mark UnwindAssembly | |||
1209 | ||||
1210 | typedef PluginInstance<UnwindAssemblyCreateInstance> UnwindAssemblyInstance; | |||
1211 | typedef PluginInstances<UnwindAssemblyInstance> UnwindAssemblyInstances; | |||
1212 | ||||
1213 | static UnwindAssemblyInstances &GetUnwindAssemblyInstances() { | |||
1214 | static UnwindAssemblyInstances g_instances; | |||
1215 | return g_instances; | |||
1216 | } | |||
1217 | ||||
1218 | bool PluginManager::RegisterPlugin( | |||
1219 | llvm::StringRef name, llvm::StringRef description, | |||
1220 | UnwindAssemblyCreateInstance create_callback) { | |||
1221 | return GetUnwindAssemblyInstances().RegisterPlugin(name, description, | |||
1222 | create_callback); | |||
1223 | } | |||
1224 | ||||
1225 | bool PluginManager::UnregisterPlugin( | |||
1226 | UnwindAssemblyCreateInstance create_callback) { | |||
1227 | return GetUnwindAssemblyInstances().UnregisterPlugin(create_callback); | |||
1228 | } | |||
1229 | ||||
1230 | UnwindAssemblyCreateInstance | |||
1231 | PluginManager::GetUnwindAssemblyCreateCallbackAtIndex(uint32_t idx) { | |||
1232 | return GetUnwindAssemblyInstances().GetCallbackAtIndex(idx); | |||
1233 | } | |||
1234 | ||||
1235 | #pragma mark MemoryHistory | |||
1236 | ||||
1237 | typedef PluginInstance<MemoryHistoryCreateInstance> MemoryHistoryInstance; | |||
1238 | typedef PluginInstances<MemoryHistoryInstance> MemoryHistoryInstances; | |||
1239 | ||||
1240 | static MemoryHistoryInstances &GetMemoryHistoryInstances() { | |||
1241 | static MemoryHistoryInstances g_instances; | |||
1242 | return g_instances; | |||
1243 | } | |||
1244 | ||||
1245 | bool PluginManager::RegisterPlugin( | |||
1246 | llvm::StringRef name, llvm::StringRef description, | |||
1247 | MemoryHistoryCreateInstance create_callback) { | |||
1248 | return GetMemoryHistoryInstances().RegisterPlugin(name, description, | |||
1249 | create_callback); | |||
1250 | } | |||
1251 | ||||
1252 | bool PluginManager::UnregisterPlugin( | |||
1253 | MemoryHistoryCreateInstance create_callback) { | |||
1254 | return GetMemoryHistoryInstances().UnregisterPlugin(create_callback); | |||
1255 | } | |||
1256 | ||||
1257 | MemoryHistoryCreateInstance | |||
1258 | PluginManager::GetMemoryHistoryCreateCallbackAtIndex(uint32_t idx) { | |||
1259 | return GetMemoryHistoryInstances().GetCallbackAtIndex(idx); | |||
1260 | } | |||
1261 | ||||
1262 | #pragma mark InstrumentationRuntime | |||
1263 | ||||
1264 | struct InstrumentationRuntimeInstance | |||
1265 | : public PluginInstance<InstrumentationRuntimeCreateInstance> { | |||
1266 | InstrumentationRuntimeInstance( | |||
1267 | llvm::StringRef name, llvm::StringRef description, | |||
1268 | CallbackType create_callback, | |||
1269 | InstrumentationRuntimeGetType get_type_callback) | |||
1270 | : PluginInstance<InstrumentationRuntimeCreateInstance>(name, description, | |||
1271 | create_callback), | |||
1272 | get_type_callback(get_type_callback) {} | |||
1273 | ||||
1274 | InstrumentationRuntimeGetType get_type_callback = nullptr; | |||
1275 | }; | |||
1276 | ||||
1277 | typedef PluginInstances<InstrumentationRuntimeInstance> | |||
1278 | InstrumentationRuntimeInstances; | |||
1279 | ||||
1280 | static InstrumentationRuntimeInstances &GetInstrumentationRuntimeInstances() { | |||
1281 | static InstrumentationRuntimeInstances g_instances; | |||
1282 | return g_instances; | |||
1283 | } | |||
1284 | ||||
1285 | bool PluginManager::RegisterPlugin( | |||
1286 | llvm::StringRef name, llvm::StringRef description, | |||
1287 | InstrumentationRuntimeCreateInstance create_callback, | |||
1288 | InstrumentationRuntimeGetType get_type_callback) { | |||
1289 | return GetInstrumentationRuntimeInstances().RegisterPlugin( | |||
1290 | name, description, create_callback, get_type_callback); | |||
1291 | } | |||
1292 | ||||
1293 | bool PluginManager::UnregisterPlugin( | |||
1294 | InstrumentationRuntimeCreateInstance create_callback) { | |||
1295 | return GetInstrumentationRuntimeInstances().UnregisterPlugin(create_callback); | |||
1296 | } | |||
1297 | ||||
1298 | InstrumentationRuntimeGetType | |||
1299 | PluginManager::GetInstrumentationRuntimeGetTypeCallbackAtIndex(uint32_t idx) { | |||
1300 | const auto &instances = GetInstrumentationRuntimeInstances().GetInstances(); | |||
1301 | if (idx < instances.size()) | |||
1302 | return instances[idx].get_type_callback; | |||
1303 | return nullptr; | |||
1304 | } | |||
1305 | ||||
1306 | InstrumentationRuntimeCreateInstance | |||
1307 | PluginManager::GetInstrumentationRuntimeCreateCallbackAtIndex(uint32_t idx) { | |||
1308 | return GetInstrumentationRuntimeInstances().GetCallbackAtIndex(idx); | |||
1309 | } | |||
1310 | ||||
1311 | #pragma mark TypeSystem | |||
1312 | ||||
1313 | struct TypeSystemInstance : public PluginInstance<TypeSystemCreateInstance> { | |||
1314 | TypeSystemInstance(llvm::StringRef name, llvm::StringRef description, | |||
1315 | CallbackType create_callback, | |||
1316 | LanguageSet supported_languages_for_types, | |||
1317 | LanguageSet supported_languages_for_expressions) | |||
1318 | : PluginInstance<TypeSystemCreateInstance>(name, description, | |||
1319 | create_callback), | |||
1320 | supported_languages_for_types(supported_languages_for_types), | |||
1321 | supported_languages_for_expressions( | |||
1322 | supported_languages_for_expressions) {} | |||
1323 | ||||
1324 | LanguageSet supported_languages_for_types; | |||
1325 | LanguageSet supported_languages_for_expressions; | |||
1326 | }; | |||
1327 | ||||
1328 | typedef PluginInstances<TypeSystemInstance> TypeSystemInstances; | |||
1329 | ||||
1330 | static TypeSystemInstances &GetTypeSystemInstances() { | |||
1331 | static TypeSystemInstances g_instances; | |||
1332 | return g_instances; | |||
1333 | } | |||
1334 | ||||
1335 | bool PluginManager::RegisterPlugin( | |||
1336 | llvm::StringRef name, llvm::StringRef description, | |||
1337 | TypeSystemCreateInstance create_callback, | |||
1338 | LanguageSet supported_languages_for_types, | |||
1339 | LanguageSet supported_languages_for_expressions) { | |||
1340 | return GetTypeSystemInstances().RegisterPlugin( | |||
| ||||
1341 | name, description, create_callback, supported_languages_for_types, | |||
1342 | supported_languages_for_expressions); | |||
1343 | } | |||
1344 | ||||
1345 | bool PluginManager::UnregisterPlugin(TypeSystemCreateInstance create_callback) { | |||
1346 | return GetTypeSystemInstances().UnregisterPlugin(create_callback); | |||
1347 | } | |||
1348 | ||||
1349 | TypeSystemCreateInstance | |||
1350 | PluginManager::GetTypeSystemCreateCallbackAtIndex(uint32_t idx) { | |||
1351 | return GetTypeSystemInstances().GetCallbackAtIndex(idx); | |||
1352 | } | |||
1353 | ||||
1354 | LanguageSet PluginManager::GetAllTypeSystemSupportedLanguagesForTypes() { | |||
1355 | const auto &instances = GetTypeSystemInstances().GetInstances(); | |||
1356 | LanguageSet all; | |||
1357 | for (unsigned i = 0; i < instances.size(); ++i) | |||
1358 | all.bitvector |= instances[i].supported_languages_for_types.bitvector; | |||
1359 | return all; | |||
1360 | } | |||
1361 | ||||
1362 | LanguageSet PluginManager::GetAllTypeSystemSupportedLanguagesForExpressions() { | |||
1363 | const auto &instances = GetTypeSystemInstances().GetInstances(); | |||
1364 | LanguageSet all; | |||
1365 | for (unsigned i = 0; i < instances.size(); ++i) | |||
1366 | all.bitvector |= instances[i].supported_languages_for_expressions.bitvector; | |||
1367 | return all; | |||
1368 | } | |||
1369 | ||||
1370 | #pragma mark REPL | |||
1371 | ||||
1372 | struct REPLInstance : public PluginInstance<REPLCreateInstance> { | |||
1373 | REPLInstance(llvm::StringRef name, llvm::StringRef description, | |||
1374 | CallbackType create_callback, LanguageSet supported_languages) | |||
1375 | : PluginInstance<REPLCreateInstance>(name, description, create_callback), | |||
1376 | supported_languages(supported_languages) {} | |||
1377 | ||||
1378 | LanguageSet supported_languages; | |||
1379 | }; | |||
1380 | ||||
1381 | typedef PluginInstances<REPLInstance> REPLInstances; | |||
1382 | ||||
1383 | static REPLInstances &GetREPLInstances() { | |||
1384 | static REPLInstances g_instances; | |||
1385 | return g_instances; | |||
1386 | } | |||
1387 | ||||
1388 | bool PluginManager::RegisterPlugin(llvm::StringRef name, llvm::StringRef description, | |||
1389 | REPLCreateInstance create_callback, | |||
1390 | LanguageSet supported_languages) { | |||
1391 | return GetREPLInstances().RegisterPlugin(name, description, create_callback, | |||
1392 | supported_languages); | |||
1393 | } | |||
1394 | ||||
1395 | bool PluginManager::UnregisterPlugin(REPLCreateInstance create_callback) { | |||
1396 | return GetREPLInstances().UnregisterPlugin(create_callback); | |||
1397 | } | |||
1398 | ||||
1399 | REPLCreateInstance PluginManager::GetREPLCreateCallbackAtIndex(uint32_t idx) { | |||
1400 | return GetREPLInstances().GetCallbackAtIndex(idx); | |||
1401 | } | |||
1402 | ||||
1403 | LanguageSet PluginManager::GetREPLSupportedLanguagesAtIndex(uint32_t idx) { | |||
1404 | const auto &instances = GetREPLInstances().GetInstances(); | |||
1405 | return idx < instances.size() ? instances[idx].supported_languages | |||
1406 | : LanguageSet(); | |||
1407 | } | |||
1408 | ||||
1409 | LanguageSet PluginManager::GetREPLAllTypeSystemSupportedLanguages() { | |||
1410 | const auto &instances = GetREPLInstances().GetInstances(); | |||
1411 | LanguageSet all; | |||
1412 | for (unsigned i = 0; i < instances.size(); ++i) | |||
1413 | all.bitvector |= instances[i].supported_languages.bitvector; | |||
1414 | return all; | |||
1415 | } | |||
1416 | ||||
1417 | #pragma mark PluginManager | |||
1418 | ||||
1419 | void PluginManager::DebuggerInitialize(Debugger &debugger) { | |||
1420 | GetDynamicLoaderInstances().PerformDebuggerCallback(debugger); | |||
1421 | GetJITLoaderInstances().PerformDebuggerCallback(debugger); | |||
1422 | GetObjectFileInstances().PerformDebuggerCallback(debugger); | |||
1423 | GetPlatformInstances().PerformDebuggerCallback(debugger); | |||
1424 | GetProcessInstances().PerformDebuggerCallback(debugger); | |||
1425 | GetSymbolFileInstances().PerformDebuggerCallback(debugger); | |||
1426 | GetOperatingSystemInstances().PerformDebuggerCallback(debugger); | |||
1427 | GetStructuredDataPluginInstances().PerformDebuggerCallback(debugger); | |||
1428 | GetTracePluginInstances().PerformDebuggerCallback(debugger); | |||
1429 | } | |||
1430 | ||||
1431 | // This is the preferred new way to register plugin specific settings. e.g. | |||
1432 | // This will put a plugin's settings under e.g. | |||
1433 | // "plugin.<plugin_type_name>.<plugin_type_desc>.SETTINGNAME". | |||
1434 | static lldb::OptionValuePropertiesSP | |||
1435 | GetDebuggerPropertyForPlugins(Debugger &debugger, ConstString plugin_type_name, | |||
1436 | llvm::StringRef plugin_type_desc, | |||
1437 | bool can_create) { | |||
1438 | lldb::OptionValuePropertiesSP parent_properties_sp( | |||
1439 | debugger.GetValueProperties()); | |||
1440 | if (parent_properties_sp) { | |||
1441 | static ConstString g_property_name("plugin"); | |||
1442 | ||||
1443 | OptionValuePropertiesSP plugin_properties_sp = | |||
1444 | parent_properties_sp->GetSubProperty(nullptr, g_property_name); | |||
1445 | if (!plugin_properties_sp && can_create) { | |||
1446 | plugin_properties_sp = | |||
1447 | std::make_shared<OptionValueProperties>(g_property_name); | |||
1448 | parent_properties_sp->AppendProperty(g_property_name, | |||
1449 | "Settings specify to plugins.", true, | |||
1450 | plugin_properties_sp); | |||
1451 | } | |||
1452 | ||||
1453 | if (plugin_properties_sp) { | |||
1454 | lldb::OptionValuePropertiesSP plugin_type_properties_sp = | |||
1455 | plugin_properties_sp->GetSubProperty(nullptr, plugin_type_name); | |||
1456 | if (!plugin_type_properties_sp && can_create) { | |||
1457 | plugin_type_properties_sp = | |||
1458 | std::make_shared<OptionValueProperties>(plugin_type_name); | |||
1459 | plugin_properties_sp->AppendProperty(plugin_type_name, plugin_type_desc, | |||
1460 | true, plugin_type_properties_sp); | |||
1461 | } | |||
1462 | return plugin_type_properties_sp; | |||
1463 | } | |||
1464 | } | |||
1465 | return lldb::OptionValuePropertiesSP(); | |||
1466 | } | |||
1467 | ||||
1468 | // This is deprecated way to register plugin specific settings. e.g. | |||
1469 | // "<plugin_type_name>.plugin.<plugin_type_desc>.SETTINGNAME" and Platform | |||
1470 | // generic settings would be under "platform.SETTINGNAME". | |||
1471 | static lldb::OptionValuePropertiesSP GetDebuggerPropertyForPluginsOldStyle( | |||
1472 | Debugger &debugger, ConstString plugin_type_name, | |||
1473 | llvm::StringRef plugin_type_desc, bool can_create) { | |||
1474 | static ConstString g_property_name("plugin"); | |||
1475 | lldb::OptionValuePropertiesSP parent_properties_sp( | |||
1476 | debugger.GetValueProperties()); | |||
1477 | if (parent_properties_sp) { | |||
1478 | OptionValuePropertiesSP plugin_properties_sp = | |||
1479 | parent_properties_sp->GetSubProperty(nullptr, plugin_type_name); | |||
1480 | if (!plugin_properties_sp && can_create) { | |||
1481 | plugin_properties_sp = | |||
1482 | std::make_shared<OptionValueProperties>(plugin_type_name); | |||
1483 | parent_properties_sp->AppendProperty(plugin_type_name, plugin_type_desc, | |||
1484 | true, plugin_properties_sp); | |||
1485 | } | |||
1486 | ||||
1487 | if (plugin_properties_sp) { | |||
1488 | lldb::OptionValuePropertiesSP plugin_type_properties_sp = | |||
1489 | plugin_properties_sp->GetSubProperty(nullptr, g_property_name); | |||
1490 | if (!plugin_type_properties_sp && can_create) { | |||
1491 | plugin_type_properties_sp = | |||
1492 | std::make_shared<OptionValueProperties>(g_property_name); | |||
1493 | plugin_properties_sp->AppendProperty(g_property_name, | |||
1494 | "Settings specific to plugins", | |||
1495 | true, plugin_type_properties_sp); | |||
1496 | } | |||
1497 | return plugin_type_properties_sp; | |||
1498 | } | |||
1499 | } | |||
1500 | return lldb::OptionValuePropertiesSP(); | |||
1501 | } | |||
1502 | ||||
1503 | namespace { | |||
1504 | ||||
1505 | typedef lldb::OptionValuePropertiesSP | |||
1506 | GetDebuggerPropertyForPluginsPtr(Debugger &, ConstString, llvm::StringRef, | |||
1507 | bool can_create); | |||
1508 | } | |||
1509 | ||||
1510 | static lldb::OptionValuePropertiesSP | |||
1511 | GetSettingForPlugin(Debugger &debugger, ConstString setting_name, | |||
1512 | ConstString plugin_type_name, | |||
1513 | GetDebuggerPropertyForPluginsPtr get_debugger_property = | |||
1514 | GetDebuggerPropertyForPlugins) { | |||
1515 | lldb::OptionValuePropertiesSP properties_sp; | |||
1516 | lldb::OptionValuePropertiesSP plugin_type_properties_sp(get_debugger_property( | |||
1517 | debugger, plugin_type_name, | |||
1518 | "", // not creating to so we don't need the description | |||
1519 | false)); | |||
1520 | if (plugin_type_properties_sp) | |||
1521 | properties_sp = | |||
1522 | plugin_type_properties_sp->GetSubProperty(nullptr, setting_name); | |||
1523 | return properties_sp; | |||
1524 | } | |||
1525 | ||||
1526 | static bool | |||
1527 | CreateSettingForPlugin(Debugger &debugger, ConstString plugin_type_name, | |||
1528 | llvm::StringRef plugin_type_desc, | |||
1529 | const lldb::OptionValuePropertiesSP &properties_sp, | |||
1530 | llvm::StringRef description, bool is_global_property, | |||
1531 | GetDebuggerPropertyForPluginsPtr get_debugger_property = | |||
1532 | GetDebuggerPropertyForPlugins) { | |||
1533 | if (properties_sp) { | |||
1534 | lldb::OptionValuePropertiesSP plugin_type_properties_sp( | |||
1535 | get_debugger_property(debugger, plugin_type_name, plugin_type_desc, | |||
1536 | true)); | |||
1537 | if (plugin_type_properties_sp) { | |||
1538 | plugin_type_properties_sp->AppendProperty(properties_sp->GetName(), | |||
1539 | description, is_global_property, | |||
1540 | properties_sp); | |||
1541 | return true; | |||
1542 | } | |||
1543 | } | |||
1544 | return false; | |||
1545 | } | |||
1546 | ||||
1547 | static const char *kDynamicLoaderPluginName("dynamic-loader"); | |||
1548 | static const char *kPlatformPluginName("platform"); | |||
1549 | static const char *kProcessPluginName("process"); | |||
1550 | static const char *kTracePluginName("trace"); | |||
1551 | static const char *kObjectFilePluginName("object-file"); | |||
1552 | static const char *kSymbolFilePluginName("symbol-file"); | |||
1553 | static const char *kJITLoaderPluginName("jit-loader"); | |||
1554 | static const char *kStructuredDataPluginName("structured-data"); | |||
1555 | ||||
1556 | lldb::OptionValuePropertiesSP | |||
1557 | PluginManager::GetSettingForDynamicLoaderPlugin(Debugger &debugger, | |||
1558 | ConstString setting_name) { | |||
1559 | return GetSettingForPlugin(debugger, setting_name, | |||
1560 | ConstString(kDynamicLoaderPluginName)); | |||
1561 | } | |||
1562 | ||||
1563 | bool PluginManager::CreateSettingForDynamicLoaderPlugin( | |||
1564 | Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, | |||
1565 | llvm::StringRef description, bool is_global_property) { | |||
1566 | return CreateSettingForPlugin(debugger, ConstString(kDynamicLoaderPluginName), | |||
1567 | "Settings for dynamic loader plug-ins", | |||
1568 | properties_sp, description, is_global_property); | |||
1569 | } | |||
1570 | ||||
1571 | lldb::OptionValuePropertiesSP | |||
1572 | PluginManager::GetSettingForPlatformPlugin(Debugger &debugger, | |||
1573 | ConstString setting_name) { | |||
1574 | return GetSettingForPlugin(debugger, setting_name, | |||
1575 | ConstString(kPlatformPluginName), | |||
1576 | GetDebuggerPropertyForPluginsOldStyle); | |||
1577 | } | |||
1578 | ||||
1579 | bool PluginManager::CreateSettingForPlatformPlugin( | |||
1580 | Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, | |||
1581 | llvm::StringRef description, bool is_global_property) { | |||
1582 | return CreateSettingForPlugin(debugger, ConstString(kPlatformPluginName), | |||
1583 | "Settings for platform plug-ins", properties_sp, | |||
1584 | description, is_global_property, | |||
1585 | GetDebuggerPropertyForPluginsOldStyle); | |||
1586 | } | |||
1587 | ||||
1588 | lldb::OptionValuePropertiesSP | |||
1589 | PluginManager::GetSettingForProcessPlugin(Debugger &debugger, | |||
1590 | ConstString setting_name) { | |||
1591 | return GetSettingForPlugin(debugger, setting_name, | |||
1592 | ConstString(kProcessPluginName)); | |||
1593 | } | |||
1594 | ||||
1595 | bool PluginManager::CreateSettingForProcessPlugin( | |||
1596 | Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, | |||
1597 | llvm::StringRef description, bool is_global_property) { | |||
1598 | return CreateSettingForPlugin(debugger, ConstString(kProcessPluginName), | |||
1599 | "Settings for process plug-ins", properties_sp, | |||
1600 | description, is_global_property); | |||
1601 | } | |||
1602 | ||||
1603 | bool PluginManager::CreateSettingForTracePlugin( | |||
1604 | Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, | |||
1605 | llvm::StringRef description, bool is_global_property) { | |||
1606 | return CreateSettingForPlugin(debugger, ConstString(kTracePluginName), | |||
1607 | "Settings for trace plug-ins", properties_sp, | |||
1608 | description, is_global_property); | |||
1609 | } | |||
1610 | ||||
1611 | lldb::OptionValuePropertiesSP | |||
1612 | PluginManager::GetSettingForObjectFilePlugin(Debugger &debugger, | |||
1613 | ConstString setting_name) { | |||
1614 | return GetSettingForPlugin(debugger, setting_name, | |||
1615 | ConstString(kObjectFilePluginName)); | |||
1616 | } | |||
1617 | ||||
1618 | bool PluginManager::CreateSettingForObjectFilePlugin( | |||
1619 | Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, | |||
1620 | llvm::StringRef description, bool is_global_property) { | |||
1621 | return CreateSettingForPlugin(debugger, ConstString(kObjectFilePluginName), | |||
1622 | "Settings for object file plug-ins", | |||
1623 | properties_sp, description, is_global_property); | |||
1624 | } | |||
1625 | ||||
1626 | lldb::OptionValuePropertiesSP | |||
1627 | PluginManager::GetSettingForSymbolFilePlugin(Debugger &debugger, | |||
1628 | ConstString setting_name) { | |||
1629 | return GetSettingForPlugin(debugger, setting_name, | |||
1630 | ConstString(kSymbolFilePluginName)); | |||
1631 | } | |||
1632 | ||||
1633 | bool PluginManager::CreateSettingForSymbolFilePlugin( | |||
1634 | Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, | |||
1635 | llvm::StringRef description, bool is_global_property) { | |||
1636 | return CreateSettingForPlugin(debugger, ConstString(kSymbolFilePluginName), | |||
1637 | "Settings for symbol file plug-ins", | |||
1638 | properties_sp, description, is_global_property); | |||
1639 | } | |||
1640 | ||||
1641 | lldb::OptionValuePropertiesSP | |||
1642 | PluginManager::GetSettingForJITLoaderPlugin(Debugger &debugger, | |||
1643 | ConstString setting_name) { | |||
1644 | return GetSettingForPlugin(debugger, setting_name, | |||
1645 | ConstString(kJITLoaderPluginName)); | |||
1646 | } | |||
1647 | ||||
1648 | bool PluginManager::CreateSettingForJITLoaderPlugin( | |||
1649 | Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, | |||
1650 | llvm::StringRef description, bool is_global_property) { | |||
1651 | return CreateSettingForPlugin(debugger, ConstString(kJITLoaderPluginName), | |||
1652 | "Settings for JIT loader plug-ins", | |||
1653 | properties_sp, description, is_global_property); | |||
1654 | } | |||
1655 | ||||
1656 | static const char *kOperatingSystemPluginName("os"); | |||
1657 | ||||
1658 | lldb::OptionValuePropertiesSP | |||
1659 | PluginManager::GetSettingForOperatingSystemPlugin(Debugger &debugger, | |||
1660 | ConstString setting_name) { | |||
1661 | lldb::OptionValuePropertiesSP properties_sp; | |||
1662 | lldb::OptionValuePropertiesSP plugin_type_properties_sp( | |||
1663 | GetDebuggerPropertyForPlugins( | |||
1664 | debugger, ConstString(kOperatingSystemPluginName), | |||
1665 | "", // not creating to so we don't need the description | |||
1666 | false)); | |||
1667 | if (plugin_type_properties_sp) | |||
1668 | properties_sp = | |||
1669 | plugin_type_properties_sp->GetSubProperty(nullptr, setting_name); | |||
1670 | return properties_sp; | |||
1671 | } | |||
1672 | ||||
1673 | bool PluginManager::CreateSettingForOperatingSystemPlugin( | |||
1674 | Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, | |||
1675 | llvm::StringRef description, bool is_global_property) { | |||
1676 | if (properties_sp) { | |||
1677 | lldb::OptionValuePropertiesSP plugin_type_properties_sp( | |||
1678 | GetDebuggerPropertyForPlugins( | |||
1679 | debugger, ConstString(kOperatingSystemPluginName), | |||
1680 | "Settings for operating system plug-ins", true)); | |||
1681 | if (plugin_type_properties_sp) { | |||
1682 | plugin_type_properties_sp->AppendProperty(properties_sp->GetName(), | |||
1683 | description, is_global_property, | |||
1684 | properties_sp); | |||
1685 | return true; | |||
1686 | } | |||
1687 | } | |||
1688 | return false; | |||
1689 | } | |||
1690 | ||||
1691 | lldb::OptionValuePropertiesSP | |||
1692 | PluginManager::GetSettingForStructuredDataPlugin(Debugger &debugger, | |||
1693 | ConstString setting_name) { | |||
1694 | return GetSettingForPlugin(debugger, setting_name, | |||
1695 | ConstString(kStructuredDataPluginName)); | |||
1696 | } | |||
1697 | ||||
1698 | bool PluginManager::CreateSettingForStructuredDataPlugin( | |||
1699 | Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, | |||
1700 | llvm::StringRef description, bool is_global_property) { | |||
1701 | return CreateSettingForPlugin(debugger, | |||
1702 | ConstString(kStructuredDataPluginName), | |||
1703 | "Settings for structured data plug-ins", | |||
1704 | properties_sp, description, is_global_property); | |||
1705 | } |
1 | //===-- TypeSystem.h ------------------------------------------*- C++ -*-===// |
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 | #ifndef LLDB_SYMBOL_TYPESYSTEM_H |
10 | #define LLDB_SYMBOL_TYPESYSTEM_H |
11 | |
12 | #include <functional> |
13 | #include <mutex> |
14 | #include <optional> |
15 | #include <string> |
16 | |
17 | #include "llvm/ADT/APFloat.h" |
18 | #include "llvm/ADT/APSInt.h" |
19 | #include "llvm/ADT/DenseMap.h" |
20 | #include "llvm/ADT/SmallBitVector.h" |
21 | #include "llvm/Support/Casting.h" |
22 | #include "llvm/Support/Error.h" |
23 | #include "llvm/Support/JSON.h" |
24 | |
25 | #include "lldb/Core/PluginInterface.h" |
26 | #include "lldb/Expression/Expression.h" |
27 | #include "lldb/Symbol/CompilerDecl.h" |
28 | #include "lldb/Symbol/CompilerDeclContext.h" |
29 | #include "lldb/lldb-private.h" |
30 | |
31 | class DWARFDIE; |
32 | class DWARFASTParser; |
33 | class PDBASTParser; |
34 | |
35 | namespace lldb_private { |
36 | namespace npdb { |
37 | class PdbAstBuilder; |
38 | } // namespace npdb |
39 | |
40 | /// A SmallBitVector that represents a set of source languages (\p |
41 | /// lldb::LanguageType). Each lldb::LanguageType is represented by |
42 | /// the bit with the position of its enumerator. The largest |
43 | /// LanguageType is < 64, so this is space-efficient and on 64-bit |
44 | /// architectures a LanguageSet can be completely stack-allocated. |
45 | struct LanguageSet { |
46 | llvm::SmallBitVector bitvector; |
47 | LanguageSet(); |
48 | |
49 | /// If the set contains a single language only, return it. |
50 | std::optional<lldb::LanguageType> GetSingularLanguage(); |
51 | void Insert(lldb::LanguageType language); |
52 | bool Empty() const; |
53 | size_t Size() const; |
54 | bool operator[](unsigned i) const; |
55 | }; |
56 | |
57 | /// Interface for representing a type system. |
58 | /// |
59 | /// Implemented by language plugins to define the type system for a given |
60 | /// language. |
61 | /// |
62 | /// This interface extensively used opaque pointers to prevent that generic |
63 | /// LLDB code has dependencies on language plugins. The type and semantics of |
64 | /// these opaque pointers are defined by the TypeSystem implementation inside |
65 | /// the respective language plugin. Opaque pointers from one TypeSystem |
66 | /// instance should never be passed to a different TypeSystem instance (even |
67 | /// when the language plugin for both TypeSystem instances is the same). |
68 | /// |
69 | /// Most of the functions in this class should not be called directly but only |
70 | /// called by their respective counterparts in CompilerType, CompilerDecl and |
71 | /// CompilerDeclContext. |
72 | /// |
73 | /// \see lldb_private::CompilerType |
74 | /// \see lldb_private::CompilerDecl |
75 | /// \see lldb_private::CompilerDeclContext |
76 | class TypeSystem : public PluginInterface, |
77 | public std::enable_shared_from_this<TypeSystem> { |
78 | public: |
79 | // Constructors and Destructors |
80 | TypeSystem(); |
81 | ~TypeSystem() override; |
82 | |
83 | // LLVM RTTI support |
84 | virtual bool isA(const void *ClassID) const = 0; |
85 | |
86 | static lldb::TypeSystemSP CreateInstance(lldb::LanguageType language, |
87 | Module *module); |
88 | |
89 | static lldb::TypeSystemSP CreateInstance(lldb::LanguageType language, |
90 | Target *target); |
91 | |
92 | /// Free up any resources associated with this TypeSystem. Done before |
93 | /// removing all the TypeSystems from the TypeSystemMap. |
94 | virtual void Finalize() {} |
95 | |
96 | virtual DWARFASTParser *GetDWARFParser() { return nullptr; } |
97 | virtual PDBASTParser *GetPDBParser() { return nullptr; } |
98 | virtual npdb::PdbAstBuilder *GetNativePDBParser() { return nullptr; } |
99 | |
100 | virtual SymbolFile *GetSymbolFile() const { return m_sym_file; } |
101 | |
102 | virtual void SetSymbolFile(SymbolFile *sym_file) { m_sym_file = sym_file; } |
103 | |
104 | // CompilerDecl functions |
105 | virtual ConstString DeclGetName(void *opaque_decl) = 0; |
106 | |
107 | virtual ConstString DeclGetMangledName(void *opaque_decl); |
108 | |
109 | virtual CompilerDeclContext DeclGetDeclContext(void *opaque_decl); |
110 | |
111 | virtual CompilerType DeclGetFunctionReturnType(void *opaque_decl); |
112 | |
113 | virtual size_t DeclGetFunctionNumArguments(void *opaque_decl); |
114 | |
115 | virtual CompilerType DeclGetFunctionArgumentType(void *opaque_decl, |
116 | size_t arg_idx); |
117 | |
118 | virtual CompilerType GetTypeForDecl(void *opaque_decl) = 0; |
119 | |
120 | // CompilerDeclContext functions |
121 | |
122 | virtual std::vector<CompilerDecl> |
123 | DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name, |
124 | const bool ignore_imported_decls); |
125 | |
126 | virtual ConstString DeclContextGetName(void *opaque_decl_ctx) = 0; |
127 | |
128 | virtual ConstString |
129 | DeclContextGetScopeQualifiedName(void *opaque_decl_ctx) = 0; |
130 | |
131 | virtual bool DeclContextIsClassMethod(void *opaque_decl_ctx) = 0; |
132 | |
133 | virtual bool DeclContextIsContainedInLookup(void *opaque_decl_ctx, |
134 | void *other_opaque_decl_ctx) = 0; |
135 | |
136 | virtual lldb::LanguageType DeclContextGetLanguage(void *opaque_decl_ctx) = 0; |
137 | |
138 | // Tests |
139 | #ifndef NDEBUG |
140 | /// Verify the integrity of the type to catch CompilerTypes that mix |
141 | /// and match invalid TypeSystem/Opaque type pairs. |
142 | virtual bool Verify(lldb::opaque_compiler_type_t type) = 0; |
143 | #endif |
144 | |
145 | virtual bool IsArrayType(lldb::opaque_compiler_type_t type, |
146 | CompilerType *element_type, uint64_t *size, |
147 | bool *is_incomplete) = 0; |
148 | |
149 | virtual bool IsAggregateType(lldb::opaque_compiler_type_t type) = 0; |
150 | |
151 | virtual bool IsAnonymousType(lldb::opaque_compiler_type_t type); |
152 | |
153 | virtual bool IsCharType(lldb::opaque_compiler_type_t type) = 0; |
154 | |
155 | virtual bool IsCompleteType(lldb::opaque_compiler_type_t type) = 0; |
156 | |
157 | virtual bool IsDefined(lldb::opaque_compiler_type_t type) = 0; |
158 | |
159 | virtual bool IsFloatingPointType(lldb::opaque_compiler_type_t type, |
160 | uint32_t &count, bool &is_complex) = 0; |
161 | |
162 | virtual bool IsFunctionType(lldb::opaque_compiler_type_t type) = 0; |
163 | |
164 | virtual size_t |
165 | GetNumberOfFunctionArguments(lldb::opaque_compiler_type_t type) = 0; |
166 | |
167 | virtual CompilerType |
168 | GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type, |
169 | const size_t index) = 0; |
170 | |
171 | virtual bool IsFunctionPointerType(lldb::opaque_compiler_type_t type) = 0; |
172 | |
173 | virtual bool |
174 | IsMemberFunctionPointerType(lldb::opaque_compiler_type_t type) = 0; |
175 | |
176 | virtual bool IsBlockPointerType(lldb::opaque_compiler_type_t type, |
177 | CompilerType *function_pointer_type_ptr) = 0; |
178 | |
179 | virtual bool IsIntegerType(lldb::opaque_compiler_type_t type, |
180 | bool &is_signed) = 0; |
181 | |
182 | virtual bool IsEnumerationType(lldb::opaque_compiler_type_t type, |
183 | bool &is_signed) { |
184 | is_signed = false; |
185 | return false; |
186 | } |
187 | |
188 | virtual bool IsScopedEnumerationType(lldb::opaque_compiler_type_t type) = 0; |
189 | |
190 | virtual bool IsPossibleDynamicType(lldb::opaque_compiler_type_t type, |
191 | CompilerType *target_type, // Can pass NULL |
192 | bool check_cplusplus, bool check_objc) = 0; |
193 | |
194 | virtual bool IsPointerType(lldb::opaque_compiler_type_t type, |
195 | CompilerType *pointee_type) = 0; |
196 | |
197 | virtual bool IsScalarType(lldb::opaque_compiler_type_t type) = 0; |
198 | |
199 | virtual bool IsVoidType(lldb::opaque_compiler_type_t type) = 0; |
200 | |
201 | virtual bool CanPassInRegisters(const CompilerType &type) = 0; |
202 | |
203 | // TypeSystems can support more than one language |
204 | virtual bool SupportsLanguage(lldb::LanguageType language) = 0; |
205 | |
206 | // Type Completion |
207 | |
208 | virtual bool GetCompleteType(lldb::opaque_compiler_type_t type) = 0; |
209 | |
210 | virtual bool IsForcefullyCompleted(lldb::opaque_compiler_type_t type) { |
211 | return false; |
212 | } |
213 | |
214 | // AST related queries |
215 | |
216 | virtual uint32_t GetPointerByteSize() = 0; |
217 | |
218 | // Accessors |
219 | |
220 | virtual ConstString GetTypeName(lldb::opaque_compiler_type_t type, |
221 | bool BaseOnly) = 0; |
222 | |
223 | virtual ConstString GetDisplayTypeName(lldb::opaque_compiler_type_t type) = 0; |
224 | |
225 | virtual uint32_t |
226 | GetTypeInfo(lldb::opaque_compiler_type_t type, |
227 | CompilerType *pointee_or_element_compiler_type) = 0; |
228 | |
229 | virtual lldb::LanguageType |
230 | GetMinimumLanguage(lldb::opaque_compiler_type_t type) = 0; |
231 | |
232 | virtual lldb::TypeClass GetTypeClass(lldb::opaque_compiler_type_t type) = 0; |
233 | |
234 | // Creating related types |
235 | |
236 | virtual CompilerType |
237 | GetArrayElementType(lldb::opaque_compiler_type_t type, |
238 | ExecutionContextScope *exe_scope) = 0; |
239 | |
240 | virtual CompilerType GetArrayType(lldb::opaque_compiler_type_t type, |
241 | uint64_t size); |
242 | |
243 | virtual CompilerType GetCanonicalType(lldb::opaque_compiler_type_t type) = 0; |
244 | |
245 | virtual CompilerType |
246 | GetEnumerationIntegerType(lldb::opaque_compiler_type_t type) = 0; |
247 | |
248 | // Returns -1 if this isn't a function of if the function doesn't have a |
249 | // prototype Returns a value >= 0 if there is a prototype. |
250 | virtual int GetFunctionArgumentCount(lldb::opaque_compiler_type_t type) = 0; |
251 | |
252 | virtual CompilerType |
253 | GetFunctionArgumentTypeAtIndex(lldb::opaque_compiler_type_t type, |
254 | size_t idx) = 0; |
255 | |
256 | virtual CompilerType |
257 | GetFunctionReturnType(lldb::opaque_compiler_type_t type) = 0; |
258 | |
259 | virtual size_t GetNumMemberFunctions(lldb::opaque_compiler_type_t type) = 0; |
260 | |
261 | virtual TypeMemberFunctionImpl |
262 | GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type, size_t idx) = 0; |
263 | |
264 | virtual CompilerType GetPointeeType(lldb::opaque_compiler_type_t type) = 0; |
265 | |
266 | virtual CompilerType GetPointerType(lldb::opaque_compiler_type_t type) = 0; |
267 | |
268 | virtual CompilerType |
269 | GetLValueReferenceType(lldb::opaque_compiler_type_t type); |
270 | |
271 | virtual CompilerType |
272 | GetRValueReferenceType(lldb::opaque_compiler_type_t type); |
273 | |
274 | virtual CompilerType GetAtomicType(lldb::opaque_compiler_type_t type); |
275 | |
276 | virtual CompilerType AddConstModifier(lldb::opaque_compiler_type_t type); |
277 | |
278 | virtual CompilerType AddVolatileModifier(lldb::opaque_compiler_type_t type); |
279 | |
280 | virtual CompilerType AddRestrictModifier(lldb::opaque_compiler_type_t type); |
281 | |
282 | /// \param opaque_payload The m_payload field of Type, which may |
283 | /// carry TypeSystem-specific extra information. |
284 | virtual CompilerType CreateTypedef(lldb::opaque_compiler_type_t type, |
285 | const char *name, |
286 | const CompilerDeclContext &decl_ctx, |
287 | uint32_t opaque_payload); |
288 | |
289 | // Exploring the type |
290 | |
291 | virtual const llvm::fltSemantics &GetFloatTypeSemantics(size_t byte_size) = 0; |
292 | |
293 | virtual std::optional<uint64_t> |
294 | GetBitSize(lldb::opaque_compiler_type_t type, |
295 | ExecutionContextScope *exe_scope) = 0; |
296 | |
297 | virtual lldb::Encoding GetEncoding(lldb::opaque_compiler_type_t type, |
298 | uint64_t &count) = 0; |
299 | |
300 | virtual lldb::Format GetFormat(lldb::opaque_compiler_type_t type) = 0; |
301 | |
302 | virtual uint32_t GetNumChildren(lldb::opaque_compiler_type_t type, |
303 | bool omit_empty_base_classes, |
304 | const ExecutionContext *exe_ctx) = 0; |
305 | |
306 | virtual CompilerType GetBuiltinTypeByName(ConstString name); |
307 | |
308 | virtual lldb::BasicType |
309 | GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) = 0; |
310 | |
311 | virtual void ForEachEnumerator( |
312 | lldb::opaque_compiler_type_t type, |
313 | std::function<bool(const CompilerType &integer_type, |
314 | ConstString name, |
315 | const llvm::APSInt &value)> const &callback) {} |
316 | |
317 | virtual uint32_t GetNumFields(lldb::opaque_compiler_type_t type) = 0; |
318 | |
319 | virtual CompilerType GetFieldAtIndex(lldb::opaque_compiler_type_t type, |
320 | size_t idx, std::string &name, |
321 | uint64_t *bit_offset_ptr, |
322 | uint32_t *bitfield_bit_size_ptr, |
323 | bool *is_bitfield_ptr) = 0; |
324 | |
325 | virtual uint32_t |
326 | GetNumDirectBaseClasses(lldb::opaque_compiler_type_t type) = 0; |
327 | |
328 | virtual uint32_t |
329 | GetNumVirtualBaseClasses(lldb::opaque_compiler_type_t type) = 0; |
330 | |
331 | virtual CompilerType |
332 | GetDirectBaseClassAtIndex(lldb::opaque_compiler_type_t type, size_t idx, |
333 | uint32_t *bit_offset_ptr) = 0; |
334 | |
335 | virtual CompilerType |
336 | GetVirtualBaseClassAtIndex(lldb::opaque_compiler_type_t type, size_t idx, |
337 | uint32_t *bit_offset_ptr) = 0; |
338 | |
339 | virtual CompilerType GetChildCompilerTypeAtIndex( |
340 | lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx, |
341 | bool transparent_pointers, bool omit_empty_base_classes, |
342 | bool ignore_array_bounds, std::string &child_name, |
343 | uint32_t &child_byte_size, int32_t &child_byte_offset, |
344 | uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset, |
345 | bool &child_is_base_class, bool &child_is_deref_of_parent, |
346 | ValueObject *valobj, uint64_t &language_flags) = 0; |
347 | |
348 | // Lookup a child given a name. This function will match base class names and |
349 | // member member names in "clang_type" only, not descendants. |
350 | virtual uint32_t GetIndexOfChildWithName(lldb::opaque_compiler_type_t type, |
351 | const char *name, |
352 | bool omit_empty_base_classes) = 0; |
353 | |
354 | // Lookup a child member given a name. This function will match member names |
355 | // only and will descend into "clang_type" children in search for the first |
356 | // member in this class, or any base class that matches "name". |
357 | // TODO: Return all matches for a given name by returning a |
358 | // vector<vector<uint32_t>> |
359 | // so we catch all names that match a given child name, not just the first. |
360 | virtual size_t |
361 | GetIndexOfChildMemberWithName(lldb::opaque_compiler_type_t type, |
362 | const char *name, bool omit_empty_base_classes, |
363 | std::vector<uint32_t> &child_indexes) = 0; |
364 | |
365 | virtual bool IsTemplateType(lldb::opaque_compiler_type_t type); |
366 | |
367 | virtual size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type, |
368 | bool expand_pack); |
369 | |
370 | virtual lldb::TemplateArgumentKind |
371 | GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, size_t idx, |
372 | bool expand_pack); |
373 | virtual CompilerType |
374 | GetTypeTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx, |
375 | bool expand_pack); |
376 | virtual std::optional<CompilerType::IntegralTemplateArgument> |
377 | GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx, |
378 | bool expand_pack); |
379 | |
380 | // Dumping types |
381 | |
382 | #ifndef NDEBUG |
383 | /// Convenience LLVM-style dump method for use in the debugger only. |
384 | LLVM_DUMP_METHOD__attribute__((noinline)) __attribute__((__used__)) virtual void |
385 | dump(lldb::opaque_compiler_type_t type) const = 0; |
386 | #endif |
387 | |
388 | virtual void DumpValue(lldb::opaque_compiler_type_t type, |
389 | ExecutionContext *exe_ctx, Stream *s, |
390 | lldb::Format format, const DataExtractor &data, |
391 | lldb::offset_t data_offset, size_t data_byte_size, |
392 | uint32_t bitfield_bit_size, |
393 | uint32_t bitfield_bit_offset, bool show_types, |
394 | bool show_summary, bool verbose, uint32_t depth) = 0; |
395 | |
396 | virtual bool DumpTypeValue(lldb::opaque_compiler_type_t type, Stream *s, |
397 | lldb::Format format, const DataExtractor &data, |
398 | lldb::offset_t data_offset, size_t data_byte_size, |
399 | uint32_t bitfield_bit_size, |
400 | uint32_t bitfield_bit_offset, |
401 | ExecutionContextScope *exe_scope) = 0; |
402 | |
403 | /// Dump the type to stdout. |
404 | virtual void DumpTypeDescription( |
405 | lldb::opaque_compiler_type_t type, |
406 | lldb::DescriptionLevel level = lldb::eDescriptionLevelFull) = 0; |
407 | |
408 | /// Print a description of the type to a stream. The exact implementation |
409 | /// varies, but the expectation is that eDescriptionLevelFull returns a |
410 | /// source-like representation of the type, whereas eDescriptionLevelVerbose |
411 | /// does a dump of the underlying AST if applicable. |
412 | virtual void DumpTypeDescription( |
413 | lldb::opaque_compiler_type_t type, Stream *s, |
414 | lldb::DescriptionLevel level = lldb::eDescriptionLevelFull) = 0; |
415 | |
416 | /// Dump a textual representation of the internal TypeSystem state to the |
417 | /// given stream. |
418 | /// |
419 | /// This should not modify the state of the TypeSystem if possible. |
420 | virtual void Dump(llvm::raw_ostream &output) = 0; |
421 | |
422 | // TODO: These methods appear unused. Should they be removed? |
423 | |
424 | virtual bool IsRuntimeGeneratedType(lldb::opaque_compiler_type_t type) = 0; |
425 | |
426 | virtual void DumpSummary(lldb::opaque_compiler_type_t type, |
427 | ExecutionContext *exe_ctx, Stream *s, |
428 | const DataExtractor &data, |
429 | lldb::offset_t data_offset, |
430 | size_t data_byte_size) = 0; |
431 | |
432 | // TODO: Determine if these methods should move to TypeSystemClang. |
433 | |
434 | virtual bool IsPointerOrReferenceType(lldb::opaque_compiler_type_t type, |
435 | CompilerType *pointee_type) = 0; |
436 | |
437 | virtual unsigned GetTypeQualifiers(lldb::opaque_compiler_type_t type) = 0; |
438 | |
439 | virtual bool IsCStringType(lldb::opaque_compiler_type_t type, |
440 | uint32_t &length) = 0; |
441 | |
442 | virtual std::optional<size_t> |
443 | GetTypeBitAlign(lldb::opaque_compiler_type_t type, |
444 | ExecutionContextScope *exe_scope) = 0; |
445 | |
446 | virtual CompilerType GetBasicTypeFromAST(lldb::BasicType basic_type) = 0; |
447 | |
448 | virtual CompilerType |
449 | GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding, |
450 | size_t bit_size) = 0; |
451 | |
452 | virtual bool IsBeingDefined(lldb::opaque_compiler_type_t type) = 0; |
453 | |
454 | virtual bool IsConst(lldb::opaque_compiler_type_t type) = 0; |
455 | |
456 | virtual uint32_t IsHomogeneousAggregate(lldb::opaque_compiler_type_t type, |
457 | CompilerType *base_type_ptr) = 0; |
458 | |
459 | virtual bool IsPolymorphicClass(lldb::opaque_compiler_type_t type) = 0; |
460 | |
461 | virtual bool IsTypedefType(lldb::opaque_compiler_type_t type) = 0; |
462 | |
463 | // If the current object represents a typedef type, get the underlying type |
464 | virtual CompilerType GetTypedefedType(lldb::opaque_compiler_type_t type) = 0; |
465 | |
466 | virtual bool IsVectorType(lldb::opaque_compiler_type_t type, |
467 | CompilerType *element_type, uint64_t *size) = 0; |
468 | |
469 | virtual CompilerType |
470 | GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) = 0; |
471 | |
472 | virtual CompilerType |
473 | GetNonReferenceType(lldb::opaque_compiler_type_t type) = 0; |
474 | |
475 | virtual bool IsReferenceType(lldb::opaque_compiler_type_t type, |
476 | CompilerType *pointee_type, bool *is_rvalue) = 0; |
477 | |
478 | virtual bool |
479 | ShouldTreatScalarValueAsAddress(lldb::opaque_compiler_type_t type) { |
480 | return IsPointerOrReferenceType(type, nullptr); |
481 | } |
482 | |
483 | virtual UserExpression * |
484 | GetUserExpression(llvm::StringRef expr, llvm::StringRef prefix, |
485 | lldb::LanguageType language, |
486 | Expression::ResultType desired_type, |
487 | const EvaluateExpressionOptions &options, |
488 | ValueObject *ctx_obj) { |
489 | return nullptr; |
490 | } |
491 | |
492 | virtual FunctionCaller *GetFunctionCaller(const CompilerType &return_type, |
493 | const Address &function_address, |
494 | const ValueList &arg_value_list, |
495 | const char *name) { |
496 | return nullptr; |
497 | } |
498 | |
499 | virtual std::unique_ptr<UtilityFunction> |
500 | CreateUtilityFunction(std::string text, std::string name); |
501 | |
502 | virtual PersistentExpressionState *GetPersistentExpressionState() { |
503 | return nullptr; |
504 | } |
505 | |
506 | virtual CompilerType GetTypeForFormatters(void *type); |
507 | |
508 | virtual LazyBool ShouldPrintAsOneLiner(void *type, ValueObject *valobj); |
509 | |
510 | // Type systems can have types that are placeholder types, which are meant to |
511 | // indicate the presence of a type, but offer no actual information about |
512 | // said types, and leave the burden of actually figuring type information out |
513 | // to dynamic type resolution. For instance a language with a generics |
514 | // system, can use placeholder types to indicate "type argument goes here", |
515 | // without promising uniqueness of the placeholder, nor attaching any |
516 | // actually idenfiable information to said placeholder. This API allows type |
517 | // systems to tell LLDB when such a type has been encountered In response, |
518 | // the debugger can react by not using this type as a cache entry in any |
519 | // type-specific way For instance, LLDB will currently not cache any |
520 | // formatters that are discovered on such a type as attributable to the |
521 | // meaningless type itself, instead preferring to use the dynamic type |
522 | virtual bool IsMeaninglessWithoutDynamicResolution(void *type); |
523 | |
524 | virtual std::optional<llvm::json::Value> ReportStatistics(); |
525 | |
526 | bool GetHasForcefullyCompletedTypes() const { |
527 | return m_has_forcefully_completed_types; |
528 | } |
529 | protected: |
530 | SymbolFile *m_sym_file = nullptr; |
531 | /// Used for reporting statistics. |
532 | bool m_has_forcefully_completed_types = false; |
533 | }; |
534 | |
535 | class TypeSystemMap { |
536 | public: |
537 | TypeSystemMap(); |
538 | ~TypeSystemMap(); |
539 | |
540 | // Clear calls Finalize on all the TypeSystems managed by this map, and then |
541 | // empties the map. |
542 | void Clear(); |
543 | |
544 | // Iterate through all of the type systems that are created. Return true from |
545 | // callback to keep iterating, false to stop iterating. |
546 | void ForEach(std::function<bool(lldb::TypeSystemSP)> const &callback); |
547 | |
548 | llvm::Expected<lldb::TypeSystemSP> |
549 | GetTypeSystemForLanguage(lldb::LanguageType language, Module *module, |
550 | bool can_create); |
551 | |
552 | llvm::Expected<lldb::TypeSystemSP> |
553 | GetTypeSystemForLanguage(lldb::LanguageType language, Target *target, |
554 | bool can_create); |
555 | |
556 | /// Check all type systems in the map to see if any have forcefully completed |
557 | /// types; |
558 | bool GetHasForcefullyCompletedTypes() const; |
559 | protected: |
560 | typedef llvm::DenseMap<uint16_t, lldb::TypeSystemSP> collection; |
561 | mutable std::mutex m_mutex; ///< A mutex to keep this object happy in |
562 | /// multi-threaded environments. |
563 | collection m_map; |
564 | bool m_clear_in_progress = false; |
565 | |
566 | private: |
567 | typedef llvm::function_ref<lldb::TypeSystemSP()> CreateCallback; |
568 | /// Finds the type system for the given language. If no type system could be |
569 | /// found for a language and a CreateCallback was provided, the value |
570 | /// returned by the callback will be treated as the TypeSystem for the |
571 | /// language. |
572 | /// |
573 | /// \param language The language for which the type system should be found. |
574 | /// \param create_callback A callback that will be called if no previously |
575 | /// created TypeSystem that fits the given language |
576 | /// could found. Can be omitted if a non-existent |
577 | /// type system should be treated as an error |
578 | /// instead. |
579 | /// \return The found type system or an error. |
580 | llvm::Expected<lldb::TypeSystemSP> GetTypeSystemForLanguage( |
581 | lldb::LanguageType language, |
582 | std::optional<CreateCallback> create_callback = std::nullopt); |
583 | }; |
584 | |
585 | } // namespace lldb_private |
586 | |
587 | #endif // LLDB_SYMBOL_TYPESYSTEM_H |
1 | //===- llvm/ADT/SmallBitVector.h - 'Normally small' bit vectors -*- C++ -*-===// | |||
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 | /// \file | |||
10 | /// This file implements the SmallBitVector class. | |||
11 | /// | |||
12 | //===----------------------------------------------------------------------===// | |||
13 | ||||
14 | #ifndef LLVM_ADT_SMALLBITVECTOR_H | |||
15 | #define LLVM_ADT_SMALLBITVECTOR_H | |||
16 | ||||
17 | #include "llvm/ADT/BitVector.h" | |||
18 | #include "llvm/ADT/iterator_range.h" | |||
19 | #include "llvm/Support/MathExtras.h" | |||
20 | #include <algorithm> | |||
21 | #include <cassert> | |||
22 | #include <climits> | |||
23 | #include <cstddef> | |||
24 | #include <cstdint> | |||
25 | #include <limits> | |||
26 | #include <utility> | |||
27 | ||||
28 | namespace llvm { | |||
29 | ||||
30 | /// This is a 'bitvector' (really, a variable-sized bit array), optimized for | |||
31 | /// the case when the array is small. It contains one pointer-sized field, which | |||
32 | /// is directly used as a plain collection of bits when possible, or as a | |||
33 | /// pointer to a larger heap-allocated array when necessary. This allows normal | |||
34 | /// "small" cases to be fast without losing generality for large inputs. | |||
35 | class SmallBitVector { | |||
36 | // TODO: In "large" mode, a pointer to a BitVector is used, leading to an | |||
37 | // unnecessary level of indirection. It would be more efficient to use a | |||
38 | // pointer to memory containing size, allocation size, and the array of bits. | |||
39 | uintptr_t X = 1; | |||
40 | ||||
41 | enum { | |||
42 | // The number of bits in this class. | |||
43 | NumBaseBits = sizeof(uintptr_t) * CHAR_BIT8, | |||
44 | ||||
45 | // One bit is used to discriminate between small and large mode. The | |||
46 | // remaining bits are used for the small-mode representation. | |||
47 | SmallNumRawBits = NumBaseBits - 1, | |||
48 | ||||
49 | // A few more bits are used to store the size of the bit set in small mode. | |||
50 | // Theoretically this is a ceil-log2. These bits are encoded in the most | |||
51 | // significant bits of the raw bits. | |||
52 | SmallNumSizeBits = (NumBaseBits == 32 ? 5 : | |||
53 | NumBaseBits == 64 ? 6 : | |||
54 | SmallNumRawBits), | |||
55 | ||||
56 | // The remaining bits are used to store the actual set in small mode. | |||
57 | SmallNumDataBits = SmallNumRawBits - SmallNumSizeBits | |||
58 | }; | |||
59 | ||||
60 | static_assert(NumBaseBits == 64 || NumBaseBits == 32, | |||
61 | "Unsupported word size"); | |||
62 | ||||
63 | public: | |||
64 | using size_type = uintptr_t; | |||
65 | ||||
66 | // Encapsulation of a single bit. | |||
67 | class reference { | |||
68 | SmallBitVector &TheVector; | |||
69 | unsigned BitPos; | |||
70 | ||||
71 | public: | |||
72 | reference(SmallBitVector &b, unsigned Idx) : TheVector(b), BitPos(Idx) {} | |||
73 | ||||
74 | reference(const reference&) = default; | |||
75 | ||||
76 | reference& operator=(reference t) { | |||
77 | *this = bool(t); | |||
78 | return *this; | |||
79 | } | |||
80 | ||||
81 | reference& operator=(bool t) { | |||
82 | if (t) | |||
83 | TheVector.set(BitPos); | |||
84 | else | |||
85 | TheVector.reset(BitPos); | |||
86 | return *this; | |||
87 | } | |||
88 | ||||
89 | operator bool() const { | |||
90 | return const_cast<const SmallBitVector &>(TheVector).operator[](BitPos); | |||
91 | } | |||
92 | }; | |||
93 | ||||
94 | private: | |||
95 | BitVector *getPointer() const { | |||
96 | assert(!isSmall())(static_cast <bool> (!isSmall()) ? void (0) : __assert_fail ("!isSmall()", "llvm/include/llvm/ADT/SmallBitVector.h", 96, __extension__ __PRETTY_FUNCTION__)); | |||
97 | return reinterpret_cast<BitVector *>(X); | |||
| ||||
98 | } | |||
99 | ||||
100 | void switchToSmall(uintptr_t NewSmallBits, size_type NewSize) { | |||
101 | X = 1; | |||
102 | setSmallSize(NewSize); | |||
103 | setSmallBits(NewSmallBits); | |||
104 | } | |||
105 | ||||
106 | void switchToLarge(BitVector *BV) { | |||
107 | X = reinterpret_cast<uintptr_t>(BV); | |||
108 | assert(!isSmall() && "Tried to use an unaligned pointer")(static_cast <bool> (!isSmall() && "Tried to use an unaligned pointer" ) ? void (0) : __assert_fail ("!isSmall() && \"Tried to use an unaligned pointer\"" , "llvm/include/llvm/ADT/SmallBitVector.h", 108, __extension__ __PRETTY_FUNCTION__)); | |||
109 | } | |||
110 | ||||
111 | // Return all the bits used for the "small" representation; this includes | |||
112 | // bits for the size as well as the element bits. | |||
113 | uintptr_t getSmallRawBits() const { | |||
114 | assert(isSmall())(static_cast <bool> (isSmall()) ? void (0) : __assert_fail ("isSmall()", "llvm/include/llvm/ADT/SmallBitVector.h", 114, __extension__ __PRETTY_FUNCTION__)); | |||
115 | return X >> 1; | |||
116 | } | |||
117 | ||||
118 | void setSmallRawBits(uintptr_t NewRawBits) { | |||
119 | assert(isSmall())(static_cast <bool> (isSmall()) ? void (0) : __assert_fail ("isSmall()", "llvm/include/llvm/ADT/SmallBitVector.h", 119, __extension__ __PRETTY_FUNCTION__)); | |||
120 | X = (NewRawBits << 1) | uintptr_t(1); | |||
121 | } | |||
122 | ||||
123 | // Return the size. | |||
124 | size_type getSmallSize() const { | |||
125 | return getSmallRawBits() >> SmallNumDataBits; | |||
126 | } | |||
127 | ||||
128 | void setSmallSize(size_type Size) { | |||
129 | setSmallRawBits(getSmallBits() | (Size << SmallNumDataBits)); | |||
130 | } | |||
131 | ||||
132 | // Return the element bits. | |||
133 | uintptr_t getSmallBits() const { | |||
134 | return getSmallRawBits() & ~(~uintptr_t(0) << getSmallSize()); | |||
135 | } | |||
136 | ||||
137 | void setSmallBits(uintptr_t NewBits) { | |||
138 | setSmallRawBits((NewBits & ~(~uintptr_t(0) << getSmallSize())) | | |||
139 | (getSmallSize() << SmallNumDataBits)); | |||
140 | } | |||
141 | ||||
142 | public: | |||
143 | /// Creates an empty bitvector. | |||
144 | SmallBitVector() = default; | |||
145 | ||||
146 | /// Creates a bitvector of specified number of bits. All bits are initialized | |||
147 | /// to the specified value. | |||
148 | explicit SmallBitVector(unsigned s, bool t = false) { | |||
149 | if (s <= SmallNumDataBits) | |||
150 | switchToSmall(t ? ~uintptr_t(0) : 0, s); | |||
151 | else | |||
152 | switchToLarge(new BitVector(s, t)); | |||
153 | } | |||
154 | ||||
155 | /// SmallBitVector copy ctor. | |||
156 | SmallBitVector(const SmallBitVector &RHS) { | |||
157 | if (RHS.isSmall()) | |||
158 | X = RHS.X; | |||
159 | else | |||
160 | switchToLarge(new BitVector(*RHS.getPointer())); | |||
161 | } | |||
162 | ||||
163 | SmallBitVector(SmallBitVector &&RHS) : X(RHS.X) { | |||
164 | RHS.X = 1; | |||
165 | } | |||
166 | ||||
167 | ~SmallBitVector() { | |||
168 | if (!isSmall()) | |||
169 | delete getPointer(); | |||
170 | } | |||
171 | ||||
172 | using const_set_bits_iterator = const_set_bits_iterator_impl<SmallBitVector>; | |||
173 | using set_iterator = const_set_bits_iterator; | |||
174 | ||||
175 | const_set_bits_iterator set_bits_begin() const { | |||
176 | return const_set_bits_iterator(*this); | |||
177 | } | |||
178 | ||||
179 | const_set_bits_iterator set_bits_end() const { | |||
180 | return const_set_bits_iterator(*this, -1); | |||
181 | } | |||
182 | ||||
183 | iterator_range<const_set_bits_iterator> set_bits() const { | |||
184 | return make_range(set_bits_begin(), set_bits_end()); | |||
185 | } | |||
186 | ||||
187 | bool isSmall() const { return X & uintptr_t(1); } | |||
188 | ||||
189 | /// Tests whether there are no bits in this bitvector. | |||
190 | bool empty() const { | |||
191 | return isSmall() ? getSmallSize() == 0 : getPointer()->empty(); | |||
192 | } | |||
193 | ||||
194 | /// Returns the number of bits in this bitvector. | |||
195 | size_type size() const { | |||
196 | return isSmall() ? getSmallSize() : getPointer()->size(); | |||
197 | } | |||
198 | ||||
199 | /// Returns the number of bits which are set. | |||
200 | size_type count() const { | |||
201 | if (isSmall()) { | |||
202 | uintptr_t Bits = getSmallBits(); | |||
203 | return llvm::popcount(Bits); | |||
204 | } | |||
205 | return getPointer()->count(); | |||
206 | } | |||
207 | ||||
208 | /// Returns true if any bit is set. | |||
209 | bool any() const { | |||
210 | if (isSmall()) | |||
211 | return getSmallBits() != 0; | |||
212 | return getPointer()->any(); | |||
213 | } | |||
214 | ||||
215 | /// Returns true if all bits are set. | |||
216 | bool all() const { | |||
217 | if (isSmall()) | |||
218 | return getSmallBits() == (uintptr_t(1) << getSmallSize()) - 1; | |||
219 | return getPointer()->all(); | |||
220 | } | |||
221 | ||||
222 | /// Returns true if none of the bits are set. | |||
223 | bool none() const { | |||
224 | if (isSmall()) | |||
225 | return getSmallBits() == 0; | |||
226 | return getPointer()->none(); | |||
227 | } | |||
228 | ||||
229 | /// Returns the index of the first set bit, -1 if none of the bits are set. | |||
230 | int find_first() const { | |||
231 | if (isSmall()) { | |||
232 | uintptr_t Bits = getSmallBits(); | |||
233 | if (Bits == 0) | |||
234 | return -1; | |||
235 | return llvm::countr_zero(Bits); | |||
236 | } | |||
237 | return getPointer()->find_first(); | |||
238 | } | |||
239 | ||||
240 | int find_last() const { | |||
241 | if (isSmall()) { | |||
242 | uintptr_t Bits = getSmallBits(); | |||
243 | if (Bits == 0) | |||
244 | return -1; | |||
245 | return NumBaseBits - llvm::countl_zero(Bits) - 1; | |||
246 | } | |||
247 | return getPointer()->find_last(); | |||
248 | } | |||
249 | ||||
250 | /// Returns the index of the first unset bit, -1 if all of the bits are set. | |||
251 | int find_first_unset() const { | |||
252 | if (isSmall()) { | |||
253 | if (count() == getSmallSize()) | |||
254 | return -1; | |||
255 | ||||
256 | uintptr_t Bits = getSmallBits(); | |||
257 | return llvm::countr_one(Bits); | |||
258 | } | |||
259 | return getPointer()->find_first_unset(); | |||
260 | } | |||
261 | ||||
262 | int find_last_unset() const { | |||
263 | if (isSmall()) { | |||
264 | if (count() == getSmallSize()) | |||
265 | return -1; | |||
266 | ||||
267 | uintptr_t Bits = getSmallBits(); | |||
268 | // Set unused bits. | |||
269 | Bits |= ~uintptr_t(0) << getSmallSize(); | |||
270 | return NumBaseBits - llvm::countl_one(Bits) - 1; | |||
271 | } | |||
272 | return getPointer()->find_last_unset(); | |||
273 | } | |||
274 | ||||
275 | /// Returns the index of the next set bit following the "Prev" bit. | |||
276 | /// Returns -1 if the next set bit is not found. | |||
277 | int find_next(unsigned Prev) const { | |||
278 | if (isSmall()) { | |||
279 | uintptr_t Bits = getSmallBits(); | |||
280 | // Mask off previous bits. | |||
281 | Bits &= ~uintptr_t(0) << (Prev + 1); | |||
282 | if (Bits == 0 || Prev + 1 >= getSmallSize()) | |||
283 | return -1; | |||
284 | return llvm::countr_zero(Bits); | |||
285 | } | |||
286 | return getPointer()->find_next(Prev); | |||
287 | } | |||
288 | ||||
289 | /// Returns the index of the next unset bit following the "Prev" bit. | |||
290 | /// Returns -1 if the next unset bit is not found. | |||
291 | int find_next_unset(unsigned Prev) const { | |||
292 | if (isSmall()) { | |||
293 | uintptr_t Bits = getSmallBits(); | |||
294 | // Mask in previous bits. | |||
295 | Bits |= (uintptr_t(1) << (Prev + 1)) - 1; | |||
296 | // Mask in unused bits. | |||
297 | Bits |= ~uintptr_t(0) << getSmallSize(); | |||
298 | ||||
299 | if (Bits == ~uintptr_t(0) || Prev + 1 >= getSmallSize()) | |||
300 | return -1; | |||
301 | return llvm::countr_one(Bits); | |||
302 | } | |||
303 | return getPointer()->find_next_unset(Prev); | |||
304 | } | |||
305 | ||||
306 | /// find_prev - Returns the index of the first set bit that precedes the | |||
307 | /// the bit at \p PriorTo. Returns -1 if all previous bits are unset. | |||
308 | int find_prev(unsigned PriorTo) const { | |||
309 | if (isSmall()) { | |||
310 | if (PriorTo == 0) | |||
311 | return -1; | |||
312 | ||||
313 | --PriorTo; | |||
314 | uintptr_t Bits = getSmallBits(); | |||
315 | Bits &= maskTrailingOnes<uintptr_t>(PriorTo + 1); | |||
316 | if (Bits == 0) | |||
317 | return -1; | |||
318 | ||||
319 | return NumBaseBits - llvm::countl_zero(Bits) - 1; | |||
320 | } | |||
321 | return getPointer()->find_prev(PriorTo); | |||
322 | } | |||
323 | ||||
324 | /// Clear all bits. | |||
325 | void clear() { | |||
326 | if (!isSmall()) | |||
327 | delete getPointer(); | |||
328 | switchToSmall(0, 0); | |||
329 | } | |||
330 | ||||
331 | /// Grow or shrink the bitvector. | |||
332 | void resize(unsigned N, bool t = false) { | |||
333 | if (!isSmall()) { | |||
334 | getPointer()->resize(N, t); | |||
335 | } else if (SmallNumDataBits >= N) { | |||
336 | uintptr_t NewBits = t ? ~uintptr_t(0) << getSmallSize() : 0; | |||
337 | setSmallSize(N); | |||
338 | setSmallBits(NewBits | getSmallBits()); | |||
339 | } else { | |||
340 | BitVector *BV = new BitVector(N, t); | |||
341 | uintptr_t OldBits = getSmallBits(); | |||
342 | for (size_type I = 0, E = getSmallSize(); I != E; ++I) | |||
343 | (*BV)[I] = (OldBits >> I) & 1; | |||
344 | switchToLarge(BV); | |||
345 | } | |||
346 | } | |||
347 | ||||
348 | void reserve(unsigned N) { | |||
349 | if (isSmall()) { | |||
350 | if (N > SmallNumDataBits) { | |||
351 | uintptr_t OldBits = getSmallRawBits(); | |||
352 | size_type SmallSize = getSmallSize(); | |||
353 | BitVector *BV = new BitVector(SmallSize); | |||
354 | for (size_type I = 0; I < SmallSize; ++I) | |||
355 | if ((OldBits >> I) & 1) | |||
356 | BV->set(I); | |||
357 | BV->reserve(N); | |||
358 | switchToLarge(BV); | |||
359 | } | |||
360 | } else { | |||
361 | getPointer()->reserve(N); | |||
362 | } | |||
363 | } | |||
364 | ||||
365 | // Set, reset, flip | |||
366 | SmallBitVector &set() { | |||
367 | if (isSmall()) | |||
368 | setSmallBits(~uintptr_t(0)); | |||
369 | else | |||
370 | getPointer()->set(); | |||
371 | return *this; | |||
372 | } | |||
373 | ||||
374 | SmallBitVector &set(unsigned Idx) { | |||
375 | if (isSmall()) { | |||
376 | assert(Idx <= static_cast<unsigned>((static_cast <bool> (Idx <= static_cast<unsigned> ( std::numeric_limits<uintptr_t>::digits) && "undefined behavior" ) ? void (0) : __assert_fail ("Idx <= static_cast<unsigned>( std::numeric_limits<uintptr_t>::digits) && \"undefined behavior\"" , "llvm/include/llvm/ADT/SmallBitVector.h", 378, __extension__ __PRETTY_FUNCTION__)) | |||
377 | std::numeric_limits<uintptr_t>::digits) &&(static_cast <bool> (Idx <= static_cast<unsigned> ( std::numeric_limits<uintptr_t>::digits) && "undefined behavior" ) ? void (0) : __assert_fail ("Idx <= static_cast<unsigned>( std::numeric_limits<uintptr_t>::digits) && \"undefined behavior\"" , "llvm/include/llvm/ADT/SmallBitVector.h", 378, __extension__ __PRETTY_FUNCTION__)) | |||
378 | "undefined behavior")(static_cast <bool> (Idx <= static_cast<unsigned> ( std::numeric_limits<uintptr_t>::digits) && "undefined behavior" ) ? void (0) : __assert_fail ("Idx <= static_cast<unsigned>( std::numeric_limits<uintptr_t>::digits) && \"undefined behavior\"" , "llvm/include/llvm/ADT/SmallBitVector.h", 378, __extension__ __PRETTY_FUNCTION__)); | |||
379 | setSmallBits(getSmallBits() | (uintptr_t(1) << Idx)); | |||
380 | } | |||
381 | else | |||
382 | getPointer()->set(Idx); | |||
383 | return *this; | |||
384 | } | |||
385 | ||||
386 | /// Efficiently set a range of bits in [I, E) | |||
387 | SmallBitVector &set(unsigned I, unsigned E) { | |||
388 | assert(I <= E && "Attempted to set backwards range!")(static_cast <bool> (I <= E && "Attempted to set backwards range!" ) ? void (0) : __assert_fail ("I <= E && \"Attempted to set backwards range!\"" , "llvm/include/llvm/ADT/SmallBitVector.h", 388, __extension__ __PRETTY_FUNCTION__)); | |||
389 | assert(E <= size() && "Attempted to set out-of-bounds range!")(static_cast <bool> (E <= size() && "Attempted to set out-of-bounds range!" ) ? void (0) : __assert_fail ("E <= size() && \"Attempted to set out-of-bounds range!\"" , "llvm/include/llvm/ADT/SmallBitVector.h", 389, __extension__ __PRETTY_FUNCTION__)); | |||
390 | if (I == E) return *this; | |||
391 | if (isSmall()) { | |||
392 | uintptr_t EMask = ((uintptr_t)1) << E; | |||
393 | uintptr_t IMask = ((uintptr_t)1) << I; | |||
394 | uintptr_t Mask = EMask - IMask; | |||
395 | setSmallBits(getSmallBits() | Mask); | |||
396 | } else | |||
397 | getPointer()->set(I, E); | |||
398 | return *this; | |||
399 | } | |||
400 | ||||
401 | SmallBitVector &reset() { | |||
402 | if (isSmall()) | |||
403 | setSmallBits(0); | |||
404 | else | |||
405 | getPointer()->reset(); | |||
406 | return *this; | |||
407 | } | |||
408 | ||||
409 | SmallBitVector &reset(unsigned Idx) { | |||
410 | if (isSmall()) | |||
411 | setSmallBits(getSmallBits() & ~(uintptr_t(1) << Idx)); | |||
412 | else | |||
413 | getPointer()->reset(Idx); | |||
414 | return *this; | |||
415 | } | |||
416 | ||||
417 | /// Efficiently reset a range of bits in [I, E) | |||
418 | SmallBitVector &reset(unsigned I, unsigned E) { | |||
419 | assert(I <= E && "Attempted to reset backwards range!")(static_cast <bool> (I <= E && "Attempted to reset backwards range!" ) ? void (0) : __assert_fail ("I <= E && \"Attempted to reset backwards range!\"" , "llvm/include/llvm/ADT/SmallBitVector.h", 419, __extension__ __PRETTY_FUNCTION__)); | |||
420 | assert(E <= size() && "Attempted to reset out-of-bounds range!")(static_cast <bool> (E <= size() && "Attempted to reset out-of-bounds range!" ) ? void (0) : __assert_fail ("E <= size() && \"Attempted to reset out-of-bounds range!\"" , "llvm/include/llvm/ADT/SmallBitVector.h", 420, __extension__ __PRETTY_FUNCTION__)); | |||
421 | if (I == E) return *this; | |||
422 | if (isSmall()) { | |||
423 | uintptr_t EMask = ((uintptr_t)1) << E; | |||
424 | uintptr_t IMask = ((uintptr_t)1) << I; | |||
425 | uintptr_t Mask = EMask - IMask; | |||
426 | setSmallBits(getSmallBits() & ~Mask); | |||
427 | } else | |||
428 | getPointer()->reset(I, E); | |||
429 | return *this; | |||
430 | } | |||
431 | ||||
432 | SmallBitVector &flip() { | |||
433 | if (isSmall()) | |||
434 | setSmallBits(~getSmallBits()); | |||
435 | else | |||
436 | getPointer()->flip(); | |||
437 | return *this; | |||
438 | } | |||
439 | ||||
440 | SmallBitVector &flip(unsigned Idx) { | |||
441 | if (isSmall()) | |||
442 | setSmallBits(getSmallBits() ^ (uintptr_t(1) << Idx)); | |||
443 | else | |||
444 | getPointer()->flip(Idx); | |||
445 | return *this; | |||
446 | } | |||
447 | ||||
448 | // No argument flip. | |||
449 | SmallBitVector operator~() const { | |||
450 | return SmallBitVector(*this).flip(); | |||
451 | } | |||
452 | ||||
453 | // Indexing. | |||
454 | reference operator[](unsigned Idx) { | |||
455 | assert(Idx < size() && "Out-of-bounds Bit access.")(static_cast <bool> (Idx < size() && "Out-of-bounds Bit access." ) ? void (0) : __assert_fail ("Idx < size() && \"Out-of-bounds Bit access.\"" , "llvm/include/llvm/ADT/SmallBitVector.h", 455, __extension__ __PRETTY_FUNCTION__)); | |||
456 | return reference(*this, Idx); | |||
457 | } | |||
458 | ||||
459 | bool operator[](unsigned Idx) const { | |||
460 | assert(Idx < size() && "Out-of-bounds Bit access.")(static_cast <bool> (Idx < size() && "Out-of-bounds Bit access." ) ? void (0) : __assert_fail ("Idx < size() && \"Out-of-bounds Bit access.\"" , "llvm/include/llvm/ADT/SmallBitVector.h", 460, __extension__ __PRETTY_FUNCTION__)); | |||
461 | if (isSmall()) | |||
462 | return ((getSmallBits() >> Idx) & 1) != 0; | |||
463 | return getPointer()->operator[](Idx); | |||
464 | } | |||
465 | ||||
466 | /// Return the last element in the vector. | |||
467 | bool back() const { | |||
468 | assert(!empty() && "Getting last element of empty vector.")(static_cast <bool> (!empty() && "Getting last element of empty vector." ) ? void (0) : __assert_fail ("!empty() && \"Getting last element of empty vector.\"" , "llvm/include/llvm/ADT/SmallBitVector.h", 468, __extension__ __PRETTY_FUNCTION__)); | |||
469 | return (*this)[size() - 1]; | |||
470 | } | |||
471 | ||||
472 | bool test(unsigned Idx) const { | |||
473 | return (*this)[Idx]; | |||
474 | } | |||
475 | ||||
476 | // Push single bit to end of vector. | |||
477 | void push_back(bool Val) { | |||
478 | resize(size() + 1, Val); | |||
479 | } | |||
480 | ||||
481 | /// Pop one bit from the end of the vector. | |||
482 | void pop_back() { | |||
483 | assert(!empty() && "Empty vector has no element to pop.")(static_cast <bool> (!empty() && "Empty vector has no element to pop." ) ? void (0) : __assert_fail ("!empty() && \"Empty vector has no element to pop.\"" , "llvm/include/llvm/ADT/SmallBitVector.h", 483, __extension__ __PRETTY_FUNCTION__)); | |||
484 | resize(size() - 1); | |||
485 | } | |||
486 | ||||
487 | /// Test if any common bits are set. | |||
488 | bool anyCommon(const SmallBitVector &RHS) const { | |||
489 | if (isSmall() && RHS.isSmall()) | |||
490 | return (getSmallBits() & RHS.getSmallBits()) != 0; | |||
491 | if (!isSmall() && !RHS.isSmall()) | |||
492 | return getPointer()->anyCommon(*RHS.getPointer()); | |||
493 | ||||
494 | for (unsigned i = 0, e = std::min(size(), RHS.size()); i != e; ++i) | |||
495 | if (test(i) && RHS.test(i)) | |||
496 | return true; | |||
497 | return false; | |||
498 | } | |||
499 | ||||
500 | // Comparison operators. | |||
501 | bool operator==(const SmallBitVector &RHS) const { | |||
502 | if (size() != RHS.size()) | |||
503 | return false; | |||
504 | if (isSmall() && RHS.isSmall()) | |||
505 | return getSmallBits() == RHS.getSmallBits(); | |||
506 | else if (!isSmall() && !RHS.isSmall()) | |||
507 | return *getPointer() == *RHS.getPointer(); | |||
508 | else { | |||
509 | for (size_type I = 0, E = size(); I != E; ++I) { | |||
510 | if ((*this)[I] != RHS[I]) | |||
511 | return false; | |||
512 | } | |||
513 | return true; | |||
514 | } | |||
515 | } | |||
516 | ||||
517 | bool operator!=(const SmallBitVector &RHS) const { | |||
518 | return !(*this == RHS); | |||
519 | } | |||
520 | ||||
521 | // Intersection, union, disjoint union. | |||
522 | // FIXME BitVector::operator&= does not resize the LHS but this does | |||
523 | SmallBitVector &operator&=(const SmallBitVector &RHS) { | |||
524 | resize(std::max(size(), RHS.size())); | |||
525 | if (isSmall() && RHS.isSmall()) | |||
526 | setSmallBits(getSmallBits() & RHS.getSmallBits()); | |||
527 | else if (!isSmall() && !RHS.isSmall()) | |||
528 | getPointer()->operator&=(*RHS.getPointer()); | |||
529 | else { | |||
530 | size_type I, E; | |||
531 | for (I = 0, E = std::min(size(), RHS.size()); I != E; ++I) | |||
532 | (*this)[I] = test(I) && RHS.test(I); | |||
533 | for (E = size(); I != E; ++I) | |||
534 | reset(I); | |||
535 | } | |||
536 | return *this; | |||
537 | } | |||
538 | ||||
539 | /// Reset bits that are set in RHS. Same as *this &= ~RHS. | |||
540 | SmallBitVector &reset(const SmallBitVector &RHS) { | |||
541 | if (isSmall() && RHS.isSmall()) | |||
542 | setSmallBits(getSmallBits() & ~RHS.getSmallBits()); | |||
543 | else if (!isSmall() && !RHS.isSmall()) | |||
544 | getPointer()->reset(*RHS.getPointer()); | |||
545 | else | |||
546 | for (unsigned i = 0, e = std::min(size(), RHS.size()); i != e; ++i) | |||
547 | if (RHS.test(i)) | |||
548 | reset(i); | |||
549 | ||||
550 | return *this; | |||
551 | } | |||
552 | ||||
553 | /// Check if (This - RHS) is zero. This is the same as reset(RHS) and any(). | |||
554 | bool test(const SmallBitVector &RHS) const { | |||
555 | if (isSmall() && RHS.isSmall()) | |||
556 | return (getSmallBits() & ~RHS.getSmallBits()) != 0; | |||
557 | if (!isSmall() && !RHS.isSmall()) | |||
558 | return getPointer()->test(*RHS.getPointer()); | |||
559 | ||||
560 | unsigned i, e; | |||
561 | for (i = 0, e = std::min(size(), RHS.size()); i != e; ++i) | |||
562 | if (test(i) && !RHS.test(i)) | |||
563 | return true; | |||
564 | ||||
565 | for (e = size(); i != e; ++i) | |||
566 | if (test(i)) | |||
567 | return true; | |||
568 | ||||
569 | return false; | |||
570 | } | |||
571 | ||||
572 | SmallBitVector &operator|=(const SmallBitVector &RHS) { | |||
573 | resize(std::max(size(), RHS.size())); | |||
574 | if (isSmall() && RHS.isSmall()) | |||
575 | setSmallBits(getSmallBits() | RHS.getSmallBits()); | |||
576 | else if (!isSmall() && !RHS.isSmall()) | |||
577 | getPointer()->operator|=(*RHS.getPointer()); | |||
578 | else { | |||
579 | for (size_type I = 0, E = RHS.size(); I != E; ++I) | |||
580 | (*this)[I] = test(I) || RHS.test(I); | |||
581 | } | |||
582 | return *this; | |||
583 | } | |||
584 | ||||
585 | SmallBitVector &operator^=(const SmallBitVector &RHS) { | |||
586 | resize(std::max(size(), RHS.size())); | |||
587 | if (isSmall() && RHS.isSmall()) | |||
588 | setSmallBits(getSmallBits() ^ RHS.getSmallBits()); | |||
589 | else if (!isSmall() && !RHS.isSmall()) | |||
590 | getPointer()->operator^=(*RHS.getPointer()); | |||
591 | else { | |||
592 | for (size_type I = 0, E = RHS.size(); I != E; ++I) | |||
593 | (*this)[I] = test(I) != RHS.test(I); | |||
594 | } | |||
595 | return *this; | |||
596 | } | |||
597 | ||||
598 | SmallBitVector &operator<<=(unsigned N) { | |||
599 | if (isSmall()) | |||
600 | setSmallBits(getSmallBits() << N); | |||
601 | else | |||
602 | getPointer()->operator<<=(N); | |||
603 | return *this; | |||
604 | } | |||
605 | ||||
606 | SmallBitVector &operator>>=(unsigned N) { | |||
607 | if (isSmall()) | |||
608 | setSmallBits(getSmallBits() >> N); | |||
609 | else | |||
610 | getPointer()->operator>>=(N); | |||
611 | return *this; | |||
612 | } | |||
613 | ||||
614 | // Assignment operator. | |||
615 | const SmallBitVector &operator=(const SmallBitVector &RHS) { | |||
616 | if (isSmall()) { | |||
617 | if (RHS.isSmall()) | |||
618 | X = RHS.X; | |||
619 | else | |||
620 | switchToLarge(new BitVector(*RHS.getPointer())); | |||
621 | } else { | |||
622 | if (!RHS.isSmall()) | |||
623 | *getPointer() = *RHS.getPointer(); | |||
624 | else { | |||
625 | delete getPointer(); | |||
626 | X = RHS.X; | |||
627 | } | |||
628 | } | |||
629 | return *this; | |||
630 | } | |||
631 | ||||
632 | const SmallBitVector &operator=(SmallBitVector &&RHS) { | |||
633 | if (this != &RHS) { | |||
634 | clear(); | |||
635 | swap(RHS); | |||
636 | } | |||
637 | return *this; | |||
638 | } | |||
639 | ||||
640 | void swap(SmallBitVector &RHS) { | |||
641 | std::swap(X, RHS.X); | |||
642 | } | |||
643 | ||||
644 | /// Add '1' bits from Mask to this vector. Don't resize. | |||
645 | /// This computes "*this |= Mask". | |||
646 | void setBitsInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) { | |||
647 | if (isSmall()) | |||
648 | applyMask<true, false>(Mask, MaskWords); | |||
649 | else | |||
650 | getPointer()->setBitsInMask(Mask, MaskWords); | |||
651 | } | |||
652 | ||||
653 | /// Clear any bits in this vector that are set in Mask. Don't resize. | |||
654 | /// This computes "*this &= ~Mask". | |||
655 | void clearBitsInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) { | |||
656 | if (isSmall()) | |||
657 | applyMask<false, false>(Mask, MaskWords); | |||
658 | else | |||
659 | getPointer()->clearBitsInMask(Mask, MaskWords); | |||
660 | } | |||
661 | ||||
662 | /// Add a bit to this vector for every '0' bit in Mask. Don't resize. | |||
663 | /// This computes "*this |= ~Mask". | |||
664 | void setBitsNotInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) { | |||
665 | if (isSmall()) | |||
666 | applyMask<true, true>(Mask, MaskWords); | |||
667 | else | |||
668 | getPointer()->setBitsNotInMask(Mask, MaskWords); | |||
669 | } | |||
670 | ||||
671 | /// Clear a bit in this vector for every '0' bit in Mask. Don't resize. | |||
672 | /// This computes "*this &= Mask". | |||
673 | void clearBitsNotInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) { | |||
674 | if (isSmall()) | |||
675 | applyMask<false, true>(Mask, MaskWords); | |||
676 | else | |||
677 | getPointer()->clearBitsNotInMask(Mask, MaskWords); | |||
678 | } | |||
679 | ||||
680 | void invalid() { | |||
681 | assert(empty())(static_cast <bool> (empty()) ? void (0) : __assert_fail ("empty()", "llvm/include/llvm/ADT/SmallBitVector.h", 681, __extension__ __PRETTY_FUNCTION__)); | |||
682 | X = (uintptr_t)-1; | |||
683 | } | |||
684 | bool isInvalid() const { return X == (uintptr_t)-1; } | |||
685 | ||||
686 | ArrayRef<uintptr_t> getData(uintptr_t &Store) const { | |||
687 | if (!isSmall()) | |||
688 | return getPointer()->getData(); | |||
689 | Store = getSmallBits(); | |||
690 | return Store; | |||
691 | } | |||
692 | ||||
693 | private: | |||
694 | template <bool AddBits, bool InvertMask> | |||
695 | void applyMask(const uint32_t *Mask, unsigned MaskWords) { | |||
696 | assert(MaskWords <= sizeof(uintptr_t) && "Mask is larger than base!")(static_cast <bool> (MaskWords <= sizeof(uintptr_t) && "Mask is larger than base!") ? void (0) : __assert_fail ("MaskWords <= sizeof(uintptr_t) && \"Mask is larger than base!\"" , "llvm/include/llvm/ADT/SmallBitVector.h", 696, __extension__ __PRETTY_FUNCTION__)); | |||
697 | uintptr_t M = Mask[0]; | |||
698 | if (NumBaseBits == 64) | |||
699 | M |= uint64_t(Mask[1]) << 32; | |||
700 | if (InvertMask) | |||
701 | M = ~M; | |||
702 | if (AddBits) | |||
703 | setSmallBits(getSmallBits() | M); | |||
704 | else | |||
705 | setSmallBits(getSmallBits() & ~M); | |||
706 | } | |||
707 | }; | |||
708 | ||||
709 | inline SmallBitVector | |||
710 | operator&(const SmallBitVector &LHS, const SmallBitVector &RHS) { | |||
711 | SmallBitVector Result(LHS); | |||
712 | Result &= RHS; | |||
713 | return Result; | |||
714 | } | |||
715 | ||||
716 | inline SmallBitVector | |||
717 | operator|(const SmallBitVector &LHS, const SmallBitVector &RHS) { | |||
718 | SmallBitVector Result(LHS); | |||
719 | Result |= RHS; | |||
720 | return Result; | |||
721 | } | |||
722 | ||||
723 | inline SmallBitVector | |||
724 | operator^(const SmallBitVector &LHS, const SmallBitVector &RHS) { | |||
725 | SmallBitVector Result(LHS); | |||
726 | Result ^= RHS; | |||
727 | return Result; | |||
728 | } | |||
729 | ||||
730 | template <> struct DenseMapInfo<SmallBitVector> { | |||
731 | static inline SmallBitVector getEmptyKey() { return SmallBitVector(); } | |||
732 | static inline SmallBitVector getTombstoneKey() { | |||
733 | SmallBitVector V; | |||
734 | V.invalid(); | |||
735 | return V; | |||
736 | } | |||
737 | static unsigned getHashValue(const SmallBitVector &V) { | |||
738 | uintptr_t Store; | |||
739 | return DenseMapInfo< | |||
740 | std::pair<SmallBitVector::size_type, ArrayRef<uintptr_t>>>:: | |||
741 | getHashValue(std::make_pair(V.size(), V.getData(Store))); | |||
742 | } | |||
743 | static bool isEqual(const SmallBitVector &LHS, const SmallBitVector &RHS) { | |||
744 | if (LHS.isInvalid() || RHS.isInvalid()) | |||
745 | return LHS.isInvalid() == RHS.isInvalid(); | |||
746 | return LHS == RHS; | |||
747 | } | |||
748 | }; | |||
749 | } // end namespace llvm | |||
750 | ||||
751 | namespace std { | |||
752 | ||||
753 | /// Implement std::swap in terms of BitVector swap. | |||
754 | inline void | |||
755 | swap(llvm::SmallBitVector &LHS, llvm::SmallBitVector &RHS) { | |||
756 | LHS.swap(RHS); | |||
757 | } | |||
758 | ||||
759 | } // end namespace std | |||
760 | ||||
761 | #endif // LLVM_ADT_SMALLBITVECTOR_H |