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