481651772afc402d83d3efcf98ff2749b7c2db9e
[oota-llvm.git] / tools / lli / RemoteMemoryManager.cpp
1 //===---- RemoteMemoryManager.cpp - Recording memory manager --------------===//
2 //
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 // This memory manager allocates local storage and keeps a record of each
11 // allocation. Iterators are provided for all data and code allocations.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "RemoteMemoryManager.h"
16 #include "llvm/ExecutionEngine/ExecutionEngine.h"
17 #include "llvm/ExecutionEngine/ObjectImage.h"
18 #include "llvm/Support/Debug.h"
19 #include "llvm/Support/Format.h"
20
21 using namespace llvm;
22
23 #define DEBUG_TYPE "lli"
24
25 RemoteMemoryManager::~RemoteMemoryManager() {
26   for (SmallVector<Allocation, 2>::iterator
27          I = AllocatedSections.begin(), E = AllocatedSections.end();
28        I != E; ++I)
29     sys::Memory::releaseMappedMemory(I->MB);
30 }
31
32 uint8_t *RemoteMemoryManager::
33 allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID,
34                     StringRef SectionName) {
35   // The recording memory manager is just a local copy of the remote target.
36   // The alignment requirement is just stored here for later use. Regular
37   // heap storage is sufficient here, but we're using mapped memory to work
38   // around a bug in MCJIT.
39   sys::MemoryBlock Block = allocateSection(Size);
40   // AllocatedSections will own this memory.
41   AllocatedSections.push_back( Allocation(Block, Alignment, true) );
42   // UnmappedSections has the same information but does not own the memory.
43   UnmappedSections.push_back( Allocation(Block, Alignment, true) );
44   return (uint8_t*)Block.base();
45 }
46
47 uint8_t *RemoteMemoryManager::
48 allocateDataSection(uintptr_t Size, unsigned Alignment,
49                     unsigned SectionID, StringRef SectionName,
50                     bool IsReadOnly) {
51   // The recording memory manager is just a local copy of the remote target.
52   // The alignment requirement is just stored here for later use. Regular
53   // heap storage is sufficient here, but we're using mapped memory to work
54   // around a bug in MCJIT.
55   sys::MemoryBlock Block = allocateSection(Size);
56   // AllocatedSections will own this memory.
57   AllocatedSections.push_back( Allocation(Block, Alignment, false) );
58   // UnmappedSections has the same information but does not own the memory.
59   UnmappedSections.push_back( Allocation(Block, Alignment, false) );
60   return (uint8_t*)Block.base();
61 }
62
63 sys::MemoryBlock RemoteMemoryManager::allocateSection(uintptr_t Size) {
64   std::error_code ec;
65   sys::MemoryBlock MB = sys::Memory::allocateMappedMemory(Size,
66                                                           &Near,
67                                                           sys::Memory::MF_READ |
68                                                           sys::Memory::MF_WRITE,
69                                                           ec);
70   assert(!ec && MB.base());
71
72   // FIXME: This is part of a work around to keep sections near one another
73   // when MCJIT performs relocations after code emission but before
74   // the generated code is moved to the remote target.
75   // Save this address as the basis for our next request
76   Near = MB;
77   return MB;
78 }
79
80 void RemoteMemoryManager::notifyObjectLoaded(ExecutionEngine *EE,
81                                                 const ObjectImage *Obj) {
82   // The client should have called setRemoteTarget() before triggering any
83   // code generation.
84   assert(Target);
85   if (!Target)
86     return;
87
88   // FIXME: Make this function thread safe.
89
90   // Lay out our sections in order, with all the code sections first, then
91   // all the data sections.
92   uint64_t CurOffset = 0;
93   unsigned MaxAlign = Target->getPageAlignment();
94   SmallVector<std::pair<Allocation, uint64_t>, 16> Offsets;
95   unsigned NumSections = UnmappedSections.size();
96   // We're going to go through the list twice to separate code and data, but
97   // it's a very small list, so that's OK.
98   for (size_t i = 0, e = NumSections; i != e; ++i) {
99     Allocation &Section = UnmappedSections[i];
100     if (Section.IsCode) {
101       unsigned Size = Section.MB.size();
102       unsigned Align = Section.Alignment;
103       DEBUG(dbgs() << "code region: size " << Size
104                   << ", alignment " << Align << "\n");
105       // Align the current offset up to whatever is needed for the next
106       // section.
107       CurOffset = (CurOffset + Align - 1) / Align * Align;
108       // Save off the address of the new section and allocate its space.
109       Offsets.push_back(std::pair<Allocation,uint64_t>(Section, CurOffset));
110       CurOffset += Size;
111     }
112   }
113   // Adjust to keep code and data aligned on separate pages.
114   CurOffset = (CurOffset + MaxAlign - 1) / MaxAlign * MaxAlign;
115   for (size_t i = 0, e = NumSections; i != e; ++i) {
116     Allocation &Section = UnmappedSections[i];
117     if (!Section.IsCode) {
118       unsigned Size = Section.MB.size();
119       unsigned Align = Section.Alignment;
120       DEBUG(dbgs() << "data region: size " << Size
121                   << ", alignment " << Align << "\n");
122       // Align the current offset up to whatever is needed for the next
123       // section.
124       CurOffset = (CurOffset + Align - 1) / Align * Align;
125       // Save off the address of the new section and allocate its space.
126       Offsets.push_back(std::pair<Allocation,uint64_t>(Section, CurOffset));
127       CurOffset += Size;
128     }
129   }
130
131   // Allocate space in the remote target.
132   uint64_t RemoteAddr;
133   if (!Target->allocateSpace(CurOffset, MaxAlign, RemoteAddr))
134     report_fatal_error(Target->getErrorMsg());
135
136   // Map the section addresses so relocations will get updated in the local
137   // copies of the sections.
138   for (unsigned i = 0, e = Offsets.size(); i != e; ++i) {
139     uint64_t Addr = RemoteAddr + Offsets[i].second;
140     EE->mapSectionAddress(const_cast<void*>(Offsets[i].first.MB.base()), Addr);
141
142     DEBUG(dbgs() << "  Mapping local: " << Offsets[i].first.MB.base()
143                  << " to remote: 0x" << format("%llx", Addr) << "\n");
144
145     MappedSections[Addr] = Offsets[i].first;
146   }
147
148   UnmappedSections.clear();
149 }
150
151 bool RemoteMemoryManager::finalizeMemory(std::string *ErrMsg) {
152   // FIXME: Make this function thread safe.
153   for (DenseMap<uint64_t, Allocation>::iterator
154          I = MappedSections.begin(), E = MappedSections.end();
155        I != E; ++I) {
156     uint64_t RemoteAddr = I->first;
157     const Allocation &Section = I->second;
158     if (Section.IsCode) {
159       if (!Target->loadCode(RemoteAddr, Section.MB.base(), Section.MB.size()))
160         report_fatal_error(Target->getErrorMsg());
161       DEBUG(dbgs() << "  loading code: " << Section.MB.base()
162             << " to remote: 0x" << format("%llx", RemoteAddr) << "\n");
163     } else {
164       if (!Target->loadData(RemoteAddr, Section.MB.base(), Section.MB.size()))
165         report_fatal_error(Target->getErrorMsg());
166       DEBUG(dbgs() << "  loading data: " << Section.MB.base()
167             << " to remote: 0x" << format("%llx", RemoteAddr) << "\n");
168     }
169   }
170
171   MappedSections.clear();
172
173   return false;
174 }
175
176 void RemoteMemoryManager::setMemoryWritable() { llvm_unreachable("Unexpected!"); }
177 void RemoteMemoryManager::setMemoryExecutable() { llvm_unreachable("Unexpected!"); }
178 void RemoteMemoryManager::setPoisonMemory(bool poison) { llvm_unreachable("Unexpected!"); }
179 void RemoteMemoryManager::AllocateGOT() { llvm_unreachable("Unexpected!"); }
180 uint8_t *RemoteMemoryManager::getGOTBase() const {
181   llvm_unreachable("Unexpected!");
182   return nullptr;
183 }
184 uint8_t *RemoteMemoryManager::startFunctionBody(const Function *F, uintptr_t &ActualSize){
185   llvm_unreachable("Unexpected!");
186   return nullptr;
187 }
188 uint8_t *RemoteMemoryManager::allocateStub(const GlobalValue* F, unsigned StubSize,
189                                               unsigned Alignment) {
190   llvm_unreachable("Unexpected!");
191   return nullptr;
192 }
193 void RemoteMemoryManager::endFunctionBody(const Function *F, uint8_t *FunctionStart,
194                                              uint8_t *FunctionEnd) {
195   llvm_unreachable("Unexpected!");
196 }
197 uint8_t *RemoteMemoryManager::allocateSpace(intptr_t Size, unsigned Alignment) {
198   llvm_unreachable("Unexpected!");
199   return nullptr;
200 }
201 uint8_t *RemoteMemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignment) {
202   llvm_unreachable("Unexpected!");
203   return nullptr;
204 }
205 void RemoteMemoryManager::deallocateFunctionBody(void *Body) {
206   llvm_unreachable("Unexpected!");
207 }