ClangExpressionVariable.h revision 01e6a58b057676d5dc434876dbb2d54871bb962e
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-public.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(ExecutionContextScope *exe_scope, 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            m_lldb_var   (),
102            m_lldb_sym   (NULL)
103        {
104        }
105
106        TypeFromParser          m_parser_type;  ///< The type of the variable according to the parser
107        const clang::NamedDecl *m_named_decl;   ///< The Decl corresponding to this variable
108        llvm::Value            *m_llvm_value;   ///< The IR value corresponding to this variable; usually a GlobalValue
109        lldb_private::Value    *m_lldb_value;   ///< The value found in LLDB for this variable
110        lldb::VariableSP        m_lldb_var;     ///< The original variable for this variable
111        const lldb_private::Symbol *m_lldb_sym; ///< The original symbol for this variable, if it was a symbol
112
113    private:
114        DISALLOW_COPY_AND_ASSIGN (ParserVars);
115    };
116    //----------------------------------------------------------------------
117    /// Make this variable usable by the parser by allocating space for
118    /// parser-specific variables
119    //----------------------------------------------------------------------
120    void
121    EnableParserVars()
122    {
123        if (!m_parser_vars.get())
124            m_parser_vars.reset(new ParserVars);
125    }
126
127    //----------------------------------------------------------------------
128    /// Deallocate parser-specific variables
129    //----------------------------------------------------------------------
130    void
131    DisableParserVars()
132    {
133        m_parser_vars.reset();
134    }
135
136    //----------------------------------------------------------------------
137    /// The following values are valid if the variable is used by JIT code
138    //----------------------------------------------------------------------
139    struct JITVars {
140        JITVars () :
141            m_alignment (0),
142            m_size (0),
143            m_offset (0)
144        {
145        }
146
147        off_t   m_alignment;    ///< The required alignment of the variable, in bytes
148        size_t  m_size;         ///< The space required for the variable, in bytes
149        off_t   m_offset;       ///< The offset of the variable in the struct, in bytes
150    };
151
152    //----------------------------------------------------------------------
153    /// Make this variable usable for materializing for the JIT by allocating
154    /// space for JIT-specific variables
155    //----------------------------------------------------------------------
156    void
157    EnableJITVars()
158    {
159        if (!m_jit_vars.get())
160            m_jit_vars.reset(new JITVars);
161    }
162
163    //----------------------------------------------------------------------
164    /// Deallocate JIT-specific variables
165    //----------------------------------------------------------------------
166    void
167    DisableJITVars()
168    {
169        m_jit_vars.reset();
170    }
171
172    //----------------------------------------------------------------------
173    /// Return the variable's size in bytes
174    //----------------------------------------------------------------------
175    size_t
176    GetByteSize ();
177
178    const ConstString &
179    GetName();
180
181    RegisterInfo *
182    GetRegisterInfo();
183
184    void
185    SetRegisterInfo (const RegisterInfo *reg_info);
186
187    lldb::clang_type_t
188    GetClangType ();
189
190    void
191    SetClangType (lldb::clang_type_t);
192
193    clang::ASTContext *
194    GetClangAST ();
195
196    void
197    SetClangAST (clang::ASTContext *ast);
198
199    TypeFromUser
200    GetTypeFromUser ();
201
202    uint8_t *
203    GetValueBytes ();
204
205    void
206    SetName (const ConstString &name);
207
208    void
209    ValueUpdated ();
210
211    // this function is used to copy the address-of m_live_sp into m_frozen_sp
212    // this is necessary because the results of certain cast and pointer-arithmetic
213    // operations (such as those described in bugzilla issues 11588 and 11618) generate
214    // frozen objcts that do not have a valid address-of, which can be troublesome when
215    // using synthetic children providers. transferring the address-of the live object
216    // solves these issues and provides the expected user-level behavior
217    void
218    TransferAddress (bool force = false);
219
220    typedef STD_SHARED_PTR(ValueObjectConstResult) ValueObjectConstResultSP;
221
222    //----------------------------------------------------------------------
223    /// Members
224    //----------------------------------------------------------------------
225    std::auto_ptr<ParserVars> m_parser_vars;
226    std::auto_ptr<JITVars> m_jit_vars;
227
228    enum Flags
229    {
230        EVNone                  = 0,
231        EVIsLLDBAllocated       = 1 << 0,   ///< This variable is resident in a location specifically allocated for it by LLDB in the target process
232        EVIsProgramReference    = 1 << 1,   ///< This variable is a reference to a (possibly invalid) area managed by the target program
233        EVNeedsAllocation       = 1 << 2,   ///< Space for this variable has yet to be allocated in the target process
234        EVIsFreezeDried         = 1 << 3,   ///< This variable's authoritative version is in m_frozen_sp (for example, for statically-computed results)
235        EVNeedsFreezeDry        = 1 << 4,   ///< Copy from m_live_sp to m_frozen_sp during dematerialization
236        EVKeepInTarget          = 1 << 5,   ///< Keep the allocation after the expression is complete rather than freeze drying its contents and freeing it
237        EVTypeIsReference       = 1 << 6,   ///< The original type of this variable is a reference, so materialize the value rather than the location
238        EVUnknownType           = 1 << 7,   ///< This is a symbol of unknown type, and the type must be resolved after parsing is complete
239        EVBareRegister          = 1 << 8    ///< This variable is a direct reference to $pc or some other entity.
240    };
241
242    typedef uint16_t FlagType;
243
244    FlagType m_flags; // takes elements of Flags
245
246    lldb::ValueObjectSP m_frozen_sp;
247    lldb::ValueObjectSP m_live_sp;
248private:
249    DISALLOW_COPY_AND_ASSIGN (ClangExpressionVariable);
250};
251
252//----------------------------------------------------------------------
253/// @class ClangExpressionVariableListBase ClangExpressionVariable.h "lldb/Expression/ClangExpressionVariable.h"
254/// @brief A list of variable references.
255///
256/// This class stores variables internally, acting as the permanent store.
257//----------------------------------------------------------------------
258class ClangExpressionVariableList
259{
260public:
261    //----------------------------------------------------------------------
262    /// Implementation of methods in ClangExpressionVariableListBase
263    //----------------------------------------------------------------------
264    size_t
265    GetSize()
266    {
267        return m_variables.size();
268    }
269
270    lldb::ClangExpressionVariableSP
271    GetVariableAtIndex(size_t index)
272    {
273        lldb::ClangExpressionVariableSP var_sp;
274        if (index < m_variables.size())
275            var_sp = m_variables[index];
276        return var_sp;
277    }
278
279    size_t
280    AddVariable (const lldb::ClangExpressionVariableSP &var_sp)
281    {
282        m_variables.push_back(var_sp);
283        return m_variables.size() - 1;
284    }
285
286    bool
287    ContainsVariable (const lldb::ClangExpressionVariableSP &var_sp)
288    {
289        const size_t size = m_variables.size();
290        for (size_t index = 0; index < size; ++index)
291        {
292            if (m_variables[index].get() == var_sp.get())
293                return true;
294        }
295        return false;
296    }
297
298    //----------------------------------------------------------------------
299    /// Finds a variable by name in the list.
300    ///
301    /// @param[in] name
302    ///     The name of the requested variable.
303    ///
304    /// @return
305    ///     The variable requested, or NULL if that variable is not in the list.
306    //----------------------------------------------------------------------
307    lldb::ClangExpressionVariableSP
308    GetVariable (const ConstString &name)
309    {
310        lldb::ClangExpressionVariableSP var_sp;
311        for (size_t index = 0, size = GetSize(); index < size; ++index)
312        {
313            var_sp = GetVariableAtIndex(index);
314            if (var_sp->GetName() == name)
315                return var_sp;
316        }
317        var_sp.reset();
318        return var_sp;
319    }
320
321    lldb::ClangExpressionVariableSP
322    GetVariable (const char *name)
323    {
324        lldb::ClangExpressionVariableSP var_sp;
325        if (name && name[0])
326        {
327            for (size_t index = 0, size = GetSize(); index < size; ++index)
328            {
329                var_sp = GetVariableAtIndex(index);
330                const char *var_name_cstr = var_sp->GetName().GetCString();
331                if (!var_name_cstr || !name)
332                    continue;
333                if (::strcmp (var_name_cstr, name) == 0)
334                    return var_sp;
335            }
336            var_sp.reset();
337        }
338        return var_sp;
339    }
340
341    //----------------------------------------------------------------------
342    /// Finds a variable by NamedDecl in the list.
343    ///
344    /// @param[in] name
345    ///     The name of the requested variable.
346    ///
347    /// @return
348    ///     The variable requested, or NULL if that variable is not in the list.
349    //----------------------------------------------------------------------
350    lldb::ClangExpressionVariableSP
351    GetVariable (const clang::NamedDecl *decl)
352    {
353        lldb::ClangExpressionVariableSP var_sp;
354        for (size_t index = 0, size = GetSize(); index < size; ++index)
355        {
356            var_sp = GetVariableAtIndex(index);
357            if (var_sp->m_parser_vars.get() && var_sp->m_parser_vars->m_named_decl == decl)
358                return var_sp;
359        }
360        var_sp.reset();
361        return var_sp;
362    }
363
364    //----------------------------------------------------------------------
365    /// Create a new variable in the list and return its index
366    //----------------------------------------------------------------------
367    lldb::ClangExpressionVariableSP
368    CreateVariable (ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size)
369    {
370        lldb::ClangExpressionVariableSP var_sp(new ClangExpressionVariable(exe_scope, byte_order, addr_byte_size));
371        m_variables.push_back(var_sp);
372        return var_sp;
373    }
374
375    lldb::ClangExpressionVariableSP
376    CreateVariable(const lldb::ValueObjectSP &valobj_sp)
377    {
378        lldb::ClangExpressionVariableSP var_sp(new ClangExpressionVariable(valobj_sp));
379        m_variables.push_back(var_sp);
380        return var_sp;
381    }
382
383    lldb::ClangExpressionVariableSP
384    CreateVariable (ExecutionContextScope *exe_scope,
385                    const ConstString &name,
386                    const TypeFromUser& user_type,
387                    lldb::ByteOrder byte_order,
388                    uint32_t addr_byte_size)
389    {
390        lldb::ClangExpressionVariableSP var_sp(new ClangExpressionVariable(exe_scope, byte_order, addr_byte_size));
391        var_sp->SetName (name);
392        var_sp->SetClangType (user_type.GetOpaqueQualType());
393        var_sp->SetClangAST (user_type.GetASTContext());
394        m_variables.push_back(var_sp);
395        return var_sp;
396    }
397
398    void
399    RemoveVariable (lldb::ClangExpressionVariableSP var_sp)
400    {
401        for (std::vector<lldb::ClangExpressionVariableSP>::iterator vi = m_variables.begin(), ve = m_variables.end();
402             vi != ve;
403             ++vi)
404        {
405            if (vi->get() == var_sp.get())
406            {
407                m_variables.erase(vi);
408                return;
409            }
410        }
411    }
412
413    void
414    Clear()
415    {
416        m_variables.clear();
417    }
418
419private:
420    std::vector <lldb::ClangExpressionVariableSP> m_variables;
421};
422
423
424} // namespace lldb_private
425
426#endif  // liblldb_ClangExpressionVariable_h_
427