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