diff options
Diffstat (limited to 'lldb/source/Expression/IRForTarget.cpp')
-rw-r--r-- | lldb/source/Expression/IRForTarget.cpp | 208 |
1 files changed, 185 insertions, 23 deletions
diff --git a/lldb/source/Expression/IRForTarget.cpp b/lldb/source/Expression/IRForTarget.cpp index a6b50e59127..8876109448e 100644 --- a/lldb/source/Expression/IRForTarget.cpp +++ b/lldb/source/Expression/IRForTarget.cpp @@ -11,7 +11,11 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/InstrTypes.h" +#include "llvm/Instructions.h" #include "llvm/Module.h" +#include "llvm/Target/TargetData.h" + +#include "clang/AST/ASTContext.h" #include "lldb/Core/dwarf.h" #include "lldb/Core/Log.h" @@ -24,9 +28,11 @@ using namespace llvm; IRForTarget::IRForTarget(const void *pid, - lldb_private::ClangExpressionDeclMap *decl_map) : + lldb_private::ClangExpressionDeclMap *decl_map, + const llvm::TargetData *target_data) : ModulePass(pid), - m_decl_map(decl_map) + m_decl_map(decl_map), + m_target_data(target_data) { } @@ -34,38 +40,177 @@ IRForTarget::~IRForTarget() { } -bool -IRForTarget::runOnBasicBlock(BasicBlock &BB) +static clang::NamedDecl * +DeclForGlobalValue(llvm::Module &module, + llvm::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) + return NULL; + + 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; +} + +bool +IRForTarget::MaybeHandleVariable(Module &M, + lldb_private::ClangExpressionDeclMap *DM, + llvm::Value *V, + bool Store) { lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); + + if (GlobalVariable *global_variable = dyn_cast<GlobalVariable>(V)) + { + clang::NamedDecl *named_decl = DeclForGlobalValue(M, global_variable); + + const llvm::Type *value_type = global_variable->getType(); + size_t value_size = m_target_data->getTypeStoreSize(value_type); + off_t value_alignment = m_target_data->getPrefTypeAlignment(value_type); + + if (named_decl && !DM->AddValueToStruct(V, named_decl, value_size, value_alignment)) + return false; + } + + return true; +} + +bool +IRForTarget::runOnBasicBlock(Module &M, BasicBlock &BB) +{ ///////////////////////////////////////////////////////////////////////// // Prepare the current basic block for execution in the remote process // + llvm::BasicBlock::iterator ii; + + for (ii = BB.begin(); + ii != BB.end(); + ++ii) + { + Instruction &inst = *ii; + + if (LoadInst *load = dyn_cast<LoadInst>(&inst)) + if (!MaybeHandleVariable(M, m_decl_map, load->getPointerOperand(), false)) + return false; + + if (StoreInst *store = dyn_cast<StoreInst>(&inst)) + if (!MaybeHandleVariable(M, m_decl_map, store->getPointerOperand(), false)) + return false; + } + + return true; +} + +static std::string PrintValue(llvm::Value *V, bool truncate = false) +{ + std::string s; + raw_string_ostream rso(s); + V->print(rso); + rso.flush(); + if (truncate) + s.resize(s.length() - 1); + return s; +} + +bool +IRForTarget::replaceVariables(Module &M, Function *F) +{ + lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); + + m_decl_map->DoStructLayout(); + + if (log) + log->Printf("Element arrangement:"); + + uint32_t num_elements; + uint32_t element_index; + + size_t size; + off_t alignment; + + if (!m_decl_map->GetStructInfo (num_elements, size, alignment)) + return false; + + Function::arg_iterator iter(F->getArgumentList().begin()); + + if (iter == F->getArgumentList().end()) + return false; + + llvm::Argument *argument = iter; + + if (!argument->getName().equals("___clang_arg")) + return false; + if (log) + log->Printf("Arg: %s", PrintValue(argument).c_str()); + + llvm::BasicBlock &entry_block(F->getEntryBlock()); + llvm::Instruction *first_entry_instruction(entry_block.getFirstNonPHIOrDbg()); + + if (!first_entry_instruction) + return false; + + LLVMContext &context(M.getContext()); + const IntegerType *offset_type(Type::getInt32Ty(context)); + + if (!offset_type) + return false; + + for (element_index = 0; element_index < num_elements; ++element_index) { - log->Printf("Preparing basic block %s:", - BB.hasName() ? BB.getNameStr().c_str() : "[anonymous]"); + const clang::NamedDecl *decl; + llvm::Value *value; + off_t offset; - llvm::BasicBlock::iterator ii; + if (!m_decl_map->GetStructElement (decl, value, offset, element_index)) + return false; - for (ii = BB.begin(); - ii != BB.end(); - ++ii) - { - llvm::Instruction &inst = *ii; - - std::string s; - raw_string_ostream os(s); - - inst.print(os); - - if (log) - log->Printf(" %s", s.c_str()); - } + if (log) + log->Printf(" %s (%s) placed at %d", + decl->getIdentifier()->getNameStart(), + PrintValue(value, true).c_str(), + offset); + + ConstantInt *offset_int(ConstantInt::getSigned(offset_type, offset)); + 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 (log) + log->Printf("Total structure [align %d, size %d]", alignment, size); + return true; } @@ -90,7 +235,24 @@ IRForTarget::runOnModule(Module &M) bbi != function->end(); ++bbi) { - runOnBasicBlock(*bbi); + if (!runOnBasicBlock(M, *bbi)) + return false; + } + + if (!replaceVariables(M, function)) + return false; + + if (log) + { + for (bbi = function->begin(); + bbi != function->end(); + ++bbi) + { + log->Printf("Rewrote basic block %s for running: \n%s", + bbi->hasName() ? bbi->getNameStr().c_str() : "[anonymous]", + PrintValue(bbi).c_str()); + } + } return true; @@ -98,7 +260,7 @@ IRForTarget::runOnModule(Module &M) void IRForTarget::assignPassManager(PMStack &PMS, - PassManagerType T) + PassManagerType T) { } |