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 90b57cec5SDimitry Andric #ifndef liblldb_ExpressionVariable_h_ 100b57cec5SDimitry Andric #define liblldb_ExpressionVariable_h_ 110b57cec5SDimitry Andric 120b57cec5SDimitry Andric #include <memory> 130b57cec5SDimitry Andric #include <vector> 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric #include "lldb/Core/ValueObject.h" 180b57cec5SDimitry Andric #include "lldb/Utility/ConstString.h" 190b57cec5SDimitry Andric #include "lldb/lldb-public.h" 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric namespace lldb_private { 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric class ExpressionVariable 240b57cec5SDimitry Andric : public std::enable_shared_from_this<ExpressionVariable> { 250b57cec5SDimitry Andric public: 260b57cec5SDimitry Andric // See TypeSystem.h for how to add subclasses to this. 270b57cec5SDimitry Andric enum LLVMCastKind { eKindClang, eKindSwift, eKindGo, kNumKinds }; 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric LLVMCastKind getKind() const { return m_kind; } 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric ExpressionVariable(LLVMCastKind kind) : m_flags(0), m_kind(kind) {} 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric virtual ~ExpressionVariable(); 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric size_t GetByteSize() { return m_frozen_sp->GetByteSize(); } 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric ConstString GetName() { return m_frozen_sp->GetName(); } 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric lldb::ValueObjectSP GetValueObject() { return m_frozen_sp; } 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric uint8_t *GetValueBytes(); 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric void ValueUpdated() { m_frozen_sp->ValueUpdated(); } 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric RegisterInfo *GetRegisterInfo() { 460b57cec5SDimitry Andric return m_frozen_sp->GetValue().GetRegisterInfo(); 470b57cec5SDimitry Andric } 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric void SetRegisterInfo(const RegisterInfo *reg_info) { 500b57cec5SDimitry Andric return m_frozen_sp->GetValue().SetContext( 510b57cec5SDimitry Andric Value::eContextTypeRegisterInfo, const_cast<RegisterInfo *>(reg_info)); 520b57cec5SDimitry Andric } 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric CompilerType GetCompilerType() { return m_frozen_sp->GetCompilerType(); } 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric void SetCompilerType(const CompilerType &compiler_type) { 570b57cec5SDimitry Andric m_frozen_sp->GetValue().SetCompilerType(compiler_type); 580b57cec5SDimitry Andric } 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric void SetName(ConstString name) { m_frozen_sp->SetName(name); } 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric // this function is used to copy the address-of m_live_sp into m_frozen_sp 630b57cec5SDimitry Andric // this is necessary because the results of certain cast and pointer- 640b57cec5SDimitry Andric // arithmetic operations (such as those described in bugzilla issues 11588 650b57cec5SDimitry Andric // and 11618) generate frozen objects that do not have a valid address-of, 660b57cec5SDimitry Andric // which can be troublesome when using synthetic children providers. 670b57cec5SDimitry Andric // Transferring the address-of the live object solves these issues and 680b57cec5SDimitry Andric // provides the expected user-level behavior 690b57cec5SDimitry Andric void TransferAddress(bool force = false) { 700b57cec5SDimitry Andric if (m_live_sp.get() == nullptr) 710b57cec5SDimitry Andric return; 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric if (m_frozen_sp.get() == nullptr) 740b57cec5SDimitry Andric return; 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric if (force || (m_frozen_sp->GetLiveAddress() == LLDB_INVALID_ADDRESS)) 770b57cec5SDimitry Andric m_frozen_sp->SetLiveAddress(m_live_sp->GetLiveAddress()); 780b57cec5SDimitry Andric } 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric enum Flags { 810b57cec5SDimitry Andric EVNone = 0, 820b57cec5SDimitry Andric EVIsLLDBAllocated = 1 << 0, ///< This variable is resident in a location 830b57cec5SDimitry Andric ///specifically allocated for it by LLDB in the 840b57cec5SDimitry Andric ///target process 850b57cec5SDimitry Andric EVIsProgramReference = 1 << 1, ///< This variable is a reference to a 860b57cec5SDimitry Andric ///(possibly invalid) area managed by the 870b57cec5SDimitry Andric ///target program 880b57cec5SDimitry Andric EVNeedsAllocation = 1 << 2, ///< Space for this variable has yet to be 890b57cec5SDimitry Andric ///allocated in the target process 900b57cec5SDimitry Andric EVIsFreezeDried = 1 << 3, ///< This variable's authoritative version is in 910b57cec5SDimitry Andric ///m_frozen_sp (for example, for 920b57cec5SDimitry Andric ///statically-computed results) 930b57cec5SDimitry Andric EVNeedsFreezeDry = 940b57cec5SDimitry Andric 1 << 4, ///< Copy from m_live_sp to m_frozen_sp during dematerialization 950b57cec5SDimitry Andric EVKeepInTarget = 1 << 5, ///< Keep the allocation after the expression is 960b57cec5SDimitry Andric ///complete rather than freeze drying its contents 970b57cec5SDimitry Andric ///and freeing it 980b57cec5SDimitry Andric EVTypeIsReference = 1 << 6, ///< The original type of this variable is a 990b57cec5SDimitry Andric ///reference, so materialize the value rather 1000b57cec5SDimitry Andric ///than the location 101480093f4SDimitry Andric EVBareRegister = 1 << 7 ///< This variable is a direct reference to $pc or 1020b57cec5SDimitry Andric ///some other entity. 1030b57cec5SDimitry Andric }; 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric typedef uint16_t FlagType; 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric FlagType m_flags; // takes elements of Flags 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric // these should be private 1100b57cec5SDimitry Andric lldb::ValueObjectSP m_frozen_sp; 1110b57cec5SDimitry Andric lldb::ValueObjectSP m_live_sp; 1120b57cec5SDimitry Andric LLVMCastKind m_kind; 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 1230b57cec5SDimitry Andric size_t GetSize() { return m_variables.size(); } 1240b57cec5SDimitry Andric 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 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 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 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. 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 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 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 1970b57cec5SDimitry Andric void Clear() { m_variables.clear(); } 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric private: 2000b57cec5SDimitry Andric std::vector<lldb::ExpressionVariableSP> m_variables; 2010b57cec5SDimitry Andric }; 2020b57cec5SDimitry Andric 2030b57cec5SDimitry Andric class PersistentExpressionState : public ExpressionVariableList { 2040b57cec5SDimitry Andric public: 2050b57cec5SDimitry Andric // See TypeSystem.h for how to add subclasses to this. 2060b57cec5SDimitry Andric enum LLVMCastKind { eKindClang, eKindSwift, eKindGo, kNumKinds }; 2070b57cec5SDimitry Andric 2080b57cec5SDimitry Andric LLVMCastKind getKind() const { return m_kind; } 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric PersistentExpressionState(LLVMCastKind kind) : m_kind(kind) {} 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. 2240b57cec5SDimitry Andric ConstString GetNextPersistentVariableName(Target &target, 2250b57cec5SDimitry Andric llvm::StringRef prefix); 2260b57cec5SDimitry Andric 2270b57cec5SDimitry Andric virtual llvm::StringRef 2280b57cec5SDimitry Andric GetPersistentVariablePrefix(bool is_error = false) const = 0; 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric virtual void 2310b57cec5SDimitry Andric RemovePersistentVariable(lldb::ExpressionVariableSP variable) = 0; 2320b57cec5SDimitry Andric 2330b57cec5SDimitry Andric virtual llvm::Optional<CompilerType> 2340b57cec5SDimitry Andric GetCompilerTypeFromPersistentDecl(ConstString type_name) = 0; 2350b57cec5SDimitry Andric 2360b57cec5SDimitry Andric virtual lldb::addr_t LookupSymbol(ConstString name); 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric void RegisterExecutionUnit(lldb::IRExecutionUnitSP &execution_unit_sp); 2390b57cec5SDimitry Andric 2400b57cec5SDimitry Andric private: 2410b57cec5SDimitry Andric LLVMCastKind m_kind; 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric typedef std::set<lldb::IRExecutionUnitSP> ExecutionUnitSet; 2440b57cec5SDimitry Andric ExecutionUnitSet 2450b57cec5SDimitry Andric m_execution_units; ///< The execution units that contain valuable symbols. 2460b57cec5SDimitry Andric 2470b57cec5SDimitry Andric typedef llvm::DenseMap<const char *, lldb::addr_t> SymbolMap; 2480b57cec5SDimitry Andric SymbolMap 2490b57cec5SDimitry Andric m_symbol_map; ///< The addresses of the symbols in m_execution_units. 2500b57cec5SDimitry Andric }; 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric } // namespace lldb_private 2530b57cec5SDimitry Andric 2540b57cec5SDimitry Andric #endif // liblldb_ExpressionVariable_h_ 255