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