Bug Summary

File:build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/llvm/include/llvm/ADT/SmallBitVector.h
Warning:line 97, column 5
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name PluginManager.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm/tools/clang/stage2-bins -resource-dir /usr/lib/llvm-16/lib/clang/16.0.0 -isystem /usr/include/libxml2 -D HAVE_ROUND -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I tools/lldb/source/Core -I /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/lldb/source/Core -I /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/lldb/include -I tools/lldb/include -I include -I /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/llvm/include -I /usr/include/python3.9 -I /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/clang/include -I tools/lldb/../clang/include -I /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/lldb/source -I tools/lldb/source -D _FORTIFY_SOURCE=2 -D NDEBUG -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-16/lib/clang/16.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fmacro-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/= -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fcoverage-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/= -O2 -Wno-unused-command-line-argument -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -Wno-misleading-indentation -Wno-deprecated-declarations -Wno-unknown-pragmas -Wno-strict-aliasing -Wno-stringop-truncation -std=c++17 -fdeprecated-macro -fdebug-compilation-dir=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/build-llvm/tools/clang/stage2-bins=build-llvm/tools/clang/stage2-bins -fdebug-prefix-map=/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/= -ferror-limit 19 -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcolor-diagnostics -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-09-04-125545-48738-1 -x c++ /build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/lldb/source/Core/PluginManager.cpp

/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/lldb/source/Core/PluginManager.cpp

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
35using namespace lldb;
36using namespace lldb_private;
37
38typedef bool (*PluginInitCallback)();
39typedef void (*PluginTermCallback)();
40
41struct PluginInfo {
42 PluginInfo() = default;
43
44 llvm::sys::DynamicLibrary library;
45 PluginInitCallback plugin_init_callback = nullptr;
46 PluginTermCallback plugin_term_callback = nullptr;
47};
48
49typedef std::map<FileSpec, PluginInfo> PluginTerminateMap;
50
51static std::recursive_mutex &GetPluginMapMutex() {
52 static std::recursive_mutex g_plugin_map_mutex;
53 return g_plugin_map_mutex;
54}
55
56static PluginTerminateMap &GetPluginMap() {
57 static PluginTerminateMap g_plugin_map;
58 return g_plugin_map;
59}
60
61static 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
67static 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
75template <typename FPtrTy> static FPtrTy CastToFPtr(void *VPtr) {
76 return reinterpret_cast<FPtrTy>(VPtr);
77}
78
79static FileSystem::EnumerateDirectoryResult
80LoadPluginCallback(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
144void 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
168void 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
184template <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
200template <typename Instance> class PluginInstances {
201public:
202 template <typename... Args>
203 bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description,
204 typename Instance::CallbackType callback,
205 Args &&...args) {
206 if (!callback)
2
Assuming 'callback' is non-null
3
Taking false branch
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__))
;
4
Assuming the condition is true
5
'?' condition is true
209 Instance instance =
210 Instance(name, description, callback, std::forward<Args>(args)...);
6
Calling implicit copy constructor for 'LanguageSet'
7
Calling copy constructor for 'SmallBitVector'
11
Returning from copy constructor for 'SmallBitVector'
12
Returning from copy constructor for 'LanguageSet'
13
Calling implicit destructor for 'LanguageSet'
14
Calling '~SmallBitVector'
18
Returning from '~SmallBitVector'
19
Returning from destructor for 'LanguageSet'
211 m_instances.push_back(instance);
212 return false;
20
Calling implicit destructor for 'TypeSystemInstance'
21
Calling implicit destructor for 'LanguageSet'
22
Calling '~SmallBitVector'
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
273private:
274 std::vector<Instance> m_instances;
275};
276
277#pragma mark ABI
278
279typedef PluginInstance<ABICreateInstance> ABIInstance;
280typedef PluginInstances<ABIInstance> ABIInstances;
281
282static ABIInstances &GetABIInstances() {
283 static ABIInstances g_instances;
284 return g_instances;
285}
286
287bool PluginManager::RegisterPlugin(llvm::StringRef name,
288 llvm::StringRef description,
289 ABICreateInstance create_callback) {
290 return GetABIInstances().RegisterPlugin(name, description, create_callback);
291}
292
293bool PluginManager::UnregisterPlugin(ABICreateInstance create_callback) {
294 return GetABIInstances().UnregisterPlugin(create_callback);
295}
296
297ABICreateInstance PluginManager::GetABICreateCallbackAtIndex(uint32_t idx) {
298 return GetABIInstances().GetCallbackAtIndex(idx);
299}
300
301#pragma mark Architecture
302
303typedef PluginInstance<ArchitectureCreateInstance> ArchitectureInstance;
304typedef std::vector<ArchitectureInstance> ArchitectureInstances;
305
306static ArchitectureInstances &GetArchitectureInstances() {
307 static ArchitectureInstances g_instances;
308 return g_instances;
309}
310
311void PluginManager::RegisterPlugin(llvm::StringRef name,
312 llvm::StringRef description,
313 ArchitectureCreateInstance create_callback) {
314 GetArchitectureInstances().push_back({name, description, create_callback});
315}
316
317void 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
330std::unique_ptr<Architecture>
331PluginManager::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
341typedef PluginInstance<DisassemblerCreateInstance> DisassemblerInstance;
342typedef PluginInstances<DisassemblerInstance> DisassemblerInstances;
343
344static DisassemblerInstances &GetDisassemblerInstances() {
345 static DisassemblerInstances g_instances;
346 return g_instances;
347}
348
349bool PluginManager::RegisterPlugin(llvm::StringRef name,
350 llvm::StringRef description,
351 DisassemblerCreateInstance create_callback) {
352 return GetDisassemblerInstances().RegisterPlugin(name, description,
353 create_callback);
354}
355
356bool PluginManager::UnregisterPlugin(
357 DisassemblerCreateInstance create_callback) {
358 return GetDisassemblerInstances().UnregisterPlugin(create_callback);
359}
360
361DisassemblerCreateInstance
362PluginManager::GetDisassemblerCreateCallbackAtIndex(uint32_t idx) {
363 return GetDisassemblerInstances().GetCallbackAtIndex(idx);
364}
365
366DisassemblerCreateInstance
367PluginManager::GetDisassemblerCreateCallbackForPluginName(
368 llvm::StringRef name) {
369 return GetDisassemblerInstances().GetCallbackForName(name);
370}
371
372#pragma mark DynamicLoader
373
374typedef PluginInstance<DynamicLoaderCreateInstance> DynamicLoaderInstance;
375typedef PluginInstances<DynamicLoaderInstance> DynamicLoaderInstances;
376
377static DynamicLoaderInstances &GetDynamicLoaderInstances() {
378 static DynamicLoaderInstances g_instances;
379 return g_instances;
380}
381
382bool 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
390bool PluginManager::UnregisterPlugin(
391 DynamicLoaderCreateInstance create_callback) {
392 return GetDynamicLoaderInstances().UnregisterPlugin(create_callback);
393}
394
395DynamicLoaderCreateInstance
396PluginManager::GetDynamicLoaderCreateCallbackAtIndex(uint32_t idx) {
397 return GetDynamicLoaderInstances().GetCallbackAtIndex(idx);
398}
399
400DynamicLoaderCreateInstance
401PluginManager::GetDynamicLoaderCreateCallbackForPluginName(
402 llvm::StringRef name) {
403 return GetDynamicLoaderInstances().GetCallbackForName(name);
404}
405
406#pragma mark JITLoader
407
408typedef PluginInstance<JITLoaderCreateInstance> JITLoaderInstance;
409typedef PluginInstances<JITLoaderInstance> JITLoaderInstances;
410
411static JITLoaderInstances &GetJITLoaderInstances() {
412 static JITLoaderInstances g_instances;
413 return g_instances;
414}
415
416bool 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
424bool PluginManager::UnregisterPlugin(JITLoaderCreateInstance create_callback) {
425 return GetJITLoaderInstances().UnregisterPlugin(create_callback);
426}
427
428JITLoaderCreateInstance
429PluginManager::GetJITLoaderCreateCallbackAtIndex(uint32_t idx) {
430 return GetJITLoaderInstances().GetCallbackAtIndex(idx);
431}
432
433#pragma mark EmulateInstruction
434
435typedef PluginInstance<EmulateInstructionCreateInstance>
436 EmulateInstructionInstance;
437typedef PluginInstances<EmulateInstructionInstance> EmulateInstructionInstances;
438
439static EmulateInstructionInstances &GetEmulateInstructionInstances() {
440 static EmulateInstructionInstances g_instances;
441 return g_instances;
442}
443
444bool PluginManager::RegisterPlugin(
445 llvm::StringRef name, llvm::StringRef description,
446 EmulateInstructionCreateInstance create_callback) {
447 return GetEmulateInstructionInstances().RegisterPlugin(name, description,
448 create_callback);
449}
450
451bool PluginManager::UnregisterPlugin(
452 EmulateInstructionCreateInstance create_callback) {
453 return GetEmulateInstructionInstances().UnregisterPlugin(create_callback);
454}
455
456EmulateInstructionCreateInstance
457PluginManager::GetEmulateInstructionCreateCallbackAtIndex(uint32_t idx) {
458 return GetEmulateInstructionInstances().GetCallbackAtIndex(idx);
459}
460
461EmulateInstructionCreateInstance
462PluginManager::GetEmulateInstructionCreateCallbackForPluginName(
463 llvm::StringRef name) {
464 return GetEmulateInstructionInstances().GetCallbackForName(name);
465}
466
467#pragma mark OperatingSystem
468
469typedef PluginInstance<OperatingSystemCreateInstance> OperatingSystemInstance;
470typedef PluginInstances<OperatingSystemInstance> OperatingSystemInstances;
471
472static OperatingSystemInstances &GetOperatingSystemInstances() {
473 static OperatingSystemInstances g_instances;
474 return g_instances;
475}
476
477bool 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
485bool PluginManager::UnregisterPlugin(
486 OperatingSystemCreateInstance create_callback) {
487 return GetOperatingSystemInstances().UnregisterPlugin(create_callback);
488}
489
490OperatingSystemCreateInstance
491PluginManager::GetOperatingSystemCreateCallbackAtIndex(uint32_t idx) {
492 return GetOperatingSystemInstances().GetCallbackAtIndex(idx);
493}
494
495OperatingSystemCreateInstance
496PluginManager::GetOperatingSystemCreateCallbackForPluginName(
497 llvm::StringRef name) {
498 return GetOperatingSystemInstances().GetCallbackForName(name);
499}
500
501#pragma mark Language
502
503typedef PluginInstance<LanguageCreateInstance> LanguageInstance;
504typedef PluginInstances<LanguageInstance> LanguageInstances;
505
506static LanguageInstances &GetLanguageInstances() {
507 static LanguageInstances g_instances;
508 return g_instances;
509}
510
511bool PluginManager::RegisterPlugin(llvm::StringRef name,
512 llvm::StringRef description,
513 LanguageCreateInstance create_callback) {
514 return GetLanguageInstances().RegisterPlugin(name, description,
515 create_callback);
516}
517
518bool PluginManager::UnregisterPlugin(LanguageCreateInstance create_callback) {
519 return GetLanguageInstances().UnregisterPlugin(create_callback);
520}
521
522LanguageCreateInstance
523PluginManager::GetLanguageCreateCallbackAtIndex(uint32_t idx) {
524 return GetLanguageInstances().GetCallbackAtIndex(idx);
525}
526
527#pragma mark LanguageRuntime
528
529struct 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
546typedef PluginInstances<LanguageRuntimeInstance> LanguageRuntimeInstances;
547
548static LanguageRuntimeInstances &GetLanguageRuntimeInstances() {
549 static LanguageRuntimeInstances g_instances;
550 return g_instances;
551}
552
553bool 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
563bool PluginManager::UnregisterPlugin(
564 LanguageRuntimeCreateInstance create_callback) {
565 return GetLanguageRuntimeInstances().UnregisterPlugin(create_callback);
566}
567
568LanguageRuntimeCreateInstance
569PluginManager::GetLanguageRuntimeCreateCallbackAtIndex(uint32_t idx) {
570 return GetLanguageRuntimeInstances().GetCallbackAtIndex(idx);
571}
572
573LanguageRuntimeGetCommandObject
574PluginManager::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
581LanguageRuntimeGetExceptionPrecondition
582PluginManager::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
591typedef PluginInstance<SystemRuntimeCreateInstance> SystemRuntimeInstance;
592typedef PluginInstances<SystemRuntimeInstance> SystemRuntimeInstances;
593
594static SystemRuntimeInstances &GetSystemRuntimeInstances() {
595 static SystemRuntimeInstances g_instances;
596 return g_instances;
597}
598
599bool PluginManager::RegisterPlugin(
600 llvm::StringRef name, llvm::StringRef description,
601 SystemRuntimeCreateInstance create_callback) {
602 return GetSystemRuntimeInstances().RegisterPlugin(name, description,
603 create_callback);
604}
605
606bool PluginManager::UnregisterPlugin(
607 SystemRuntimeCreateInstance create_callback) {
608 return GetSystemRuntimeInstances().UnregisterPlugin(create_callback);
609}
610
611SystemRuntimeCreateInstance
612PluginManager::GetSystemRuntimeCreateCallbackAtIndex(uint32_t idx) {
613 return GetSystemRuntimeInstances().GetCallbackAtIndex(idx);
614}
615
616#pragma mark ObjectFile
617
618struct 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};
636typedef PluginInstances<ObjectFileInstance> ObjectFileInstances;
637
638static ObjectFileInstances &GetObjectFileInstances() {
639 static ObjectFileInstances g_instances;
640 return g_instances;
641}
642
643bool 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
655bool PluginManager::UnregisterPlugin(ObjectFileCreateInstance create_callback) {
656 return GetObjectFileInstances().UnregisterPlugin(create_callback);
657}
658
659ObjectFileCreateInstance
660PluginManager::GetObjectFileCreateCallbackAtIndex(uint32_t idx) {
661 return GetObjectFileInstances().GetCallbackAtIndex(idx);
662}
663
664ObjectFileCreateMemoryInstance
665PluginManager::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
672ObjectFileGetModuleSpecifications
673PluginManager::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
681ObjectFileCreateMemoryInstance
682PluginManager::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
692Status 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
722struct 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};
737typedef PluginInstances<ObjectContainerInstance> ObjectContainerInstances;
738
739static ObjectContainerInstances &GetObjectContainerInstances() {
740 static ObjectContainerInstances g_instances;
741 return g_instances;
742}
743
744bool 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
754bool PluginManager::UnregisterPlugin(
755 ObjectContainerCreateInstance create_callback) {
756 return GetObjectContainerInstances().UnregisterPlugin(create_callback);
757}
758
759ObjectContainerCreateInstance
760PluginManager::GetObjectContainerCreateCallbackAtIndex(uint32_t idx) {
761 return GetObjectContainerInstances().GetCallbackAtIndex(idx);
762}
763
764ObjectContainerCreateMemoryInstance
765PluginManager::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
772ObjectFileGetModuleSpecifications
773PluginManager::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
783typedef PluginInstance<PlatformCreateInstance> PlatformInstance;
784typedef PluginInstances<PlatformInstance> PlatformInstances;
785
786static PlatformInstances &GetPlatformInstances() {
787 static PlatformInstances g_platform_instances;
788 return g_platform_instances;
789}
790
791bool 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
799bool PluginManager::UnregisterPlugin(PlatformCreateInstance create_callback) {
800 return GetPlatformInstances().UnregisterPlugin(create_callback);
801}
802
803llvm::StringRef PluginManager::GetPlatformPluginNameAtIndex(uint32_t idx) {
804 return GetPlatformInstances().GetNameAtIndex(idx);
805}
806
807llvm::StringRef
808PluginManager::GetPlatformPluginDescriptionAtIndex(uint32_t idx) {
809 return GetPlatformInstances().GetDescriptionAtIndex(idx);
810}
811
812PlatformCreateInstance
813PluginManager::GetPlatformCreateCallbackAtIndex(uint32_t idx) {
814 return GetPlatformInstances().GetCallbackAtIndex(idx);
815}
816
817PlatformCreateInstance
818PluginManager::GetPlatformCreateCallbackForPluginName(llvm::StringRef name) {
819 return GetPlatformInstances().GetCallbackForName(name);
820}
821
822void 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
832typedef PluginInstance<ProcessCreateInstance> ProcessInstance;
833typedef PluginInstances<ProcessInstance> ProcessInstances;
834
835static ProcessInstances &GetProcessInstances() {
836 static ProcessInstances g_instances;
837 return g_instances;
838}
839
840bool 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
848bool PluginManager::UnregisterPlugin(ProcessCreateInstance create_callback) {
849 return GetProcessInstances().UnregisterPlugin(create_callback);
850}
851
852llvm::StringRef PluginManager::GetProcessPluginNameAtIndex(uint32_t idx) {
853 return GetProcessInstances().GetNameAtIndex(idx);
854}
855
856llvm::StringRef PluginManager::GetProcessPluginDescriptionAtIndex(uint32_t idx) {
857 return GetProcessInstances().GetDescriptionAtIndex(idx);
858}
859
860ProcessCreateInstance
861PluginManager::GetProcessCreateCallbackAtIndex(uint32_t idx) {
862 return GetProcessInstances().GetCallbackAtIndex(idx);
863}
864
865ProcessCreateInstance
866PluginManager::GetProcessCreateCallbackForPluginName(llvm::StringRef name) {
867 return GetProcessInstances().GetCallbackForName(name);
868}
869
870void 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 ScriptInterpreter
879
880struct ScriptInterpreterInstance
881 : public PluginInstance<ScriptInterpreterCreateInstance> {
882 ScriptInterpreterInstance(llvm::StringRef name, llvm::StringRef description,
883 CallbackType create_callback,
884 lldb::ScriptLanguage language)
885 : PluginInstance<ScriptInterpreterCreateInstance>(name, description,
886 create_callback),
887 language(language) {}
888
889 lldb::ScriptLanguage language = lldb::eScriptLanguageNone;
890};
891
892typedef PluginInstances<ScriptInterpreterInstance> ScriptInterpreterInstances;
893
894static ScriptInterpreterInstances &GetScriptInterpreterInstances() {
895 static ScriptInterpreterInstances g_instances;
896 return g_instances;
897}
898
899bool PluginManager::RegisterPlugin(
900 llvm::StringRef name, llvm::StringRef description,
901 lldb::ScriptLanguage script_language,
902 ScriptInterpreterCreateInstance create_callback) {
903 return GetScriptInterpreterInstances().RegisterPlugin(
904 name, description, create_callback, script_language);
905}
906
907bool PluginManager::UnregisterPlugin(
908 ScriptInterpreterCreateInstance create_callback) {
909 return GetScriptInterpreterInstances().UnregisterPlugin(create_callback);
910}
911
912ScriptInterpreterCreateInstance
913PluginManager::GetScriptInterpreterCreateCallbackAtIndex(uint32_t idx) {
914 return GetScriptInterpreterInstances().GetCallbackAtIndex(idx);
915}
916
917lldb::ScriptInterpreterSP
918PluginManager::GetScriptInterpreterForLanguage(lldb::ScriptLanguage script_lang,
919 Debugger &debugger) {
920 const auto &instances = GetScriptInterpreterInstances().GetInstances();
921 ScriptInterpreterCreateInstance none_instance = nullptr;
922 for (const auto &instance : instances) {
923 if (instance.language == lldb::eScriptLanguageNone)
924 none_instance = instance.create_callback;
925
926 if (script_lang == instance.language)
927 return instance.create_callback(debugger);
928 }
929
930 // If we didn't find one, return the ScriptInterpreter for the null language.
931 assert(none_instance != nullptr)(static_cast <bool> (none_instance != nullptr) ? void (
0) : __assert_fail ("none_instance != nullptr", "lldb/source/Core/PluginManager.cpp"
, 931, __extension__ __PRETTY_FUNCTION__))
;
932 return none_instance(debugger);
933}
934
935#pragma mark StructuredDataPlugin
936
937struct StructuredDataPluginInstance
938 : public PluginInstance<StructuredDataPluginCreateInstance> {
939 StructuredDataPluginInstance(
940 llvm::StringRef name, llvm::StringRef description,
941 CallbackType create_callback,
942 DebuggerInitializeCallback debugger_init_callback,
943 StructuredDataFilterLaunchInfo filter_callback)
944 : PluginInstance<StructuredDataPluginCreateInstance>(
945 name, description, create_callback, debugger_init_callback),
946 filter_callback(filter_callback) {}
947
948 StructuredDataFilterLaunchInfo filter_callback = nullptr;
949};
950
951typedef PluginInstances<StructuredDataPluginInstance>
952 StructuredDataPluginInstances;
953
954static StructuredDataPluginInstances &GetStructuredDataPluginInstances() {
955 static StructuredDataPluginInstances g_instances;
956 return g_instances;
957}
958
959bool PluginManager::RegisterPlugin(
960 llvm::StringRef name, llvm::StringRef description,
961 StructuredDataPluginCreateInstance create_callback,
962 DebuggerInitializeCallback debugger_init_callback,
963 StructuredDataFilterLaunchInfo filter_callback) {
964 return GetStructuredDataPluginInstances().RegisterPlugin(
965 name, description, create_callback, debugger_init_callback,
966 filter_callback);
967}
968
969bool PluginManager::UnregisterPlugin(
970 StructuredDataPluginCreateInstance create_callback) {
971 return GetStructuredDataPluginInstances().UnregisterPlugin(create_callback);
972}
973
974StructuredDataPluginCreateInstance
975PluginManager::GetStructuredDataPluginCreateCallbackAtIndex(uint32_t idx) {
976 return GetStructuredDataPluginInstances().GetCallbackAtIndex(idx);
977}
978
979StructuredDataFilterLaunchInfo
980PluginManager::GetStructuredDataFilterCallbackAtIndex(
981 uint32_t idx, bool &iteration_complete) {
982 const auto &instances = GetStructuredDataPluginInstances().GetInstances();
983 if (idx < instances.size()) {
984 iteration_complete = false;
985 return instances[idx].filter_callback;
986 } else {
987 iteration_complete = true;
988 }
989 return nullptr;
990}
991
992#pragma mark SymbolFile
993
994typedef PluginInstance<SymbolFileCreateInstance> SymbolFileInstance;
995typedef PluginInstances<SymbolFileInstance> SymbolFileInstances;
996
997static SymbolFileInstances &GetSymbolFileInstances() {
998 static SymbolFileInstances g_instances;
999 return g_instances;
1000}
1001
1002bool PluginManager::RegisterPlugin(
1003 llvm::StringRef name, llvm::StringRef description,
1004 SymbolFileCreateInstance create_callback,
1005 DebuggerInitializeCallback debugger_init_callback) {
1006 return GetSymbolFileInstances().RegisterPlugin(
1007 name, description, create_callback, debugger_init_callback);
1008}
1009
1010bool PluginManager::UnregisterPlugin(SymbolFileCreateInstance create_callback) {
1011 return GetSymbolFileInstances().UnregisterPlugin(create_callback);
1012}
1013
1014SymbolFileCreateInstance
1015PluginManager::GetSymbolFileCreateCallbackAtIndex(uint32_t idx) {
1016 return GetSymbolFileInstances().GetCallbackAtIndex(idx);
1017}
1018
1019#pragma mark SymbolVendor
1020
1021typedef PluginInstance<SymbolVendorCreateInstance> SymbolVendorInstance;
1022typedef PluginInstances<SymbolVendorInstance> SymbolVendorInstances;
1023
1024static SymbolVendorInstances &GetSymbolVendorInstances() {
1025 static SymbolVendorInstances g_instances;
1026 return g_instances;
1027}
1028
1029bool PluginManager::RegisterPlugin(llvm::StringRef name,
1030 llvm::StringRef description,
1031 SymbolVendorCreateInstance create_callback) {
1032 return GetSymbolVendorInstances().RegisterPlugin(name, description,
1033 create_callback);
1034}
1035
1036bool PluginManager::UnregisterPlugin(
1037 SymbolVendorCreateInstance create_callback) {
1038 return GetSymbolVendorInstances().UnregisterPlugin(create_callback);
1039}
1040
1041SymbolVendorCreateInstance
1042PluginManager::GetSymbolVendorCreateCallbackAtIndex(uint32_t idx) {
1043 return GetSymbolVendorInstances().GetCallbackAtIndex(idx);
1044}
1045
1046#pragma mark Trace
1047
1048struct TraceInstance
1049 : public PluginInstance<TraceCreateInstanceFromBundle> {
1050 TraceInstance(
1051 llvm::StringRef name, llvm::StringRef description,
1052 CallbackType create_callback_from_bundle,
1053 TraceCreateInstanceForLiveProcess create_callback_for_live_process,
1054 llvm::StringRef schema)
1055 : PluginInstance<TraceCreateInstanceFromBundle>(
1056 name, description, create_callback_from_bundle),
1057 schema(schema),
1058 create_callback_for_live_process(create_callback_for_live_process) {}
1059
1060 llvm::StringRef schema;
1061 TraceCreateInstanceForLiveProcess create_callback_for_live_process;
1062};
1063
1064typedef PluginInstances<TraceInstance> TraceInstances;
1065
1066static TraceInstances &GetTracePluginInstances() {
1067 static TraceInstances g_instances;
1068 return g_instances;
1069}
1070
1071bool PluginManager::RegisterPlugin(
1072 llvm::StringRef name, llvm::StringRef description,
1073 TraceCreateInstanceFromBundle create_callback_from_bundle,
1074 TraceCreateInstanceForLiveProcess create_callback_for_live_process,
1075 llvm::StringRef schema) {
1076 return GetTracePluginInstances().RegisterPlugin(
1077 name, description, create_callback_from_bundle,
1078 create_callback_for_live_process, schema);
1079}
1080
1081bool PluginManager::UnregisterPlugin(
1082 TraceCreateInstanceFromBundle create_callback_from_bundle) {
1083 return GetTracePluginInstances().UnregisterPlugin(
1084 create_callback_from_bundle);
1085}
1086
1087TraceCreateInstanceFromBundle
1088PluginManager::GetTraceCreateCallback(llvm::StringRef plugin_name) {
1089 return GetTracePluginInstances().GetCallbackForName(plugin_name);
1090}
1091
1092TraceCreateInstanceForLiveProcess
1093PluginManager::GetTraceCreateCallbackForLiveProcess(llvm::StringRef plugin_name) {
1094 for (const TraceInstance &instance : GetTracePluginInstances().GetInstances())
1095 if (instance.name == plugin_name)
1096 return instance.create_callback_for_live_process;
1097 return nullptr;
1098}
1099
1100llvm::StringRef PluginManager::GetTraceSchema(llvm::StringRef plugin_name) {
1101 for (const TraceInstance &instance : GetTracePluginInstances().GetInstances())
1102 if (instance.name == plugin_name)
1103 return instance.schema;
1104 return llvm::StringRef();
1105}
1106
1107llvm::StringRef PluginManager::GetTraceSchema(size_t index) {
1108 if (TraceInstance *instance =
1109 GetTracePluginInstances().GetInstanceAtIndex(index))
1110 return instance->schema;
1111 return llvm::StringRef();
1112}
1113
1114#pragma mark TraceExporter
1115
1116struct TraceExporterInstance
1117 : public PluginInstance<TraceExporterCreateInstance> {
1118 TraceExporterInstance(
1119 llvm::StringRef name, llvm::StringRef description,
1120 TraceExporterCreateInstance create_instance,
1121 ThreadTraceExportCommandCreator create_thread_trace_export_command)
1122 : PluginInstance<TraceExporterCreateInstance>(name, description,
1123 create_instance),
1124 create_thread_trace_export_command(create_thread_trace_export_command) {
1125 }
1126
1127 ThreadTraceExportCommandCreator create_thread_trace_export_command;
1128};
1129
1130typedef PluginInstances<TraceExporterInstance> TraceExporterInstances;
1131
1132static TraceExporterInstances &GetTraceExporterInstances() {
1133 static TraceExporterInstances g_instances;
1134 return g_instances;
1135}
1136
1137bool PluginManager::RegisterPlugin(
1138 llvm::StringRef name, llvm::StringRef description,
1139 TraceExporterCreateInstance create_callback,
1140 ThreadTraceExportCommandCreator create_thread_trace_export_command) {
1141 return GetTraceExporterInstances().RegisterPlugin(
1142 name, description, create_callback, create_thread_trace_export_command);
1143}
1144
1145TraceExporterCreateInstance
1146PluginManager::GetTraceExporterCreateCallback(llvm::StringRef plugin_name) {
1147 return GetTraceExporterInstances().GetCallbackForName(plugin_name);
1148}
1149
1150bool PluginManager::UnregisterPlugin(
1151 TraceExporterCreateInstance create_callback) {
1152 return GetTraceExporterInstances().UnregisterPlugin(create_callback);
1153}
1154
1155ThreadTraceExportCommandCreator
1156PluginManager::GetThreadTraceExportCommandCreatorAtIndex(uint32_t index) {
1157 if (TraceExporterInstance *instance =
1158 GetTraceExporterInstances().GetInstanceAtIndex(index))
1159 return instance->create_thread_trace_export_command;
1160 return nullptr;
1161}
1162
1163llvm::StringRef
1164PluginManager::GetTraceExporterPluginNameAtIndex(uint32_t index) {
1165 return GetTraceExporterInstances().GetNameAtIndex(index);
1166}
1167
1168#pragma mark UnwindAssembly
1169
1170typedef PluginInstance<UnwindAssemblyCreateInstance> UnwindAssemblyInstance;
1171typedef PluginInstances<UnwindAssemblyInstance> UnwindAssemblyInstances;
1172
1173static UnwindAssemblyInstances &GetUnwindAssemblyInstances() {
1174 static UnwindAssemblyInstances g_instances;
1175 return g_instances;
1176}
1177
1178bool PluginManager::RegisterPlugin(
1179 llvm::StringRef name, llvm::StringRef description,
1180 UnwindAssemblyCreateInstance create_callback) {
1181 return GetUnwindAssemblyInstances().RegisterPlugin(name, description,
1182 create_callback);
1183}
1184
1185bool PluginManager::UnregisterPlugin(
1186 UnwindAssemblyCreateInstance create_callback) {
1187 return GetUnwindAssemblyInstances().UnregisterPlugin(create_callback);
1188}
1189
1190UnwindAssemblyCreateInstance
1191PluginManager::GetUnwindAssemblyCreateCallbackAtIndex(uint32_t idx) {
1192 return GetUnwindAssemblyInstances().GetCallbackAtIndex(idx);
1193}
1194
1195#pragma mark MemoryHistory
1196
1197typedef PluginInstance<MemoryHistoryCreateInstance> MemoryHistoryInstance;
1198typedef PluginInstances<MemoryHistoryInstance> MemoryHistoryInstances;
1199
1200static MemoryHistoryInstances &GetMemoryHistoryInstances() {
1201 static MemoryHistoryInstances g_instances;
1202 return g_instances;
1203}
1204
1205bool PluginManager::RegisterPlugin(
1206 llvm::StringRef name, llvm::StringRef description,
1207 MemoryHistoryCreateInstance create_callback) {
1208 return GetMemoryHistoryInstances().RegisterPlugin(name, description,
1209 create_callback);
1210}
1211
1212bool PluginManager::UnregisterPlugin(
1213 MemoryHistoryCreateInstance create_callback) {
1214 return GetMemoryHistoryInstances().UnregisterPlugin(create_callback);
1215}
1216
1217MemoryHistoryCreateInstance
1218PluginManager::GetMemoryHistoryCreateCallbackAtIndex(uint32_t idx) {
1219 return GetMemoryHistoryInstances().GetCallbackAtIndex(idx);
1220}
1221
1222#pragma mark InstrumentationRuntime
1223
1224struct InstrumentationRuntimeInstance
1225 : public PluginInstance<InstrumentationRuntimeCreateInstance> {
1226 InstrumentationRuntimeInstance(
1227 llvm::StringRef name, llvm::StringRef description,
1228 CallbackType create_callback,
1229 InstrumentationRuntimeGetType get_type_callback)
1230 : PluginInstance<InstrumentationRuntimeCreateInstance>(name, description,
1231 create_callback),
1232 get_type_callback(get_type_callback) {}
1233
1234 InstrumentationRuntimeGetType get_type_callback = nullptr;
1235};
1236
1237typedef PluginInstances<InstrumentationRuntimeInstance>
1238 InstrumentationRuntimeInstances;
1239
1240static InstrumentationRuntimeInstances &GetInstrumentationRuntimeInstances() {
1241 static InstrumentationRuntimeInstances g_instances;
1242 return g_instances;
1243}
1244
1245bool PluginManager::RegisterPlugin(
1246 llvm::StringRef name, llvm::StringRef description,
1247 InstrumentationRuntimeCreateInstance create_callback,
1248 InstrumentationRuntimeGetType get_type_callback) {
1249 return GetInstrumentationRuntimeInstances().RegisterPlugin(
1250 name, description, create_callback, get_type_callback);
1251}
1252
1253bool PluginManager::UnregisterPlugin(
1254 InstrumentationRuntimeCreateInstance create_callback) {
1255 return GetInstrumentationRuntimeInstances().UnregisterPlugin(create_callback);
1256}
1257
1258InstrumentationRuntimeGetType
1259PluginManager::GetInstrumentationRuntimeGetTypeCallbackAtIndex(uint32_t idx) {
1260 const auto &instances = GetInstrumentationRuntimeInstances().GetInstances();
1261 if (idx < instances.size())
1262 return instances[idx].get_type_callback;
1263 return nullptr;
1264}
1265
1266InstrumentationRuntimeCreateInstance
1267PluginManager::GetInstrumentationRuntimeCreateCallbackAtIndex(uint32_t idx) {
1268 return GetInstrumentationRuntimeInstances().GetCallbackAtIndex(idx);
1269}
1270
1271#pragma mark TypeSystem
1272
1273struct TypeSystemInstance : public PluginInstance<TypeSystemCreateInstance> {
1274 TypeSystemInstance(llvm::StringRef name, llvm::StringRef description,
1275 CallbackType create_callback,
1276 LanguageSet supported_languages_for_types,
1277 LanguageSet supported_languages_for_expressions)
1278 : PluginInstance<TypeSystemCreateInstance>(name, description,
1279 create_callback),
1280 supported_languages_for_types(supported_languages_for_types),
1281 supported_languages_for_expressions(
1282 supported_languages_for_expressions) {}
1283
1284 LanguageSet supported_languages_for_types;
1285 LanguageSet supported_languages_for_expressions;
1286};
1287
1288typedef PluginInstances<TypeSystemInstance> TypeSystemInstances;
1289
1290static TypeSystemInstances &GetTypeSystemInstances() {
1291 static TypeSystemInstances g_instances;
1292 return g_instances;
1293}
1294
1295bool PluginManager::RegisterPlugin(
1296 llvm::StringRef name, llvm::StringRef description,
1297 TypeSystemCreateInstance create_callback,
1298 LanguageSet supported_languages_for_types,
1299 LanguageSet supported_languages_for_expressions) {
1300 return GetTypeSystemInstances().RegisterPlugin(
1
Calling 'PluginInstances::RegisterPlugin'
1301 name, description, create_callback, supported_languages_for_types,
1302 supported_languages_for_expressions);
1303}
1304
1305bool PluginManager::UnregisterPlugin(TypeSystemCreateInstance create_callback) {
1306 return GetTypeSystemInstances().UnregisterPlugin(create_callback);
1307}
1308
1309TypeSystemCreateInstance
1310PluginManager::GetTypeSystemCreateCallbackAtIndex(uint32_t idx) {
1311 return GetTypeSystemInstances().GetCallbackAtIndex(idx);
1312}
1313
1314LanguageSet PluginManager::GetAllTypeSystemSupportedLanguagesForTypes() {
1315 const auto &instances = GetTypeSystemInstances().GetInstances();
1316 LanguageSet all;
1317 for (unsigned i = 0; i < instances.size(); ++i)
1318 all.bitvector |= instances[i].supported_languages_for_types.bitvector;
1319 return all;
1320}
1321
1322LanguageSet PluginManager::GetAllTypeSystemSupportedLanguagesForExpressions() {
1323 const auto &instances = GetTypeSystemInstances().GetInstances();
1324 LanguageSet all;
1325 for (unsigned i = 0; i < instances.size(); ++i)
1326 all.bitvector |= instances[i].supported_languages_for_expressions.bitvector;
1327 return all;
1328}
1329
1330#pragma mark REPL
1331
1332struct REPLInstance : public PluginInstance<REPLCreateInstance> {
1333 REPLInstance(llvm::StringRef name, llvm::StringRef description,
1334 CallbackType create_callback, LanguageSet supported_languages)
1335 : PluginInstance<REPLCreateInstance>(name, description, create_callback),
1336 supported_languages(supported_languages) {}
1337
1338 LanguageSet supported_languages;
1339};
1340
1341typedef PluginInstances<REPLInstance> REPLInstances;
1342
1343static REPLInstances &GetREPLInstances() {
1344 static REPLInstances g_instances;
1345 return g_instances;
1346}
1347
1348bool PluginManager::RegisterPlugin(llvm::StringRef name, llvm::StringRef description,
1349 REPLCreateInstance create_callback,
1350 LanguageSet supported_languages) {
1351 return GetREPLInstances().RegisterPlugin(name, description, create_callback,
1352 supported_languages);
1353}
1354
1355bool PluginManager::UnregisterPlugin(REPLCreateInstance create_callback) {
1356 return GetREPLInstances().UnregisterPlugin(create_callback);
1357}
1358
1359REPLCreateInstance PluginManager::GetREPLCreateCallbackAtIndex(uint32_t idx) {
1360 return GetREPLInstances().GetCallbackAtIndex(idx);
1361}
1362
1363LanguageSet PluginManager::GetREPLSupportedLanguagesAtIndex(uint32_t idx) {
1364 const auto &instances = GetREPLInstances().GetInstances();
1365 return idx < instances.size() ? instances[idx].supported_languages
1366 : LanguageSet();
1367}
1368
1369LanguageSet PluginManager::GetREPLAllTypeSystemSupportedLanguages() {
1370 const auto &instances = GetREPLInstances().GetInstances();
1371 LanguageSet all;
1372 for (unsigned i = 0; i < instances.size(); ++i)
1373 all.bitvector |= instances[i].supported_languages.bitvector;
1374 return all;
1375}
1376
1377#pragma mark PluginManager
1378
1379void PluginManager::DebuggerInitialize(Debugger &debugger) {
1380 GetDynamicLoaderInstances().PerformDebuggerCallback(debugger);
1381 GetJITLoaderInstances().PerformDebuggerCallback(debugger);
1382 GetObjectFileInstances().PerformDebuggerCallback(debugger);
1383 GetPlatformInstances().PerformDebuggerCallback(debugger);
1384 GetProcessInstances().PerformDebuggerCallback(debugger);
1385 GetSymbolFileInstances().PerformDebuggerCallback(debugger);
1386 GetOperatingSystemInstances().PerformDebuggerCallback(debugger);
1387 GetStructuredDataPluginInstances().PerformDebuggerCallback(debugger);
1388 GetTracePluginInstances().PerformDebuggerCallback(debugger);
1389}
1390
1391// This is the preferred new way to register plugin specific settings. e.g.
1392// This will put a plugin's settings under e.g.
1393// "plugin.<plugin_type_name>.<plugin_type_desc>.SETTINGNAME".
1394static lldb::OptionValuePropertiesSP
1395GetDebuggerPropertyForPlugins(Debugger &debugger, ConstString plugin_type_name,
1396 ConstString plugin_type_desc, bool can_create) {
1397 lldb::OptionValuePropertiesSP parent_properties_sp(
1398 debugger.GetValueProperties());
1399 if (parent_properties_sp) {
1400 static ConstString g_property_name("plugin");
1401
1402 OptionValuePropertiesSP plugin_properties_sp =
1403 parent_properties_sp->GetSubProperty(nullptr, g_property_name);
1404 if (!plugin_properties_sp && can_create) {
1405 plugin_properties_sp =
1406 std::make_shared<OptionValueProperties>(g_property_name);
1407 parent_properties_sp->AppendProperty(
1408 g_property_name, ConstString("Settings specify to plugins."), true,
1409 plugin_properties_sp);
1410 }
1411
1412 if (plugin_properties_sp) {
1413 lldb::OptionValuePropertiesSP plugin_type_properties_sp =
1414 plugin_properties_sp->GetSubProperty(nullptr, plugin_type_name);
1415 if (!plugin_type_properties_sp && can_create) {
1416 plugin_type_properties_sp =
1417 std::make_shared<OptionValueProperties>(plugin_type_name);
1418 plugin_properties_sp->AppendProperty(plugin_type_name, plugin_type_desc,
1419 true, plugin_type_properties_sp);
1420 }
1421 return plugin_type_properties_sp;
1422 }
1423 }
1424 return lldb::OptionValuePropertiesSP();
1425}
1426
1427// This is deprecated way to register plugin specific settings. e.g.
1428// "<plugin_type_name>.plugin.<plugin_type_desc>.SETTINGNAME" and Platform
1429// generic settings would be under "platform.SETTINGNAME".
1430static lldb::OptionValuePropertiesSP GetDebuggerPropertyForPluginsOldStyle(
1431 Debugger &debugger, ConstString plugin_type_name,
1432 ConstString plugin_type_desc, bool can_create) {
1433 static ConstString g_property_name("plugin");
1434 lldb::OptionValuePropertiesSP parent_properties_sp(
1435 debugger.GetValueProperties());
1436 if (parent_properties_sp) {
1437 OptionValuePropertiesSP plugin_properties_sp =
1438 parent_properties_sp->GetSubProperty(nullptr, plugin_type_name);
1439 if (!plugin_properties_sp && can_create) {
1440 plugin_properties_sp =
1441 std::make_shared<OptionValueProperties>(plugin_type_name);
1442 parent_properties_sp->AppendProperty(plugin_type_name, plugin_type_desc,
1443 true, plugin_properties_sp);
1444 }
1445
1446 if (plugin_properties_sp) {
1447 lldb::OptionValuePropertiesSP plugin_type_properties_sp =
1448 plugin_properties_sp->GetSubProperty(nullptr, g_property_name);
1449 if (!plugin_type_properties_sp && can_create) {
1450 plugin_type_properties_sp =
1451 std::make_shared<OptionValueProperties>(g_property_name);
1452 plugin_properties_sp->AppendProperty(
1453 g_property_name, ConstString("Settings specific to plugins"), true,
1454 plugin_type_properties_sp);
1455 }
1456 return plugin_type_properties_sp;
1457 }
1458 }
1459 return lldb::OptionValuePropertiesSP();
1460}
1461
1462namespace {
1463
1464typedef lldb::OptionValuePropertiesSP
1465GetDebuggerPropertyForPluginsPtr(Debugger &, ConstString, ConstString,
1466 bool can_create);
1467}
1468
1469static lldb::OptionValuePropertiesSP
1470GetSettingForPlugin(Debugger &debugger, ConstString setting_name,
1471 ConstString plugin_type_name,
1472 GetDebuggerPropertyForPluginsPtr get_debugger_property =
1473 GetDebuggerPropertyForPlugins) {
1474 lldb::OptionValuePropertiesSP properties_sp;
1475 lldb::OptionValuePropertiesSP plugin_type_properties_sp(get_debugger_property(
1476 debugger, plugin_type_name,
1477 ConstString(), // not creating to so we don't need the description
1478 false));
1479 if (plugin_type_properties_sp)
1480 properties_sp =
1481 plugin_type_properties_sp->GetSubProperty(nullptr, setting_name);
1482 return properties_sp;
1483}
1484
1485static bool
1486CreateSettingForPlugin(Debugger &debugger, ConstString plugin_type_name,
1487 ConstString plugin_type_desc,
1488 const lldb::OptionValuePropertiesSP &properties_sp,
1489 ConstString description, bool is_global_property,
1490 GetDebuggerPropertyForPluginsPtr get_debugger_property =
1491 GetDebuggerPropertyForPlugins) {
1492 if (properties_sp) {
1493 lldb::OptionValuePropertiesSP plugin_type_properties_sp(
1494 get_debugger_property(debugger, plugin_type_name, plugin_type_desc,
1495 true));
1496 if (plugin_type_properties_sp) {
1497 plugin_type_properties_sp->AppendProperty(properties_sp->GetName(),
1498 description, is_global_property,
1499 properties_sp);
1500 return true;
1501 }
1502 }
1503 return false;
1504}
1505
1506static const char *kDynamicLoaderPluginName("dynamic-loader");
1507static const char *kPlatformPluginName("platform");
1508static const char *kProcessPluginName("process");
1509static const char *kObjectFilePluginName("object-file");
1510static const char *kSymbolFilePluginName("symbol-file");
1511static const char *kJITLoaderPluginName("jit-loader");
1512static const char *kStructuredDataPluginName("structured-data");
1513
1514lldb::OptionValuePropertiesSP
1515PluginManager::GetSettingForDynamicLoaderPlugin(Debugger &debugger,
1516 ConstString setting_name) {
1517 return GetSettingForPlugin(debugger, setting_name,
1518 ConstString(kDynamicLoaderPluginName));
1519}
1520
1521bool PluginManager::CreateSettingForDynamicLoaderPlugin(
1522 Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
1523 ConstString description, bool is_global_property) {
1524 return CreateSettingForPlugin(
1525 debugger, ConstString(kDynamicLoaderPluginName),
1526 ConstString("Settings for dynamic loader plug-ins"), properties_sp,
1527 description, is_global_property);
1528}
1529
1530lldb::OptionValuePropertiesSP
1531PluginManager::GetSettingForPlatformPlugin(Debugger &debugger,
1532 ConstString setting_name) {
1533 return GetSettingForPlugin(debugger, setting_name,
1534 ConstString(kPlatformPluginName),
1535 GetDebuggerPropertyForPluginsOldStyle);
1536}
1537
1538bool PluginManager::CreateSettingForPlatformPlugin(
1539 Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
1540 ConstString description, bool is_global_property) {
1541 return CreateSettingForPlugin(debugger, ConstString(kPlatformPluginName),
1542 ConstString("Settings for platform plug-ins"),
1543 properties_sp, description, is_global_property,
1544 GetDebuggerPropertyForPluginsOldStyle);
1545}
1546
1547lldb::OptionValuePropertiesSP
1548PluginManager::GetSettingForProcessPlugin(Debugger &debugger,
1549 ConstString setting_name) {
1550 return GetSettingForPlugin(debugger, setting_name,
1551 ConstString(kProcessPluginName));
1552}
1553
1554bool PluginManager::CreateSettingForProcessPlugin(
1555 Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
1556 ConstString description, bool is_global_property) {
1557 return CreateSettingForPlugin(debugger, ConstString(kProcessPluginName),
1558 ConstString("Settings for process plug-ins"),
1559 properties_sp, description, is_global_property);
1560}
1561
1562lldb::OptionValuePropertiesSP
1563PluginManager::GetSettingForObjectFilePlugin(Debugger &debugger,
1564 ConstString setting_name) {
1565 return GetSettingForPlugin(debugger, setting_name,
1566 ConstString(kObjectFilePluginName));
1567}
1568
1569bool PluginManager::CreateSettingForObjectFilePlugin(
1570 Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
1571 ConstString description, bool is_global_property) {
1572 return CreateSettingForPlugin(
1573 debugger, ConstString(kObjectFilePluginName),
1574 ConstString("Settings for object file plug-ins"), properties_sp,
1575 description, is_global_property);
1576}
1577
1578lldb::OptionValuePropertiesSP
1579PluginManager::GetSettingForSymbolFilePlugin(Debugger &debugger,
1580 ConstString setting_name) {
1581 return GetSettingForPlugin(debugger, setting_name,
1582 ConstString(kSymbolFilePluginName));
1583}
1584
1585bool PluginManager::CreateSettingForSymbolFilePlugin(
1586 Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
1587 ConstString description, bool is_global_property) {
1588 return CreateSettingForPlugin(
1589 debugger, ConstString(kSymbolFilePluginName),
1590 ConstString("Settings for symbol file plug-ins"), properties_sp,
1591 description, is_global_property);
1592}
1593
1594lldb::OptionValuePropertiesSP
1595PluginManager::GetSettingForJITLoaderPlugin(Debugger &debugger,
1596 ConstString setting_name) {
1597 return GetSettingForPlugin(debugger, setting_name,
1598 ConstString(kJITLoaderPluginName));
1599}
1600
1601bool PluginManager::CreateSettingForJITLoaderPlugin(
1602 Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
1603 ConstString description, bool is_global_property) {
1604 return CreateSettingForPlugin(debugger, ConstString(kJITLoaderPluginName),
1605 ConstString("Settings for JIT loader plug-ins"),
1606 properties_sp, description, is_global_property);
1607}
1608
1609static const char *kOperatingSystemPluginName("os");
1610
1611lldb::OptionValuePropertiesSP
1612PluginManager::GetSettingForOperatingSystemPlugin(Debugger &debugger,
1613 ConstString setting_name) {
1614 lldb::OptionValuePropertiesSP properties_sp;
1615 lldb::OptionValuePropertiesSP plugin_type_properties_sp(
1616 GetDebuggerPropertyForPlugins(
1617 debugger, ConstString(kOperatingSystemPluginName),
1618 ConstString(), // not creating to so we don't need the description
1619 false));
1620 if (plugin_type_properties_sp)
1621 properties_sp =
1622 plugin_type_properties_sp->GetSubProperty(nullptr, setting_name);
1623 return properties_sp;
1624}
1625
1626bool PluginManager::CreateSettingForOperatingSystemPlugin(
1627 Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
1628 ConstString description, bool is_global_property) {
1629 if (properties_sp) {
1630 lldb::OptionValuePropertiesSP plugin_type_properties_sp(
1631 GetDebuggerPropertyForPlugins(
1632 debugger, ConstString(kOperatingSystemPluginName),
1633 ConstString("Settings for operating system plug-ins"), true));
1634 if (plugin_type_properties_sp) {
1635 plugin_type_properties_sp->AppendProperty(properties_sp->GetName(),
1636 description, is_global_property,
1637 properties_sp);
1638 return true;
1639 }
1640 }
1641 return false;
1642}
1643
1644lldb::OptionValuePropertiesSP
1645PluginManager::GetSettingForStructuredDataPlugin(Debugger &debugger,
1646 ConstString setting_name) {
1647 return GetSettingForPlugin(debugger, setting_name,
1648 ConstString(kStructuredDataPluginName));
1649}
1650
1651bool PluginManager::CreateSettingForStructuredDataPlugin(
1652 Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp,
1653 ConstString description, bool is_global_property) {
1654 return CreateSettingForPlugin(
1655 debugger, ConstString(kStructuredDataPluginName),
1656 ConstString("Settings for structured data plug-ins"), properties_sp,
1657 description, is_global_property);
1658}

/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/lldb/include/lldb/Symbol/TypeSystem.h

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 <map>
14#include <mutex>
15#include <string>
16
17#include "llvm/ADT/APFloat.h"
18#include "llvm/ADT/APSInt.h"
19#include "llvm/ADT/SmallBitVector.h"
20#include "llvm/Support/Casting.h"
21#include "llvm/Support/Error.h"
22
23#include "lldb/Core/PluginInterface.h"
24#include "lldb/Expression/Expression.h"
25#include "lldb/Symbol/CompilerDecl.h"
26#include "lldb/Symbol/CompilerDeclContext.h"
27#include "lldb/lldb-private.h"
28
29class DWARFDIE;
30class DWARFASTParser;
31class PDBASTParser;
32
33namespace lldb_private {
34
35/// A SmallBitVector that represents a set of source languages (\p
36/// lldb::LanguageType). Each lldb::LanguageType is represented by
37/// the bit with the position of its enumerator. The largest
38/// LanguageType is < 64, so this is space-efficient and on 64-bit
39/// architectures a LanguageSet can be completely stack-allocated.
40struct LanguageSet {
41 llvm::SmallBitVector bitvector;
42 LanguageSet();
43
44 /// If the set contains a single language only, return it.
45 llvm::Optional<lldb::LanguageType> GetSingularLanguage();
46 void Insert(lldb::LanguageType language);
47 bool Empty() const;
48 size_t Size() const;
49 bool operator[](unsigned i) const;
50};
51
52/// Interface for representing a type system.
53///
54/// Implemented by language plugins to define the type system for a given
55/// language.
56///
57/// This interface extensively used opaque pointers to prevent that generic
58/// LLDB code has dependencies on language plugins. The type and semantics of
59/// these opaque pointers are defined by the TypeSystem implementation inside
60/// the respective language plugin. Opaque pointers from one TypeSystem
61/// instance should never be passed to a different TypeSystem instance (even
62/// when the language plugin for both TypeSystem instances is the same).
63///
64/// Most of the functions in this class should not be called directly but only
65/// called by their respective counterparts in CompilerType, CompilerDecl and
66/// CompilerDeclContext.
67///
68/// \see lldb_private::CompilerType
69/// \see lldb_private::CompilerDecl
70/// \see lldb_private::CompilerDeclContext
71class TypeSystem : public PluginInterface {
72public:
73 // Constructors and Destructors
74 ~TypeSystem() override;
75
76 // LLVM RTTI support
77 virtual bool isA(const void *ClassID) const = 0;
78
79 static lldb::TypeSystemSP CreateInstance(lldb::LanguageType language,
80 Module *module);
81
82 static lldb::TypeSystemSP CreateInstance(lldb::LanguageType language,
83 Target *target);
84
85 // Free up any resources associated with this TypeSystem. Done before
86 // removing all the TypeSystems from the TypeSystemMap.
87 virtual void Finalize() {}
88
89 virtual DWARFASTParser *GetDWARFParser() { return nullptr; }
90 virtual PDBASTParser *GetPDBParser() { return nullptr; }
91
92 virtual SymbolFile *GetSymbolFile() const { return m_sym_file; }
93
94 virtual void SetSymbolFile(SymbolFile *sym_file) { m_sym_file = sym_file; }
95
96 // CompilerDecl functions
97 virtual ConstString DeclGetName(void *opaque_decl) = 0;
98
99 virtual ConstString DeclGetMangledName(void *opaque_decl);
100
101 virtual CompilerDeclContext DeclGetDeclContext(void *opaque_decl);
102
103 virtual CompilerType DeclGetFunctionReturnType(void *opaque_decl);
104
105 virtual size_t DeclGetFunctionNumArguments(void *opaque_decl);
106
107 virtual CompilerType DeclGetFunctionArgumentType(void *opaque_decl,
108 size_t arg_idx);
109
110 virtual CompilerType GetTypeForDecl(void *opaque_decl) = 0;
111
112 // CompilerDeclContext functions
113
114 virtual std::vector<CompilerDecl>
115 DeclContextFindDeclByName(void *opaque_decl_ctx, ConstString name,
116 const bool ignore_imported_decls);
117
118 virtual ConstString DeclContextGetName(void *opaque_decl_ctx) = 0;
119
120 virtual ConstString
121 DeclContextGetScopeQualifiedName(void *opaque_decl_ctx) = 0;
122
123 virtual bool DeclContextIsClassMethod(
124 void *opaque_decl_ctx, lldb::LanguageType *language_ptr,
125 bool *is_instance_method_ptr, ConstString *language_object_name_ptr) = 0;
126
127 virtual bool DeclContextIsContainedInLookup(void *opaque_decl_ctx,
128 void *other_opaque_decl_ctx) = 0;
129
130 // Tests
131#ifndef NDEBUG
132 /// Verify the integrity of the type to catch CompilerTypes that mix
133 /// and match invalid TypeSystem/Opaque type pairs.
134 virtual bool Verify(lldb::opaque_compiler_type_t type) = 0;
135#endif
136
137 virtual bool IsArrayType(lldb::opaque_compiler_type_t type,
138 CompilerType *element_type, uint64_t *size,
139 bool *is_incomplete) = 0;
140
141 virtual bool IsAggregateType(lldb::opaque_compiler_type_t type) = 0;
142
143 virtual bool IsAnonymousType(lldb::opaque_compiler_type_t type);
144
145 virtual bool IsCharType(lldb::opaque_compiler_type_t type) = 0;
146
147 virtual bool IsCompleteType(lldb::opaque_compiler_type_t type) = 0;
148
149 virtual bool IsDefined(lldb::opaque_compiler_type_t type) = 0;
150
151 virtual bool IsFloatingPointType(lldb::opaque_compiler_type_t type,
152 uint32_t &count, bool &is_complex) = 0;
153
154 virtual bool IsFunctionType(lldb::opaque_compiler_type_t type) = 0;
155
156 virtual size_t
157 GetNumberOfFunctionArguments(lldb::opaque_compiler_type_t type) = 0;
158
159 virtual CompilerType
160 GetFunctionArgumentAtIndex(lldb::opaque_compiler_type_t type,
161 const size_t index) = 0;
162
163 virtual bool IsFunctionPointerType(lldb::opaque_compiler_type_t type) = 0;
164
165 virtual bool IsBlockPointerType(lldb::opaque_compiler_type_t type,
166 CompilerType *function_pointer_type_ptr) = 0;
167
168 virtual bool IsIntegerType(lldb::opaque_compiler_type_t type,
169 bool &is_signed) = 0;
170
171 virtual bool IsEnumerationType(lldb::opaque_compiler_type_t type,
172 bool &is_signed) {
173 is_signed = false;
174 return false;
175 }
176
177 virtual bool IsScopedEnumerationType(lldb::opaque_compiler_type_t type) = 0;
178
179 virtual bool IsPossibleDynamicType(lldb::opaque_compiler_type_t type,
180 CompilerType *target_type, // Can pass NULL
181 bool check_cplusplus, bool check_objc) = 0;
182
183 virtual bool IsPointerType(lldb::opaque_compiler_type_t type,
184 CompilerType *pointee_type) = 0;
185
186 virtual bool IsScalarType(lldb::opaque_compiler_type_t type) = 0;
187
188 virtual bool IsVoidType(lldb::opaque_compiler_type_t type) = 0;
189
190 virtual bool CanPassInRegisters(const CompilerType &type) = 0;
191
192 // TypeSystems can support more than one language
193 virtual bool SupportsLanguage(lldb::LanguageType language) = 0;
194
195 // Type Completion
196
197 virtual bool GetCompleteType(lldb::opaque_compiler_type_t type) = 0;
198
199 // AST related queries
200
201 virtual uint32_t GetPointerByteSize() = 0;
202
203 // Accessors
204
205 virtual ConstString GetTypeName(lldb::opaque_compiler_type_t type) = 0;
206
207 virtual ConstString GetDisplayTypeName(lldb::opaque_compiler_type_t type) = 0;
208
209 virtual uint32_t
210 GetTypeInfo(lldb::opaque_compiler_type_t type,
211 CompilerType *pointee_or_element_compiler_type) = 0;
212
213 virtual lldb::LanguageType
214 GetMinimumLanguage(lldb::opaque_compiler_type_t type) = 0;
215
216 virtual lldb::TypeClass GetTypeClass(lldb::opaque_compiler_type_t type) = 0;
217
218 // Creating related types
219
220 virtual CompilerType
221 GetArrayElementType(lldb::opaque_compiler_type_t type,
222 ExecutionContextScope *exe_scope) = 0;
223
224 virtual CompilerType GetArrayType(lldb::opaque_compiler_type_t type,
225 uint64_t size);
226
227 virtual CompilerType GetCanonicalType(lldb::opaque_compiler_type_t type) = 0;
228
229 virtual CompilerType
230 GetEnumerationIntegerType(lldb::opaque_compiler_type_t type) = 0;
231
232 // Returns -1 if this isn't a function of if the function doesn't have a
233 // prototype Returns a value >= 0 if there is a prototype.
234 virtual int GetFunctionArgumentCount(lldb::opaque_compiler_type_t type) = 0;
235
236 virtual CompilerType
237 GetFunctionArgumentTypeAtIndex(lldb::opaque_compiler_type_t type,
238 size_t idx) = 0;
239
240 virtual CompilerType
241 GetFunctionReturnType(lldb::opaque_compiler_type_t type) = 0;
242
243 virtual size_t GetNumMemberFunctions(lldb::opaque_compiler_type_t type) = 0;
244
245 virtual TypeMemberFunctionImpl
246 GetMemberFunctionAtIndex(lldb::opaque_compiler_type_t type, size_t idx) = 0;
247
248 virtual CompilerType GetPointeeType(lldb::opaque_compiler_type_t type) = 0;
249
250 virtual CompilerType GetPointerType(lldb::opaque_compiler_type_t type) = 0;
251
252 virtual CompilerType
253 GetLValueReferenceType(lldb::opaque_compiler_type_t type);
254
255 virtual CompilerType
256 GetRValueReferenceType(lldb::opaque_compiler_type_t type);
257
258 virtual CompilerType GetAtomicType(lldb::opaque_compiler_type_t type);
259
260 virtual CompilerType AddConstModifier(lldb::opaque_compiler_type_t type);
261
262 virtual CompilerType AddVolatileModifier(lldb::opaque_compiler_type_t type);
263
264 virtual CompilerType AddRestrictModifier(lldb::opaque_compiler_type_t type);
265
266 /// \param opaque_payload The m_payload field of Type, which may
267 /// carry TypeSystem-specific extra information.
268 virtual CompilerType CreateTypedef(lldb::opaque_compiler_type_t type,
269 const char *name,
270 const CompilerDeclContext &decl_ctx,
271 uint32_t opaque_payload);
272
273 // Exploring the type
274
275 virtual const llvm::fltSemantics &GetFloatTypeSemantics(size_t byte_size) = 0;
276
277 virtual llvm::Optional<uint64_t>
278 GetBitSize(lldb::opaque_compiler_type_t type,
279 ExecutionContextScope *exe_scope) = 0;
280
281 virtual lldb::Encoding GetEncoding(lldb::opaque_compiler_type_t type,
282 uint64_t &count) = 0;
283
284 virtual lldb::Format GetFormat(lldb::opaque_compiler_type_t type) = 0;
285
286 virtual uint32_t GetNumChildren(lldb::opaque_compiler_type_t type,
287 bool omit_empty_base_classes,
288 const ExecutionContext *exe_ctx) = 0;
289
290 virtual CompilerType GetBuiltinTypeByName(ConstString name);
291
292 virtual lldb::BasicType
293 GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) = 0;
294
295 virtual void ForEachEnumerator(
296 lldb::opaque_compiler_type_t type,
297 std::function<bool(const CompilerType &integer_type,
298 ConstString name,
299 const llvm::APSInt &value)> const &callback) {}
300
301 virtual uint32_t GetNumFields(lldb::opaque_compiler_type_t type) = 0;
302
303 virtual CompilerType GetFieldAtIndex(lldb::opaque_compiler_type_t type,
304 size_t idx, std::string &name,
305 uint64_t *bit_offset_ptr,
306 uint32_t *bitfield_bit_size_ptr,
307 bool *is_bitfield_ptr) = 0;
308
309 virtual uint32_t
310 GetNumDirectBaseClasses(lldb::opaque_compiler_type_t type) = 0;
311
312 virtual uint32_t
313 GetNumVirtualBaseClasses(lldb::opaque_compiler_type_t type) = 0;
314
315 virtual CompilerType
316 GetDirectBaseClassAtIndex(lldb::opaque_compiler_type_t type, size_t idx,
317 uint32_t *bit_offset_ptr) = 0;
318
319 virtual CompilerType
320 GetVirtualBaseClassAtIndex(lldb::opaque_compiler_type_t type, size_t idx,
321 uint32_t *bit_offset_ptr) = 0;
322
323 virtual CompilerType GetChildCompilerTypeAtIndex(
324 lldb::opaque_compiler_type_t type, ExecutionContext *exe_ctx, size_t idx,
325 bool transparent_pointers, bool omit_empty_base_classes,
326 bool ignore_array_bounds, std::string &child_name,
327 uint32_t &child_byte_size, int32_t &child_byte_offset,
328 uint32_t &child_bitfield_bit_size, uint32_t &child_bitfield_bit_offset,
329 bool &child_is_base_class, bool &child_is_deref_of_parent,
330 ValueObject *valobj, uint64_t &language_flags) = 0;
331
332 // Lookup a child given a name. This function will match base class names and
333 // member member names in "clang_type" only, not descendants.
334 virtual uint32_t GetIndexOfChildWithName(lldb::opaque_compiler_type_t type,
335 const char *name,
336 bool omit_empty_base_classes) = 0;
337
338 // Lookup a child member given a name. This function will match member names
339 // only and will descend into "clang_type" children in search for the first
340 // member in this class, or any base class that matches "name".
341 // TODO: Return all matches for a given name by returning a
342 // vector<vector<uint32_t>>
343 // so we catch all names that match a given child name, not just the first.
344 virtual size_t
345 GetIndexOfChildMemberWithName(lldb::opaque_compiler_type_t type,
346 const char *name, bool omit_empty_base_classes,
347 std::vector<uint32_t> &child_indexes) = 0;
348
349 virtual size_t GetNumTemplateArguments(lldb::opaque_compiler_type_t type,
350 bool expand_pack);
351
352 virtual lldb::TemplateArgumentKind
353 GetTemplateArgumentKind(lldb::opaque_compiler_type_t type, size_t idx,
354 bool expand_pack);
355 virtual CompilerType
356 GetTypeTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx,
357 bool expand_pack);
358 virtual llvm::Optional<CompilerType::IntegralTemplateArgument>
359 GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx,
360 bool expand_pack);
361
362 // Dumping types
363
364#ifndef NDEBUG
365 /// Convenience LLVM-style dump method for use in the debugger only.
366 LLVM_DUMP_METHOD__attribute__((noinline)) __attribute__((__used__)) virtual void
367 dump(lldb::opaque_compiler_type_t type) const = 0;
368#endif
369
370 virtual void DumpValue(lldb::opaque_compiler_type_t type,
371 ExecutionContext *exe_ctx, Stream *s,
372 lldb::Format format, const DataExtractor &data,
373 lldb::offset_t data_offset, size_t data_byte_size,
374 uint32_t bitfield_bit_size,
375 uint32_t bitfield_bit_offset, bool show_types,
376 bool show_summary, bool verbose, uint32_t depth) = 0;
377
378 virtual bool DumpTypeValue(lldb::opaque_compiler_type_t type, Stream *s,
379 lldb::Format format, const DataExtractor &data,
380 lldb::offset_t data_offset, size_t data_byte_size,
381 uint32_t bitfield_bit_size,
382 uint32_t bitfield_bit_offset,
383 ExecutionContextScope *exe_scope) = 0;
384
385 /// Dump the type to stdout.
386 virtual void DumpTypeDescription(
387 lldb::opaque_compiler_type_t type,
388 lldb::DescriptionLevel level = lldb::eDescriptionLevelFull) = 0;
389
390 /// Print a description of the type to a stream. The exact implementation
391 /// varies, but the expectation is that eDescriptionLevelFull returns a
392 /// source-like representation of the type, whereas eDescriptionLevelVerbose
393 /// does a dump of the underlying AST if applicable.
394 virtual void DumpTypeDescription(
395 lldb::opaque_compiler_type_t type, Stream *s,
396 lldb::DescriptionLevel level = lldb::eDescriptionLevelFull) = 0;
397
398 /// Dump a textual representation of the internal TypeSystem state to the
399 /// given stream.
400 ///
401 /// This should not modify the state of the TypeSystem if possible.
402 virtual void Dump(llvm::raw_ostream &output) = 0;
403
404 // TODO: These methods appear unused. Should they be removed?
405
406 virtual bool IsRuntimeGeneratedType(lldb::opaque_compiler_type_t type) = 0;
407
408 virtual void DumpSummary(lldb::opaque_compiler_type_t type,
409 ExecutionContext *exe_ctx, Stream *s,
410 const DataExtractor &data,
411 lldb::offset_t data_offset,
412 size_t data_byte_size) = 0;
413
414 // TODO: Determine if these methods should move to TypeSystemClang.
415
416 virtual bool IsPointerOrReferenceType(lldb::opaque_compiler_type_t type,
417 CompilerType *pointee_type) = 0;
418
419 virtual unsigned GetTypeQualifiers(lldb::opaque_compiler_type_t type) = 0;
420
421 virtual bool IsCStringType(lldb::opaque_compiler_type_t type,
422 uint32_t &length) = 0;
423
424 virtual llvm::Optional<size_t>
425 GetTypeBitAlign(lldb::opaque_compiler_type_t type,
426 ExecutionContextScope *exe_scope) = 0;
427
428 virtual CompilerType GetBasicTypeFromAST(lldb::BasicType basic_type) = 0;
429
430 virtual CompilerType
431 GetBuiltinTypeForEncodingAndBitSize(lldb::Encoding encoding,
432 size_t bit_size) = 0;
433
434 virtual bool IsBeingDefined(lldb::opaque_compiler_type_t type) = 0;
435
436 virtual bool IsConst(lldb::opaque_compiler_type_t type) = 0;
437
438 virtual uint32_t IsHomogeneousAggregate(lldb::opaque_compiler_type_t type,
439 CompilerType *base_type_ptr) = 0;
440
441 virtual bool IsPolymorphicClass(lldb::opaque_compiler_type_t type) = 0;
442
443 virtual bool IsTypedefType(lldb::opaque_compiler_type_t type) = 0;
444
445 // If the current object represents a typedef type, get the underlying type
446 virtual CompilerType GetTypedefedType(lldb::opaque_compiler_type_t type) = 0;
447
448 virtual bool IsVectorType(lldb::opaque_compiler_type_t type,
449 CompilerType *element_type, uint64_t *size) = 0;
450
451 virtual CompilerType
452 GetFullyUnqualifiedType(lldb::opaque_compiler_type_t type) = 0;
453
454 virtual CompilerType
455 GetNonReferenceType(lldb::opaque_compiler_type_t type) = 0;
456
457 virtual bool IsReferenceType(lldb::opaque_compiler_type_t type,
458 CompilerType *pointee_type, bool *is_rvalue) = 0;
459
460 virtual bool
461 ShouldTreatScalarValueAsAddress(lldb::opaque_compiler_type_t type) {
462 return IsPointerOrReferenceType(type, nullptr);
463 }
464
465 virtual UserExpression *
466 GetUserExpression(llvm::StringRef expr, llvm::StringRef prefix,
467 lldb::LanguageType language,
468 Expression::ResultType desired_type,
469 const EvaluateExpressionOptions &options,
470 ValueObject *ctx_obj) {
471 return nullptr;
472 }
473
474 virtual FunctionCaller *GetFunctionCaller(const CompilerType &return_type,
475 const Address &function_address,
476 const ValueList &arg_value_list,
477 const char *name) {
478 return nullptr;
479 }
480
481 virtual std::unique_ptr<UtilityFunction>
482 CreateUtilityFunction(std::string text, std::string name);
483
484 virtual PersistentExpressionState *GetPersistentExpressionState() {
485 return nullptr;
486 }
487
488 virtual CompilerType GetTypeForFormatters(void *type);
489
490 virtual LazyBool ShouldPrintAsOneLiner(void *type, ValueObject *valobj);
491
492 // Type systems can have types that are placeholder types, which are meant to
493 // indicate the presence of a type, but offer no actual information about
494 // said types, and leave the burden of actually figuring type information out
495 // to dynamic type resolution. For instance a language with a generics
496 // system, can use placeholder types to indicate "type argument goes here",
497 // without promising uniqueness of the placeholder, nor attaching any
498 // actually idenfiable information to said placeholder. This API allows type
499 // systems to tell LLDB when such a type has been encountered In response,
500 // the debugger can react by not using this type as a cache entry in any
501 // type-specific way For instance, LLDB will currently not cache any
502 // formatters that are discovered on such a type as attributable to the
503 // meaningless type itself, instead preferring to use the dynamic type
504 virtual bool IsMeaninglessWithoutDynamicResolution(void *type);
505
506protected:
507 SymbolFile *m_sym_file = nullptr;
508};
509
510class TypeSystemMap {
511public:
512 TypeSystemMap();
513 ~TypeSystemMap();
514
515 // Clear calls Finalize on all the TypeSystems managed by this map, and then
516 // empties the map.
517 void Clear();
518
519 // Iterate through all of the type systems that are created. Return true from
520 // callback to keep iterating, false to stop iterating.
521 void ForEach(std::function<bool(TypeSystem *)> const &callback);
522
523 llvm::Expected<TypeSystem &>
524 GetTypeSystemForLanguage(lldb::LanguageType language, Module *module,
525 bool can_create);
526
527 llvm::Expected<TypeSystem &>
528 GetTypeSystemForLanguage(lldb::LanguageType language, Target *target,
529 bool can_create);
530
531protected:
532 typedef std::map<lldb::LanguageType, lldb::TypeSystemSP> collection;
533 mutable std::mutex m_mutex; ///< A mutex to keep this object happy in
534 ///multi-threaded environments.
535 collection m_map;
536 bool m_clear_in_progress = false;
537
538private:
539 typedef llvm::function_ref<lldb::TypeSystemSP()> CreateCallback;
540 /// Finds the type system for the given language. If no type system could be
541 /// found for a language and a CreateCallback was provided, the value returned
542 /// by the callback will be treated as the TypeSystem for the language.
543 ///
544 /// \param language The language for which the type system should be found.
545 /// \param create_callback A callback that will be called if no previously
546 /// created TypeSystem that fits the given language
547 /// could found. Can be omitted if a non-existent
548 /// type system should be treated as an error instead.
549 /// \return The found type system or an error.
550 llvm::Expected<TypeSystem &> GetTypeSystemForLanguage(
551 lldb::LanguageType language,
552 llvm::Optional<CreateCallback> create_callback = llvm::None);
553};
554
555} // namespace lldb_private
556
557#endif // LLDB_SYMBOL_TYPESYSTEM_H

/build/llvm-toolchain-snapshot-16~++20220904122748+c444af1c20b3/llvm/include/llvm/ADT/SmallBitVector.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
28namespace 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.
35class 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
63public:
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
94private:
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__))
;
26
Assuming the condition is true
27
'?' condition is true
97 return reinterpret_cast<BitVector *>(X);
28
Use of memory after it is freed
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
142public:
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())
8
Assuming the condition is false
9
Taking false branch
158 X = RHS.X;
159 else
160 switchToLarge(new BitVector(*RHS.getPointer()));
10
Memory is allocated
161 }
162
163 SmallBitVector(SmallBitVector &&RHS) : X(RHS.X) {
164 RHS.X = 1;
165 }
166
167 ~SmallBitVector() {
168 if (!isSmall())
15
Assuming the condition is true
16
Taking true branch
23
Assuming the condition is true
24
Taking true branch
169 delete getPointer();
17
Memory is released
25
Calling 'SmallBitVector::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 countPopulation(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 countTrailingZeros(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 - countLeadingZeros(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 countTrailingOnes(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 - countLeadingOnes(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 countTrailingZeros(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 countTrailingOnes(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 - countLeadingZeros(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 makeArrayRef(Store);
691 }
692
693private:
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
709inline SmallBitVector
710operator&(const SmallBitVector &LHS, const SmallBitVector &RHS) {
711 SmallBitVector Result(LHS);
712 Result &= RHS;
713 return Result;
714}
715
716inline SmallBitVector
717operator|(const SmallBitVector &LHS, const SmallBitVector &RHS) {
718 SmallBitVector Result(LHS);
719 Result |= RHS;
720 return Result;
721}
722
723inline SmallBitVector
724operator^(const SmallBitVector &LHS, const SmallBitVector &RHS) {
725 SmallBitVector Result(LHS);
726 Result ^= RHS;
727 return Result;
728}
729
730template <> 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
751namespace std {
752
753/// Implement std::swap in terms of BitVector swap.
754inline void
755swap(llvm::SmallBitVector &LHS, llvm::SmallBitVector &RHS) {
756 LHS.swap(RHS);
757}
758
759} // end namespace std
760
761#endif // LLVM_ADT_SMALLBITVECTOR_H