2010-07-03 01:35:46 +00:00
|
|
|
//===-- IRForTarget.cpp -------------------------------------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "lldb/Expression/IRForTarget.h"
|
|
|
|
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
#include "llvm/InstrTypes.h"
|
2010-07-13 21:41:46 +00:00
|
|
|
#include "llvm/Instructions.h"
|
2010-07-03 01:35:46 +00:00
|
|
|
#include "llvm/Module.h"
|
2010-07-13 21:41:46 +00:00
|
|
|
#include "llvm/Target/TargetData.h"
|
|
|
|
|
|
|
|
#include "clang/AST/ASTContext.h"
|
2010-07-03 01:35:46 +00:00
|
|
|
|
|
|
|
#include "lldb/Core/dwarf.h"
|
|
|
|
#include "lldb/Core/Log.h"
|
|
|
|
#include "lldb/Core/Scalar.h"
|
|
|
|
#include "lldb/Core/StreamString.h"
|
|
|
|
#include "lldb/Expression/ClangExpressionDeclMap.h"
|
|
|
|
|
|
|
|
#include <map>
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
IRForTarget::IRForTarget(const void *pid,
|
2010-07-13 21:41:46 +00:00
|
|
|
lldb_private::ClangExpressionDeclMap *decl_map,
|
|
|
|
const llvm::TargetData *target_data) :
|
2010-07-03 01:35:46 +00:00
|
|
|
ModulePass(pid),
|
2010-07-13 21:41:46 +00:00
|
|
|
m_decl_map(decl_map),
|
|
|
|
m_target_data(target_data)
|
2010-07-03 01:35:46 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
IRForTarget::~IRForTarget()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2010-07-13 21:41:46 +00:00
|
|
|
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)
|
2010-07-03 01:35:46 +00:00
|
|
|
{
|
2010-07-13 21:41:46 +00:00
|
|
|
if (GlobalVariable *global_variable = dyn_cast<GlobalVariable>(V))
|
|
|
|
{
|
|
|
|
clang::NamedDecl *named_decl = DeclForGlobalValue(M, global_variable);
|
|
|
|
|
2010-07-16 00:09:46 +00:00
|
|
|
std::string name = named_decl->getName().str();
|
|
|
|
|
|
|
|
void *qual_type = NULL;
|
2010-07-20 23:31:16 +00:00
|
|
|
clang::ASTContext *ast_context = NULL;
|
2010-07-16 00:09:46 +00:00
|
|
|
|
|
|
|
if (clang::ValueDecl *value_decl = dyn_cast<clang::ValueDecl>(named_decl))
|
2010-07-20 23:31:16 +00:00
|
|
|
{
|
2010-07-16 00:09:46 +00:00
|
|
|
qual_type = value_decl->getType().getAsOpaquePtr();
|
2010-07-20 23:31:16 +00:00
|
|
|
ast_context = &value_decl->getASTContext();
|
|
|
|
}
|
2010-07-16 00:09:46 +00:00
|
|
|
else
|
2010-07-20 23:31:16 +00:00
|
|
|
{
|
2010-07-16 00:09:46 +00:00
|
|
|
return false;
|
2010-07-20 23:31:16 +00:00
|
|
|
}
|
|
|
|
|
2010-07-13 21:41:46 +00:00
|
|
|
const llvm::Type *value_type = global_variable->getType();
|
2010-07-03 01:35:46 +00:00
|
|
|
|
2010-07-13 21:41:46 +00:00
|
|
|
size_t value_size = m_target_data->getTypeStoreSize(value_type);
|
|
|
|
off_t value_alignment = m_target_data->getPrefTypeAlignment(value_type);
|
|
|
|
|
2010-07-16 00:09:46 +00:00
|
|
|
if (named_decl && !DM->AddValueToStruct(V,
|
|
|
|
named_decl,
|
|
|
|
name,
|
|
|
|
qual_type,
|
2010-07-20 23:31:16 +00:00
|
|
|
ast_context,
|
2010-07-16 00:09:46 +00:00
|
|
|
value_size,
|
|
|
|
value_alignment))
|
2010-07-13 21:41:46 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
IRForTarget::runOnBasicBlock(Module &M, BasicBlock &BB)
|
|
|
|
{
|
2010-07-03 01:35:46 +00:00
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
// Prepare the current basic block for execution in the remote process
|
|
|
|
//
|
|
|
|
|
2010-07-13 21:41:46 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2010-07-14 23:40:29 +00:00
|
|
|
static std::string
|
|
|
|
PrintValue(llvm::Value *V, bool truncate = false)
|
2010-07-13 21:41:46 +00:00
|
|
|
{
|
|
|
|
std::string s;
|
|
|
|
raw_string_ostream rso(s);
|
|
|
|
V->print(rso);
|
|
|
|
rso.flush();
|
|
|
|
if (truncate)
|
|
|
|
s.resize(s.length() - 1);
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2010-07-14 23:40:29 +00:00
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
2010-07-13 21:41:46 +00:00
|
|
|
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;
|
|
|
|
|
2010-07-03 01:35:46 +00:00
|
|
|
if (log)
|
2010-07-13 21:41:46 +00:00
|
|
|
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)
|
2010-07-03 01:35:46 +00:00
|
|
|
{
|
2010-07-13 21:41:46 +00:00
|
|
|
const clang::NamedDecl *decl;
|
|
|
|
llvm::Value *value;
|
|
|
|
off_t offset;
|
2010-07-03 01:35:46 +00:00
|
|
|
|
2010-07-13 21:41:46 +00:00
|
|
|
if (!m_decl_map->GetStructElement (decl, value, offset, element_index))
|
|
|
|
return false;
|
2010-07-03 01:35:46 +00:00
|
|
|
|
2010-07-13 21:41:46 +00:00
|
|
|
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);
|
|
|
|
|
2010-07-14 23:40:29 +00:00
|
|
|
if (Constant *constant = dyn_cast<Constant>(value))
|
|
|
|
UnfoldConstant(constant, bit_cast, first_entry_instruction);
|
|
|
|
else
|
|
|
|
value->replaceAllUsesWith(bit_cast);
|
2010-07-03 01:35:46 +00:00
|
|
|
}
|
|
|
|
|
2010-07-13 21:41:46 +00:00
|
|
|
if (log)
|
|
|
|
log->Printf("Total structure [align %d, size %d]", alignment, size);
|
|
|
|
|
2010-07-03 01:35:46 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
IRForTarget::runOnModule(Module &M)
|
|
|
|
{
|
|
|
|
lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
|
|
|
|
|
|
|
|
llvm::Function* function = M.getFunction(StringRef("___clang_expr"));
|
|
|
|
|
|
|
|
if (!function)
|
|
|
|
{
|
|
|
|
if (log)
|
|
|
|
log->Printf("Couldn't find ___clang_expr() in the module");
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::Function::iterator bbi;
|
|
|
|
|
|
|
|
for (bbi = function->begin();
|
|
|
|
bbi != function->end();
|
|
|
|
++bbi)
|
|
|
|
{
|
2010-07-13 21:41:46 +00:00
|
|
|
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());
|
|
|
|
}
|
|
|
|
|
2010-07-03 01:35:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
IRForTarget::assignPassManager(PMStack &PMS,
|
2010-07-13 21:41:46 +00:00
|
|
|
PassManagerType T)
|
2010-07-03 01:35:46 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
PassManagerType
|
|
|
|
IRForTarget::getPotentialPassManagerType() const
|
|
|
|
{
|
|
|
|
return PMT_ModulePassManager;
|
|
|
|
}
|