1 //===-- ClangPersistentVariables.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 "ClangPersistentVariables.h"
10 #include "ClangASTImporter.h"
11 #include "ClangModulesDeclVendor.h"
12 
13 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
14 #include "lldb/Core/Value.h"
15 #include "lldb/Target/Target.h"
16 #include "lldb/Utility/DataExtractor.h"
17 #include "lldb/Utility/Log.h"
18 #include "lldb/Utility/StreamString.h"
19 
20 #include "clang/AST/Decl.h"
21 
22 #include "llvm/ADT/StringMap.h"
23 #include <optional>
24 #include <memory>
25 
26 using namespace lldb;
27 using namespace lldb_private;
28 
29 char ClangPersistentVariables::ID;
30 
31 ClangPersistentVariables::ClangPersistentVariables(
32     std::shared_ptr<Target> target_sp)
33     : m_target_sp(target_sp) {}
34 
35 ExpressionVariableSP ClangPersistentVariables::CreatePersistentVariable(
36     const lldb::ValueObjectSP &valobj_sp) {
37   return AddNewlyConstructedVariable(new ClangExpressionVariable(valobj_sp));
38 }
39 
40 ExpressionVariableSP ClangPersistentVariables::CreatePersistentVariable(
41     ExecutionContextScope *exe_scope, ConstString name,
42     const CompilerType &compiler_type, lldb::ByteOrder byte_order,
43     uint32_t addr_byte_size) {
44   return AddNewlyConstructedVariable(new ClangExpressionVariable(
45       exe_scope, name, compiler_type, byte_order, addr_byte_size));
46 }
47 
48 void ClangPersistentVariables::RemovePersistentVariable(
49     lldb::ExpressionVariableSP variable) {
50   RemoveVariable(variable);
51 
52   // Check if the removed variable was the last one that was created. If yes,
53   // reuse the variable id for the next variable.
54 
55   // Nothing to do if we have not assigned a variable id so far.
56   if (m_next_persistent_variable_id == 0)
57     return;
58 
59   llvm::StringRef name = variable->GetName().GetStringRef();
60   // Remove the prefix from the variable that only the indes is left.
61   if (!name.consume_front(GetPersistentVariablePrefix(false)))
62     return;
63 
64   // Check if the variable contained a variable id.
65   uint32_t variable_id;
66   if (name.getAsInteger(10, variable_id))
67     return;
68   // If it's the most recent variable id that was assigned, make sure that this
69   // variable id will be used for the next persistent variable.
70   if (variable_id == m_next_persistent_variable_id - 1)
71     m_next_persistent_variable_id--;
72 }
73 
74 std::optional<CompilerType>
75 ClangPersistentVariables::GetCompilerTypeFromPersistentDecl(
76     ConstString type_name) {
77   PersistentDecl p = m_persistent_decls.lookup(type_name.GetCString());
78 
79   if (p.m_decl == nullptr)
80     return std::nullopt;
81 
82   if (clang::TypeDecl *tdecl = llvm::dyn_cast<clang::TypeDecl>(p.m_decl)) {
83     opaque_compiler_type_t t = static_cast<opaque_compiler_type_t>(
84         const_cast<clang::Type *>(tdecl->getTypeForDecl()));
85     return CompilerType(p.m_context, t);
86   }
87   return std::nullopt;
88 }
89 
90 void ClangPersistentVariables::RegisterPersistentDecl(
91     ConstString name, clang::NamedDecl *decl,
92     std::shared_ptr<TypeSystemClang> ctx) {
93   PersistentDecl p = {decl, ctx};
94   m_persistent_decls.insert(std::make_pair(name.GetCString(), p));
95 
96   if (clang::EnumDecl *enum_decl = llvm::dyn_cast<clang::EnumDecl>(decl)) {
97     for (clang::EnumConstantDecl *enumerator_decl : enum_decl->enumerators()) {
98       p = {enumerator_decl, ctx};
99       m_persistent_decls.insert(std::make_pair(
100           ConstString(enumerator_decl->getNameAsString()).GetCString(), p));
101     }
102   }
103 }
104 
105 clang::NamedDecl *
106 ClangPersistentVariables::GetPersistentDecl(ConstString name) {
107   return m_persistent_decls.lookup(name.GetCString()).m_decl;
108 }
109 
110 std::shared_ptr<ClangASTImporter>
111 ClangPersistentVariables::GetClangASTImporter() {
112   if (!m_ast_importer_sp) {
113     m_ast_importer_sp = std::make_shared<ClangASTImporter>();
114   }
115   return m_ast_importer_sp;
116 }
117 
118 std::shared_ptr<ClangModulesDeclVendor>
119 ClangPersistentVariables::GetClangModulesDeclVendor() {
120   if (!m_modules_decl_vendor_sp) {
121     m_modules_decl_vendor_sp.reset(
122         ClangModulesDeclVendor::Create(*m_target_sp));
123   }
124   return m_modules_decl_vendor_sp;
125 }
126 
127 ConstString
128 ClangPersistentVariables::GetNextPersistentVariableName(bool is_error) {
129   llvm::SmallString<64> name;
130   {
131     llvm::raw_svector_ostream os(name);
132     os << GetPersistentVariablePrefix(is_error)
133        << m_next_persistent_variable_id++;
134   }
135   return ConstString(name);
136 }
137