[Lldb-commits] [lldb] r114384 - in /lldb/trunk: include/lldb/Expression/ include/lldb/Target/ source/Expression/ source/Plugins/ABI/MacOSX-i386/ source/Plugins/ABI/SysV-x86_64/ source/Symbol/ source/Target/

Sean Callanan scallanan at apple.com
Mon Sep 20 17:44:12 PDT 2010


Author: spyffe
Date: Mon Sep 20 19:44:12 2010
New Revision: 114384

URL: http://llvm.org/viewvc/llvm-project?rev=114384&view=rev
Log:
Removed the hacky "#define this ___clang_this" handler
for C++ classes.  Replaced it with a less hacky approach:

 - If an expression is defined in the context of a
   method of class A, then that expression is wrapped as
   ___clang_class::___clang_expr(void*) { ... }
   instead of ___clang_expr(void*) { ... }.

 - ___clang_class is resolved as the type of the target
   of the "this" pointer in the method the expression
   is defined in.

 - When reporting the type of ___clang_class, a method
   with the signature ___clang_expr(void*) is added to
   that class, so that Clang doesn't complain about a
   method being defined without a corresponding
   declaration.

 - Whenever the expression gets called, "this" gets
   looked up, type-checked, and then passed in as the
   first argument.

This required the following changes:

 - The ABIs were changed to support passing of the "this"
   pointer as part of trivial calls.

 - ThreadPlanCallFunction and ClangFunction were changed
   to support passing of an optional "this" pointer.

 - ClangUserExpression was extended to perform the
   wrapping described above.

 - ClangASTSource was changed to revert the changes
   required by the hack.

 - ClangExpressionParser, IRForTarget, and
   ClangExpressionDeclMap were changed to handle
   different manglings of ___clang_expr flexibly.  This
   meant no longer searching for a function called
   ___clang_expr, but rather looking for a function whose
   name *contains* ___clang_expr.

 - ClangExpressionParser and ClangExpressionDeclMap now
   remember whether "this" is required, and know how to
   look it up as necessary.

A few inheritance bugs remain, and I'm trying to resolve
these.  But it is now possible to use "this" as well as
refer implicitly to member variables, when in the proper
context.

Modified:
    lldb/trunk/include/lldb/Expression/ClangASTSource.h
    lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h
    lldb/trunk/include/lldb/Expression/ClangFunction.h
    lldb/trunk/include/lldb/Expression/ClangUserExpression.h
    lldb/trunk/include/lldb/Target/ABI.h
    lldb/trunk/include/lldb/Target/ThreadPlanCallFunction.h
    lldb/trunk/source/Expression/ClangASTSource.cpp
    lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp
    lldb/trunk/source/Expression/ClangExpressionParser.cpp
    lldb/trunk/source/Expression/ClangFunction.cpp
    lldb/trunk/source/Expression/ClangUserExpression.cpp
    lldb/trunk/source/Expression/IRForTarget.cpp
    lldb/trunk/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
    lldb/trunk/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
    lldb/trunk/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
    lldb/trunk/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
    lldb/trunk/source/Symbol/ClangASTContext.cpp
    lldb/trunk/source/Target/ThreadPlanCallFunction.cpp

Modified: lldb/trunk/include/lldb/Expression/ClangASTSource.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangASTSource.h?rev=114384&r1=114383&r2=114384&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangASTSource.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangASTSource.h Mon Sep 20 19:44:12 2010
@@ -161,15 +161,8 @@
     ///
     /// @param[in] type
     ///     The opaque QualType for the VarDecl being registered.
-    ///
-    /// @param[in] override_name
-    ///     In some cases, the name needs to be overridden (such as when
-    ///     searching for ___clang_this, which should resolve to this).
-    ///     This is the name to be used instead of what is being searched
-    ///     for.
     //------------------------------------------------------------------
-    clang::NamedDecl *AddVarDecl(void *type,
-                                 const char *override_name = NULL);
+    clang::NamedDecl *AddVarDecl(void *type);
     
     //------------------------------------------------------------------
     /// Create a FunDecl with the name being searched for and the provided

Modified: lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h?rev=114384&r1=114383&r2=114384&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangExpressionDeclMap.h Mon Sep 20 19:44:12 2010
@@ -267,6 +267,27 @@
                      Error &error);
     
     //------------------------------------------------------------------
+    /// [Used by CommandObjectExpression] Get the "this" pointer
+    /// from a given execution context.
+    ///
+    /// @param[out] object_ptr
+    ///     The this pointer.
+    ///
+    /// @param[in] exe_ctx
+    ///     The execution context at which to dump the struct.
+    ///
+    /// @param[in] error
+    ///     An Error to populate with any messages related to
+    ///     finding the "this" pointer.
+    ///
+    /// @return
+    ///     True on success; false otherwise.
+    //------------------------------------------------------------------
+    bool GetObjectPointer(lldb::addr_t &object_ptr,
+                          ExecutionContext *exe_ctx,
+                          Error &error);
+    
+    //------------------------------------------------------------------
     /// [Used by CommandObjectExpression] Pretty-print a materialized
     /// struct, which must have been materialized by Materialize(),
     /// byte for byte on a given stream.
@@ -340,6 +361,7 @@
     lldb::addr_t                m_allocated_area;           ///< The base of the memory allocated for the struct.  Starts on a potentially unaligned address and may therefore be larger than the struct.
     lldb::addr_t                m_materialized_location;    ///< The address at which the struct is placed.  Falls inside the allocated area.
     std::string                 m_result_name;              ///< The name of the result variable ($1, for example)
+    TypeFromUser                m_object_pointer_type;      ///< The type of the "this" variable, if one exists.
     
     //------------------------------------------------------------------
     /// Given a stack frame, find a variable that matches the given name and 
@@ -415,14 +437,9 @@
     ///
     /// @param[in] var
     ///     The LLDB Variable that needs a Decl.
-    ///
-    /// @param[in] override_name
-    ///     A new name to give the Decl, if the one being looked for needs
-    ///     to be overriden.  Example: this for ___clang_this.
     //------------------------------------------------------------------
     void AddOneVariable(NameSearchContext &context, 
-                        Variable *var, 
-                        const char *override_name);
+                        Variable *var);
     
     //------------------------------------------------------------------
     /// Use the NameSearchContext to generate a Decl for the given
@@ -462,9 +479,15 @@
     ///     The NameSearchContext to use when constructing the Decl.
     ///
     /// @param[in] type
-    ///     The LLDB Type that needs to be created.
-    //------------------------------------------------------------------
-    void AddOneType(NameSearchContext &context, Type *type);
+    ///     The type that needs to be created.
+    ///
+    /// @param[in] add_method
+    ///     True if a method with signature void ___clang_expr(void*)
+    ///     should be added to the C++ class type passed in
+    //------------------------------------------------------------------
+    void AddOneType(NameSearchContext &context, 
+                    TypeFromUser &type, 
+                    bool add_method = false);
     
     //------------------------------------------------------------------
     /// Actually do the task of materializing or dematerializing the struct.

Modified: lldb/trunk/include/lldb/Expression/ClangFunction.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangFunction.h?rev=114384&r1=114383&r2=114384&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangFunction.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangFunction.h Mon Sep 20 19:44:12 2010
@@ -262,6 +262,10 @@
     /// @param[in] errors
     ///     The stream to write errors to.
     ///
+    /// @param[in] this_arg
+    ///     If non-NULL, the function is invoked like a C++ method, with the
+    ///     value pointed to by the pointer as its 'this' argument.
+    ///
     /// @return
     ///     Returns one of the ExecutionResults enum indicating function call status.
 	//------------------------------------------------------------------
@@ -271,7 +275,8 @@
                                              bool stop_others, 
                                              bool try_all_threads, 
                                              uint32_t single_thread_timeout_usec, 
-                                             Stream &errors);
+                                             Stream &errors,
+                                             lldb::addr_t* this_arg = 0);
     
     //------------------------------------------------------------------
     /// Run the function this ClangFunction was created with.
@@ -415,6 +420,10 @@
     /// @param[in] discard_on_error
     ///     True if the thread plan may simply be discarded if an error occurs.
     ///
+    /// @param[in] this_arg
+    ///     If non-NULL, the function is invoked like a C++ method, with the
+    ///     value pointed to by the pointer as its 'this' argument.
+    ///
     /// @return
     ///     A ThreadPlan for executing the function.
 	//------------------------------------------------------------------
@@ -424,7 +433,8 @@
                                  lldb::addr_t &args_addr_ref, 
                                  Stream &errors, 
                                  bool stop_others, 
-                                 bool discard_on_error = true);
+                                 bool discard_on_error = true,
+                                 lldb::addr_t *this_arg = 0);
     
     //------------------------------------------------------------------
     /// Get a thread plan to run the function this ClangFunction was created with.

Modified: lldb/trunk/include/lldb/Expression/ClangUserExpression.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/ClangUserExpression.h?rev=114384&r1=114383&r2=114384&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/ClangUserExpression.h (original)
+++ lldb/trunk/include/lldb/Expression/ClangUserExpression.h Mon Sep 20 19:44:12 2010
@@ -171,6 +171,12 @@
     }
 
 private:
+    //------------------------------------------------------------------
+    /// Populate m_cplusplus and m_objetivec based on the environment.
+    //------------------------------------------------------------------
+    void
+    ScanContext(ExecutionContext &exe_ctx);
+    
     std::string                                 m_expr_text;            ///< The text of the expression, as typed by the user
     std::string                                 m_transformed_text;     ///< The text of the expression, as send to the parser
     
@@ -178,6 +184,10 @@
     std::auto_ptr<ClangExpressionVariableStore> m_local_variables;      ///< The local expression variables, if the expression is DWARF.
     std::auto_ptr<StreamString>                 m_dwarf_opcodes;        ///< The DWARF opcodes for the expression.  May be NULL.
     lldb::addr_t                                m_jit_addr;             ///< The address of the JITted code.  LLDB_INVALID_ADDRESS if invalid.
+    
+    bool                                        m_cplusplus;            ///< 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_objectivec;           ///< 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_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.
 };
     
 } // namespace lldb_private

Modified: lldb/trunk/include/lldb/Target/ABI.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ABI.h?rev=114384&r1=114383&r2=114384&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ABI.h (original)
+++ lldb/trunk/include/lldb/Target/ABI.h Mon Sep 20 19:44:12 2010
@@ -34,7 +34,8 @@
                         lldb::addr_t sp,
                         lldb::addr_t functionAddress,
                         lldb::addr_t returnAddress, 
-                        lldb::addr_t arg) const = 0;
+                        lldb::addr_t arg,
+                        lldb::addr_t *this_arg) const = 0;
     
     virtual bool
     PrepareNormalCall (Thread &thread,

Modified: lldb/trunk/include/lldb/Target/ThreadPlanCallFunction.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ThreadPlanCallFunction.h?rev=114384&r1=114383&r2=114384&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ThreadPlanCallFunction.h (original)
+++ lldb/trunk/include/lldb/Target/ThreadPlanCallFunction.h Mon Sep 20 19:44:12 2010
@@ -27,7 +27,8 @@
                             Address &function,
                             lldb::addr_t arg,
                             bool stop_other_threads,
-                            bool discard_on_error = true);
+                            bool discard_on_error = true,
+                            lldb::addr_t *this_arg = 0);
     
     ThreadPlanCallFunction (Thread &thread,
                             Address &function,

Modified: lldb/trunk/source/Expression/ClangASTSource.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangASTSource.cpp?rev=114384&r1=114383&r2=114384&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangASTSource.cpp (original)
+++ lldb/trunk/source/Expression/ClangASTSource.cpp Mon Sep 20 19:44:12 2010
@@ -85,15 +85,8 @@
     return &ASTSource.Context;
 }
 
-clang::NamedDecl *NameSearchContext::AddVarDecl(void *type,
-                                                const char *override_name) {
-    IdentifierInfo *ii = NULL;
-    
-    if (override_name)
-        ii = &ASTSource.Context.Idents.get(override_name);
-    else
-        ii = Name.getAsIdentifierInfo();
-    
+clang::NamedDecl *NameSearchContext::AddVarDecl(void *type) {
+    IdentifierInfo *ii = Name.getAsIdentifierInfo();
         
     clang::NamedDecl *Decl = VarDecl::Create(ASTSource.Context, 
                                              const_cast<DeclContext*>(DC), 

Modified: lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp?rev=114384&r1=114383&r2=114384&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp (original)
+++ lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp Mon Sep 20 19:44:12 2010
@@ -300,6 +300,78 @@
 }
 
 bool 
+ClangExpressionDeclMap::GetObjectPointer(lldb::addr_t &object_ptr,
+                                         ExecutionContext *exe_ctx,
+                                         Error &err)
+{
+    if (!exe_ctx || !exe_ctx->frame || !exe_ctx->target || !exe_ctx->process)
+    {
+        err.SetErrorString("Couldn't load 'this' because the context is incomplete");
+        return false;
+    }
+    
+    if (!m_object_pointer_type.GetOpaqueQualType())
+    {
+        err.SetErrorString("Couldn't load 'this' because its type is unknown");
+        return false;
+    }
+    
+    Variable *object_ptr_var = FindVariableInScope(*exe_ctx->frame, "this", &m_object_pointer_type);
+    
+    if (!object_ptr_var)
+    {
+        err.SetErrorString("Couldn't find 'this' with appropriate type in scope");
+        return false;
+    }
+    
+    std::auto_ptr<lldb_private::Value> location_value(GetVariableValue(*exe_ctx,
+                                                                       object_ptr_var,
+                                                                       m_object_pointer_type.GetASTContext()));
+    
+    if (!location_value.get())
+    {
+        err.SetErrorString("Couldn't get the location for 'this'");
+        return false;
+    }
+    
+    if (location_value->GetValueType() == Value::eValueTypeLoadAddress)
+    {
+        lldb::addr_t value_addr = location_value->GetScalar().ULongLong();
+        uint32_t address_byte_size = exe_ctx->target->GetArchitecture().GetAddressByteSize();
+        lldb::ByteOrder address_byte_order = exe_ctx->process->GetByteOrder();
+        
+        if (ClangASTType::GetClangTypeBitWidth(m_object_pointer_type.GetASTContext(), m_object_pointer_type.GetOpaqueQualType()) != address_byte_size * 8)
+        {
+            err.SetErrorStringWithFormat("'this' is not of an expected pointer size");
+            return false;
+        }
+        
+        DataBufferHeap data;
+        data.SetByteSize(address_byte_size);
+        Error read_error;
+        
+        if (exe_ctx->process->ReadMemory (value_addr, data.GetBytes(), address_byte_size, read_error) != address_byte_size)
+        {
+            err.SetErrorStringWithFormat("Coldn't read 'this' from the target: %s", read_error.AsCString());
+            return false;
+        }
+        
+        DataExtractor extractor(data.GetBytes(), data.GetByteSize(), address_byte_order, address_byte_size);
+        
+        uint32_t offset = 0;
+        
+        object_ptr = extractor.GetPointer(&offset);
+        
+        return true;
+    }
+    else
+    {
+        err.SetErrorString("'this' is not in memory; LLDB must be extended to handle registers");
+        return false;
+    }
+}
+
+bool 
 ClangExpressionDeclMap::Dematerialize (ExecutionContext *exe_ctx,
                                        ClangExpressionVariable *&result,
                                        Error &err)
@@ -763,24 +835,54 @@
                                  const char *name)
 {
     Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
-    
-    const char* override_name = NULL;
-    
-    if (!strcmp(name, "___clang_this"))
-        override_name = "this";
-    if (!strcmp(name, "___clang_self"))
-        override_name = "self";
-    
-    const char *search_name = (override_name ? override_name : name);
-    
+        
     if (log)
-        log->Printf("Hunting for a definition for %s", search_name);
+        log->Printf("Hunting for a definition for %s", name);
     
     // Back out in all cases where we're not fully initialized
     if (!m_exe_ctx || !m_exe_ctx->frame || !m_sym_ctx)
         return;
+        
+    ConstString name_cs(name);
+    
+    if (!strcmp(name, "___clang_class"))
+    {
+        // Clang is looking for the type of "this"
+        
+        VariableList *vars = m_exe_ctx->frame->GetVariableList(false);
+        
+        if (!vars)
+            return;
+        
+        lldb::VariableSP this_var = vars->FindVariable(ConstString("this"));
+        
+        if (!this_var)
+            return;
+        
+        Type *this_type = this_var->GetType();
+        
+        if (!this_type)
+            return;
+        
+        TypeFromUser this_user_type(this_type->GetOpaqueClangQualType(),
+                                    this_type->GetClangAST());
+        
+        m_object_pointer_type = this_user_type;
+        
+        void *pointer_target_type;
+        
+        if (!ClangASTContext::IsPointerType(this_user_type.GetOpaqueQualType(),
+                                            &pointer_target_type))
+            return;
+        
+        TypeFromUser class_user_type(pointer_target_type,
+                                     this_type->GetClangAST());
+
+        AddOneType(context, class_user_type, true);
+        
+        return;
+    }
     
-    ConstString name_cs(search_name);
     SymbolContextList sym_ctxs;
     
     m_sym_ctx->FindFunctionsByName(name_cs, false, sym_ctxs);
@@ -813,10 +915,10 @@
         }
     }
     
-    Variable *var = FindVariableInScope(*m_exe_ctx->frame, search_name);
+    Variable *var = FindVariableInScope(*m_exe_ctx->frame, name);
     
     if (var)
-        AddOneVariable(context, var, override_name);
+        AddOneVariable(context, var);
     
     ClangExpressionVariable *pvar(m_persistent_vars->GetVariable(name));
     
@@ -943,8 +1045,7 @@
 
 void
 ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context,
-                                       Variable* var,
-                                       const char *override_name)
+                                       Variable* var)
 {
     Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
     
@@ -957,10 +1058,10 @@
                                            &ut,
                                            &pt);
     
-    NamedDecl *var_decl = context.AddVarDecl(pt.GetOpaqueQualType(), override_name);
+    NamedDecl *var_decl = context.AddVarDecl(pt.GetOpaqueQualType());
     
     ClangExpressionVariable &entity(m_found_entities.VariableAtIndex(m_found_entities.CreateVariable()));
-    entity.m_name       = (override_name ? override_name : context.Name.getAsString());
+    entity.m_name       = context.Name.getAsString();
     entity.m_user_type  = ut;
     
     entity.EnableParserVars();
@@ -1081,12 +1182,34 @@
 
 void 
 ClangExpressionDeclMap::AddOneType(NameSearchContext &context, 
-                                   Type *type)
+                                   TypeFromUser &ut,
+                                   bool add_method)
 {
-    TypeFromUser ut(type->GetOpaqueClangQualType(),
-                    type->GetClangAST());
+    clang::ASTContext *parser_ast_context = context.GetASTContext();
+    clang::ASTContext *user_ast_context = ut.GetASTContext();
+    
+    void *copied_type = ClangASTContext::CopyType(parser_ast_context, user_ast_context, ut.GetOpaqueQualType());
+ 
+    TypeFromParser parser_type(copied_type, parser_ast_context);
     
-    void *copied_type = ClangASTContext::CopyType(context.GetASTContext(), ut.GetASTContext(), ut.GetOpaqueQualType());
+    if (add_method && ClangASTContext::IsAggregateType(copied_type))
+    {
+        void *args[1];
+        
+        args[0] = ClangASTContext::GetVoidPtrType(parser_ast_context, false);
+        
+        void *method_type = ClangASTContext::CreateFunctionType (parser_ast_context,
+                                                                 ClangASTContext::GetBuiltInType_void(parser_ast_context),
+                                                                 args,
+                                                                 1,
+                                                                 false,
+                                                                 ClangASTContext::GetTypeQualifiers(copied_type));
+        
+        ClangASTContext::AddMethodToCXXRecordType(parser_ast_context,
+                                                  copied_type,
+                                                  "___clang_expr",
+                                                  method_type);
+    }
     
     context.AddTypeDecl(copied_type);
 }

Modified: lldb/trunk/source/Expression/ClangExpressionParser.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangExpressionParser.cpp?rev=114384&r1=114383&r2=114384&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangExpressionParser.cpp (original)
+++ lldb/trunk/source/Expression/ClangExpressionParser.cpp Mon Sep 20 19:44:12 2010
@@ -326,6 +326,24 @@
     return num_errors;
 }
 
+static bool FindFunctionInModule (std::string &mangled_name,
+                                  llvm::Module *module,
+                                  const char *orig_name)
+{
+    for (llvm::Module::iterator fi = module->getFunctionList().begin(), fe = module->getFunctionList().end();
+         fi != fe;
+         ++fi)
+    {        
+        if (fi->getName().str().find(orig_name) != std::string::npos)
+        {
+            mangled_name = fi->getName().str();
+            return true;
+        }
+    }
+    
+    return false;
+}
+
 Error
 ClangExpressionParser::MakeDWARF ()
 {
@@ -357,7 +375,16 @@
         return err;
     }
     
-    IRToDWARF ir_to_dwarf(*local_variables, decl_map, m_expr.DwarfOpcodeStream());
+    std::string function_name;
+    
+    if (!FindFunctionInModule(function_name, module, m_expr.FunctionName()))
+    {
+        err.SetErrorToGenericError();
+        err.SetErrorStringWithFormat("Couldn't find %s() in the module", m_expr.FunctionName());
+        return err;
+    }
+    
+    IRToDWARF ir_to_dwarf(*local_variables, decl_map, m_expr.DwarfOpcodeStream(), function_name.c_str());
     
     if (!ir_to_dwarf.runOnModule(*module))
     {
@@ -375,6 +402,8 @@
                                 lldb::addr_t &func_end, 
                                 ExecutionContext &exe_ctx)
 {
+    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
+
     Error err;
     
     llvm::Module *module = m_code_generator->ReleaseModule();
@@ -386,6 +415,22 @@
         return err;
     }
     
+    // Find the actual name of the function (it's often mangled somehow)
+    
+    std::string function_name;
+    
+    if (!FindFunctionInModule(function_name, module, m_expr.FunctionName()))
+    {
+        err.SetErrorToGenericError();
+        err.SetErrorStringWithFormat("Couldn't find %s() in the module", m_expr.FunctionName());
+        return err;
+    }
+    else
+    {
+        if(log)
+            log->Printf("Found function %s for %s", function_name.c_str(), m_expr.FunctionName());
+    }
+    
     ClangExpressionDeclMap *decl_map = m_expr.DeclMap(); // result can be NULL
     
     if (decl_map)
@@ -406,7 +451,7 @@
         IRForTarget ir_for_target(decl_map, 
                                   target_machine->getTargetData(),
                                   m_expr.NeedsVariableResolution(),
-                                  m_expr.FunctionName());
+                                  function_name.c_str());
         
         if (!ir_for_target.runOnModule(*module))
         {
@@ -417,7 +462,7 @@
         
         if (m_expr.NeedsValidation())
         {
-            IRDynamicChecks ir_dynamic_checks(*exe_ctx.process->GetDynamicCheckers(), m_expr.FunctionName());
+            IRDynamicChecks ir_dynamic_checks(*exe_ctx.process->GetDynamicCheckers(), function_name.c_str());
         
             if (!ir_dynamic_checks.runOnModule(*module))
             {
@@ -448,7 +493,7 @@
     
     m_execution_engine->DisableLazyCompilation();
     
-    llvm::Function *function = module->getFunction (m_expr.FunctionName());
+    llvm::Function *function = module->getFunction (function_name.c_str());
     
     // We don't actually need the function pointer here, this just forces it to get resolved.
     
@@ -463,7 +508,7 @@
         return err;
     }
     
-    m_jitted_functions.push_back (ClangExpressionParser::JittedFunction(m_expr.FunctionName(), (lldb::addr_t)fun_ptr));
+    m_jitted_functions.push_back (ClangExpressionParser::JittedFunction(function_name.c_str(), (lldb::addr_t)fun_ptr));
     
     ExecutionContext &exc_context(exe_ctx);
     
@@ -525,7 +570,7 @@
     {
         (*pos).m_remote_addr = m_jit_mm->GetRemoteAddressForLocal ((*pos).m_local_addr);
     
-        if (!(*pos).m_name.compare(m_expr.FunctionName()))
+        if (!(*pos).m_name.compare(function_name.c_str()))
         {
             func_end = m_jit_mm->GetRemoteRangeForLocal ((*pos).m_local_addr).second;
             func_addr = (*pos).m_remote_addr;
@@ -554,7 +599,7 @@
     
     for (pos = m_jitted_functions.begin(); pos < end; pos++)
     {
-        if (strcmp(pos->m_name.c_str(), name) == 0)
+        if (strstr(pos->m_name.c_str(), name))
         {
             func_local_addr = pos->m_local_addr;
             func_remote_addr = pos->m_remote_addr;

Modified: lldb/trunk/source/Expression/ClangFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangFunction.cpp?rev=114384&r1=114383&r2=114384&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangFunction.cpp (original)
+++ lldb/trunk/source/Expression/ClangFunction.cpp Mon Sep 20 19:44:12 2010
@@ -359,7 +359,7 @@
 }
 
 ThreadPlan *
-ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx, lldb::addr_t func_addr, lldb::addr_t &args_addr, Stream &errors, bool stop_others, bool discard_on_error)
+ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx, lldb::addr_t func_addr, lldb::addr_t &args_addr, Stream &errors, bool stop_others, bool discard_on_error, lldb::addr_t *this_arg)
 {
     // FIXME: Use the errors Stream for better error reporting.
 
@@ -377,7 +377,9 @@
     ThreadPlan *new_plan = new ThreadPlanCallFunction (*exe_ctx.thread, 
                                           wrapper_address,
                                           args_addr,
-                                          stop_others, discard_on_error);
+                                          stop_others, 
+                                          discard_on_error,
+                                          this_arg);
     return new_plan;
 }
 
@@ -456,7 +458,8 @@
         bool stop_others,
         bool try_all_threads,
         uint32_t single_thread_timeout_usec,
-        Stream &errors)
+        Stream &errors,
+        lldb::addr_t *this_arg)
 {
     // Save this value for restoration of the execution context after we run
     uint32_t tid = exe_ctx.thread->GetIndexID();
@@ -480,7 +483,7 @@
 
     ClangFunction::ExecutionResults return_value = eExecutionSetupError;
     
-    lldb::ThreadPlanSP call_plan_sp(ClangFunction::GetThreadPlanToCallFunction(exe_ctx, function_address, void_arg, errors, stop_others, false));
+    lldb::ThreadPlanSP call_plan_sp(ClangFunction::GetThreadPlanToCallFunction(exe_ctx, function_address, void_arg, errors, stop_others, false, this_arg));
     
     ThreadPlanCallFunction *call_plan_ptr = static_cast<ThreadPlanCallFunction *> (call_plan_sp.get());
     

Modified: lldb/trunk/source/Expression/ClangUserExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangUserExpression.cpp?rev=114384&r1=114383&r2=114384&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangUserExpression.cpp (original)
+++ lldb/trunk/source/Expression/ClangUserExpression.cpp Mon Sep 20 19:44:12 2010
@@ -27,28 +27,21 @@
 #include "lldb/Expression/ASTResultSynthesizer.h"
 #include "lldb/Expression/ClangUserExpression.h"
 #include "lldb/Host/Host.h"
+#include "lldb/Symbol/VariableList.h"
 #include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/StackFrame.h"
 #include "lldb/Target/Target.h"
 
 using namespace lldb_private;
 
 ClangUserExpression::ClangUserExpression (const char *expr) :
     m_expr_text(expr),
-    m_jit_addr(LLDB_INVALID_ADDRESS)
+    m_transformed_text(),
+    m_jit_addr(LLDB_INVALID_ADDRESS),
+    m_cplusplus(false),
+    m_objectivec(false),
+    m_needs_object_ptr(false)
 {
-    StreamString m_transformed_stream;
-    
-    m_transformed_stream.Printf("#define this ___clang_this     \n"
-                                "#define self ___clang_self     \n"
-                                "extern \"C\" void              \n"
-                                "%s(void *___clang_arg)         \n"
-                                "{                              \n"
-                                    "%s;                        \n" 
-                                "}                              \n",
-                                FunctionName(),
-                                m_expr_text.c_str());
-    
-    m_transformed_text = m_transformed_stream.GetData();
 }
 
 ClangUserExpression::~ClangUserExpression ()
@@ -61,11 +54,65 @@
     return new ASTResultSynthesizer(passthrough);
 }
 
+void
+ClangUserExpression::ScanContext(ExecutionContext &exe_ctx)
+{
+    if (!exe_ctx.frame)
+        return;
+    
+    VariableList *vars = exe_ctx.frame->GetVariableList(false);
+    
+    if (!vars)
+        return;
+    
+    if (vars->FindVariable(ConstString("this")).get())
+        m_cplusplus = true;
+    else if (vars->FindVariable(ConstString("self")).get())
+        m_objectivec = true;
+}
+
 bool 
 ClangUserExpression::Parse (Stream &error_stream, ExecutionContext &exe_ctx)
 {
     Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
     
+    ScanContext(exe_ctx);
+    
+    StreamString m_transformed_stream;
+    
+    ////////////////////////////////////
+    // Generate the expression
+    //
+
+    if (m_cplusplus)
+    {
+        m_transformed_stream.Printf("void                                   \n"
+                                    "___clang_class::%s(void *___clang_arg) \n"
+                                    "{                                      \n"
+                                    "    %s;                                \n" 
+                                    "}                                      \n",
+                                    FunctionName(),
+                                    m_expr_text.c_str());
+        
+        m_needs_object_ptr = true;
+    }
+    else
+    {
+        m_transformed_stream.Printf("void                           \n"
+                                    "%s(void *___clang_arg)         \n"
+                                    "{                              \n"
+                                    "    %s;                        \n" 
+                                    "}                              \n",
+                                    FunctionName(),
+                                    m_expr_text.c_str());
+    }
+    
+    m_transformed_text = m_transformed_stream.GetData();
+    
+    
+    if (log)
+        log->Printf("Parsing the following code:\n%s", m_transformed_text.c_str());
+    
     ////////////////////////////////////
     // Set up the target and compiler
     //
@@ -187,15 +234,27 @@
         
         Error materialize_error;
         
+        lldb::addr_t object_ptr = NULL;
+        
+        if (m_needs_object_ptr && !(m_expr_decl_map->GetObjectPointer(object_ptr, &exe_ctx, materialize_error)))
+        {
+            error_stream.Printf("Couldn't get required object pointer: %s\n", materialize_error.AsCString());
+            return false;
+        }
+                
         if (!m_expr_decl_map->Materialize(&exe_ctx, struct_address, materialize_error))
         {
-            error_stream.Printf("Couldn't materialize struct: %s\n", materialize_error.AsCString("unknown error"));
+            error_stream.Printf("Couldn't materialize struct: %s\n", materialize_error.AsCString());
             return false;
         }
         
         if (log)
         {
             log->Printf("Function address  : 0x%llx", (uint64_t)m_jit_addr);
+            
+            if (m_needs_object_ptr)
+                log->Printf("Object pointer    : 0x%llx", (uint64_t)object_ptr);
+            
             log->Printf("Structure address : 0x%llx", (uint64_t)struct_address);
                     
             StreamString args;
@@ -216,7 +275,14 @@
         }
         
         ClangFunction::ExecutionResults execution_result = 
-        ClangFunction::ExecuteFunction (exe_ctx, m_jit_addr, struct_address, true, true, 10000, error_stream);
+        ClangFunction::ExecuteFunction (exe_ctx, 
+                                        m_jit_addr, 
+                                        struct_address, 
+                                        true,
+                                        true, 
+                                        10000, 
+                                        error_stream,
+                                        (m_needs_object_ptr ? &object_ptr : NULL));
         
         if (execution_result != ClangFunction::eExecutionCompleted)
         {

Modified: lldb/trunk/source/Expression/IRForTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/IRForTarget.cpp?rev=114384&r1=114383&r2=114384&view=diff
==============================================================================
--- lldb/trunk/source/Expression/IRForTarget.cpp (original)
+++ lldb/trunk/source/Expression/IRForTarget.cpp Mon Sep 20 19:44:12 2010
@@ -71,16 +71,36 @@
         return true;
     
     // Find the result variable.  If it doesn't exist, we can give up right here.
-            
-    Value *result_value = M.getNamedValue("___clang_expr_result");
     
-    if (!result_value)
+    ValueSymbolTable& value_symbol_table = M.getValueSymbolTable();
+    
+    const char *result_name = NULL;
+    
+    for (ValueSymbolTable::iterator vi = value_symbol_table.begin(), ve = value_symbol_table.end();
+         vi != ve;
+         ++vi)
+    {
+        if (strstr(vi->first(), "___clang_expr_result"))
+            result_name = vi->first();
+    }
+    
+    if (!result_name)
     {
         if (log)
             log->PutCString("Couldn't find result variable");
-                
+        
         return true;
     }
+    
+    Value *result_value = M.getNamedValue(result_name);
+    
+    if (!result_value)
+    {
+        if (log)
+            log->PutCString("Result variable had no data");
+                
+        return false;
+    }
         
     if (log)
         log->Printf("Found result in the IR: %s", PrintValue(result_value, false).c_str());
@@ -935,6 +955,16 @@
     
     Argument *argument = iter;
     
+    if (argument->getName().equals("this"))
+    {
+        ++iter;
+        
+        if (iter == F.getArgumentList().end())
+            return false;
+        
+        argument = iter;
+    }
+    
     if (!argument->getName().equals("___clang_arg"))
         return false;
     

Modified: lldb/trunk/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp?rev=114384&r1=114383&r2=114384&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp (original)
+++ lldb/trunk/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp Mon Sep 20 19:44:12 2010
@@ -57,7 +57,8 @@
                                     lldb::addr_t sp, 
                                     lldb::addr_t functionAddress, 
                                     lldb::addr_t returnAddress, 
-                                    lldb::addr_t arg) const
+                                    lldb::addr_t arg,
+                                    lldb::addr_t *this_arg) const
 {
     RegisterContext *reg_ctx = thread.GetRegisterContext();
     if (!reg_ctx)
@@ -70,9 +71,12 @@
     uint32_t eipID = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
     uint32_t espID = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
     
-    // Make room for the argument on the stack
+    // Make room for the argument(s) on the stack
     
-    sp -= 4;
+    if (this_arg)
+        sp -= 8;
+    else
+        sp -= 4;
     
     // Align the SP
     
@@ -80,10 +84,25 @@
     
     // Write the argument on the stack
     
-    uint32_t argU32 = arg & 0xffffffffull;
     Error error;
-    if (thread.GetProcess().WriteMemory (sp, &argU32, sizeof(argU32), error) != sizeof(argU32))
-        return false;
+    
+    if (this_arg)
+    {
+        uint32_t this_argU32 = *this_arg & 0xffffffffull;
+        uint32_t argU32 = arg & 0xffffffffull;
+                
+        if (thread.GetProcess().WriteMemory(sp, &this_argU32, sizeof(this_argU32), error) != sizeof(this_argU32))
+            return false;
+        if (thread.GetProcess().WriteMemory(sp + 4, &argU32, sizeof(argU32), error) != sizeof(argU32))
+            return false;
+    }
+    else
+    {
+        uint32_t argU32 = arg & 0xffffffffull;
+
+        if (thread.GetProcess().WriteMemory (sp, &argU32, sizeof(argU32), error) != sizeof(argU32))
+            return false;
+    }
     
     // The return address is pushed onto the stack.
     

Modified: lldb/trunk/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h?rev=114384&r1=114383&r2=114384&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h (original)
+++ lldb/trunk/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h Mon Sep 20 19:44:12 2010
@@ -34,7 +34,8 @@
                             lldb::addr_t sp,
                             lldb::addr_t functionAddress,
                             lldb::addr_t returnAddress, 
-                            lldb::addr_t arg) const;
+                            lldb::addr_t arg,
+                            lldb::addr_t *this_arg) const;
         
         virtual bool
         PrepareNormalCall (Thread &thread,

Modified: lldb/trunk/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp?rev=114384&r1=114383&r2=114384&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp (original)
+++ lldb/trunk/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp Mon Sep 20 19:44:12 2010
@@ -57,7 +57,8 @@
                                     lldb::addr_t sp, 
                                     lldb::addr_t functionAddress, 
                                     lldb::addr_t returnAddress, 
-                                    lldb::addr_t arg) const
+                                    lldb::addr_t arg,
+                                    lldb::addr_t *this_arg) const
 {
     RegisterContext *reg_ctx = thread.GetRegisterContext();
     if (!reg_ctx)
@@ -74,9 +75,22 @@
     uint32_t rspID = reg_ctx->ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
 
     // The argument is in %rdi, and not on the stack.
-
-    if (!reg_ctx->WriteRegisterFromUnsigned(rdiID, arg))
-        return false;
+    
+    if (this_arg)
+    {
+        uint32_t rsiID = reg_ctx->GetRegisterInfoByName("rsi", 0)->kinds[eRegisterKindLLDB];
+        
+        if (!reg_ctx->WriteRegisterFromUnsigned(rdiID, *this_arg))
+            return false;
+        
+        if (!reg_ctx->WriteRegisterFromUnsigned(rsiID, arg))
+            return false;
+    }
+    else
+    {
+        if (!reg_ctx->WriteRegisterFromUnsigned(rdiID, arg))
+            return false;
+    }
 
     // First, align the SP
 

Modified: lldb/trunk/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h?rev=114384&r1=114383&r2=114384&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h (original)
+++ lldb/trunk/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h Mon Sep 20 19:44:12 2010
@@ -33,7 +33,8 @@
                         lldb::addr_t sp,
                         lldb::addr_t functionAddress,
                         lldb::addr_t returnAddress, 
-                        lldb::addr_t arg) const;
+                        lldb::addr_t arg,
+                        lldb::addr_t *this_arg) const;
     
     virtual bool
     PrepareNormalCall (Thread &thread,

Modified: lldb/trunk/source/Symbol/ClangASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/ClangASTContext.cpp?rev=114384&r1=114383&r2=114384&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/ClangASTContext.cpp (original)
+++ lldb/trunk/source/Symbol/ClangASTContext.cpp Mon Sep 20 19:44:12 2010
@@ -807,12 +807,12 @@
 ClangASTContext::AddMethodToCXXRecordType
 (
  clang::ASTContext *ast_context,
- void *record_clang_type,
+ void *record_opaque_type,
  const char *name,
- void *method_type
+ void *method_opaque_type
  )
 {
-    if (!record_clang_type || !method_type || !name)
+    if (!record_opaque_type || !method_opaque_type || !name)
         return false;
     
     assert(ast_context);
@@ -821,7 +821,7 @@
     
     assert(identifier_table);
     
-    QualType record_qual_type(QualType::getFromOpaquePtr(record_clang_type));
+    QualType record_qual_type(QualType::getFromOpaquePtr(record_opaque_type));
     clang::Type *record_type(record_qual_type.getTypePtr());
     
     if (!record_type)
@@ -842,13 +842,48 @@
     if (!cxx_record_decl)
         return false;
     
+    QualType method_qual_type(QualType::getFromOpaquePtr(method_opaque_type));
+    
     CXXMethodDecl *cxx_method_decl = CXXMethodDecl::Create(*ast_context,
                                                            cxx_record_decl, 
                                                            SourceLocation(), 
                                                            DeclarationName(&identifier_table->get(name)), 
-                                                           QualType::getFromOpaquePtr(method_type), 
+                                                           method_qual_type, 
                                                            NULL);
     
+    // Populate the method decl with parameter decls
+    
+    clang::Type *method_type(method_qual_type.getTypePtr());
+    
+    if (!method_type)
+        return false;
+    
+    FunctionProtoType *method_funprototy(dyn_cast<FunctionProtoType>(method_type));
+    
+    if (!method_funprototy)
+        return false;
+    
+    unsigned int num_params = method_funprototy->getNumArgs();
+    
+    ParmVarDecl *params[num_params];
+    
+    for (int param_index = 0;
+         param_index < num_params;
+         ++param_index)
+    {
+        params[param_index] = ParmVarDecl::Create(*ast_context,
+                                                  cxx_method_decl,
+                                                  SourceLocation(),
+                                                  NULL, // anonymous
+                                                  method_funprototy->getArgType(param_index), 
+                                                  NULL,
+                                                  VarDecl::Auto, 
+                                                  VarDecl::Auto,
+                                                  NULL); 
+    }
+    
+    cxx_method_decl->setParams(params, num_params);
+    
     cxx_record_decl->addDecl(cxx_method_decl);
     
     return true;

Modified: lldb/trunk/source/Target/ThreadPlanCallFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadPlanCallFunction.cpp?rev=114384&r1=114383&r2=114384&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadPlanCallFunction.cpp (original)
+++ lldb/trunk/source/Target/ThreadPlanCallFunction.cpp Mon Sep 20 19:44:12 2010
@@ -34,7 +34,8 @@
                                                 Address &function,
                                                 lldb::addr_t arg,
                                                 bool stop_other_threads,
-                                                bool discard_on_error) :
+                                                bool discard_on_error,
+                                                lldb::addr_t *this_arg) :
     ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion),
     m_valid (false),
     m_stop_other_threads (stop_other_threads),
@@ -43,7 +44,6 @@
     m_process (thread.GetProcess()),
     m_thread (thread)
 {
-
     SetOkayToDiscard (discard_on_error);
 
     Process& process = thread.GetProcess();
@@ -78,7 +78,8 @@
                                  spBelowRedZone, 
                                  FunctionLoadAddr, 
                                  StartLoadAddr, 
-                                 m_arg_addr))
+                                 m_arg_addr,
+                                 this_arg))
         return;
     
     m_valid = true;    





More information about the lldb-commits mailing list