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 liblldb_ClangUserExpression_h_ 10 #define liblldb_ClangUserExpression_h_ 11 12 #include <vector> 13 14 #include "ASTResultSynthesizer.h" 15 #include "ASTStructExtractor.h" 16 #include "ClangExpressionDeclMap.h" 17 #include "ClangExpressionHelper.h" 18 #include "ClangExpressionVariable.h" 19 #include "IRForTarget.h" 20 21 #include "lldb/Core/Address.h" 22 #include "lldb/Core/ClangForward.h" 23 #include "lldb/Expression/LLVMUserExpression.h" 24 #include "lldb/Expression/Materializer.h" 25 #include "lldb/Target/ExecutionContext.h" 26 #include "lldb/lldb-forward.h" 27 #include "lldb/lldb-private.h" 28 29 namespace lldb_private { 30 31 /// \class ClangUserExpression ClangUserExpression.h 32 /// "lldb/Expression/ClangUserExpression.h" Encapsulates a single expression 33 /// for use with Clang 34 /// 35 /// LLDB uses expressions for various purposes, notably to call functions 36 /// and as a backend for the expr command. ClangUserExpression encapsulates 37 /// the objects needed to parse and interpret or JIT an expression. It uses 38 /// the Clang parser to produce LLVM IR from the expression. 39 class ClangUserExpression : public LLVMUserExpression { 40 public: 41 /// LLVM-style RTTI support. 42 static bool classof(const Expression *E) { 43 return E->getKind() == eKindClangUserExpression; 44 } 45 46 enum { kDefaultTimeout = 500000u }; 47 48 class ClangUserExpressionHelper : public ClangExpressionHelper { 49 public: 50 ClangUserExpressionHelper(Target &target, bool top_level) 51 : m_target(target), m_top_level(top_level) {} 52 53 ~ClangUserExpressionHelper() override = default; 54 55 /// Return the object that the parser should use when resolving external 56 /// values. May be NULL if everything should be self-contained. 57 ClangExpressionDeclMap *DeclMap() override { 58 return m_expr_decl_map_up.get(); 59 } 60 61 void ResetDeclMap() { m_expr_decl_map_up.reset(); } 62 63 void ResetDeclMap(ExecutionContext &exe_ctx, 64 Materializer::PersistentVariableDelegate &result_delegate, 65 bool keep_result_in_memory, 66 ValueObject *ctx_obj); 67 68 /// Return the object that the parser should allow to access ASTs. May be 69 /// NULL if the ASTs do not need to be transformed. 70 /// 71 /// \param[in] passthrough 72 /// The ASTConsumer that the returned transformer should send 73 /// the ASTs to after transformation. 74 clang::ASTConsumer * 75 ASTTransformer(clang::ASTConsumer *passthrough) override; 76 77 void CommitPersistentDecls() override; 78 79 private: 80 Target &m_target; 81 std::unique_ptr<ClangExpressionDeclMap> m_expr_decl_map_up; 82 std::unique_ptr<ASTStructExtractor> m_struct_extractor_up; ///< The class 83 ///that generates 84 ///the argument 85 ///struct layout. 86 std::unique_ptr<ASTResultSynthesizer> m_result_synthesizer_up; 87 bool m_top_level; 88 }; 89 90 /// Constructor 91 /// 92 /// \param[in] expr 93 /// The expression to parse. 94 /// 95 /// \param[in] expr_prefix 96 /// If non-NULL, a C string containing translation-unit level 97 /// definitions to be included when the expression is parsed. 98 /// 99 /// \param[in] language 100 /// If not eLanguageTypeUnknown, a language to use when parsing 101 /// the expression. Currently restricted to those languages 102 /// supported by Clang. 103 /// 104 /// \param[in] desired_type 105 /// If not eResultTypeAny, the type to use for the expression 106 /// result. 107 /// 108 /// \param[in] ctx_obj 109 /// The object (if any) in which context the expression 110 /// must be evaluated. For details see the comment to 111 /// `UserExpression::Evaluate`. 112 ClangUserExpression(ExecutionContextScope &exe_scope, llvm::StringRef expr, 113 llvm::StringRef prefix, lldb::LanguageType language, 114 ResultType desired_type, 115 const EvaluateExpressionOptions &options, 116 ValueObject *ctx_obj); 117 118 ~ClangUserExpression() override; 119 120 /// Parse the expression 121 /// 122 /// \param[in] diagnostic_manager 123 /// A diagnostic manager to report parse errors and warnings to. 124 /// 125 /// \param[in] exe_ctx 126 /// The execution context to use when looking up entities that 127 /// are needed for parsing (locations of functions, types of 128 /// variables, persistent variables, etc.) 129 /// 130 /// \param[in] execution_policy 131 /// Determines whether interpretation is possible or mandatory. 132 /// 133 /// \param[in] keep_result_in_memory 134 /// True if the resulting persistent variable should reside in 135 /// target memory, if applicable. 136 /// 137 /// \return 138 /// True on success (no errors); false otherwise. 139 bool Parse(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, 140 lldb_private::ExecutionPolicy execution_policy, 141 bool keep_result_in_memory, bool generate_debug_info) override; 142 143 bool Complete(ExecutionContext &exe_ctx, CompletionRequest &request, 144 unsigned complete_pos) override; 145 146 ExpressionTypeSystemHelper *GetTypeSystemHelper() override { 147 return &m_type_system_helper; 148 } 149 150 ClangExpressionDeclMap *DeclMap() { return m_type_system_helper.DeclMap(); } 151 152 void ResetDeclMap() { m_type_system_helper.ResetDeclMap(); } 153 154 void ResetDeclMap(ExecutionContext &exe_ctx, 155 Materializer::PersistentVariableDelegate &result_delegate, 156 bool keep_result_in_memory) { 157 m_type_system_helper.ResetDeclMap(exe_ctx, result_delegate, 158 keep_result_in_memory, 159 m_ctx_obj); 160 } 161 162 lldb::ExpressionVariableSP 163 GetResultAfterDematerialization(ExecutionContextScope *exe_scope) override; 164 165 bool DidImportCxxModules() const { return m_imported_cpp_modules; } 166 167 private: 168 /// Populate m_in_cplusplus_method and m_in_objectivec_method based on the 169 /// environment. 170 171 void ScanContext(ExecutionContext &exe_ctx, 172 lldb_private::Status &err) override; 173 174 bool AddArguments(ExecutionContext &exe_ctx, std::vector<lldb::addr_t> &args, 175 lldb::addr_t struct_address, 176 DiagnosticManager &diagnostic_manager) override; 177 178 std::vector<std::string> GetModulesToImport(ExecutionContext &exe_ctx); 179 void UpdateLanguageForExpr(DiagnosticManager &diagnostic_manager, 180 ExecutionContext &exe_ctx, 181 std::vector<std::string> modules_to_import, 182 bool for_completion); 183 bool SetupPersistentState(DiagnosticManager &diagnostic_manager, 184 ExecutionContext &exe_ctx); 185 bool PrepareForParsing(DiagnosticManager &diagnostic_manager, 186 ExecutionContext &exe_ctx, bool for_completion); 187 188 ClangUserExpressionHelper m_type_system_helper; 189 190 class ResultDelegate : public Materializer::PersistentVariableDelegate { 191 public: 192 ResultDelegate(lldb::TargetSP target) : m_target_sp(target) {} 193 ConstString GetName() override; 194 void DidDematerialize(lldb::ExpressionVariableSP &variable) override; 195 196 void RegisterPersistentState(PersistentExpressionState *persistent_state); 197 lldb::ExpressionVariableSP &GetVariable(); 198 199 private: 200 PersistentExpressionState *m_persistent_state; 201 lldb::ExpressionVariableSP m_variable; 202 lldb::TargetSP m_target_sp; 203 }; 204 205 /// The language type of the current expression. 206 lldb::LanguageType m_expr_lang = lldb::eLanguageTypeUnknown; 207 /// The include directories that should be used when parsing the expression. 208 std::vector<ConstString> m_include_directories; 209 210 /// The absolute character position in the transformed source code where the 211 /// user code (as typed by the user) starts. If the variable is empty, then we 212 /// were not able to calculate this position. 213 llvm::Optional<size_t> m_user_expression_start_pos; 214 ResultDelegate m_result_delegate; 215 216 /// The object (if any) in which context the expression is evaluated. 217 /// See the comment to `UserExpression::Evaluate` for details. 218 ValueObject *m_ctx_obj; 219 220 /// True iff this expression explicitly imported C++ modules. 221 bool m_imported_cpp_modules = false; 222 }; 223 224 } // namespace lldb_private 225 226 #endif // liblldb_ClangUserExpression_h_ 227