xref: /minix3/external/bsd/llvm/dist/llvm/tools/lli/RemoteMemoryManager.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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