Added the skeleton of a transformation pass to
convert IR to DWARF. So far, this pass only
performs a depth-first traversal of the IR,
logging each basic block as it finds it.
git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@107515 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Expression/ClangExpression.cpp b/source/Expression/ClangExpression.cpp
index cadb5eb..d01d062 100644
--- a/source/Expression/ClangExpression.cpp
+++ b/source/Expression/ClangExpression.cpp
@@ -58,6 +58,7 @@
#include "lldb/Expression/ClangASTSource.h"
#include "lldb/Expression/ClangResultSynthesizer.h"
#include "lldb/Expression/ClangStmtVisitor.h"
+#include "lldb/Expression/IRToDWARF.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Expression/RecordingMemoryManager.h"
#include "lldb/Target/ExecutionContext.h"
@@ -473,7 +474,7 @@
}
unsigned
-ClangExpression::ConvertIRToDWARF (ClangExpressionVariableList &excpr_local_variable_list,
+ClangExpression::ConvertIRToDWARF (ClangExpressionVariableList &expr_local_variable_list,
StreamString &dwarf_opcode_strm)
{
Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
@@ -488,46 +489,9 @@
return 1;
}
- llvm::Function* function = module->getFunction(StringRef("___clang_expr"));
+ IRToDWARF ir_to_dwarf("IR to DWARF", expr_local_variable_list, m_decl_map, dwarf_opcode_strm);
- if (!function)
- {
- if (log)
- log->Printf("Couldn't find ___clang_expr() in the module");
-
- return 1;
- }
-
- if (log)
- log->Printf("IR for %s:", function->getName().str().c_str());
-
- llvm::Function::iterator bbi;
-
- for (bbi = function->begin();
- bbi != function->end();
- ++bbi)
- {
- llvm::BasicBlock &bb = *bbi;
-
- llvm::BasicBlock::iterator ii;
-
- for (ii = bb.begin();
- ii != bb.end();
- ++ii)
- {
- llvm::Instruction &inst = *ii;
-
- std::string s;
- llvm::raw_string_ostream os(s);
-
- inst.print(os);
-
- if (log)
- log->Printf(" %s", s.c_str());
- }
- }
-
- return 0;
+ return ir_to_dwarf.runOnModule(*module);
}
bool
diff --git a/source/Expression/IRToDWARF.cpp b/source/Expression/IRToDWARF.cpp
new file mode 100644
index 0000000..055d66d
--- /dev/null
+++ b/source/Expression/IRToDWARF.cpp
@@ -0,0 +1,222 @@
+//===-- 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;
+
+IRToDWARF::IRToDWARF(const void *pid,
+ lldb_private::ClangExpressionVariableList &variable_list,
+ lldb_private::ClangExpressionDeclMap *decl_map,
+ lldb_private::StreamString &strm) :
+ ModulePass(pid),
+ m_variable_list(variable_list),
+ m_decl_map(decl_map),
+ m_strm(strm)
+{
+}
+
+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 << target_off;
+
+ memcpy(temporary_buffer + off, 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)
+{
+ lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
+
+ ///////////////////////////////////////
+ // 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
+ //
+
+ if (log)
+ {
+ log->Printf("Translating a basic block:");
+
+ llvm::BasicBlock::iterator ii;
+
+ 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());
+ }
+ }
+
+ /////////////////////////////////////////////////
+ // 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_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 1;
+ }
+
+ Relocator relocator;
+
+ llvm::BasicBlock ¤tBB = function->getEntryBlock();
+
+ runOnBasicBlock(currentBB, relocator);
+
+ return relocator.ResolveRelocations(m_strm);
+}
+
+void
+IRToDWARF::assignPassManager(PMStack &PMS,
+ PassManagerType T)
+{
+}
+
+PassManagerType
+IRToDWARF::getPotentialPassManagerType() const
+{
+ return PMT_ModulePassManager;
+}