blob: 88d880be21958990092027e627429c0e7cb374b2 [file] [log] [blame]
//===-- IRToDWARF.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/IRToDWARF.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/InstrTypes.h"
#include "llvm/Module.h"
#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 "lldb/Expression/ClangExpressionVariable.h"
#include <map>
using namespace llvm;
static char ID;
IRToDWARF::IRToDWARF(lldb_private::ClangExpressionVariableList &local_vars,
lldb_private::ClangExpressionDeclMap *decl_map,
lldb_private::StreamString &strm,
const char *func_name) :
ModulePass(ID),
m_local_vars(local_vars),
m_decl_map(decl_map),
m_strm(strm),
m_func_name(func_name)
{
}
IRToDWARF::~IRToDWARF()
{
}
class Relocator
{
public:
Relocator()
{
}
~Relocator()
{
}
void MarkBasicBlock(BasicBlock *bb, uint16_t offset)
{
m_basic_blocks[bb] = offset;
}
bool BasicBlockIsMarked(BasicBlock *bb)
{
return m_basic_blocks.find(bb) != m_basic_blocks.end();
}
void MarkRelocation(BasicBlock *bb, uint16_t offset)
{
m_relocations[offset] = bb;
}
bool ResolveRelocations(lldb_private::StreamString &strm)
{
std::map<uint16_t, BasicBlock*>::const_iterator iter;
lldb_private::StreamString swapper(0, 32, strm.GetByteOrder());
// This array must be delete [] d at every exit
size_t temporary_bufsize = strm.GetSize();
uint8_t *temporary_buffer(new uint8_t[temporary_bufsize]);
memcpy(temporary_buffer, strm.GetData(), temporary_bufsize);
for (iter = m_relocations.begin();
iter != m_relocations.end();
++iter)
{
const std::pair<uint16_t, BasicBlock*> &pair = *iter;
uint16_t off = pair.first;
BasicBlock *bb = pair.second;
if (m_basic_blocks.find(bb) == m_basic_blocks.end())
{
delete [] temporary_buffer;
return false;
}
uint16_t target_off = m_basic_blocks[bb];
int16_t relative = (int16_t)target_off - (int16_t)off;
swapper.Clear();
swapper << relative;
// off is intended to be the offset of the branch opcode (which is
// what the relative location is added to) so
// (temporary_buffer + off + 1) skips the opcode and writes to the
// relative location
memcpy(temporary_buffer + off + 1, swapper.GetData(), sizeof(uint16_t));
}
strm.Clear();
strm.Write(temporary_buffer, temporary_bufsize);
delete [] temporary_buffer;
return true;
}
private:
std::map<BasicBlock*, uint16_t> m_basic_blocks;
std::map<uint16_t, BasicBlock*> m_relocations;
};
bool
IRToDWARF::runOnBasicBlock(BasicBlock &BB, Relocator &R)
{
///////////////////////////////////////
// Mark the current block as visited
//
size_t stream_size = m_strm.GetSize();
if (stream_size > 0xffff)
return false;
uint16_t offset = stream_size & 0xffff;
R.MarkBasicBlock(&BB, offset);
////////////////////////////////////////////////
// Translate the current basic block to DWARF
//
/////////////////////////////////////////////////
// Visit all successors we haven't visited yet
//
TerminatorInst *arnold = BB.getTerminator();
if (!arnold)
return false;
unsigned successor_index;
unsigned num_successors = arnold->getNumSuccessors();
for (successor_index = 0;
successor_index < num_successors;
++successor_index)
{
BasicBlock *successor = arnold->getSuccessor(successor_index);
if (!R.BasicBlockIsMarked(successor))
{
if (!runOnBasicBlock(*successor, R))
return false;
}
}
return true;
}
bool
IRToDWARF::runOnModule(Module &M)
{
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
llvm::Function* function = M.getFunction(StringRef(m_func_name.c_str()));
if (!function)
{
if (log)
log->Printf("Couldn't find %s() in the module", m_func_name.c_str());
return false;
}
Relocator relocator;
if (!runOnBasicBlock(function->getEntryBlock(), relocator))
return false;
if (log && log->GetVerbose())
{
std::string s;
raw_string_ostream oss(s);
M.print(oss, NULL);
oss.flush();
log->Printf ("Module being translated to DWARF: \n%s", s.c_str());
}
// TEMPORARY: Fail in order to force execution in the target.
return false;
return relocator.ResolveRelocations(m_strm);
}
void
IRToDWARF::assignPassManager(PMStack &PMS,
PassManagerType T)
{
}
PassManagerType
IRToDWARF::getPotentialPassManagerType() const
{
return PMT_ModulePassManager;
}