1 | //===-- ClangUserExpression.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 LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGUSEREXPRESSION_H |
10 | #define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGUSEREXPRESSION_H |
11 | |
12 | #include <optional> |
13 | #include <vector> |
14 | |
15 | #include "ASTResultSynthesizer.h" |
16 | #include "ASTStructExtractor.h" |
17 | #include "ClangExpressionDeclMap.h" |
18 | #include "ClangExpressionHelper.h" |
19 | #include "ClangExpressionSourceCode.h" |
20 | #include "ClangExpressionVariable.h" |
21 | #include "IRForTarget.h" |
22 | |
23 | #include "lldb/Core/Address.h" |
24 | #include "lldb/Expression/LLVMUserExpression.h" |
25 | #include "lldb/Expression/Materializer.h" |
26 | #include "lldb/Target/ExecutionContext.h" |
27 | #include "lldb/lldb-forward.h" |
28 | #include "lldb/lldb-private.h" |
29 | |
30 | namespace lldb_private { |
31 | |
32 | class ClangExpressionParser; |
33 | |
34 | /// \class ClangUserExpression ClangUserExpression.h |
35 | /// "lldb/Expression/ClangUserExpression.h" Encapsulates a single expression |
36 | /// for use with Clang |
37 | /// |
38 | /// LLDB uses expressions for various purposes, notably to call functions |
39 | /// and as a backend for the expr command. ClangUserExpression encapsulates |
40 | /// the objects needed to parse and interpret or JIT an expression. It uses |
41 | /// the Clang parser to produce LLVM IR from the expression. |
42 | class ClangUserExpression : public LLVMUserExpression { |
43 | // LLVM RTTI support |
44 | static char ID; |
45 | |
46 | public: |
47 | bool isA(const void *ClassID) const override { |
48 | return ClassID == &ID || LLVMUserExpression::isA(ClassID); |
49 | } |
50 | static bool classof(const Expression *obj) { return obj->isA(ClassID: &ID); } |
51 | |
52 | enum { kDefaultTimeout = 500000u }; |
53 | |
54 | class ClangUserExpressionHelper |
55 | : public llvm::RTTIExtends<ClangUserExpressionHelper, |
56 | ClangExpressionHelper> { |
57 | public: |
58 | // LLVM RTTI support |
59 | static char ID; |
60 | |
61 | ClangUserExpressionHelper(Target &target, bool top_level) |
62 | : m_target(target), m_top_level(top_level) {} |
63 | |
64 | /// Return the object that the parser should use when resolving external |
65 | /// values. May be NULL if everything should be self-contained. |
66 | ClangExpressionDeclMap *DeclMap() override { |
67 | return m_expr_decl_map_up.get(); |
68 | } |
69 | |
70 | void ResetDeclMap() { m_expr_decl_map_up.reset(); } |
71 | |
72 | void ResetDeclMap(ExecutionContext &exe_ctx, |
73 | Materializer::PersistentVariableDelegate &result_delegate, |
74 | bool keep_result_in_memory, |
75 | ValueObject *ctx_obj); |
76 | |
77 | /// Return the object that the parser should allow to access ASTs. May be |
78 | /// NULL if the ASTs do not need to be transformed. |
79 | /// |
80 | /// \param[in] passthrough |
81 | /// The ASTConsumer that the returned transformer should send |
82 | /// the ASTs to after transformation. |
83 | clang::ASTConsumer * |
84 | ASTTransformer(clang::ASTConsumer *passthrough) override; |
85 | |
86 | void CommitPersistentDecls() override; |
87 | |
88 | private: |
89 | Target &m_target; |
90 | std::unique_ptr<ClangExpressionDeclMap> m_expr_decl_map_up; |
91 | std::unique_ptr<ASTStructExtractor> ; ///< The class |
92 | ///that generates |
93 | ///the argument |
94 | ///struct layout. |
95 | std::unique_ptr<ASTResultSynthesizer> m_result_synthesizer_up; |
96 | bool m_top_level; |
97 | }; |
98 | |
99 | /// Constructor |
100 | /// |
101 | /// \param[in] expr |
102 | /// The expression to parse. |
103 | /// |
104 | /// \param[in] prefix |
105 | /// If non-NULL, a C string containing translation-unit level |
106 | /// definitions to be included when the expression is parsed. |
107 | /// |
108 | /// \param[in] language |
109 | /// If not eLanguageTypeUnknown, a language to use when parsing |
110 | /// the expression. Currently restricted to those languages |
111 | /// supported by Clang. |
112 | /// |
113 | /// \param[in] desired_type |
114 | /// If not eResultTypeAny, the type to use for the expression |
115 | /// result. |
116 | /// |
117 | /// \param[in] options |
118 | /// Additional options for the expression. |
119 | /// |
120 | /// \param[in] ctx_obj |
121 | /// The object (if any) in which context the expression |
122 | /// must be evaluated. For details see the comment to |
123 | /// `UserExpression::Evaluate`. |
124 | ClangUserExpression(ExecutionContextScope &exe_scope, llvm::StringRef expr, |
125 | llvm::StringRef prefix, lldb::LanguageType language, |
126 | ResultType desired_type, |
127 | const EvaluateExpressionOptions &options, |
128 | ValueObject *ctx_obj); |
129 | |
130 | ~ClangUserExpression() override; |
131 | |
132 | /// Parse the expression |
133 | /// |
134 | /// \param[in] diagnostic_manager |
135 | /// A diagnostic manager to report parse errors and warnings to. |
136 | /// |
137 | /// \param[in] exe_ctx |
138 | /// The execution context to use when looking up entities that |
139 | /// are needed for parsing (locations of functions, types of |
140 | /// variables, persistent variables, etc.) |
141 | /// |
142 | /// \param[in] execution_policy |
143 | /// Determines whether interpretation is possible or mandatory. |
144 | /// |
145 | /// \param[in] keep_result_in_memory |
146 | /// True if the resulting persistent variable should reside in |
147 | /// target memory, if applicable. |
148 | /// |
149 | /// \return |
150 | /// True on success (no errors); false otherwise. |
151 | bool Parse(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, |
152 | lldb_private::ExecutionPolicy execution_policy, |
153 | bool keep_result_in_memory, bool generate_debug_info) override; |
154 | |
155 | bool Complete(ExecutionContext &exe_ctx, CompletionRequest &request, |
156 | unsigned complete_pos) override; |
157 | |
158 | ExpressionTypeSystemHelper *GetTypeSystemHelper() override { |
159 | return &m_type_system_helper; |
160 | } |
161 | |
162 | ClangExpressionDeclMap *DeclMap() { return m_type_system_helper.DeclMap(); } |
163 | |
164 | void ResetDeclMap() { m_type_system_helper.ResetDeclMap(); } |
165 | |
166 | void ResetDeclMap(ExecutionContext &exe_ctx, |
167 | Materializer::PersistentVariableDelegate &result_delegate, |
168 | bool keep_result_in_memory) { |
169 | m_type_system_helper.ResetDeclMap(exe_ctx, result_delegate, |
170 | keep_result_in_memory, |
171 | ctx_obj: m_ctx_obj); |
172 | } |
173 | |
174 | lldb::ExpressionVariableSP |
175 | GetResultAfterDematerialization(ExecutionContextScope *exe_scope) override; |
176 | |
177 | /// Returns true iff this expression is using any imported C++ modules. |
178 | bool DidImportCxxModules() const { return !m_imported_cpp_modules.empty(); } |
179 | |
180 | private: |
181 | /// Populate m_in_cplusplus_method and m_in_objectivec_method based on the |
182 | /// environment. |
183 | |
184 | /// Contains the actual parsing implementation. |
185 | /// The parameter have the same meaning as in ClangUserExpression::Parse. |
186 | /// \see ClangUserExpression::Parse |
187 | bool TryParse(DiagnosticManager &diagnostic_manager, |
188 | ExecutionContext &exe_ctx, |
189 | lldb_private::ExecutionPolicy execution_policy, |
190 | bool keep_result_in_memory, bool generate_debug_info); |
191 | |
192 | void SetupCppModuleImports(ExecutionContext &exe_ctx); |
193 | |
194 | void ScanContext(ExecutionContext &exe_ctx, |
195 | lldb_private::Status &err) override; |
196 | |
197 | bool AddArguments(ExecutionContext &exe_ctx, std::vector<lldb::addr_t> &args, |
198 | lldb::addr_t struct_address, |
199 | DiagnosticManager &diagnostic_manager) override; |
200 | |
201 | void CreateSourceCode(DiagnosticManager &diagnostic_manager, |
202 | ExecutionContext &exe_ctx, |
203 | std::vector<std::string> modules_to_import, |
204 | bool for_completion); |
205 | |
206 | lldb::addr_t GetCppObjectPointer(lldb::StackFrameSP frame, |
207 | llvm::StringRef object_name, Status &err); |
208 | |
209 | /// Defines how the current expression should be wrapped. |
210 | ClangExpressionSourceCode::WrapKind GetWrapKind() const; |
211 | bool SetupPersistentState(DiagnosticManager &diagnostic_manager, |
212 | ExecutionContext &exe_ctx); |
213 | bool PrepareForParsing(DiagnosticManager &diagnostic_manager, |
214 | ExecutionContext &exe_ctx, bool for_completion); |
215 | |
216 | ClangUserExpressionHelper m_type_system_helper; |
217 | |
218 | class ResultDelegate : public Materializer::PersistentVariableDelegate { |
219 | public: |
220 | ResultDelegate(lldb::TargetSP target) : m_target_sp(target) {} |
221 | ConstString GetName() override; |
222 | void DidDematerialize(lldb::ExpressionVariableSP &variable) override; |
223 | |
224 | void RegisterPersistentState(PersistentExpressionState *persistent_state); |
225 | lldb::ExpressionVariableSP &GetVariable(); |
226 | |
227 | private: |
228 | PersistentExpressionState *m_persistent_state; |
229 | lldb::ExpressionVariableSP m_variable; |
230 | lldb::TargetSP m_target_sp; |
231 | }; |
232 | |
233 | /// The include directories that should be used when parsing the expression. |
234 | std::vector<std::string> m_include_directories; |
235 | |
236 | /// The absolute character position in the transformed source code where the |
237 | /// user code (as typed by the user) starts. If the variable is empty, then we |
238 | /// were not able to calculate this position. |
239 | std::optional<size_t> m_user_expression_start_pos; |
240 | ResultDelegate m_result_delegate; |
241 | ClangPersistentVariables *m_clang_state; |
242 | std::unique_ptr<ClangExpressionSourceCode> m_source_code; |
243 | /// The parser instance we used to parse the expression. |
244 | std::unique_ptr<ClangExpressionParser> m_parser; |
245 | /// File name used for the expression. |
246 | std::string m_filename; |
247 | |
248 | /// The object (if any) in which context the expression is evaluated. |
249 | /// See the comment to `UserExpression::Evaluate` for details. |
250 | ValueObject *m_ctx_obj; |
251 | |
252 | /// A list of module names that should be imported when parsing. |
253 | /// \see CppModuleConfiguration::GetImportedModules |
254 | std::vector<std::string> m_imported_cpp_modules; |
255 | |
256 | /// True if the expression parser should enforce the presence of a valid class |
257 | /// pointer in order to generate the expression as a method. |
258 | bool m_enforce_valid_object = true; |
259 | /// True if the expression is compiled as a C++ member function (true if it |
260 | /// was parsed when exe_ctx was in a C++ method). |
261 | bool m_in_cplusplus_method = false; |
262 | /// True if the expression is compiled as an Objective-C method (true if it |
263 | /// was parsed when exe_ctx was in an Objective-C method). |
264 | bool m_in_objectivec_method = false; |
265 | /// True if the expression is compiled as a static (or class) method |
266 | /// (currently true if it was parsed when exe_ctx was in an Objective-C class |
267 | /// method). |
268 | bool m_in_static_method = false; |
269 | /// True if "this" or "self" must be looked up and passed in. False if the |
270 | /// expression doesn't really use them and they can be NULL. |
271 | bool m_needs_object_ptr = false; |
272 | }; |
273 | |
274 | } // namespace lldb_private |
275 | |
276 | #endif // LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGUSEREXPRESSION_H |
277 | |