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