blob: d4a4a3fbc244ff58437f87a4ba2fa3e344f60c8a [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
Sean Callanan65dafa82010-08-27 01:01:44 +000029IRToDWARF::IRToDWARF(lldb_private::ClangExpressionVariableStore &local_vars,
Sean Callanandcb658b2010-07-02 21:09:36 +000030 lldb_private::ClangExpressionDeclMap *decl_map,
Sean Callanan65dafa82010-08-27 01:01:44 +000031 lldb_private::StreamString &strm,
32 const char *func_name) :
Sean Callanan47a5c4c2010-09-23 03:01:22 +000033 ModulePass(ID),
Sean Callanan65dafa82010-08-27 01:01:44 +000034 m_local_vars(local_vars),
Sean Callanandcb658b2010-07-02 21:09:36 +000035 m_decl_map(decl_map),
Sean Callanan65dafa82010-08-27 01:01:44 +000036 m_strm(strm),
37 m_func_name(func_name)
Sean Callanandcb658b2010-07-02 21:09:36 +000038{
39}
40
41IRToDWARF::~IRToDWARF()
42{
43}
44
45class Relocator
46{
47public:
48 Relocator()
49 {
50 }
51
52 ~Relocator()
53 {
54 }
55
56 void MarkBasicBlock(BasicBlock *bb, uint16_t offset)
57 {
58 m_basic_blocks[bb] = offset;
59 }
60
61 bool BasicBlockIsMarked(BasicBlock *bb)
62 {
63 return m_basic_blocks.find(bb) != m_basic_blocks.end();
64 }
65
66 void MarkRelocation(BasicBlock *bb, uint16_t offset)
67 {
68 m_relocations[offset] = bb;
69 }
70
71 bool ResolveRelocations(lldb_private::StreamString &strm)
72 {
73 std::map<uint16_t, BasicBlock*>::const_iterator iter;
74
75 lldb_private::StreamString swapper(0, 32, strm.GetByteOrder());
76
77 // This array must be delete [] d at every exit
78 size_t temporary_bufsize = strm.GetSize();
79 uint8_t *temporary_buffer(new uint8_t[temporary_bufsize]);
80
81 memcpy(temporary_buffer, strm.GetData(), temporary_bufsize);
82
83 for (iter = m_relocations.begin();
84 iter != m_relocations.end();
85 ++iter)
86 {
87 const std::pair<uint16_t, BasicBlock*> &pair = *iter;
88
89 uint16_t off = pair.first;
90 BasicBlock *bb = pair.second;
91
92 if (m_basic_blocks.find(bb) == m_basic_blocks.end())
93 {
94 delete [] temporary_buffer;
95 return false;
96 }
97
98 uint16_t target_off = m_basic_blocks[bb];
99
100 int16_t relative = (int16_t)target_off - (int16_t)off;
101
102 swapper.Clear();
Sean Callanan702abd62010-07-02 21:28:35 +0000103 swapper << relative;
Sean Callanandcb658b2010-07-02 21:09:36 +0000104
Sean Callanan702abd62010-07-02 21:28:35 +0000105 // off is intended to be the offset of the branch opcode (which is
106 // what the relative location is added to) so
107 // (temporary_buffer + off + 1) skips the opcode and writes to the
108 // relative location
109 memcpy(temporary_buffer + off + 1, swapper.GetData(), sizeof(uint16_t));
Sean Callanandcb658b2010-07-02 21:09:36 +0000110 }
111
112 strm.Clear();
113 strm.Write(temporary_buffer, temporary_bufsize);
114
115 delete [] temporary_buffer;
116 return true;
117 }
118private:
119 std::map<BasicBlock*, uint16_t> m_basic_blocks;
120 std::map<uint16_t, BasicBlock*> m_relocations;
121};
122
123bool
124IRToDWARF::runOnBasicBlock(BasicBlock &BB, Relocator &R)
Sean Callanan321fe9e2010-07-28 01:00:59 +0000125{
Sean Callanandcb658b2010-07-02 21:09:36 +0000126 ///////////////////////////////////////
127 // Mark the current block as visited
128 //
129
130 size_t stream_size = m_strm.GetSize();
131
132 if (stream_size > 0xffff)
133 return false;
134
135 uint16_t offset = stream_size & 0xffff;
136
137 R.MarkBasicBlock(&BB, offset);
138
139 ////////////////////////////////////////////////
140 // Translate the current basic block to DWARF
141 //
142
Sean Callanandcb658b2010-07-02 21:09:36 +0000143 /////////////////////////////////////////////////
144 // Visit all successors we haven't visited yet
145 //
146
147 TerminatorInst *arnold = BB.getTerminator();
148
149 if (!arnold)
150 return false;
151
152 unsigned successor_index;
153 unsigned num_successors = arnold->getNumSuccessors();
154
155 for (successor_index = 0;
156 successor_index < num_successors;
157 ++successor_index)
158 {
159 BasicBlock *successor = arnold->getSuccessor(successor_index);
160
161 if (!R.BasicBlockIsMarked(successor))
162 {
163 if (!runOnBasicBlock(*successor, R))
164 return false;
165 }
166 }
167
168 return true;
169}
170
171bool
172IRToDWARF::runOnModule(Module &M)
173{
174 lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
175
Sean Callanan65dafa82010-08-27 01:01:44 +0000176 llvm::Function* function = M.getFunction(StringRef(m_func_name.c_str()));
Sean Callanandcb658b2010-07-02 21:09:36 +0000177
178 if (!function)
179 {
180 if (log)
Sean Callanan65dafa82010-08-27 01:01:44 +0000181 log->Printf("Couldn't find %s() in the module", m_func_name.c_str());
Sean Callanandcb658b2010-07-02 21:09:36 +0000182
Sean Callanan65dafa82010-08-27 01:01:44 +0000183 return false;
Sean Callanandcb658b2010-07-02 21:09:36 +0000184 }
185
186 Relocator relocator;
187
Sean Callanan5cf4a1c2010-07-03 01:35:46 +0000188 if (!runOnBasicBlock(function->getEntryBlock(), relocator))
189 return false;
Sean Callanandcb658b2010-07-02 21:09:36 +0000190
Sean Callanan321fe9e2010-07-28 01:00:59 +0000191 if (log)
192 {
193 std::string s;
194 raw_string_ostream oss(s);
195
196 M.print(oss, NULL);
197
198 oss.flush();
199
200 log->Printf("Module being translated to DWARF: \n%s", s.c_str());
201 }
202
Sean Callanan5cf4a1c2010-07-03 01:35:46 +0000203 // TEMPORARY: Fail in order to force execution in the target.
204 return false;
Sean Callanandcb658b2010-07-02 21:09:36 +0000205
206 return relocator.ResolveRelocations(m_strm);
207}
208
209void
210IRToDWARF::assignPassManager(PMStack &PMS,
211 PassManagerType T)
212{
213}
214
215PassManagerType
216IRToDWARF::getPotentialPassManagerType() const
217{
218 return PMT_ModulePassManager;
219}