summaryrefslogtreecommitdiffstats
path: root/lldb
diff options
context:
space:
mode:
authorJim Ingham <jingham@apple.com>2015-09-15 21:13:50 +0000
committerJim Ingham <jingham@apple.com>2015-09-15 21:13:50 +0000
commit151c032c86aa7de4244a9ed52d420ecb09550d0b (patch)
tree44f8d890499ac2e99bb2a4fd50975f7c986d72a8 /lldb
parent01fa3f96b37499e43d0d26b46151268b1b891342 (diff)
downloadbcm5719-llvm-151c032c86aa7de4244a9ed52d420ecb09550d0b.tar.gz
bcm5719-llvm-151c032c86aa7de4244a9ed52d420ecb09550d0b.zip
This patch makes Clang-independent base classes for all the expression types that lldb currently vends.
Before we had: ClangFunction ClangUtilityFunction ClangUserExpression and code all over in lldb that explicitly made Clang-based expressions. This patch adds an Expression base class, and three pure virtual implementations for the Expression kinds: FunctionCaller UtilityFunction UserExpression You can request one of these expression types from the Target using the Get<ExpressionType>ForLanguage. The Target will then consult all the registered TypeSystem plugins, and if the type system that matches the language can make an expression of that kind, it will do so and return it. Because all of the real expression types need to communicate with their ExpressionParser in a uniform way, I also added a ExpressionTypeSystemHelper class that expressions generically can vend, and a ClangExpressionHelper that encapsulates the operations that the ClangExpressionParser needs to perform on the ClangExpression types. Then each of the Clang* expression kinds constructs the appropriate helper to do what it needs. The patch also fixes a wart in the UtilityFunction that to use it you had to create a parallel FunctionCaller to actually call the function made by the UtilityFunction. Now the UtilityFunction can be asked to vend a FunctionCaller that will run its function. This cleaned up a lot of boiler plate code using UtilityFunctions. Note, in this patch all the expression types explicitly depend on the LLVM JIT and IR, and all the common JIT running code is in the FunctionCaller etc base classes. At some point we could also abstract that dependency but I don't see us adding another back end in the near term, so I'll leave that exercise till it is actually necessary. llvm-svn: 247720
Diffstat (limited to 'lldb')
-rw-r--r--lldb/include/lldb/Breakpoint/BreakpointLocation.h5
-rw-r--r--lldb/include/lldb/Breakpoint/Watchpoint.h2
-rw-r--r--lldb/include/lldb/Expression/ASTStructExtractor.h12
-rw-r--r--lldb/include/lldb/Expression/ClangExpressionHelper.h79
-rw-r--r--lldb/include/lldb/Expression/ClangExpressionParser.h32
-rw-r--r--lldb/include/lldb/Expression/ClangFunctionCaller.h175
-rw-r--r--lldb/include/lldb/Expression/ClangUserExpression.h315
-rw-r--r--lldb/include/lldb/Expression/ClangUtilityFunction.h175
-rw-r--r--lldb/include/lldb/Expression/Expression.h (renamed from lldb/include/lldb/Expression/ClangExpression.h)61
-rw-r--r--lldb/include/lldb/Expression/ExpressionParser.h129
-rw-r--r--lldb/include/lldb/Expression/ExpressionTypeSystemHelper.h54
-rw-r--r--lldb/include/lldb/Expression/FunctionCaller.h (renamed from lldb/include/lldb/Expression/ClangFunction.h)94
-rw-r--r--lldb/include/lldb/Expression/IRDynamicChecks.h5
-rw-r--r--lldb/include/lldb/Expression/IRExecutionUnit.h1
-rw-r--r--lldb/include/lldb/Expression/UserExpression.h361
-rw-r--r--lldb/include/lldb/Expression/UtilityFunction.h166
-rw-r--r--lldb/include/lldb/Symbol/ClangASTContext.h26
-rw-r--r--lldb/include/lldb/Symbol/TypeSystem.h26
-rw-r--r--lldb/include/lldb/Target/LanguageRuntime.h6
-rw-r--r--lldb/include/lldb/Target/ObjCLanguageRuntime.h4
-rw-r--r--lldb/include/lldb/Target/Process.h2
-rw-r--r--lldb/include/lldb/Target/Target.h42
-rw-r--r--lldb/include/lldb/Target/ThreadPlanCallFunction.h2
-rw-r--r--lldb/include/lldb/Target/ThreadPlanCallUserExpression.h4
-rw-r--r--lldb/include/lldb/lldb-forward.h14
-rw-r--r--lldb/lldb.xcodeproj/project.pbxproj52
-rw-r--r--lldb/source/API/SBFrame.cpp2
-rw-r--r--lldb/source/Breakpoint/BreakpointLocation.cpp33
-rw-r--r--lldb/source/Breakpoint/BreakpointOptions.cpp1
-rw-r--r--lldb/source/Breakpoint/Watchpoint.cpp14
-rw-r--r--lldb/source/Breakpoint/WatchpointOptions.cpp1
-rw-r--r--lldb/source/Commands/CommandObjectArgs.cpp2
-rw-r--r--lldb/source/Commands/CommandObjectExpression.cpp5
-rw-r--r--lldb/source/DataFormatters/VectorType.cpp2
-rw-r--r--lldb/source/Expression/ASTStructExtractor.cpp2
-rw-r--r--lldb/source/Expression/CMakeLists.txt6
-rw-r--r--lldb/source/Expression/ClangASTSource.cpp1
-rw-r--r--lldb/source/Expression/ClangExpressionParser.cpp33
-rw-r--r--lldb/source/Expression/ClangFunctionCaller.cpp220
-rw-r--r--lldb/source/Expression/ClangUserExpression.cpp669
-rw-r--r--lldb/source/Expression/ClangUtilityFunction.cpp36
-rw-r--r--lldb/source/Expression/Expression.cpp32
-rw-r--r--lldb/source/Expression/FunctionCaller.cpp (renamed from lldb/source/Expression/ClangFunction.cpp)222
-rw-r--r--lldb/source/Expression/IRDynamicChecks.cpp13
-rw-r--r--lldb/source/Expression/UserExpression.cpp644
-rw-r--r--lldb/source/Expression/UtilityFunction.cpp123
-rw-r--r--lldb/source/Plugins/Language/ObjC/CoreMedia.cpp2
-rw-r--r--lldb/source/Plugins/Language/ObjC/NSArray.cpp1
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp2
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp55
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h4
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp9
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h2
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp208
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h12
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp98
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h7
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp14
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h6
-rw-r--r--lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp112
-rw-r--r--lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.h9
-rw-r--r--lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp99
-rw-r--r--lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.h8
-rw-r--r--lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp117
-rw-r--r--lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.h8
-rw-r--r--lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp109
-rw-r--r--lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.h8
-rw-r--r--lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp2
-rw-r--r--lldb/source/Symbol/ClangASTContext.cpp54
-rw-r--r--lldb/source/Target/Process.cpp29
-rw-r--r--lldb/source/Target/StopInfo.cpp15
-rw-r--r--lldb/source/Target/Target.cpp120
-rw-r--r--lldb/source/Target/ThreadPlanCallUserExpression.cpp4
73 files changed, 3062 insertions, 1957 deletions
diff --git a/lldb/include/lldb/Breakpoint/BreakpointLocation.h b/lldb/include/lldb/Breakpoint/BreakpointLocation.h
index b2b8ebdc55e..c8b66629317 100644
--- a/lldb/include/lldb/Breakpoint/BreakpointLocation.h
+++ b/lldb/include/lldb/Breakpoint/BreakpointLocation.h
@@ -74,6 +74,9 @@ public:
//------------------------------------------------------------------
Breakpoint &
GetBreakpoint ();
+
+ Target &
+ GetTarget();
//------------------------------------------------------------------
/// Determines whether we should stop due to a hit at this
@@ -458,7 +461,7 @@ private:
Breakpoint &m_owner; ///< The breakpoint that produced this object.
std::unique_ptr<BreakpointOptions> m_options_ap; ///< Breakpoint options pointer, NULL if we're using our breakpoint's options.
lldb::BreakpointSiteSP m_bp_site_sp; ///< Our breakpoint site (it may be shared by more than one location.)
- lldb::ClangUserExpressionSP m_user_expression_sp; ///< The compiled expression to use in testing our condition.
+ lldb::UserExpressionSP m_user_expression_sp; ///< The compiled expression to use in testing our condition.
Mutex m_condition_mutex; ///< Guards parsing and evaluation of the condition, which could be evaluated by multiple processes.
size_t m_condition_hash; ///< For testing whether the condition source code changed.
diff --git a/lldb/include/lldb/Breakpoint/Watchpoint.h b/lldb/include/lldb/Breakpoint/Watchpoint.h
index 14c2ae75b71..b6c3c1c9fc8 100644
--- a/lldb/include/lldb/Breakpoint/Watchpoint.h
+++ b/lldb/include/lldb/Breakpoint/Watchpoint.h
@@ -243,7 +243,7 @@ private:
// the callback machinery.
bool m_being_created;
- std::unique_ptr<ClangUserExpression> m_condition_ap; // The condition to test.
+ std::unique_ptr<UserExpression> m_condition_ap; // The condition to test.
void SetID(lldb::watch_id_t id) { m_loc_id = id; }
diff --git a/lldb/include/lldb/Expression/ASTStructExtractor.h b/lldb/include/lldb/Expression/ASTStructExtractor.h
index 1cba98b9ef3..af327ecfd01 100644
--- a/lldb/include/lldb/Expression/ASTStructExtractor.h
+++ b/lldb/include/lldb/Expression/ASTStructExtractor.h
@@ -13,7 +13,7 @@
#include "clang/Sema/SemaConsumer.h"
#include "lldb/Core/ClangForward.h"
#include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h"
-#include "lldb/Expression/ClangFunction.h"
+#include "lldb/Expression/ClangFunctionCaller.h"
namespace lldb_private {
@@ -21,9 +21,9 @@ namespace lldb_private {
/// @class ASTStructExtractor ASTStructExtractor.h "lldb/Expression/ASTStructExtractor.h"
/// @brief Extracts and describes the argument structure for a wrapped function.
///
-/// This pass integrates with ClangFunction, which calls functions with custom
+/// This pass integrates with ClangFunctionCaller, which calls functions with custom
/// sets of arguments. To avoid having to implement the full calling convention
-/// for the target's architecture, ClangFunction writes a simple wrapper
+/// for the target's architecture, ClangFunctionCaller writes a simple wrapper
/// function that takes a pointer to an argument structure that contains room
/// for the address of the function to be called, the values of all its
/// arguments, and room for the function's return value.
@@ -49,12 +49,12 @@ public:
///
/// @param[in] function
/// The caller object whose members should be populated with information
- /// about the argument struct. ClangFunction friends ASTStructExtractor
+ /// about the argument struct. ClangFunctionCaller friends ASTStructExtractor
/// for this purpose.
//----------------------------------------------------------------------
ASTStructExtractor(clang::ASTConsumer *passthrough,
const char *struct_name,
- ClangFunction &function);
+ ClangFunctionCaller &function);
//----------------------------------------------------------------------
/// Destructor
@@ -148,7 +148,7 @@ private:
clang::Sema *m_sema; ///< The Sema to use.
clang::Action *m_action; ///< The Sema to use, cast to an Action so it's usable.
- ClangFunction &m_function; ///< The function to populate with information about the argument structure.
+ ClangFunctionCaller &m_function; ///< The function to populate with information about the argument structure.
std::string m_struct_name; ///< The name of the structure to extract.
};
diff --git a/lldb/include/lldb/Expression/ClangExpressionHelper.h b/lldb/include/lldb/Expression/ClangExpressionHelper.h
new file mode 100644
index 00000000000..bb620def691
--- /dev/null
+++ b/lldb/include/lldb/Expression/ClangExpressionHelper.h
@@ -0,0 +1,79 @@
+//===-- ClangExpression.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_ClangExpression_h_
+#define liblldb_ClangExpression_h_
+
+// C Includes
+// C++ Includes
+#include <string>
+#include <map>
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ClangForward.h"
+#include "lldb/Expression/ExpressionTypeSystemHelper.h"
+
+namespace lldb_private {
+
+class RecordingMemoryManager;
+
+//----------------------------------------------------------------------
+// ClangExpressionHelper
+//----------------------------------------------------------------------
+class ClangExpressionHelper : public ExpressionTypeSystemHelper
+{
+public:
+ static bool classof(const ExpressionTypeSystemHelper *ts)
+ {
+ return ts->getKind() == eKindClangHelper;
+ }
+
+ ClangExpressionHelper () :
+ ExpressionTypeSystemHelper(ExpressionTypeSystemHelper::LLVMCastKind::eKindClangHelper)
+ {
+ }
+
+ //------------------------------------------------------------------
+ /// Destructor
+ //------------------------------------------------------------------
+ virtual ~ClangExpressionHelper ()
+ {
+ }
+
+ //------------------------------------------------------------------
+ /// Return the object that the parser should use when resolving external
+ /// values. May be NULL if everything should be self-contained.
+ //------------------------------------------------------------------
+ virtual ClangExpressionDeclMap *
+ DeclMap () = 0;
+
+ //------------------------------------------------------------------
+ /// Return the object that the parser should allow to access ASTs.
+ /// May be NULL if the ASTs do not need to be transformed.
+ ///
+ /// @param[in] passthrough
+ /// The ASTConsumer that the returned transformer should send
+ /// the ASTs to after transformation.
+ //------------------------------------------------------------------
+ virtual clang::ASTConsumer *
+ ASTTransformer (clang::ASTConsumer *passthrough) = 0;
+
+
+protected:
+
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_ClangExpression_h_
diff --git a/lldb/include/lldb/Expression/ClangExpressionParser.h b/lldb/include/lldb/Expression/ClangExpressionParser.h
index 1b78cb8d1e9..e828d1b6597 100644
--- a/lldb/include/lldb/Expression/ClangExpressionParser.h
+++ b/lldb/include/lldb/Expression/ClangExpressionParser.h
@@ -14,6 +14,7 @@
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/ClangForward.h"
#include "lldb/Core/Error.h"
+#include "lldb/Expression/ExpressionParser.h"
#include "lldb/Expression/IRForTarget.h"
#include <string>
@@ -34,7 +35,7 @@ class IRExecutionUnit;
/// conversion to formats (DWARF bytecode, or JIT compiled machine code)
/// that can be executed.
//----------------------------------------------------------------------
-class ClangExpressionParser
+class ClangExpressionParser : public ExpressionParser
{
public:
//------------------------------------------------------------------
@@ -51,13 +52,13 @@ public:
/// The expression to be parsed.
//------------------------------------------------------------------
ClangExpressionParser (ExecutionContextScope *exe_scope,
- ClangExpression &expr,
+ Expression &expr,
bool generate_debug_info);
//------------------------------------------------------------------
/// Destructor
//------------------------------------------------------------------
- ~ClangExpressionParser ();
+ ~ClangExpressionParser () override;
//------------------------------------------------------------------
/// Parse a single expression and convert it to IR using Clang. Don't
@@ -71,7 +72,7 @@ public:
/// success.
//------------------------------------------------------------------
unsigned
- Parse (Stream &stream);
+ Parse (Stream &stream) override;
//------------------------------------------------------------------
/// Ready an already-parsed expression for execution, possibly
@@ -116,30 +117,9 @@ public:
std::shared_ptr<IRExecutionUnit> &execution_unit_sp,
ExecutionContext &exe_ctx,
bool &can_interpret,
- lldb_private::ExecutionPolicy execution_policy);
+ lldb_private::ExecutionPolicy execution_policy) override;
- //------------------------------------------------------------------
- /// Disassemble the machine code for a JITted function from the target
- /// process's memory and print the result to a stream.
- ///
- /// @param[in] stream
- /// The stream to print disassembly to.
- ///
- /// @param[in] exc_context
- /// The execution context to get the machine code from.
- ///
- /// @return
- /// The error generated. If .Success() is true, disassembly succeeded.
- //------------------------------------------------------------------
- Error
- DisassembleFunction (Stream &stream,
- ExecutionContext &exe_ctx);
-
- bool
- GetGenerateDebugInfo () const;
-
private:
- ClangExpression & m_expr; ///< The expression to be parsed
std::unique_ptr<llvm::LLVMContext> m_llvm_context; ///< The LLVM context to generate IR into
std::unique_ptr<clang::FileManager> m_file_manager; ///< The Clang file manager object used by the compiler
std::unique_ptr<clang::CompilerInstance> m_compiler; ///< The Clang compiler used to parse expressions into IR
diff --git a/lldb/include/lldb/Expression/ClangFunctionCaller.h b/lldb/include/lldb/Expression/ClangFunctionCaller.h
new file mode 100644
index 00000000000..7922f14edd8
--- /dev/null
+++ b/lldb/include/lldb/Expression/ClangFunctionCaller.h
@@ -0,0 +1,175 @@
+//===-- ClangFunctionCaller.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_ClangFunctionCaller_h_
+#define liblldb_ClangFunctionCaller_h_
+
+// C Includes
+// C++ Includes
+#include <vector>
+#include <list>
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Core/ClangForward.h"
+#include "lldb/Core/Address.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Core/ValueObjectList.h"
+#include "lldb/Expression/ClangExpressionHelper.h"
+#include "lldb/Expression/FunctionCaller.h"
+#include "lldb/Symbol/CompilerType.h"
+#include "lldb/Target/Process.h"
+
+namespace lldb_private
+{
+
+class ASTStructExtractor;
+class ClangExpressionParser;
+
+//----------------------------------------------------------------------
+/// @class ClangFunctionCaller ClangFunctionCaller.h "lldb/Expression/ClangFunctionCaller.h"
+/// @brief Encapsulates a function that can be called.
+///
+/// A given ClangFunctionCaller object can handle a single function signature.
+/// Once constructed, it can set up any number of concurrent calls to
+/// functions with that signature.
+///
+/// It performs the call by synthesizing a structure that contains the pointer
+/// to the function and the arguments that should be passed to that function,
+/// and producing a special-purpose JIT-compiled function that accepts a void*
+/// pointing to this struct as its only argument and calls the function in the
+/// struct with the written arguments. This method lets Clang handle the
+/// vagaries of function calling conventions.
+///
+/// The simplest use of the ClangFunctionCaller is to construct it with a
+/// function representative of the signature you want to use, then call
+/// ExecuteFunction(ExecutionContext &, Stream &, Value &).
+///
+/// If you need to reuse the arguments for several calls, you can call
+/// InsertFunction() followed by WriteFunctionArguments(), which will return
+/// the location of the args struct for the wrapper function in args_addr_ref.
+///
+/// If you need to call the function on the thread plan stack, you can also
+/// call InsertFunction() followed by GetThreadPlanToCallFunction().
+///
+/// Any of the methods that take arg_addr_ptr or arg_addr_ref can be passed
+/// a pointer set to LLDB_INVALID_ADDRESS and new structure will be allocated
+/// and its address returned in that variable.
+///
+/// Any of the methods that take arg_addr_ptr can be passed NULL, and the
+/// argument space will be managed for you.
+//----------------------------------------------------------------------
+class ClangFunctionCaller : public FunctionCaller
+{
+ friend class ASTStructExtractor;
+
+ class ClangFunctionCallerHelper : public ClangExpressionHelper
+ {
+ public:
+ ClangFunctionCallerHelper (ClangFunctionCaller &owner) :
+ m_owner(owner)
+ {
+ }
+
+ ~ClangFunctionCallerHelper() {}
+
+ //------------------------------------------------------------------
+ /// Return the object that the parser should use when resolving external
+ /// values. May be NULL if everything should be self-contained.
+ //------------------------------------------------------------------
+ ClangExpressionDeclMap *
+ DeclMap() override
+ {
+ return NULL;
+ }
+
+ //------------------------------------------------------------------
+ /// Return the object that the parser should allow to access ASTs.
+ /// May be NULL if the ASTs do not need to be transformed.
+ ///
+ /// @param[in] passthrough
+ /// The ASTConsumer that the returned transformer should send
+ /// the ASTs to after transformation.
+ //------------------------------------------------------------------
+ clang::ASTConsumer *
+ ASTTransformer(clang::ASTConsumer *passthrough) override;
+ private:
+ ClangFunctionCaller &m_owner;
+ std::unique_ptr<ASTStructExtractor> m_struct_extractor; ///< The class that generates the argument struct layout.
+ };
+
+public:
+ //------------------------------------------------------------------
+ /// Constructor
+ ///
+ /// @param[in] exe_scope
+ /// An execution context scope that gets us at least a target and
+ /// process.
+ ///
+ /// @param[in] ast_context
+ /// The AST context to evaluate argument types in.
+ ///
+ /// @param[in] return_qualtype
+ /// An opaque Clang QualType for the function result. Should be
+ /// defined in ast_context.
+ ///
+ /// @param[in] function_address
+ /// The address of the function to call.
+ ///
+ /// @param[in] arg_value_list
+ /// The default values to use when calling this function. Can
+ /// be overridden using WriteFunctionArguments().
+ //------------------------------------------------------------------
+ ClangFunctionCaller (ExecutionContextScope &exe_scope,
+ const CompilerType &return_type,
+ const Address& function_address,
+ const ValueList &arg_value_list,
+ const char *name);
+
+ //------------------------------------------------------------------
+ /// Destructor
+ //------------------------------------------------------------------
+ ~ClangFunctionCaller() override;
+
+ //------------------------------------------------------------------
+ /// Compile the wrapper function
+ ///
+ /// @param[in] errors
+ /// The stream to print parser errors to.
+ ///
+ /// @return
+ /// The number of errors.
+ //------------------------------------------------------------------
+ unsigned
+ CompileFunction (Stream &errors) override;
+
+ ExpressionTypeSystemHelper *
+ GetTypeSystemHelper () override
+ {
+ return &m_type_system_helper;
+ }
+protected:
+ const char *GetWrapperStructName()
+ {
+ return m_wrapper_struct_name.c_str();
+ }
+private:
+ //------------------------------------------------------------------
+ // For ClangFunctionCaller only
+ //------------------------------------------------------------------
+
+ // Note: the parser needs to be destructed before the execution unit, so
+ // declare the execution unit first.
+ ClangFunctionCallerHelper m_type_system_helper;
+
+};
+
+} // Namespace lldb_private
+
+#endif // liblldb_ClangFunctionCaller_h_
diff --git a/lldb/include/lldb/Expression/ClangUserExpression.h b/lldb/include/lldb/Expression/ClangUserExpression.h
index 176a9e23036..169e2194534 100644
--- a/lldb/include/lldb/Expression/ClangUserExpression.h
+++ b/lldb/include/lldb/Expression/ClangUserExpression.h
@@ -23,7 +23,9 @@
#include "lldb/lldb-private.h"
#include "lldb/Core/Address.h"
#include "lldb/Core/ClangForward.h"
-#include "lldb/Expression/ClangExpression.h"
+#include "lldb/Expression/UserExpression.h"
+#include "lldb/Expression/ClangExpressionHelper.h"
+#include "lldb/Expression/ASTStructExtractor.h"
#include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h"
#include "lldb/Expression/IRForTarget.h"
#include "lldb/Expression/Materializer.h"
@@ -42,11 +44,59 @@ namespace lldb_private
/// the objects needed to parse and interpret or JIT an expression. It
/// uses the Clang parser to produce LLVM IR from the expression.
//----------------------------------------------------------------------
-class ClangUserExpression : public ClangExpression
+class ClangUserExpression : public UserExpression
{
public:
enum { kDefaultTimeout = 500000u };
+
+
+ class ClangUserExpressionHelper : public ClangExpressionHelper
+ {
+ public:
+ ClangUserExpressionHelper (Target &target) :
+ m_target(target)
+ {
+ }
+
+ ~ClangUserExpressionHelper() {}
+
+ //------------------------------------------------------------------
+ /// Return the object that the parser should use when resolving external
+ /// values. May be NULL if everything should be self-contained.
+ //------------------------------------------------------------------
+ ClangExpressionDeclMap *
+ DeclMap() override
+ {
+ return m_expr_decl_map_up.get();
+ }
+
+ void
+ ResetDeclMap()
+ {
+ m_expr_decl_map_up.reset();
+ }
+
+ void
+ ResetDeclMap (ExecutionContext & exe_ctx, bool keep_result_in_memory);
+
+ //------------------------------------------------------------------
+ /// Return the object that the parser should allow to access ASTs.
+ /// May be NULL if the ASTs do not need to be transformed.
+ ///
+ /// @param[in] passthrough
+ /// The ASTConsumer that the returned transformer should send
+ /// the ASTs to after transformation.
+ //------------------------------------------------------------------
+ clang::ASTConsumer *
+ ASTTransformer(clang::ASTConsumer *passthrough) override;
+ private:
+ Target &m_target;
+ std::unique_ptr<ClangExpressionDeclMap> m_expr_decl_map_up;
+ std::unique_ptr<ASTStructExtractor> m_struct_extractor_up; ///< The class that generates the argument struct layout.
+ std::unique_ptr<ASTResultSynthesizer> m_result_synthesizer_up;
+ };
+
//------------------------------------------------------------------
/// Constructor
///
@@ -66,7 +116,8 @@ public:
/// If not eResultTypeAny, the type to use for the expression
/// result.
//------------------------------------------------------------------
- ClangUserExpression (const char *expr,
+ ClangUserExpression (ExecutionContextScope &exe_scope,
+ const char *expr,
const char *expr_prefix,
lldb::LanguageType language,
ResultType desired_type);
@@ -102,207 +153,32 @@ public:
ExecutionContext &exe_ctx,
lldb_private::ExecutionPolicy execution_policy,
bool keep_result_in_memory,
- bool generate_debug_info);
-
- bool
- CanInterpret ()
- {
- return m_can_interpret;
- }
-
- bool
- MatchesContext (ExecutionContext &exe_ctx);
-
- //------------------------------------------------------------------
- /// Execute the parsed expression
- ///
- /// @param[in] error_stream
- /// A stream to print errors to.
- ///
- /// @param[in] exe_ctx
- /// The execution context to use when looking up entities that
- /// are needed for parsing (locations of variables, etc.)
- ///
- /// @param[in] options
- /// Expression evaluation options.
- ///
- /// @param[in] shared_ptr_to_me
- /// This is a shared pointer to this ClangUserExpression. This is
- /// needed because Execute can push a thread plan that will hold onto
- /// the ClangUserExpression for an unbounded period of time. So you
- /// need to give the thread plan a reference to this object that can
- /// keep it alive.
- ///
- /// @param[in] result
- /// A pointer to direct at the persistent variable in which the
- /// expression's result is stored.
- ///
- /// @return
- /// A Process::Execution results value.
- //------------------------------------------------------------------
- lldb::ExpressionResults
- Execute (Stream &error_stream,
- ExecutionContext &exe_ctx,
- const EvaluateExpressionOptions& options,
- lldb::ClangUserExpressionSP &shared_ptr_to_me,
- lldb::ExpressionVariableSP &result);
-
- //------------------------------------------------------------------
- /// Apply the side effects of the function to program state.
- ///
- /// @param[in] error_stream
- /// A stream to print errors to.
- ///
- /// @param[in] exe_ctx
- /// The execution context to use when looking up entities that
- /// are needed for parsing (locations of variables, etc.)
- ///
- /// @param[in] result
- /// A pointer to direct at the persistent variable in which the
- /// expression's result is stored.
- ///
- /// @param[in] function_stack_pointer
- /// A pointer to the base of the function's stack frame. This
- /// is used to determine whether the expression result resides in
- /// memory that will still be valid, or whether it needs to be
- /// treated as homeless for the purpose of future expressions.
- ///
- /// @return
- /// A Process::Execution results value.
- //------------------------------------------------------------------
- bool
- FinalizeJITExecution (Stream &error_stream,
- ExecutionContext &exe_ctx,
- lldb::ExpressionVariableSP &result,
- lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS,
- lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS);
-
- //------------------------------------------------------------------
- /// Return the string that the parser should parse. Must be a full
- /// translation unit.
- //------------------------------------------------------------------
- const char *
- Text() override
- {
- return m_transformed_text.c_str();
- }
-
- //------------------------------------------------------------------
- /// Return the string that the user typed.
- //------------------------------------------------------------------
- const char *
- GetUserText ()
- {
- return m_expr_text.c_str();
- }
-
- //------------------------------------------------------------------
- /// Return the function name that should be used for executing the
- /// expression. Text() should contain the definition of this
- /// function.
- //------------------------------------------------------------------
- const char *
- FunctionName() override
- {
- return "$__lldb_expr";
- }
+ bool generate_debug_info) override;
- //------------------------------------------------------------------
- /// Return the language that should be used when parsing. To use
- /// the default, return eLanguageTypeUnknown.
- //------------------------------------------------------------------
- lldb::LanguageType
- Language() override
+ ExpressionTypeSystemHelper *
+ GetTypeSystemHelper () override
{
- return m_language;
+ return &m_type_system_helper;
}
-
- //------------------------------------------------------------------
- /// Return the object that the parser should use when resolving external
- /// values. May be NULL if everything should be self-contained.
- //------------------------------------------------------------------
+
ClangExpressionDeclMap *
- DeclMap() override
+ DeclMap ()
{
- return m_expr_decl_map.get();
+ return m_type_system_helper.DeclMap();
}
-
- //------------------------------------------------------------------
- /// Return the object that the parser should allow to access ASTs.
- /// May be NULL if the ASTs do not need to be transformed.
- ///
- /// @param[in] passthrough
- /// The ASTConsumer that the returned transformer should send
- /// the ASTs to after transformation.
- //------------------------------------------------------------------
- clang::ASTConsumer *
- ASTTransformer(clang::ASTConsumer *passthrough) override;
-
- //------------------------------------------------------------------
- /// Return the desired result type of the function, or
- /// eResultTypeAny if indifferent.
- //------------------------------------------------------------------
- ResultType
- DesiredResultType() override
- {
- return m_desired_type;
- }
-
- //------------------------------------------------------------------
- /// Return true if validation code should be inserted into the
- /// expression.
- //------------------------------------------------------------------
- bool
- NeedsValidation() override
+
+ void
+ ResetDeclMap ()
{
- return true;
+ m_type_system_helper.ResetDeclMap();
}
-
- //------------------------------------------------------------------
- /// Return true if external variables in the expression should be
- /// resolved.
- //------------------------------------------------------------------
- bool
- NeedsVariableResolution() override
+
+ void
+ ResetDeclMap (ExecutionContext & exe_ctx, bool keep_result_in_memory)
{
- return true;
+ m_type_system_helper.ResetDeclMap(exe_ctx, keep_result_in_memory);
}
-
- //------------------------------------------------------------------
- /// Evaluate one expression and return its result.
- ///
- /// @param[in] exe_ctx
- /// The execution context to use when evaluating the expression.
- ///
- /// @param[in] options
- /// Expression evaluation options.
- ///
- /// @param[in] expr_cstr
- /// A C string containing the expression to be evaluated.
- ///
- /// @param[in] expr_prefix
- /// If non-NULL, a C string containing translation-unit level
- /// definitions to be included when the expression is parsed.
- ///
- /// @param[in,out] result_valobj_sp
- /// If execution is successful, the result valobj is placed here.
- ///
- /// @param[out]
- /// Filled in with an error in case the expression evaluation
- /// fails to parse, run, or evaluated.
- ///
- /// @result
- /// A Process::ExpressionResults value. eExpressionCompleted for success.
- //------------------------------------------------------------------
- static lldb::ExpressionResults
- Evaluate (ExecutionContext &exe_ctx,
- const EvaluateExpressionOptions& options,
- const char *expr_cstr,
- const char *expr_prefix,
- lldb::ValueObjectSP &result_valobj_sp,
- Error &error);
-
- static const Error::ValueType kNoResult = 0x1001; ///< ValueObject::GetError() returns this if there is no result from the expression.
+
private:
//------------------------------------------------------------------
/// Populate m_in_cplusplus_method and m_in_objectivec_method based on the environment.
@@ -310,53 +186,14 @@ private:
void
ScanContext (ExecutionContext &exe_ctx,
- lldb_private::Error &err);
-
- bool
- PrepareToExecuteJITExpression (Stream &error_stream,
- ExecutionContext &exe_ctx,
- lldb::addr_t &struct_address,
- lldb::addr_t &object_ptr,
- lldb::addr_t &cmd_ptr);
-
- void
- InstallContext (ExecutionContext &exe_ctx);
+ lldb_private::Error &err) override;
bool
- LockAndCheckContext (ExecutionContext &exe_ctx,
- lldb::TargetSP &target_sp,
- lldb::ProcessSP &process_sp,
- lldb::StackFrameSP &frame_sp);
-
- lldb::ProcessWP m_process_wp; ///< The process used as the context for the expression.
- Address m_address; ///< The address the process is stopped in.
- 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.
-
- std::string m_expr_text; ///< The text of the expression, as typed by the user
- std::string m_expr_prefix; ///< The text of the translation-level definitions, as provided by the user
- lldb::LanguageType m_language; ///< The language to use when parsing (eLanguageTypeUnknown means use defaults)
- 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
- ResultType m_desired_type; ///< The type to coerce the expression's result to. If eResultTypeAny, inferred from the expression.
-
- std::unique_ptr<ClangExpressionDeclMap> m_expr_decl_map; ///< The map to use when parsing the expression.
- 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.
- std::unique_ptr<ASTResultSynthesizer> m_result_synthesizer; ///< The result synthesizer, if one is needed.
- 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.
+ AddInitialArguments (ExecutionContext &exe_ctx,
+ std::vector<lldb::addr_t> &args,
+ Stream &error_stream) override;
+
+ ClangUserExpressionHelper m_type_system_helper;
};
} // namespace lldb_private
diff --git a/lldb/include/lldb/Expression/ClangUtilityFunction.h b/lldb/include/lldb/Expression/ClangUtilityFunction.h
index 1a028174810..37b1ebbba12 100644
--- a/lldb/include/lldb/Expression/ClangUtilityFunction.h
+++ b/lldb/include/lldb/Expression/ClangUtilityFunction.h
@@ -22,7 +22,8 @@
#include "lldb/lldb-forward.h"
#include "lldb/lldb-private.h"
#include "lldb/Core/ClangForward.h"
-#include "lldb/Expression/ClangExpression.h"
+#include "lldb/Expression/ClangExpressionHelper.h"
+#include "lldb/Expression/UtilityFunction.h"
namespace lldb_private
{
@@ -34,11 +35,57 @@ namespace lldb_private
/// LLDB uses expressions for various purposes, notably to call functions
/// and as a backend for the expr command. ClangUtilityFunction encapsulates
/// a self-contained function meant to be used from other code. Utility
-/// functions can perform error-checking for ClangUserExpressions,
+/// functions can perform error-checking for ClangUserExpressions, or can
+/// simply provide a way to push a function into the target for the debugger to
+/// call later on.
//----------------------------------------------------------------------
-class ClangUtilityFunction : public ClangExpression
+class ClangUtilityFunction : public UtilityFunction
{
public:
+ class ClangUtilityFunctionHelper : public ClangExpressionHelper
+ {
+ public:
+ ClangUtilityFunctionHelper ()
+ {
+ }
+
+ ~ClangUtilityFunctionHelper() override {}
+
+ //------------------------------------------------------------------
+ /// Return the object that the parser should use when resolving external
+ /// values. May be NULL if everything should be self-contained.
+ //------------------------------------------------------------------
+ ClangExpressionDeclMap *
+ DeclMap() override
+ {
+ return m_expr_decl_map_up.get();
+ }
+
+ void
+ ResetDeclMap()
+ {
+ m_expr_decl_map_up.reset();
+ }
+
+ void
+ ResetDeclMap (ExecutionContext & exe_ctx, bool keep_result_in_memory);
+
+ //------------------------------------------------------------------
+ /// Return the object that the parser should allow to access ASTs.
+ /// May be NULL if the ASTs do not need to be transformed.
+ ///
+ /// @param[in] passthrough
+ /// The ASTConsumer that the returned transformer should send
+ /// the ASTs to after transformation.
+ //------------------------------------------------------------------
+ clang::ASTConsumer *
+ ASTTransformer(clang::ASTConsumer *passthrough) override
+ {
+ return nullptr;
+ }
+ private:
+ std::unique_ptr<ClangExpressionDeclMap> m_expr_decl_map_up;
+ };
//------------------------------------------------------------------
/// Constructor
///
@@ -48,129 +95,41 @@ public:
/// @param[in] name
/// The name of the function, as used in the text.
//------------------------------------------------------------------
- ClangUtilityFunction (const char *text,
+ ClangUtilityFunction (ExecutionContextScope &exe_scope,
+ const char *text,
const char *name);
~ClangUtilityFunction() override;
-
- //------------------------------------------------------------------
- /// Install the utility function into a process
- ///
- /// @param[in] error_stream
- /// A stream to print parse errors and warnings to.
- ///
- /// @param[in] exe_ctx
- /// The execution context to install the utility function to.
- ///
- /// @return
- /// True on success (no errors); false otherwise.
- //------------------------------------------------------------------
- bool
- Install (Stream &error_stream, ExecutionContext &exe_ctx);
-
- //------------------------------------------------------------------
- /// Check whether the given PC is inside the function
- ///
- /// Especially useful if the function dereferences NULL to indicate a failed
- /// assert.
- ///
- /// @param[in] pc
- /// The program counter to check.
- ///
- /// @return
- /// True if the program counter falls within the function's bounds;
- /// false if not (or the function is not JIT compiled)
- //------------------------------------------------------------------
- bool
- ContainsAddress (lldb::addr_t address)
- {
- // nothing is both >= LLDB_INVALID_ADDRESS and < LLDB_INVALID_ADDRESS,
- // so this always returns false if the function is not JIT compiled yet
- return (address >= m_jit_start_addr && address < m_jit_end_addr);
- }
-
- //------------------------------------------------------------------
- /// Return the string that the parser should parse. Must be a full
- /// translation unit.
- //------------------------------------------------------------------
- const char *
- Text() override
+ ExpressionTypeSystemHelper *
+ GetTypeSystemHelper () override
{
- return m_function_text.c_str();
+ return &m_type_system_helper;
}
-
- //------------------------------------------------------------------
- /// Return the function name that should be used for executing the
- /// expression. Text() should contain the definition of this
- /// function.
- //------------------------------------------------------------------
- const char *
- FunctionName() override
- {
- return m_function_name.c_str();
- }
-
- //------------------------------------------------------------------
- /// Return the object that the parser should use when resolving external
- /// values. May be NULL if everything should be self-contained.
- //------------------------------------------------------------------
+
ClangExpressionDeclMap *
- DeclMap() override
+ DeclMap()
{
- return m_expr_decl_map.get();
+ return m_type_system_helper.DeclMap();
}
-
- //------------------------------------------------------------------
- /// Return the object that the parser should use when registering
- /// local variables. May be NULL if the Expression doesn't care.
- //------------------------------------------------------------------
- ExpressionVariableList *
- LocalVariables ()
- {
- return NULL;
- }
-
- //------------------------------------------------------------------
- /// Return the object that the parser should allow to access ASTs.
- /// May be NULL if the ASTs do not need to be transformed.
- ///
- /// @param[in] passthrough
- /// The ASTConsumer that the returned transformer should send
- /// the ASTs to after transformation.
- //------------------------------------------------------------------
- clang::ASTConsumer *
- ASTTransformer(clang::ASTConsumer *passthrough) override
+
+ void
+ ResetDeclMap ()
{
- return NULL;
+ m_type_system_helper.ResetDeclMap();
}
- //------------------------------------------------------------------
- /// Return true if validation code should be inserted into the
- /// expression.
- //------------------------------------------------------------------
- bool
- NeedsValidation() override
+ void
+ ResetDeclMap (ExecutionContext & exe_ctx, bool keep_result_in_memory)
{
- return false;
+ m_type_system_helper.ResetDeclMap(exe_ctx, keep_result_in_memory);
}
- //------------------------------------------------------------------
- /// Return true if external variables in the expression should be
- /// resolved.
- //------------------------------------------------------------------
bool
- NeedsVariableResolution() override
- {
- return false;
- }
+ Install (Stream &error_stream, ExecutionContext &exe_ctx) override;
private:
- std::unique_ptr<ClangExpressionDeclMap> m_expr_decl_map; ///< The map to use when parsing and materializing the expression.
- std::shared_ptr<IRExecutionUnit> m_execution_unit_sp;
- lldb::ModuleWP m_jit_module_wp;
- std::string m_function_text; ///< The text of the function. Must be a well-formed translation unit.
- std::string m_function_name; ///< The name of the function.
+ ClangUtilityFunctionHelper m_type_system_helper; ///< The map to use when parsing and materializing the expression.
};
} // namespace lldb_private
diff --git a/lldb/include/lldb/Expression/ClangExpression.h b/lldb/include/lldb/Expression/Expression.h
index 6e831e4471e..12f15b5f3c7 100644
--- a/lldb/include/lldb/Expression/ClangExpression.h
+++ b/lldb/include/lldb/Expression/Expression.h
@@ -1,4 +1,4 @@
-//===-- ClangExpression.h ---------------------------------------*- C++ -*-===//
+//===-- Expression.h --------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_ClangExpression_h_
-#define liblldb_ClangExpression_h_
+#ifndef liblldb_Expression_h_
+#define liblldb_Expression_h_
// C Includes
// C++ Includes
@@ -22,22 +22,23 @@
#include "lldb/lldb-forward.h"
#include "lldb/lldb-private.h"
#include "lldb/Core/ClangForward.h"
-#include "lldb/Target/Process.h"
+#include "lldb/Expression/ExpressionTypeSystemHelper.h"
namespace lldb_private {
class RecordingMemoryManager;
//----------------------------------------------------------------------
-/// @class ClangExpression ClangExpression.h "lldb/Expression/ClangExpression.h"
-/// @brief Encapsulates a single expression for use with Clang
+/// @class Expression Expression.h "lldb/Expression/Expression.h"
+/// @brief Encapsulates a single expression for use in lldb
///
/// LLDB uses expressions for various purposes, notably to call functions
-/// and as a backend for the expr command. ClangExpression encapsulates
+/// and as a backend for the expr command. Expression encapsulates
/// the objects needed to parse and interpret or JIT an expression. It
-/// uses the Clang parser to produce LLVM IR from the expression.
+/// uses the expression parser appropriate to the language of the expression
+/// to produce LLVM IR from the expression.
//----------------------------------------------------------------------
-class ClangExpression
+class Expression
{
public:
enum ResultType {
@@ -45,17 +46,14 @@ public:
eResultTypeId
};
- ClangExpression () :
- m_jit_process_wp(),
- m_jit_start_addr (LLDB_INVALID_ADDRESS),
- m_jit_end_addr (LLDB_INVALID_ADDRESS)
- {
- }
-
+ Expression (Target &target);
+
+ Expression (ExecutionContextScope &exe_scope);
+
//------------------------------------------------------------------
/// Destructor
//------------------------------------------------------------------
- virtual ~ClangExpression ()
+ virtual ~Expression ()
{
}
@@ -85,24 +83,6 @@ public:
}
//------------------------------------------------------------------
- /// Return the object that the parser should use when resolving external
- /// values. May be NULL if everything should be self-contained.
- //------------------------------------------------------------------
- virtual ClangExpressionDeclMap *
- DeclMap () = 0;
-
- //------------------------------------------------------------------
- /// Return the object that the parser should allow to access ASTs.
- /// May be NULL if the ASTs do not need to be transformed.
- ///
- /// @param[in] passthrough
- /// The ASTConsumer that the returned transformer should send
- /// the ASTs to after transformation.
- //------------------------------------------------------------------
- virtual clang::ASTConsumer *
- ASTTransformer (clang::ASTConsumer *passthrough) = 0;
-
- //------------------------------------------------------------------
/// Return the desired result type of the function, or
/// eResultTypeAny if indifferent.
//------------------------------------------------------------------
@@ -139,10 +119,17 @@ public:
{
return m_jit_start_addr;
}
+
+ virtual ExpressionTypeSystemHelper *
+ GetTypeSystemHelper ()
+ {
+ return nullptr;
+ }
protected:
- lldb::ProcessWP m_jit_process_wp;
+ lldb::TargetWP m_target_wp; /// Expression's always have to have a target...
+ lldb::ProcessWP m_jit_process_wp; /// An expression might have a process, but it doesn't need to (e.g. calculator mode.)
lldb::addr_t m_jit_start_addr; ///< The address of the JITted function within the JIT allocation. LLDB_INVALID_ADDRESS if invalid.
lldb::addr_t m_jit_end_addr; ///< The address of the JITted function within the JIT allocation. LLDB_INVALID_ADDRESS if invalid.
@@ -150,4 +137,4 @@ protected:
} // namespace lldb_private
-#endif // liblldb_ClangExpression_h_
+#endif // liblldb_Expression_h_
diff --git a/lldb/include/lldb/Expression/ExpressionParser.h b/lldb/include/lldb/Expression/ExpressionParser.h
new file mode 100644
index 00000000000..e49525a624d
--- /dev/null
+++ b/lldb/include/lldb/Expression/ExpressionParser.h
@@ -0,0 +1,129 @@
+//===-- ExpressionParser.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_ExpressionParser_h_
+#define liblldb_ExpressionParser_h_
+
+#include "lldb/lldb-public.h"
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/ClangForward.h"
+#include "lldb/Core/Error.h"
+#include "lldb/Expression/IRForTarget.h"
+
+#include <string>
+#include <vector>
+
+namespace lldb_private
+{
+
+class IRExecutionUnit;
+
+//----------------------------------------------------------------------
+/// @class ExpressionParser ExpressionParser.h "lldb/Expression/ExpressionParser.h"
+/// @brief Encapsulates an instance of a compiler that can parse expressions.
+///
+/// ExpressionParser is the base class for llvm based Expression parsers.
+//----------------------------------------------------------------------
+class ExpressionParser
+{
+public:
+ //------------------------------------------------------------------
+ /// Constructor
+ ///
+ /// Initializes class variables.
+ ///
+ /// @param[in] exe_scope,
+ /// If non-NULL, an execution context scope that can help to
+ /// correctly create an expression with a valid process for
+ /// optional tuning Objective-C runtime support. Can be NULL.
+ ///
+ /// @param[in] expr
+ /// The expression to be parsed.
+ //------------------------------------------------------------------
+ ExpressionParser (ExecutionContextScope *exe_scope,
+ Expression &expr,
+ bool generate_debug_info) :
+ m_expr(expr),
+ m_generate_debug_info(generate_debug_info)
+ {
+ }
+
+ //------------------------------------------------------------------
+ /// Destructor
+ //------------------------------------------------------------------
+ virtual ~ExpressionParser () {};
+
+ //------------------------------------------------------------------
+ /// Parse a single expression and convert it to IR using Clang. Don't
+ /// wrap the expression in anything at all.
+ ///
+ /// @param[in] stream
+ /// The stream to print errors to.
+ ///
+ /// @return
+ /// The number of errors encountered during parsing. 0 means
+ /// success.
+ //------------------------------------------------------------------
+ virtual unsigned
+ Parse (Stream &stream) = 0;
+
+ //------------------------------------------------------------------
+ /// Ready an already-parsed expression for execution, possibly
+ /// evaluating it statically.
+ ///
+ /// @param[out] func_addr
+ /// The address to which the function has been written.
+ ///
+ /// @param[out] func_end
+ /// The end of the function's allocated memory region. (func_addr
+ /// and func_end do not delimit an allocated region; the allocated
+ /// region may begin before func_addr.)
+ ///
+ /// @param[in] execution_unit_sp
+ /// After parsing, ownership of the execution unit for
+ /// for the expression is handed to this shared pointer.
+ ///
+ /// @param[in] exe_ctx
+ /// The execution context to write the function into.
+ ///
+ /// @param[out] can_interpret
+ /// Set to true if the expression could be interpreted statically;
+ /// untouched otherwise.
+ ///
+ /// @param[in] execution_policy
+ /// Determines whether the expression must be JIT-compiled, must be
+ /// evaluated statically, or whether this decision may be made
+ /// opportunistically.
+ ///
+ /// @return
+ /// An error code indicating the success or failure of the operation.
+ /// Test with Success().
+ //------------------------------------------------------------------
+ virtual Error
+ PrepareForExecution (lldb::addr_t &func_addr,
+ lldb::addr_t &func_end,
+ std::shared_ptr<IRExecutionUnit> &execution_unit_sp,
+ ExecutionContext &exe_ctx,
+ bool &can_interpret,
+ lldb_private::ExecutionPolicy execution_policy) = 0;
+
+ bool
+ GetGenerateDebugInfo () const
+ {
+ return m_generate_debug_info;
+ }
+
+protected:
+ Expression & m_expr; ///< The expression to be parsed
+ bool m_generate_debug_info;
+};
+
+}
+
+#endif // liblldb_ExpressionParser_h_
diff --git a/lldb/include/lldb/Expression/ExpressionTypeSystemHelper.h b/lldb/include/lldb/Expression/ExpressionTypeSystemHelper.h
new file mode 100644
index 00000000000..cb560c9b5a4
--- /dev/null
+++ b/lldb/include/lldb/Expression/ExpressionTypeSystemHelper.h
@@ -0,0 +1,54 @@
+//===-- ExpressionTypeSystemHelper.h ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef ExpressionTypeSystemHelper_h
+#define ExpressionTypeSystemHelper_h
+
+#include "llvm/Support/Casting.h"
+
+namespace lldb_private
+{
+
+//----------------------------------------------------------------------
+/// @class ExpressionTypeSystemHelper ExpressionTypeSystemHelper.h "lldb/Expression/ExpressionTypeSystemHelper.h"
+/// @brief A helper object that the Expression can pass to its ExpressionParser to provide generic information that
+/// any type of expression will need to supply. It's only job is to support dyn_cast so that the expression parser
+/// can cast it back to the requisite specific type.
+///
+//----------------------------------------------------------------------
+
+class ExpressionTypeSystemHelper
+{
+public:
+ enum LLVMCastKind {
+ eKindClangHelper,
+ eKindSwiftHelper,
+ eKindGoHelper,
+ kNumKinds
+ };
+
+ LLVMCastKind getKind() const { return m_kind; }
+
+ ExpressionTypeSystemHelper (LLVMCastKind kind) :
+ m_kind(kind)
+ {
+ }
+
+ ~ExpressionTypeSystemHelper () {}
+
+protected:
+ LLVMCastKind m_kind;
+};
+
+
+
+
+} // namespace lldb_private
+
+#endif /* ExpressionTypeSystemHelper_h */
diff --git a/lldb/include/lldb/Expression/ClangFunction.h b/lldb/include/lldb/Expression/FunctionCaller.h
index 10a623eaeeb..2510e10bde8 100644
--- a/lldb/include/lldb/Expression/ClangFunction.h
+++ b/lldb/include/lldb/Expression/FunctionCaller.h
@@ -1,4 +1,4 @@
-//===-- ClangFunction.h -----------------------------------------*- C++ -*-===//
+//===-- FunctionCaller.h -----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef liblldb_ClangFunction_h_
-#define liblldb_ClangFunction_h_
+#ifndef liblldb_FunctionCaller_h_
+#define liblldb_FunctionCaller_h_
// C Includes
// C++ Includes
@@ -21,7 +21,8 @@
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectList.h"
-#include "lldb/Expression/ClangExpression.h"
+#include "lldb/Expression/Expression.h"
+#include "lldb/Expression/ExpressionParser.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Target/Process.h"
@@ -32,10 +33,10 @@ class ASTStructExtractor;
class ClangExpressionParser;
//----------------------------------------------------------------------
-/// @class ClangFunction ClangFunction.h "lldb/Expression/ClangFunction.h"
+/// @class FunctionCaller FunctionCaller.h "lldb/Expression/FunctionCaller.h"
/// @brief Encapsulates a function that can be called.
///
-/// A given ClangFunction object can handle a single function signature.
+/// A given FunctionCaller object can handle a single function signature.
/// Once constructed, it can set up any number of concurrent calls to
/// functions with that signature.
///
@@ -46,7 +47,7 @@ class ClangExpressionParser;
/// struct with the written arguments. This method lets Clang handle the
/// vagaries of function calling conventions.
///
-/// The simplest use of the ClangFunction is to construct it with a
+/// The simplest use of the FunctionCaller is to construct it with a
/// function representative of the signature you want to use, then call
/// ExecuteFunction(ExecutionContext &, Stream &, Value &).
///
@@ -64,9 +65,8 @@ class ClangExpressionParser;
/// Any of the methods that take arg_addr_ptr can be passed NULL, and the
/// argument space will be managed for you.
//----------------------------------------------------------------------
-class ClangFunction : public ClangExpression
+class FunctionCaller : public Expression
{
- friend class ASTStructExtractor;
public:
//------------------------------------------------------------------
/// Constructor
@@ -75,30 +75,6 @@ public:
/// An execution context scope that gets us at least a target and
/// process.
///
- /// @param[in] function_ptr
- /// The default function to be called. Can be overridden using
- /// WriteFunctionArguments().
- ///
- /// @param[in] ast_context
- /// The AST context to evaluate argument types in.
- ///
- /// @param[in] arg_value_list
- /// The default values to use when calling this function. Can
- /// be overridden using WriteFunctionArguments().
- //------------------------------------------------------------------
- ClangFunction (ExecutionContextScope &exe_scope,
- Function &function_ptr,
- ClangASTContext *ast_context,
- const ValueList &arg_value_list,
- const char *name);
-
- //------------------------------------------------------------------
- /// Constructor
- ///
- /// @param[in] exe_scope
- /// An execution context scope that gets us at least a target and
- /// process.
- ///
/// @param[in] ast_context
/// The AST context to evaluate argument types in.
///
@@ -113,7 +89,7 @@ public:
/// The default values to use when calling this function. Can
/// be overridden using WriteFunctionArguments().
//------------------------------------------------------------------
- ClangFunction (ExecutionContextScope &exe_scope,
+ FunctionCaller (ExecutionContextScope &exe_scope,
const CompilerType &return_type,
const Address& function_address,
const ValueList &arg_value_list,
@@ -122,7 +98,7 @@ public:
//------------------------------------------------------------------
/// Destructor
//------------------------------------------------------------------
- ~ClangFunction() override;
+ ~FunctionCaller() override;
//------------------------------------------------------------------
/// Compile the wrapper function
@@ -133,8 +109,8 @@ public:
/// @return
/// The number of errors.
//------------------------------------------------------------------
- unsigned
- CompileFunction (Stream &errors);
+ virtual unsigned
+ CompileFunction (Stream &errors) = 0;
//------------------------------------------------------------------
/// Insert the default function wrapper and its default argument struct
@@ -208,10 +184,7 @@ public:
/// @param[in,out] args_addr_ref
/// The address of the structure to write the arguments into. May
/// be LLDB_INVALID_ADDRESS; if it is, a new structure is allocated
- /// and args_addr_ref is pointed to it.
- ///
- /// @param[in] function_address
- /// The address of the function to call.
+ /// and args_addr_ref is pointed at it.
///
/// @param[in] arg_values
/// The values of the function's arguments.
@@ -224,12 +197,11 @@ public:
//------------------------------------------------------------------
bool WriteFunctionArguments (ExecutionContext &exe_ctx,
lldb::addr_t &args_addr_ref,
- Address function_address,
- ValueList &arg_values,
+ ValueList &arg_values,
Stream &errors);
//------------------------------------------------------------------
- /// Run the function this ClangFunction was created with.
+ /// Run the function this FunctionCaller was created with.
///
/// This is the full version.
///
@@ -263,7 +235,7 @@ public:
Value &results);
//------------------------------------------------------------------
- /// Get a thread plan to run the function this ClangFunction was created with.
+ /// Get a thread plan to run the function this FunctionCaller was created with.
///
/// @param[in] exe_ctx
/// The execution context to insert the function and its arguments
@@ -351,16 +323,6 @@ public:
}
//------------------------------------------------------------------
- /// Return the object that the parser should use when resolving external
- /// values. May be NULL if everything should be self-contained.
- //------------------------------------------------------------------
- ClangExpressionDeclMap *
- DeclMap() override
- {
- return NULL;
- }
-
- //------------------------------------------------------------------
/// Return the object that the parser should use when registering
/// local variables. May be NULL if the Expression doesn't care.
//------------------------------------------------------------------
@@ -371,17 +333,6 @@ public:
}
//------------------------------------------------------------------
- /// Return the object that the parser should allow to access ASTs.
- /// May be NULL if the ASTs do not need to be transformed.
- ///
- /// @param[in] passthrough
- /// The ASTConsumer that the returned transformer should send
- /// the ASTs to after transformation.
- //------------------------------------------------------------------
- clang::ASTConsumer *
- ASTTransformer(clang::ASTConsumer *passthrough) override;
-
- //------------------------------------------------------------------
/// Return true if validation code should be inserted into the
/// expression.
//------------------------------------------------------------------
@@ -406,15 +357,18 @@ public:
{
return m_arg_values;
}
-private:
+protected:
//------------------------------------------------------------------
- // For ClangFunction only
+ // For FunctionCaller only
//------------------------------------------------------------------
// Note: the parser needs to be destructed before the execution unit, so
// declare the execution unit first.
std::shared_ptr<IRExecutionUnit> m_execution_unit_sp;
- std::unique_ptr<ClangExpressionParser> m_parser; ///< The parser responsible for compiling the function.
+ std::unique_ptr<ExpressionParser> m_parser; ///< The parser responsible for compiling the function.
+ ///< This will get made in CompileFunction, so it is
+ ///< safe to access it after that.
+
lldb::ModuleWP m_jit_module_wp;
std::string m_name; ///< The name of this clang function - for debugging purposes.
@@ -447,4 +401,4 @@ private:
} // Namespace lldb_private
-#endif // liblldb_ClangFunction_h_
+#endif // liblldb_FunctionCaller_h_
diff --git a/lldb/include/lldb/Expression/IRDynamicChecks.h b/lldb/include/lldb/Expression/IRDynamicChecks.h
index 914e0df38e8..ef77d55f4b3 100644
--- a/lldb/include/lldb/Expression/IRDynamicChecks.h
+++ b/lldb/include/lldb/Expression/IRDynamicChecks.h
@@ -28,7 +28,6 @@ namespace lldb_private
{
class ClangExpressionDeclMap;
-class ClangUtilityFunction;
class ExecutionContext;
class Stream;
@@ -77,8 +76,8 @@ public:
bool DoCheckersExplainStop (lldb::addr_t addr, Stream &message);
- std::unique_ptr<ClangUtilityFunction> m_valid_pointer_check;
- std::unique_ptr<ClangUtilityFunction> m_objc_object_check;
+ std::unique_ptr<UtilityFunction> m_valid_pointer_check;
+ std::unique_ptr<UtilityFunction> m_objc_object_check;
};
//----------------------------------------------------------------------
diff --git a/lldb/include/lldb/Expression/IRExecutionUnit.h b/lldb/include/lldb/Expression/IRExecutionUnit.h
index a0e0f508775..6389b76d47c 100644
--- a/lldb/include/lldb/Expression/IRExecutionUnit.h
+++ b/lldb/include/lldb/Expression/IRExecutionUnit.h
@@ -26,7 +26,6 @@
#include "lldb/Core/ClangForward.h"
#include "lldb/Core/DataBufferHeap.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
-#include "lldb/Expression/ClangExpression.h"
#include "lldb/Expression/ClangExpressionParser.h"
#include "lldb/Expression/IRMemoryMap.h"
#include "lldb/Host/Mutex.h"
diff --git a/lldb/include/lldb/Expression/UserExpression.h b/lldb/include/lldb/Expression/UserExpression.h
new file mode 100644
index 00000000000..1a325eab05f
--- /dev/null
+++ b/lldb/include/lldb/Expression/UserExpression.h
@@ -0,0 +1,361 @@
+//===-- UserExpression.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_UserExpression_h_
+#define liblldb_UserExpression_h_
+
+// C Includes
+// C++ Includes
+#include <string>
+#include <map>
+#include <vector>
+
+// Other libraries and framework includes
+
+#include "llvm/ADT/ArrayRef.h"
+
+// Project includes
+
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private.h"
+#include "lldb/Core/Address.h"
+#include "lldb/Core/ClangForward.h"
+#include "lldb/Expression/ClangExpressionHelper.h"
+#include "lldb/Expression/Expression.h"
+#include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h"
+#include "lldb/Expression/IRForTarget.h"
+#include "lldb/Expression/Materializer.h"
+#include "lldb/Symbol/TaggedASTType.h"
+#include "lldb/Target/ExecutionContext.h"
+
+namespace lldb_private
+{
+
+//----------------------------------------------------------------------
+/// @class UserExpression UserExpression.h "lldb/Expression/UserExpression.h"
+/// @brief 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. UserExpression is a virtual base
+/// class that encapsulates the objects needed to parse and interpret or
+/// JIT an expression. The actual parsing part will be provided by the specific
+/// implementations of UserExpression - which will be vended through the
+/// appropriate TypeSystem.
+//----------------------------------------------------------------------
+class UserExpression : public Expression
+{
+public:
+
+ enum { kDefaultTimeout = 500000u };
+ //------------------------------------------------------------------
+ /// Constructor
+ ///
+ /// @param[in] expr
+ /// The expression to parse.
+ ///
+ /// @param[in] expr_prefix
+ /// If non-NULL, a C string containing translation-unit level
+ /// definitions to be included when the expression is parsed.
+ ///
+ /// @param[in] language
+ /// If not eLanguageTypeUnknown, a language to use when parsing
+ /// the expression. Currently restricted to those languages
+ /// supported by Clang.
+ ///
+ /// @param[in] desired_type
+ /// If not eResultTypeAny, the type to use for the expression
+ /// result.
+ //------------------------------------------------------------------
+ UserExpression (ExecutionContextScope &exe_scope,
+ const char *expr,
+ const char *expr_prefix,
+ lldb::LanguageType language,
+ ResultType desired_type);
+
+ //------------------------------------------------------------------
+ /// Destructor
+ //------------------------------------------------------------------
+ ~UserExpression() override;
+
+ //------------------------------------------------------------------
+ /// Parse the expression
+ ///
+ /// @param[in] error_stream
+ /// A stream to print parse errors and warnings to.
+ ///
+ /// @param[in] exe_ctx
+ /// The execution context to use when looking up entities that
+ /// are needed for parsing (locations of functions, types of
+ /// variables, persistent variables, etc.)
+ ///
+ /// @param[in] execution_policy
+ /// Determines whether interpretation is possible or mandatory.
+ ///
+ /// @param[in] keep_result_in_memory
+ /// True if the resulting persistent variable should reside in
+ /// target memory, if applicable.
+ ///
+ /// @return
+ /// True on success (no errors); false otherwise.
+ //------------------------------------------------------------------
+ virtual bool
+ Parse (Stream &error_stream,
+ ExecutionContext &exe_ctx,
+ lldb_private::ExecutionPolicy execution_policy,
+ bool keep_result_in_memory,
+ bool generate_debug_info) = 0;
+
+ bool
+ CanInterpret ()
+ {
+ return m_can_interpret;
+ }
+
+ bool
+ MatchesContext (ExecutionContext &exe_ctx);
+
+ //------------------------------------------------------------------
+ /// Execute the parsed expression
+ ///
+ /// @param[in] error_stream
+ /// A stream to print errors to.
+ ///
+ /// @param[in] exe_ctx
+ /// The execution context to use when looking up entities that
+ /// are needed for parsing (locations of variables, etc.)
+ ///
+ /// @param[in] options
+ /// Expression evaluation options.
+ ///
+ /// @param[in] shared_ptr_to_me
+ /// This is a shared pointer to this UserExpression. This is
+ /// needed because Execute can push a thread plan that will hold onto
+ /// the UserExpression for an unbounded period of time. So you
+ /// need to give the thread plan a reference to this object that can
+ /// keep it alive.
+ ///
+ /// @param[in] result
+ /// A pointer to direct at the persistent variable in which the
+ /// expression's result is stored.
+ ///
+ /// @return
+ /// A Process::Execution results value.
+ //------------------------------------------------------------------
+ lldb::ExpressionResults
+ Execute (Stream &error_stream,
+ ExecutionContext &exe_ctx,
+ const EvaluateExpressionOptions& options,
+ lldb::UserExpressionSP &shared_ptr_to_me,
+ lldb::ExpressionVariableSP &result);
+
+ //------------------------------------------------------------------
+ /// Apply the side effects of the function to program state.
+ ///
+ /// @param[in] error_stream
+ /// A stream to print errors to.
+ ///
+ /// @param[in] exe_ctx
+ /// The execution context to use when looking up entities that
+ /// are needed for parsing (locations of variables, etc.)
+ ///
+ /// @param[in] result
+ /// A pointer to direct at the persistent variable in which the
+ /// expression's result is stored.
+ ///
+ /// @param[in] function_stack_pointer
+ /// A pointer to the base of the function's stack frame. This
+ /// is used to determine whether the expression result resides in
+ /// memory that will still be valid, or whether it needs to be
+ /// treated as homeless for the purpose of future expressions.
+ ///
+ /// @return
+ /// A Process::Execution results value.
+ //------------------------------------------------------------------
+ bool
+ FinalizeJITExecution (Stream &error_stream,
+ ExecutionContext &exe_ctx,
+ lldb::ExpressionVariableSP &result,
+ lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS,
+ lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS);
+
+ //------------------------------------------------------------------
+ /// Return the string that the parser should parse. Must be a full
+ /// translation unit.
+ //------------------------------------------------------------------
+ const char *
+ Text() override
+ {
+ return m_transformed_text.c_str();
+ }
+
+ //------------------------------------------------------------------
+ /// Return the string that the user typed.
+ //------------------------------------------------------------------
+ const char *
+ GetUserText ()
+ {
+ return m_expr_text.c_str();
+ }
+
+ //------------------------------------------------------------------
+ /// Return the function name that should be used for executing the
+ /// expression. Text() should contain the definition of this
+ /// function.
+ //------------------------------------------------------------------
+ const char *
+ FunctionName() override
+ {
+ return "$__lldb_expr";
+ }
+
+ //------------------------------------------------------------------
+ /// Return the language that should be used when parsing. To use
+ /// the default, return eLanguageTypeUnknown.
+ //------------------------------------------------------------------
+ lldb::LanguageType
+ Language() override
+ {
+ return m_language;
+ }
+
+ //------------------------------------------------------------------
+ /// Return the desired result type of the function, or
+ /// eResultTypeAny if indifferent.
+ //------------------------------------------------------------------
+ ResultType
+ DesiredResultType() override
+ {
+ return m_desired_type;
+ }
+
+ //------------------------------------------------------------------
+ /// Return true if validation code should be inserted into the
+ /// expression.
+ //------------------------------------------------------------------
+ bool
+ NeedsValidation() override
+ {
+ return true;
+ }
+
+ //------------------------------------------------------------------
+ /// Return true if external variables in the expression should be
+ /// resolved.
+ //------------------------------------------------------------------
+ bool
+ NeedsVariableResolution() override
+ {
+ return true;
+ }
+
+ //------------------------------------------------------------------
+ /// Evaluate one expression in the scratch context of the
+ /// target passed in the exe_ctx and return its result.
+ ///
+ /// @param[in] exe_ctx
+ /// The execution context to use when evaluating the expression.
+ ///
+ /// @param[in] options
+ /// Expression evaluation options. N.B. The language in the
+ /// evaluation options will be used to determine the language used for
+ /// expression evaluation.
+ ///
+ /// @param[in] expr_cstr
+ /// A C string containing the expression to be evaluated.
+ ///
+ /// @param[in] expr_prefix
+ /// If non-NULL, a C string containing translation-unit level
+ /// definitions to be included when the expression is parsed.
+ ///
+ /// @param[in,out] result_valobj_sp
+ /// If execution is successful, the result valobj is placed here.
+ ///
+ /// @param[out]
+ /// Filled in with an error in case the expression evaluation
+ /// fails to parse, run, or evaluated.
+ ///
+ /// @result
+ /// A Process::ExpressionResults value. eExpressionCompleted for success.
+ //------------------------------------------------------------------
+ static lldb::ExpressionResults
+ Evaluate (ExecutionContext &exe_ctx,
+ const EvaluateExpressionOptions& options,
+ const char *expr_cstr,
+ const char *expr_prefix,
+ lldb::ValueObjectSP &result_valobj_sp,
+ Error &error);
+
+ static const Error::ValueType kNoResult = 0x1001; ///< ValueObject::GetError() returns this if there is no result from the expression.
+protected:
+ static lldb::addr_t
+ GetObjectPointer (lldb::StackFrameSP frame_sp,
+ ConstString &object_name,
+ Error &err);
+
+ //------------------------------------------------------------------
+ /// Populate m_in_cplusplus_method and m_in_objectivec_method based on the environment.
+ //------------------------------------------------------------------
+
+ virtual void
+ ScanContext (ExecutionContext &exe_ctx,
+ lldb_private::Error &err) = 0;
+
+ bool
+ PrepareToExecuteJITExpression (Stream &error_stream,
+ ExecutionContext &exe_ctx,
+ lldb::addr_t &struct_address);
+
+ virtual bool
+ AddInitialArguments (ExecutionContext &exe_ctx,
+ std::vector<lldb::addr_t> &args,
+ Stream &error_stream)
+ {
+ return true;
+ }
+
+ void
+ InstallContext (ExecutionContext &exe_ctx);
+
+ bool
+ LockAndCheckContext (ExecutionContext &exe_ctx,
+ lldb::TargetSP &target_sp,
+ lldb::ProcessSP &process_sp,
+ lldb::StackFrameSP &frame_sp);
+
+ Address m_address; ///< The address the process is stopped in.
+ 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.
+
+ std::string m_expr_text; ///< The text of the expression, as typed by the user
+ std::string m_expr_prefix; ///< The text of the translation-level definitions, as provided by the user
+ lldb::LanguageType m_language; ///< The language to use when parsing (eLanguageTypeUnknown means use defaults)
+ 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
+ ResultType m_desired_type; ///< The type to coerce the expression's result to. If eResultTypeAny, inferred from the expression.
+
+ 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 // liblldb_UserExpression_h_
diff --git a/lldb/include/lldb/Expression/UtilityFunction.h b/lldb/include/lldb/Expression/UtilityFunction.h
new file mode 100644
index 00000000000..12c7bc28bad
--- /dev/null
+++ b/lldb/include/lldb/Expression/UtilityFunction.h
@@ -0,0 +1,166 @@
+//===-- UtilityFunction.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_UtilityFunction_h_
+#define liblldb_UtilityFunction_h_
+
+// C Includes
+// C++ Includes
+#include <string>
+#include <map>
+#include <vector>
+
+// Other libraries and framework includes
+// Project includes
+
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private.h"
+#include "lldb/Core/ClangForward.h"
+#include "lldb/Expression/Expression.h"
+
+namespace lldb_private
+{
+
+//----------------------------------------------------------------------
+/// @class UtilityFunction UtilityFunction.h "lldb/Expression/UtilityFunction.h"
+/// @brief Encapsulates a bit of source code that provides a function that is callable
+///
+/// LLDB uses expressions for various purposes, notably to call functions
+/// and as a backend for the expr command. UtilityFunction encapsulates
+/// a self-contained function meant to be used from other code. Utility
+/// functions can perform error-checking for ClangUserExpressions,
+//----------------------------------------------------------------------
+class UtilityFunction : public Expression
+{
+public:
+ //------------------------------------------------------------------
+ /// Constructor
+ ///
+ /// @param[in] text
+ /// The text of the function. Must be a full translation unit.
+ ///
+ /// @param[in] name
+ /// The name of the function, as used in the text.
+ //------------------------------------------------------------------
+ UtilityFunction (ExecutionContextScope &exe_scope,
+ const char *text,
+ const char *name);
+
+ ~UtilityFunction() override;
+
+ //------------------------------------------------------------------
+ /// Install the utility function into a process
+ ///
+ /// @param[in] error_stream
+ /// A stream to print parse errors and warnings to.
+ ///
+ /// @param[in] exe_ctx
+ /// The execution context to install the utility function to.
+ ///
+ /// @return
+ /// True on success (no errors); false otherwise.
+ //------------------------------------------------------------------
+ virtual bool
+ Install (Stream &error_stream, ExecutionContext &exe_ctx) = 0;
+
+ //------------------------------------------------------------------
+ /// Check whether the given PC is inside the function
+ ///
+ /// Especially useful if the function dereferences NULL to indicate a failed
+ /// assert.
+ ///
+ /// @param[in] pc
+ /// The program counter to check.
+ ///
+ /// @return
+ /// True if the program counter falls within the function's bounds;
+ /// false if not (or the function is not JIT compiled)
+ //------------------------------------------------------------------
+ bool
+ ContainsAddress (lldb::addr_t address)
+ {
+ // nothing is both >= LLDB_INVALID_ADDRESS and < LLDB_INVALID_ADDRESS,
+ // so this always returns false if the function is not JIT compiled yet
+ return (address >= m_jit_start_addr && address < m_jit_end_addr);
+ }
+
+
+ //------------------------------------------------------------------
+ /// Return the string that the parser should parse. Must be a full
+ /// translation unit.
+ //------------------------------------------------------------------
+ const char *
+ Text() override
+ {
+ return m_function_text.c_str();
+ }
+
+ //------------------------------------------------------------------
+ /// Return the function name that should be used for executing the
+ /// expression. Text() should contain the definition of this
+ /// function.
+ //------------------------------------------------------------------
+ const char *
+ FunctionName() override
+ {
+ return m_function_name.c_str();
+ }
+
+ //------------------------------------------------------------------
+ /// Return the object that the parser should use when registering
+ /// local variables. May be NULL if the Expression doesn't care.
+ //------------------------------------------------------------------
+ ExpressionVariableList *
+ LocalVariables ()
+ {
+ return NULL;
+ }
+
+ //------------------------------------------------------------------
+ /// Return true if validation code should be inserted into the
+ /// expression.
+ //------------------------------------------------------------------
+ bool
+ NeedsValidation() override
+ {
+ return false;
+ }
+
+ //------------------------------------------------------------------
+ /// Return true if external variables in the expression should be
+ /// resolved.
+ //------------------------------------------------------------------
+ bool
+ NeedsVariableResolution() override
+ {
+ return false;
+ }
+
+ // This makes the function caller function.
+ FunctionCaller *
+ MakeFunctionCaller(const CompilerType &return_type, const ValueList &arg_value_list, Error &error);
+
+ // This one retrieves the function caller that is already made. If you haven't made it yet, this returns nullptr
+ FunctionCaller *
+ GetFunctionCaller()
+ {
+ return m_caller_up.get();
+ }
+
+protected:
+ std::shared_ptr<IRExecutionUnit> m_execution_unit_sp;
+ lldb::ModuleWP m_jit_module_wp;
+ std::string m_function_text; ///< The text of the function. Must be a well-formed translation unit.
+ std::string m_function_name; ///< The name of the function.
+ std::unique_ptr<FunctionCaller> m_caller_up;
+};
+
+} // namespace lldb_private
+
+#endif // liblldb_UtilityFunction_h_
diff --git a/lldb/include/lldb/Symbol/ClangASTContext.h b/lldb/include/lldb/Symbol/ClangASTContext.h
index 1735a483923..214ef8ff46b 100644
--- a/lldb/include/lldb/Symbol/ClangASTContext.h
+++ b/lldb/include/lldb/Symbol/ClangASTContext.h
@@ -1109,6 +1109,7 @@ protected:
void * m_callback_baton;
uint32_t m_pointer_byte_size;
bool m_ast_owned;
+ bool m_can_evaluate_expressions;
private:
//------------------------------------------------------------------
@@ -1118,6 +1119,31 @@ private:
const ClangASTContext& operator=(const ClangASTContext&);
};
+class ClangASTContextForExpressions : public ClangASTContext
+{
+public:
+ ClangASTContextForExpressions (Target &target);
+
+ virtual ~ClangASTContextForExpressions () {}
+
+ UserExpression *
+ GetUserExpression (const char *expr,
+ const char *expr_prefix,
+ lldb::LanguageType language,
+ Expression::ResultType desired_type) override;
+
+ FunctionCaller *
+ GetFunctionCaller (const CompilerType &return_type,
+ const Address& function_address,
+ const ValueList &arg_value_list,
+ const char *name) override;
+
+ UtilityFunction *
+ GetUtilityFunction(const char *text, const char *name) override;
+private:
+ lldb::TargetWP m_target_wp;
+};
+
} // namespace lldb_private
#endif // liblldb_ClangASTContext_h_
diff --git a/lldb/include/lldb/Symbol/TypeSystem.h b/lldb/include/lldb/Symbol/TypeSystem.h
index a5d25f99f0d..657b8a512ba 100644
--- a/lldb/include/lldb/Symbol/TypeSystem.h
+++ b/lldb/include/lldb/Symbol/TypeSystem.h
@@ -14,6 +14,7 @@
#include <string>
#include "lldb/lldb-private.h"
#include "lldb/Core/ClangForward.h"
+#include "lldb/Expression/Expression.h"
#include "lldb/Symbol/CompilerDeclContext.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/Type.h"
@@ -438,6 +439,31 @@ public:
virtual bool
IsReferenceType (void *type, CompilerType *pointee_type, bool* is_rvalue) = 0;
+
+ virtual UserExpression *
+ GetUserExpression (const char *expr,
+ const char *expr_prefix,
+ lldb::LanguageType language,
+ Expression::ResultType desired_type)
+ {
+ return nullptr;
+ }
+
+ virtual FunctionCaller *
+ GetFunctionCaller (const CompilerType &return_type,
+ const Address& function_address,
+ const ValueList &arg_value_list,
+ const char *name)
+ {
+ return nullptr;
+ }
+
+ virtual UtilityFunction *
+ GetUtilityFunction(const char *text, const char *name)
+ {
+ return nullptr;
+ }
+
protected:
const LLVMCastKind m_kind; // Support for llvm casting
SymbolFile *m_sym_file;
diff --git a/lldb/include/lldb/Target/LanguageRuntime.h b/lldb/include/lldb/Target/LanguageRuntime.h
index 57770ff487e..cdf0fbd8f45 100644
--- a/lldb/include/lldb/Target/LanguageRuntime.h
+++ b/lldb/include/lldb/Target/LanguageRuntime.h
@@ -97,6 +97,12 @@ public:
{
return m_process;
}
+
+ Target&
+ GetTargetRef()
+ {
+ return m_process->GetTarget();
+ }
virtual lldb::BreakpointResolverSP
CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp) = 0;
diff --git a/lldb/include/lldb/Target/ObjCLanguageRuntime.h b/lldb/include/lldb/Target/ObjCLanguageRuntime.h
index a45f39098ab..b8973af84da 100644
--- a/lldb/include/lldb/Target/ObjCLanguageRuntime.h
+++ b/lldb/include/lldb/Target/ObjCLanguageRuntime.h
@@ -30,7 +30,7 @@ class CommandObjectObjC_ClassTable_Dump;
namespace lldb_private {
-class ClangUtilityFunction;
+class UtilityFunction;
class ObjCLanguageRuntime :
public LanguageRuntime
@@ -289,7 +289,7 @@ public:
lldb::TypeSP
LookupInCompleteClassCache (ConstString &name);
- virtual ClangUtilityFunction *
+ virtual UtilityFunction *
CreateObjectChecker (const char *) = 0;
virtual ObjCRuntimeVersions
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index 8612c3f8a70..90eb372a28e 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -742,7 +742,7 @@ class Process :
public ExecutionContextScope,
public PluginInterface
{
- friend class ClangFunction; // For WaitForStateChangeEventsPrivate
+ friend class FunctionCaller; // For WaitForStateChangeEventsPrivate
friend class Debugger; // For PopProcessIOHandler and ProcessIOHandlerIsActive
friend class ProcessEventData;
friend class StopInfo;
diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index 824d51c0487..c8df9ca069c 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -24,6 +24,7 @@
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/ModuleList.h"
#include "lldb/Core/UserSettingsController.h"
+#include "lldb/Expression/Expression.h"
#include "lldb/Target/ExecutionContextScope.h"
#include "lldb/Target/PathMappingList.h"
#include "lldb/Target/ProcessLaunchInfo.h"
@@ -1227,12 +1228,47 @@ public:
PathMappingList &
GetImageSearchPathList ();
+ TypeSystem *
+ GetScratchTypeSystemForLanguage (lldb::LanguageType language, bool create_on_demand = true);
+
+ // Creates a UserExpression for the given language, the rest of the parameters have the
+ // same meaning as for the UserExpression constructor.
+ // Returns a new-ed object which the caller owns.
+
+ UserExpression *
+ GetUserExpressionForLanguage(const char *expr,
+ const char *expr_prefix,
+ lldb::LanguageType language,
+ Expression::ResultType desired_type,
+ Error &error);
+
+ // Creates a FunctionCaller for the given language, the rest of the parameters have the
+ // same meaning as for the FunctionCaller constructor. Since a FunctionCaller can't be
+ // IR Interpreted, it makes no sense to call this with an ExecutionContextScope that lacks
+ // a Process.
+ // Returns a new-ed object which the caller owns.
+
+ FunctionCaller *
+ GetFunctionCallerForLanguage (lldb::LanguageType language,
+ const CompilerType &return_type,
+ const Address& function_address,
+ const ValueList &arg_value_list,
+ const char *name,
+ Error &error);
+
+ // Creates a UtilityFunction for the given language, the rest of the parameters have the
+ // same meaning as for the UtilityFunction constructor.
+ // Returns a new-ed object which the caller owns.
+
+ UtilityFunction *
+ GetUtilityFunctionForLanguage (const char *expr,
+ lldb::LanguageType language,
+ const char *name,
+ Error &error);
+
ClangASTContext *
GetScratchClangASTContext(bool create_on_demand=true);
- TypeSystem*
- GetTypeSystemForLanguage (lldb::LanguageType language);
-
ClangASTImporter *
GetClangASTImporter();
diff --git a/lldb/include/lldb/Target/ThreadPlanCallFunction.h b/lldb/include/lldb/Target/ThreadPlanCallFunction.h
index c2876937419..47eee2808f1 100644
--- a/lldb/include/lldb/Target/ThreadPlanCallFunction.h
+++ b/lldb/include/lldb/Target/ThreadPlanCallFunction.h
@@ -92,7 +92,7 @@ public:
return m_function_sp;
}
- // Classes that derive from ClangFunction, and implement
+ // Classes that derive from FunctionCaller, and implement
// their own WillPop methods should call this so that the
// thread state gets restored if the plan gets discarded.
void
diff --git a/lldb/include/lldb/Target/ThreadPlanCallUserExpression.h b/lldb/include/lldb/Target/ThreadPlanCallUserExpression.h
index a1eba4a1d67..bb261d9c96b 100644
--- a/lldb/include/lldb/Target/ThreadPlanCallUserExpression.h
+++ b/lldb/include/lldb/Target/ThreadPlanCallUserExpression.h
@@ -30,7 +30,7 @@ public:
Address &function,
llvm::ArrayRef<lldb::addr_t> args,
const EvaluateExpressionOptions &options,
- lldb::ClangUserExpressionSP &user_expression_sp);
+ lldb::UserExpressionSP &user_expression_sp);
~ThreadPlanCallUserExpression() override;
@@ -60,7 +60,7 @@ public:
protected:
private:
- lldb::ClangUserExpressionSP m_user_expression_sp; // This is currently just used to ensure the
+ lldb::UserExpressionSP m_user_expression_sp; // This is currently just used to ensure the
// User expression the initiated this ThreadPlan
// lives as long as the thread plan does.
bool m_manage_materialization = false;
diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h
index 10bd5bc5cc7..787001a3307 100644
--- a/lldb/include/lldb/lldb-forward.h
+++ b/lldb/include/lldb/lldb-forward.h
@@ -27,6 +27,7 @@ class AddressResolver;
class ArchSpec;
class Args;
class ASTResultSynthesizer;
+class ASTStructExtractor;
class Baton;
class Block;
class Breakpoint;
@@ -48,16 +49,12 @@ class ClangASTContext;
class ClangASTImporter;
class ClangASTMetadata;
class ClangASTSource;
-class ClangExpression;
class ClangExpressionDeclMap;
class ClangExpressionParser;
class ClangExpressionVariable;
class ClangExpressionVariables;
-class ClangFunction;
class ClangModulesDeclVendor;
class ClangPersistentVariables;
-class ClangUserExpression;
-class ClangUtilityFunction;
class CommandInterpreter;
class CommandInterpreterRunOptions;
class CommandObject;
@@ -93,8 +90,10 @@ class ExecutionContext;
class ExecutionContextRef;
class ExecutionContextRefLocker;
class ExecutionContextScope;
+class Expression;
class ExpressionVariable;
class ExpressionVariableList;
+class ExpressionTypeSystemHelper;
class File;
class FileSpec;
class FileSpecList;
@@ -163,6 +162,7 @@ class OptionValueUInt64;
class OptionValueUUID;
class NamedOption;
class PathMappingList;
+class FunctionCaller;
class Platform;
class Process;
class ProcessAttachInfo;
@@ -268,6 +268,8 @@ class Unwind;
class UnwindAssembly;
class UnwindPlan;
class UnwindTable;
+class UserExpression;
+class UtilityFunction;
class VMRange;
class Value;
class ValueList;
@@ -308,7 +310,7 @@ namespace lldb {
typedef std::unique_ptr<lldb_private::ClangASTSource> ClangASTSourceUP;
typedef std::unique_ptr<lldb_private::ClangModulesDeclVendor> ClangModulesDeclVendorUP;
typedef std::unique_ptr<lldb_private::ClangPersistentVariables> ClangPersistentVariablesUP;
- typedef std::shared_ptr<lldb_private::ClangUserExpression> ClangUserExpressionSP;
+ typedef std::shared_ptr<lldb_private::UserExpression> UserExpressionSP;
typedef std::shared_ptr<lldb_private::CommandObject> CommandObjectSP;
typedef std::shared_ptr<lldb_private::Communication> CommunicationSP;
typedef std::shared_ptr<lldb_private::Connection> ConnectionSP;
@@ -326,6 +328,7 @@ namespace lldb {
typedef std::shared_ptr<lldb_private::ExpressionVariable> ExpressionVariableSP;
typedef std::shared_ptr<lldb_private::File> FileSP;
typedef std::shared_ptr<lldb_private::Function> FunctionSP;
+ typedef std::shared_ptr<lldb_private::FunctionCaller> FunctionCallerSP;
typedef std::shared_ptr<lldb_private::FuncUnwinders> FuncUnwindersSP;
typedef std::unique_ptr<lldb_private::GoASTContext> GoASTContextUP;
typedef std::shared_ptr<lldb_private::InlineFunctionInfo> InlineFunctionInfoSP;
@@ -434,6 +437,7 @@ namespace lldb {
typedef std::weak_ptr<lldb_private::UnixSignals> UnixSignalsWP;
typedef std::shared_ptr<lldb_private::UnwindAssembly> UnwindAssemblySP;
typedef std::shared_ptr<lldb_private::UnwindPlan> UnwindPlanSP;
+ typedef std::shared_ptr<lldb_private::UtilityFunction> UtilityFunctionSP;
typedef lldb_private::SharingPtr<lldb_private::ValueObject> ValueObjectSP;
typedef std::shared_ptr<lldb_private::Value> ValueSP;
typedef std::shared_ptr<lldb_private::ValueList> ValueListSP;
diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj
index e48a6875cce..6b960a6c637 100644
--- a/lldb/lldb.xcodeproj/project.pbxproj
+++ b/lldb/lldb.xcodeproj/project.pbxproj
@@ -387,7 +387,7 @@
2689005C13353E0400698AC0 /* ValueObjectVariable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E9D10F1B85900F91463 /* ValueObjectVariable.cpp */; };
2689005D13353E0400698AC0 /* VMRange.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E9E10F1B85900F91463 /* VMRange.cpp */; };
2689005E13353E0E00698AC0 /* ClangASTSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49D7072811B5AD11001AD875 /* ClangASTSource.cpp */; };
- 2689005F13353E0E00698AC0 /* ClangFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C98D3DA118FB96F00E575D0 /* ClangFunction.cpp */; };
+ 2689005F13353E0E00698AC0 /* ClangFunctionCaller.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C98D3DA118FB96F00E575D0 /* ClangFunctionCaller.cpp */; };
2689006013353E0E00698AC0 /* ClangExpressionDeclMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49F1A74511B3388F003ED505 /* ClangExpressionDeclMap.cpp */; };
2689006113353E0E00698AC0 /* ClangExpressionParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49445C2512245E3600C11A81 /* ClangExpressionParser.cpp */; };
2689006313353E0E00698AC0 /* ClangPersistentVariables.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49D4FE871210B61C00CDB854 /* ClangPersistentVariables.cpp */; };
@@ -680,11 +680,15 @@
49DA65031485C92A005FF180 /* AppleObjCDeclVendor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49DA65021485C92A005FF180 /* AppleObjCDeclVendor.cpp */; };
49DCF6FE170E6B4A0092F75E /* IRMemoryMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49DCF6FD170E6B4A0092F75E /* IRMemoryMap.cpp */; };
49DCF702170E70120092F75E /* Materializer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49DCF700170E70120092F75E /* Materializer.cpp */; };
+ 4C0083401B9F9BA900D5CF24 /* UtilityFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C00833F1B9F9BA900D5CF24 /* UtilityFunction.cpp */; settings = {ASSET_TAGS = (); }; };
+ 4C2479BD1BA39295009C9A7B /* FunctionCaller.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C0083321B9A5DE200D5CF24 /* FunctionCaller.cpp */; settings = {ASSET_TAGS = (); }; };
4C3ADCD61810D88B00357218 /* BreakpointResolverFileRegex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CAA56141422D986001FFA01 /* BreakpointResolverFileRegex.cpp */; };
4C56543119D1EFAA002E9C44 /* ThreadPlanPython.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C56543019D1EFAA002E9C44 /* ThreadPlanPython.cpp */; };
4C56543519D2297A002E9C44 /* SBThreadPlan.h in Headers */ = {isa = PBXBuildFile; fileRef = 4C56543419D2297A002E9C44 /* SBThreadPlan.h */; settings = {ATTRIBUTES = (Public, ); }; };
4C56543719D22B32002E9C44 /* SBThreadPlan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C56543619D22B32002E9C44 /* SBThreadPlan.cpp */; };
4C6649A314EEE81000B0316F /* StreamCallback.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C6649A214EEE81000B0316F /* StreamCallback.cpp */; };
+ 4C88BC2A1BA3722B00AA0964 /* Expression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C88BC291BA3722B00AA0964 /* Expression.cpp */; settings = {ASSET_TAGS = (); }; };
+ 4C88BC2D1BA391B000AA0964 /* UserExpression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C0083331B9A5DE200D5CF24 /* UserExpression.cpp */; settings = {ASSET_TAGS = (); }; };
4CABA9E0134A8BCD00539BDD /* ValueObjectMemory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CABA9DF134A8BCD00539BDD /* ValueObjectMemory.cpp */; };
4CCA644D13B40B82003BDF98 /* ItaniumABILanguageRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CCA643D13B40B82003BDF98 /* ItaniumABILanguageRuntime.cpp */; };
4CCA645013B40B82003BDF98 /* AppleObjCRuntime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CCA644213B40B82003BDF98 /* AppleObjCRuntime.cpp */; };
@@ -1875,7 +1879,7 @@
26BC7D8410F1B77400F91463 /* ValueObjectList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObjectList.h; path = include/lldb/Core/ValueObjectList.h; sourceTree = "<group>"; };
26BC7D8510F1B77400F91463 /* ValueObjectVariable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValueObjectVariable.h; path = include/lldb/Core/ValueObjectVariable.h; sourceTree = "<group>"; };
26BC7D8610F1B77400F91463 /* VMRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = VMRange.h; path = include/lldb/Core/VMRange.h; sourceTree = "<group>"; };
- 26BC7DC010F1B79500F91463 /* ClangExpression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangExpression.h; path = include/lldb/Expression/ClangExpression.h; sourceTree = "<group>"; };
+ 26BC7DC010F1B79500F91463 /* ClangExpressionHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangExpressionHelper.h; path = include/lldb/Expression/ClangExpressionHelper.h; sourceTree = "<group>"; };
26BC7DC310F1B79500F91463 /* DWARFExpression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DWARFExpression.h; path = include/lldb/Expression/DWARFExpression.h; sourceTree = "<group>"; };
26BC7DD210F1B7D500F91463 /* Condition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Condition.h; path = include/lldb/Host/Condition.h; sourceTree = "<group>"; };
26BC7DD310F1B7D500F91463 /* Endian.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Endian.h; path = include/lldb/Host/Endian.h; sourceTree = "<group>"; };
@@ -2289,12 +2293,21 @@
49EC3E9C118F90D400B1265E /* ThreadPlanCallFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanCallFunction.h; path = include/lldb/Target/ThreadPlanCallFunction.h; sourceTree = "<group>"; };
49F1A74511B3388F003ED505 /* ClangExpressionDeclMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangExpressionDeclMap.cpp; path = source/Expression/ClangExpressionDeclMap.cpp; sourceTree = "<group>"; };
49F1A74911B338AE003ED505 /* ClangExpressionDeclMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangExpressionDeclMap.h; path = include/lldb/Expression/ClangExpressionDeclMap.h; sourceTree = "<group>"; };
+ 4C00832C1B9A58A700D5CF24 /* Expression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Expression.h; path = include/lldb/Expression/Expression.h; sourceTree = "<group>"; };
+ 4C00832D1B9A58A700D5CF24 /* FunctionCaller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FunctionCaller.h; path = include/lldb/Expression/FunctionCaller.h; sourceTree = "<group>"; };
+ 4C00832E1B9A58A700D5CF24 /* UserExpression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UserExpression.h; path = include/lldb/Expression/UserExpression.h; sourceTree = "<group>"; };
+ 4C0083321B9A5DE200D5CF24 /* FunctionCaller.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FunctionCaller.cpp; path = source/Expression/FunctionCaller.cpp; sourceTree = "<group>"; };
+ 4C0083331B9A5DE200D5CF24 /* UserExpression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UserExpression.cpp; path = source/Expression/UserExpression.cpp; sourceTree = "<group>"; };
+ 4C00833D1B9F9B8400D5CF24 /* UtilityFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UtilityFunction.h; path = include/lldb/Expression/UtilityFunction.h; sourceTree = "<group>"; };
+ 4C00833F1B9F9BA900D5CF24 /* UtilityFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UtilityFunction.cpp; path = source/Expression/UtilityFunction.cpp; sourceTree = "<group>"; };
4C00986F11500B4300F316B0 /* UnixSignals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UnixSignals.h; path = include/lldb/Target/UnixSignals.h; sourceTree = "<group>"; };
4C00987011500B4300F316B0 /* UnixSignals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UnixSignals.cpp; path = source/Target/UnixSignals.cpp; sourceTree = "<group>"; };
4C08CDE711C81EF8001610A8 /* ThreadSpec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadSpec.cpp; path = source/Target/ThreadSpec.cpp; sourceTree = "<group>"; };
4C08CDEB11C81F1E001610A8 /* ThreadSpec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadSpec.h; path = include/lldb/Target/ThreadSpec.h; sourceTree = "<group>"; };
4C09CB73116BD98B00C7A725 /* CommandCompletions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandCompletions.h; path = include/lldb/Interpreter/CommandCompletions.h; sourceTree = "<group>"; };
4C09CB74116BD98B00C7A725 /* CommandCompletions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandCompletions.cpp; path = source/Commands/CommandCompletions.cpp; sourceTree = "<group>"; };
+ 4C2479BE1BA39843009C9A7B /* ExpressionParser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ExpressionParser.h; path = include/lldb/Expression/ExpressionParser.h; sourceTree = "<group>"; };
+ 4C29E77D1BA2403F00DFF855 /* ExpressionTypeSystemHelper.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.h; name = ExpressionTypeSystemHelper.h; path = include/lldb/Expression/ExpressionTypeSystemHelper.h; sourceTree = "<group>"; };
4C2FAE2E135E3A70001EDE44 /* SharedCluster.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SharedCluster.h; path = include/lldb/Utility/SharedCluster.h; sourceTree = "<group>"; };
4C43DEF9110641F300E55CBF /* ThreadPlanShouldStopHere.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanShouldStopHere.h; path = include/lldb/Target/ThreadPlanShouldStopHere.h; sourceTree = "<group>"; };
4C43DEFA110641F300E55CBF /* ThreadPlanShouldStopHere.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanShouldStopHere.cpp; path = source/Target/ThreadPlanShouldStopHere.cpp; sourceTree = "<group>"; };
@@ -2315,9 +2328,10 @@
4C73152119B7D71700F865A4 /* Iterable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Iterable.h; path = include/lldb/Utility/Iterable.h; sourceTree = "<group>"; };
4C7CF7E31295E10E00B4FBB5 /* ThreadPlanCallUserExpression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThreadPlanCallUserExpression.h; path = include/lldb/Target/ThreadPlanCallUserExpression.h; sourceTree = "<group>"; };
4C7CF7E51295E12B00B4FBB5 /* ThreadPlanCallUserExpression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ThreadPlanCallUserExpression.cpp; path = source/Target/ThreadPlanCallUserExpression.cpp; sourceTree = "<group>"; };
- 4C98D3DA118FB96F00E575D0 /* ClangFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangFunction.cpp; path = source/Expression/ClangFunction.cpp; sourceTree = "<group>"; };
+ 4C88BC291BA3722B00AA0964 /* Expression.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Expression.cpp; path = source/Expression/Expression.cpp; sourceTree = "<group>"; };
+ 4C98D3DA118FB96F00E575D0 /* ClangFunctionCaller.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangFunctionCaller.cpp; path = source/Expression/ClangFunctionCaller.cpp; sourceTree = "<group>"; };
4C98D3DB118FB96F00E575D0 /* IRExecutionUnit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IRExecutionUnit.cpp; path = source/Expression/IRExecutionUnit.cpp; sourceTree = "<group>"; };
- 4C98D3E0118FB98F00E575D0 /* ClangFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangFunction.h; path = include/lldb/Expression/ClangFunction.h; sourceTree = "<group>"; };
+ 4C98D3E0118FB98F00E575D0 /* ClangFunctionCaller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangFunctionCaller.h; path = include/lldb/Expression/ClangFunctionCaller.h; sourceTree = "<group>"; };
4C98D3E1118FB98F00E575D0 /* IRExecutionUnit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = IRExecutionUnit.h; path = include/lldb/Expression/IRExecutionUnit.h; sourceTree = "<group>"; };
4CA9637911B6E99A00780E28 /* CommandObjectApropos.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectApropos.cpp; path = source/Commands/CommandObjectApropos.cpp; sourceTree = "<group>"; };
4CA9637A11B6E99A00780E28 /* CommandObjectApropos.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CommandObjectApropos.h; path = source/Commands/CommandObjectApropos.h; sourceTree = "<group>"; };
@@ -4374,27 +4388,37 @@
26BC7DBE10F1B78200F91463 /* Expression */ = {
isa = PBXGroup;
children = (
+ 4C00832C1B9A58A700D5CF24 /* Expression.h */,
+ 4C88BC291BA3722B00AA0964 /* Expression.cpp */,
+ 4C29E77D1BA2403F00DFF855 /* ExpressionTypeSystemHelper.h */,
+ 26BC7DC010F1B79500F91463 /* ClangExpressionHelper.h */,
+ 4C00832D1B9A58A700D5CF24 /* FunctionCaller.h */,
+ 4C0083321B9A5DE200D5CF24 /* FunctionCaller.cpp */,
+ 4C98D3E0118FB98F00E575D0 /* ClangFunctionCaller.h */,
+ 4C98D3DA118FB96F00E575D0 /* ClangFunctionCaller.cpp */,
+ 4C00832E1B9A58A700D5CF24 /* UserExpression.h */,
+ 4C0083331B9A5DE200D5CF24 /* UserExpression.cpp */,
+ 49445E341225AB6A00C11A81 /* ClangUserExpression.h */,
+ 26BC7ED510F1B86700F91463 /* ClangUserExpression.cpp */,
+ 497C86C1122823F300B54702 /* ClangUtilityFunction.h */,
+ 497C86BD122823D800B54702 /* ClangUtilityFunction.cpp */,
+ 4C00833D1B9F9B8400D5CF24 /* UtilityFunction.h */,
+ 4C00833F1B9F9BA900D5CF24 /* UtilityFunction.cpp */,
49A1CAC11430E21D00306AC9 /* ExpressionSourceCode.h */,
49A1CAC31430E8BD00306AC9 /* ExpressionSourceCode.cpp */,
4984BA171B979C08008658D4 /* ExpressionVariable.h */,
4984BA151B979973008658D4 /* ExpressionVariable.cpp */,
49D7072611B5AD03001AD875 /* ClangASTSource.h */,
49D7072811B5AD11001AD875 /* ClangASTSource.cpp */,
- 26BC7DC010F1B79500F91463 /* ClangExpression.h */,
- 4C98D3E0118FB98F00E575D0 /* ClangFunction.h */,
- 4C98D3DA118FB96F00E575D0 /* ClangFunction.cpp */,
49F1A74911B338AE003ED505 /* ClangExpressionDeclMap.h */,
49F1A74511B3388F003ED505 /* ClangExpressionDeclMap.cpp */,
+ 4C2479BE1BA39843009C9A7B /* ExpressionParser.h */,
49445C2912245E5500C11A81 /* ClangExpressionParser.h */,
49445C2512245E3600C11A81 /* ClangExpressionParser.cpp */,
4959511B1A1BC48100F6F8FC /* ClangModulesDeclVendor.h */,
4959511E1A1BC4BC00F6F8FC /* ClangModulesDeclVendor.cpp */,
49D4FE821210B5FB00CDB854 /* ClangPersistentVariables.h */,
49D4FE871210B61C00CDB854 /* ClangPersistentVariables.cpp */,
- 49445E341225AB6A00C11A81 /* ClangUserExpression.h */,
- 26BC7ED510F1B86700F91463 /* ClangUserExpression.cpp */,
- 497C86C1122823F300B54702 /* ClangUtilityFunction.h */,
- 497C86BD122823D800B54702 /* ClangUtilityFunction.cpp */,
26BC7DC310F1B79500F91463 /* DWARFExpression.h */,
26BC7ED810F1B86700F91463 /* DWARFExpression.cpp */,
4906FD4412F2257600A2A77C /* ASTDumper.h */,
@@ -6124,6 +6148,7 @@
33E5E8471A674FB60024ED68 /* StringConvert.cpp in Sources */,
26D1804216CEDF0700EDFB5B /* TimeSpecTimeout.cpp in Sources */,
2689FFDA13353D9D00698AC0 /* lldb.cpp in Sources */,
+ 4C0083401B9F9BA900D5CF24 /* UtilityFunction.cpp in Sources */,
26474CCD18D0CB5B0073DEBA /* RegisterContextPOSIX_x86.cpp in Sources */,
2689FFEF13353DB600698AC0 /* Breakpoint.cpp in Sources */,
267A47FB1B1411C40021A5BC /* NativeRegisterContext.cpp in Sources */,
@@ -6159,6 +6184,7 @@
2689000F13353DB600698AC0 /* StoppointLocation.cpp in Sources */,
2689001113353DB600698AC0 /* Watchpoint.cpp in Sources */,
2689001213353DDE00698AC0 /* CommandObjectApropos.cpp in Sources */,
+ 4C88BC2A1BA3722B00AA0964 /* Expression.cpp in Sources */,
23042D121976CA1D00621B2C /* PlatformKalimba.cpp in Sources */,
2689001313353DDE00698AC0 /* CommandObjectArgs.cpp in Sources */,
2689001413353DDE00698AC0 /* CommandObjectBreakpoint.cpp in Sources */,
@@ -6278,7 +6304,7 @@
2689005D13353E0400698AC0 /* VMRange.cpp in Sources */,
2689005E13353E0E00698AC0 /* ClangASTSource.cpp in Sources */,
3FDFED0F19B7D269009756A7 /* ThisThread.cpp in Sources */,
- 2689005F13353E0E00698AC0 /* ClangFunction.cpp in Sources */,
+ 2689005F13353E0E00698AC0 /* ClangFunctionCaller.cpp in Sources */,
2689006013353E0E00698AC0 /* ClangExpressionDeclMap.cpp in Sources */,
2689006113353E0E00698AC0 /* ClangExpressionParser.cpp in Sources */,
B5EFAE861AE53B1D007059F3 /* RegisterContextFreeBSD_arm.cpp in Sources */,
@@ -6402,6 +6428,7 @@
268900CC13353E5F00698AC0 /* SymbolFileDWARFDebugMap.cpp in Sources */,
268900CD13353E5F00698AC0 /* UniqueDWARFASTType.cpp in Sources */,
944372DC171F6B4300E57C32 /* RegisterContextDummy.cpp in Sources */,
+ 4C88BC2D1BA391B000AA0964 /* UserExpression.cpp in Sources */,
268900CE13353E5F00698AC0 /* SymbolFileSymtab.cpp in Sources */,
266E82971B8CE3AC008FCA06 /* DWARFDIE.cpp in Sources */,
268900CF13353E5F00698AC0 /* SymbolVendorMacOSX.cpp in Sources */,
@@ -6444,6 +6471,7 @@
268900EC13353E6F00698AC0 /* LanguageRuntime.cpp in Sources */,
268900ED13353E6F00698AC0 /* ObjCLanguageRuntime.cpp in Sources */,
268900EE13353E6F00698AC0 /* PathMappingList.cpp in Sources */,
+ 4C2479BD1BA39295009C9A7B /* FunctionCaller.cpp in Sources */,
268900EF13353E6F00698AC0 /* Platform.cpp in Sources */,
268900F013353E6F00698AC0 /* Process.cpp in Sources */,
26BC17AD18C7F4CB00D2196D /* RegisterContextPOSIXCore_mips64.cpp in Sources */,
diff --git a/lldb/source/API/SBFrame.cpp b/lldb/source/API/SBFrame.cpp
index df6cc51ed07..ee467402569 100644
--- a/lldb/source/API/SBFrame.cpp
+++ b/lldb/source/API/SBFrame.cpp
@@ -22,7 +22,7 @@
#include "lldb/Core/ValueObjectRegister.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/Expression/ClangPersistentVariables.h"
-#include "lldb/Expression/ClangUserExpression.h"
+#include "lldb/Expression/UserExpression.h"
#include "lldb/Host/Host.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/Function.h"
diff --git a/lldb/source/Breakpoint/BreakpointLocation.cpp b/lldb/source/Breakpoint/BreakpointLocation.cpp
index 1d082f69416..0dab0e16bf1 100644
--- a/lldb/source/Breakpoint/BreakpointLocation.cpp
+++ b/lldb/source/Breakpoint/BreakpointLocation.cpp
@@ -21,9 +21,10 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/ValueObject.h"
-#include "lldb/Expression/ClangUserExpression.h"
+#include "lldb/Expression/UserExpression.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/Symbol.h"
+#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Thread.h"
@@ -88,6 +89,12 @@ BreakpointLocation::GetBreakpoint ()
return m_owner;
}
+Target &
+BreakpointLocation::GetTarget()
+{
+ return m_owner.GetTarget();
+}
+
bool
BreakpointLocation::IsEnabled () const
{
@@ -278,10 +285,26 @@ BreakpointLocation::ConditionSaysStop (ExecutionContext &exe_ctx, Error &error)
!m_user_expression_sp ||
!m_user_expression_sp->MatchesContext(exe_ctx))
{
- m_user_expression_sp.reset(new ClangUserExpression(condition_text,
- NULL,
- lldb::eLanguageTypeUnknown,
- ClangUserExpression::eResultTypeAny));
+ LanguageType language = eLanguageTypeUnknown;
+ // See if we can figure out the language from the frame, otherwise use the default language:
+ CompileUnit *comp_unit = m_address.CalculateSymbolContextCompileUnit();
+ if (comp_unit)
+ language = comp_unit->GetLanguage();
+
+ Error error;
+ m_user_expression_sp.reset(GetTarget().GetUserExpressionForLanguage(condition_text,
+ NULL,
+ language,
+ Expression::eResultTypeAny,
+ error));
+ if (error.Fail())
+ {
+ if (log)
+ log->Printf("Error getting condition expression: %s.", error.AsCString());
+ m_user_expression_sp.reset();
+ return true;
+ }
+
StreamString errors;
diff --git a/lldb/source/Breakpoint/BreakpointOptions.cpp b/lldb/source/Breakpoint/BreakpointOptions.cpp
index db76ffb8685..99a4d47a8d9 100644
--- a/lldb/source/Breakpoint/BreakpointOptions.cpp
+++ b/lldb/source/Breakpoint/BreakpointOptions.cpp
@@ -20,7 +20,6 @@
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadSpec.h"
-#include "lldb/Expression/ClangUserExpression.h"
using namespace lldb;
using namespace lldb_private;
diff --git a/lldb/source/Breakpoint/Watchpoint.cpp b/lldb/source/Breakpoint/Watchpoint.cpp
index af9cfaff6a2..41b24fd67df 100644
--- a/lldb/source/Breakpoint/Watchpoint.cpp
+++ b/lldb/source/Breakpoint/Watchpoint.cpp
@@ -22,7 +22,7 @@
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadSpec.h"
-#include "lldb/Expression/ClangUserExpression.h"
+#include "lldb/Expression/UserExpression.h"
using namespace lldb;
using namespace lldb_private;
@@ -371,7 +371,17 @@ Watchpoint::SetCondition (const char *condition)
else
{
// Pass NULL for expr_prefix (no translation-unit level definitions).
- m_condition_ap.reset(new ClangUserExpression (condition, NULL, lldb::eLanguageTypeUnknown, ClangUserExpression::eResultTypeAny));
+ Error error;
+ m_condition_ap.reset(m_target.GetUserExpressionForLanguage (condition,
+ NULL,
+ lldb::eLanguageTypeUnknown,
+ UserExpression::eResultTypeAny,
+ error));
+ if (error.Fail())
+ {
+ // FIXME: Log something...
+ m_condition_ap.reset();
+ }
}
SendWatchpointChangedEvent (eWatchpointEventTypeConditionChanged);
}
diff --git a/lldb/source/Breakpoint/WatchpointOptions.cpp b/lldb/source/Breakpoint/WatchpointOptions.cpp
index c2c9696c4ce..d11c8f74f94 100644
--- a/lldb/source/Breakpoint/WatchpointOptions.cpp
+++ b/lldb/source/Breakpoint/WatchpointOptions.cpp
@@ -20,7 +20,6 @@
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/ThreadSpec.h"
-#include "lldb/Expression/ClangUserExpression.h"
using namespace lldb;
using namespace lldb_private;
diff --git a/lldb/source/Commands/CommandObjectArgs.cpp b/lldb/source/Commands/CommandObjectArgs.cpp
index 39dcba07cca..c4db97caa6a 100644
--- a/lldb/source/Commands/CommandObjectArgs.cpp
+++ b/lldb/source/Commands/CommandObjectArgs.cpp
@@ -17,9 +17,7 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Value.h"
-#include "lldb/Expression/ClangExpression.h"
#include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h"
-#include "lldb/Expression/ClangFunction.h"
#include "lldb/Host/Host.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp
index 7e787bce8c9..96dd90e7ecc 100644
--- a/lldb/source/Commands/CommandObjectExpression.cpp
+++ b/lldb/source/Commands/CommandObjectExpression.cpp
@@ -17,8 +17,7 @@
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/DataFormatters/ValueObjectPrinter.h"
#include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h"
-#include "lldb/Expression/ClangUserExpression.h"
-#include "lldb/Expression/ClangFunction.h"
+#include "lldb/Expression/UserExpression.h"
#include "lldb/Expression/DWARFExpression.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/StringConvert.h"
@@ -345,7 +344,7 @@ CommandObjectExpression::EvaluateExpression
}
else
{
- if (result_valobj_sp->GetError().GetError() == ClangUserExpression::kNoResult)
+ if (result_valobj_sp->GetError().GetError() == UserExpression::kNoResult)
{
if (format != eFormatVoid && m_interpreter.GetDebugger().GetNotifyVoid())
{
diff --git a/lldb/source/DataFormatters/VectorType.cpp b/lldb/source/DataFormatters/VectorType.cpp
index faef33de909..56ca3ceac2a 100644
--- a/lldb/source/DataFormatters/VectorType.cpp
+++ b/lldb/source/DataFormatters/VectorType.cpp
@@ -235,7 +235,7 @@ namespace lldb_private {
TargetSP target_sp(m_backend.GetTargetSP());
m_child_type = ::GetCompilerTypeForFormat(m_parent_format,
element_type,
- target_sp ? target_sp->GetTypeSystemForLanguage(lldb::eLanguageTypeC) : nullptr);
+ target_sp ? target_sp->GetScratchTypeSystemForLanguage(lldb::eLanguageTypeC) : nullptr);
m_num_children = ::CalculateNumChildren(parent_type,
m_child_type);
m_item_format = GetItemFormatForFormat(m_parent_format,
diff --git a/lldb/source/Expression/ASTStructExtractor.cpp b/lldb/source/Expression/ASTStructExtractor.cpp
index 98628dbc92b..049173e32f3 100644
--- a/lldb/source/Expression/ASTStructExtractor.cpp
+++ b/lldb/source/Expression/ASTStructExtractor.cpp
@@ -28,7 +28,7 @@ using namespace lldb_private;
ASTStructExtractor::ASTStructExtractor(ASTConsumer *passthrough,
const char *struct_name,
- ClangFunction &function) :
+ ClangFunctionCaller &function) :
m_ast_context (NULL),
m_passthrough (passthrough),
m_passthrough_sema (NULL),
diff --git a/lldb/source/Expression/CMakeLists.txt b/lldb/source/Expression/CMakeLists.txt
index 92f8f0863bf..4b689da027b 100644
--- a/lldb/source/Expression/CMakeLists.txt
+++ b/lldb/source/Expression/CMakeLists.txt
@@ -5,18 +5,22 @@ add_lldb_library(lldbExpression
ClangASTSource.cpp
ClangExpressionDeclMap.cpp
ClangExpressionParser.cpp
- ClangFunction.cpp
+ ClangFunctionCaller.cpp
ClangModulesDeclVendor.cpp
ClangPersistentVariables.cpp
ClangUserExpression.cpp
ClangUtilityFunction.cpp
DWARFExpression.cpp
+ Expression.cpp
ExpressionSourceCode.cpp
ExpressionVariable.cpp
+ FunctionCaller.cpp
IRDynamicChecks.cpp
IRExecutionUnit.cpp
IRForTarget.cpp
IRInterpreter.cpp
IRMemoryMap.cpp
Materializer.cpp
+ UserExpression.cpp
+ UtilityFunction.cpp
)
diff --git a/lldb/source/Expression/ClangASTSource.cpp b/lldb/source/Expression/ClangASTSource.cpp
index ef778a1bca4..e6ddaa7e506 100644
--- a/lldb/source/Expression/ClangASTSource.cpp
+++ b/lldb/source/Expression/ClangASTSource.cpp
@@ -15,7 +15,6 @@
#include "lldb/Core/ModuleList.h"
#include "lldb/Expression/ASTDumper.h"
#include "lldb/Expression/ClangASTSource.h"
-#include "lldb/Expression/ClangExpression.h"
#include "lldb/Expression/ClangModulesDeclVendor.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/CompilerDeclContext.h"
diff --git a/lldb/source/Expression/ClangExpressionParser.cpp b/lldb/source/Expression/ClangExpressionParser.cpp
index d5dbaf16b4a..2a4663966cf 100644
--- a/lldb/source/Expression/ClangExpressionParser.cpp
+++ b/lldb/source/Expression/ClangExpressionParser.cpp
@@ -19,7 +19,7 @@
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Expression/ClangASTSource.h"
-#include "lldb/Expression/ClangExpression.h"
+#include "lldb/Expression/ClangExpressionHelper.h"
#include "lldb/Expression/ClangExpressionDeclMap.h"
#include "lldb/Expression/ClangModulesDeclVendor.h"
#include "lldb/Expression/ClangPersistentVariables.h"
@@ -37,6 +37,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Version.h"
#include "clang/CodeGen/CodeGenAction.h"
@@ -108,7 +109,7 @@ public:
}
virtual void moduleImport(SourceLocation import_location,
- ModuleIdPath path,
+ clang::ModuleIdPath path,
const clang::Module * /*null*/)
{
std::vector<ConstString> string_path;
@@ -149,9 +150,9 @@ public:
//===----------------------------------------------------------------------===//
ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope,
- ClangExpression &expr,
+ Expression &expr,
bool generate_debug_info) :
- m_expr (expr),
+ ExpressionParser (exe_scope, expr, generate_debug_info),
m_compiler (),
m_code_generator (),
m_pp_callbacks(nullptr)
@@ -255,7 +256,7 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope,
m_compiler->getLangOpts().WChar = true;
m_compiler->getLangOpts().Blocks = true;
m_compiler->getLangOpts().DebuggerSupport = true; // Features specifically for debugger clients
- if (expr.DesiredResultType() == ClangExpression::eResultTypeId)
+ if (expr.DesiredResultType() == Expression::eResultTypeId)
m_compiler->getLangOpts().DebuggerCastResultToId = true;
m_compiler->getLangOpts().CharIsSigned =
@@ -346,7 +347,8 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope,
ast_context->InitBuiltinTypes(m_compiler->getTarget());
- ClangExpressionDeclMap *decl_map = m_expr.DeclMap();
+ ClangExpressionHelper *type_system_helper = dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper());
+ ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap();
if (decl_map)
{
@@ -430,9 +432,11 @@ ClangExpressionParser::Parse (Stream &stream)
diag_buf->BeginSourceFile(m_compiler->getLangOpts(), &m_compiler->getPreprocessor());
- ASTConsumer *ast_transformer = m_expr.ASTTransformer(m_code_generator.get());
+ ClangExpressionHelper *type_system_helper = dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper());
- if (ClangExpressionDeclMap *decl_map = m_expr.DeclMap())
+ ASTConsumer *ast_transformer = type_system_helper->ASTTransformer(m_code_generator.get());
+
+ if (ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap())
decl_map->InstallCodeGenerator(m_code_generator.get());
if (ast_transformer)
@@ -479,7 +483,7 @@ ClangExpressionParser::Parse (Stream &stream)
if (!num_errors)
{
- if (m_expr.DeclMap() && !m_expr.DeclMap()->ResolveUnknownTypes())
+ if (type_system_helper->DeclMap() && !type_system_helper->DeclMap()->ResolveUnknownTypes())
{
stream.Printf("error: Couldn't infer the type of a variable\n");
num_errors++;
@@ -552,7 +556,8 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
exe_ctx.GetTargetSP(),
m_compiler->getTargetOpts().Features));
- ClangExpressionDeclMap *decl_map = m_expr.DeclMap(); // result can be NULL
+ ClangExpressionHelper *type_system_helper = dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper());
+ ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap(); // result can be NULL
if (decl_map)
{
@@ -640,11 +645,3 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr,
return err;
}
-
-bool
-ClangExpressionParser::GetGenerateDebugInfo () const
-{
- if (m_compiler)
- return m_compiler->getCodeGenOpts().getDebugInfo() == CodeGenOptions::FullDebugInfo;
- return false;
-}
diff --git a/lldb/source/Expression/ClangFunctionCaller.cpp b/lldb/source/Expression/ClangFunctionCaller.cpp
new file mode 100644
index 00000000000..628952fe6b8
--- /dev/null
+++ b/lldb/source/Expression/ClangFunctionCaller.cpp
@@ -0,0 +1,220 @@
+//===-- ClangFunctionCallerCaller.cpp ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/CodeGen/CodeGenAction.h"
+#include "clang/CodeGen/ModuleBuilder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/IR/Module.h"
+
+// Project includes
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/State.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectList.h"
+#include "lldb/Expression/ASTStructExtractor.h"
+#include "lldb/Expression/ClangExpressionParser.h"
+#include "lldb/Expression/ClangFunctionCaller.h"
+#include "lldb/Expression/IRExecutionUnit.h"
+#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanCallFunction.h"
+
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// ClangFunctionCaller constructor
+//----------------------------------------------------------------------
+ClangFunctionCaller::ClangFunctionCaller
+(
+ ExecutionContextScope &exe_scope,
+ const CompilerType &return_type,
+ const Address& functionAddress,
+ const ValueList &arg_value_list,
+ const char *name
+) :
+ FunctionCaller(exe_scope, return_type, functionAddress, arg_value_list, name),
+ m_type_system_helper (*this)
+{
+ m_jit_process_wp = lldb::ProcessWP(exe_scope.CalculateProcess());
+ // Can't make a ClangFunctionCaller without a process.
+ assert (m_jit_process_wp.lock());
+}
+
+//----------------------------------------------------------------------
+// Destructor
+//----------------------------------------------------------------------
+ClangFunctionCaller::~ClangFunctionCaller()
+{
+}
+
+unsigned
+ClangFunctionCaller::CompileFunction (Stream &errors)
+{
+ if (m_compiled)
+ return 0;
+
+ // FIXME: How does clang tell us there's no return value? We need to handle that case.
+ unsigned num_errors = 0;
+
+ std::string return_type_str (m_function_return_type.GetTypeName().AsCString(""));
+
+ // Cons up the function we're going to wrap our call in, then compile it...
+ // We declare the function "extern "C"" because the compiler might be in C++
+ // mode which would mangle the name and then we couldn't find it again...
+ m_wrapper_function_text.clear();
+ m_wrapper_function_text.append ("extern \"C\" void ");
+ m_wrapper_function_text.append (m_wrapper_function_name);
+ m_wrapper_function_text.append (" (void *input)\n{\n struct ");
+ m_wrapper_function_text.append (m_wrapper_struct_name);
+ m_wrapper_function_text.append (" \n {\n");
+ m_wrapper_function_text.append (" ");
+ m_wrapper_function_text.append (return_type_str);
+ m_wrapper_function_text.append (" (*fn_ptr) (");
+
+ // Get the number of arguments. If we have a function type and it is prototyped,
+ // trust that, otherwise use the values we were given.
+
+ // FIXME: This will need to be extended to handle Variadic functions. We'll need
+ // to pull the defined arguments out of the function, then add the types from the
+ // arguments list for the variable arguments.
+
+ uint32_t num_args = UINT32_MAX;
+ bool trust_function = false;
+ // GetArgumentCount returns -1 for an unprototyped function.
+ CompilerType function_clang_type;
+ if (m_function_ptr)
+ {
+ function_clang_type = m_function_ptr->GetCompilerType();
+ if (function_clang_type)
+ {
+ int num_func_args = function_clang_type.GetFunctionArgumentCount();
+ if (num_func_args >= 0)
+ {
+ trust_function = true;
+ num_args = num_func_args;
+ }
+ }
+ }
+
+ if (num_args == UINT32_MAX)
+ num_args = m_arg_values.GetSize();
+
+ std::string args_buffer; // This one stores the definition of all the args in "struct caller".
+ std::string args_list_buffer; // This one stores the argument list called from the structure.
+ for (size_t i = 0; i < num_args; i++)
+ {
+ std::string type_name;
+
+ if (trust_function)
+ {
+ type_name = function_clang_type.GetFunctionArgumentTypeAtIndex(i).GetTypeName().AsCString("");
+ }
+ else
+ {
+ CompilerType clang_qual_type = m_arg_values.GetValueAtIndex(i)->GetCompilerType ();
+ if (clang_qual_type)
+ {
+ type_name = clang_qual_type.GetTypeName().AsCString("");
+ }
+ else
+ {
+ errors.Printf("Could not determine type of input value %" PRIu64 ".", (uint64_t)i);
+ return 1;
+ }
+ }
+
+ m_wrapper_function_text.append (type_name);
+ if (i < num_args - 1)
+ m_wrapper_function_text.append (", ");
+
+ char arg_buf[32];
+ args_buffer.append (" ");
+ args_buffer.append (type_name);
+ snprintf(arg_buf, 31, "arg_%" PRIu64, (uint64_t)i);
+ args_buffer.push_back (' ');
+ args_buffer.append (arg_buf);
+ args_buffer.append (";\n");
+
+ args_list_buffer.append ("__lldb_fn_data->");
+ args_list_buffer.append (arg_buf);
+ if (i < num_args - 1)
+ args_list_buffer.append (", ");
+
+ }
+ m_wrapper_function_text.append (");\n"); // Close off the function calling prototype.
+
+ m_wrapper_function_text.append (args_buffer);
+
+ m_wrapper_function_text.append (" ");
+ m_wrapper_function_text.append (return_type_str);
+ m_wrapper_function_text.append (" return_value;");
+ m_wrapper_function_text.append ("\n };\n struct ");
+ m_wrapper_function_text.append (m_wrapper_struct_name);
+ m_wrapper_function_text.append ("* __lldb_fn_data = (struct ");
+ m_wrapper_function_text.append (m_wrapper_struct_name);
+ m_wrapper_function_text.append (" *) input;\n");
+
+ m_wrapper_function_text.append (" __lldb_fn_data->return_value = __lldb_fn_data->fn_ptr (");
+ m_wrapper_function_text.append (args_list_buffer);
+ m_wrapper_function_text.append (");\n}\n");
+
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+ if (log)
+ log->Printf ("Expression: \n\n%s\n\n", m_wrapper_function_text.c_str());
+
+ // Okay, now compile this expression
+
+ lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());
+ if (jit_process_sp)
+ {
+ const bool generate_debug_info = true;
+ m_parser.reset(new ClangExpressionParser(jit_process_sp.get(), *this, generate_debug_info));
+
+ num_errors = m_parser->Parse (errors);
+ }
+ else
+ {
+ errors.Printf("no process - unable to inject function");
+ num_errors = 1;
+ }
+
+ m_compiled = (num_errors == 0);
+
+ if (!m_compiled)
+ return num_errors;
+
+ return num_errors;
+}
+
+clang::ASTConsumer *
+ClangFunctionCaller::ClangFunctionCallerHelper::ASTTransformer (clang::ASTConsumer *passthrough)
+{
+ m_struct_extractor.reset(new ASTStructExtractor(passthrough, m_owner.GetWrapperStructName(), m_owner));
+
+ return m_struct_extractor.get();
+}
diff --git a/lldb/source/Expression/ClangUserExpression.cpp b/lldb/source/Expression/ClangUserExpression.cpp
index 9239389753e..a6e5923bf28 100644
--- a/lldb/source/Expression/ClangUserExpression.cpp
+++ b/lldb/source/Expression/ClangUserExpression.cpp
@@ -25,7 +25,6 @@
#include "lldb/Expression/ASTResultSynthesizer.h"
#include "lldb/Expression/ClangExpressionDeclMap.h"
#include "lldb/Expression/ClangExpressionParser.h"
-#include "lldb/Expression/ClangFunction.h"
#include "lldb/Expression/ClangModulesDeclVendor.h"
#include "lldb/Expression/ClangPersistentVariables.h"
#include "lldb/Expression/ClangUserExpression.h"
@@ -54,32 +53,13 @@
using namespace lldb_private;
-ClangUserExpression::ClangUserExpression (const char *expr,
+ClangUserExpression::ClangUserExpression (ExecutionContextScope &exe_scope,
+ const char *expr,
const char *expr_prefix,
lldb::LanguageType language,
ResultType desired_type) :
- ClangExpression (),
- m_stack_frame_bottom (LLDB_INVALID_ADDRESS),
- m_stack_frame_top (LLDB_INVALID_ADDRESS),
- m_expr_text (expr),
- m_expr_prefix (expr_prefix ? expr_prefix : ""),
- m_language (language),
- m_transformed_text (),
- m_desired_type (desired_type),
- m_expr_decl_map(),
- m_execution_unit_sp(),
- m_materializer_ap(),
- m_result_synthesizer(),
- m_jit_module_wp(),
- m_enforce_valid_object (true),
- m_in_cplusplus_method (false),
- m_in_objectivec_method (false),
- m_in_static_method(false),
- m_needs_object_ptr (false),
- m_const_object (false),
- m_target (NULL),
- m_can_interpret (false),
- m_materialized_address (LLDB_INVALID_ADDRESS)
+ UserExpression (exe_scope, expr, expr_prefix, language, desired_type),
+ m_type_system_helper(*m_target_wp.lock().get())
{
switch (m_language)
{
@@ -99,21 +79,6 @@ ClangUserExpression::ClangUserExpression (const char *expr,
ClangUserExpression::~ClangUserExpression ()
{
- if (m_target)
- {
- lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock());
- if (jit_module_sp)
- m_target->GetImages().Remove(jit_module_sp);
- }
-}
-
-clang::ASTConsumer *
-ClangUserExpression::ASTTransformer (clang::ASTConsumer *passthrough)
-{
- m_result_synthesizer.reset(new ASTResultSynthesizer(passthrough,
- *m_target));
-
- return m_result_synthesizer.get();
}
void
@@ -338,54 +303,6 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err)
}
}
-void
-ClangUserExpression::InstallContext (ExecutionContext &exe_ctx)
-{
- m_process_wp = exe_ctx.GetProcessSP();
-
- lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP();
-
- if (frame_sp)
- m_address = frame_sp->GetFrameCodeAddress();
-}
-
-bool
-ClangUserExpression::LockAndCheckContext (ExecutionContext &exe_ctx,
- lldb::TargetSP &target_sp,
- lldb::ProcessSP &process_sp,
- lldb::StackFrameSP &frame_sp)
-{
- lldb::ProcessSP expected_process_sp = m_process_wp.lock();
- process_sp = exe_ctx.GetProcessSP();
-
- if (process_sp != expected_process_sp)
- return false;
-
- process_sp = exe_ctx.GetProcessSP();
- target_sp = exe_ctx.GetTargetSP();
- frame_sp = exe_ctx.GetFrameSP();
-
- if (m_address.IsValid())
- {
- if (!frame_sp)
- return false;
- else
- return (0 == Address::CompareLoadAddress(m_address, frame_sp->GetFrameCodeAddress(), target_sp.get()));
- }
-
- return true;
-}
-
-bool
-ClangUserExpression::MatchesContext (ExecutionContext &exe_ctx)
-{
- lldb::TargetSP target_sp;
- lldb::ProcessSP process_sp;
- lldb::StackFrameSP frame_sp;
-
- return LockAndCheckContext(exe_ctx, target_sp, process_sp, frame_sp);
-}
-
// This is a really nasty hack, meant to fix Objective-C expressions of the form
// (int)[myArray count]. Right now, because the type information for count is
// not available, [myArray count] returns id, which can't be directly cast to
@@ -405,26 +322,6 @@ ApplyObjcCastHack(std::string &expr)
#undef OBJC_CAST_HACK_FROM
}
-// Another hack, meant to allow use of unichar despite it not being available in
-// the type information. Although we could special-case it in type lookup,
-// hopefully we'll figure out a way to #include the same environment as is
-// present in the original source file rather than try to hack specific type
-// definitions in as needed.
-//static void
-//ApplyUnicharHack(std::string &expr)
-//{
-//#define UNICHAR_HACK_FROM "unichar"
-//#define UNICHAR_HACK_TO "unsigned short"
-//
-// size_t from_offset;
-//
-// while ((from_offset = expr.find(UNICHAR_HACK_FROM)) != expr.npos)
-// expr.replace(from_offset, sizeof(UNICHAR_HACK_FROM) - 1, UNICHAR_HACK_TO);
-//
-//#undef UNICHAR_HACK_TO
-//#undef UNICHAR_HACK_FROM
-//}
-
bool
ClangUserExpression::Parse (Stream &error_stream,
ExecutionContext &exe_ctx,
@@ -525,7 +422,7 @@ ClangUserExpression::Parse (Stream &error_stream,
m_materializer_ap.reset(new Materializer());
- m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx));
+ ResetDeclMap(exe_ctx, keep_result_in_memory);
class OnExit
{
@@ -545,13 +442,13 @@ ClangUserExpression::Parse (Stream &error_stream,
Callback m_callback;
};
- OnExit on_exit([this]() { m_expr_decl_map.reset(); });
+ OnExit on_exit([this]() { ResetDeclMap(); });
- if (!m_expr_decl_map->WillParse(exe_ctx, m_materializer_ap.get()))
+ if (!DeclMap()->WillParse(exe_ctx, m_materializer_ap.get()))
{
error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n");
- m_expr_decl_map.reset(); // We are being careful here in the case of breakpoint conditions.
+ ResetDeclMap(); // We are being careful here in the case of breakpoint conditions.
return false;
}
@@ -570,7 +467,7 @@ ClangUserExpression::Parse (Stream &error_stream,
{
error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
- m_expr_decl_map.reset(); // We are being careful here in the case of breakpoint conditions.
+ ResetDeclMap(); // We are being careful here in the case of breakpoint conditions.
return false;
}
@@ -617,7 +514,7 @@ ClangUserExpression::Parse (Stream &error_stream,
// }
}
- m_expr_decl_map.reset(); // Make this go away since we don't need any of its state after parsing. This also gets rid of any ClangASTImporter::Minions.
+ ResetDeclMap(); // Make this go away since we don't need any of its state after parsing. This also gets rid of any ClangASTImporter::Minions.
if (jit_error.Success())
{
@@ -636,537 +533,81 @@ ClangUserExpression::Parse (Stream &error_stream,
}
}
-static lldb::addr_t
-GetObjectPointer (lldb::StackFrameSP frame_sp,
- ConstString &object_name,
- Error &err)
-{
- err.Clear();
-
- if (!frame_sp)
- {
- err.SetErrorStringWithFormat("Couldn't load '%s' because the context is incomplete", object_name.AsCString());
- return LLDB_INVALID_ADDRESS;
- }
-
- lldb::VariableSP var_sp;
- lldb::ValueObjectSP valobj_sp;
-
- valobj_sp = frame_sp->GetValueForVariableExpressionPath(object_name.AsCString(),
- lldb::eNoDynamicValues,
- StackFrame::eExpressionPathOptionCheckPtrVsMember |
- StackFrame::eExpressionPathOptionsNoFragileObjcIvar |
- StackFrame::eExpressionPathOptionsNoSyntheticChildren |
- StackFrame::eExpressionPathOptionsNoSyntheticArrayRange,
- var_sp,
- err);
-
- if (!err.Success() || !valobj_sp.get())
- return LLDB_INVALID_ADDRESS;
-
- lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
-
- if (ret == LLDB_INVALID_ADDRESS)
- {
- err.SetErrorStringWithFormat("Couldn't load '%s' because its value couldn't be evaluated", object_name.AsCString());
- return LLDB_INVALID_ADDRESS;
- }
-
- return ret;
-}
-
bool
-ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
- ExecutionContext &exe_ctx,
- lldb::addr_t &struct_address,
- lldb::addr_t &object_ptr,
- lldb::addr_t &cmd_ptr)
+ClangUserExpression::AddInitialArguments (ExecutionContext &exe_ctx,
+ std::vector<lldb::addr_t> &args,
+ Stream &error_stream)
{
- lldb::TargetSP target;
- lldb::ProcessSP process;
- lldb::StackFrameSP frame;
-
- if (!LockAndCheckContext(exe_ctx,
- target,
- process,
- frame))
- {
- error_stream.Printf("The context has changed before we could JIT the expression!\n");
- return false;
- }
-
- if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret)
+ lldb::addr_t object_ptr = LLDB_INVALID_ADDRESS;
+ lldb::addr_t cmd_ptr = LLDB_INVALID_ADDRESS;
+
+ if (m_needs_object_ptr)
{
- if (m_needs_object_ptr)
- {
- ConstString object_name;
-
- if (m_in_cplusplus_method)
- {
- object_name.SetCString("this");
- }
- else if (m_in_objectivec_method)
- {
- object_name.SetCString("self");
- }
- else
- {
- error_stream.Printf("Need object pointer but don't know the language\n");
- return false;
- }
-
- Error object_ptr_error;
-
- object_ptr = GetObjectPointer(frame, object_name, object_ptr_error);
-
- if (!object_ptr_error.Success())
- {
- error_stream.Printf("warning: couldn't get required object pointer (substituting NULL): %s\n", object_ptr_error.AsCString());
- object_ptr = 0;
- }
-
- if (m_in_objectivec_method)
- {
- ConstString cmd_name("_cmd");
-
- cmd_ptr = GetObjectPointer(frame, cmd_name, object_ptr_error);
-
- if (!object_ptr_error.Success())
- {
- error_stream.Printf("warning: couldn't get cmd pointer (substituting NULL): %s\n", object_ptr_error.AsCString());
- cmd_ptr = 0;
- }
- }
- }
+ lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP();
+ if (!frame_sp)
+ return true;
+
+ ConstString object_name;
- if (m_materialized_address == LLDB_INVALID_ADDRESS)
+ if (m_in_cplusplus_method)
{
- Error alloc_error;
-
- IRMemoryMap::AllocationPolicy policy = m_can_interpret ? IRMemoryMap::eAllocationPolicyHostOnly : IRMemoryMap::eAllocationPolicyMirror;
-
- m_materialized_address = m_execution_unit_sp->Malloc(m_materializer_ap->GetStructByteSize(),
- m_materializer_ap->GetStructAlignment(),
- lldb::ePermissionsReadable | lldb::ePermissionsWritable,
- policy,
- alloc_error);
-
- if (!alloc_error.Success())
- {
- error_stream.Printf("Couldn't allocate space for materialized struct: %s\n", alloc_error.AsCString());
- return false;
- }
+ object_name.SetCString("this");
}
-
- struct_address = m_materialized_address;
-
- if (m_can_interpret && m_stack_frame_bottom == LLDB_INVALID_ADDRESS)
+ else if (m_in_objectivec_method)
{
- Error alloc_error;
-
- const size_t stack_frame_size = 512 * 1024;
-
- m_stack_frame_bottom = m_execution_unit_sp->Malloc(stack_frame_size,
- 8,
- lldb::ePermissionsReadable | lldb::ePermissionsWritable,
- IRMemoryMap::eAllocationPolicyHostOnly,
- alloc_error);
-
- m_stack_frame_top = m_stack_frame_bottom + stack_frame_size;
-
- if (!alloc_error.Success())
- {
- error_stream.Printf("Couldn't allocate space for the stack frame: %s\n", alloc_error.AsCString());
- return false;
- }
+ object_name.SetCString("self");
}
-
- Error materialize_error;
-
- m_dematerializer_sp = m_materializer_ap->Materialize(frame, *m_execution_unit_sp, struct_address, materialize_error);
-
- if (!materialize_error.Success())
+ else
{
- error_stream.Printf("Couldn't materialize: %s\n", materialize_error.AsCString());
+ error_stream.Printf("Need object pointer but don't know the language\n");
return false;
}
- }
- return true;
-}
-
-bool
-ClangUserExpression::FinalizeJITExecution (Stream &error_stream,
- ExecutionContext &exe_ctx,
- lldb::ExpressionVariableSP &result,
- lldb::addr_t function_stack_bottom,
- lldb::addr_t function_stack_top)
-{
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
- if (log)
- log->Printf("-- [ClangUserExpression::FinalizeJITExecution] Dematerializing after execution --");
- if (!m_dematerializer_sp)
- {
- error_stream.Printf ("Couldn't apply expression side effects : no dematerializer is present");
- return false;
- }
-
- Error dematerialize_error;
-
- m_dematerializer_sp->Dematerialize(dematerialize_error, result, function_stack_bottom, function_stack_top);
-
- if (!dematerialize_error.Success())
- {
- error_stream.Printf ("Couldn't apply expression side effects : %s\n", dematerialize_error.AsCString("unknown error"));
- return false;
- }
-
- if (result)
- result->TransferAddress();
-
- m_dematerializer_sp.reset();
-
- return true;
-}
-
-lldb::ExpressionResults
-ClangUserExpression::Execute (Stream &error_stream,
- ExecutionContext &exe_ctx,
- const EvaluateExpressionOptions& options,
- lldb::ClangUserExpressionSP &shared_ptr_to_me,
- lldb::ExpressionVariableSP &result)
-{
- // The expression log is quite verbose, and if you're just tracking the execution of the
- // expression, it's quite convenient to have these logs come out with the STEP log as well.
- Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
-
- if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret)
- {
- lldb::addr_t struct_address = LLDB_INVALID_ADDRESS;
+ Error object_ptr_error;
- lldb::addr_t object_ptr = 0;
- lldb::addr_t cmd_ptr = 0;
+ object_ptr = GetObjectPointer(frame_sp, object_name, object_ptr_error);
- if (!PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr))
+ if (!object_ptr_error.Success())
{
- error_stream.Printf("Errored out in %s, couldn't PrepareToExecuteJITExpression", __FUNCTION__);
- return lldb::eExpressionSetupError;
+ error_stream.Printf("warning: couldn't get required object pointer (substituting NULL): %s\n", object_ptr_error.AsCString());
+ object_ptr = 0;
}
- lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS;
- lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS;
-
- if (m_can_interpret)
+ if (m_in_objectivec_method)
{
- llvm::Module *module = m_execution_unit_sp->GetModule();
- llvm::Function *function = m_execution_unit_sp->GetFunction();
-
- if (!module || !function)
- {
- error_stream.Printf("Supposed to interpret, but nothing is there");
- return lldb::eExpressionSetupError;
- }
-
- Error interpreter_error;
-
- llvm::SmallVector <lldb::addr_t, 3> args;
-
- if (m_needs_object_ptr)
- {
- args.push_back(object_ptr);
+ ConstString cmd_name("_cmd");
- if (m_in_objectivec_method)
- args.push_back(cmd_ptr);
- }
-
- args.push_back(struct_address);
-
- function_stack_bottom = m_stack_frame_bottom;
- function_stack_top = m_stack_frame_top;
-
- IRInterpreter::Interpret (*module,
- *function,
- args,
- *m_execution_unit_sp.get(),
- interpreter_error,
- function_stack_bottom,
- function_stack_top,
- exe_ctx);
+ cmd_ptr = GetObjectPointer(frame_sp, cmd_name, object_ptr_error);
- if (!interpreter_error.Success())
+ if (!object_ptr_error.Success())
{
- error_stream.Printf("Supposed to interpret, but failed: %s", interpreter_error.AsCString());
- return lldb::eExpressionDiscarded;
+ error_stream.Printf("warning: couldn't get cmd pointer (substituting NULL): %s\n", object_ptr_error.AsCString());
+ cmd_ptr = 0;
}
}
- else
- {
- if (!exe_ctx.HasThreadScope())
- {
- error_stream.Printf("ClangUserExpression::Execute called with no thread selected.");
- return lldb::eExpressionSetupError;
- }
-
- Address wrapper_address (m_jit_start_addr);
-
- llvm::SmallVector <lldb::addr_t, 3> args;
-
- if (m_needs_object_ptr) {
- args.push_back(object_ptr);
- if (m_in_objectivec_method)
- args.push_back(cmd_ptr);
- }
-
- args.push_back(struct_address);
-
- lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(),
- wrapper_address,
- args,
- options,
- shared_ptr_to_me));
-
- if (!call_plan_sp || !call_plan_sp->ValidatePlan (&error_stream))
- return lldb::eExpressionSetupError;
-
- ThreadPlanCallUserExpression *user_expression_plan = static_cast<ThreadPlanCallUserExpression *>(call_plan_sp.get());
-
- lldb::addr_t function_stack_pointer = user_expression_plan->GetFunctionStackPointer();
-
- function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize();
- function_stack_top = function_stack_pointer;
-
- if (log)
- log->Printf("-- [ClangUserExpression::Execute] Execution of expression begins --");
-
- if (exe_ctx.GetProcessPtr())
- exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
-
- lldb::ExpressionResults execution_result = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx,
- call_plan_sp,
- options,
- error_stream);
-
- if (exe_ctx.GetProcessPtr())
- exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
-
- if (log)
- log->Printf("-- [ClangUserExpression::Execute] Execution of expression completed --");
+ if (object_ptr)
+ args.push_back(object_ptr);
- if (execution_result == lldb::eExpressionInterrupted || execution_result == lldb::eExpressionHitBreakpoint)
- {
- const char *error_desc = NULL;
-
- if (call_plan_sp)
- {
- lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo();
- if (real_stop_info_sp)
- error_desc = real_stop_info_sp->GetDescription();
- }
- if (error_desc)
- error_stream.Printf ("Execution was interrupted, reason: %s.", error_desc);
- else
- error_stream.PutCString ("Execution was interrupted.");
-
- if ((execution_result == lldb::eExpressionInterrupted && options.DoesUnwindOnError())
- || (execution_result == lldb::eExpressionHitBreakpoint && options.DoesIgnoreBreakpoints()))
- error_stream.PutCString ("\nThe process has been returned to the state before expression evaluation.");
- else
- {
- if (execution_result == lldb::eExpressionHitBreakpoint)
- user_expression_plan->TransferExpressionOwnership();
- error_stream.PutCString ("\nThe process has been left at the point where it was interrupted, "
- "use \"thread return -x\" to return to the state before expression evaluation.");
- }
+ if (m_in_objectivec_method)
+ args.push_back(cmd_ptr);
- return execution_result;
- }
- else if (execution_result == lldb::eExpressionStoppedForDebug)
- {
- error_stream.PutCString ("Execution was halted at the first instruction of the expression "
- "function because \"debug\" was requested.\n"
- "Use \"thread return -x\" to return to the state before expression evaluation.");
- return execution_result;
- }
- else if (execution_result != lldb::eExpressionCompleted)
- {
- error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result));
- return execution_result;
- }
- }
- if (FinalizeJITExecution (error_stream, exe_ctx, result, function_stack_bottom, function_stack_top))
- {
- return lldb::eExpressionCompleted;
- }
- else
- {
- return lldb::eExpressionResultUnavailable;
- }
- }
- else
- {
- error_stream.Printf("Expression can't be run, because there is no JIT compiled function");
- return lldb::eExpressionSetupError;
}
+ return true;
}
-lldb::ExpressionResults
-ClangUserExpression::Evaluate (ExecutionContext &exe_ctx,
- const EvaluateExpressionOptions& options,
- const char *expr_cstr,
- const char *expr_prefix,
- lldb::ValueObjectSP &result_valobj_sp,
- Error &error)
+void
+ClangUserExpression::ClangUserExpressionHelper::ResetDeclMap(ExecutionContext &exe_ctx, bool keep_result_in_memory)
{
- Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
-
- lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
- const lldb::LanguageType language = options.GetLanguage();
- const ResultType desired_type = options.DoesCoerceToId() ? ClangUserExpression::eResultTypeId : ClangUserExpression::eResultTypeAny;
- lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;
-
- Process *process = exe_ctx.GetProcessPtr();
-
- if (process == NULL || process->GetState() != lldb::eStateStopped)
- {
- if (execution_policy == eExecutionPolicyAlways)
- {
- if (log)
- log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant ==");
-
- error.SetErrorString ("expression needed to run but couldn't");
-
- return execution_results;
- }
- }
-
- if (process == NULL || !process->CanJIT())
- execution_policy = eExecutionPolicyNever;
-
- const char *full_prefix = NULL;
- const char *option_prefix = options.GetPrefix();
- std::string full_prefix_storage;
- if (expr_prefix && option_prefix)
- {
- full_prefix_storage.assign(expr_prefix);
- full_prefix_storage.append(option_prefix);
- if (!full_prefix_storage.empty())
- full_prefix = full_prefix_storage.c_str();
- }
- else if (expr_prefix)
- full_prefix = expr_prefix;
- else
- full_prefix = option_prefix;
-
- lldb::ClangUserExpressionSP user_expression_sp (new ClangUserExpression (expr_cstr, full_prefix, language, desired_type));
-
- StreamString error_stream;
-
- if (log)
- log->Printf("== [ClangUserExpression::Evaluate] Parsing expression %s ==", expr_cstr);
-
- const bool keep_expression_in_memory = true;
- const bool generate_debug_info = options.GetGenerateDebugInfo();
-
- if (options.InvokeCancelCallback (lldb::eExpressionEvaluationParse))
- {
- error.SetErrorString ("expression interrupted by callback before parse");
- result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
- return lldb::eExpressionInterrupted;
- }
-
- if (!user_expression_sp->Parse (error_stream,
- exe_ctx,
- execution_policy,
- keep_expression_in_memory,
- generate_debug_info))
- {
- execution_results = lldb::eExpressionParseError;
- if (error_stream.GetString().empty())
- error.SetExpressionError (execution_results, "expression failed to parse, unknown error");
- else
- error.SetExpressionError (execution_results, error_stream.GetString().c_str());
- }
- else
- {
- lldb::ExpressionVariableSP expr_result;
-
- if (execution_policy == eExecutionPolicyNever &&
- !user_expression_sp->CanInterpret())
- {
- if (log)
- log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant ==");
-
- if (error_stream.GetString().empty())
- error.SetExpressionError (lldb::eExpressionSetupError, "expression needed to run but couldn't");
- }
- else
- {
- if (options.InvokeCancelCallback (lldb::eExpressionEvaluationExecution))
- {
- error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback before execution");
- result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
- return lldb::eExpressionInterrupted;
- }
-
- error_stream.GetString().clear();
-
- if (log)
- log->Printf("== [ClangUserExpression::Evaluate] Executing expression ==");
-
- execution_results = user_expression_sp->Execute (error_stream,
- exe_ctx,
- options,
- user_expression_sp,
- expr_result);
-
- if (options.GetResultIsInternal() && expr_result && process)
- {
- process->GetTarget().GetPersistentVariables().RemovePersistentVariable (expr_result);
- }
-
- if (execution_results != lldb::eExpressionCompleted)
- {
- if (log)
- log->Printf("== [ClangUserExpression::Evaluate] Execution completed abnormally ==");
-
- if (error_stream.GetString().empty())
- error.SetExpressionError (execution_results, "expression failed to execute, unknown error");
- else
- error.SetExpressionError (execution_results, error_stream.GetString().c_str());
- }
- else
- {
- if (expr_result)
- {
- result_valobj_sp = expr_result->GetValueObject();
-
- if (log)
- log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with result %s ==",
- result_valobj_sp->GetValueAsCString());
- }
- else
- {
- if (log)
- log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with no result ==");
-
- error.SetError(ClangUserExpression::kNoResult, lldb::eErrorTypeGeneric);
- }
- }
- }
- }
-
- if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete))
- {
- error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback after complete");
- return lldb::eExpressionInterrupted;
- }
+ m_expr_decl_map_up.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx));
+}
- if (result_valobj_sp.get() == NULL)
- {
- result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
- }
+clang::ASTConsumer *
+ClangUserExpression::ClangUserExpressionHelper::ASTTransformer (clang::ASTConsumer *passthrough)
+{
+ m_result_synthesizer_up.reset(new ASTResultSynthesizer(passthrough,
+ m_target));
- return execution_results;
+ return m_result_synthesizer_up.get();
}
+
diff --git a/lldb/source/Expression/ClangUtilityFunction.cpp b/lldb/source/Expression/ClangUtilityFunction.cpp
index de5b0c1b03f..2a07a428803 100644
--- a/lldb/source/Expression/ClangUtilityFunction.cpp
+++ b/lldb/source/Expression/ClangUtilityFunction.cpp
@@ -40,29 +40,15 @@ using namespace lldb_private;
/// @param[in] name
/// The name of the function, as used in the text.
//------------------------------------------------------------------
-ClangUtilityFunction::ClangUtilityFunction (const char *text,
+ClangUtilityFunction::ClangUtilityFunction (ExecutionContextScope &exe_scope,
+ const char *text,
const char *name) :
- ClangExpression (),
- m_expr_decl_map (),
- m_execution_unit_sp (),
- m_jit_module_wp (),
- m_function_text (ExpressionSourceCode::g_expression_prefix),
- m_function_name (name)
+ UtilityFunction (exe_scope, text, name)
{
- if (text && text[0])
- m_function_text.append (text);
}
ClangUtilityFunction::~ClangUtilityFunction ()
{
- lldb::ProcessSP process_sp (m_jit_process_wp.lock());
- if (process_sp)
- {
- lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock());
- if (jit_module_sp)
- process_sp->GetTarget().GetImages().Remove(jit_module_sp);
- }
-
}
//------------------------------------------------------------------
@@ -113,9 +99,9 @@ ClangUtilityFunction::Install (Stream &error_stream,
bool keep_result_in_memory = false;
- m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx));
+ ResetDeclMap(exe_ctx, keep_result_in_memory);
- if (!m_expr_decl_map->WillParse(exe_ctx, NULL))
+ if (!DeclMap()->WillParse(exe_ctx, NULL))
{
error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n");
return false;
@@ -130,7 +116,7 @@ ClangUtilityFunction::Install (Stream &error_stream,
{
error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
- m_expr_decl_map.reset();
+ ResetDeclMap();
return false;
}
@@ -176,9 +162,9 @@ ClangUtilityFunction::Install (Stream &error_stream,
m_function_text.c_str());
#endif
- m_expr_decl_map->DidParse();
+ DeclMap()->DidParse();
- m_expr_decl_map.reset();
+ ResetDeclMap();
if (jit_error.Success())
{
@@ -195,4 +181,8 @@ ClangUtilityFunction::Install (Stream &error_stream,
}
}
-
+void
+ClangUtilityFunction::ClangUtilityFunctionHelper::ResetDeclMap(ExecutionContext &exe_ctx, bool keep_result_in_memory)
+{
+ m_expr_decl_map_up.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx));
+}
diff --git a/lldb/source/Expression/Expression.cpp b/lldb/source/Expression/Expression.cpp
new file mode 100644
index 00000000000..e5dd9c03db7
--- /dev/null
+++ b/lldb/source/Expression/Expression.cpp
@@ -0,0 +1,32 @@
+//===-- Expression.h ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Expression/Expression.h"
+#include "lldb/Target/ExecutionContextScope.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb_private;
+
+Expression::Expression (Target &target) :
+ m_target_wp (target.shared_from_this()),
+ m_jit_start_addr (LLDB_INVALID_ADDRESS),
+ m_jit_end_addr (LLDB_INVALID_ADDRESS)
+{
+ // Can't make any kind of expression without a target.
+ assert (m_target_wp.lock());
+}
+
+Expression::Expression (ExecutionContextScope &exe_scope) :
+ m_target_wp (exe_scope.CalculateTarget()),
+ m_jit_start_addr (LLDB_INVALID_ADDRESS),
+ m_jit_end_addr (LLDB_INVALID_ADDRESS)
+{
+ assert (m_target_wp.lock());
+}
+
diff --git a/lldb/source/Expression/ClangFunction.cpp b/lldb/source/Expression/FunctionCaller.cpp
index 3798c212059..acfc71c146e 100644
--- a/lldb/source/Expression/ClangFunction.cpp
+++ b/lldb/source/Expression/FunctionCaller.cpp
@@ -1,4 +1,4 @@
-//===-- ClangFunction.cpp ---------------------------------------*- C++ -*-===//
+//===-- FunctionCaller.cpp ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -30,7 +30,7 @@
#include "lldb/Core/ValueObjectList.h"
#include "lldb/Expression/ASTStructExtractor.h"
#include "lldb/Expression/ClangExpressionParser.h"
-#include "lldb/Expression/ClangFunction.h"
+#include "lldb/Expression/FunctionCaller.h"
#include "lldb/Expression/IRExecutionUnit.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Symbol/ClangASTContext.h"
@@ -47,9 +47,9 @@
using namespace lldb_private;
//----------------------------------------------------------------------
-// ClangFunction constructor
+// FunctionCaller constructor
//----------------------------------------------------------------------
-ClangFunction::ClangFunction
+FunctionCaller::FunctionCaller
(
ExecutionContextScope &exe_scope,
const CompilerType &return_type,
@@ -57,6 +57,7 @@ ClangFunction::ClangFunction
const ValueList &arg_value_list,
const char *name
) :
+ Expression (exe_scope),
m_execution_unit_sp(),
m_parser(),
m_jit_module_wp(),
@@ -72,41 +73,14 @@ ClangFunction::ClangFunction
m_JITted (false)
{
m_jit_process_wp = lldb::ProcessWP(exe_scope.CalculateProcess());
- // Can't make a ClangFunction without a process.
+ // Can't make a FunctionCaller without a process.
assert (m_jit_process_wp.lock());
}
-ClangFunction::ClangFunction
-(
- ExecutionContextScope &exe_scope,
- Function &function,
- ClangASTContext *ast_context,
- const ValueList &arg_value_list,
- const char *name
-) :
- m_name (name ? name : "<unknown>"),
- m_function_ptr (&function),
- m_function_addr (),
- m_function_return_type (),
- m_wrapper_function_name ("__lldb_function_caller"),
- m_wrapper_struct_name ("__lldb_caller_struct"),
- m_wrapper_args_addrs (),
- m_arg_values (arg_value_list),
- m_compiled (false),
- m_JITted (false)
-{
- m_jit_process_wp = exe_scope.CalculateProcess();
- // Can't make a ClangFunction without a process.
- assert (m_jit_process_wp.lock());
-
- m_function_addr = m_function_ptr->GetAddressRange().GetBaseAddress();
- m_function_return_type = m_function_ptr->GetCompilerType().GetFunctionReturnType();
-}
-
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
-ClangFunction::~ClangFunction()
+FunctionCaller::~FunctionCaller()
{
lldb::ProcessSP process_sp (m_jit_process_wp.lock());
if (process_sp)
@@ -117,147 +91,8 @@ ClangFunction::~ClangFunction()
}
}
-unsigned
-ClangFunction::CompileFunction (Stream &errors)
-{
- if (m_compiled)
- return 0;
-
- // FIXME: How does clang tell us there's no return value? We need to handle that case.
- unsigned num_errors = 0;
-
- std::string return_type_str (m_function_return_type.GetTypeName().AsCString(""));
-
- // Cons up the function we're going to wrap our call in, then compile it...
- // We declare the function "extern "C"" because the compiler might be in C++
- // mode which would mangle the name and then we couldn't find it again...
- m_wrapper_function_text.clear();
- m_wrapper_function_text.append ("extern \"C\" void ");
- m_wrapper_function_text.append (m_wrapper_function_name);
- m_wrapper_function_text.append (" (void *input)\n{\n struct ");
- m_wrapper_function_text.append (m_wrapper_struct_name);
- m_wrapper_function_text.append (" \n {\n");
- m_wrapper_function_text.append (" ");
- m_wrapper_function_text.append (return_type_str);
- m_wrapper_function_text.append (" (*fn_ptr) (");
-
- // Get the number of arguments. If we have a function type and it is prototyped,
- // trust that, otherwise use the values we were given.
-
- // FIXME: This will need to be extended to handle Variadic functions. We'll need
- // to pull the defined arguments out of the function, then add the types from the
- // arguments list for the variable arguments.
-
- uint32_t num_args = UINT32_MAX;
- bool trust_function = false;
- // GetArgumentCount returns -1 for an unprototyped function.
- CompilerType function_clang_type;
- if (m_function_ptr)
- {
- function_clang_type = m_function_ptr->GetCompilerType();
- if (function_clang_type)
- {
- int num_func_args = function_clang_type.GetFunctionArgumentCount();
- if (num_func_args >= 0)
- {
- trust_function = true;
- num_args = num_func_args;
- }
- }
- }
-
- if (num_args == UINT32_MAX)
- num_args = m_arg_values.GetSize();
-
- std::string args_buffer; // This one stores the definition of all the args in "struct caller".
- std::string args_list_buffer; // This one stores the argument list called from the structure.
- for (size_t i = 0; i < num_args; i++)
- {
- std::string type_name;
-
- if (trust_function)
- {
- type_name = function_clang_type.GetFunctionArgumentTypeAtIndex(i).GetTypeName().AsCString("");
- }
- else
- {
- CompilerType clang_qual_type = m_arg_values.GetValueAtIndex(i)->GetCompilerType ();
- if (clang_qual_type)
- {
- type_name = clang_qual_type.GetTypeName().AsCString("");
- }
- else
- {
- errors.Printf("Could not determine type of input value %" PRIu64 ".", (uint64_t)i);
- return 1;
- }
- }
-
- m_wrapper_function_text.append (type_name);
- if (i < num_args - 1)
- m_wrapper_function_text.append (", ");
-
- char arg_buf[32];
- args_buffer.append (" ");
- args_buffer.append (type_name);
- snprintf(arg_buf, 31, "arg_%" PRIu64, (uint64_t)i);
- args_buffer.push_back (' ');
- args_buffer.append (arg_buf);
- args_buffer.append (";\n");
-
- args_list_buffer.append ("__lldb_fn_data->");
- args_list_buffer.append (arg_buf);
- if (i < num_args - 1)
- args_list_buffer.append (", ");
-
- }
- m_wrapper_function_text.append (");\n"); // Close off the function calling prototype.
-
- m_wrapper_function_text.append (args_buffer);
-
- m_wrapper_function_text.append (" ");
- m_wrapper_function_text.append (return_type_str);
- m_wrapper_function_text.append (" return_value;");
- m_wrapper_function_text.append ("\n };\n struct ");
- m_wrapper_function_text.append (m_wrapper_struct_name);
- m_wrapper_function_text.append ("* __lldb_fn_data = (struct ");
- m_wrapper_function_text.append (m_wrapper_struct_name);
- m_wrapper_function_text.append (" *) input;\n");
-
- m_wrapper_function_text.append (" __lldb_fn_data->return_value = __lldb_fn_data->fn_ptr (");
- m_wrapper_function_text.append (args_list_buffer);
- m_wrapper_function_text.append (");\n}\n");
-
- Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
- if (log)
- log->Printf ("Expression: \n\n%s\n\n", m_wrapper_function_text.c_str());
-
- // Okay, now compile this expression
-
- lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock());
- if (jit_process_sp)
- {
- const bool generate_debug_info = true;
- m_parser.reset(new ClangExpressionParser(jit_process_sp.get(), *this, generate_debug_info));
-
- num_errors = m_parser->Parse (errors);
- }
- else
- {
- errors.Printf("no process - unable to inject function");
- num_errors = 1;
- }
-
- m_compiled = (num_errors == 0);
-
- if (!m_compiled)
- return num_errors;
-
- return num_errors;
-}
-
bool
-ClangFunction::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors)
+FunctionCaller::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors)
{
Process *process = exe_ctx.GetProcessPtr();
@@ -310,18 +145,17 @@ ClangFunction::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors)
}
bool
-ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Stream &errors)
+FunctionCaller::WriteFunctionArguments (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Stream &errors)
{
- return WriteFunctionArguments(exe_ctx, args_addr_ref, m_function_addr, m_arg_values, errors);
+ return WriteFunctionArguments(exe_ctx, args_addr_ref, m_arg_values, errors);
}
// FIXME: Assure that the ValueList we were passed in is consistent with the one that defined this function.
bool
-ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx,
+FunctionCaller::WriteFunctionArguments (ExecutionContext &exe_ctx,
lldb::addr_t &args_addr_ref,
- Address function_address,
- ValueList &arg_values,
+ ValueList &arg_values,
Stream &errors)
{
// All the information to reconstruct the struct is provided by the
@@ -363,7 +197,7 @@ ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx,
}
// TODO: verify fun_addr needs to be a callable address
- Scalar fun_addr (function_address.GetCallableLoadAddress(exe_ctx.GetTargetPtr()));
+ Scalar fun_addr (m_function_addr.GetCallableLoadAddress(exe_ctx.GetTargetPtr()));
uint64_t first_offset = m_member_offsets[0];
process->WriteScalarToMemory(args_addr_ref + first_offset, fun_addr, process->GetAddressByteSize(), error);
@@ -404,7 +238,7 @@ ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx,
}
bool
-ClangFunction::InsertFunction (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Stream &errors)
+FunctionCaller::InsertFunction (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Stream &errors)
{
using namespace clang;
@@ -423,7 +257,7 @@ ClangFunction::InsertFunction (ExecutionContext &exe_ctx, lldb::addr_t &args_add
}
lldb::ThreadPlanSP
-ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
+FunctionCaller::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
lldb::addr_t args_addr,
const EvaluateExpressionOptions &options,
Stream &errors)
@@ -431,7 +265,7 @@ ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
if (log)
- log->Printf("-- [ClangFunction::GetThreadPlanToCallFunction] Creating thread plan to call function \"%s\" --", m_name.c_str());
+ log->Printf("-- [FunctionCaller::GetThreadPlanToCallFunction] Creating thread plan to call function \"%s\" --", m_name.c_str());
// FIXME: Use the errors Stream for better error reporting.
Thread *thread = exe_ctx.GetThreadPtr();
@@ -458,7 +292,7 @@ ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
}
bool
-ClangFunction::FetchFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr, Value &ret_value)
+FunctionCaller::FetchFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr, Value &ret_value)
{
// Read the return value - it is the last field in the struct:
// FIXME: How does clang tell us there's no return value? We need to handle that case.
@@ -468,7 +302,7 @@ ClangFunction::FetchFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t arg
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
if (log)
- log->Printf("-- [ClangFunction::FetchFunctionResults] Fetching function results for \"%s\"--", m_name.c_str());
+ log->Printf("-- [FunctionCaller::FetchFunctionResults] Fetching function results for \"%s\"--", m_name.c_str());
Process *process = exe_ctx.GetProcessPtr();
@@ -492,7 +326,7 @@ ClangFunction::FetchFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t arg
}
void
-ClangFunction::DeallocateFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr)
+FunctionCaller::DeallocateFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr)
{
std::list<lldb::addr_t>::iterator pos;
pos = std::find(m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(), args_addr);
@@ -503,7 +337,7 @@ ClangFunction::DeallocateFunctionResults (ExecutionContext &exe_ctx, lldb::addr_
}
lldb::ExpressionResults
-ClangFunction::ExecuteFunction(
+FunctionCaller::ExecuteFunction(
ExecutionContext &exe_ctx,
lldb::addr_t *args_addr_ptr,
const EvaluateExpressionOptions &options,
@@ -513,7 +347,7 @@ ClangFunction::ExecuteFunction(
using namespace clang;
lldb::ExpressionResults return_value = lldb::eExpressionSetupError;
- // ClangFunction::ExecuteFunction execution is always just to get the result. Do make sure we ignore
+ // FunctionCaller::ExecuteFunction execution is always just to get the result. Do make sure we ignore
// breakpoints, unwind on error, and don't try to debug it.
EvaluateExpressionOptions real_options = options;
real_options.SetDebug(false);
@@ -539,7 +373,7 @@ ClangFunction::ExecuteFunction(
Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
if (log)
- log->Printf("== [ClangFunction::ExecuteFunction] Executing function \"%s\" ==", m_name.c_str());
+ log->Printf("== [FunctionCaller::ExecuteFunction] Executing function \"%s\" ==", m_name.c_str());
lldb::ThreadPlanSP call_plan_sp = GetThreadPlanToCallFunction (exe_ctx,
args_addr,
@@ -562,11 +396,11 @@ ClangFunction::ExecuteFunction(
{
if (return_value != lldb::eExpressionCompleted)
{
- log->Printf("== [ClangFunction::ExecuteFunction] Execution of \"%s\" completed abnormally ==", m_name.c_str());
+ log->Printf("== [FunctionCaller::ExecuteFunction] Execution of \"%s\" completed abnormally ==", m_name.c_str());
}
else
{
- log->Printf("== [ClangFunction::ExecuteFunction] Execution of \"%s\" completed normally ==", m_name.c_str());
+ log->Printf("== [FunctionCaller::ExecuteFunction] Execution of \"%s\" completed normally ==", m_name.c_str());
}
}
@@ -586,11 +420,3 @@ ClangFunction::ExecuteFunction(
return lldb::eExpressionCompleted;
}
-
-clang::ASTConsumer *
-ClangFunction::ASTTransformer (clang::ASTConsumer *passthrough)
-{
- m_struct_extractor.reset(new ASTStructExtractor(passthrough, m_wrapper_struct_name.c_str(), *this));
-
- return m_struct_extractor.get();
-}
diff --git a/lldb/source/Expression/IRDynamicChecks.cpp b/lldb/source/Expression/IRDynamicChecks.cpp
index aa5d28bb8aa..5c8d0e5288b 100644
--- a/lldb/source/Expression/IRDynamicChecks.cpp
+++ b/lldb/source/Expression/IRDynamicChecks.cpp
@@ -11,11 +11,12 @@
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Log.h"
-#include "lldb/Expression/ClangUtilityFunction.h"
+#include "lldb/Expression/UtilityFunction.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/IR/Constants.h"
@@ -52,8 +53,14 @@ bool
DynamicCheckerFunctions::Install(Stream &error_stream,
ExecutionContext &exe_ctx)
{
- m_valid_pointer_check.reset(new ClangUtilityFunction(g_valid_pointer_check_text,
- VALID_POINTER_CHECK_NAME));
+ Error error;
+ m_valid_pointer_check.reset(exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage(g_valid_pointer_check_text,
+ lldb::eLanguageTypeC,
+ VALID_POINTER_CHECK_NAME,
+ error));
+ if (error.Fail())
+ return false;
+
if (!m_valid_pointer_check->Install(error_stream, exe_ctx))
return false;
diff --git a/lldb/source/Expression/UserExpression.cpp b/lldb/source/Expression/UserExpression.cpp
new file mode 100644
index 00000000000..547c02a1317
--- /dev/null
+++ b/lldb/source/Expression/UserExpression.cpp
@@ -0,0 +1,644 @@
+//===-- UserExpression.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+#include <cstdlib>
+#include <string>
+#include <map>
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Expression/ASTResultSynthesizer.h"
+#include "lldb/Expression/ClangExpressionDeclMap.h"
+#include "lldb/Expression/ClangExpressionParser.h"
+#include "lldb/Expression/ClangModulesDeclVendor.h"
+#include "lldb/Expression/ClangPersistentVariables.h"
+#include "lldb/Expression/ExpressionSourceCode.h"
+#include "lldb/Expression/IRExecutionUnit.h"
+#include "lldb/Expression/IRInterpreter.h"
+#include "lldb/Expression/Materializer.h"
+#include "lldb/Expression/UserExpression.h"
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Symbol/Block.h"
+#include "lldb/Symbol/ClangASTContext.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Symbol/Type.h"
+#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
+#include "lldb/Symbol/VariableList.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/StackFrame.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/ThreadPlan.h"
+#include "lldb/Target/ThreadPlanCallUserExpression.h"
+
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+
+using namespace lldb_private;
+
+UserExpression::UserExpression (ExecutionContextScope &exe_scope,
+ const char *expr,
+ const char *expr_prefix,
+ lldb::LanguageType language,
+ ResultType desired_type) :
+ Expression (exe_scope),
+ m_stack_frame_bottom (LLDB_INVALID_ADDRESS),
+ m_stack_frame_top (LLDB_INVALID_ADDRESS),
+ m_expr_text (expr),
+ m_expr_prefix (expr_prefix ? expr_prefix : ""),
+ m_language (language),
+ m_transformed_text (),
+ m_desired_type (desired_type),
+ m_execution_unit_sp(),
+ m_materializer_ap(),
+ m_jit_module_wp(),
+ m_enforce_valid_object (true),
+ m_in_cplusplus_method (false),
+ m_in_objectivec_method (false),
+ m_in_static_method(false),
+ m_needs_object_ptr (false),
+ m_const_object (false),
+ m_target (NULL),
+ m_can_interpret (false),
+ m_materialized_address (LLDB_INVALID_ADDRESS)
+{
+}
+
+UserExpression::~UserExpression ()
+{
+ if (m_target)
+ {
+ lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock());
+ if (jit_module_sp)
+ m_target->GetImages().Remove(jit_module_sp);
+ }
+}
+
+void
+UserExpression::InstallContext (ExecutionContext &exe_ctx)
+{
+ m_jit_process_wp = exe_ctx.GetProcessSP();
+
+ lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP();
+
+ if (frame_sp)
+ m_address = frame_sp->GetFrameCodeAddress();
+}
+
+bool
+UserExpression::LockAndCheckContext (ExecutionContext &exe_ctx,
+ lldb::TargetSP &target_sp,
+ lldb::ProcessSP &process_sp,
+ lldb::StackFrameSP &frame_sp)
+{
+ lldb::ProcessSP expected_process_sp = m_jit_process_wp.lock();
+ process_sp = exe_ctx.GetProcessSP();
+
+ if (process_sp != expected_process_sp)
+ return false;
+
+ process_sp = exe_ctx.GetProcessSP();
+ target_sp = exe_ctx.GetTargetSP();
+ frame_sp = exe_ctx.GetFrameSP();
+
+ if (m_address.IsValid())
+ {
+ if (!frame_sp)
+ return false;
+ else
+ return (0 == Address::CompareLoadAddress(m_address, frame_sp->GetFrameCodeAddress(), target_sp.get()));
+ }
+
+ return true;
+}
+
+bool
+UserExpression::MatchesContext (ExecutionContext &exe_ctx)
+{
+ lldb::TargetSP target_sp;
+ lldb::ProcessSP process_sp;
+ lldb::StackFrameSP frame_sp;
+
+ return LockAndCheckContext(exe_ctx, target_sp, process_sp, frame_sp);
+}
+
+lldb::addr_t
+UserExpression::GetObjectPointer (lldb::StackFrameSP frame_sp,
+ ConstString &object_name,
+ Error &err)
+{
+ err.Clear();
+
+ if (!frame_sp)
+ {
+ err.SetErrorStringWithFormat("Couldn't load '%s' because the context is incomplete", object_name.AsCString());
+ return LLDB_INVALID_ADDRESS;
+ }
+
+ lldb::VariableSP var_sp;
+ lldb::ValueObjectSP valobj_sp;
+
+ valobj_sp = frame_sp->GetValueForVariableExpressionPath(object_name.AsCString(),
+ lldb::eNoDynamicValues,
+ StackFrame::eExpressionPathOptionCheckPtrVsMember |
+ StackFrame::eExpressionPathOptionsNoFragileObjcIvar |
+ StackFrame::eExpressionPathOptionsNoSyntheticChildren |
+ StackFrame::eExpressionPathOptionsNoSyntheticArrayRange,
+ var_sp,
+ err);
+
+ if (!err.Success() || !valobj_sp.get())
+ return LLDB_INVALID_ADDRESS;
+
+ lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
+
+ if (ret == LLDB_INVALID_ADDRESS)
+ {
+ err.SetErrorStringWithFormat("Couldn't load '%s' because its value couldn't be evaluated", object_name.AsCString());
+ return LLDB_INVALID_ADDRESS;
+ }
+
+ return ret;
+}
+
+bool
+UserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
+ ExecutionContext &exe_ctx,
+ lldb::addr_t &struct_address)
+{
+ lldb::TargetSP target;
+ lldb::ProcessSP process;
+ lldb::StackFrameSP frame;
+
+ if (!LockAndCheckContext(exe_ctx,
+ target,
+ process,
+ frame))
+ {
+ error_stream.Printf("The context has changed before we could JIT the expression!\n");
+ return false;
+ }
+
+ if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret)
+ {
+ if (m_materialized_address == LLDB_INVALID_ADDRESS)
+ {
+ Error alloc_error;
+
+ IRMemoryMap::AllocationPolicy policy = m_can_interpret ? IRMemoryMap::eAllocationPolicyHostOnly : IRMemoryMap::eAllocationPolicyMirror;
+
+ m_materialized_address = m_execution_unit_sp->Malloc(m_materializer_ap->GetStructByteSize(),
+ m_materializer_ap->GetStructAlignment(),
+ lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+ policy,
+ alloc_error);
+
+ if (!alloc_error.Success())
+ {
+ error_stream.Printf("Couldn't allocate space for materialized struct: %s\n", alloc_error.AsCString());
+ return false;
+ }
+ }
+
+ struct_address = m_materialized_address;
+
+ if (m_can_interpret && m_stack_frame_bottom == LLDB_INVALID_ADDRESS)
+ {
+ Error alloc_error;
+
+ const size_t stack_frame_size = 512 * 1024;
+
+ m_stack_frame_bottom = m_execution_unit_sp->Malloc(stack_frame_size,
+ 8,
+ lldb::ePermissionsReadable | lldb::ePermissionsWritable,
+ IRMemoryMap::eAllocationPolicyHostOnly,
+ alloc_error);
+
+ m_stack_frame_top = m_stack_frame_bottom + stack_frame_size;
+
+ if (!alloc_error.Success())
+ {
+ error_stream.Printf("Couldn't allocate space for the stack frame: %s\n", alloc_error.AsCString());
+ return false;
+ }
+ }
+
+ Error materialize_error;
+
+ m_dematerializer_sp = m_materializer_ap->Materialize(frame, *m_execution_unit_sp, struct_address, materialize_error);
+
+ if (!materialize_error.Success())
+ {
+ error_stream.Printf("Couldn't materialize: %s\n", materialize_error.AsCString());
+ return false;
+ }
+ }
+ return true;
+}
+
+bool
+UserExpression::FinalizeJITExecution (Stream &error_stream,
+ ExecutionContext &exe_ctx,
+ lldb::ExpressionVariableSP &result,
+ lldb::addr_t function_stack_bottom,
+ lldb::addr_t function_stack_top)
+{
+ Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (log)
+ log->Printf("-- [UserExpression::FinalizeJITExecution] Dematerializing after execution --");
+
+ if (!m_dematerializer_sp)
+ {
+ error_stream.Printf ("Couldn't apply expression side effects : no dematerializer is present");
+ return false;
+ }
+
+ Error dematerialize_error;
+
+ m_dematerializer_sp->Dematerialize(dematerialize_error, result, function_stack_bottom, function_stack_top);
+
+ if (!dematerialize_error.Success())
+ {
+ error_stream.Printf ("Couldn't apply expression side effects : %s\n", dematerialize_error.AsCString("unknown error"));
+ return false;
+ }
+
+ if (result)
+ result->TransferAddress();
+
+ m_dematerializer_sp.reset();
+
+ return true;
+}
+
+lldb::ExpressionResults
+UserExpression::Execute (Stream &error_stream,
+ ExecutionContext &exe_ctx,
+ const EvaluateExpressionOptions& options,
+ lldb::UserExpressionSP &shared_ptr_to_me,
+ lldb::ExpressionVariableSP &result)
+{
+ // The expression log is quite verbose, and if you're just tracking the execution of the
+ // expression, it's quite convenient to have these logs come out with the STEP log as well.
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
+
+ if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret)
+ {
+ lldb::addr_t struct_address = LLDB_INVALID_ADDRESS;
+
+ if (!PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address))
+ {
+ error_stream.Printf("Errored out in %s, couldn't PrepareToExecuteJITExpression", __FUNCTION__);
+ return lldb::eExpressionSetupError;
+ }
+
+ lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS;
+ lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS;
+
+ if (m_can_interpret)
+ {
+ llvm::Module *module = m_execution_unit_sp->GetModule();
+ llvm::Function *function = m_execution_unit_sp->GetFunction();
+
+ if (!module || !function)
+ {
+ error_stream.Printf("Supposed to interpret, but nothing is there");
+ return lldb::eExpressionSetupError;
+ }
+
+ Error interpreter_error;
+
+ std::vector<lldb::addr_t> args;
+
+ if (!AddInitialArguments(exe_ctx, args, error_stream))
+ {
+ error_stream.Printf ("Errored out in %s, couldn't AddInitialArguments", __FUNCTION__);
+ return lldb::eExpressionSetupError;
+ }
+
+ args.push_back(struct_address);
+
+ function_stack_bottom = m_stack_frame_bottom;
+ function_stack_top = m_stack_frame_top;
+
+ IRInterpreter::Interpret (*module,
+ *function,
+ args,
+ *m_execution_unit_sp.get(),
+ interpreter_error,
+ function_stack_bottom,
+ function_stack_top,
+ exe_ctx);
+
+ if (!interpreter_error.Success())
+ {
+ error_stream.Printf("Supposed to interpret, but failed: %s", interpreter_error.AsCString());
+ return lldb::eExpressionDiscarded;
+ }
+ }
+ else
+ {
+ if (!exe_ctx.HasThreadScope())
+ {
+ error_stream.Printf("UserExpression::Execute called with no thread selected.");
+ return lldb::eExpressionSetupError;
+ }
+
+ Address wrapper_address (m_jit_start_addr);
+
+ std::vector<lldb::addr_t> args;
+
+ if (!AddInitialArguments(exe_ctx, args, error_stream))
+ {
+ error_stream.Printf ("Errored out in %s, couldn't AddInitialArguments", __FUNCTION__);
+ return lldb::eExpressionSetupError;
+ }
+
+ args.push_back(struct_address);
+
+ lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (exe_ctx.GetThreadRef(),
+ wrapper_address,
+ args,
+ options,
+ shared_ptr_to_me));
+
+ if (!call_plan_sp || !call_plan_sp->ValidatePlan (&error_stream))
+ return lldb::eExpressionSetupError;
+
+ ThreadPlanCallUserExpression *user_expression_plan = static_cast<ThreadPlanCallUserExpression *>(call_plan_sp.get());
+
+ lldb::addr_t function_stack_pointer = user_expression_plan->GetFunctionStackPointer();
+
+ function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize();
+ function_stack_top = function_stack_pointer;
+
+ if (log)
+ log->Printf("-- [UserExpression::Execute] Execution of expression begins --");
+
+ if (exe_ctx.GetProcessPtr())
+ exe_ctx.GetProcessPtr()->SetRunningUserExpression(true);
+
+ lldb::ExpressionResults execution_result = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx,
+ call_plan_sp,
+ options,
+ error_stream);
+
+ if (exe_ctx.GetProcessPtr())
+ exe_ctx.GetProcessPtr()->SetRunningUserExpression(false);
+
+ if (log)
+ log->Printf("-- [UserExpression::Execute] Execution of expression completed --");
+
+ if (execution_result == lldb::eExpressionInterrupted || execution_result == lldb::eExpressionHitBreakpoint)
+ {
+ const char *error_desc = NULL;
+
+ if (call_plan_sp)
+ {
+ lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo();
+ if (real_stop_info_sp)
+ error_desc = real_stop_info_sp->GetDescription();
+ }
+ if (error_desc)
+ error_stream.Printf ("Execution was interrupted, reason: %s.", error_desc);
+ else
+ error_stream.PutCString ("Execution was interrupted.");
+
+ if ((execution_result == lldb::eExpressionInterrupted && options.DoesUnwindOnError())
+ || (execution_result == lldb::eExpressionHitBreakpoint && options.DoesIgnoreBreakpoints()))
+ error_stream.PutCString ("\nThe process has been returned to the state before expression evaluation.");
+ else
+ {
+ if (execution_result == lldb::eExpressionHitBreakpoint)
+ user_expression_plan->TransferExpressionOwnership();
+ error_stream.PutCString ("\nThe process has been left at the point where it was interrupted, "
+ "use \"thread return -x\" to return to the state before expression evaluation.");
+ }
+
+ return execution_result;
+ }
+ else if (execution_result == lldb::eExpressionStoppedForDebug)
+ {
+ error_stream.PutCString ("Execution was halted at the first instruction of the expression "
+ "function because \"debug\" was requested.\n"
+ "Use \"thread return -x\" to return to the state before expression evaluation.");
+ return execution_result;
+ }
+ else if (execution_result != lldb::eExpressionCompleted)
+ {
+ error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result));
+ return execution_result;
+ }
+ }
+
+ if (FinalizeJITExecution (error_stream, exe_ctx, result, function_stack_bottom, function_stack_top))
+ {
+ return lldb::eExpressionCompleted;
+ }
+ else
+ {
+ return lldb::eExpressionResultUnavailable;
+ }
+ }
+ else
+ {
+ error_stream.Printf("Expression can't be run, because there is no JIT compiled function");
+ return lldb::eExpressionSetupError;
+ }
+}
+
+lldb::ExpressionResults
+UserExpression::Evaluate (ExecutionContext &exe_ctx,
+ const EvaluateExpressionOptions& options,
+ const char *expr_cstr,
+ const char *expr_prefix,
+ lldb::ValueObjectSP &result_valobj_sp,
+ Error &error)
+{
+ Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP));
+
+ lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
+ const lldb::LanguageType language = options.GetLanguage();
+ const ResultType desired_type = options.DoesCoerceToId() ? UserExpression::eResultTypeId : UserExpression::eResultTypeAny;
+ lldb::ExpressionResults execution_results = lldb::eExpressionSetupError;
+
+ Target *target = exe_ctx.GetTargetPtr();
+ if (!target)
+ {
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Passed a NULL target, can't run expressions.");
+ return lldb::eExpressionSetupError;
+ }
+
+ Process *process = exe_ctx.GetProcessPtr();
+
+ if (process == NULL || process->GetState() != lldb::eStateStopped)
+ {
+ if (execution_policy == eExecutionPolicyAlways)
+ {
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant ==");
+
+ error.SetErrorString ("expression needed to run but couldn't");
+
+ return execution_results;
+ }
+ }
+
+ if (process == NULL || !process->CanJIT())
+ execution_policy = eExecutionPolicyNever;
+
+ const char *full_prefix = NULL;
+ const char *option_prefix = options.GetPrefix();
+ std::string full_prefix_storage;
+ if (expr_prefix && option_prefix)
+ {
+ full_prefix_storage.assign(expr_prefix);
+ full_prefix_storage.append(option_prefix);
+ if (!full_prefix_storage.empty())
+ full_prefix = full_prefix_storage.c_str();
+ }
+ else if (expr_prefix)
+ full_prefix = expr_prefix;
+ else
+ full_prefix = option_prefix;
+
+ lldb::UserExpressionSP user_expression_sp(target->GetUserExpressionForLanguage (expr_cstr,
+ full_prefix,
+ language,
+ desired_type,
+ error));
+ if (error.Fail())
+ {
+ if (log)
+ log->Printf ("== [UserExpression::Evaluate] Getting expression: %s ==", error.AsCString());
+ return lldb::eExpressionSetupError;
+ }
+
+ StreamString error_stream;
+
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Parsing expression %s ==", expr_cstr);
+
+ const bool keep_expression_in_memory = true;
+ const bool generate_debug_info = options.GetGenerateDebugInfo();
+
+ if (options.InvokeCancelCallback (lldb::eExpressionEvaluationParse))
+ {
+ error.SetErrorString ("expression interrupted by callback before parse");
+ result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
+ return lldb::eExpressionInterrupted;
+ }
+
+ if (!user_expression_sp->Parse (error_stream,
+ exe_ctx,
+ execution_policy,
+ keep_expression_in_memory,
+ generate_debug_info))
+ {
+ execution_results = lldb::eExpressionParseError;
+ if (error_stream.GetString().empty())
+ error.SetExpressionError (execution_results, "expression failed to parse, unknown error");
+ else
+ error.SetExpressionError (execution_results, error_stream.GetString().c_str());
+ }
+ else
+ {
+ lldb::ExpressionVariableSP expr_result;
+
+ if (execution_policy == eExecutionPolicyNever &&
+ !user_expression_sp->CanInterpret())
+ {
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant ==");
+
+ if (error_stream.GetString().empty())
+ error.SetExpressionError (lldb::eExpressionSetupError, "expression needed to run but couldn't");
+ }
+ else
+ {
+ if (options.InvokeCancelCallback (lldb::eExpressionEvaluationExecution))
+ {
+ error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback before execution");
+ result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
+ return lldb::eExpressionInterrupted;
+ }
+
+ error_stream.GetString().clear();
+
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Executing expression ==");
+
+ execution_results = user_expression_sp->Execute (error_stream,
+ exe_ctx,
+ options,
+ user_expression_sp,
+ expr_result);
+
+ if (options.GetResultIsInternal() && expr_result && process)
+ {
+ process->GetTarget().GetPersistentVariables().RemovePersistentVariable (expr_result);
+ }
+
+ if (execution_results != lldb::eExpressionCompleted)
+ {
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Execution completed abnormally ==");
+
+ if (error_stream.GetString().empty())
+ error.SetExpressionError (execution_results, "expression failed to execute, unknown error");
+ else
+ error.SetExpressionError (execution_results, error_stream.GetString().c_str());
+ }
+ else
+ {
+ if (expr_result)
+ {
+ result_valobj_sp = expr_result->GetValueObject();
+
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Execution completed normally with result %s ==",
+ result_valobj_sp->GetValueAsCString());
+ }
+ else
+ {
+ if (log)
+ log->Printf("== [UserExpression::Evaluate] Execution completed normally with no result ==");
+
+ error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric);
+ }
+ }
+ }
+ }
+
+ if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete))
+ {
+ error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback after complete");
+ return lldb::eExpressionInterrupted;
+ }
+
+ if (result_valobj_sp.get() == NULL)
+ {
+ result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error);
+ }
+
+ return execution_results;
+}
diff --git a/lldb/source/Expression/UtilityFunction.cpp b/lldb/source/Expression/UtilityFunction.cpp
new file mode 100644
index 00000000000..fad6e2f2568
--- /dev/null
+++ b/lldb/source/Expression/UtilityFunction.cpp
@@ -0,0 +1,123 @@
+//===-- ClangUserExpression.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+// C++ Includes
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Core/StreamFile.h"
+#include "lldb/Expression/FunctionCaller.h"
+#include "lldb/Expression/UtilityFunction.h"
+#include "lldb/Expression/ExpressionSourceCode.h"
+#include "lldb/Expression/IRExecutionUnit.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+//------------------------------------------------------------------
+/// Constructor
+///
+/// @param[in] text
+/// The text of the function. Must be a full translation unit.
+///
+/// @param[in] name
+/// The name of the function, as used in the text.
+//------------------------------------------------------------------
+UtilityFunction::UtilityFunction (ExecutionContextScope &exe_scope,
+ const char *text,
+ const char *name) :
+ Expression (exe_scope),
+ m_execution_unit_sp (),
+ m_jit_module_wp (),
+ m_function_text (ExpressionSourceCode::g_expression_prefix),
+ m_function_name (name)
+{
+ if (text && text[0])
+ m_function_text.append (text);
+}
+
+UtilityFunction::~UtilityFunction ()
+{
+ lldb::ProcessSP process_sp (m_jit_process_wp.lock());
+ if (process_sp)
+ {
+ lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock());
+ if (jit_module_sp)
+ process_sp->GetTarget().GetImages().Remove(jit_module_sp);
+ }
+
+}
+
+// FIXME: We should check that every time this is called it is called with the same return type & arguments...
+
+FunctionCaller *
+UtilityFunction::MakeFunctionCaller (const CompilerType &return_type, const ValueList &arg_value_list, Error &error)
+{
+ if (m_caller_up)
+ return m_caller_up.get();
+
+ ProcessSP process_sp = m_jit_process_wp.lock();
+ if (!process_sp)
+ return nullptr;
+
+ Address impl_code_address;
+ impl_code_address.SetOffset(StartAddress());
+ std::string name(m_function_name);
+ name.append("-caller");
+
+ m_caller_up.reset (process_sp->GetTarget().GetFunctionCallerForLanguage (Language(),
+ return_type,
+ impl_code_address,
+ arg_value_list,
+ name.c_str(),
+ error));
+ if (error.Fail())
+ {
+
+ return nullptr;
+ }
+ if (m_caller_up)
+ {
+ StreamString errors;
+ errors.Clear();
+ unsigned num_errors = m_caller_up->CompileFunction(errors);
+ if (num_errors)
+ {
+ error.SetErrorStringWithFormat ("Error compiling %s caller function: \"%s\".",
+ m_function_name.c_str(),
+ errors.GetData());
+ m_caller_up.reset();
+ return nullptr;
+ }
+
+ errors.Clear();
+ ExecutionContext exe_ctx(process_sp);
+
+ if (!m_caller_up->WriteFunctionWrapper(exe_ctx, errors))
+ {
+ error.SetErrorStringWithFormat ("Error inserting caller function for %s: \"%s\".",
+ m_function_name.c_str(),
+ errors.GetData());
+ m_caller_up.reset();
+ return nullptr;
+ }
+ }
+ return m_caller_up.get();
+}
diff --git a/lldb/source/Plugins/Language/ObjC/CoreMedia.cpp b/lldb/source/Plugins/Language/ObjC/CoreMedia.cpp
index bc7a93314c4..14123af27ca 100644
--- a/lldb/source/Plugins/Language/ObjC/CoreMedia.cpp
+++ b/lldb/source/Plugins/Language/ObjC/CoreMedia.cpp
@@ -25,7 +25,7 @@ lldb_private::formatters::CMTimeSummaryProvider (ValueObject& valobj, Stream& st
if (!type.IsValid())
return false;
- TypeSystem *type_system = valobj.GetExecutionContextRef().GetTargetSP()->GetTypeSystemForLanguage(lldb::eLanguageTypeC);
+ TypeSystem *type_system = valobj.GetExecutionContextRef().GetTargetSP()->GetScratchTypeSystemForLanguage(lldb::eLanguageTypeC);
if (!type_system)
return false;
diff --git a/lldb/source/Plugins/Language/ObjC/NSArray.cpp b/lldb/source/Plugins/Language/ObjC/NSArray.cpp
index d5466ed4c8d..c6db27e93d4 100644
--- a/lldb/source/Plugins/Language/ObjC/NSArray.cpp
+++ b/lldb/source/Plugins/Language/ObjC/NSArray.cpp
@@ -15,6 +15,7 @@
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/Expression/FunctionCaller.h"
#include "lldb/Host/Endian.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
index 7a519532036..925e49883b5 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp
@@ -8,7 +8,9 @@
//===----------------------------------------------------------------------===//
#include "AppleObjCClassDescriptorV2.h"
+
#include "lldb/Core/Log.h"
+#include "lldb/Expression/FunctionCaller.h"
using namespace lldb;
using namespace lldb_private;
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
index 81ae61841ae..b4b725ea3cc 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
@@ -1,4 +1,4 @@
-//===-- AppleObjCRuntime.cpp --------------------------------------*- C++ -*-===//
+//===-- AppleObjCRuntime.cpp -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -22,7 +22,8 @@
#include "lldb/Core/Scalar.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/StreamString.h"
-#include "lldb/Expression/ClangFunction.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Expression/FunctionCaller.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/ExecutionContext.h"
@@ -39,6 +40,10 @@ using namespace lldb_private;
#define PO_FUNCTION_TIMEOUT_USEC 15*1000*1000
+AppleObjCRuntime::~AppleObjCRuntime()
+{
+}
+
AppleObjCRuntime::AppleObjCRuntime(Process *process) :
ObjCLanguageRuntime (process),
m_read_objc_library (false),
@@ -135,16 +140,36 @@ AppleObjCRuntime::GetObjectDescription (Stream &strm, Value &value, ExecutionCon
}
// Now we're ready to call the function:
- ClangFunction func (*exe_ctx.GetBestExecutionContextScope(),
- return_clang_type,
- *function_address,
- arg_value_list,
- "objc-object-description");
-
- StreamString error_stream;
+ StreamString error_stream;
lldb::addr_t wrapper_struct_addr = LLDB_INVALID_ADDRESS;
- func.InsertFunction(exe_ctx, wrapper_struct_addr, error_stream);
+
+ if (!m_print_object_caller_up)
+ {
+ Error error;
+ m_print_object_caller_up.reset(exe_scope->CalculateTarget()->GetFunctionCallerForLanguage (eLanguageTypeObjC,
+ return_clang_type,
+ *function_address,
+ arg_value_list,
+ "objc-object-description",
+ error));
+ if (error.Fail())
+ {
+ m_print_object_caller_up.reset();
+ strm.Printf("Could not get function runner to call print for debugger function: %s.", error.AsCString());
+ return false;
+ }
+ m_print_object_caller_up->InsertFunction(exe_ctx, wrapper_struct_addr, error_stream);
+ }
+ else
+ {
+ m_print_object_caller_up->WriteFunctionArguments(exe_ctx,
+ wrapper_struct_addr,
+ arg_value_list,
+ error_stream);
+ }
+
+
EvaluateExpressionOptions options;
options.SetUnwindOnError(true);
@@ -153,11 +178,11 @@ AppleObjCRuntime::GetObjectDescription (Stream &strm, Value &value, ExecutionCon
options.SetIgnoreBreakpoints(true);
options.SetTimeoutUsec(PO_FUNCTION_TIMEOUT_USEC);
- ExpressionResults results = func.ExecuteFunction (exe_ctx,
- &wrapper_struct_addr,
- options,
- error_stream,
- ret);
+ ExpressionResults results = m_print_object_caller_up->ExecuteFunction (exe_ctx,
+ &wrapper_struct_addr,
+ options,
+ error_stream,
+ ret);
if (results != eExpressionCompleted)
{
strm.Printf("Error evaluating Print Object function: %d.\n", results);
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h
index f8f73bae865..424058ee0b7 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h
@@ -20,7 +20,6 @@
#include "lldb/lldb-private.h"
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
-#include "lldb/Core/ValueObject.h"
#include "AppleObjCTrampolineHandler.h"
#include "AppleThreadPlanStepThroughObjCTrampoline.h"
@@ -31,7 +30,7 @@ class AppleObjCRuntime :
{
public:
- virtual ~AppleObjCRuntime() { }
+ virtual ~AppleObjCRuntime();
// These are generic runtime functions:
bool
@@ -127,6 +126,7 @@ protected:
std::unique_ptr<lldb_private::AppleObjCTrampolineHandler> m_objc_trampoline_handler_ap;
lldb::BreakpointSP m_objc_exception_bp_sp;
lldb::ModuleWP m_objc_module_wp;
+ std::unique_ptr<FunctionCaller> m_print_object_caller_up;
llvm::Optional<uint32_t> m_Foundation_major;
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
index 17aa03e4a64..85729e827f5 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp
@@ -21,8 +21,8 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Core/StreamString.h"
-#include "lldb/Expression/ClangFunction.h"
-#include "lldb/Expression/ClangUtilityFunction.h"
+#include "lldb/Expression/FunctionCaller.h"
+#include "lldb/Expression/UtilityFunction.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/ExecutionContext.h"
@@ -143,7 +143,7 @@ struct BufStruct {
char contents[2048];
};
-ClangUtilityFunction *
+UtilityFunction *
AppleObjCRuntimeV1::CreateObjectChecker(const char *name)
{
std::unique_ptr<BufStruct> buf(new BufStruct);
@@ -170,7 +170,8 @@ AppleObjCRuntimeV1::CreateObjectChecker(const char *name)
"} \n",
name) < (int)sizeof(buf->contents));
- return new ClangUtilityFunction(buf->contents, name);
+ Error error;
+ return GetTargetRef().GetUtilityFunctionForLanguage(buf->contents, eLanguageTypeObjC, name, error);
}
AppleObjCRuntimeV1::ClassDescriptorV1::ClassDescriptorV1 (ValueObject &isa_pointer)
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
index f98f065f6a7..73e8607286f 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h
@@ -102,7 +102,7 @@ public:
TypeAndOrName &class_type_or_name,
Address &address);
- virtual ClangUtilityFunction *
+ virtual UtilityFunction *
CreateObjectChecker (const char *);
//------------------------------------------------------------------
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
index 4817d57a353..ac643064415 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
@@ -28,8 +28,8 @@
#include "lldb/Core/StreamString.h"
#include "lldb/Core/Timer.h"
#include "lldb/Core/ValueObjectVariable.h"
-#include "lldb/Expression/ClangFunction.h"
-#include "lldb/Expression/ClangUtilityFunction.h"
+#include "lldb/Expression/FunctionCaller.h"
+#include "lldb/Expression/UtilityFunction.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
@@ -348,11 +348,9 @@ ExtractRuntimeGlobalSymbol (Process* process,
AppleObjCRuntimeV2::AppleObjCRuntimeV2 (Process *process,
const ModuleSP &objc_module_sp) :
AppleObjCRuntime (process),
- m_get_class_info_function(),
m_get_class_info_code(),
m_get_class_info_args (LLDB_INVALID_ADDRESS),
m_get_class_info_args_mutex (Mutex::eMutexTypeNormal),
- m_get_shared_cache_class_info_function(),
m_get_shared_cache_class_info_code(),
m_get_shared_cache_class_info_args (LLDB_INVALID_ADDRESS),
m_get_shared_cache_class_info_args_mutex (Mutex::eMutexTypeNormal),
@@ -722,7 +720,7 @@ AppleObjCRuntimeV2::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bo
return resolver_sp;
}
-ClangUtilityFunction *
+UtilityFunction *
AppleObjCRuntimeV2::CreateObjectChecker(const char *name)
{
char check_function_code[2048];
@@ -780,7 +778,8 @@ AppleObjCRuntimeV2::CreateObjectChecker(const char *name)
assert (len < (int)sizeof(check_function_code));
- return new ClangUtilityFunction(check_function_code, name);
+ Error error;
+ return GetTargetRef().GetUtilityFunctionForLanguage(check_function_code, eLanguageTypeObjC, name, error);
}
size_t
@@ -1248,75 +1247,74 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table
CompilerType clang_uint32_t_type = ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
CompilerType clang_void_pointer_type = ast->GetBasicType(eBasicTypeVoid).GetPointerType();
+ ValueList arguments;
+ FunctionCaller *get_class_info_function = nullptr;
+
if (!m_get_class_info_code.get())
{
- m_get_class_info_code.reset (new ClangUtilityFunction (g_get_dynamic_class_info_body,
- g_get_dynamic_class_info_name));
-
- errors.Clear();
-
- if (!m_get_class_info_code->Install(errors, exe_ctx))
+ Error error;
+ m_get_class_info_code.reset (GetTargetRef().GetUtilityFunctionForLanguage (g_get_dynamic_class_info_body,
+ eLanguageTypeObjC,
+ g_get_dynamic_class_info_name,
+ error));
+ if (error.Fail())
{
if (log)
- log->Printf ("Failed to install implementation lookup: %s.", errors.GetData());
+ log->Printf ("Failed to get Utility Function for implementation lookup: %s", error.AsCString());
m_get_class_info_code.reset();
}
- }
-
- if (m_get_class_info_code.get())
- function_address.SetOffset(m_get_class_info_code->StartAddress());
- else
- return false;
-
- ValueList arguments;
-
- // Next make the runner function for our implementation utility function.
- if (!m_get_class_info_function.get())
- {
+ else
+ {
+ errors.Clear();
+
+ if (!m_get_class_info_code->Install(errors, exe_ctx))
+ {
+ if (log)
+ log->Printf ("Failed to install implementation lookup: %s.", errors.GetData());
+ m_get_class_info_code.reset();
+ }
+ }
+ if (!m_get_class_info_code.get())
+ return false;
+
+ // Next make the runner function for our implementation utility function.
Value value;
value.SetValueType (Value::eValueTypeScalar);
-// value.SetContext (Value::eContextTypeClangType, clang_void_pointer_type);
value.SetCompilerType (clang_void_pointer_type);
arguments.PushValue (value);
arguments.PushValue (value);
value.SetValueType (Value::eValueTypeScalar);
-// value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type);
value.SetCompilerType (clang_uint32_t_type);
arguments.PushValue (value);
- m_get_class_info_function.reset(new ClangFunction (*m_process,
- clang_uint32_t_type,
- function_address,
- arguments,
- "objc-v2-isa-to-descriptor"));
-
- if (m_get_class_info_function.get() == NULL)
- return false;
-
- errors.Clear();
+ get_class_info_function = m_get_class_info_code->MakeFunctionCaller(clang_uint32_t_type,
+ arguments,
+ error);
- unsigned num_errors = m_get_class_info_function->CompileFunction(errors);
- if (num_errors)
+ if (error.Fail())
{
if (log)
- log->Printf ("Error compiling function: \"%s\".", errors.GetData());
+ log->Printf("Failed to make function caller for implementation lookup: %s.", error.AsCString());
return false;
}
-
- errors.Clear();
-
- if (!m_get_class_info_function->WriteFunctionWrapper(exe_ctx, errors))
+ }
+ else
+ {
+ get_class_info_function = m_get_class_info_code->GetFunctionCaller();
+ if (!get_class_info_function)
{
if (log)
- log->Printf ("Error Inserting function: \"%s\".", errors.GetData());
+ log->Printf ("Failed to get implementation lookup function caller: %s.", errors.GetData());
return false;
}
+ arguments = get_class_info_function->GetArgumentValues();
}
- else
- {
- arguments = m_get_class_info_function->GetArgumentValues ();
- }
+
+
+
+
+ errors.Clear();
const uint32_t class_info_byte_size = addr_size + 4;
const uint32_t class_infos_byte_size = num_classes * class_info_byte_size;
@@ -1339,9 +1337,8 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table
errors.Clear();
// Write our function arguments into the process so we can run our function
- if (m_get_class_info_function->WriteFunctionArguments (exe_ctx,
+ if (get_class_info_function->WriteFunctionArguments (exe_ctx,
m_get_class_info_args,
- function_address,
arguments,
errors))
{
@@ -1361,11 +1358,11 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table
errors.Clear();
// Run the function
- ExpressionResults results = m_get_class_info_function->ExecuteFunction (exe_ctx,
- &m_get_class_info_args,
- options,
- errors,
- return_value);
+ ExpressionResults results = get_class_info_function->ExecuteFunction (exe_ctx,
+ &m_get_class_info_args,
+ options,
+ errors,
+ return_value);
if (results == eExpressionCompleted)
{
@@ -1502,31 +1499,38 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache()
CompilerType clang_uint32_t_type = ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
CompilerType clang_void_pointer_type = ast->GetBasicType(eBasicTypeVoid).GetPointerType();
+ ValueList arguments;
+ FunctionCaller *get_shared_cache_class_info_function = nullptr;
+
if (!m_get_shared_cache_class_info_code.get())
{
- m_get_shared_cache_class_info_code.reset (new ClangUtilityFunction (g_get_shared_cache_class_info_body,
- g_get_shared_cache_class_info_name));
-
- errors.Clear();
-
- if (!m_get_shared_cache_class_info_code->Install(errors, exe_ctx))
+ Error error;
+ m_get_shared_cache_class_info_code.reset (GetTargetRef().GetUtilityFunctionForLanguage (g_get_shared_cache_class_info_body,
+ eLanguageTypeObjC,
+ g_get_shared_cache_class_info_name,
+ error));
+ if (error.Fail())
{
if (log)
- log->Printf ("Failed to install implementation lookup: %s.", errors.GetData());
+ log->Printf ("Failed to get Utility function for implementation lookup: %s.", error.AsCString());
m_get_shared_cache_class_info_code.reset();
}
- }
-
- if (m_get_shared_cache_class_info_code.get())
- function_address.SetOffset(m_get_shared_cache_class_info_code->StartAddress());
- else
- return DescriptorMapUpdateResult::Fail();
-
- ValueList arguments;
+ else
+ {
+ errors.Clear();
+
+ if (!m_get_shared_cache_class_info_code->Install(errors, exe_ctx))
+ {
+ if (log)
+ log->Printf ("Failed to install implementation lookup: %s.", errors.GetData());
+ m_get_shared_cache_class_info_code.reset();
+ }
+ }
+
+ if (!m_get_shared_cache_class_info_code.get())
+ return DescriptorMapUpdateResult::Fail();
- // Next make the runner function for our implementation utility function.
- if (!m_get_shared_cache_class_info_function.get())
- {
+ // Next make the function caller for our implementation utility function.
Value value;
value.SetValueType (Value::eValueTypeScalar);
//value.SetContext (Value::eContextTypeClangType, clang_void_pointer_type);
@@ -1539,39 +1543,24 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache()
value.SetCompilerType (clang_uint32_t_type);
arguments.PushValue (value);
- m_get_shared_cache_class_info_function.reset(new ClangFunction (*m_process,
- clang_uint32_t_type,
- function_address,
- arguments,
- "objc-isa-to-descriptor-shared-cache"));
-
- if (m_get_shared_cache_class_info_function.get() == NULL)
- return DescriptorMapUpdateResult::Fail();
-
- errors.Clear();
-
- unsigned num_errors = m_get_shared_cache_class_info_function->CompileFunction(errors);
- if (num_errors)
- {
- if (log)
- log->Printf ("Error compiling function: \"%s\".", errors.GetData());
- return DescriptorMapUpdateResult::Fail();
- }
-
- errors.Clear();
+ get_shared_cache_class_info_function = m_get_shared_cache_class_info_code->MakeFunctionCaller(clang_uint32_t_type,
+ arguments,
+ error);
- if (!m_get_shared_cache_class_info_function->WriteFunctionWrapper(exe_ctx, errors))
- {
- if (log)
- log->Printf ("Error Inserting function: \"%s\".", errors.GetData());
+ if (get_shared_cache_class_info_function == nullptr)
return DescriptorMapUpdateResult::Fail();
- }
+
}
else
{
- arguments = m_get_shared_cache_class_info_function->GetArgumentValues ();
+ get_shared_cache_class_info_function = m_get_shared_cache_class_info_code->GetFunctionCaller();
+ if (get_shared_cache_class_info_function == nullptr)
+ return DescriptorMapUpdateResult::Fail();
+ arguments = get_shared_cache_class_info_function->GetArgumentValues();
}
+ errors.Clear();
+
const uint32_t class_info_byte_size = addr_size + 4;
const uint32_t class_infos_byte_size = num_classes * class_info_byte_size;
lldb::addr_t class_infos_addr = process->AllocateMemory (class_infos_byte_size,
@@ -1594,11 +1583,10 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache()
errors.Clear();
// Write our function arguments into the process so we can run our function
- if (m_get_shared_cache_class_info_function->WriteFunctionArguments (exe_ctx,
- m_get_shared_cache_class_info_args,
- function_address,
- arguments,
- errors))
+ if (get_shared_cache_class_info_function->WriteFunctionArguments (exe_ctx,
+ m_get_shared_cache_class_info_args,
+ arguments,
+ errors))
{
EvaluateExpressionOptions options;
options.SetUnwindOnError(true);
@@ -1616,11 +1604,11 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache()
errors.Clear();
// Run the function
- ExpressionResults results = m_get_shared_cache_class_info_function->ExecuteFunction (exe_ctx,
- &m_get_shared_cache_class_info_args,
- options,
- errors,
- return_value);
+ ExpressionResults results = get_shared_cache_class_info_function->ExecuteFunction (exe_ctx,
+ &m_get_shared_cache_class_info_args,
+ options,
+ errors,
+ return_value);
if (results == eExpressionCompleted)
{
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
index 6d981f72d8c..feaf9d4d6f0 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
@@ -39,7 +39,7 @@ public:
TypeAndOrName &class_type_or_name,
Address &address);
- virtual ClangUtilityFunction *
+ virtual UtilityFunction *
CreateObjectChecker (const char *);
@@ -299,22 +299,20 @@ private:
friend class ClassDescriptorV2;
- std::unique_ptr<ClangFunction> m_get_class_info_function;
- std::unique_ptr<ClangUtilityFunction> m_get_class_info_code;
+ std::unique_ptr<UtilityFunction> m_get_class_info_code;
lldb::addr_t m_get_class_info_args;
Mutex m_get_class_info_args_mutex;
- std::unique_ptr<ClangFunction> m_get_shared_cache_class_info_function;
- std::unique_ptr<ClangUtilityFunction> m_get_shared_cache_class_info_code;
+ std::unique_ptr<UtilityFunction> m_get_shared_cache_class_info_code;
lldb::addr_t m_get_shared_cache_class_info_args;
Mutex m_get_shared_cache_class_info_args_mutex;
- std::unique_ptr<DeclVendor> m_decl_vendor_ap;
+ std::unique_ptr<DeclVendor> m_decl_vendor_ap;
lldb::addr_t m_isa_hash_table_ptr;
HashTableSignature m_hash_signature;
bool m_has_object_getClass;
bool m_loaded_objc_opt;
- std::unique_ptr<NonPointerISACache> m_non_pointer_isa_cache_ap;
+ std::unique_ptr<NonPointerISACache> m_non_pointer_isa_cache_ap;
std::unique_ptr<TaggedPointerVendor> m_tagged_pointer_vendor_ap;
EncodingToTypeSP m_encoding_to_type_sp;
bool m_noclasses_warning_emitted;
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
index db5b7f0a406..d38a076ad5d 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp
@@ -22,9 +22,9 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Core/Value.h"
-#include "lldb/Expression/ClangExpression.h"
-#include "lldb/Expression/ClangFunction.h"
-#include "lldb/Expression/ClangUtilityFunction.h"
+#include "lldb/Expression/UserExpression.h"
+#include "lldb/Expression/FunctionCaller.h"
+#include "lldb/Expression/UtilityFunction.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/Symbol.h"
@@ -741,10 +741,10 @@ lldb::addr_t
AppleObjCTrampolineHandler::SetupDispatchFunction (Thread &thread, ValueList &dispatch_values)
{
ExecutionContext exe_ctx (thread.shared_from_this());
- Address impl_code_address;
StreamString errors;
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
lldb::addr_t args_addr = LLDB_INVALID_ADDRESS;
+ FunctionCaller *impl_function_caller = nullptr;
// Scope for mutex locker:
{
@@ -752,38 +752,23 @@ AppleObjCTrampolineHandler::SetupDispatchFunction (Thread &thread, ValueList &di
// First stage is to make the ClangUtility to hold our injected function:
- #define USE_BUILTIN_FUNCTION 0 // Define this to 1 and we will use the get_implementation function found in the target.
- // This is useful for debugging additions to the get_impl function 'cause you don't have
- // to bother with string-ifying the code into g_lookup_implementation_function_code.
-
- if (USE_BUILTIN_FUNCTION)
- {
- ConstString our_utility_function_name("__lldb_objc_find_implementation_for_selector");
- SymbolContextList sc_list;
-
- exe_ctx.GetTargetRef().GetImages().FindSymbolsWithNameAndType (our_utility_function_name, eSymbolTypeCode, sc_list);
- if (sc_list.GetSize() == 1)
- {
- SymbolContext sc;
- sc_list.GetContextAtIndex(0, sc);
- if (sc.symbol != NULL)
- impl_code_address = sc.symbol->GetAddress();
-
- //lldb::addr_t addr = impl_code_address.GetOpcodeLoadAddress (exe_ctx.GetTargetPtr());
- //printf ("Getting address for our_utility_function: 0x%" PRIx64 ".\n", addr);
- }
- else
- {
- //printf ("Could not find implementation function address.\n");
- return args_addr;
- }
- }
- else if (!m_impl_code.get())
+ if (!m_impl_code.get())
{
if (g_lookup_implementation_function_code != NULL)
{
- m_impl_code.reset (new ClangUtilityFunction (g_lookup_implementation_function_code,
- g_lookup_implementation_function_name));
+ Error error;
+ m_impl_code.reset (exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage (g_lookup_implementation_function_code,
+ eLanguageTypeObjC,
+ g_lookup_implementation_function_name,
+ error));
+ if (error.Fail())
+ {
+ if (log)
+ log->Printf ("Failed to get Utility Function for implementation lookup: %s.", error.AsCString());
+ m_impl_code.reset();
+ return args_addr;
+ }
+
if (!m_impl_code->Install(errors, exe_ctx))
{
if (log)
@@ -800,43 +785,26 @@ AppleObjCTrampolineHandler::SetupDispatchFunction (Thread &thread, ValueList &di
return LLDB_INVALID_ADDRESS;
}
- impl_code_address.Clear();
- impl_code_address.SetOffset(m_impl_code->StartAddress());
- }
- else
- {
- impl_code_address.Clear();
- impl_code_address.SetOffset(m_impl_code->StartAddress());
- }
- // Next make the runner function for our implementation utility function.
- if (!m_impl_function.get())
- {
+ // Next make the runner function for our implementation utility function.
ClangASTContext *clang_ast_context = thread.GetProcess()->GetTarget().GetScratchClangASTContext();
CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
- m_impl_function.reset(new ClangFunction (thread,
- clang_void_ptr_type,
- impl_code_address,
- dispatch_values,
- "objc-dispatch-lookup"));
+ Error error;
- errors.Clear();
- unsigned num_errors = m_impl_function->CompileFunction(errors);
- if (num_errors)
+ impl_function_caller = m_impl_code->MakeFunctionCaller(clang_void_ptr_type,
+ dispatch_values,
+ error);
+ if (error.Fail())
{
if (log)
- log->Printf ("Error compiling function: \"%s\".", errors.GetData());
- return args_addr;
- }
-
- errors.Clear();
- if (!m_impl_function->WriteFunctionWrapper(exe_ctx, errors))
- {
- if (log)
- log->Printf ("Error Inserting function: \"%s\".", errors.GetData());
+ log->Printf ("Error getting function caller for dispatch lookup: \"%s\".", error.AsCString());
return args_addr;
}
}
+ else
+ {
+ impl_function_caller = m_impl_code->GetFunctionCaller();
+ }
}
errors.Clear();
@@ -845,7 +813,7 @@ AppleObjCTrampolineHandler::SetupDispatchFunction (Thread &thread, ValueList &di
// if other threads were calling into here, but actually it isn't because we allocate a new args structure for
// this call by passing args_addr = LLDB_INVALID_ADDRESS...
- if (!m_impl_function->WriteFunctionArguments (exe_ctx, args_addr, impl_code_address, dispatch_values, errors))
+ if (impl_function_caller->WriteFunctionArguments (exe_ctx, args_addr, dispatch_values, errors))
{
if (log)
log->Printf ("Error writing function arguments: \"%s\".", errors.GetData());
@@ -1169,8 +1137,8 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan (Thread &thread, bool sto
return ret_plan_sp;
}
-ClangFunction *
-AppleObjCTrampolineHandler::GetLookupImplementationWrapperFunction ()
+FunctionCaller *
+AppleObjCTrampolineHandler::GetLookupImplementationFunctionCaller ()
{
- return m_impl_function.get();
+ return m_impl_code->GetFunctionCaller();
}
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h
index c9d0e19ed2b..0ddb540439d 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h
@@ -35,8 +35,8 @@ public:
GetStepThroughDispatchPlan (Thread &thread,
bool stop_others);
- ClangFunction *
- GetLookupImplementationWrapperFunction ();
+ FunctionCaller *
+ GetLookupImplementationFunctionCaller ();
bool
AddrIsMsgForward (lldb::addr_t addr) const
@@ -198,8 +198,7 @@ private:
MsgsendMap m_msgSend_map;
lldb::ProcessWP m_process_wp;
lldb::ModuleSP m_objc_module_sp;
- std::unique_ptr<ClangFunction> m_impl_function;
- std::unique_ptr<ClangUtilityFunction> m_impl_code;
+ std::unique_ptr<UtilityFunction> m_impl_code;
Mutex m_impl_function_mutex;
lldb::addr_t m_impl_fn_addr;
lldb::addr_t m_impl_stret_fn_addr;
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
index fe364faefe3..285786a09db 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp
@@ -15,8 +15,8 @@
#include "AppleObjCTrampolineHandler.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Thread.h"
-#include "lldb/Expression/ClangExpression.h"
-#include "lldb/Expression/ClangFunction.h"
+#include "lldb/Expression/FunctionCaller.h"
+#include "lldb/Expression/UtilityFunction.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/ThreadPlanRunToAddress.h"
@@ -67,11 +67,11 @@ AppleThreadPlanStepThroughObjCTrampoline::DidPush ()
{
// Setting up the memory space for the called function text might require allocations,
// i.e. a nested function call. This needs to be done as a PreResumeAction.
- m_thread.GetProcess()->AddPreResumeAction (PreResumeInitializeClangFunction, (void *) this);
+ m_thread.GetProcess()->AddPreResumeAction (PreResumeInitializeFunctionCaller, (void *) this);
}
bool
-AppleThreadPlanStepThroughObjCTrampoline::InitializeClangFunction ()
+AppleThreadPlanStepThroughObjCTrampoline::InitializeFunctionCaller ()
{
if (!m_func_sp)
{
@@ -82,7 +82,7 @@ AppleThreadPlanStepThroughObjCTrampoline::InitializeClangFunction ()
{
return false;
}
- m_impl_function = m_trampoline_handler->GetLookupImplementationWrapperFunction();
+ m_impl_function = m_trampoline_handler->GetLookupImplementationFunctionCaller();
ExecutionContext exc_ctx;
EvaluateExpressionOptions options;
options.SetUnwindOnError(true);
@@ -100,10 +100,10 @@ AppleThreadPlanStepThroughObjCTrampoline::InitializeClangFunction ()
}
bool
-AppleThreadPlanStepThroughObjCTrampoline::PreResumeInitializeClangFunction(void *void_myself)
+AppleThreadPlanStepThroughObjCTrampoline::PreResumeInitializeFunctionCaller(void *void_myself)
{
AppleThreadPlanStepThroughObjCTrampoline *myself = static_cast<AppleThreadPlanStepThroughObjCTrampoline *>(void_myself);
- return myself->InitializeClangFunction();
+ return myself->InitializeFunctionCaller();
}
void
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h
index 253190991ce..2ad181e553f 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h
@@ -66,7 +66,7 @@ public:
DidPush();
static bool
- PreResumeInitializeClangFunction(void *myself);
+ PreResumeInitializeFunctionCaller(void *myself);
virtual bool
WillStop();
@@ -82,7 +82,7 @@ protected:
private:
bool
- InitializeClangFunction ();
+ InitializeFunctionCaller ();
//------------------------------------------------------------------
// For AppleThreadPlanStepThroughObjCTrampoline only
@@ -96,7 +96,7 @@ private:
lldb::ThreadPlanSP m_func_sp; // This is the function call plan. We fill it at start, then set it
// to NULL when this plan is done. That way we know to go to:
lldb::ThreadPlanSP m_run_to_sp; // The plan that runs to the target.
- ClangFunction *m_impl_function; // This is a pointer to a impl function that
+ FunctionCaller *m_impl_function; // This is a pointer to a impl function that
// is owned by the client that pushes this plan.
bool m_stop_others;
};
diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp
index a882b7e3e87..66b8b8bcf59 100644
--- a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp
+++ b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp
@@ -22,9 +22,8 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/Value.h"
-#include "lldb/Expression/ClangExpression.h"
-#include "lldb/Expression/ClangFunction.h"
-#include "lldb/Expression/ClangUtilityFunction.h"
+#include "lldb/Expression/FunctionCaller.h"
+#include "lldb/Expression/UtilityFunction.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/ExecutionContext.h"
@@ -101,7 +100,6 @@ extern \"C\"
AppleGetItemInfoHandler::AppleGetItemInfoHandler (Process *process) :
m_process (process),
- m_get_item_info_function (),
m_get_item_info_impl_code (),
m_get_item_info_function_mutex(),
m_get_item_info_return_buffer_addr (LLDB_INVALID_ADDRESS),
@@ -140,49 +138,33 @@ lldb::addr_t
AppleGetItemInfoHandler::SetupGetItemInfoFunction (Thread &thread, ValueList &get_item_info_arglist)
{
ExecutionContext exe_ctx (thread.shared_from_this());
- Address impl_code_address;
StreamString errors;
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYSTEM_RUNTIME));
lldb::addr_t args_addr = LLDB_INVALID_ADDRESS;
+ FunctionCaller *get_item_info_caller = nullptr;
// Scope for mutex locker:
{
Mutex::Locker locker(m_get_item_info_function_mutex);
- // First stage is to make the ClangUtility to hold our injected function:
+ // First stage is to make the UtilityFunction to hold our injected function:
-#define USE_BUILTIN_FUNCTION 0 // Define this to 1 and we will use the get_implementation function found in the target.
- // This is useful for debugging additions to the get_impl function 'cause you don't have
- // to bother with string-ifying the code into g_get_item_info_function_code.
-
- if (USE_BUILTIN_FUNCTION)
- {
- ConstString our_utility_function_name("__lldb_backtrace_recording_get_item_info");
- SymbolContextList sc_list;
-
- exe_ctx.GetTargetRef().GetImages().FindSymbolsWithNameAndType (our_utility_function_name, eSymbolTypeCode, sc_list);
- if (sc_list.GetSize() == 1)
- {
- SymbolContext sc;
- sc_list.GetContextAtIndex(0, sc);
- if (sc.symbol != NULL)
- impl_code_address = sc.symbol->GetAddress();
-
- //lldb::addr_t addr = impl_code_address.GetOpcodeLoadAddress (exe_ctx.GetTargetPtr());
- //printf ("Getting address for our_utility_function: 0x%" PRIx64 ".\n", addr);
- }
- else
- {
- //printf ("Could not find queues introspection function address.\n");
- return args_addr;
- }
- }
- else if (!m_get_item_info_impl_code.get())
+ if (!m_get_item_info_impl_code.get())
{
if (g_get_item_info_function_code != NULL)
{
- m_get_item_info_impl_code.reset (new ClangUtilityFunction (g_get_item_info_function_code,
- g_get_item_info_function_name));
+ Error error;
+ m_get_item_info_impl_code.reset(exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage (g_get_item_info_function_code,
+ eLanguageTypeObjC,
+ g_get_item_info_function_name,
+ error));
+ if (error.Fail())
+ {
+ if (log)
+ log->Printf ("Failed to get utility function: %s.", error.AsCString());
+ return args_addr;
+ }
+
if (!m_get_item_info_impl_code->Install(errors, exe_ctx))
{
if (log)
@@ -198,41 +180,32 @@ AppleGetItemInfoHandler::SetupGetItemInfoFunction (Thread &thread, ValueList &ge
errors.Printf ("No get-item-info introspection code found.");
return LLDB_INVALID_ADDRESS;
}
-
- impl_code_address.Clear();
- impl_code_address.SetOffset(m_get_item_info_impl_code->StartAddress());
- }
- else
- {
- impl_code_address.Clear();
- impl_code_address.SetOffset(m_get_item_info_impl_code->StartAddress());
- }
- // Next make the runner function for our implementation utility function.
- if (!m_get_item_info_function.get())
- {
- ClangASTContext *clang_ast_context = thread.GetProcess()->GetTarget().GetScratchClangASTContext();
- CompilerType get_item_info_return_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
- m_get_item_info_function.reset(new ClangFunction (thread,
- get_item_info_return_type,
- impl_code_address,
- get_item_info_arglist,
- "queue-bt-item-info"));
+ // Next make the runner function for our implementation utility function.
+ Error error;
+
+ TypeSystem *type_system = thread.GetProcess()->GetTarget().GetScratchTypeSystemForLanguage(eLanguageTypeC);
+ CompilerType get_item_info_return_type = type_system->GetBasicTypeFromAST(eBasicTypeVoid).GetPointerType();
- errors.Clear();
- unsigned num_errors = m_get_item_info_function->CompileFunction(errors);
- if (num_errors)
+ get_item_info_caller = m_get_item_info_impl_code->MakeFunctionCaller(get_item_info_return_type,
+ get_item_info_arglist,
+ error);
+ if (error.Fail())
{
if (log)
- log->Printf ("Error compiling get-item-info function: \"%s\".", errors.GetData());
+ log->Printf ("Error Inserting get-item-info function: \"%s\".", error.AsCString());
return args_addr;
}
-
- errors.Clear();
- if (!m_get_item_info_function->WriteFunctionWrapper(exe_ctx, errors))
+ }
+ else
+ {
+ // If it's already made, then we can just retrieve the caller:
+ get_item_info_caller = m_get_item_info_impl_code->GetFunctionCaller();
+ if (!get_item_info_caller)
{
if (log)
- log->Printf ("Error Inserting get-item-info function: \"%s\".", errors.GetData());
+ log->Printf ("Failed to get get-item-info introspection caller.");
+ m_get_item_info_impl_code.reset();
return args_addr;
}
}
@@ -244,7 +217,7 @@ AppleGetItemInfoHandler::SetupGetItemInfoFunction (Thread &thread, ValueList &ge
// if other threads were calling into here, but actually it isn't because we allocate a new args structure for
// this call by passing args_addr = LLDB_INVALID_ADDRESS...
- if (!m_get_item_info_function->WriteFunctionArguments (exe_ctx, args_addr, impl_code_address, get_item_info_arglist, errors))
+ if (!get_item_info_caller->WriteFunctionArguments (exe_ctx, args_addr, get_item_info_arglist, errors))
{
if (log)
log->Printf ("Error writing get-item-info function arguments: \"%s\".", errors.GetData());
@@ -364,7 +337,7 @@ AppleGetItemInfoHandler::GetItemInfo (Thread &thread, uint64_t item, addr_t page
options.SetTryAllThreads (false);
thread.CalculateExecutionContext (exe_ctx);
- if (m_get_item_info_function == NULL)
+ if (!m_get_item_info_impl_code)
{
error.SetErrorString ("Unable to compile function to call __introspection_dispatch_queue_item_get_info");
return return_value;
@@ -373,7 +346,16 @@ AppleGetItemInfoHandler::GetItemInfo (Thread &thread, uint64_t item, addr_t page
ExpressionResults func_call_ret;
Value results;
- func_call_ret = m_get_item_info_function->ExecuteFunction (exe_ctx, &args_addr, options, errors, results);
+ FunctionCaller *func_caller = m_get_item_info_impl_code->GetFunctionCaller();
+ if (!func_caller)
+ {
+ if (log)
+ log->Printf ("Could not retrieve function caller for __introspection_dispatch_queue_item_get_info.");
+ error.SetErrorString("Could not retrieve function caller for __introspection_dispatch_queue_item_get_info.");
+ return return_value;
+ }
+
+ func_call_ret = func_caller->ExecuteFunction (exe_ctx, &args_addr, options, errors, results);
if (func_call_ret != eExpressionCompleted || !error.Success())
{
if (log)
diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.h b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.h
index 5c086c61978..51182a62493 100644
--- a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.h
+++ b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.h
@@ -18,11 +18,11 @@
// Project includes
#include "lldb/lldb-public.h"
#include "lldb/Core/Error.h"
-#include "lldb/Expression/ClangFunction.h"
+#include "lldb/Expression/UtilityFunction.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Symbol/CompilerType.h"
-// This class will insert a ClangUtilityFunction into the inferior process for
+// This class will insert a UtilityFunction into the inferior process for
// calling libBacktraceRecording's __introspection_dispatch_queue_item_get_info()
// function. The function in the inferior will return a struct by value
// with these members:
@@ -37,7 +37,7 @@
// space (item_buffer_size in size) which must be mach_vm_deallocate'd by
// lldb.
//
-// The AppleGetItemInfoHandler object should persist so that the ClangUtilityFunction
+// The AppleGetItemInfoHandler object should persist so that the UtilityFunction
// can be reused multiple times.
namespace lldb_private
@@ -104,8 +104,7 @@ private:
static const char *g_get_item_info_function_code;
lldb_private::Process *m_process;
- std::unique_ptr<ClangFunction> m_get_item_info_function;
- std::unique_ptr<ClangUtilityFunction> m_get_item_info_impl_code;
+ std::unique_ptr<UtilityFunction> m_get_item_info_impl_code;
Mutex m_get_item_info_function_mutex;
lldb::addr_t m_get_item_info_return_buffer_addr;
diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp
index c3e68eaa0a6..3e3a2620013 100644
--- a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp
+++ b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp
@@ -22,9 +22,8 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/Value.h"
-#include "lldb/Expression/ClangExpression.h"
-#include "lldb/Expression/ClangFunction.h"
-#include "lldb/Expression/ClangUtilityFunction.h"
+#include "lldb/Expression/FunctionCaller.h"
+#include "lldb/Expression/UtilityFunction.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/ExecutionContext.h"
@@ -105,7 +104,6 @@ extern \"C\"
AppleGetPendingItemsHandler::AppleGetPendingItemsHandler (Process *process) :
m_process (process),
- m_get_pending_items_function (),
m_get_pending_items_impl_code (),
m_get_pending_items_function_mutex(),
m_get_pending_items_return_buffer_addr (LLDB_INVALID_ADDRESS),
@@ -144,49 +142,33 @@ lldb::addr_t
AppleGetPendingItemsHandler::SetupGetPendingItemsFunction (Thread &thread, ValueList &get_pending_items_arglist)
{
ExecutionContext exe_ctx (thread.shared_from_this());
- Address impl_code_address;
StreamString errors;
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYSTEM_RUNTIME));
lldb::addr_t args_addr = LLDB_INVALID_ADDRESS;
-
+ FunctionCaller *get_pending_items_caller = nullptr;
+
// Scope for mutex locker:
{
Mutex::Locker locker(m_get_pending_items_function_mutex);
// First stage is to make the ClangUtility to hold our injected function:
-#define USE_BUILTIN_FUNCTION 0 // Define this to 1 and we will use the get_implementation function found in the target.
- // This is useful for debugging additions to the get_impl function 'cause you don't have
- // to bother with string-ifying the code into g_get_pending_items_function_code.
-
- if (USE_BUILTIN_FUNCTION)
- {
- ConstString our_utility_function_name("__lldb_backtrace_recording_get_pending_items");
- SymbolContextList sc_list;
-
- exe_ctx.GetTargetRef().GetImages().FindSymbolsWithNameAndType (our_utility_function_name, eSymbolTypeCode, sc_list);
- if (sc_list.GetSize() == 1)
- {
- SymbolContext sc;
- sc_list.GetContextAtIndex(0, sc);
- if (sc.symbol != NULL)
- impl_code_address = sc.symbol->GetAddress();
-
- //lldb::addr_t addr = impl_code_address.GetOpcodeLoadAddress (exe_ctx.GetTargetPtr());
- //printf ("Getting address for our_utility_function: 0x%" PRIx64 ".\n", addr);
- }
- else
- {
- //printf ("Could not find queues introspection function address.\n");
- return args_addr;
- }
- }
- else if (!m_get_pending_items_impl_code.get())
+ if (!m_get_pending_items_impl_code.get())
{
if (g_get_pending_items_function_code != NULL)
{
- m_get_pending_items_impl_code.reset (new ClangUtilityFunction (g_get_pending_items_function_code,
- g_get_pending_items_function_name));
+ Error error;
+ m_get_pending_items_impl_code.reset (exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage(g_get_pending_items_function_code,
+ eLanguageTypeObjC,
+ g_get_pending_items_function_name,
+ error));
+ if (error.Fail())
+ {
+ if (log)
+ log->Printf ("Failed to get UtilityFunction for pending-items introspection: %s.", error.AsCString());
+ return args_addr;
+ }
+
if (!m_get_pending_items_impl_code->Install(errors, exe_ctx))
{
if (log)
@@ -203,43 +185,22 @@ AppleGetPendingItemsHandler::SetupGetPendingItemsFunction (Thread &thread, Value
return LLDB_INVALID_ADDRESS;
}
- impl_code_address.Clear();
- impl_code_address.SetOffset(m_get_pending_items_impl_code->StartAddress());
- }
- else
- {
- impl_code_address.Clear();
- impl_code_address.SetOffset(m_get_pending_items_impl_code->StartAddress());
- }
-
- // Next make the runner function for our implementation utility function.
- if (!m_get_pending_items_function.get())
- {
+ // Next make the runner function for our implementation utility function.
+ Error error;
ClangASTContext *clang_ast_context = thread.GetProcess()->GetTarget().GetScratchClangASTContext();
CompilerType get_pending_items_return_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
- m_get_pending_items_function.reset(new ClangFunction (thread,
- get_pending_items_return_type,
- impl_code_address,
- get_pending_items_arglist,
- "queue-pending-items"));
-
- errors.Clear();
- unsigned num_errors = m_get_pending_items_function->CompileFunction(errors);
- if (num_errors)
+ get_pending_items_caller = m_get_pending_items_impl_code->MakeFunctionCaller (get_pending_items_return_type,
+ get_pending_items_arglist,
+ error);
+ if (error.Fail())
{
if (log)
- log->Printf ("Error compiling pending-items function: \"%s\".", errors.GetData());
- return args_addr;
- }
-
- errors.Clear();
- if (!m_get_pending_items_function->WriteFunctionWrapper(exe_ctx, errors))
- {
- if (log)
- log->Printf ("Error Inserting pending-items function: \"%s\".", errors.GetData());
+ log->Printf ("Failed to install pending-items introspection function caller: %s.", error.AsCString());
+ m_get_pending_items_impl_code.reset();
return args_addr;
}
}
+
}
errors.Clear();
@@ -248,7 +209,7 @@ AppleGetPendingItemsHandler::SetupGetPendingItemsFunction (Thread &thread, Value
// if other threads were calling into here, but actually it isn't because we allocate a new args structure for
// this call by passing args_addr = LLDB_INVALID_ADDRESS...
- if (!m_get_pending_items_function->WriteFunctionArguments (exe_ctx, args_addr, impl_code_address, get_pending_items_arglist, errors))
+ if (!get_pending_items_caller->WriteFunctionArguments (exe_ctx, args_addr, get_pending_items_arglist, errors))
{
if (log)
log->Printf ("Error writing pending-items function arguments: \"%s\".", errors.GetData());
@@ -362,6 +323,8 @@ AppleGetPendingItemsHandler::GetPendingItems (Thread &thread, addr_t queue, addr
StreamString errors;
ExecutionContext exe_ctx;
+ FunctionCaller *get_pending_items_caller = m_get_pending_items_impl_code->GetFunctionCaller();
+
EvaluateExpressionOptions options;
options.SetUnwindOnError (true);
options.SetIgnoreBreakpoints (true);
@@ -370,7 +333,7 @@ AppleGetPendingItemsHandler::GetPendingItems (Thread &thread, addr_t queue, addr
options.SetTryAllThreads (false);
thread.CalculateExecutionContext (exe_ctx);
- if (m_get_pending_items_function == NULL)
+ if (get_pending_items_caller == NULL)
{
error.SetErrorString ("Unable to compile function to call __introspection_dispatch_queue_get_pending_items");
return return_value;
@@ -379,7 +342,7 @@ AppleGetPendingItemsHandler::GetPendingItems (Thread &thread, addr_t queue, addr
ExpressionResults func_call_ret;
Value results;
- func_call_ret = m_get_pending_items_function->ExecuteFunction (exe_ctx, &args_addr, options, errors, results);
+ func_call_ret = get_pending_items_caller->ExecuteFunction (exe_ctx, &args_addr, options, errors, results);
if (func_call_ret != eExpressionCompleted || !error.Success())
{
if (log)
diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.h b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.h
index 22ab1f6132c..445c4a0fb82 100644
--- a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.h
+++ b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.h
@@ -18,11 +18,10 @@
// Project includes
#include "lldb/lldb-public.h"
#include "lldb/Core/Error.h"
-#include "lldb/Expression/ClangFunction.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Symbol/CompilerType.h"
-// This class will insert a ClangUtilityFunction into the inferior process for
+// This class will insert a UtilityFunction into the inferior process for
// calling libBacktraceRecording's __introspection_dispatch_queue_get_pending_items()
// function. The function in the inferior will return a struct by value
// with these members:
@@ -38,7 +37,7 @@
// space (items_buffer_size in size) which must be mach_vm_deallocate'd by
// lldb. count is the number of items that were stored in the buffer.
//
-// The AppleGetPendingItemsHandler object should persist so that the ClangUtilityFunction
+// The AppleGetPendingItemsHandler object should persist so that the UtilityFunction
// can be reused multiple times.
namespace lldb_private
@@ -107,8 +106,7 @@ private:
static const char *g_get_pending_items_function_code;
lldb_private::Process *m_process;
- std::unique_ptr<ClangFunction> m_get_pending_items_function;
- std::unique_ptr<ClangUtilityFunction> m_get_pending_items_impl_code;
+ std::unique_ptr<UtilityFunction> m_get_pending_items_impl_code;
Mutex m_get_pending_items_function_mutex;
lldb::addr_t m_get_pending_items_return_buffer_addr;
diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp
index d5b1380e273..6d7eaf72191 100644
--- a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp
+++ b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp
@@ -21,9 +21,8 @@
#include "lldb/Core/Module.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/Value.h"
-#include "lldb/Expression/ClangExpression.h"
-#include "lldb/Expression/ClangFunction.h"
-#include "lldb/Expression/ClangUtilityFunction.h"
+#include "lldb/Expression/FunctionCaller.h"
+#include "lldb/Expression/UtilityFunction.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/ExecutionContext.h"
@@ -101,8 +100,7 @@ extern \"C\"
AppleGetQueuesHandler::AppleGetQueuesHandler (Process *process) :
m_process (process),
- m_get_queues_function (),
- m_get_queues_impl_code (),
+ m_get_queues_impl_code_up (),
m_get_queues_function_mutex(),
m_get_queues_return_buffer_addr (LLDB_INVALID_ADDRESS),
m_get_queues_retbuffer_mutex()
@@ -156,6 +154,8 @@ AppleGetQueuesHandler::SetupGetQueuesFunction (Thread &thread, ValueList &get_qu
StreamString errors;
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYSTEM_RUNTIME));
lldb::addr_t args_addr = LLDB_INVALID_ADDRESS;
+
+ FunctionCaller *get_queues_caller = nullptr;
// Scope for mutex locker:
{
@@ -163,43 +163,27 @@ AppleGetQueuesHandler::SetupGetQueuesFunction (Thread &thread, ValueList &get_qu
// First stage is to make the ClangUtility to hold our injected function:
-#define USE_BUILTIN_FUNCTION 0 // Define this to 1 and we will use the get_implementation function found in the target.
- // This is useful for debugging additions to the get_impl function 'cause you don't have
- // to bother with string-ifying the code into g_get_current_queues_function_code.
-
- if (USE_BUILTIN_FUNCTION)
- {
- ConstString our_utility_function_name("__lldb_backtrace_recording_get_current_queues");
- SymbolContextList sc_list;
-
- exe_ctx.GetTargetRef().GetImages().FindSymbolsWithNameAndType (our_utility_function_name, eSymbolTypeCode, sc_list);
- if (sc_list.GetSize() == 1)
- {
- SymbolContext sc;
- sc_list.GetContextAtIndex(0, sc);
- if (sc.symbol != NULL)
- impl_code_address = sc.symbol->GetAddress();
-
- //lldb::addr_t addr = impl_code_address.GetOpcodeLoadAddress (exe_ctx.GetTargetPtr());
- //printf ("Getting address for our_utility_function: 0x%" PRIx64 ".\n", addr);
- }
- else
- {
- //printf ("Could not find queues introspection function address.\n");
- return args_addr;
- }
- }
- else if (!m_get_queues_impl_code.get())
+ if (!m_get_queues_impl_code_up.get())
{
if (g_get_current_queues_function_code != NULL)
{
- m_get_queues_impl_code.reset (new ClangUtilityFunction (g_get_current_queues_function_code,
- g_get_current_queues_function_name));
- if (!m_get_queues_impl_code->Install(errors, exe_ctx))
+ Error error;
+ m_get_queues_impl_code_up.reset (exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage(g_get_current_queues_function_code,
+ eLanguageTypeC,
+ g_get_current_queues_function_name,
+ error));
+ if (error.Fail())
+ {
+ if (log)
+ log->Printf ("Failed to get UtilityFunction for queues introspection: %s.", error.AsCString());
+ return args_addr;
+ }
+
+ if (!m_get_queues_impl_code_up->Install(errors, exe_ctx))
{
if (log)
log->Printf ("Failed to install queues introspection: %s.", errors.GetData());
- m_get_queues_impl_code.reset();
+ m_get_queues_impl_code_up.reset();
return args_addr;
}
}
@@ -210,43 +194,20 @@ AppleGetQueuesHandler::SetupGetQueuesFunction (Thread &thread, ValueList &get_qu
errors.Printf ("No queues introspection code found.");
return LLDB_INVALID_ADDRESS;
}
-
- impl_code_address.Clear();
- impl_code_address.SetOffset(m_get_queues_impl_code->StartAddress());
- }
- else
- {
- impl_code_address.Clear();
- impl_code_address.SetOffset(m_get_queues_impl_code->StartAddress());
}
-
+
// Next make the runner function for our implementation utility function.
- if (!m_get_queues_function.get())
+ ClangASTContext *clang_ast_context = thread.GetProcess()->GetTarget().GetScratchClangASTContext();
+ CompilerType get_queues_return_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
+ Error error;
+ get_queues_caller = m_get_queues_impl_code_up->MakeFunctionCaller (get_queues_return_type,
+ get_queues_arglist,
+ error);
+ if (error.Fail())
{
- ClangASTContext *clang_ast_context = thread.GetProcess()->GetTarget().GetScratchClangASTContext();
- CompilerType get_queues_return_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
- m_get_queues_function.reset(new ClangFunction (thread,
- get_queues_return_type,
- impl_code_address,
- get_queues_arglist,
- "queue-fetch-queues"));
-
- errors.Clear();
- unsigned num_errors = m_get_queues_function->CompileFunction(errors);
- if (num_errors)
- {
- if (log)
- log->Printf ("Error compiling get-queues function: \"%s\".", errors.GetData());
- return args_addr;
- }
-
- errors.Clear();
- if (!m_get_queues_function->WriteFunctionWrapper(exe_ctx, errors))
- {
- if (log)
- log->Printf ("Error Inserting get-queues function: \"%s\".", errors.GetData());
- return args_addr;
- }
+ if (log)
+ log->Printf ("Could not get function caller for get-queues function: %s.", error.AsCString());
+ return args_addr;
}
}
@@ -256,7 +217,7 @@ AppleGetQueuesHandler::SetupGetQueuesFunction (Thread &thread, ValueList &get_qu
// if other threads were calling into here, but actually it isn't because we allocate a new args structure for
// this call by passing args_addr = LLDB_INVALID_ADDRESS...
- if (!m_get_queues_function->WriteFunctionArguments (exe_ctx, args_addr, impl_code_address, get_queues_arglist, errors))
+ if (!get_queues_caller->WriteFunctionArguments (exe_ctx, args_addr, get_queues_arglist, errors))
{
if (log)
log->Printf ("Error writing get-queues function arguments: \"%s\".", errors.GetData());
@@ -360,9 +321,17 @@ AppleGetQueuesHandler::GetCurrentQueues (Thread &thread, addr_t page_to_free, ui
addr_t args_addr = SetupGetQueuesFunction (thread, argument_values);
- if (m_get_queues_function == NULL)
+ if (!m_get_queues_impl_code_up)
+ {
+ error.SetErrorString ("Unable to compile __introspection_dispatch_get_queues.");
+ return return_value;
+ }
+
+ FunctionCaller *get_queues_caller = m_get_queues_impl_code_up->GetFunctionCaller();
+
+ if (get_queues_caller == NULL)
{
- error.SetErrorString ("Unable to compile function to call __introspection_dispatch_get_queues");
+ error.SetErrorString ("Unable to get caller for call __introspection_dispatch_get_queues");
return return_value;
}
@@ -378,7 +347,7 @@ AppleGetQueuesHandler::GetCurrentQueues (Thread &thread, addr_t page_to_free, ui
ExpressionResults func_call_ret;
Value results;
- func_call_ret = m_get_queues_function->ExecuteFunction (exe_ctx, &args_addr, options, errors, results);
+ func_call_ret = get_queues_caller->ExecuteFunction (exe_ctx, &args_addr, options, errors, results);
if (func_call_ret != eExpressionCompleted || !error.Success())
{
if (log)
diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.h b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.h
index 83730b58374..6f3df5f6280 100644
--- a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.h
+++ b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.h
@@ -18,11 +18,10 @@
// Project includes
#include "lldb/lldb-public.h"
#include "lldb/Core/Error.h"
-#include "lldb/Expression/ClangFunction.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Symbol/CompilerType.h"
-// This class will insert a ClangUtilityFunction into the inferior process for
+// This class will insert a UtilityFunction into the inferior process for
// calling libBacktraceRecording's introspection_get_dispatch_queues()
// function. The function in the inferior will return a struct by value
// with these members:
@@ -38,7 +37,7 @@
// space (queues_buffer_size in size) which must be mach_vm_deallocate'd by
// lldb. count is the number of queues that were stored in the buffer.
//
-// The AppleGetQueuesHandler object should persist so that the ClangUtilityFunction
+// The AppleGetQueuesHandler object should persist so that the UtilityFunction
// can be reused multiple times.
namespace lldb_private
@@ -104,8 +103,7 @@ private:
static const char *g_get_current_queues_function_code;
lldb_private::Process *m_process;
- std::unique_ptr<ClangFunction> m_get_queues_function;
- std::unique_ptr<ClangUtilityFunction> m_get_queues_impl_code;
+ std::unique_ptr<UtilityFunction> m_get_queues_impl_code_up;
Mutex m_get_queues_function_mutex;
lldb::addr_t m_get_queues_return_buffer_addr;
diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp
index 2509b3ba0ef..ea7014147b6 100644
--- a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp
+++ b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp
@@ -17,18 +17,20 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclCXX.h"
+#include "lldb/lldb-private.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/Value.h"
-#include "lldb/Expression/ClangExpression.h"
-#include "lldb/Expression/ClangFunction.h"
-#include "lldb/Expression/ClangUtilityFunction.h"
+#include "lldb/Expression/Expression.h"
+#include "lldb/Expression/FunctionCaller.h"
+#include "lldb/Expression/UtilityFunction.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h"
+#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
@@ -105,7 +107,6 @@ extern \"C\"
AppleGetThreadItemInfoHandler::AppleGetThreadItemInfoHandler (Process *process) :
m_process (process),
- m_get_thread_item_info_function (),
m_get_thread_item_info_impl_code (),
m_get_thread_item_info_function_mutex(),
m_get_thread_item_info_return_buffer_addr (LLDB_INVALID_ADDRESS),
@@ -148,6 +149,7 @@ AppleGetThreadItemInfoHandler::SetupGetThreadItemInfoFunction (Thread &thread, V
StreamString errors;
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYSTEM_RUNTIME));
lldb::addr_t args_addr = LLDB_INVALID_ADDRESS;
+ FunctionCaller *get_thread_item_info_caller = nullptr;
// Scope for mutex locker:
{
@@ -155,38 +157,24 @@ AppleGetThreadItemInfoHandler::SetupGetThreadItemInfoFunction (Thread &thread, V
// First stage is to make the ClangUtility to hold our injected function:
-#define USE_BUILTIN_FUNCTION 0 // Define this to 1 and we will use the get_implementation function found in the target.
- // This is useful for debugging additions to the get_impl function 'cause you don't have
- // to bother with string-ifying the code into g_get_thread_item_info_function_code.
-
- if (USE_BUILTIN_FUNCTION)
- {
- ConstString our_utility_function_name("__lldb_backtrace_recording_get_thread_item_info");
- SymbolContextList sc_list;
-
- exe_ctx.GetTargetRef().GetImages().FindSymbolsWithNameAndType (our_utility_function_name, eSymbolTypeCode, sc_list);
- if (sc_list.GetSize() == 1)
- {
- SymbolContext sc;
- sc_list.GetContextAtIndex(0, sc);
- if (sc.symbol != NULL)
- impl_code_address = sc.symbol->GetAddress();
-
- //lldb::addr_t addr = impl_code_address.GetOpcodeLoadAddress (exe_ctx.GetTargetPtr());
- //printf ("Getting address for our_utility_function: 0x%" PRIx64 ".\n", addr);
- }
- else
- {
- //printf ("Could not find queues introspection function address.\n");
- return args_addr;
- }
- }
- else if (!m_get_thread_item_info_impl_code.get())
+ if (!m_get_thread_item_info_impl_code.get())
{
+ Error error;
if (g_get_thread_item_info_function_code != NULL)
{
- m_get_thread_item_info_impl_code.reset (new ClangUtilityFunction (g_get_thread_item_info_function_code,
- g_get_thread_item_info_function_name));
+ m_get_thread_item_info_impl_code.reset (exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage (g_get_thread_item_info_function_code,
+ eLanguageTypeC,
+ g_get_thread_item_info_function_name,
+ error));
+ if (error.Fail())
+ {
+ if (log)
+ log->Printf ("Failed to get UtilityFunction for get-thread-item-info introspection: %s.",
+ error.AsCString());
+ m_get_thread_item_info_impl_code.reset();
+ return args_addr;
+ }
+
if (!m_get_thread_item_info_impl_code->Install(errors, exe_ctx))
{
if (log)
@@ -203,42 +191,26 @@ AppleGetThreadItemInfoHandler::SetupGetThreadItemInfoFunction (Thread &thread, V
return LLDB_INVALID_ADDRESS;
}
- impl_code_address.Clear();
- impl_code_address.SetOffset(m_get_thread_item_info_impl_code->StartAddress());
- }
- else
- {
- impl_code_address.Clear();
- impl_code_address.SetOffset(m_get_thread_item_info_impl_code->StartAddress());
- }
-
- // Next make the runner function for our implementation utility function.
- if (!m_get_thread_item_info_function.get())
- {
+ // Also make the FunctionCaller for this UtilityFunction:
+
ClangASTContext *clang_ast_context = thread.GetProcess()->GetTarget().GetScratchClangASTContext();
CompilerType get_thread_item_info_return_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
- m_get_thread_item_info_function.reset(new ClangFunction (thread,
- get_thread_item_info_return_type,
- impl_code_address,
- get_thread_item_info_arglist,
- "queue-thread-item-info"));
- errors.Clear();
- unsigned num_errors = m_get_thread_item_info_function->CompileFunction(errors);
- if (num_errors)
+ get_thread_item_info_caller = m_get_thread_item_info_impl_code->MakeFunctionCaller (get_thread_item_info_return_type,
+ get_thread_item_info_arglist,
+ error);
+ if (error.Fail())
{
if (log)
- log->Printf ("Error compiling get-thread-item-info function: \"%s\".", errors.GetData());
+ log->Printf ("Failed to install get-thread-item-info introspection caller: %s.", error.AsCString());
+ m_get_thread_item_info_impl_code.reset();
return args_addr;
}
- errors.Clear();
- if (!m_get_thread_item_info_function->WriteFunctionWrapper(exe_ctx, errors))
- {
- if (log)
- log->Printf ("Error Inserting get-thread-item-info function: \"%s\".", errors.GetData());
- return args_addr;
- }
+ }
+ else
+ {
+ get_thread_item_info_caller = m_get_thread_item_info_impl_code->GetFunctionCaller();
}
}
@@ -248,7 +220,7 @@ AppleGetThreadItemInfoHandler::SetupGetThreadItemInfoFunction (Thread &thread, V
// if other threads were calling into here, but actually it isn't because we allocate a new args structure for
// this call by passing args_addr = LLDB_INVALID_ADDRESS...
- if (!m_get_thread_item_info_function->WriteFunctionArguments (exe_ctx, args_addr, impl_code_address, get_thread_item_info_arglist, errors))
+ if (!get_thread_item_info_caller->WriteFunctionArguments (exe_ctx, args_addr, get_thread_item_info_arglist, errors))
{
if (log)
log->Printf ("Error writing get-thread-item-info function arguments: \"%s\".", errors.GetData());
@@ -360,6 +332,8 @@ AppleGetThreadItemInfoHandler::GetThreadItemInfo (Thread &thread, tid_t thread_i
StreamString errors;
ExecutionContext exe_ctx;
EvaluateExpressionOptions options;
+ FunctionCaller *get_thread_item_info_caller = nullptr;
+
options.SetUnwindOnError (true);
options.SetIgnoreBreakpoints (true);
options.SetStopOthers (true);
@@ -367,16 +341,23 @@ AppleGetThreadItemInfoHandler::GetThreadItemInfo (Thread &thread, tid_t thread_i
options.SetTryAllThreads (false);
thread.CalculateExecutionContext (exe_ctx);
- if (m_get_thread_item_info_function == NULL)
+ if (!m_get_thread_item_info_impl_code)
{
error.SetErrorString ("Unable to compile function to call __introspection_dispatch_thread_get_item_info");
return return_value;
}
+ get_thread_item_info_caller = m_get_thread_item_info_impl_code->GetFunctionCaller();
+
+ if (!get_thread_item_info_caller)
+ {
+ error.SetErrorString ("Unable to compile function caller for __introspection_dispatch_thread_get_item_info");
+ return return_value;
+ }
ExpressionResults func_call_ret;
Value results;
- func_call_ret = m_get_thread_item_info_function->ExecuteFunction (exe_ctx, &args_addr, options, errors, results);
+ func_call_ret = get_thread_item_info_caller->ExecuteFunction (exe_ctx, &args_addr, options, errors, results);
if (func_call_ret != eExpressionCompleted || !error.Success())
{
if (log)
diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.h b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.h
index 6ced39ae851..c1798fb515b 100644
--- a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.h
+++ b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.h
@@ -18,11 +18,10 @@
// Project includes
#include "lldb/lldb-public.h"
#include "lldb/Core/Error.h"
-#include "lldb/Expression/ClangFunction.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Symbol/CompilerType.h"
-// This class will insert a ClangUtilityFunction into the inferior process for
+// This class will insert a UtilityFunction into the inferior process for
// calling libBacktraceRecording's __introspection_dispatch_thread_get_item_info()
// function. The function in the inferior will return a struct by value
// with these members:
@@ -37,7 +36,7 @@
// space (item_buffer_size in size) which must be mach_vm_deallocate'd by
// lldb.
//
-// The AppleGetThreadItemInfoHandler object should persist so that the ClangUtilityFunction
+// The AppleGetThreadItemInfoHandler object should persist so that the UtilityFunction
// can be reused multiple times.
namespace lldb_private
@@ -101,8 +100,7 @@ private:
static const char *g_get_thread_item_info_function_code;
lldb_private::Process *m_process;
- std::unique_ptr<ClangFunction> m_get_thread_item_info_function;
- std::unique_ptr<ClangUtilityFunction> m_get_thread_item_info_impl_code;
+ std::unique_ptr<UtilityFunction> m_get_thread_item_info_impl_code;
Mutex m_get_thread_item_info_function_mutex;
lldb::addr_t m_get_thread_item_info_return_buffer_addr;
diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp b/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp
index 90271f29c71..11b47df87d0 100644
--- a/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp
+++ b/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp
@@ -17,8 +17,6 @@
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/StreamString.h"
-#include "lldb/Expression/ClangFunction.h"
-#include "lldb/Expression/ClangUtilityFunction.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ObjectFile.h"
diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp
index b7157bd9aac..ccff1c19431 100644
--- a/lldb/source/Symbol/ClangASTContext.cpp
+++ b/lldb/source/Symbol/ClangASTContext.cpp
@@ -69,14 +69,20 @@
#include "lldb/Core/ThreadSafeDenseMap.h"
#include "lldb/Core/UniqueCStringMap.h"
#include "lldb/Expression/ASTDumper.h"
+#include "lldb/Expression/ASTResultSynthesizer.h"
+#include "lldb/Expression/ClangExpressionDeclMap.h"
+#include "lldb/Expression/ClangUserExpression.h"
+#include "lldb/Expression/ClangFunctionCaller.h"
+#include "lldb/Expression/ClangUtilityFunction.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/ClangExternalASTSourceCallbacks.h"
#include "lldb/Symbol/ClangExternalASTSourceCommon.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/VerifyDecl.h"
#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/Process.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
#include "Plugins/SymbolFile/DWARF/DWARFASTParserClang.h"
@@ -8942,3 +8948,49 @@ ClangASTContext::DeclContextGetClangASTContext (const CompilerDeclContext &dc)
return nullptr;
}
+ClangASTContextForExpressions::ClangASTContextForExpressions (Target &target) :
+ ClangASTContext (target.GetArchitecture().GetTriple().getTriple().c_str()),
+ m_target_wp(target.shared_from_this())
+{
+}
+
+UserExpression *
+ClangASTContextForExpressions::GetUserExpression (const char *expr,
+ const char *expr_prefix,
+ lldb::LanguageType language,
+ Expression::ResultType desired_type)
+{
+ TargetSP target_sp = m_target_wp.lock();
+ if (!target_sp)
+ return nullptr;
+
+ return new ClangUserExpression(*target_sp.get(), expr, expr_prefix, language, desired_type);
+}
+
+FunctionCaller *
+ClangASTContextForExpressions::GetFunctionCaller (const CompilerType &return_type,
+ const Address& function_address,
+ const ValueList &arg_value_list,
+ const char *name)
+{
+ TargetSP target_sp = m_target_wp.lock();
+ if (!target_sp)
+ return nullptr;
+
+ Process *process = target_sp->GetProcessSP().get();
+ if (!process)
+ return nullptr;
+
+ return new ClangFunctionCaller (*process, return_type, function_address, arg_value_list, name);
+}
+
+UtilityFunction *
+ClangASTContextForExpressions::GetUtilityFunction (const char *text,
+ const char *name)
+{
+ TargetSP target_sp = m_target_wp.lock();
+ if (!target_sp)
+ return nullptr;
+
+ return new ClangUtilityFunction(*target_sp.get(), text, name);
+}
diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp
index 0fd8d53a24e..e2bb2e48c41 100644
--- a/lldb/source/Target/Process.cpp
+++ b/lldb/source/Target/Process.cpp
@@ -18,7 +18,7 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/State.h"
#include "lldb/Core/StreamFile.h"
-#include "lldb/Expression/ClangUserExpression.h"
+#include "lldb/Expression/UserExpression.h"
#include "lldb/Expression/IRDynamicChecks.h"
#include "lldb/Host/ConnectionFileDescriptor.h"
#include "lldb/Host/Host.h"
@@ -1917,6 +1917,7 @@ Process::LoadImage (const FileSpec &image_spec, Error &error)
expr_options.SetIgnoreBreakpoints(true);
expr_options.SetExecutionPolicy(eExecutionPolicyAlways);
expr_options.SetResultIsInternal(true);
+ expr_options.SetLanguage(eLanguageTypeC_plus_plus);
StreamString expr;
expr.Printf(R"(
@@ -1939,12 +1940,12 @@ Process::LoadImage (const FileSpec &image_spec, Error &error)
)";
lldb::ValueObjectSP result_valobj_sp;
Error expr_error;
- ClangUserExpression::Evaluate (exe_ctx,
- expr_options,
- expr.GetData(),
- prefix,
- result_valobj_sp,
- expr_error);
+ UserExpression::Evaluate (exe_ctx,
+ expr_options,
+ expr.GetData(),
+ prefix,
+ result_valobj_sp,
+ expr_error);
if (expr_error.Success())
{
error = result_valobj_sp->GetError();
@@ -2044,17 +2045,19 @@ Process::UnloadImage (uint32_t image_token)
expr_options.SetUnwindOnError(true);
expr_options.SetIgnoreBreakpoints(true);
expr_options.SetExecutionPolicy(eExecutionPolicyAlways);
+ expr_options.SetLanguage(eLanguageTypeC_plus_plus);
+
StreamString expr;
expr.Printf("dlclose ((void *)0x%" PRIx64 ")", image_addr);
const char *prefix = "extern \"C\" int dlclose(void* handle);\n";
lldb::ValueObjectSP result_valobj_sp;
Error expr_error;
- ClangUserExpression::Evaluate (exe_ctx,
- expr_options,
- expr.GetData(),
- prefix,
- result_valobj_sp,
- expr_error);
+ UserExpression::Evaluate (exe_ctx,
+ expr_options,
+ expr.GetData(),
+ prefix,
+ result_valobj_sp,
+ expr_error);
if (result_valobj_sp->GetError().Success())
{
Scalar scalar;
diff --git a/lldb/source/Target/StopInfo.cpp b/lldb/source/Target/StopInfo.cpp
index 00fd79aa8fd..fc1cb9af238 100644
--- a/lldb/source/Target/StopInfo.cpp
+++ b/lldb/source/Target/StopInfo.cpp
@@ -23,7 +23,7 @@
#include "lldb/Core/Debugger.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/ValueObject.h"
-#include "lldb/Expression/ClangUserExpression.h"
+#include "lldb/Expression/UserExpression.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h"
@@ -770,12 +770,13 @@ protected:
expr_options.SetIgnoreBreakpoints(true);
ValueObjectSP result_value_sp;
Error error;
- result_code = ClangUserExpression::Evaluate (exe_ctx,
- expr_options,
- wp_sp->GetConditionText(),
- NULL,
- result_value_sp,
- error);
+ result_code = UserExpression::Evaluate (exe_ctx,
+ expr_options,
+ wp_sp->GetConditionText(),
+ NULL,
+ result_value_sp,
+ error);
+
if (result_code == eExpressionCompleted)
{
if (result_value_sp)
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index aca6605f2af..993706fa889 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -33,7 +33,7 @@
#include "lldb/Core/ValueObject.h"
#include "lldb/Expression/ClangASTSource.h"
#include "lldb/Expression/ClangPersistentVariables.h"
-#include "lldb/Expression/ClangUserExpression.h"
+#include "lldb/Expression/UserExpression.h"
#include "lldb/Expression/ClangModulesDeclVendor.h"
#include "lldb/Host/FileSpec.h"
#include "lldb/Host/Host.h"
@@ -46,6 +46,7 @@
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
+#include "lldb/Target/Language.h"
#include "lldb/Target/LanguageRuntime.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Process.h"
@@ -1891,13 +1892,95 @@ Target::ImageSearchPathsChanged
target->SetExecutableModule (exe_module_sp, true);
}
+TypeSystem *
+Target::GetScratchTypeSystemForLanguage (lldb::LanguageType language, bool create_on_demand)
+{
+ if (Language::LanguageIsC(language)
+ || Language::LanguageIsObjC(language)
+ || Language::LanguageIsCPlusPlus(language)
+ || language == eLanguageTypeUnknown)
+ return GetScratchClangASTContext(create_on_demand);
+ else
+ return NULL;
+}
+
+UserExpression *
+Target::GetUserExpressionForLanguage(const char *expr,
+ const char *expr_prefix,
+ lldb::LanguageType language,
+ Expression::ResultType desired_type,
+ Error &error)
+{
+ TypeSystem *type_system = GetScratchTypeSystemForLanguage (language);
+ UserExpression *user_expr = nullptr;
+
+ if (!type_system)
+ {
+ error.SetErrorStringWithFormat("Could not find type system for language: %s", Language::GetNameForLanguageType(language));
+ return nullptr;
+ }
+
+ user_expr = type_system->GetUserExpression(expr, expr_prefix, language, desired_type);
+ if (!user_expr)
+ error.SetErrorStringWithFormat("Could not create an expression for language %s", Language::GetNameForLanguageType(language));
+
+ return user_expr;
+}
+
+FunctionCaller *
+Target::GetFunctionCallerForLanguage (lldb::LanguageType language,
+ const CompilerType &return_type,
+ const Address& function_address,
+ const ValueList &arg_value_list,
+ const char *name,
+ Error &error)
+{
+ TypeSystem *type_system = GetScratchTypeSystemForLanguage (language);
+ FunctionCaller *persistent_fn = nullptr;
+
+ if (!type_system)
+ {
+ error.SetErrorStringWithFormat("Could not find type system for language: %s", Language::GetNameForLanguageType(language));
+ return persistent_fn;
+ }
+
+ persistent_fn = type_system->GetFunctionCaller (return_type, function_address, arg_value_list, name);
+ if (!persistent_fn)
+ error.SetErrorStringWithFormat("Could not create an expression for language %s", Language::GetNameForLanguageType(language));
+
+ return persistent_fn;
+}
+
+UtilityFunction *
+Target::GetUtilityFunctionForLanguage (const char *text,
+ lldb::LanguageType language,
+ const char *name,
+ Error &error)
+{
+ TypeSystem *type_system = GetScratchTypeSystemForLanguage (language);
+ UtilityFunction *utility_fn = nullptr;
+
+ if (!type_system)
+ {
+ error.SetErrorStringWithFormat("Could not find type system for language: %s", Language::GetNameForLanguageType(language));
+ return utility_fn;
+ }
+
+ utility_fn = type_system->GetUtilityFunction (text, name);
+ if (!utility_fn)
+ error.SetErrorStringWithFormat("Could not create an expression for language %s", Language::GetNameForLanguageType(language));
+
+ return utility_fn;
+}
+
+
ClangASTContext *
Target::GetScratchClangASTContext(bool create_on_demand)
{
// Now see if we know the target triple, and if so, create our scratch AST context:
if (m_scratch_ast_context_ap.get() == NULL && m_arch.IsValid() && create_on_demand)
{
- m_scratch_ast_context_ap.reset (new ClangASTContext(m_arch.GetTriple().str().c_str()));
+ m_scratch_ast_context_ap.reset (new ClangASTContextForExpressions(*this));
m_scratch_ast_source_ap.reset (new ClangASTSource(shared_from_this()));
m_scratch_ast_source_ap->InstallASTContext(m_scratch_ast_context_ap->getASTContext());
llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> proxy_ast_source(m_scratch_ast_source_ap->CreateProxy());
@@ -1906,27 +1989,6 @@ Target::GetScratchClangASTContext(bool create_on_demand)
return m_scratch_ast_context_ap.get();
}
-TypeSystem*
-Target::GetTypeSystemForLanguage (lldb::LanguageType language)
-{
- switch (language)
- {
- case lldb::eLanguageTypeC:
- case lldb::eLanguageTypeC11:
- case lldb::eLanguageTypeC89:
- case lldb::eLanguageTypeC99:
- case lldb::eLanguageTypeC_plus_plus:
- case lldb::eLanguageTypeC_plus_plus_03:
- case lldb::eLanguageTypeC_plus_plus_11:
- case lldb::eLanguageTypeC_plus_plus_14:
- case lldb::eLanguageTypeObjC:
- case lldb::eLanguageTypeObjC_plus_plus:
- return GetScratchClangASTContext(true);
- default:
- return nullptr;
- }
-}
-
ClangASTImporter *
Target::GetClangASTImporter()
{
@@ -2067,12 +2129,12 @@ Target::EvaluateExpression
{
const char *prefix = GetExpressionPrefixContentsAsCString();
Error error;
- execution_results = ClangUserExpression::Evaluate (exe_ctx,
- options,
- expr_cstr,
- prefix,
- result_valobj_sp,
- error);
+ execution_results = UserExpression::Evaluate (exe_ctx,
+ options,
+ expr_cstr,
+ prefix,
+ result_valobj_sp,
+ error);
}
m_suppress_stop_hooks = old_suppress_value;
diff --git a/lldb/source/Target/ThreadPlanCallUserExpression.cpp b/lldb/source/Target/ThreadPlanCallUserExpression.cpp
index 3ec3284afb4..b24f74b10df 100644
--- a/lldb/source/Target/ThreadPlanCallUserExpression.cpp
+++ b/lldb/source/Target/ThreadPlanCallUserExpression.cpp
@@ -19,7 +19,7 @@
#include "lldb/Core/Address.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Stream.h"
-#include "lldb/Expression/ClangUserExpression.h"
+#include "lldb/Expression/UserExpression.h"
#include "lldb/Expression/IRDynamicChecks.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Target/LanguageRuntime.h"
@@ -41,7 +41,7 @@ ThreadPlanCallUserExpression::ThreadPlanCallUserExpression (Thread &thread,
Address &function,
llvm::ArrayRef<lldb::addr_t> args,
const EvaluateExpressionOptions &options,
- lldb::ClangUserExpressionSP &user_expression_sp) :
+ lldb::UserExpressionSP &user_expression_sp) :
ThreadPlanCallFunction (thread, function, CompilerType(), args, options),
m_user_expression_sp (user_expression_sp)
{
OpenPOWER on IntegriCloud