blob: db38e8e53d2a2fd42918e87c13ec9d14ba8c0091 [file] [log] [blame]
Sean Callanan051052f2010-07-02 22:22:28 +00001//===-- IRToDWARF.cpp -------------------------------------------*- C++ -*-===//
Sean Callanandcb658b2010-07-02 21:09:36 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/Expression/IRToDWARF.h"
11
12#include "llvm/Support/raw_ostream.h"
13#include "llvm/InstrTypes.h"
14#include "llvm/Module.h"
15
16#include "lldb/Core/dwarf.h"
17#include "lldb/Core/Log.h"
18#include "lldb/Core/Scalar.h"
19#include "lldb/Core/StreamString.h"
20#include "lldb/Expression/ClangExpressionDeclMap.h"
21#include "lldb/Expression/ClangExpressionVariable.h"
22
23#include <map>
24
25using namespace llvm;
26
Sean Callanan3351dac2010-08-18 18:50:51 +000027static char ID;
28
29IRToDWARF::IRToDWARF(lldb_private::ClangExpressionVariableList &variable_list,
Sean Callanandcb658b2010-07-02 21:09:36 +000030 lldb_private::ClangExpressionDeclMap *decl_map,
31 lldb_private::StreamString &strm) :
Sean Callanan3351dac2010-08-18 18:50:51 +000032 ModulePass(ID),
Sean Callanandcb658b2010-07-02 21:09:36 +000033 m_variable_list(variable_list),
34 m_decl_map(decl_map),
35 m_strm(strm)
36{
37}
38
39IRToDWARF::~IRToDWARF()
40{
41}
42
43class Relocator
44{
45public:
46 Relocator()
47 {
48 }
49
50 ~Relocator()
51 {
52 }
53
54 void MarkBasicBlock(BasicBlock *bb, uint16_t offset)
55 {
56 m_basic_blocks[bb] = offset;
57 }
58
59 bool BasicBlockIsMarked(BasicBlock *bb)
60 {
61 return m_basic_blocks.find(bb) != m_basic_blocks.end();
62 }
63
64 void MarkRelocation(BasicBlock *bb, uint16_t offset)
65 {
66 m_relocations[offset] = bb;
67 }
68
69 bool ResolveRelocations(lldb_private::StreamString &strm)
70 {
71 std::map<uint16_t, BasicBlock*>::const_iterator iter;
72
73 lldb_private::StreamString swapper(0, 32, strm.GetByteOrder());
74
75 // This array must be delete [] d at every exit
76 size_t temporary_bufsize = strm.GetSize();
77 uint8_t *temporary_buffer(new uint8_t[temporary_bufsize]);
78
79 memcpy(temporary_buffer, strm.GetData(), temporary_bufsize);
80
81 for (iter = m_relocations.begin();
82 iter != m_relocations.end();
83 ++iter)
84 {
85 const std::pair<uint16_t, BasicBlock*> &pair = *iter;
86
87 uint16_t off = pair.first;
88 BasicBlock *bb = pair.second;
89
90 if (m_basic_blocks.find(bb) == m_basic_blocks.end())
91 {
92 delete [] temporary_buffer;
93 return false;
94 }
95
96 uint16_t target_off = m_basic_blocks[bb];
97
98 int16_t relative = (int16_t)target_off - (int16_t)off;
99
100 swapper.Clear();
Sean Callanan702abd62010-07-02 21:28:35 +0000101 swapper << relative;
Sean Callanandcb658b2010-07-02 21:09:36 +0000102
Sean Callanan702abd62010-07-02 21:28:35 +0000103 // off is intended to be the offset of the branch opcode (which is
104 // what the relative location is added to) so
105 // (temporary_buffer + off + 1) skips the opcode and writes to the
106 // relative location
107 memcpy(temporary_buffer + off + 1, swapper.GetData(), sizeof(uint16_t));
Sean Callanandcb658b2010-07-02 21:09:36 +0000108 }
109
110 strm.Clear();
111 strm.Write(temporary_buffer, temporary_bufsize);
112
113 delete [] temporary_buffer;
114 return true;
115 }
116private:
117 std::map<BasicBlock*, uint16_t> m_basic_blocks;
118 std::map<uint16_t, BasicBlock*> m_relocations;
119};
120
121bool
122IRToDWARF::runOnBasicBlock(BasicBlock &BB, Relocator &R)
Sean Callanan321fe9e2010-07-28 01:00:59 +0000123{
Sean Callanandcb658b2010-07-02 21:09:36 +0000124 ///////////////////////////////////////
125 // Mark the current block as visited
126 //
127
128 size_t stream_size = m_strm.GetSize();
129
130 if (stream_size > 0xffff)
131 return false;
132
133 uint16_t offset = stream_size & 0xffff;
134
135 R.MarkBasicBlock(&BB, offset);
136
137 ////////////////////////////////////////////////
138 // Translate the current basic block to DWARF
139 //
140
Sean Callanandcb658b2010-07-02 21:09:36 +0000141 /////////////////////////////////////////////////
142 // Visit all successors we haven't visited yet
143 //
144
145 TerminatorInst *arnold = BB.getTerminator();
146
147 if (!arnold)
148 return false;
149
150 unsigned successor_index;
151 unsigned num_successors = arnold->getNumSuccessors();
152
153 for (successor_index = 0;
154 successor_index < num_successors;
155 ++successor_index)
156 {
157 BasicBlock *successor = arnold->getSuccessor(successor_index);
158
159 if (!R.BasicBlockIsMarked(successor))
160 {
161 if (!runOnBasicBlock(*successor, R))
162 return false;
163 }
164 }
165
166 return true;
167}
168
169bool
170IRToDWARF::runOnModule(Module &M)
171{
172 lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
173
174 llvm::Function* function = M.getFunction(StringRef("___clang_expr"));
175
176 if (!function)
177 {
178 if (log)
179 log->Printf("Couldn't find ___clang_expr() in the module");
180
181 return 1;
182 }
183
184 Relocator relocator;
185
Sean Callanan5cf4a1c2010-07-03 01:35:46 +0000186 if (!runOnBasicBlock(function->getEntryBlock(), relocator))
187 return false;
Sean Callanandcb658b2010-07-02 21:09:36 +0000188
Sean Callanan321fe9e2010-07-28 01:00:59 +0000189 if (log)
190 {
191 std::string s;
192 raw_string_ostream oss(s);
193
194 M.print(oss, NULL);
195
196 oss.flush();
197
198 log->Printf("Module being translated to DWARF: \n%s", s.c_str());
199 }
200
Sean Callanan5cf4a1c2010-07-03 01:35:46 +0000201 // TEMPORARY: Fail in order to force execution in the target.
202 return false;
Sean Callanandcb658b2010-07-02 21:09:36 +0000203
204 return relocator.ResolveRelocations(m_strm);
205}
206
207void
208IRToDWARF::assignPassManager(PMStack &PMS,
209 PassManagerType T)
210{
211}
212
213PassManagerType
214IRToDWARF::getPotentialPassManagerType() const
215{
216 return PMT_ModulePassManager;
217}