ClangExpressionVariable.h revision 52f792329be5db8e38961350589e97e8f2823acd
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 <map>
20#include <string>
21#include <vector>
22
23// Other libraries and framework includes
24// Project includes
25#include "lldb/lldb-public.h"
26#include "lldb/Core/ClangForward.h"
27#include "lldb/Core/ConstString.h"
28#include "lldb/Core/Value.h"
29#include "lldb/Symbol/TaggedASTType.h"
30
31namespace llvm {
32    class Value;
33}
34
35namespace lldb_private {
36
37class ClangExpressionVariableList;
38class ValueObjectConstResult;
39
40//----------------------------------------------------------------------
41/// @class ClangExpressionVariable ClangExpressionVariable.h "lldb/Expression/ClangExpressionVariable.h"
42/// @brief Encapsulates one variable for the expression parser.
43///
44/// The expression parser uses variables in three different contexts:
45///
46/// First, it stores persistent variables along with the process for use
47/// in expressions.  These persistent variables contain their own data
48/// and are typed.
49///
50/// Second, in an interpreted expression, it stores the local variables
51/// for the expression along with the expression.  These variables
52/// contain their own data and are typed.
53///
54/// Third, in a JIT-compiled expression, it stores the variables that
55/// the expression needs to have materialized and dematerialized at each
56/// execution.  These do not contain their own data but are named and
57/// typed.
58///
59/// This class supports all of these use cases using simple type
60/// polymorphism, and provides necessary support methods.  Its interface
61/// is RTTI-neutral.
62//----------------------------------------------------------------------
63class ClangExpressionVariable
64{
65public:
66    ClangExpressionVariable(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size);
67
68    ClangExpressionVariable(const lldb::ValueObjectSP &valobj_sp);
69
70    //----------------------------------------------------------------------
71    /// If the variable contains its own data, make a Value point at it.
72    /// If \a exe_ctx in not NULL, the value will be resolved in with
73    /// that execution context.
74    ///
75    /// @param[in] value
76    ///     The value to point at the data.
77    ///
78    /// @param[in] exe_ctx
79    ///     The execution context to use to resolve \a value.
80    ///
81    /// @return
82    ///     True on success; false otherwise (in particular, if this variable
83    ///     does not contain its own data).
84    //----------------------------------------------------------------------
85    bool
86    PointValueAtData(Value &value, ExecutionContext *exe_ctx);
87
88    lldb::ValueObjectSP
89    GetValueObject();
90
91    //----------------------------------------------------------------------
92    /// The following values should not live beyond parsing
93    //----------------------------------------------------------------------
94    class ParserVars
95    {
96    public:
97
98        ParserVars() :
99            m_parser_type(),
100            m_named_decl (NULL),
101            m_llvm_value (NULL),
102            m_lldb_value (),
103            m_lldb_var   (),
104            m_lldb_sym   (NULL)
105        {
106        }
107
108        TypeFromParser          m_parser_type;  ///< The type of the variable according to the parser
109        const clang::NamedDecl *m_named_decl;   ///< The Decl corresponding to this variable
110        llvm::Value            *m_llvm_value;   ///< The IR value corresponding to this variable; usually a GlobalValue
111        lldb_private::Value     m_lldb_value;   ///< The value found in LLDB for this variable
112        lldb::VariableSP        m_lldb_var;     ///< The original variable for this variable
113        const lldb_private::Symbol *m_lldb_sym; ///< The original symbol for this variable, if it was a symbol
114    };
115
116private:
117    typedef std::map <uint64_t, ParserVars> ParserVarMap;
118    ParserVarMap m_parser_vars;
119
120public:
121    //----------------------------------------------------------------------
122    /// Make this variable usable by the parser by allocating space for
123    /// parser-specific variables
124    //----------------------------------------------------------------------
125    void
126    EnableParserVars(uint64_t parser_id)
127    {
128        m_parser_vars.insert(std::make_pair(parser_id, ParserVars()));
129    }
130
131    //----------------------------------------------------------------------
132    /// Deallocate parser-specific variables
133    //----------------------------------------------------------------------
134    void
135    DisableParserVars(uint64_t parser_id)
136    {
137        m_parser_vars.erase(parser_id);
138    }
139
140    //----------------------------------------------------------------------
141    /// Access parser-specific variables
142    //----------------------------------------------------------------------
143    ParserVars *
144    GetParserVars(uint64_t parser_id)
145    {
146        ParserVarMap::iterator i = m_parser_vars.find(parser_id);
147
148        if (i == m_parser_vars.end())
149            return NULL;
150        else
151            return &i->second;
152    }
153
154    //----------------------------------------------------------------------
155    /// The following values are valid if the variable is used by JIT code
156    //----------------------------------------------------------------------
157    struct JITVars {
158        JITVars () :
159            m_alignment (0),
160            m_size (0),
161            m_offset (0)
162        {
163        }
164
165        off_t   m_alignment;    ///< The required alignment of the variable, in bytes
166        size_t  m_size;         ///< The space required for the variable, in bytes
167        off_t   m_offset;       ///< The offset of the variable in the struct, in bytes
168    };
169
170private:
171    typedef std::map <uint64_t, JITVars> JITVarMap;
172    JITVarMap m_jit_vars;
173
174public:
175    //----------------------------------------------------------------------
176    /// Make this variable usable for materializing for the JIT by allocating
177    /// space for JIT-specific variables
178    //----------------------------------------------------------------------
179    void
180    EnableJITVars(uint64_t parser_id)
181    {
182        m_jit_vars.insert(std::make_pair(parser_id, JITVars()));
183    }
184
185    //----------------------------------------------------------------------
186    /// Deallocate JIT-specific variables
187    //----------------------------------------------------------------------
188    void
189    DisableJITVars(uint64_t parser_id)
190    {
191        m_jit_vars.erase(parser_id);
192    }
193
194    JITVars *GetJITVars(uint64_t parser_id)
195    {
196        JITVarMap::iterator i = m_jit_vars.find(parser_id);
197
198        if (i == m_jit_vars.end())
199            return NULL;
200        else
201            return &i->second;
202    }
203
204    //----------------------------------------------------------------------
205    /// Return the variable's size in bytes
206    //----------------------------------------------------------------------
207    size_t
208    GetByteSize ();
209
210    const ConstString &
211    GetName();
212
213    RegisterInfo *
214    GetRegisterInfo();
215
216    void
217    SetRegisterInfo (const RegisterInfo *reg_info);
218
219    ClangASTType
220    GetClangType ();
221
222    void
223    SetClangType (const ClangASTType &clang_type);
224
225    TypeFromUser
226    GetTypeFromUser ();
227
228    uint8_t *
229    GetValueBytes ();
230
231    void
232    SetName (const ConstString &name);
233
234    void
235    ValueUpdated ();
236
237    // this function is used to copy the address-of m_live_sp into m_frozen_sp
238    // this is necessary because the results of certain cast and pointer-arithmetic
239    // operations (such as those described in bugzilla issues 11588 and 11618) generate
240    // frozen objcts that do not have a valid address-of, which can be troublesome when
241    // using synthetic children providers. transferring the address-of the live object
242    // solves these issues and provides the expected user-level behavior
243    void
244    TransferAddress (bool force = false);
245
246    typedef std::shared_ptr<ValueObjectConstResult> ValueObjectConstResultSP;
247
248    //----------------------------------------------------------------------
249    /// Members
250    //----------------------------------------------------------------------
251    enum Flags
252    {
253        EVNone                  = 0,
254        EVIsLLDBAllocated       = 1 << 0,   ///< This variable is resident in a location specifically allocated for it by LLDB in the target process
255        EVIsProgramReference    = 1 << 1,   ///< This variable is a reference to a (possibly invalid) area managed by the target program
256        EVNeedsAllocation       = 1 << 2,   ///< Space for this variable has yet to be allocated in the target process
257        EVIsFreezeDried         = 1 << 3,   ///< This variable's authoritative version is in m_frozen_sp (for example, for statically-computed results)
258        EVNeedsFreezeDry        = 1 << 4,   ///< Copy from m_live_sp to m_frozen_sp during dematerialization
259        EVKeepInTarget          = 1 << 5,   ///< Keep the allocation after the expression is complete rather than freeze drying its contents and freeing it
260        EVTypeIsReference       = 1 << 6,   ///< The original type of this variable is a reference, so materialize the value rather than the location
261        EVUnknownType           = 1 << 7,   ///< This is a symbol of unknown type, and the type must be resolved after parsing is complete
262        EVBareRegister          = 1 << 8    ///< This variable is a direct reference to $pc or some other entity.
263    };
264
265    typedef uint16_t FlagType;
266
267    FlagType m_flags; // takes elements of Flags
268
269    lldb::ValueObjectSP m_frozen_sp;
270    lldb::ValueObjectSP m_live_sp;
271
272    DISALLOW_COPY_AND_ASSIGN (ClangExpressionVariable);
273};
274
275//----------------------------------------------------------------------
276/// @class ClangExpressionVariableListBase ClangExpressionVariable.h "lldb/Expression/ClangExpressionVariable.h"
277/// @brief A list of variable references.
278///
279/// This class stores variables internally, acting as the permanent store.
280//----------------------------------------------------------------------
281class ClangExpressionVariableList
282{
283public:
284    //----------------------------------------------------------------------
285    /// Implementation of methods in ClangExpressionVariableListBase
286    //----------------------------------------------------------------------
287    size_t
288    GetSize()
289    {
290        return m_variables.size();
291    }
292
293    lldb::ClangExpressionVariableSP
294    GetVariableAtIndex(size_t index)
295    {
296        lldb::ClangExpressionVariableSP var_sp;
297        if (index < m_variables.size())
298            var_sp = m_variables[index];
299        return var_sp;
300    }
301
302    size_t
303    AddVariable (const lldb::ClangExpressionVariableSP &var_sp)
304    {
305        m_variables.push_back(var_sp);
306        return m_variables.size() - 1;
307    }
308
309    bool
310    ContainsVariable (const lldb::ClangExpressionVariableSP &var_sp)
311    {
312        const size_t size = m_variables.size();
313        for (size_t index = 0; index < size; ++index)
314        {
315            if (m_variables[index].get() == var_sp.get())
316                return true;
317        }
318        return false;
319    }
320
321    //----------------------------------------------------------------------
322    /// Finds a variable by name 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 ConstString &name)
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->GetName() == name)
338                return var_sp;
339        }
340        var_sp.reset();
341        return var_sp;
342    }
343
344    lldb::ClangExpressionVariableSP
345    GetVariable (const char *name)
346    {
347        lldb::ClangExpressionVariableSP var_sp;
348        if (name && name[0])
349        {
350            for (size_t index = 0, size = GetSize(); index < size; ++index)
351            {
352                var_sp = GetVariableAtIndex(index);
353                const char *var_name_cstr = var_sp->GetName().GetCString();
354                if (!var_name_cstr || !name)
355                    continue;
356                if (::strcmp (var_name_cstr, name) == 0)
357                    return var_sp;
358            }
359            var_sp.reset();
360        }
361        return var_sp;
362    }
363
364    //----------------------------------------------------------------------
365    /// Finds a variable by NamedDecl in the list.
366    ///
367    /// @param[in] name
368    ///     The name of the requested variable.
369    ///
370    /// @return
371    ///     The variable requested, or NULL if that variable is not in the list.
372    //----------------------------------------------------------------------
373    lldb::ClangExpressionVariableSP
374    GetVariable (const clang::NamedDecl *decl, uint64_t parser_id)
375    {
376        lldb::ClangExpressionVariableSP var_sp;
377        for (size_t index = 0, size = GetSize(); index < size; ++index)
378        {
379            var_sp = GetVariableAtIndex(index);
380
381            ClangExpressionVariable::ParserVars *parser_vars = var_sp->GetParserVars(parser_id);
382
383            if (parser_vars && parser_vars->m_named_decl == decl)
384                return var_sp;
385        }
386        var_sp.reset();
387        return var_sp;
388    }
389
390    //----------------------------------------------------------------------
391    /// Create a new variable in the list and return its index
392    //----------------------------------------------------------------------
393    lldb::ClangExpressionVariableSP
394    CreateVariable (ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size)
395    {
396        lldb::ClangExpressionVariableSP var_sp(new ClangExpressionVariable(exe_scope, byte_order, addr_byte_size));
397        m_variables.push_back(var_sp);
398        return var_sp;
399    }
400
401    lldb::ClangExpressionVariableSP
402    CreateVariable(const lldb::ValueObjectSP &valobj_sp)
403    {
404        lldb::ClangExpressionVariableSP var_sp(new ClangExpressionVariable(valobj_sp));
405        m_variables.push_back(var_sp);
406        return var_sp;
407    }
408
409    lldb::ClangExpressionVariableSP
410    CreateVariable (ExecutionContextScope *exe_scope,
411                    const ConstString &name,
412                    const TypeFromUser& user_type,
413                    lldb::ByteOrder byte_order,
414                    uint32_t addr_byte_size)
415    {
416        lldb::ClangExpressionVariableSP var_sp(new ClangExpressionVariable(exe_scope, byte_order, addr_byte_size));
417        var_sp->SetName (name);
418        var_sp->SetClangType (user_type);
419        m_variables.push_back(var_sp);
420        return var_sp;
421    }
422
423    void
424    RemoveVariable (lldb::ClangExpressionVariableSP var_sp)
425    {
426        for (std::vector<lldb::ClangExpressionVariableSP>::iterator vi = m_variables.begin(), ve = m_variables.end();
427             vi != ve;
428             ++vi)
429        {
430            if (vi->get() == var_sp.get())
431            {
432                m_variables.erase(vi);
433                return;
434            }
435        }
436    }
437
438    void
439    Clear()
440    {
441        m_variables.clear();
442    }
443
444private:
445    std::vector <lldb::ClangExpressionVariableSP> m_variables;
446};
447
448
449} // namespace lldb_private
450
451#endif  // liblldb_ClangExpressionVariable_h_
452