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