| 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 unknown, a language to use when parsing the |
| 110 | /// 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, SourceLanguage 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 | llvm::StringRef GetFilename() const { return m_filename; } |
| 181 | |
| 182 | private: |
| 183 | /// Populate m_in_cplusplus_method and m_in_objectivec_method based on the |
| 184 | /// environment. |
| 185 | |
| 186 | /// Contains the actual parsing implementation. |
| 187 | /// The parameter have the same meaning as in ClangUserExpression::Parse. |
| 188 | /// \see ClangUserExpression::Parse |
| 189 | bool TryParse(DiagnosticManager &diagnostic_manager, |
| 190 | ExecutionContext &exe_ctx, |
| 191 | lldb_private::ExecutionPolicy execution_policy, |
| 192 | bool keep_result_in_memory, bool generate_debug_info); |
| 193 | |
| 194 | void SetupCppModuleImports(ExecutionContext &exe_ctx); |
| 195 | |
| 196 | void ScanContext(ExecutionContext &exe_ctx, |
| 197 | lldb_private::Status &err) override; |
| 198 | |
| 199 | bool AddArguments(ExecutionContext &exe_ctx, std::vector<lldb::addr_t> &args, |
| 200 | lldb::addr_t struct_address, |
| 201 | DiagnosticManager &diagnostic_manager) override; |
| 202 | |
| 203 | void CreateSourceCode(DiagnosticManager &diagnostic_manager, |
| 204 | ExecutionContext &exe_ctx, |
| 205 | std::vector<std::string> modules_to_import, |
| 206 | bool for_completion); |
| 207 | |
| 208 | lldb::addr_t GetCppObjectPointer(lldb::StackFrameSP frame, |
| 209 | llvm::StringRef object_name, Status &err); |
| 210 | |
| 211 | /// Defines how the current expression should be wrapped. |
| 212 | ClangExpressionSourceCode::WrapKind GetWrapKind() const; |
| 213 | bool SetupPersistentState(DiagnosticManager &diagnostic_manager, |
| 214 | ExecutionContext &exe_ctx); |
| 215 | bool PrepareForParsing(DiagnosticManager &diagnostic_manager, |
| 216 | ExecutionContext &exe_ctx, bool for_completion); |
| 217 | |
| 218 | ClangUserExpressionHelper m_type_system_helper; |
| 219 | |
| 220 | class ResultDelegate : public Materializer::PersistentVariableDelegate { |
| 221 | public: |
| 222 | ResultDelegate(lldb::TargetSP target) : m_target_sp(target) {} |
| 223 | ConstString GetName() override; |
| 224 | void DidDematerialize(lldb::ExpressionVariableSP &variable) override; |
| 225 | |
| 226 | void RegisterPersistentState(PersistentExpressionState *persistent_state); |
| 227 | lldb::ExpressionVariableSP &GetVariable(); |
| 228 | |
| 229 | private: |
| 230 | PersistentExpressionState *m_persistent_state; |
| 231 | lldb::ExpressionVariableSP m_variable; |
| 232 | lldb::TargetSP m_target_sp; |
| 233 | }; |
| 234 | |
| 235 | /// The include directories that should be used when parsing the expression. |
| 236 | std::vector<std::string> m_include_directories; |
| 237 | |
| 238 | /// The absolute character position in the transformed source code where the |
| 239 | /// user code (as typed by the user) starts. If the variable is empty, then we |
| 240 | /// were not able to calculate this position. |
| 241 | std::optional<size_t> m_user_expression_start_pos; |
| 242 | ResultDelegate m_result_delegate; |
| 243 | ClangPersistentVariables *m_clang_state; |
| 244 | std::unique_ptr<ClangExpressionSourceCode> m_source_code; |
| 245 | /// The parser instance we used to parse the expression. |
| 246 | std::unique_ptr<ClangExpressionParser> m_parser; |
| 247 | /// File name used for the expression. |
| 248 | std::string m_filename; |
| 249 | |
| 250 | /// The object (if any) in which context the expression is evaluated. |
| 251 | /// See the comment to `UserExpression::Evaluate` for details. |
| 252 | ValueObject *m_ctx_obj; |
| 253 | |
| 254 | /// A list of module names that should be imported when parsing. |
| 255 | /// \see CppModuleConfiguration::GetImportedModules |
| 256 | std::vector<std::string> m_imported_cpp_modules; |
| 257 | |
| 258 | /// True if the expression parser should enforce the presence of a valid class |
| 259 | /// pointer in order to generate the expression as a method. |
| 260 | bool m_enforce_valid_object = true; |
| 261 | /// True if the expression is compiled as a C++ member function (true if it |
| 262 | /// was parsed when exe_ctx was in a C++ method). |
| 263 | bool m_in_cplusplus_method = false; |
| 264 | /// True if the expression is compiled as an Objective-C method (true if it |
| 265 | /// was parsed when exe_ctx was in an Objective-C method). |
| 266 | bool m_in_objectivec_method = false; |
| 267 | /// True if the expression is compiled as a static (or class) method |
| 268 | /// (currently true if it was parsed when exe_ctx was in an Objective-C class |
| 269 | /// method). |
| 270 | bool m_in_static_method = false; |
| 271 | /// True if "this" or "self" must be looked up and passed in. False if the |
| 272 | /// expression doesn't really use them and they can be NULL. |
| 273 | bool m_needs_object_ptr = false; |
| 274 | }; |
| 275 | |
| 276 | } // namespace lldb_private |
| 277 | |
| 278 | #endif // LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGUSEREXPRESSION_H |
| 279 | |