[Lldb-commits] [lldb] r136928 - in /lldb/trunk: include/lldb/Expression/IRForTarget.h source/Expression/ASTResultSynthesizer.cpp source/Expression/IRForTarget.cpp

Sean Callanan scallanan at apple.com
Thu Aug 4 14:37:47 PDT 2011


Author: spyffe
Date: Thu Aug  4 16:37:47 2011
New Revision: 136928

URL: http://llvm.org/viewvc/llvm-project?rev=136928&view=rev
Log:
Fixed a problem that caused LLDB to fail to execute
expressions that used function pointers.  The problem
was that IRForTarget previously only scanned the IR
for the expression for call instructions; if a function
was used in another context, it was ignored.

Now LLDB scans the Module for functions that are only
declared (not also defined -- so these are externals);
it then constructs function pointers for these
functions and substitutes them wherever the function
is used.

Also made some changes so that "expr main" works just
as well as "expr &main"; they end up being the same
code, but LLDB was generating the result variable in
different ways.

Modified:
    lldb/trunk/include/lldb/Expression/IRForTarget.h
    lldb/trunk/source/Expression/ASTResultSynthesizer.cpp
    lldb/trunk/source/Expression/IRForTarget.cpp

Modified: lldb/trunk/include/lldb/Expression/IRForTarget.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Expression/IRForTarget.h?rev=136928&r1=136927&r2=136928&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Expression/IRForTarget.h (original)
+++ lldb/trunk/include/lldb/Expression/IRForTarget.h Thu Aug  4 16:37:47 2011
@@ -149,11 +149,73 @@
     FixFunctionLinkage (llvm::Function &llvm_function);
     
     //------------------------------------------------------------------
+    /// A module-level pass to replace all function pointers with their
+    /// integer equivalents.
+    //------------------------------------------------------------------
+    
+    //------------------------------------------------------------------
+    /// The top-level pass implementation
+    ///
+    /// @param[in] llvm_module
+    ///     The module currently being processed.
+    ///
+    /// @param[in] llvm_function
+    ///     The function currently being processed.
+    ///
+    /// @return
+    ///     True on success; false otherwise.
+    //------------------------------------------------------------------
+    bool 
+    HasSideEffects (llvm::Function &llvm_function);
+    
+    //------------------------------------------------------------------
     /// A function-level pass to check whether the function has side
     /// effects.
     //------------------------------------------------------------------
     
     //------------------------------------------------------------------
+    /// Get the address of a fuction, and a location to put the complete
+    /// Value of the function if one is available.
+    ///
+    /// @param[in] function
+    ///     The function to find the location of.
+    ///
+    /// @param[out] ptr
+    ///     The location of the function in the target.
+    ///
+    /// @param[out] name
+    ///     The resolved name of the function (matters for intrinsics).
+    ///
+    /// @param[out] value_ptr
+    ///     A variable to put the function's completed Value* in, or NULL
+    ///     if the Value* shouldn't be stored anywhere.
+    ///
+    /// @return
+    ///     The pointer.
+    //------------------------------------------------------------------ 
+    bool 
+    GetFunctionAddress (llvm::Function *function,
+                        uint64_t &ptr,
+                        lldb_private::ConstString &name,
+                        llvm::Constant **&value_ptr);
+    
+    //------------------------------------------------------------------
+    /// Build a function pointer given a type and a raw pointer.
+    ///
+    /// @param[in] type
+    ///     The type of the function pointer to be built.
+    ///
+    /// @param[in] ptr
+    ///     The value of the pointer.
+    ///
+    /// @return
+    ///     The pointer.
+    //------------------------------------------------------------------ 
+    llvm::Constant *
+    BuildFunctionPointer (llvm::Type *type,
+                          uint64_t ptr);
+    
+    //------------------------------------------------------------------
     /// The top-level pass implementation
     ///
     /// @param[in] llvm_function
@@ -164,7 +226,8 @@
     ///     be determined); false otherwise.
     //------------------------------------------------------------------
     bool 
-    HasSideEffects (llvm::Function &llvm_function);
+    ResolveFunctionPointers (llvm::Module &llvm_module,
+                             llvm::Function &llvm_function);
     
     //------------------------------------------------------------------
     /// A function-level pass to take the generated global value
@@ -382,19 +445,7 @@
     MaybeHandleCallArguments (llvm::CallInst *call_inst);
     
     //------------------------------------------------------------------
-    /// Handle a single external function call
-    ///
-    /// @param[in] C
-    ///     The call instruction.
-    ///
-    /// @return
-    ///     True on success; false otherwise
-    //------------------------------------------------------------------
-    bool 
-    MaybeHandleCall (llvm::CallInst *C);
-    
-    //------------------------------------------------------------------
-    /// Resolve calls to external functions
+    /// Resolve variable references in calls to external functions
     ///
     /// @param[in] basic_block
     ///     The basic block currently being processed.

Modified: lldb/trunk/source/Expression/ASTResultSynthesizer.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ASTResultSynthesizer.cpp?rev=136928&r1=136927&r2=136928&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ASTResultSynthesizer.cpp (original)
+++ lldb/trunk/source/Expression/ASTResultSynthesizer.cpp Thu Aug  4 16:37:47 2011
@@ -311,7 +311,12 @@
     
     if (is_lvalue)
     {
-        IdentifierInfo &result_ptr_id = Ctx.Idents.get("$__lldb_expr_result_ptr");
+        IdentifierInfo *result_ptr_id;
+        
+        if (expr_type->isFunctionType())
+            result_ptr_id = &Ctx.Idents.get("$__lldb_expr_result"); // functions actually should be treated like function pointers
+        else
+            result_ptr_id = &Ctx.Idents.get("$__lldb_expr_result_ptr");
         
         QualType ptr_qual_type = Ctx.getPointerType(expr_qual_type);
         
@@ -319,7 +324,7 @@
                                       DC,
                                       SourceLocation(),
                                       SourceLocation(),
-                                      &result_ptr_id,
+                                      result_ptr_id,
                                       ptr_qual_type,
                                       NULL,
                                       SC_Static,

Modified: lldb/trunk/source/Expression/IRForTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/IRForTarget.cpp?rev=136928&r1=136927&r2=136928&view=diff
==============================================================================
--- lldb/trunk/source/Expression/IRForTarget.cpp (original)
+++ lldb/trunk/source/Expression/IRForTarget.cpp Thu Aug  4 16:37:47 2011
@@ -169,6 +169,146 @@
     return false;
 }
 
+bool 
+IRForTarget::GetFunctionAddress (llvm::Function *fun,
+                                 uint64_t &fun_addr,
+                                 lldb_private::ConstString &name,
+                                 Constant **&value_ptr)
+{
+    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+    
+    fun_addr = LLDB_INVALID_ADDRESS;
+    name.Clear();
+    value_ptr = NULL;
+    
+    if (fun->isIntrinsic())
+    {
+        Intrinsic::ID intrinsic_id = (Intrinsic::ID)fun->getIntrinsicID();
+        
+        switch (intrinsic_id)
+        {
+        default:
+            if (log)
+                log->Printf("Unresolved intrinsic \"%s\"", Intrinsic::getName(intrinsic_id).c_str());
+                
+            if (m_error_stream)
+                m_error_stream->Printf("Internal error [IRForTarget]: Call to unhandled compiler intrinsic '%s'\n", Intrinsic::getName(intrinsic_id).c_str());
+            
+            return false;
+        case Intrinsic::memcpy:
+            {
+                static lldb_private::ConstString g_memcpy_str ("memcpy");
+                name = g_memcpy_str;
+            }
+            break;
+        }
+        
+        if (log && name)
+            log->Printf("Resolved intrinsic name \"%s\"", name.GetCString());
+    }
+    else
+    {
+        name.SetCStringWithLength (fun->getName().data(), fun->getName().size());
+    }
+    
+    // Find the address of the function.
+    
+    clang::NamedDecl *fun_decl = DeclForGlobal (fun);
+    Value **fun_value_ptr = NULL;
+    
+    if (fun_decl)
+    {
+        if (!m_decl_map->GetFunctionInfo (fun_decl, fun_value_ptr, fun_addr)) 
+        {
+            fun_value_ptr = NULL;
+            
+            if (!m_decl_map->GetFunctionAddress (name, fun_addr))
+            {
+                if (log)
+                    log->Printf("Function \"%s\" had no address", name.GetCString());
+                
+                if (m_error_stream)
+                    m_error_stream->Printf("Error [IRForTarget]: Call to a function '%s' that is not present in the target\n", name.GetCString());
+                
+                return false;
+            }
+        }
+    }
+    else 
+    {
+        if (!m_decl_map->GetFunctionAddress (name, fun_addr))
+        {
+            if (log)
+                log->Printf ("Metadataless function \"%s\" had no address", name.GetCString());
+            
+            if (m_error_stream)
+                m_error_stream->Printf("Error [IRForTarget]: Call to a symbol-only function '%s' that is not present in the target\n", name.GetCString());
+            
+            return false;
+        }
+    }
+    
+    if (log)
+        log->Printf("Found \"%s\" at 0x%llx", name.GetCString(), fun_addr);
+    
+    return true;
+}
+
+llvm::Constant *
+IRForTarget::BuildFunctionPointer (llvm::Type *type,
+                                   uint64_t ptr)
+{
+    IntegerType *intptr_ty = Type::getIntNTy(m_module->getContext(),
+                                             (m_module->getPointerSize() == Module::Pointer64) ? 64 : 32);
+    PointerType *fun_ptr_ty = PointerType::getUnqual(type);
+    Constant *fun_addr_int = ConstantInt::get(intptr_ty, ptr, false);
+    return ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty);
+}
+
+bool 
+IRForTarget::ResolveFunctionPointers(llvm::Module &llvm_module,
+                                     llvm::Function &llvm_function)
+{
+    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+    
+    for (llvm::Module::iterator fi = llvm_module.begin();
+         fi != llvm_module.end();
+         ++fi)
+    {
+        Function *fun = fi;
+        
+        bool is_decl = fun->isDeclaration();
+        
+        if (log)
+            log->Printf("Examining %s function %s", (is_decl ? "declaration" : "non-declaration"), fun->getNameStr().c_str());
+        
+        if (!is_decl)
+            continue;
+        
+        if (fun->hasNUses(0))
+            continue; // ignore
+        
+        uint64_t addr = LLDB_INVALID_ADDRESS;
+        lldb_private::ConstString name;
+        Constant **value_ptr = NULL;
+        
+        if (!GetFunctionAddress(fun,
+                                addr,
+                                name,
+                                value_ptr))
+            return false; // GetFunctionAddress reports its own errors
+        
+        Constant *value = BuildFunctionPointer(fun->getFunctionType(), addr);
+        
+        if (value_ptr)
+            *value_ptr = value;
+        
+        fun->replaceAllUsesWith(value);
+    }
+    
+    return true;
+}
+
 clang::NamedDecl *
 IRForTarget::DeclForGlobal (GlobalValue *global_val)
 {
@@ -1403,193 +1543,6 @@
 }
 
 bool
-IRForTarget::MaybeHandleCall (CallInst *llvm_call_inst)
-{
-    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
-
-    Function *fun = llvm_call_inst->getCalledFunction();
-    
-    bool is_bitcast = false;
-
-    // If the call is to something other than a plain llvm::Function, resolve which
-    // Function is meant or give up.
-    
-    if (fun == NULL)
-    {
-        Value *val = llvm_call_inst->getCalledValue();
-        
-        ConstantExpr *const_expr = dyn_cast<ConstantExpr>(val);
-        LoadInst *load_inst = dyn_cast<LoadInst>(val);
-        
-        if (const_expr && const_expr->getOpcode() == Instruction::BitCast)
-        {
-            fun = dyn_cast<Function>(const_expr->getOperand(0));
-            
-            if (!fun)
-            {
-                if (m_error_stream)
-                    m_error_stream->Printf("Internal error [IRForTaget]: Called entity is a cast of something not a function\n");
-            
-                return false;
-            }
-            
-            is_bitcast = true;
-        }
-        else if (const_expr && const_expr->getOpcode() == Instruction::IntToPtr)
-        {
-            return true; // already resolved
-        }
-        else if (load_inst)
-        {
-            return true; // virtual method call
-        }
-        else
-        {
-            if (m_error_stream)
-                m_error_stream->Printf("Internal error [IRForTarget]: Called entity is not a function\n");
-            
-            return false;
-        }
-    }
-    
-    // Determine the name of the called function, which is needed to find the address.
-    // Intrinsics are special-cased.
-    
-    lldb_private::ConstString str;
-    
-    if (fun->isIntrinsic())
-    {
-        Intrinsic::ID intrinsic_id = (Intrinsic::ID)fun->getIntrinsicID();
-        
-        switch (intrinsic_id)
-        {
-        default:
-            if (log)
-                log->Printf("Unresolved intrinsic \"%s\"", Intrinsic::getName(intrinsic_id).c_str());
-            
-            if (m_error_stream)
-                m_error_stream->Printf("Internal error [IRForTarget]: Call to unhandled compiler intrinsic '%s'\n", Intrinsic::getName(intrinsic_id).c_str());
-                
-            return false;
-        case Intrinsic::memcpy:
-            {
-                static lldb_private::ConstString g_memcpy_str ("memcpy");
-                str = g_memcpy_str;
-            }
-            break;
-        }
-        
-        if (log && str)
-            log->Printf("Resolved intrinsic name \"%s\"", str.GetCString());
-    }
-    else
-    {
-        str.SetCStringWithLength (fun->getName().data(), fun->getName().size());
-    }
-    
-    // Find the address of the function, and the type if possible.
-    
-    clang::NamedDecl *fun_decl = DeclForGlobal (fun);
-    lldb::addr_t fun_addr = LLDB_INVALID_ADDRESS;
-    Value **fun_value_ptr = NULL;
-    
-    if (fun_decl)
-    {
-        if (!m_decl_map->GetFunctionInfo (fun_decl, fun_value_ptr, fun_addr)) 
-        {
-            fun_value_ptr = NULL;
-            
-            if (!m_decl_map->GetFunctionAddress (str, fun_addr))
-            {
-                if (log)
-                    log->Printf("Function \"%s\" had no address", str.GetCString());
-                
-                if (m_error_stream)
-                    m_error_stream->Printf("Error [IRForTarget]: Call to a function '%s' that is not present in the target\n", str.GetCString());
-                
-                return false;
-            }
-        }
-    }
-    else 
-    {
-        if (!m_decl_map->GetFunctionAddress (str, fun_addr))
-        {
-            if (log)
-                log->Printf ("Metadataless function \"%s\" had no address", str.GetCString());
-            
-            if (m_error_stream)
-                m_error_stream->Printf("Error [IRForTarget]: Call to a symbol-only function '%s' that is not present in the target\n", str.GetCString());
-            
-            return false;
-        }
-    }
-        
-    if (log)
-        log->Printf("Found \"%s\" at 0x%llx", str.GetCString(), fun_addr);
-    
-    // Construct the typed pointer to the function.
-    
-    Value *fun_addr_ptr = NULL;
-            
-    if (!fun_value_ptr || !*fun_value_ptr)
-    {
-        IntegerType *intptr_ty = Type::getIntNTy(m_module->getContext(),
-                                                 (m_module->getPointerSize() == Module::Pointer64) ? 64 : 32);
-        FunctionType *fun_ty = fun->getFunctionType();
-        PointerType *fun_ptr_ty = PointerType::getUnqual(fun_ty);
-        Constant *fun_addr_int = ConstantInt::get(intptr_ty, fun_addr, false);
-        fun_addr_ptr = ConstantExpr::getIntToPtr(fun_addr_int, fun_ptr_ty);
-            
-        if (fun_value_ptr)
-            *fun_value_ptr = fun_addr_ptr;
-    }
-            
-    if (fun_value_ptr)
-        fun_addr_ptr = *fun_value_ptr;
-    
-    if (is_bitcast)
-    {
-        Value *val = llvm_call_inst->getCalledValue();
-        
-        ConstantExpr *const_expr = dyn_cast<ConstantExpr>(val);
-        
-        Constant *fun_addr_ptr_cst = dyn_cast<Constant>(fun_addr_ptr);
-        
-        if (!fun_addr_ptr_cst)
-        {
-            if (m_error_stream)
-                m_error_stream->Printf("Error [IRForTarget]: Non-constant source function '%s' has a constant BitCast\n", str.GetCString());
-            
-            return false;
-        }
-            
-        Constant *new_bit_cast = ConstantExpr::getBitCast(fun_addr_ptr_cst, const_expr->getType());
-        
-        llvm_call_inst->setCalledFunction(new_bit_cast);
-    }
-    else
-    {
-        llvm_call_inst->setCalledFunction(fun_addr_ptr);
-    }
-    
-    ConstantArray *func_name = (ConstantArray*)ConstantArray::get(m_module->getContext(), str.GetCString());
-    
-    Value *values[1];
-    values[0] = func_name;
-    ArrayRef<Value*> value_ref(values, 1);
-    
-    MDNode *func_metadata = MDNode::get(m_module->getContext(), value_ref);
-    
-    llvm_call_inst->setMetadata("lldb.call.realName", func_metadata);
-    
-    if (log)
-        log->Printf("Set metadata for %p [%d, \"%s\"]", llvm_call_inst, func_name->isString(), func_name->getAsString().c_str());
-    
-    return true;
-}
-
-bool
 IRForTarget::ResolveCalls(BasicBlock &basic_block)
 {        
     /////////////////////////////////////////////////////////////////////////
@@ -1606,10 +1559,6 @@
         
         CallInst *call = dyn_cast<CallInst>(&inst);
         
-        // MaybeHandleCall handles error reporting; we are silent here
-        if (call && !MaybeHandleCall(call))
-            return false;
-        
         // MaybeHandleCallArguments handles error reporting; we are silent here
         if (call && !MaybeHandleCallArguments(call))
             return false;
@@ -2385,6 +2334,20 @@
         return false;
     }
     
+    ///////////////////////////////
+    // Resolve function pointers
+    //
+    
+    if (!ResolveFunctionPointers(llvm_module, *function))
+    {
+        if (log)
+            log->Printf("ResolveFunctionPointers() failed");
+        
+        // ResolveFunctionPointers() reports its own errors, so we don't do so here
+        
+        return false;
+    }
+    
     //////////////////////////////////
     // Run basic-block level passes
     //





More information about the lldb-commits mailing list