Oke got that figured out. Attached patch works perfectly and stores the cached functions in the Target. I've managed to make the changes in existing classes minimal by creating a ClangFunction subclass.

comments welcome.

--
Carlo Kok
RemObjects Software
Index: include/lldb/API/SBExpressionOptions.h
===================================================================
--- include/lldb/API/SBExpressionOptions.h      (revision 219490)
+++ include/lldb/API/SBExpressionOptions.h      (working copy)
@@ -118,6 +118,8 @@
     friend class SBFrame;
     friend class SBValue;
     friend class SBTarget;
+    friend class SBTypeMemberFunction;
+    friend class SBFunction;
 
 private:
     // This auto_pointer is made in the constructor and is always valid.
Index: include/lldb/API/SBFrame.h
===================================================================
--- include/lldb/API/SBFrame.h  (revision 219490)
+++ include/lldb/API/SBFrame.h  (working copy)
@@ -210,6 +210,8 @@
     friend class SBInstruction;
     friend class SBThread;
     friend class SBValue;
+    friend class SBTypeMemberFunction;
+    friend class SBFunction;
 #ifndef LLDB_DISABLE_PYTHON
     friend class lldb_private::ScriptInterpreterPython;
 #endif
Index: include/lldb/API/SBFunction.h
===================================================================
--- include/lldb/API/SBFunction.h       (revision 219490)
+++ include/lldb/API/SBFunction.h       (working copy)
@@ -68,6 +68,13 @@
     bool
     GetDescription (lldb::SBStream &description);
 
+    lldb::SBValue ExecuteFunction(lldb::SBFrame &frame,
+                                  lldb::SBValueList arguments,
+                                  lldb::SBStream &errors,
+                                  lldb::SBExpressionOptions options,
+                                  bool reusable);
+
+    void RemoveReusableFunction (lldb::SBTarget &target);
 protected:
 
     lldb_private::Function *
Index: include/lldb/API/SBTarget.h
===================================================================
--- include/lldb/API/SBTarget.h (revision 219490)
+++ include/lldb/API/SBTarget.h (working copy)
@@ -942,6 +942,7 @@
     friend class SBSourceManager;
     friend class SBSymbol;
     friend class SBValue;
+    friend class SBTypeMemberFunction;
 
     //------------------------------------------------------------------
     // Constructors are private, use static Target::Create function to
Index: include/lldb/API/SBType.h
===================================================================
--- include/lldb/API/SBType.h   (revision 219490)
+++ include/lldb/API/SBType.h   (working copy)
@@ -104,7 +104,15 @@
     bool
     GetDescription (lldb::SBStream &description,
                     lldb::DescriptionLevel description_level);
-    
+
+    lldb::SBValue ExecuteFunction (lldb::SBFrame &frame,
+                                   lldb::SBValue self,
+                                   lldb::SBValueList arguments,
+                                   lldb::SBStream &errors,
+                                   lldb::SBExpressionOptions options,
+                                   bool reusable);
+
+    void RemoveReusableFunction(lldb::SBTarget& target);
 protected:
     friend class SBType;
     
Index: include/lldb/Expression/ClangFunction.h
===================================================================
--- include/lldb/Expression/ClangFunction.h     (revision 219490)
+++ include/lldb/Expression/ClangFunction.h     (working copy)
@@ -23,6 +23,7 @@
 #include "lldb/Core/ValueObjectList.h"
 #include "lldb/Expression/ClangExpression.h"
 #include "lldb/Target/Process.h"
+#include "lldb/Target/ExecutionContext.h"
 
 namespace lldb_private
 {
@@ -133,7 +134,7 @@
     /// @return
     ///     The number of errors.
     //------------------------------------------------------------------
-    unsigned
+    virtual unsigned
     CompileFunction (Stream &errors);
     
     //------------------------------------------------------------------
@@ -406,7 +407,13 @@
     {
         return m_arg_values;
     }
-private:
+
+    Address
+    GetFunctionAddress() const
+    {
+        return m_function_addr;
+    }
+protected:
     //------------------------------------------------------------------
     // For ClangFunction only
     //------------------------------------------------------------------
@@ -443,6 +450,76 @@
     bool                            m_JITted;                       ///< True 
if the wrapper function has already been JIT-compiled.
 };
 
+class ClangFunctionWithDeclMap : public ClangFunction
+{
+public:
+    //------------------------------------------------------------------
+    /// Constructor
+    ///
+    /// @param[in] exe_scope
+    ///     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().
+    //------------------------------------------------------------------  
+    ClangFunctionWithDeclMap (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.
+    ///
+    /// @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().
+    //------------------------------------------------------------------
+    ClangFunctionWithDeclMap (ExecutionContextScope &exe_scope,
+        const ClangASTType &return_type,
+        const Address& function_address,
+        const ValueList &arg_value_list,
+        const char *name);
+
+    ClangExpressionDeclMap *
+        DeclMap ()
+    {
+        return m_expr_decl_map.get();
+    }
+
+    unsigned
+    CompileFunction (Stream &errors);
+
+private:
+    ExecutionContext m_context;
+    std::shared_ptr<Materializer> m_materializer;
+    std::unique_ptr<ClangExpressionDeclMap>     m_expr_decl_map;        ///< 
The map to use when parsing the expression.
+
+};
+
 } // Namespace lldb_private
 
 #endif  // lldb_ClangFunction_h_
Index: include/lldb/Target/ObjCLanguageRuntime.h
===================================================================
--- include/lldb/Target/ObjCLanguageRuntime.h   (revision 219490)
+++ include/lldb/Target/ObjCLanguageRuntime.h   (working copy)
@@ -510,6 +510,11 @@
     {
         m_negative_complete_class_cache.clear();
     }
+
+
+    lldb::addr_t
+    GetSelectorFor(const ConstString& value, ExecutionContextScope *exe_scope);
+
     
 protected:
     //------------------------------------------------------------------
@@ -607,11 +612,13 @@
     typedef std::multimap<uint32_t, ObjCISA> HashToISAMap;
     typedef ISAToDescriptorMap::iterator ISAToDescriptorIterator;
     typedef HashToISAMap::iterator HashToISAIterator;
+    typedef std::map<ConstString, lldb::addr_t> SelectorMap;
 
     MsgImplMap m_impl_cache;
     LazyBool m_has_new_literals_and_indexing;
     ISAToDescriptorMap m_isa_to_descriptor;
     HashToISAMap m_hash_to_isa_map;
+    SelectorMap m_selector_map;
 
 protected:
     uint32_t m_isa_to_descriptor_stop_id;
Index: include/lldb/Target/Target.h
===================================================================
--- include/lldb/Target/Target.h        (revision 219490)
+++ include/lldb/Target/Target.h        (working copy)
@@ -1345,6 +1345,25 @@
     lldb::SearchFilterSP
     GetSearchFilterForModuleAndCUList (const FileSpecList *containingModules, 
const FileSpecList *containingSourceFiles);
 
+    std::shared_ptr<ClangFunction>& GetOrAddClangFunction (Function* func)
+    {
+        return m_clang_functions[func];
+    }
+
+    std::shared_ptr<ClangFunction>& GetOrAddClangFunction 
(TypeMemberFunctionImpl* func)
+    {
+        return m_clang_functions[func];
+    }
+
+    void RemoveClangFunction (Function* func)
+    {
+        m_clang_functions.erase (func);
+    }
+
+    void RemoveClangFunction (TypeMemberFunctionImpl* func)
+    {
+        m_clang_functions.erase (func);
+    }
 protected:
     //------------------------------------------------------------------
     // Member variables.
@@ -1378,6 +1397,9 @@
     lldb::user_id_t         m_stop_hook_next_id;
     bool                    m_valid;
     bool                    m_suppress_stop_hooks;
+    typedef std::map<void*, std::shared_ptr<ClangFunction>> 
ClangFunctionCollection;
+    ClangFunctionCollection m_clang_functions;
+
     
     static void
     ImageSearchPathsChanged (const PathMappingList &path_list,
Index: scripts/Python/interface/SBFunction.i
===================================================================
--- scripts/Python/interface/SBFunction.i       (revision 219490)
+++ scripts/Python/interface/SBFunction.i       (working copy)
@@ -85,7 +85,15 @@
 
     bool
     GetDescription (lldb::SBStream &description);
-    
+
+    lldb::SBValue ExecuteFunction(lldb::SBFrame &frame,
+                                  lldb::SBValueList arguments,
+                                  lldb::SBStream &errors,
+                                  lldb::SBExpressionOptions options,
+                                  bool reusable);
+
+    void RemoveReusableFunction (lldb::SBTarget &target);      
+
     bool
     operator == (const lldb::SBFunction &rhs) const;
     
Index: scripts/Python/interface/SBType.i
===================================================================
--- scripts/Python/interface/SBType.i   (revision 219490)
+++ scripts/Python/interface/SBType.i   (working copy)
@@ -101,7 +101,15 @@
     bool
     GetDescription (lldb::SBStream &description,
                     lldb::DescriptionLevel description_level);
-    
+
+    lldb::SBValue ExecuteFunction (lldb::SBFrame &frame,
+                                   lldb::SBValue self,
+                                   lldb::SBValueList arguments,
+                                   lldb::SBStream &errors,
+                                   lldb::SBExpressionOptions options,
+                                   bool reusable);
+
+    void RemoveReusableFunction(lldb::SBTarget& target);                       
                
 protected:
     lldb::TypeMemberFunctionImplSP m_opaque_sp;
 };
Index: source/API/SBFunction.cpp
===================================================================
--- source/API/SBFunction.cpp   (revision 219490)
+++ source/API/SBFunction.cpp   (working copy)
@@ -18,6 +18,12 @@
 #include "lldb/Symbol/Type.h"
 #include "lldb/Target/ExecutionContext.h"
 #include "lldb/Target/Target.h"
+#include "lldb/API/SBExpressionOptions.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/API/SBFrame.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Expression/ClangFunction.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -229,3 +235,79 @@
 
 
 
+lldb::SBValue SBFunction::ExecuteFunction(lldb::SBFrame &frame,
+    lldb::SBValueList arguments,
+    lldb::SBStream &errors,
+    lldb::SBExpressionOptions options,
+    bool reusable)
+{
+    if (!m_opaque_ptr)
+    {
+        errors->PutCString("no value");
+        return SBValue();
+    }
+
+    ExecutionContext exe_ctx = frame.GetFrameSP();
+
+    if (!exe_ctx.GetFrameSP())
+    {
+        errors->PutCString("no frame");
+        return SBValue();
+    }
+
+    ValueList args;
+    for (int i = 0; i < arguments.GetSize(); i++)
+    {
+        const ValueObjectSP value = arguments.GetValueAtIndex(i).GetSP();
+        value->UpdateValueIfNeeded();
+        args.PushValue(value->GetValue());
+    }
+    //arguments.
+    
+    std::shared_ptr<ClangFunction>& func = exe_ctx.GetTargetPtr 
()->GetOrAddClangFunction (m_opaque_ptr);
+
+    if (!func)
+    {
+        func.reset (new ClangFunctionWithDeclMap (*frame.GetFrameSP (),
+            m_opaque_ptr->GetClangType ().GetFunctionReturnType (),
+            m_opaque_ptr->GetAddressRange ().GetBaseAddress (),
+            args,
+            m_opaque_ptr->GetName ().GetCString ()));
+
+        if (func->CompileFunction (*errors.get ()))
+            return SBValue ();
+
+        if (!func->WriteFunctionWrapper (exe_ctx, *errors.get ()))
+            return SBValue ();
+    }
+    errors.Clear ();
+
+    lldb::addr_t args_addr = LLDB_INVALID_ADDRESS;
+    if (!func->WriteFunctionArguments (exe_ctx, args_addr,
+        func->GetFunctionAddress (), args, *errors.get ()))
+    {
+        return SBValue ();
+    }
+
+    Value res;
+    if (func->ExecuteFunction (exe_ctx, &args_addr, *options.get (), 
*errors.get (), res))
+    {
+        func->DeallocateFunctionResults (exe_ctx, args_addr);
+        if (!reusable)
+            exe_ctx.GetTargetPtr ()->RemoveClangFunction (m_opaque_ptr);
+        return SBValue ();
+    }
+
+    SBValue results = ValueObjectConstResult::Create (exe_ctx.GetThreadPtr(), 
res, ConstString ("<evaluation result>"));
+
+    func->DeallocateFunctionResults (exe_ctx, args_addr);
+    if (!reusable)
+        exe_ctx.GetTargetPtr ()->RemoveClangFunction (m_opaque_ptr);
+    return results;
+}
+
+void SBFunction::RemoveReusableFunction (lldb::SBTarget &target)
+{
+    if (target.m_opaque_sp)
+        target.m_opaque_sp->RemoveClangFunction (m_opaque_ptr);
+}
\ No newline at end of file
Index: source/API/SBType.cpp
===================================================================
--- source/API/SBType.cpp       (revision 219490)
+++ source/API/SBType.cpp       (working copy)
@@ -17,6 +17,22 @@
 #include "lldb/Symbol/ClangASTContext.h"
 #include "lldb/Symbol/ClangASTType.h"
 #include "lldb/Symbol/Type.h"
+#include "lldb/API/SBValue.h"
+#include "lldb/API/SBValueList.h"
+#include "lldb/API/SBExpressionOptions.h"
+#include "lldb/API/SBError.h"
+#include "lldb/API/SBFrame.h"
+#include "lldb/Expression/ClangFunction.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/API/SBValueList.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Core/ValueObject.h"
+#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Symbol/Symbol.h"
+#include "lldb/API/SBTarget.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
 
 #include "clang/AST/Decl.h"
 
@@ -821,3 +837,106 @@
 {
     return *m_opaque_sp.get();
 }
+
+void SBTypeMemberFunction::RemoveReusableFunction (lldb::SBTarget& target)
+{
+    if (target.m_opaque_sp)
+        target.m_opaque_sp->RemoveClangFunction (m_opaque_sp.get ());
+}
+
+lldb::SBValue SBTypeMemberFunction::ExecuteFunction (lldb::SBFrame &frame,
+    lldb::SBValue self,
+    lldb::SBValueList arguments,
+    lldb::SBStream &errors,
+    lldb::SBExpressionOptions options,
+    bool reusable)
+{
+    if (!m_opaque_sp)
+    {
+        errors->PutCString ("no value");
+        return SBValue ();
+    }
+    if (!self.IsValid ())
+    {
+        errors->PutCString ("No self");
+        return SBValue ();
+    }
+
+    if (!frame.GetFrameSP ())
+    {
+        errors->PutCString ("no frame");
+        return SBValue ();
+    }
+
+    ExecutionContext exe_ctx;
+    frame.GetFrameSP ()->CalculateExecutionContext (exe_ctx);
+
+    TypeMemberFunctionImpl& val = *m_opaque_sp.get ();
+
+    ValueList args;
+    ClangASTContext* ast = exe_ctx.GetTargetPtr ()->GetScratchClangASTContext 
();
+    ClangASTType pointertype = ast->GetCStringType (true);
+    ValueObjectSP selfptr = self.GetSP ()->Cast (pointertype);
+    selfptr->UpdateValueIfNeeded ();
+    args.PushValue (selfptr->GetValue ());
+
+    uint64_t sel = exe_ctx.GetProcessPtr ()->GetObjCLanguageRuntime 
()->GetSelectorFor (ConstString (m_opaque_sp->GetName ()), exe_ctx.GetFramePtr 
());
+    Value selectorvalue (ast->GetPointerByteSize () == 4 ? Scalar 
((uint32_t)sel) : Scalar (sel));
+    selectorvalue.SetClangType (pointertype);
+    args.PushValue (selectorvalue);
+
+
+    for (int i = 0; i < arguments.GetSize (); i++)  {
+        const ValueObjectSP value = arguments.GetValueAtIndex (i).GetSP ();
+        value->UpdateValueIfNeeded ();
+        args.PushValue (value->GetValue ());
+    }
+
+    std::shared_ptr<ClangFunction>& func = exe_ctx.GetTargetPtr 
()->GetOrAddClangFunction (m_opaque_sp.get ());
+
+    if (!func)
+    {
+        SymbolContextList sclist;
+        exe_ctx.GetTargetPtr ()->GetImages ().FindFunctions (ConstString 
("objc_msgSend"), eFunctionNameTypeAny,
+            true, false, true, sclist);
+        if (!sclist.GetSize ()) {
+            errors->PutCString ("Cannot find msgSend");
+            return SBValue ();
+        }
+        Address* msgsend_address = &sclist[0].symbol->GetAddress ();
+        func.reset (new ClangFunctionWithDeclMap (*frame.GetFrameSP (),
+            m_opaque_sp->GetReturnType (),
+            *msgsend_address,
+            args,
+            m_opaque_sp->GetName ().GetCString ()));
+
+
+        if (func->CompileFunction (*errors.get ()))
+            return SBValue ();
+
+        if (!func->WriteFunctionWrapper (exe_ctx, *errors.get ()))
+            return SBValue ();
+    }
+    errors.Clear ();
+
+    lldb::addr_t args_addr = LLDB_INVALID_ADDRESS;
+    if (!func->WriteFunctionArguments (exe_ctx, args_addr,
+        func->GetFunctionAddress (), args, *errors.get ()))
+    {
+        return SBValue ();
+    }
+
+    Value res;
+    if (func->ExecuteFunction (exe_ctx, &args_addr, *options.get (), 
*errors.get (), res))
+    {
+        func->DeallocateFunctionResults (exe_ctx, args_addr);
+        if (!reusable)
+            exe_ctx.GetTargetPtr ()->RemoveClangFunction (m_opaque_sp.get ());
+        return SBValue ();
+    }
+
+    func->DeallocateFunctionResults (exe_ctx, args_addr);
+    if (!reusable)
+        exe_ctx.GetTargetPtr ()->RemoveClangFunction (m_opaque_sp.get ());
+    return ValueObjectConstResult::Create (exe_ctx.GetThreadPtr (), res, 
ConstString ("<evaluation result>"));
+}
Index: source/Expression/ClangFunction.cpp
===================================================================
--- source/Expression/ClangFunction.cpp (revision 219490)
+++ source/Expression/ClangFunction.cpp (working copy)
@@ -43,6 +43,7 @@
 #include "lldb/Target/Thread.h"
 #include "lldb/Target/ThreadPlan.h"
 #include "lldb/Target/ThreadPlanCallFunction.h"
+#include "lldb/Expression/ClangExpressionDeclMap.h"
 
 using namespace lldb_private;
 
@@ -594,3 +595,48 @@
     
     return m_struct_extractor.get();
 }
+
+
+ClangFunctionWithDeclMap::ClangFunctionWithDeclMap (ExecutionContextScope 
&exe_scope,
+    Function &function_ptr,
+    ClangASTContext *ast_context,
+    const ValueList &arg_value_list,
+    const char *name)
+    : ClangFunction (exe_scope, function_ptr, ast_context, arg_value_list, 
name)
+{
+    exe_scope.CalculateExecutionContext (m_context);
+    // ClangASTSource depends on the struct name starting with $ for external 
lookups
+    m_wrapper_struct_name = "$__lldb_caller_struct"; 
+}
+
+ClangFunctionWithDeclMap::ClangFunctionWithDeclMap (ExecutionContextScope 
&exe_scope,
+    const ClangASTType &return_type,
+    const Address& function_address,
+    const ValueList &arg_value_list,
+    const char *name)
+
+    : ClangFunction (exe_scope, return_type, function_address, arg_value_list, 
name)
+{
+    exe_scope.CalculateExecutionContext (m_context);
+    // ClangASTSource depends on the struct name starting with $ for external 
lookups
+    m_wrapper_struct_name = "$__lldb_caller_struct";
+}
+
+
+unsigned ClangFunctionWithDeclMap::CompileFunction (Stream &errors)
+{
+    if (!m_materializer)
+        m_materializer.reset (new Materializer ());
+    
+    if (!m_expr_decl_map) 
+        m_expr_decl_map.reset (new ClangExpressionDeclMap (false, m_context));
+        
+    if (!m_expr_decl_map->WillParse (m_context, m_materializer.get ()))
+    {
+        errors.PutCString ("Could not materialize");
+        return 1;
+    }
+    unsigned res = ClangFunction::CompileFunction (errors);
+
+    return res;
+}
\ No newline at end of file
Index: source/Target/ObjCLanguageRuntime.cpp
===================================================================
--- source/Target/ObjCLanguageRuntime.cpp       (revision 219490)
+++ source/Target/ObjCLanguageRuntime.cpp       (working copy)
@@ -19,6 +19,7 @@
 #include "lldb/Symbol/TypeList.h"
 #include "lldb/Target/ObjCLanguageRuntime.h"
 #include "lldb/Target/Target.h"
+#include "lldb/Core/ValueObjectConstResult.h"
 
 #include "llvm/ADT/StringRef.h"
 
@@ -626,3 +627,22 @@
 {
     return nullptr;
 }
+
+lldb::addr_t
+ObjCLanguageRuntime::GetSelectorFor (const ConstString& value, 
ExecutionContextScope *exe_scope)
+{
+    auto res = m_selector_map.find (value);
+    if (res != m_selector_map.end ())
+        return res->second;
+
+    ValueList args;
+    std::string selector;
+    selector = selector + "((void* (*)(char*))sel_registerName)(\"" + 
value.AsCString () + "\")";
+    ValueObjectSP selectorptr;
+    exe_scope->CalculateTarget ()->EvaluateExpression (selector.c_str (), 
exe_scope->CalculateStackFrame ().get (), selectorptr);
+
+    addr_t result = selectorptr->GetValueAsUnsigned (0);
+    if (result)
+        m_selector_map[value] = result;
+    return result;
+}
\ No newline at end of file
_______________________________________________
lldb-dev mailing list
lldb-dev@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-dev

Reply via email to