ClangExpressionVariable.h revision bdcb6abaa287df2c5f312c51d993c1d0b0cb120c
1//===-- ClangExpressionVariable.h -------------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef liblldb_ClangExpressionVariable_h_
11#define liblldb_ClangExpressionVariable_h_
12
13// C Includes
14#include <signal.h>
15#include <stdint.h>
16#include <string.h>
17
18// C++ Includes
19#include <string>
20#include <vector>
21
22// Other libraries and framework includes
23// Project includes
24#include "lldb/lldb-include.h"
25#include "lldb/Core/ClangForward.h"
26#include "lldb/Core/ConstString.h"
27#include "lldb/Symbol/TaggedASTType.h"
28
29namespace llvm {
30    class Value;
31}
32
33namespace lldb_private {
34
35class ClangExpressionVariableList;
36class ValueObjectConstResult;
37
38//----------------------------------------------------------------------
39/// @class ClangExpressionVariable ClangExpressionVariable.h "lldb/Expression/ClangExpressionVariable.h"
40/// @brief Encapsulates one variable for the expression parser.
41///
42/// The expression parser uses variables in three different contexts:
43///
44/// First, it stores persistent variables along with the process for use
45/// in expressions.  These persistent variables contain their own data
46/// and are typed.
47///
48/// Second, in an interpreted expression, it stores the local variables
49/// for the expression along with the expression.  These variables
50/// contain their own data and are typed.
51///
52/// Third, in a JIT-compiled expression, it stores the variables that
53/// the expression needs to have materialized and dematerialized at each
54/// execution.  These do not contain their own data but are named and
55/// typed.
56///
57/// This class supports all of these use cases using simple type
58/// polymorphism, and provides necessary support methods.  Its interface
59/// is RTTI-neutral.
60//----------------------------------------------------------------------
61class ClangExpressionVariable
62{
63public:
64    ClangExpressionVariable(lldb::ByteOrder byte_order, uint32_t addr_byte_size);
65
66    ClangExpressionVariable(const lldb::ValueObjectSP &valobj_sp);
67
68    //----------------------------------------------------------------------
69    /// If the variable contains its own data, make a Value point at it.
70    /// If \a exe_ctx in not NULL, the value will be resolved in with
71    /// that execution context.
72    ///
73    /// @param[in] value
74    ///     The value to point at the data.
75    ///
76    /// @param[in] exe_ctx
77    ///     The execution context to use to resolve \a value.
78    ///
79    /// @return
80    ///     True on success; false otherwise (in particular, if this variable
81    ///     does not contain its own data).
82    //----------------------------------------------------------------------
83    bool
84    PointValueAtData(Value &value, ExecutionContext *exe_ctx);
85
86    lldb::ValueObjectSP
87    GetValueObject();
88
89    //----------------------------------------------------------------------
90    /// The following values should not live beyond parsing
91    //----------------------------------------------------------------------
92    class ParserVars
93    {
94    public:
95
96        ParserVars() :
97            m_parser_type(),
98            m_named_decl (NULL),
99            m_llvm_value (NULL),
100            m_lldb_value (NULL)
101        {
102        }
103
104        TypeFromParser          m_parser_type;  ///< The type of the variable according to the parser
105        const clang::NamedDecl *m_named_decl;   ///< The Decl corresponding to this variable
106        llvm::Value            *m_llvm_value;   ///< The IR value corresponding to this variable; usually a GlobalValue
107        lldb_private::Value    *m_lldb_value;   ///< The value found in LLDB for this variable
108
109    private:
110        DISALLOW_COPY_AND_ASSIGN (ParserVars);
111    };
112    //----------------------------------------------------------------------
113    /// Make this variable usable by the parser by allocating space for
114    /// parser-specific variables
115    //----------------------------------------------------------------------
116    void
117    EnableParserVars()
118    {
119        if (!m_parser_vars.get())
120            m_parser_vars.reset(new struct ParserVars);
121    }
122
123    //----------------------------------------------------------------------
124    /// Deallocate parser-specific variables
125    //----------------------------------------------------------------------
126    void
127    DisableParserVars()
128    {
129        m_parser_vars.reset();
130    }
131
132    //----------------------------------------------------------------------
133    /// The following values are valid if the variable is used by JIT code
134    //----------------------------------------------------------------------
135    struct JITVars {
136        JITVars () :
137            m_alignment (0),
138            m_size (0),
139            m_offset (0)
140        {
141        }
142
143        off_t   m_alignment;    ///< The required alignment of the variable, in bytes
144        size_t  m_size;         ///< The space required for the variable, in bytes
145        off_t   m_offset;       ///< The offset of the variable in the struct, in bytes
146    };
147
148    //----------------------------------------------------------------------
149    /// Make this variable usable for materializing for the JIT by allocating
150    /// space for JIT-specific variables
151    //----------------------------------------------------------------------
152    void
153    EnableJITVars()
154    {
155        if (!m_jit_vars.get())
156            m_jit_vars.reset(new struct JITVars);
157    }
158
159    //----------------------------------------------------------------------
160    /// Deallocate JIT-specific variables
161    //----------------------------------------------------------------------
162    void
163    DisableJITVars()
164    {
165        m_jit_vars.reset();
166    }
167
168    //----------------------------------------------------------------------
169    /// Return the variable's size in bytes
170    //----------------------------------------------------------------------
171    size_t
172    GetByteSize ();
173
174    const ConstString &
175    GetName();
176
177    lldb::RegisterInfo *
178    GetRegisterInfo();
179
180    void
181    SetRegisterInfo (const lldb::RegisterInfo *reg_info);
182
183    lldb::clang_type_t
184    GetClangType ();
185
186    void
187    SetClangType (lldb::clang_type_t);
188
189    clang::ASTContext *
190    GetClangAST ();
191
192    void
193    SetClangAST (clang::ASTContext *ast);
194
195    TypeFromUser
196    GetTypeFromUser ();
197
198    uint8_t *
199    GetValueBytes ();
200
201    void
202    SetName (const ConstString &name);
203
204    void
205    ValueUpdated ();
206
207    typedef lldb::SharedPtr<ValueObjectConstResult>::Type ValueObjectConstResultSP;
208
209    //----------------------------------------------------------------------
210    /// Members
211    //----------------------------------------------------------------------
212    std::auto_ptr<ParserVars> m_parser_vars;
213    std::auto_ptr<JITVars> m_jit_vars;
214
215    enum Flags
216    {
217        EVNone                  = 0,
218        EVIsLLDBAllocated       = 1 << 0,   ///< This variable is resident in a location specifically allocated for it by LLDB in the target process
219        EVIsProgramReference    = 1 << 1,   ///< This variable is a reference to a (possibly invalid) area managed by the target program
220        EVNeedsAllocation       = 1 << 2,   ///< Space for this variable has yet to be allocated in the target process
221        EVIsFreezeDried         = 1 << 3,   ///< This variable's authoritative version is in m_frozen_sp (for example, for statically-computed results)
222        EVNeedsFreezeDry        = 1 << 4,   ///< Copy from m_live_sp to m_frozen_sp during dematerialization
223        EVKeepInTarget          = 1 << 5    ///< Keep the allocation after the expression is complete rather than freeze drying its contents and freeing it
224    };
225
226    uint16_t m_flags; // takes elements of Flags
227
228    lldb::ValueObjectSP m_frozen_sp;
229    lldb::ValueObjectSP m_live_sp;
230private:
231    DISALLOW_COPY_AND_ASSIGN (ClangExpressionVariable);
232};
233
234//----------------------------------------------------------------------
235/// @class ClangExpressionVariableListBase ClangExpressionVariable.h "lldb/Expression/ClangExpressionVariable.h"
236/// @brief A list of variable references.
237///
238/// This class stores variables internally, acting as the permanent store.
239//----------------------------------------------------------------------
240class ClangExpressionVariableList
241{
242public:
243    //----------------------------------------------------------------------
244    /// Implementation of methods in ClangExpressionVariableListBase
245    //----------------------------------------------------------------------
246    size_t
247    GetSize()
248    {
249        return m_variables.size();
250    }
251
252    lldb::ClangExpressionVariableSP
253    GetVariableAtIndex(size_t index)
254    {
255        lldb::ClangExpressionVariableSP var_sp;
256        if (index < m_variables.size())
257            var_sp = m_variables[index];
258        return var_sp;
259    }
260
261    size_t
262    AddVariable (const lldb::ClangExpressionVariableSP &var_sp)
263    {
264        m_variables.push_back(var_sp);
265        return m_variables.size() - 1;
266    }
267
268    bool
269    ContainsVariable (const lldb::ClangExpressionVariableSP &var_sp)
270    {
271        const size_t size = m_variables.size();
272        for (size_t index = 0; index < size; ++index)
273        {
274            if (m_variables[index].get() == var_sp.get())
275                return true;
276        }
277        return false;
278    }
279
280    //----------------------------------------------------------------------
281    /// Finds a variable by name in the list.
282    ///
283    /// @param[in] name
284    ///     The name of the requested variable.
285    ///
286    /// @return
287    ///     The variable requested, or NULL if that variable is not in the list.
288    //----------------------------------------------------------------------
289    lldb::ClangExpressionVariableSP
290    GetVariable (const ConstString &name)
291    {
292        lldb::ClangExpressionVariableSP var_sp;
293        for (size_t index = 0, size = GetSize(); index < size; ++index)
294        {
295            var_sp = GetVariableAtIndex(index);
296            if (var_sp->GetName() == name)
297                return var_sp;
298        }
299        var_sp.reset();
300        return var_sp;
301    }
302
303    lldb::ClangExpressionVariableSP
304    GetVariable (const char *name)
305    {
306        lldb::ClangExpressionVariableSP var_sp;
307        if (name && name[0])
308        {
309            for (size_t index = 0, size = GetSize(); index < size; ++index)
310            {
311                var_sp = GetVariableAtIndex(index);
312                const char *var_name_cstr = var_sp->GetName().GetCString();
313                if (::strcmp (var_name_cstr, name) == 0)
314                    return var_sp;
315            }
316            var_sp.reset();
317        }
318        return var_sp;
319    }
320
321    //----------------------------------------------------------------------
322    /// Finds a variable by NamedDecl in the list.
323    ///
324    /// @param[in] name
325    ///     The name of the requested variable.
326    ///
327    /// @return
328    ///     The variable requested, or NULL if that variable is not in the list.
329    //----------------------------------------------------------------------
330    lldb::ClangExpressionVariableSP
331    GetVariable (const clang::NamedDecl *decl)
332    {
333        lldb::ClangExpressionVariableSP var_sp;
334        for (size_t index = 0, size = GetSize(); index < size; ++index)
335        {
336            var_sp = GetVariableAtIndex(index);
337            if (var_sp->m_parser_vars.get() && var_sp->m_parser_vars->m_named_decl == decl)
338                return var_sp;
339        }
340        var_sp.reset();
341        return var_sp;
342    }
343
344    //----------------------------------------------------------------------
345    /// Create a new variable in the list and return its index
346    //----------------------------------------------------------------------
347    lldb::ClangExpressionVariableSP
348    CreateVariable (lldb::ByteOrder byte_order, uint32_t addr_byte_size)
349    {
350        lldb::ClangExpressionVariableSP var_sp(new ClangExpressionVariable(byte_order, addr_byte_size));
351        m_variables.push_back(var_sp);
352        return var_sp;
353    }
354
355    lldb::ClangExpressionVariableSP
356    CreateVariable(const lldb::ValueObjectSP &valobj_sp)
357    {
358        lldb::ClangExpressionVariableSP var_sp(new ClangExpressionVariable(valobj_sp));
359        m_variables.push_back(var_sp);
360        return var_sp;
361    }
362
363
364
365    lldb::ClangExpressionVariableSP
366    CreateVariable (const ConstString &name,
367                    const TypeFromUser& user_type,
368                    lldb::ByteOrder byte_order,
369                    uint32_t addr_byte_size)
370    {
371        lldb::ClangExpressionVariableSP var_sp(new ClangExpressionVariable(byte_order, addr_byte_size));
372        var_sp->SetName (name);
373        var_sp->SetClangType (user_type.GetOpaqueQualType());
374        var_sp->SetClangAST (user_type.GetASTContext());
375        m_variables.push_back(var_sp);
376        return var_sp;
377    }
378
379private:
380    std::vector <lldb::ClangExpressionVariableSP> m_variables;
381};
382
383
384} // namespace lldb_private
385
386#endif  // liblldb_ClangExpressionVariable_h_
387