1 //===-- ClangExpressionVariable.h -------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef liblldb_ClangExpressionVariable_h_
10 #define liblldb_ClangExpressionVariable_h_
11 
12 #include <signal.h>
13 #include <stdint.h>
14 #include <string.h>
15 
16 #include <map>
17 #include <string>
18 #include <vector>
19 
20 #include "llvm/Support/Casting.h"
21 
22 #include "lldb/Core/ClangForward.h"
23 #include "lldb/Core/Value.h"
24 #include "lldb/Expression/ExpressionVariable.h"
25 #include "lldb/Symbol/TaggedASTType.h"
26 #include "lldb/Utility/ConstString.h"
27 #include "lldb/lldb-public.h"
28 
29 namespace llvm {
30 class Value;
31 }
32 
33 namespace lldb_private {
34 
35 class ValueObjectConstResult;
36 
37 /// \class ClangExpressionVariable ClangExpressionVariable.h
38 /// "lldb/Expression/ClangExpressionVariable.h" Encapsulates one variable for
39 /// the expression parser.
40 ///
41 /// The expression parser uses variables in three different contexts:
42 ///
43 /// First, it stores persistent variables along with the process for use in
44 /// expressions.  These persistent variables contain their own data and are
45 /// typed.
46 ///
47 /// Second, in an interpreted expression, it stores the local variables for
48 /// the expression along with the expression.  These variables contain their
49 /// own data and are typed.
50 ///
51 /// Third, in a JIT-compiled expression, it stores the variables that the
52 /// expression needs to have materialized and dematerialized at each
53 /// execution.  These do not contain their own data but are named and typed.
54 ///
55 /// This class supports all of these use cases using simple type polymorphism,
56 /// and provides necessary support methods.  Its interface is RTTI-neutral.
57 class ClangExpressionVariable : public ExpressionVariable {
58 public:
59   ClangExpressionVariable(ExecutionContextScope *exe_scope,
60                           lldb::ByteOrder byte_order, uint32_t addr_byte_size);
61 
62   ClangExpressionVariable(ExecutionContextScope *exe_scope, Value &value,
63                           ConstString name, uint16_t flags = EVNone);
64 
65   ClangExpressionVariable(const lldb::ValueObjectSP &valobj_sp);
66 
67   ClangExpressionVariable(ExecutionContextScope *exe_scope,
68                           ConstString name,
69                           const TypeFromUser &user_type,
70                           lldb::ByteOrder byte_order, uint32_t addr_byte_size);
71 
72   /// Utility functions for dealing with ExpressionVariableLists in Clang-
73   /// specific ways
74 
75   /// Finds a variable by NamedDecl in the list.
76   ///
77   /// \return
78   ///     The variable requested, or NULL if that variable is not in the list.
79   static ClangExpressionVariable *
80   FindVariableInList(ExpressionVariableList &list, const clang::NamedDecl *decl,
81                      uint64_t parser_id) {
82     lldb::ExpressionVariableSP var_sp;
83     for (size_t index = 0, size = list.GetSize(); index < size; ++index) {
84       var_sp = list.GetVariableAtIndex(index);
85 
86       if (ClangExpressionVariable *clang_var =
87               llvm::dyn_cast<ClangExpressionVariable>(var_sp.get())) {
88         ClangExpressionVariable::ParserVars *parser_vars =
89             clang_var->GetParserVars(parser_id);
90 
91         if (parser_vars && parser_vars->m_named_decl == decl)
92           return clang_var;
93       }
94     }
95     return nullptr;
96   }
97 
98   /// If the variable contains its own data, make a Value point at it. If \a
99   /// exe_ctx in not NULL, the value will be resolved in with that execution
100   /// context.
101   ///
102   /// \param[in] value
103   ///     The value to point at the data.
104   ///
105   /// \param[in] exe_ctx
106   ///     The execution context to use to resolve \a value.
107   ///
108   /// \return
109   ///     True on success; false otherwise (in particular, if this variable
110   ///     does not contain its own data).
111   bool PointValueAtData(Value &value, ExecutionContext *exe_ctx);
112 
113   /// The following values should not live beyond parsing
114   class ParserVars {
115   public:
116     ParserVars()
117         : m_parser_type(), m_named_decl(nullptr), m_llvm_value(nullptr),
118           m_lldb_value(), m_lldb_var(), m_lldb_sym(nullptr) {}
119 
120     TypeFromParser
121         m_parser_type; ///< The type of the variable according to the parser
122     const clang::NamedDecl
123         *m_named_decl;         ///< The Decl corresponding to this variable
124     llvm::Value *m_llvm_value; ///< The IR value corresponding to this variable;
125                                ///usually a GlobalValue
126     lldb_private::Value
127         m_lldb_value;            ///< The value found in LLDB for this variable
128     lldb::VariableSP m_lldb_var; ///< The original variable for this variable
129     const lldb_private::Symbol *m_lldb_sym; ///< The original symbol for this
130                                             ///variable, if it was a symbol
131   };
132 
133 private:
134   typedef std::map<uint64_t, ParserVars> ParserVarMap;
135   ParserVarMap m_parser_vars;
136 
137 public:
138   /// Make this variable usable by the parser by allocating space for parser-
139   /// specific variables
140   void EnableParserVars(uint64_t parser_id) {
141     m_parser_vars.insert(std::make_pair(parser_id, ParserVars()));
142   }
143 
144   /// Deallocate parser-specific variables
145   void DisableParserVars(uint64_t parser_id) { m_parser_vars.erase(parser_id); }
146 
147   /// Access parser-specific variables
148   ParserVars *GetParserVars(uint64_t parser_id) {
149     ParserVarMap::iterator i = m_parser_vars.find(parser_id);
150 
151     if (i == m_parser_vars.end())
152       return nullptr;
153     else
154       return &i->second;
155   }
156 
157   /// The following values are valid if the variable is used by JIT code
158   struct JITVars {
159     JITVars() : m_alignment(0), m_size(0), m_offset(0) {}
160 
161     lldb::offset_t
162         m_alignment; ///< The required alignment of the variable, in bytes
163     size_t m_size;   ///< The space required for the variable, in bytes
164     lldb::offset_t
165         m_offset; ///< The offset of the variable in the struct, in bytes
166   };
167 
168 private:
169   typedef std::map<uint64_t, JITVars> JITVarMap;
170   JITVarMap m_jit_vars;
171 
172 public:
173   /// Make this variable usable for materializing for the JIT by allocating
174   /// space for JIT-specific variables
175   void EnableJITVars(uint64_t parser_id) {
176     m_jit_vars.insert(std::make_pair(parser_id, JITVars()));
177   }
178 
179   /// Deallocate JIT-specific variables
180   void DisableJITVars(uint64_t parser_id) { m_jit_vars.erase(parser_id); }
181 
182   JITVars *GetJITVars(uint64_t parser_id) {
183     JITVarMap::iterator i = m_jit_vars.find(parser_id);
184 
185     if (i == m_jit_vars.end())
186       return nullptr;
187     else
188       return &i->second;
189   }
190 
191   TypeFromUser GetTypeFromUser();
192 
193   // llvm casting support
194   static bool classof(const ExpressionVariable *ev) {
195     return ev->getKind() == ExpressionVariable::eKindClang;
196   }
197 
198   /// Members
199   DISALLOW_COPY_AND_ASSIGN(ClangExpressionVariable);
200 };
201 
202 } // namespace lldb_private
203 
204 #endif // liblldb_ClangExpressionVariable_h_
205