10b57cec5SDimitry Andric //===-- ExpressionVariable.h ------------------------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 95ffd83dbSDimitry Andric #ifndef LLDB_EXPRESSION_EXPRESSIONVARIABLE_H 105ffd83dbSDimitry Andric #define LLDB_EXPRESSION_EXPRESSIONVARIABLE_H 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #include <memory> 13bdd1243dSDimitry Andric #include <optional> 140b57cec5SDimitry Andric #include <vector> 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 170b57cec5SDimitry Andric 180b57cec5SDimitry Andric #include "lldb/Core/ValueObject.h" 190b57cec5SDimitry Andric #include "lldb/Utility/ConstString.h" 200b57cec5SDimitry Andric #include "lldb/lldb-public.h" 2106c3fb27SDimitry Andric #include "llvm/Support/ExtensibleRTTI.h" 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric namespace lldb_private { 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric class ExpressionVariable 2606c3fb27SDimitry Andric : public std::enable_shared_from_this<ExpressionVariable>, 2706c3fb27SDimitry Andric public llvm::RTTIExtends<ExpressionVariable, llvm::RTTIRoot> { 280b57cec5SDimitry Andric public: 2906c3fb27SDimitry Andric /// LLVM RTTI support 3006c3fb27SDimitry Andric static char ID; 310b57cec5SDimitry Andric 3206c3fb27SDimitry Andric ExpressionVariable(); 330b57cec5SDimitry Andric 3406c3fb27SDimitry Andric virtual ~ExpressionVariable() = default; 350b57cec5SDimitry Andric GetByteSize()36bdd1243dSDimitry Andric std::optional<uint64_t> GetByteSize() { return m_frozen_sp->GetByteSize(); } 370b57cec5SDimitry Andric GetName()380b57cec5SDimitry Andric ConstString GetName() { return m_frozen_sp->GetName(); } 390b57cec5SDimitry Andric GetValueObject()400b57cec5SDimitry Andric lldb::ValueObjectSP GetValueObject() { return m_frozen_sp; } 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric uint8_t *GetValueBytes(); 430b57cec5SDimitry Andric ValueUpdated()440b57cec5SDimitry Andric void ValueUpdated() { m_frozen_sp->ValueUpdated(); } 450b57cec5SDimitry Andric GetRegisterInfo()460b57cec5SDimitry Andric RegisterInfo *GetRegisterInfo() { 470b57cec5SDimitry Andric return m_frozen_sp->GetValue().GetRegisterInfo(); 480b57cec5SDimitry Andric } 490b57cec5SDimitry Andric SetRegisterInfo(const RegisterInfo * reg_info)500b57cec5SDimitry Andric void SetRegisterInfo(const RegisterInfo *reg_info) { 510b57cec5SDimitry Andric return m_frozen_sp->GetValue().SetContext( 52fe6060f1SDimitry Andric Value::ContextType::RegisterInfo, const_cast<RegisterInfo *>(reg_info)); 530b57cec5SDimitry Andric } 540b57cec5SDimitry Andric GetCompilerType()550b57cec5SDimitry Andric CompilerType GetCompilerType() { return m_frozen_sp->GetCompilerType(); } 560b57cec5SDimitry Andric SetCompilerType(const CompilerType & compiler_type)570b57cec5SDimitry Andric void SetCompilerType(const CompilerType &compiler_type) { 580b57cec5SDimitry Andric m_frozen_sp->GetValue().SetCompilerType(compiler_type); 590b57cec5SDimitry Andric } 600b57cec5SDimitry Andric SetName(ConstString name)610b57cec5SDimitry Andric void SetName(ConstString name) { m_frozen_sp->SetName(name); } 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric // this function is used to copy the address-of m_live_sp into m_frozen_sp 640b57cec5SDimitry Andric // this is necessary because the results of certain cast and pointer- 650b57cec5SDimitry Andric // arithmetic operations (such as those described in bugzilla issues 11588 660b57cec5SDimitry Andric // and 11618) generate frozen objects that do not have a valid address-of, 670b57cec5SDimitry Andric // which can be troublesome when using synthetic children providers. 680b57cec5SDimitry Andric // Transferring the address-of the live object solves these issues and 690b57cec5SDimitry Andric // provides the expected user-level behavior 700b57cec5SDimitry Andric void TransferAddress(bool force = false) { 710b57cec5SDimitry Andric if (m_live_sp.get() == nullptr) 720b57cec5SDimitry Andric return; 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric if (m_frozen_sp.get() == nullptr) 750b57cec5SDimitry Andric return; 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric if (force || (m_frozen_sp->GetLiveAddress() == LLDB_INVALID_ADDRESS)) 780b57cec5SDimitry Andric m_frozen_sp->SetLiveAddress(m_live_sp->GetLiveAddress()); 790b57cec5SDimitry Andric } 800b57cec5SDimitry Andric 810b57cec5SDimitry Andric enum Flags { 820b57cec5SDimitry Andric EVNone = 0, 830b57cec5SDimitry Andric EVIsLLDBAllocated = 1 << 0, ///< This variable is resident in a location 840b57cec5SDimitry Andric ///specifically allocated for it by LLDB in the 850b57cec5SDimitry Andric ///target process 860b57cec5SDimitry Andric EVIsProgramReference = 1 << 1, ///< This variable is a reference to a 870b57cec5SDimitry Andric ///(possibly invalid) area managed by the 880b57cec5SDimitry Andric ///target program 890b57cec5SDimitry Andric EVNeedsAllocation = 1 << 2, ///< Space for this variable has yet to be 900b57cec5SDimitry Andric ///allocated in the target process 910b57cec5SDimitry Andric EVIsFreezeDried = 1 << 3, ///< This variable's authoritative version is in 920b57cec5SDimitry Andric ///m_frozen_sp (for example, for 930b57cec5SDimitry Andric ///statically-computed results) 940b57cec5SDimitry Andric EVNeedsFreezeDry = 950b57cec5SDimitry Andric 1 << 4, ///< Copy from m_live_sp to m_frozen_sp during dematerialization 960b57cec5SDimitry Andric EVKeepInTarget = 1 << 5, ///< Keep the allocation after the expression is 970b57cec5SDimitry Andric ///complete rather than freeze drying its contents 980b57cec5SDimitry Andric ///and freeing it 990b57cec5SDimitry Andric EVTypeIsReference = 1 << 6, ///< The original type of this variable is a 1000b57cec5SDimitry Andric ///reference, so materialize the value rather 1010b57cec5SDimitry Andric ///than the location 102480093f4SDimitry Andric EVBareRegister = 1 << 7 ///< This variable is a direct reference to $pc or 1030b57cec5SDimitry Andric ///some other entity. 1040b57cec5SDimitry Andric }; 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric typedef uint16_t FlagType; 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric FlagType m_flags; // takes elements of Flags 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric // these should be private 1110b57cec5SDimitry Andric lldb::ValueObjectSP m_frozen_sp; 1120b57cec5SDimitry Andric lldb::ValueObjectSP m_live_sp; 1130b57cec5SDimitry Andric }; 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric /// \class ExpressionVariableList ExpressionVariable.h 1160b57cec5SDimitry Andric /// "lldb/Expression/ExpressionVariable.h" 1170b57cec5SDimitry Andric /// A list of variable references. 1180b57cec5SDimitry Andric /// 1190b57cec5SDimitry Andric /// This class stores variables internally, acting as the permanent store. 1200b57cec5SDimitry Andric class ExpressionVariableList { 1210b57cec5SDimitry Andric public: 1220b57cec5SDimitry Andric /// Implementation of methods in ExpressionVariableListBase GetSize()1230b57cec5SDimitry Andric size_t GetSize() { return m_variables.size(); } 1240b57cec5SDimitry Andric GetVariableAtIndex(size_t index)1250b57cec5SDimitry Andric lldb::ExpressionVariableSP GetVariableAtIndex(size_t index) { 1260b57cec5SDimitry Andric lldb::ExpressionVariableSP var_sp; 1270b57cec5SDimitry Andric if (index < m_variables.size()) 1280b57cec5SDimitry Andric var_sp = m_variables[index]; 1290b57cec5SDimitry Andric return var_sp; 1300b57cec5SDimitry Andric } 1310b57cec5SDimitry Andric AddVariable(const lldb::ExpressionVariableSP & var_sp)1320b57cec5SDimitry Andric size_t AddVariable(const lldb::ExpressionVariableSP &var_sp) { 1330b57cec5SDimitry Andric m_variables.push_back(var_sp); 1340b57cec5SDimitry Andric return m_variables.size() - 1; 1350b57cec5SDimitry Andric } 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric lldb::ExpressionVariableSP AddNewlyConstructedVariable(ExpressionVariable * var)1380b57cec5SDimitry Andric AddNewlyConstructedVariable(ExpressionVariable *var) { 1390b57cec5SDimitry Andric lldb::ExpressionVariableSP var_sp(var); 1400b57cec5SDimitry Andric m_variables.push_back(var_sp); 1410b57cec5SDimitry Andric return m_variables.back(); 1420b57cec5SDimitry Andric } 1430b57cec5SDimitry Andric ContainsVariable(const lldb::ExpressionVariableSP & var_sp)1440b57cec5SDimitry Andric bool ContainsVariable(const lldb::ExpressionVariableSP &var_sp) { 1450b57cec5SDimitry Andric const size_t size = m_variables.size(); 1460b57cec5SDimitry Andric for (size_t index = 0; index < size; ++index) { 1470b57cec5SDimitry Andric if (m_variables[index].get() == var_sp.get()) 1480b57cec5SDimitry Andric return true; 1490b57cec5SDimitry Andric } 1500b57cec5SDimitry Andric return false; 1510b57cec5SDimitry Andric } 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric /// Finds a variable by name in the list. 1540b57cec5SDimitry Andric /// 1550b57cec5SDimitry Andric /// \param[in] name 1560b57cec5SDimitry Andric /// The name of the requested variable. 1570b57cec5SDimitry Andric /// 1580b57cec5SDimitry Andric /// \return 1590b57cec5SDimitry Andric /// The variable requested, or nullptr if that variable is not in the 1600b57cec5SDimitry Andric /// list. GetVariable(ConstString name)1610b57cec5SDimitry Andric lldb::ExpressionVariableSP GetVariable(ConstString name) { 1620b57cec5SDimitry Andric lldb::ExpressionVariableSP var_sp; 1630b57cec5SDimitry Andric for (size_t index = 0, size = GetSize(); index < size; ++index) { 1640b57cec5SDimitry Andric var_sp = GetVariableAtIndex(index); 1650b57cec5SDimitry Andric if (var_sp->GetName() == name) 1660b57cec5SDimitry Andric return var_sp; 1670b57cec5SDimitry Andric } 1680b57cec5SDimitry Andric var_sp.reset(); 1690b57cec5SDimitry Andric return var_sp; 1700b57cec5SDimitry Andric } 1710b57cec5SDimitry Andric GetVariable(llvm::StringRef name)1720b57cec5SDimitry Andric lldb::ExpressionVariableSP GetVariable(llvm::StringRef name) { 1730b57cec5SDimitry Andric if (name.empty()) 1740b57cec5SDimitry Andric return nullptr; 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric for (size_t index = 0, size = GetSize(); index < size; ++index) { 1770b57cec5SDimitry Andric auto var_sp = GetVariableAtIndex(index); 1780b57cec5SDimitry Andric llvm::StringRef var_name_str = var_sp->GetName().GetStringRef(); 1790b57cec5SDimitry Andric if (var_name_str == name) 1800b57cec5SDimitry Andric return var_sp; 1810b57cec5SDimitry Andric } 1820b57cec5SDimitry Andric return nullptr; 1830b57cec5SDimitry Andric } 1840b57cec5SDimitry Andric RemoveVariable(lldb::ExpressionVariableSP var_sp)1850b57cec5SDimitry Andric void RemoveVariable(lldb::ExpressionVariableSP var_sp) { 1860b57cec5SDimitry Andric for (std::vector<lldb::ExpressionVariableSP>::iterator 1870b57cec5SDimitry Andric vi = m_variables.begin(), 1880b57cec5SDimitry Andric ve = m_variables.end(); 1890b57cec5SDimitry Andric vi != ve; ++vi) { 1900b57cec5SDimitry Andric if (vi->get() == var_sp.get()) { 1910b57cec5SDimitry Andric m_variables.erase(vi); 1920b57cec5SDimitry Andric return; 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric } 1950b57cec5SDimitry Andric } 1960b57cec5SDimitry Andric Clear()1970b57cec5SDimitry Andric void Clear() { m_variables.clear(); } 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric private: 2000b57cec5SDimitry Andric std::vector<lldb::ExpressionVariableSP> m_variables; 2010b57cec5SDimitry Andric }; 2020b57cec5SDimitry Andric 20306c3fb27SDimitry Andric class PersistentExpressionState 20406c3fb27SDimitry Andric : public ExpressionVariableList, 20506c3fb27SDimitry Andric public llvm::RTTIExtends<PersistentExpressionState, llvm::RTTIRoot> { 2060b57cec5SDimitry Andric public: 20706c3fb27SDimitry Andric /// LLVM RTTI support 20806c3fb27SDimitry Andric static char ID; 2090b57cec5SDimitry Andric 21006c3fb27SDimitry Andric PersistentExpressionState(); 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric virtual ~PersistentExpressionState(); 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andric virtual lldb::ExpressionVariableSP 2150b57cec5SDimitry Andric CreatePersistentVariable(const lldb::ValueObjectSP &valobj_sp) = 0; 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric virtual lldb::ExpressionVariableSP 2180b57cec5SDimitry Andric CreatePersistentVariable(ExecutionContextScope *exe_scope, 2190b57cec5SDimitry Andric ConstString name, const CompilerType &type, 2200b57cec5SDimitry Andric lldb::ByteOrder byte_order, 2210b57cec5SDimitry Andric uint32_t addr_byte_size) = 0; 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric /// Return a new persistent variable name with the specified prefix. 2245ffd83dbSDimitry Andric virtual ConstString GetNextPersistentVariableName(bool is_error = false) = 0; 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric virtual void 2270b57cec5SDimitry Andric RemovePersistentVariable(lldb::ExpressionVariableSP variable) = 0; 2280b57cec5SDimitry Andric 229bdd1243dSDimitry Andric virtual std::optional<CompilerType> 2300b57cec5SDimitry Andric GetCompilerTypeFromPersistentDecl(ConstString type_name) = 0; 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric virtual lldb::addr_t LookupSymbol(ConstString name); 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric void RegisterExecutionUnit(lldb::IRExecutionUnitSP &execution_unit_sp); 2350b57cec5SDimitry Andric 2365ffd83dbSDimitry Andric protected: 2375ffd83dbSDimitry Andric virtual llvm::StringRef 2385ffd83dbSDimitry Andric GetPersistentVariablePrefix(bool is_error = false) const = 0; 2395ffd83dbSDimitry Andric 2400b57cec5SDimitry Andric private: 2410b57cec5SDimitry Andric typedef std::set<lldb::IRExecutionUnitSP> ExecutionUnitSet; 2420b57cec5SDimitry Andric ExecutionUnitSet 2430b57cec5SDimitry Andric m_execution_units; ///< The execution units that contain valuable symbols. 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric typedef llvm::DenseMap<const char *, lldb::addr_t> SymbolMap; 2460b57cec5SDimitry Andric SymbolMap 2470b57cec5SDimitry Andric m_symbol_map; ///< The addresses of the symbols in m_execution_units. 2480b57cec5SDimitry Andric }; 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric } // namespace lldb_private 2510b57cec5SDimitry Andric 2525ffd83dbSDimitry Andric #endif // LLDB_EXPRESSION_EXPRESSIONVARIABLE_H 253