[Lldb-commits] [lldb] r108380 - in /lldb/trunk/source: Commands/CommandObjectExpression.cpp Expression/IRForTarget.cpp

Sean Callanan scallanan at apple.com
Wed Jul 14 16:40:29 PDT 2010


Author: spyffe
Date: Wed Jul 14 18:40:29 2010
New Revision: 108380

URL: http://llvm.org/viewvc/llvm-project?rev=108380&view=rev
Log:
Fixes to the IR generator in the expression parser
to correctly unfold constant-folded global variables.
Also added code to JIT the expression.  Simple 
expressions are now JIT compiled successfully.

Modified:
    lldb/trunk/source/Commands/CommandObjectExpression.cpp
    lldb/trunk/source/Expression/IRForTarget.cpp

Modified: lldb/trunk/source/Commands/CommandObjectExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectExpression.cpp?rev=108380&r1=108379&r2=108380&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectExpression.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectExpression.cpp Wed Jul 14 18:40:29 2010
@@ -270,122 +270,158 @@
                 log->Printf("Code cannot be interpreted and must be run in the target.");
             success = clang_expr.PrepareIRForTarget (expr_local_vars);
         }
+        
+        if (!success)
+        {
+            error_stream.PutCString ("error: expression couldn't be converted to IR\n");
+            return false;
+        }
+        
+        if (canInterpret)
+        {
+            // TODO interpret IR
+            return false;
+        }
+        else
+        {
+            if (!clang_expr.JITFunction (m_exe_ctx, "___clang_expr"))
+            {
+                error_stream.PutCString ("error: IR could not be JIT compiled\n");
+                return false;
+            }
+            
+            if (!clang_expr.WriteJITCode (m_exe_ctx))
+            {
+                error_stream.PutCString ("error: JIT code could not be written to the target\n");
+                return false;
+            }
+            
+            lldb::addr_t function_address(clang_expr.GetFunctionAddress ("___clang_expr"));
+            
+            if (function_address == LLDB_INVALID_ADDRESS)
+            {
+                error_stream.PutCString ("JIT compiled code's address couldn't be found\n");
+                return false;
+            }
+            
+            log->Printf("Function is at 0x%llx", (uint64_t)function_address);
+        }
     }
     else
     {
         success = (clang_expr.ConvertExpressionToDWARF (expr_local_vars, dwarf_opcodes) == 0);
-    }
-    
-    if (!success)
-    {
-        error_stream.PutCString ("error: expression couldn't be translated to DWARF\n");
-        return false;
-    }
-    
-    //////////////////////////////////////////
-    // Evaluate the generated DWARF opcodes
-    //
-
-    DataExtractor dwarf_opcodes_data (dwarf_opcodes.GetData (), dwarf_opcodes.GetSize (), eByteOrderHost, 8);
-    DWARFExpression dwarf_expr (dwarf_opcodes_data, 0, dwarf_opcodes_data.GetByteSize (), NULL);
-    
-    dwarf_expr.SetExpressionLocalVariableList(&expr_local_vars);
-    
-    if (log)
-    {
-        StreamString stream_string;
         
-        log->PutCString ("Expression parsed ok, dwarf opcodes:");
+        if (!success)
+        {
+            error_stream.PutCString ("error: expression couldn't be translated to DWARF\n");
+            return false;
+        }
         
-        stream_string.PutCString ("\n");
-        stream_string.IndentMore ();
-        dwarf_expr.GetDescription (&stream_string, lldb::eDescriptionLevelVerbose);
-        stream_string.IndentLess ();
-        stream_string.EOL ();
+        //////////////////////////////////////////
+        // Evaluate the generated DWARF opcodes
+        //
+        
+        DataExtractor dwarf_opcodes_data (dwarf_opcodes.GetData (), dwarf_opcodes.GetSize (), eByteOrderHost, 8);
+        DWARFExpression dwarf_expr (dwarf_opcodes_data, 0, dwarf_opcodes_data.GetByteSize (), NULL);
+        
+        dwarf_expr.SetExpressionLocalVariableList(&expr_local_vars);
+        
+        if (log)
+        {
+            StreamString stream_string;
+            
+            log->PutCString ("Expression parsed ok, dwarf opcodes:");
+            
+            stream_string.PutCString ("\n");
+            stream_string.IndentMore ();
+            dwarf_expr.GetDescription (&stream_string, lldb::eDescriptionLevelVerbose);
+            stream_string.IndentLess ();
+            stream_string.EOL ();
+            
+            log->PutCString (stream_string.GetString ().c_str ());
+        }
+        
+        clang::ASTContext *ast_context = clang_expr.GetASTContext ();
+        Value expr_result;
+        Error expr_error;
+        success = dwarf_expr.Evaluate (&m_exe_ctx, ast_context, NULL, expr_result, &expr_error);
+        
+        if (!success)
+        {
+            error_stream.Printf ("error: couldn't evaluate DWARF expression: %s\n", expr_error.AsCString ());
+            return false;
+        }
+        
+        ///////////////////////////////////////
+        // Interpret the result and print it
+        //
+        
+        lldb::Format format = m_options.format;
+        
+        // Resolve any values that are possible
+        expr_result.ResolveValue (&m_exe_ctx, ast_context);
+        
+        if (expr_result.GetContextType () == Value::eContextTypeInvalid &&
+            expr_result.GetValueType () == Value::eValueTypeScalar &&
+            format == eFormatDefault)
+        {
+            // The expression result is just a scalar with no special formatting
+            expr_result.GetScalar ().GetValue (&output_stream, m_options.show_types);
+            output_stream.EOL ();
+            return true;
+        }
+        
+        // The expression result is more complext and requires special handling
+        DataExtractor data;
+        expr_error = expr_result.GetValueAsData (&m_exe_ctx, ast_context, data, 0);
+        
+        if (!expr_error.Success ())
+        {
+            error_stream.Printf ("error: couldn't resolve result value: %s\n", expr_error.AsCString ());
+            return false;
+        }
+        
+        if (format == eFormatDefault)
+            format = expr_result.GetValueDefaultFormat ();
+        
+        void *clang_type = expr_result.GetValueOpaqueClangQualType ();
+        
+        if (clang_type)
+        {
+            if (m_options.show_types)
+                Type::DumpClangTypeName (&output_stream, clang_type);
+            
+            Type::DumpValue (&m_exe_ctx,                // The execution context for memory and variable access
+                             ast_context,               // The ASTContext that the clang type belongs to
+                             clang_type,                // The opaque clang type we want to dump that value of
+                             &output_stream,            // Stream to dump to
+                             format,                    // Format to use when dumping
+                             data,                      // A buffer containing the bytes for the clang type
+                             0,                         // Byte offset within "data" where value is
+                             data.GetByteSize (),       // Size in bytes of the value we are dumping
+                             0,                         // Bitfield bit size
+                             0,                         // Bitfield bit offset
+                             m_options.show_types,      // Show types?
+                             m_options.show_summary,    // Show summary?
+                             m_options.debug,           // Debug logging output?
+                             UINT32_MAX);               // Depth to dump in case this is an aggregate type
+        }
+        else
+        {
+            data.Dump (&output_stream,          // Stream to dump to
+                       0,                       // Byte offset within "data"
+                       format,                  // Format to use when dumping
+                       data.GetByteSize (),     // Size in bytes of each item we are dumping
+                       1,                       // Number of items to dump
+                       UINT32_MAX,              // Number of items per line
+                       LLDB_INVALID_ADDRESS,    // Invalid address, don't show any offset/address context
+                       0,                       // Bitfield bit size
+                       0);                      // Bitfield bit offset
+        }
+        output_stream.EOL();
         
-        log->PutCString (stream_string.GetString ().c_str ());
-    }
-
-    clang::ASTContext *ast_context = clang_expr.GetASTContext ();
-    Value expr_result;
-    Error expr_error;
-    success = dwarf_expr.Evaluate (&m_exe_ctx, ast_context, NULL, expr_result, &expr_error);
-    
-    if (!success)
-    {
-        error_stream.Printf ("error: couldn't evaluate DWARF expression: %s\n", expr_error.AsCString ());
-        return false;
-    }
-    
-    ///////////////////////////////////////
-    // Interpret the result and print it
-    //
-    
-    lldb::Format format = m_options.format;
-
-    // Resolve any values that are possible
-    expr_result.ResolveValue (&m_exe_ctx, ast_context);
-
-    if (expr_result.GetContextType () == Value::eContextTypeInvalid &&
-        expr_result.GetValueType () == Value::eValueTypeScalar &&
-        format == eFormatDefault)
-    {
-        // The expression result is just a scalar with no special formatting
-        expr_result.GetScalar ().GetValue (&output_stream, m_options.show_types);
-        output_stream.EOL ();
         return true;
     }
-    
-    // The expression result is more complext and requires special handling
-    DataExtractor data;
-    expr_error = expr_result.GetValueAsData (&m_exe_ctx, ast_context, data, 0);
-    
-    if (!expr_error.Success ())
-    {
-        error_stream.Printf ("error: couldn't resolve result value: %s\n", expr_error.AsCString ());
-        return false;
-    }
-
-    if (format == eFormatDefault)
-        format = expr_result.GetValueDefaultFormat ();
-
-    void *clang_type = expr_result.GetValueOpaqueClangQualType ();
-    
-    if (clang_type)
-    {
-        if (m_options.show_types)
-            Type::DumpClangTypeName (&output_stream, clang_type);
-
-        Type::DumpValue (&m_exe_ctx,                // The execution context for memory and variable access
-                         ast_context,               // The ASTContext that the clang type belongs to
-                         clang_type,                // The opaque clang type we want to dump that value of
-                         &output_stream,            // Stream to dump to
-                         format,                    // Format to use when dumping
-                         data,                      // A buffer containing the bytes for the clang type
-                         0,                         // Byte offset within "data" where value is
-                         data.GetByteSize (),       // Size in bytes of the value we are dumping
-                         0,                         // Bitfield bit size
-                         0,                         // Bitfield bit offset
-                         m_options.show_types,      // Show types?
-                         m_options.show_summary,    // Show summary?
-                         m_options.debug,           // Debug logging output?
-                         UINT32_MAX);               // Depth to dump in case this is an aggregate type
-    }
-    else
-    {
-        data.Dump (&output_stream,          // Stream to dump to
-                   0,                       // Byte offset within "data"
-                   format,                  // Format to use when dumping
-                   data.GetByteSize (),     // Size in bytes of each item we are dumping
-                   1,                       // Number of items to dump
-                   UINT32_MAX,              // Number of items per line
-                   LLDB_INVALID_ADDRESS,    // Invalid address, don't show any offset/address context
-                   0,                       // Bitfield bit size
-                   0);                      // Bitfield bit offset
-    }
-    output_stream.EOL();
-    
-    return true;
 }
 
 bool

Modified: lldb/trunk/source/Expression/IRForTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/IRForTarget.cpp?rev=108380&r1=108379&r2=108380&view=diff
==============================================================================
--- lldb/trunk/source/Expression/IRForTarget.cpp (original)
+++ lldb/trunk/source/Expression/IRForTarget.cpp Wed Jul 14 18:40:29 2010
@@ -129,7 +129,8 @@
     return true;
 }
 
-static std::string PrintValue(llvm::Value *V, bool truncate = false)
+static std::string 
+PrintValue(llvm::Value *V, bool truncate = false)
 {
     std::string s;
     raw_string_ostream rso(s);
@@ -140,6 +141,109 @@
     return s;
 }
 
+// UnfoldConstant operates on a constant [C] which has just been replaced with a value
+// [new_value].  We assume that new_value has been properly placed early in the function,
+// most likely somewhere in front of the first instruction in the entry basic block 
+// [first_entry_instruction].  
+//
+// UnfoldConstant reads through the uses of C and replaces C in those uses with new_value.
+// Where those uses are constants, the function generates new instructions to compute the
+// result of the new, non-constant expression and places them before first_entry_instruction.  
+// These instructions replace the constant uses, so UnfoldConstant calls itself recursively
+// for those.
+
+static bool
+UnfoldConstant(llvm::Constant *C, llvm::Value *new_value, llvm::Instruction *first_entry_instruction)
+{
+    lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
+
+    Value::use_iterator ui;
+    
+    for (ui = C->use_begin();
+         ui != C->use_end();
+         ++ui)
+    {
+        User *user = *ui;
+        
+        if (Constant *constant = dyn_cast<Constant>(user))
+        {
+            // synthesize a new non-constant equivalent of the constant
+            
+            if (ConstantExpr *constant_expr = dyn_cast<ConstantExpr>(constant))
+            {
+                switch (constant_expr->getOpcode())
+                {
+                default:
+                    if (log)
+                        log->Printf("Unhandled constant expression type: %s", PrintValue(constant_expr).c_str());
+                    return false;
+                case Instruction::BitCast:
+                    {
+                        // UnaryExpr
+                        //   OperandList[0] is value
+                        
+                        Value *s = constant_expr->getOperand(0);
+                        
+                        if (s == C)
+                            s = new_value;
+                        
+                        BitCastInst *bit_cast(new BitCastInst(s, C->getType(), "", first_entry_instruction));
+                        
+                        UnfoldConstant(constant_expr, bit_cast, first_entry_instruction);
+                    }
+                    break;
+                case Instruction::GetElementPtr:
+                    {
+                        // GetElementPtrConstantExpr
+                        //   OperandList[0] is base
+                        //   OperandList[1]... are indices
+                        
+                        Value *ptr = constant_expr->getOperand(0);
+                        
+                        if (ptr == C)
+                            ptr = new_value;
+                        
+                        SmallVector<Value*, 16> indices;
+                        
+                        unsigned operand_index;
+                        unsigned num_operands = constant_expr->getNumOperands();
+                        
+                        for (operand_index = 1;
+                             operand_index < num_operands;
+                             ++operand_index)
+                        {
+                            Value *operand = constant_expr->getOperand(operand_index);
+                            
+                            if (operand == C)
+                                operand = new_value;
+                            
+                            indices.push_back(operand);
+                        }
+                        
+                        GetElementPtrInst *get_element_ptr(GetElementPtrInst::Create(ptr, indices.begin(), indices.end(), "", first_entry_instruction));
+                        
+                        UnfoldConstant(constant_expr, get_element_ptr, first_entry_instruction);
+                    }
+                    break;
+                }
+            }
+            else
+            {
+                if (log)
+                    log->Printf("Unhandled constant type: %s", PrintValue(constant).c_str());
+                return false;
+            }
+        }
+        else
+        {
+            // simple fall-through case for non-constants
+            user->replaceUsesOfWith(C, new_value);
+        }
+    }
+    
+    return true;
+}
+
 bool 
 IRForTarget::replaceVariables(Module &M, Function *F)
 {
@@ -203,7 +307,10 @@
         GetElementPtrInst *get_element_ptr = GetElementPtrInst::Create(argument, offset_int, "", first_entry_instruction);
         BitCastInst *bit_cast = new BitCastInst(get_element_ptr, value->getType(), "", first_entry_instruction);
         
-        value->replaceAllUsesWith(bit_cast);
+        if (Constant *constant = dyn_cast<Constant>(value))
+            UnfoldConstant(constant, bit_cast, first_entry_instruction);
+        else
+            value->replaceAllUsesWith(bit_cast);
     }
     
     if (log)





More information about the lldb-commits mailing list