]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/llvm/tools/lli/RemoteMemoryManager.cpp
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / llvm / 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 #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
22 using namespace llvm;
23
24 RemoteMemoryManager::~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
31 uint8_t *RemoteMemoryManager::
32 allocateCodeSection(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 will own this memory.
40   AllocatedSections.push_back( Allocation(Block, Alignment, true) );
41   // UnmappedSections has the same information but does not own the memory.
42   UnmappedSections.push_back( Allocation(Block, Alignment, true) );
43   return (uint8_t*)Block.base();
44 }
45
46 uint8_t *RemoteMemoryManager::
47 allocateDataSection(uintptr_t Size, unsigned Alignment,
48                     unsigned SectionID, StringRef SectionName,
49                     bool IsReadOnly) {
50   // The recording memory manager is just a local copy of the remote target.
51   // The alignment requirement is just stored here for later use. Regular
52   // heap storage is sufficient here, but we're using mapped memory to work
53   // around a bug in MCJIT.
54   sys::MemoryBlock Block = allocateSection(Size);
55   // AllocatedSections will own this memory.
56   AllocatedSections.push_back( Allocation(Block, Alignment, false) );
57   // UnmappedSections has the same information but does not own the memory.
58   UnmappedSections.push_back( Allocation(Block, Alignment, false) );
59   return (uint8_t*)Block.base();
60 }
61
62 sys::MemoryBlock RemoteMemoryManager::allocateSection(uintptr_t Size) {
63   error_code ec;
64   sys::MemoryBlock MB = sys::Memory::allocateMappedMemory(Size,
65                                                           &Near,
66                                                           sys::Memory::MF_READ |
67                                                           sys::Memory::MF_WRITE,
68                                                           ec);
69   assert(!ec && MB.base());
70
71   // FIXME: This is part of a work around to keep sections near one another
72   // when MCJIT performs relocations after code emission but before
73   // the generated code is moved to the remote target.
74   // Save this address as the basis for our next request
75   Near = MB;
76   return MB;
77 }
78
79 void RemoteMemoryManager::notifyObjectLoaded(ExecutionEngine *EE,
80                                                 const ObjectImage *Obj) {
81   // The client should have called setRemoteTarget() before triggering any
82   // code generation.
83   assert(Target);
84   if (!Target)
85     return;
86
87   // FIXME: Make this function thread safe.
88
89   // Lay out our sections in order, with all the code sections first, then
90   // all the data sections.
91   uint64_t CurOffset = 0;
92   unsigned MaxAlign = Target->getPageAlignment();
93   SmallVector<std::pair<Allocation, uint64_t>, 16> Offsets;
94   unsigned NumSections = UnmappedSections.size();
95   // We're going to go through the list twice to separate code and data, but
96   // it's a very small list, so that's OK.
97   for (size_t i = 0, e = NumSections; i != e; ++i) {
98     Allocation &Section = UnmappedSections[i];
99     if (Section.IsCode) {
100       unsigned Size = Section.MB.size();
101       unsigned Align = Section.Alignment;
102       DEBUG(dbgs() << "code region: size " << Size
103                   << ", alignment " << Align << "\n");
104       // Align the current offset up to whatever is needed for the next
105       // section.
106       CurOffset = (CurOffset + Align - 1) / Align * Align;
107       // Save off the address of the new section and allocate its space.
108       Offsets.push_back(std::pair<Allocation,uint64_t>(Section, CurOffset));
109       CurOffset += Size;
110     }
111   }
112   // Adjust to keep code and data aligned on seperate pages.
113   CurOffset = (CurOffset + MaxAlign - 1) / MaxAlign * MaxAlign;
114   for (size_t i = 0, e = NumSections; i != e; ++i) {
115     Allocation &Section = UnmappedSections[i];
116     if (!Section.IsCode) {
117       unsigned Size = Section.MB.size();
118       unsigned Align = Section.Alignment;
119       DEBUG(dbgs() << "data region: size " << Size
120                   << ", alignment " << Align << "\n");
121       // Align the current offset up to whatever is needed for the next
122       // section.
123       CurOffset = (CurOffset + Align - 1) / Align * Align;
124       // Save off the address of the new section and allocate its space.
125       Offsets.push_back(std::pair<Allocation,uint64_t>(Section, 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
150 bool RemoteMemoryManager::finalizeMemory(std::string *ErrMsg) {
151   // FIXME: Make this function thread safe.
152   for (DenseMap<uint64_t, 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
175 void RemoteMemoryManager::setMemoryWritable() { llvm_unreachable("Unexpected!"); }
176 void RemoteMemoryManager::setMemoryExecutable() { llvm_unreachable("Unexpected!"); }
177 void RemoteMemoryManager::setPoisonMemory(bool poison) { llvm_unreachable("Unexpected!"); }
178 void RemoteMemoryManager::AllocateGOT() { llvm_unreachable("Unexpected!"); }
179 uint8_t *RemoteMemoryManager::getGOTBase() const {
180   llvm_unreachable("Unexpected!");
181   return 0;
182 }
183 uint8_t *RemoteMemoryManager::startFunctionBody(const Function *F, uintptr_t &ActualSize){
184   llvm_unreachable("Unexpected!");
185   return 0;
186 }
187 uint8_t *RemoteMemoryManager::allocateStub(const GlobalValue* F, unsigned StubSize,
188                                               unsigned Alignment) {
189   llvm_unreachable("Unexpected!");
190   return 0;
191 }
192 void RemoteMemoryManager::endFunctionBody(const Function *F, uint8_t *FunctionStart,
193                                              uint8_t *FunctionEnd) {
194   llvm_unreachable("Unexpected!");
195 }
196 uint8_t *RemoteMemoryManager::allocateSpace(intptr_t Size, unsigned Alignment) {
197   llvm_unreachable("Unexpected!");
198   return 0;
199 }
200 uint8_t *RemoteMemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignment) {
201   llvm_unreachable("Unexpected!");
202   return 0;
203 }
204 void RemoteMemoryManager::deallocateFunctionBody(void *Body) {
205   llvm_unreachable("Unexpected!");
206 }