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