[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