summaryrefslogtreecommitdiff
path: root/include/lldb/Expression/LLVMUserExpression.h
blob: 1ba822265fcaae4f91fef8d611d30c25f15b6892 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
//===-- LLVMUserExpression.h ------------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef liblldb_LLVMUserExpression_h
#define liblldb_LLVMUserExpression_h

#include <map>
#include <string>
#include <vector>

#include "llvm/IR/LegacyPassManager.h"

#include "lldb/Expression/UserExpression.h"

namespace lldb_private {

//----------------------------------------------------------------------
/// @class LLVMUserExpression LLVMUserExpression.h
/// "lldb/Expression/LLVMUserExpression.h" Encapsulates a one-time expression
/// for use in lldb.
///
/// LLDB uses expressions for various purposes, notably to call functions
/// and as a backend for the expr command.  LLVMUserExpression is a virtual
/// base class that encapsulates the objects needed to parse and JIT an
/// expression. The actual parsing part will be provided by the specific
/// implementations of LLVMUserExpression - which will be vended through the
/// appropriate TypeSystem.
//----------------------------------------------------------------------
class LLVMUserExpression : public UserExpression {
public:
  // The IRPasses struct is filled in by a runtime after an expression is
  // compiled and can be used to to run fixups/analysis passes as required.
  // EarlyPasses are run on the generated module before lldb runs its own IR
  // fixups and inserts instrumentation code/pointer checks. LatePasses are run
  // after the module has been processed by llvm, before the module is
  // assembled and run in the ThreadPlan.
  struct IRPasses {
    IRPasses() : EarlyPasses(nullptr), LatePasses(nullptr){};
    std::shared_ptr<llvm::legacy::PassManager> EarlyPasses;
    std::shared_ptr<llvm::legacy::PassManager> LatePasses;
  };

  LLVMUserExpression(ExecutionContextScope &exe_scope, llvm::StringRef expr,
                     llvm::StringRef prefix, lldb::LanguageType language,
                     ResultType desired_type,
                     const EvaluateExpressionOptions &options);
  ~LLVMUserExpression() override;

  bool FinalizeJITExecution(
      DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
      lldb::ExpressionVariableSP &result,
      lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS,
      lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS) override;

  bool CanInterpret() override { return m_can_interpret; }

  //------------------------------------------------------------------
  /// Return the string that the parser should parse.  Must be a full
  /// translation unit.
  //------------------------------------------------------------------
  const char *Text() override { return m_transformed_text.c_str(); }

  lldb::ModuleSP GetJITModule() override;

protected:
  lldb::ExpressionResults
  DoExecute(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx,
            const EvaluateExpressionOptions &options,
            lldb::UserExpressionSP &shared_ptr_to_me,
            lldb::ExpressionVariableSP &result) override;

  virtual void ScanContext(ExecutionContext &exe_ctx,
                           lldb_private::Status &err) = 0;

  bool PrepareToExecuteJITExpression(DiagnosticManager &diagnostic_manager,
                                     ExecutionContext &exe_ctx,
                                     lldb::addr_t &struct_address);

  virtual bool AddArguments(ExecutionContext &exe_ctx,
                            std::vector<lldb::addr_t> &args,
                            lldb::addr_t struct_address,
                            DiagnosticManager &diagnostic_manager) = 0;

  lldb::addr_t
      m_stack_frame_bottom;       ///< The bottom of the allocated stack frame.
  lldb::addr_t m_stack_frame_top; ///< The top of the allocated stack frame.

  bool m_allow_cxx;  ///< True if the language allows C++.
  bool m_allow_objc; ///< True if the language allows Objective-C.
  std::string
      m_transformed_text; ///< The text of the expression, as send to the parser

  std::shared_ptr<IRExecutionUnit>
      m_execution_unit_sp; ///< The execution unit the expression is stored in.
  std::unique_ptr<Materializer> m_materializer_ap; ///< The materializer to use
                                                   ///when running the
                                                   ///expression.
  lldb::ModuleWP m_jit_module_wp;
  bool m_enforce_valid_object; ///< True if the expression parser should enforce
                               ///the presence of a valid class pointer
  /// in order to generate the expression as a method.
  bool m_in_cplusplus_method;  ///< True if the expression is compiled as a C++
                               ///member function (true if it was parsed
                               /// when exe_ctx was in a C++ method).
  bool m_in_objectivec_method; ///< True if the expression is compiled as an
                               ///Objective-C method (true if it was parsed
                               /// when exe_ctx was in an Objective-C method).
  bool m_in_static_method; ///< True if the expression is compiled as a static
                           ///(or class) method (currently true if it
  /// was parsed when exe_ctx was in an Objective-C class method).
  bool m_needs_object_ptr; ///< True if "this" or "self" must be looked up and
                           ///passed in.  False if the expression
                           /// doesn't really use them and they can be NULL.
  bool m_const_object;     ///< True if "this" is const.
  Target *m_target; ///< The target for storing persistent data like types and
                    ///variables.

  bool m_can_interpret; ///< True if the expression could be evaluated
                        ///statically; false otherwise.
  lldb::addr_t m_materialized_address; ///< The address at which the arguments
                                       ///to the expression have been
                                       ///materialized.
  Materializer::DematerializerSP m_dematerializer_sp; ///< The dematerializer.
};

} // namespace lldb_private
#endif