180814287SRaphael Isemann //===-- ClangPersistentVariables.cpp --------------------------------------===//
24dbb271fSSean Callanan //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64dbb271fSSean Callanan //
74dbb271fSSean Callanan //===----------------------------------------------------------------------===//
84dbb271fSSean Callanan 
94dbb271fSSean Callanan #include "ClangPersistentVariables.h"
108be30215SAlex Langford #include "ClangASTImporter.h"
11*4c0b0de9SAlex Langford #include "ClangModulesDeclVendor.h"
124dbb271fSSean Callanan 
138be30215SAlex Langford #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
144dbb271fSSean Callanan #include "lldb/Core/Value.h"
155435f780SAdrian Prantl #include "lldb/Target/Target.h"
16666cc0b2SZachary Turner #include "lldb/Utility/DataExtractor.h"
176f9e6901SZachary Turner #include "lldb/Utility/Log.h"
18bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h"
194dbb271fSSean Callanan 
20b3a36df3SSean Callanan #include "clang/AST/Decl.h"
21b3a36df3SSean Callanan 
224dbb271fSSean Callanan #include "llvm/ADT/StringMap.h"
234dbb271fSSean Callanan 
244dbb271fSSean Callanan using namespace lldb;
254dbb271fSSean Callanan using namespace lldb_private;
264dbb271fSSean Callanan 
ClangPersistentVariables(std::shared_ptr<Target> target_sp)27*4c0b0de9SAlex Langford ClangPersistentVariables::ClangPersistentVariables(
28*4c0b0de9SAlex Langford     std::shared_ptr<Target> target_sp)
29*4c0b0de9SAlex Langford     : lldb_private::PersistentExpressionState(LLVMCastKind::eKindClang),
30*4c0b0de9SAlex Langford       m_target_sp(target_sp) {}
314dbb271fSSean Callanan 
CreatePersistentVariable(const lldb::ValueObjectSP & valobj_sp)32b9c1b51eSKate Stone ExpressionVariableSP ClangPersistentVariables::CreatePersistentVariable(
33b9c1b51eSKate Stone     const lldb::ValueObjectSP &valobj_sp) {
349301ec11SSean Callanan   return AddNewlyConstructedVariable(new ClangExpressionVariable(valobj_sp));
354dbb271fSSean Callanan }
364dbb271fSSean Callanan 
CreatePersistentVariable(ExecutionContextScope * exe_scope,ConstString name,const CompilerType & compiler_type,lldb::ByteOrder byte_order,uint32_t addr_byte_size)37b9c1b51eSKate Stone ExpressionVariableSP ClangPersistentVariables::CreatePersistentVariable(
380e4c4821SAdrian Prantl     ExecutionContextScope *exe_scope, ConstString name,
39b9c1b51eSKate Stone     const CompilerType &compiler_type, lldb::ByteOrder byte_order,
40b9c1b51eSKate Stone     uint32_t addr_byte_size) {
41b9c1b51eSKate Stone   return AddNewlyConstructedVariable(new ClangExpressionVariable(
42b9c1b51eSKate Stone       exe_scope, name, compiler_type, byte_order, addr_byte_size));
434dbb271fSSean Callanan }
444dbb271fSSean Callanan 
RemovePersistentVariable(lldb::ExpressionVariableSP variable)45b9c1b51eSKate Stone void ClangPersistentVariables::RemovePersistentVariable(
46b9c1b51eSKate Stone     lldb::ExpressionVariableSP variable) {
474dbb271fSSean Callanan   RemoveVariable(variable);
484dbb271fSSean Callanan 
499de71690SRaphael Isemann   // Check if the removed variable was the last one that was created. If yes,
509de71690SRaphael Isemann   // reuse the variable id for the next variable.
514dbb271fSSean Callanan 
529de71690SRaphael Isemann   // Nothing to do if we have not assigned a variable id so far.
539de71690SRaphael Isemann   if (m_next_persistent_variable_id == 0)
544dbb271fSSean Callanan     return;
554dbb271fSSean Callanan 
569de71690SRaphael Isemann   llvm::StringRef name = variable->GetName().GetStringRef();
579de71690SRaphael Isemann   // Remove the prefix from the variable that only the indes is left.
589de71690SRaphael Isemann   if (!name.consume_front(GetPersistentVariablePrefix(false)))
599de71690SRaphael Isemann     return;
609de71690SRaphael Isemann 
619de71690SRaphael Isemann   // Check if the variable contained a variable id.
629de71690SRaphael Isemann   uint32_t variable_id;
639de71690SRaphael Isemann   if (name.getAsInteger(10, variable_id))
649de71690SRaphael Isemann     return;
659de71690SRaphael Isemann   // If it's the most recent variable id that was assigned, make sure that this
669de71690SRaphael Isemann   // variable id will be used for the next persistent variable.
679de71690SRaphael Isemann   if (variable_id == m_next_persistent_variable_id - 1)
684dbb271fSSean Callanan     m_next_persistent_variable_id--;
694dbb271fSSean Callanan }
704dbb271fSSean Callanan 
715b99928bSAlex Langford llvm::Optional<CompilerType>
GetCompilerTypeFromPersistentDecl(ConstString type_name)725b99928bSAlex Langford ClangPersistentVariables::GetCompilerTypeFromPersistentDecl(
735b99928bSAlex Langford     ConstString type_name) {
7436fb199eSRaphael Isemann   PersistentDecl p = m_persistent_decls.lookup(type_name.GetCString());
7536fb199eSRaphael Isemann 
7636fb199eSRaphael Isemann   if (p.m_decl == nullptr)
7736fb199eSRaphael Isemann     return llvm::None;
7836fb199eSRaphael Isemann 
7936fb199eSRaphael Isemann   if (clang::TypeDecl *tdecl = llvm::dyn_cast<clang::TypeDecl>(p.m_decl)) {
8036fb199eSRaphael Isemann     opaque_compiler_type_t t = static_cast<opaque_compiler_type_t>(
8136fb199eSRaphael Isemann         const_cast<clang::Type *>(tdecl->getTypeForDecl()));
8236fb199eSRaphael Isemann     return CompilerType(p.m_context, t);
835b99928bSAlex Langford   }
845b99928bSAlex Langford   return llvm::None;
855b99928bSAlex Langford }
865b99928bSAlex Langford 
RegisterPersistentDecl(ConstString name,clang::NamedDecl * decl,TypeSystemClang * ctx)870e4c4821SAdrian Prantl void ClangPersistentVariables::RegisterPersistentDecl(ConstString name,
8836fb199eSRaphael Isemann                                                       clang::NamedDecl *decl,
896e3b0cc2SRaphael Isemann                                                       TypeSystemClang *ctx) {
9036fb199eSRaphael Isemann   PersistentDecl p = {decl, ctx};
9136fb199eSRaphael Isemann   m_persistent_decls.insert(std::make_pair(name.GetCString(), p));
92b3a36df3SSean Callanan 
93b9c1b51eSKate Stone   if (clang::EnumDecl *enum_decl = llvm::dyn_cast<clang::EnumDecl>(decl)) {
94b9c1b51eSKate Stone     for (clang::EnumConstantDecl *enumerator_decl : enum_decl->enumerators()) {
9536fb199eSRaphael Isemann       p = {enumerator_decl, ctx};
9636fb199eSRaphael Isemann       m_persistent_decls.insert(std::make_pair(
9736fb199eSRaphael Isemann           ConstString(enumerator_decl->getNameAsString()).GetCString(), p));
98b3a36df3SSean Callanan     }
99b3a36df3SSean Callanan   }
1004dbb271fSSean Callanan }
1014dbb271fSSean Callanan 
102b3a36df3SSean Callanan clang::NamedDecl *
GetPersistentDecl(ConstString name)1030e4c4821SAdrian Prantl ClangPersistentVariables::GetPersistentDecl(ConstString name) {
10436fb199eSRaphael Isemann   return m_persistent_decls.lookup(name.GetCString()).m_decl;
1054dbb271fSSean Callanan }
106c4f6fbe9SAlex Langford 
1077c9ebdd3SAlex Langford std::shared_ptr<ClangASTImporter>
GetClangASTImporter()1087c9ebdd3SAlex Langford ClangPersistentVariables::GetClangASTImporter() {
109c4f6fbe9SAlex Langford   if (!m_ast_importer_sp) {
110c4f6fbe9SAlex Langford     m_ast_importer_sp = std::make_shared<ClangASTImporter>();
111c4f6fbe9SAlex Langford   }
112c4f6fbe9SAlex Langford   return m_ast_importer_sp;
113c4f6fbe9SAlex Langford }
11467d67ebeSJim Ingham 
115*4c0b0de9SAlex Langford std::shared_ptr<ClangModulesDeclVendor>
GetClangModulesDeclVendor()116*4c0b0de9SAlex Langford ClangPersistentVariables::GetClangModulesDeclVendor() {
117*4c0b0de9SAlex Langford   if (!m_modules_decl_vendor_sp) {
118*4c0b0de9SAlex Langford     m_modules_decl_vendor_sp.reset(
119*4c0b0de9SAlex Langford         ClangModulesDeclVendor::Create(*m_target_sp.get()));
120*4c0b0de9SAlex Langford   }
121*4c0b0de9SAlex Langford   return m_modules_decl_vendor_sp;
122*4c0b0de9SAlex Langford }
123*4c0b0de9SAlex Langford 
12467d67ebeSJim Ingham ConstString
GetNextPersistentVariableName(bool is_error)12567d67ebeSJim Ingham ClangPersistentVariables::GetNextPersistentVariableName(bool is_error) {
12667d67ebeSJim Ingham   llvm::SmallString<64> name;
12767d67ebeSJim Ingham   {
12867d67ebeSJim Ingham     llvm::raw_svector_ostream os(name);
12967d67ebeSJim Ingham     os << GetPersistentVariablePrefix(is_error)
13067d67ebeSJim Ingham        << m_next_persistent_variable_id++;
13167d67ebeSJim Ingham   }
13267d67ebeSJim Ingham   return ConstString(name);
13367d67ebeSJim Ingham }
134