Made expressions that are just casts of pointer
variables be evaluated statically.
Also fixed a bug that caused the results of
statically-evaluated expressions to be materialized
improperly.
This bug also removes some duplicate code.
git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@131042 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Expression/IRForTarget.cpp b/source/Expression/IRForTarget.cpp
index 4581712..8be2a42 100644
--- a/source/Expression/IRForTarget.cpp
+++ b/source/Expression/IRForTarget.cpp
@@ -26,6 +26,7 @@
#include "lldb/Core/Scalar.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Expression/ClangExpressionDeclMap.h"
+#include "lldb/Symbol/ClangASTContext.h"
#include <map>
@@ -35,7 +36,7 @@
IRForTarget::IRForTarget (lldb_private::ClangExpressionDeclMap *decl_map,
bool resolve_vars,
- lldb::ClangExpressionVariableSP *const_result,
+ lldb::ClangExpressionVariableSP &const_result,
lldb_private::Stream *error_stream,
const char *func_name) :
ModulePass(ID),
@@ -44,10 +45,11 @@
m_decl_map(decl_map),
m_CFStringCreateWithBytes(NULL),
m_sel_registerName(NULL),
- m_const_result(const_result),
m_error_stream(error_stream),
m_has_side_effects(false),
- m_result_is_pointer(false)
+ m_result_store(NULL),
+ m_result_is_pointer(false),
+ m_const_result(const_result)
{
}
@@ -87,7 +89,7 @@
{
llvm::Function::iterator bbi;
BasicBlock::iterator ii;
-
+
for (bbi = llvm_function.begin();
bbi != llvm_function.end();
++bbi)
@@ -108,15 +110,33 @@
Value *store_ptr = store_inst->getPointerOperand();
- if (!isa <AllocaInst> (store_ptr))
- return true;
- else
+ std::string ptr_name;
+
+ if (store_ptr->hasName())
+ ptr_name = store_ptr->getNameStr();
+
+ if (isa <AllocaInst> (store_ptr))
break;
+
+ if (ptr_name.find("$__lldb_expr_result") != std::string::npos)
+ {
+ if (ptr_name.find("GV") == std::string::npos)
+ m_result_store = store_inst;
+ }
+ else
+ {
+ return true;
+ }
+
+ break;
}
case Instruction::Load:
case Instruction::Alloca:
case Instruction::GetElementPtr:
+ case Instruction::BitCast:
case Instruction::Ret:
+ case Instruction::ICmp:
+ case Instruction::Br:
break;
}
}
@@ -125,18 +145,133 @@
return false;
}
+clang::NamedDecl *
+IRForTarget::DeclForGlobal (llvm::Module &module, GlobalValue *global_val)
+{
+ lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ NamedMDNode *named_metadata = module.getNamedMetadata("clang.global.decl.ptrs");
+
+ if (!named_metadata)
+ return NULL;
+
+ unsigned num_nodes = named_metadata->getNumOperands();
+ unsigned node_index;
+
+ for (node_index = 0;
+ node_index < num_nodes;
+ ++node_index)
+ {
+ MDNode *metadata_node = named_metadata->getOperand(node_index);
+
+ if (!metadata_node)
+ return NULL;
+
+ if (metadata_node->getNumOperands() != 2)
+ continue;
+
+ if (metadata_node->getOperand(0) != global_val)
+ continue;
+
+ ConstantInt *constant_int = dyn_cast<ConstantInt>(metadata_node->getOperand(1));
+
+ if (!constant_int)
+ return NULL;
+
+ uintptr_t ptr = constant_int->getZExtValue();
+
+ return reinterpret_cast<clang::NamedDecl *>(ptr);
+ }
+
+ return NULL;
+}
+
void
IRForTarget::MaybeSetConstantResult (llvm::Constant *initializer,
const lldb_private::ConstString &name,
lldb_private::TypeFromParser type)
{
- if (!m_const_result)
+ if (llvm::ConstantExpr *init_expr = dyn_cast<llvm::ConstantExpr>(initializer))
+ {
+ switch (init_expr->getOpcode())
+ {
+ default:
+ return;
+ case Instruction::IntToPtr:
+ MaybeSetConstantResult (init_expr->getOperand(0), name, type);
+ return;
+ }
+ }
+ else if (llvm::ConstantInt *init_int = dyn_cast<llvm::ConstantInt>(initializer))
+ {
+ m_const_result = m_decl_map->BuildIntegerVariable(name, type, init_int->getValue());
+ }
+}
+
+void
+IRForTarget::MaybeSetCastResult (llvm::Module &llvm_module, lldb_private::TypeFromParser type)
+{
+ lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
+
+ if (!m_result_store)
return;
- if (llvm::ConstantInt *init_int = dyn_cast<llvm::ConstantInt>(initializer))
+ LoadInst *original_load = NULL;
+
+ for (llvm::Value *current_value = m_result_store->getValueOperand(), *next_value;
+ current_value != NULL;
+ current_value = next_value)
{
- *m_const_result = m_decl_map->BuildIntegerVariable(name, type, init_int->getValue());
+ CastInst *cast_inst = dyn_cast<CastInst>(current_value);
+ LoadInst *load_inst = dyn_cast<LoadInst>(current_value);
+
+ if (cast_inst)
+ {
+ next_value = cast_inst->getOperand(0);
+ }
+ else if(load_inst)
+ {
+ if (isa<LoadInst>(load_inst->getPointerOperand()))
+ {
+ next_value = load_inst->getPointerOperand();
+ }
+ else
+ {
+ original_load = load_inst;
+ break;
+ }
+ }
+ else
+ {
+ return;
+ }
}
+
+ Value *loaded_value = original_load->getPointerOperand();
+ GlobalVariable *loaded_global = dyn_cast<GlobalVariable>(loaded_value);
+
+ if (!loaded_global)
+ return;
+
+ clang::NamedDecl *loaded_decl = DeclForGlobal(llvm_module, loaded_global);
+
+ if (!loaded_decl)
+ return;
+
+ clang::VarDecl *loaded_var = dyn_cast<clang::VarDecl>(loaded_decl);
+
+ if (!loaded_var)
+ return;
+
+ if (log)
+ {
+ lldb_private::StreamString type_desc_stream;
+ type.DumpTypeDescription(&type_desc_stream);
+
+ log->Printf("Type to cast variable to: \"%s\"", type_desc_stream.GetString().c_str());
+ }
+
+ m_const_result = m_decl_map->BuildCastVariable(m_result_name, loaded_var, type);
}
bool
@@ -214,64 +349,50 @@
return false;
}
- // Find the metadata and follow it to the VarDecl
-
- NamedMDNode *named_metadata = llvm_module.getNamedMetadata("clang.global.decl.ptrs");
-
- if (!named_metadata)
+ clang::NamedDecl *result_decl = DeclForGlobal (llvm_module, result_global);
+ if (!result_decl)
{
if (log)
- log->PutCString("No global metadata");
+ log->PutCString("Result variable doesn't have a corresponding Decl");
if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: No metadata\n");
+ m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s) does not have a corresponding Clang entity\n", result_name);
return false;
}
-
- unsigned num_nodes = named_metadata->getNumOperands();
- unsigned node_index;
- MDNode *metadata_node = NULL;
-
- for (node_index = 0;
- node_index < num_nodes;
- ++node_index)
+ if (log)
{
- metadata_node = named_metadata->getOperand(node_index);
+ std::string decl_desc_str;
+ raw_string_ostream decl_desc_stream(decl_desc_str);
+ result_decl->print(decl_desc_stream);
+ decl_desc_stream.flush();
- if (metadata_node->getNumOperands() != 2)
- continue;
-
- if (metadata_node->getOperand(0) == result_global)
- break;
+ log->Printf("Found result decl: \"%s\"", decl_desc_str.c_str());
}
- if (!metadata_node)
+ clang::VarDecl *result_var = dyn_cast<clang::VarDecl>(result_decl);
+ if (!result_var)
{
if (log)
- log->PutCString("Couldn't find result metadata");
+ log->PutCString("Result variable Decl isn't a VarDecl");
if (m_error_stream)
- m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s) is a global variable, but has no metadata\n", result_name);
+ m_error_stream->Printf("Internal error [IRForTarget]: Result variable (%s)'s corresponding Clang entity isn't a variable\n", result_name);
return false;
}
-
- ConstantInt *constant_int = dyn_cast<ConstantInt>(metadata_node->getOperand(1));
-
- lldb::addr_t result_decl_intptr = constant_int->getZExtValue();
- clang::VarDecl *result_decl = reinterpret_cast<clang::VarDecl *>(result_decl_intptr);
-
// Get the next available result name from m_decl_map and create the persistent
// variable for it
lldb_private::TypeFromParser result_decl_type;
+ // If the result is an Lvalue, it is emitted as a pointer; see
+ // ASTResultSynthesizer::SynthesizeBodyResult.
if (m_result_is_pointer)
{
- clang::QualType pointer_qual_type = result_decl->getType();
+ clang::QualType pointer_qual_type = result_var->getType();
const clang::Type *pointer_type = pointer_qual_type.getTypePtr();
const clang::PointerType *pointer_pointertype = dyn_cast<clang::PointerType>(pointer_type);
@@ -293,18 +414,19 @@
}
else
{
- result_decl_type = lldb_private::TypeFromParser(result_decl->getType().getAsOpaquePtr(),
+ result_decl_type = lldb_private::TypeFromParser(result_var->getType().getAsOpaquePtr(),
&result_decl->getASTContext());
}
+ if (log)
+ {
+ lldb_private::StreamString type_desc_stream;
+ result_decl_type.DumpTypeDescription(&type_desc_stream);
+
+ log->Printf("Result decl type: \"%s\"", type_desc_stream.GetString().c_str());
+ }
+
m_result_name = m_decl_map->GetPersistentResultName();
- // If the result is an Lvalue, it is emitted as a pointer; see
- // ASTResultSynthesizer::SynthesizeBodyResult.
- m_decl_map->AddPersistentVariable(result_decl,
- m_result_name,
- result_decl_type,
- true,
- m_result_is_pointer);
if (log)
log->Printf("Creating a new result global: \"%s\"", m_result_name.GetCString());
@@ -325,8 +447,8 @@
// ClangExpressionDeclMap::DoMaterialize, and the name of the variable is
// fixed up.
- ConstantInt *new_constant_int = ConstantInt::get(constant_int->getType(),
- result_decl_intptr,
+ ConstantInt *new_constant_int = ConstantInt::get(llvm::Type::getInt64Ty(llvm_module.getContext()),
+ reinterpret_cast<uint64_t>(result_decl),
false);
llvm::Value* values[2];
@@ -334,6 +456,7 @@
values[1] = new_constant_int;
MDNode *persistent_global_md = MDNode::get(llvm_module.getContext(), values, 2);
+ NamedMDNode *named_metadata = llvm_module.getNamedMetadata("clang.global.decl.ptrs");
named_metadata->addOperand(persistent_global_md);
if (log)
@@ -384,8 +507,20 @@
}
else
{
+ if (!m_has_side_effects && lldb_private::ClangASTContext::IsPointerType (result_decl_type.GetOpaqueQualType()))
+ {
+ MaybeSetCastResult (llvm_module, result_decl_type);
+ }
+
result_global->replaceAllUsesWith(new_result_global);
}
+
+ if (!m_const_result)
+ m_decl_map->AddPersistentVariable(result_decl,
+ m_result_name,
+ result_decl_type,
+ true,
+ m_result_is_pointer);
result_global->eraseFromParent();
@@ -1047,45 +1182,6 @@
return true;
}
-static clang::NamedDecl *
-DeclForGlobalValue(Module &module, GlobalValue *global_value)
-{
- NamedMDNode *named_metadata = module.getNamedMetadata("clang.global.decl.ptrs");
-
- if (!named_metadata)
- return NULL;
-
- unsigned num_nodes = named_metadata->getNumOperands();
- unsigned node_index;
-
- for (node_index = 0;
- node_index < num_nodes;
- ++node_index)
- {
- MDNode *metadata_node = named_metadata->getOperand(node_index);
-
- if (!metadata_node)
- return NULL;
-
- if (metadata_node->getNumOperands() != 2)
- continue;
-
- if (metadata_node->getOperand(0) != global_value)
- continue;
-
- ConstantInt *constant_int = dyn_cast<ConstantInt>(metadata_node->getOperand(1));
-
- if (!constant_int)
- return NULL;
-
- uintptr_t ptr = constant_int->getZExtValue();
-
- return reinterpret_cast<clang::NamedDecl *>(ptr);
- }
-
- return NULL;
-}
-
// This function does not report errors; its callers are responsible.
bool
IRForTarget::MaybeHandleVariable (Module &llvm_module, Value *llvm_value_ptr)
@@ -1110,7 +1206,7 @@
}
else if (GlobalVariable *global_variable = dyn_cast<GlobalVariable>(llvm_value_ptr))
{
- clang::NamedDecl *named_decl = DeclForGlobalValue(llvm_module, global_variable);
+ clang::NamedDecl *named_decl = DeclForGlobal(llvm_module, global_variable);
if (!named_decl)
{
@@ -1331,7 +1427,7 @@
str.SetCStringWithLength (fun->getName().data(), fun->getName().size());
}
- clang::NamedDecl *fun_decl = DeclForGlobalValue (llvm_module, fun);
+ clang::NamedDecl *fun_decl = DeclForGlobal (llvm_module, fun);
lldb::addr_t fun_addr = LLDB_INVALID_ADDRESS;
Value **fun_value_ptr = NULL;
@@ -1445,7 +1541,7 @@
if (log)
log->Printf("Examining %s, DeclForGlobalValue returns %p",
(*global).getName().str().c_str(),
- DeclForGlobalValue(llvm_module, global));
+ DeclForGlobal(llvm_module, global));
if ((*global).getName().str().find("OBJC_IVAR") == 0)
{
@@ -1457,7 +1553,7 @@
return false;
}
}
- else if (DeclForGlobalValue(llvm_module, global))
+ else if (DeclForGlobal(llvm_module, global))
{
if (!MaybeHandleVariable (llvm_module, global))
{
@@ -1882,6 +1978,9 @@
return false;
}
+ if (m_const_result)
+ return true;
+
///////////////////////////////////////////////////////////////////////////////
// Fix all Objective-C constant strings to use NSStringWithCString:encoding:
//