blob: b6e0b4310fa52ca81d7ffae25d5d625dfeab9172 [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
27IRToDWARF::IRToDWARF(const void *pid,
28 lldb_private::ClangExpressionVariableList &variable_list,
29 lldb_private::ClangExpressionDeclMap *decl_map,
30 lldb_private::StreamString &strm) :
31 ModulePass(pid),
32 m_variable_list(variable_list),
33 m_decl_map(decl_map),
34 m_strm(strm)
35{
36}
37
38IRToDWARF::~IRToDWARF()
39{
40}
41
42class Relocator
43{
44public:
45 Relocator()
46 {
47 }
48
49 ~Relocator()
50 {
51 }
52
53 void MarkBasicBlock(BasicBlock *bb, uint16_t offset)
54 {
55 m_basic_blocks[bb] = offset;
56 }
57
58 bool BasicBlockIsMarked(BasicBlock *bb)
59 {
60 return m_basic_blocks.find(bb) != m_basic_blocks.end();
61 }
62
63 void MarkRelocation(BasicBlock *bb, uint16_t offset)
64 {
65 m_relocations[offset] = bb;
66 }
67
68 bool ResolveRelocations(lldb_private::StreamString &strm)
69 {
70 std::map<uint16_t, BasicBlock*>::const_iterator iter;
71
72 lldb_private::StreamString swapper(0, 32, strm.GetByteOrder());
73
74 // This array must be delete [] d at every exit
75 size_t temporary_bufsize = strm.GetSize();
76 uint8_t *temporary_buffer(new uint8_t[temporary_bufsize]);
77
78 memcpy(temporary_buffer, strm.GetData(), temporary_bufsize);
79
80 for (iter = m_relocations.begin();
81 iter != m_relocations.end();
82 ++iter)
83 {
84 const std::pair<uint16_t, BasicBlock*> &pair = *iter;
85
86 uint16_t off = pair.first;
87 BasicBlock *bb = pair.second;
88
89 if (m_basic_blocks.find(bb) == m_basic_blocks.end())
90 {
91 delete [] temporary_buffer;
92 return false;
93 }
94
95 uint16_t target_off = m_basic_blocks[bb];
96
97 int16_t relative = (int16_t)target_off - (int16_t)off;
98
99 swapper.Clear();
Sean Callanan702abd62010-07-02 21:28:35 +0000100 swapper << relative;
Sean Callanandcb658b2010-07-02 21:09:36 +0000101
Sean Callanan702abd62010-07-02 21:28:35 +0000102 // off is intended to be the offset of the branch opcode (which is
103 // what the relative location is added to) so
104 // (temporary_buffer + off + 1) skips the opcode and writes to the
105 // relative location
106 memcpy(temporary_buffer + off + 1, swapper.GetData(), sizeof(uint16_t));
Sean Callanandcb658b2010-07-02 21:09:36 +0000107 }
108
109 strm.Clear();
110 strm.Write(temporary_buffer, temporary_bufsize);
111
112 delete [] temporary_buffer;
113 return true;
114 }
115private:
116 std::map<BasicBlock*, uint16_t> m_basic_blocks;
117 std::map<uint16_t, BasicBlock*> m_relocations;
118};
119
120bool
121IRToDWARF::runOnBasicBlock(BasicBlock &BB, Relocator &R)
Sean Callanan321fe9e2010-07-28 01:00:59 +0000122{
Sean Callanandcb658b2010-07-02 21:09:36 +0000123 ///////////////////////////////////////
124 // Mark the current block as visited
125 //
126
127 size_t stream_size = m_strm.GetSize();
128
129 if (stream_size > 0xffff)
130 return false;
131
132 uint16_t offset = stream_size & 0xffff;
133
134 R.MarkBasicBlock(&BB, offset);
135
136 ////////////////////////////////////////////////
137 // Translate the current basic block to DWARF
138 //
139
Sean Callanandcb658b2010-07-02 21:09:36 +0000140 /////////////////////////////////////////////////
141 // Visit all successors we haven't visited yet
142 //
143
144 TerminatorInst *arnold = BB.getTerminator();
145
146 if (!arnold)
147 return false;
148
149 unsigned successor_index;
150 unsigned num_successors = arnold->getNumSuccessors();
151
152 for (successor_index = 0;
153 successor_index < num_successors;
154 ++successor_index)
155 {
156 BasicBlock *successor = arnold->getSuccessor(successor_index);
157
158 if (!R.BasicBlockIsMarked(successor))
159 {
160 if (!runOnBasicBlock(*successor, R))
161 return false;
162 }
163 }
164
165 return true;
166}
167
168bool
169IRToDWARF::runOnModule(Module &M)
170{
171 lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
172
173 llvm::Function* function = M.getFunction(StringRef("___clang_expr"));
174
175 if (!function)
176 {
177 if (log)
178 log->Printf("Couldn't find ___clang_expr() in the module");
179
180 return 1;
181 }
182
183 Relocator relocator;
184
Sean Callanan5cf4a1c2010-07-03 01:35:46 +0000185 if (!runOnBasicBlock(function->getEntryBlock(), relocator))
186 return false;
Sean Callanandcb658b2010-07-02 21:09:36 +0000187
Sean Callanan321fe9e2010-07-28 01:00:59 +0000188 if (log)
189 {
190 std::string s;
191 raw_string_ostream oss(s);
192
193 M.print(oss, NULL);
194
195 oss.flush();
196
197 log->Printf("Module being translated to DWARF: \n%s", s.c_str());
198 }
199
Sean Callanan5cf4a1c2010-07-03 01:35:46 +0000200 // TEMPORARY: Fail in order to force execution in the target.
201 return false;
Sean Callanandcb658b2010-07-02 21:09:36 +0000202
203 return relocator.ResolveRelocations(m_strm);
204}
205
206void
207IRToDWARF::assignPassManager(PMStack &PMS,
208 PassManagerType T)
209{
210}
211
212PassManagerType
213IRToDWARF::getPotentialPassManagerType() const
214{
215 return PMT_ModulePassManager;
216}