diff options
| author | Sean Callanan <scallanan@apple.com> | 2010-08-12 01:56:52 +0000 |
|---|---|---|
| committer | Sean Callanan <scallanan@apple.com> | 2010-08-12 01:56:52 +0000 |
| commit | d1e5b439c9a48255f1f88bf99f42547a81bef07e (patch) | |
| tree | 7836354617fa7cd619bbfd8e48c442902302a9b3 /lldb/source/Expression/IRForTarget.cpp | |
| parent | 74491bb52c7ff7f8ddf4df715c1a43a949edefed (diff) | |
| download | bcm5719-llvm-d1e5b439c9a48255f1f88bf99f42547a81bef07e.tar.gz bcm5719-llvm-d1e5b439c9a48255f1f88bf99f42547a81bef07e.zip | |
Added automatically generated result variables for each
expression. It is now possible to do things like this:
(lldb) expr int $i = 5; $i + 1
$0 = (int) 6
(lldb) expr $i + 3
$1 = (int) 8
(lldb) expr $1 + $0
$2 = (int) 14
As a bonus, this allowed us to move printing of
expression results into the ClangPersistentVariable
class. This code needs a bit of refactoring -- in
particular, ClangExpressionDeclMap has eaten one too
many bacteria and needs to undergo mitosis -- but the
infrastructure appears to be holding up nicely.
llvm-svn: 110896
Diffstat (limited to 'lldb/source/Expression/IRForTarget.cpp')
| -rw-r--r-- | lldb/source/Expression/IRForTarget.cpp | 140 |
1 files changed, 137 insertions, 3 deletions
diff --git a/lldb/source/Expression/IRForTarget.cpp b/lldb/source/Expression/IRForTarget.cpp index 9541945eebc..ca1aeb4327c 100644 --- a/lldb/source/Expression/IRForTarget.cpp +++ b/lldb/source/Expression/IRForTarget.cpp @@ -14,6 +14,7 @@ #include "llvm/Instructions.h" #include "llvm/Module.h" #include "llvm/Target/TargetData.h" +#include "llvm/ValueSymbolTable.h" #include "clang/AST/ASTContext.h" @@ -55,6 +56,129 @@ IRForTarget::~IRForTarget() { } +bool +IRForTarget::createResultVariable(llvm::Module &M, + llvm::Function &F) +{ + lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); + + // Find the result variable + + Value *result_value = M.getNamedValue("___clang_expr_result"); + + if (!result_value) + { + if (log) + log->PutCString("Couldn't find result variable"); + return false; + } + + if (log) + log->Printf("Found result in the IR: %s", PrintValue(result_value, false).c_str()); + + GlobalVariable *result_global = dyn_cast<GlobalVariable>(result_value); + + if (!result_global) + { + if (log) + log->PutCString("Result variable isn't a GlobalVariable"); + return false; + } + + // Find the metadata and follow it to the VarDecl + + NamedMDNode *named_metadata = M.getNamedMetadata("clang.global.decl.ptrs"); + + if (!named_metadata) + { + if (log) + log->PutCString("No global metadata"); + + 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) + { + metadata_node = named_metadata->getOperand(node_index); + + if (metadata_node->getNumOperands() != 2) + continue; + + if (metadata_node->getOperand(0) == result_global) + break; + } + + if (!metadata_node) + { + if (log) + log->PutCString("Couldn't find result metadata"); + return false; + } + + ConstantInt *constant_int = dyn_cast<ConstantInt>(metadata_node->getOperand(1)); + + uint64_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 (result_decl->getType().getAsOpaquePtr(), + &result_decl->getASTContext()); + std::string new_result_name; + + m_decl_map->GetPersistentResultName(new_result_name); + m_decl_map->AddPersistentVariable(new_result_name.c_str(), result_decl_type); + + if (log) + log->Printf("Creating a new result global: %s", new_result_name.c_str()); + + // Construct a new result global and set up its metadata + + GlobalVariable *new_result_global = new GlobalVariable(M, + result_global->getType()->getElementType(), + false, /* not constant */ + GlobalValue::ExternalLinkage, + NULL, /* no initializer */ + new_result_name.c_str()); + + // It's too late in compilation to create a new VarDecl for this, but we don't + // need to. We point the metadata at the old VarDecl. This creates an odd + // anomaly: a variable with a Value whose name is something like $0 and a + // Decl whose name is ___clang_expr_result. This condition is handled in + // ClangExpressionDeclMap::DoMaterialize, and the name of the variable is + // fixed up. + + ConstantInt *new_constant_int = ConstantInt::get(constant_int->getType(), + result_decl_intptr, + false); + + llvm::Value* values[2]; + values[0] = new_result_global; + values[1] = new_constant_int; + + MDNode *persistent_global_md = MDNode::get(M.getContext(), values, 2); + named_metadata->addOperand(persistent_global_md); + + if (log) + log->Printf("Replacing %s with %s", + PrintValue(result_global).c_str(), + PrintValue(new_result_global).c_str()); + + result_global->replaceAllUsesWith(new_result_global); + result_global->eraseFromParent(); + + return true; +} + static bool isObjCSelectorRef(Value *V) { GlobalVariable *GV = dyn_cast<GlobalVariable>(V); @@ -234,9 +358,12 @@ IRForTarget::RewritePersistentAlloc(llvm::Instruction *persistent_alloc, uintptr_t ptr = constant_int->getZExtValue(); - clang::NamedDecl *decl = reinterpret_cast<clang::NamedDecl *>(ptr); + clang::VarDecl *decl = reinterpret_cast<clang::VarDecl *>(ptr); - if (!m_decl_map->AddPersistentVariable(decl)) + lldb_private::TypeFromParser result_decl_type (decl->getType().getAsOpaquePtr(), + &decl->getASTContext()); + + if (!m_decl_map->AddPersistentVariable(decl->getName().str().c_str(), result_decl_type)) return false; GlobalVariable *persistent_global = new GlobalVariable(M, @@ -760,7 +887,7 @@ IRForTarget::replaceVariables(Module &M, Function &F) if (log) log->Printf(" %s (%s) placed at %d", - decl->getIdentifier()->getNameStart(), + value->getName().str().c_str(), PrintValue(value, true).c_str(), offset); @@ -797,6 +924,13 @@ IRForTarget::runOnModule(Module &M) Function::iterator bbi; + //////////////////////////////////////////////////////////// + // Replace __clang_expr_result with a persistent variable + // + + if (!createResultVariable(M, *function)) + return false; + ////////////////////////////////// // Run basic-block level passes // |

