blob: 47da8fb60c985b3c1ba8fbca73491a5f79c9838c [file] [log] [blame]
Andrew Kaylor1b2cfb62013-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
Andrew Kaylor1b2cfb62013-10-04 00:49:38 +000015#include "RemoteMemoryManager.h"
16#include "llvm/ExecutionEngine/ExecutionEngine.h"
Andrew Kaylor1b2cfb62013-10-04 00:49:38 +000017#include "llvm/Support/Debug.h"
18#include "llvm/Support/Format.h"
19
20using namespace llvm;
21
Chandler Carruthf98597a2014-04-22 03:10:36 +000022#define DEBUG_TYPE "lli"
23
Andrew Kaylor1b2cfb62013-10-04 00:49:38 +000024RemoteMemoryManager::~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);
Andrew Kaylor97231762013-10-04 20:09:36 +000039 // AllocatedSections will own this memory.
Andrew Kaylor1b2cfb62013-10-04 00:49:38 +000040 AllocatedSections.push_back( Allocation(Block, Alignment, true) );
Andrew Kaylor97231762013-10-04 20:09:36 +000041 // UnmappedSections has the same information but does not own the memory.
42 UnmappedSections.push_back( Allocation(Block, Alignment, true) );
Andrew Kaylor1b2cfb62013-10-04 00:49:38 +000043 return (uint8_t*)Block.base();
44}
45
46uint8_t *RemoteMemoryManager::
47allocateDataSection(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);
Andrew Kaylor97231762013-10-04 20:09:36 +000055 // AllocatedSections will own this memory.
Andrew Kaylor1b2cfb62013-10-04 00:49:38 +000056 AllocatedSections.push_back( Allocation(Block, Alignment, false) );
Andrew Kaylor97231762013-10-04 20:09:36 +000057 // UnmappedSections has the same information but does not own the memory.
58 UnmappedSections.push_back( Allocation(Block, Alignment, false) );
Andrew Kaylor1b2cfb62013-10-04 00:49:38 +000059 return (uint8_t*)Block.base();
60}
61
62sys::MemoryBlock RemoteMemoryManager::allocateSection(uintptr_t Size) {
Rafael Espindola4453e42942014-06-13 03:07:50 +000063 std::error_code ec;
Andrew Kaylor1b2cfb62013-10-04 00:49:38 +000064 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
79void RemoteMemoryManager::notifyObjectLoaded(ExecutionEngine *EE,
Lang Hames829a19a2014-11-26 06:53:26 +000080 const object::ObjectFile &Obj) {
Andrew Kaylor1b2cfb62013-10-04 00:49:38 +000081 // 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();
Andrew Kaylor21730802013-10-04 20:53:49 +000093 SmallVector<std::pair<Allocation, uint64_t>, 16> Offsets;
Andrew Kaylor1b2cfb62013-10-04 00:49:38 +000094 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) {
Andrew Kaylor97231762013-10-04 20:09:36 +000098 Allocation &Section = UnmappedSections[i];
99 if (Section.IsCode) {
100 unsigned Size = Section.MB.size();
101 unsigned Align = Section.Alignment;
Andrew Kaylor1b2cfb62013-10-04 00:49:38 +0000102 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.
Andrew Kaylor21730802013-10-04 20:53:49 +0000108 Offsets.push_back(std::pair<Allocation,uint64_t>(Section, CurOffset));
Andrew Kaylor1b2cfb62013-10-04 00:49:38 +0000109 CurOffset += Size;
110 }
111 }
Alp Tokercb402912014-01-24 17:20:08 +0000112 // Adjust to keep code and data aligned on separate pages.
Andrew Kaylor1b2cfb62013-10-04 00:49:38 +0000113 CurOffset = (CurOffset + MaxAlign - 1) / MaxAlign * MaxAlign;
114 for (size_t i = 0, e = NumSections; i != e; ++i) {
Andrew Kaylor97231762013-10-04 20:09:36 +0000115 Allocation &Section = UnmappedSections[i];
116 if (!Section.IsCode) {
117 unsigned Size = Section.MB.size();
118 unsigned Align = Section.Alignment;
Andrew Kaylor1b2cfb62013-10-04 00:49:38 +0000119 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.
Andrew Kaylor21730802013-10-04 20:53:49 +0000125 Offsets.push_back(std::pair<Allocation,uint64_t>(Section, CurOffset));
Andrew Kaylor1b2cfb62013-10-04 00:49:38 +0000126 CurOffset += Size;
127 }
128 }
129
130 // Allocate space in the remote target.
131 uint64_t RemoteAddr;
Renato Golin695895c2014-01-14 22:43:43 +0000132 if (!Target->allocateSpace(CurOffset, MaxAlign, RemoteAddr))
Andrew Kaylor1b2cfb62013-10-04 00:49:38 +0000133 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;
Andrew Kaylor97231762013-10-04 20:09:36 +0000139 EE->mapSectionAddress(const_cast<void*>(Offsets[i].first.MB.base()), Addr);
Andrew Kaylor1b2cfb62013-10-04 00:49:38 +0000140
Andrew Kaylor97231762013-10-04 20:09:36 +0000141 DEBUG(dbgs() << " Mapping local: " << Offsets[i].first.MB.base()
Andrew Kaylor1b2cfb62013-10-04 00:49:38 +0000142 << " 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.
Andrew Kaylor97231762013-10-04 20:09:36 +0000152 for (DenseMap<uint64_t, Allocation>::iterator
Andrew Kaylor1b2cfb62013-10-04 00:49:38 +0000153 I = MappedSections.begin(), E = MappedSections.end();
154 I != E; ++I) {
155 uint64_t RemoteAddr = I->first;
Andrew Kaylor97231762013-10-04 20:09:36 +0000156 const Allocation &Section = I->second;
157 if (Section.IsCode) {
Renato Golin695895c2014-01-14 22:43:43 +0000158 if (!Target->loadCode(RemoteAddr, Section.MB.base(), Section.MB.size()))
159 report_fatal_error(Target->getErrorMsg());
Andrew Kaylor97231762013-10-04 20:09:36 +0000160 DEBUG(dbgs() << " loading code: " << Section.MB.base()
Andrew Kaylor1b2cfb62013-10-04 00:49:38 +0000161 << " to remote: 0x" << format("%llx", RemoteAddr) << "\n");
162 } else {
Renato Golin695895c2014-01-14 22:43:43 +0000163 if (!Target->loadData(RemoteAddr, Section.MB.base(), Section.MB.size()))
164 report_fatal_error(Target->getErrorMsg());
Andrew Kaylor97231762013-10-04 20:09:36 +0000165 DEBUG(dbgs() << " loading data: " << Section.MB.base()
Andrew Kaylor1b2cfb62013-10-04 00:49:38 +0000166 << " to remote: 0x" << format("%llx", RemoteAddr) << "\n");
167 }
168 }
169
170 MappedSections.clear();
171
172 return false;
173}