1*349cc55cSDimitry Andric //===----- EPCGenericRTDyldMemoryManager.cpp - EPC-bbasde MemMgr -----===// 2*349cc55cSDimitry Andric // 3*349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*349cc55cSDimitry Andric // 7*349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 8*349cc55cSDimitry Andric 9*349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/EPCGenericRTDyldMemoryManager.h" 10*349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/EPCGenericMemoryAccess.h" 11*349cc55cSDimitry Andric #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h" 12*349cc55cSDimitry Andric #include "llvm/Support/Alignment.h" 13*349cc55cSDimitry Andric #include "llvm/Support/FormatVariadic.h" 14*349cc55cSDimitry Andric 15*349cc55cSDimitry Andric #define DEBUG_TYPE "orc" 16*349cc55cSDimitry Andric 17*349cc55cSDimitry Andric namespace llvm { 18*349cc55cSDimitry Andric namespace orc { 19*349cc55cSDimitry Andric 20*349cc55cSDimitry Andric Expected<std::unique_ptr<EPCGenericRTDyldMemoryManager>> 21*349cc55cSDimitry Andric EPCGenericRTDyldMemoryManager::CreateWithDefaultBootstrapSymbols( 22*349cc55cSDimitry Andric ExecutorProcessControl &EPC) { 23*349cc55cSDimitry Andric SymbolAddrs SAs; 24*349cc55cSDimitry Andric if (auto Err = EPC.getBootstrapSymbols( 25*349cc55cSDimitry Andric {{SAs.Instance, rt::SimpleExecutorMemoryManagerInstanceName}, 26*349cc55cSDimitry Andric {SAs.Reserve, rt::SimpleExecutorMemoryManagerReserveWrapperName}, 27*349cc55cSDimitry Andric {SAs.Finalize, rt::SimpleExecutorMemoryManagerFinalizeWrapperName}, 28*349cc55cSDimitry Andric {SAs.Deallocate, 29*349cc55cSDimitry Andric rt::SimpleExecutorMemoryManagerDeallocateWrapperName}, 30*349cc55cSDimitry Andric {SAs.RegisterEHFrame, 31*349cc55cSDimitry Andric rt::RegisterEHFrameSectionCustomDirectWrapperName}, 32*349cc55cSDimitry Andric {SAs.DeregisterEHFrame, 33*349cc55cSDimitry Andric rt::DeregisterEHFrameSectionCustomDirectWrapperName}})) 34*349cc55cSDimitry Andric return std::move(Err); 35*349cc55cSDimitry Andric return std::make_unique<EPCGenericRTDyldMemoryManager>(EPC, std::move(SAs)); 36*349cc55cSDimitry Andric } 37*349cc55cSDimitry Andric 38*349cc55cSDimitry Andric EPCGenericRTDyldMemoryManager::EPCGenericRTDyldMemoryManager( 39*349cc55cSDimitry Andric ExecutorProcessControl &EPC, SymbolAddrs SAs) 40*349cc55cSDimitry Andric : EPC(EPC), SAs(std::move(SAs)) { 41*349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << "Created remote allocator " << (void *)this << "\n"); 42*349cc55cSDimitry Andric } 43*349cc55cSDimitry Andric 44*349cc55cSDimitry Andric EPCGenericRTDyldMemoryManager::~EPCGenericRTDyldMemoryManager() { 45*349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << "Destroyed remote allocator " << (void *)this << "\n"); 46*349cc55cSDimitry Andric if (!ErrMsg.empty()) 47*349cc55cSDimitry Andric errs() << "Destroying with existing errors:\n" << ErrMsg << "\n"; 48*349cc55cSDimitry Andric 49*349cc55cSDimitry Andric Error Err = Error::success(); 50*349cc55cSDimitry Andric if (auto Err2 = EPC.callSPSWrapper< 51*349cc55cSDimitry Andric rt::SPSSimpleExecutorMemoryManagerDeallocateSignature>( 52*349cc55cSDimitry Andric SAs.Reserve, Err, SAs.Instance, FinalizedAllocs)) { 53*349cc55cSDimitry Andric // FIXME: Report errors through EPC once that functionality is available. 54*349cc55cSDimitry Andric logAllUnhandledErrors(std::move(Err2), errs(), ""); 55*349cc55cSDimitry Andric return; 56*349cc55cSDimitry Andric } 57*349cc55cSDimitry Andric 58*349cc55cSDimitry Andric if (Err) 59*349cc55cSDimitry Andric logAllUnhandledErrors(std::move(Err), errs(), ""); 60*349cc55cSDimitry Andric } 61*349cc55cSDimitry Andric 62*349cc55cSDimitry Andric uint8_t *EPCGenericRTDyldMemoryManager::allocateCodeSection( 63*349cc55cSDimitry Andric uintptr_t Size, unsigned Alignment, unsigned SectionID, 64*349cc55cSDimitry Andric StringRef SectionName) { 65*349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(M); 66*349cc55cSDimitry Andric LLVM_DEBUG({ 67*349cc55cSDimitry Andric dbgs() << "Allocator " << (void *)this << " allocating code section " 68*349cc55cSDimitry Andric << SectionName << ": size = " << formatv("{0:x}", Size) 69*349cc55cSDimitry Andric << " bytes, alignment = " << Alignment << "\n"; 70*349cc55cSDimitry Andric }); 71*349cc55cSDimitry Andric auto &Seg = Unmapped.back().CodeAllocs; 72*349cc55cSDimitry Andric Seg.emplace_back(Size, Alignment); 73*349cc55cSDimitry Andric return reinterpret_cast<uint8_t *>( 74*349cc55cSDimitry Andric alignAddr(Seg.back().Contents.get(), Align(Alignment))); 75*349cc55cSDimitry Andric } 76*349cc55cSDimitry Andric 77*349cc55cSDimitry Andric uint8_t *EPCGenericRTDyldMemoryManager::allocateDataSection( 78*349cc55cSDimitry Andric uintptr_t Size, unsigned Alignment, unsigned SectionID, 79*349cc55cSDimitry Andric StringRef SectionName, bool IsReadOnly) { 80*349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(M); 81*349cc55cSDimitry Andric LLVM_DEBUG({ 82*349cc55cSDimitry Andric dbgs() << "Allocator " << (void *)this << " allocating " 83*349cc55cSDimitry Andric << (IsReadOnly ? "ro" : "rw") << "-data section " << SectionName 84*349cc55cSDimitry Andric << ": size = " << formatv("{0:x}", Size) << " bytes, alignment " 85*349cc55cSDimitry Andric << Alignment << ")\n"; 86*349cc55cSDimitry Andric }); 87*349cc55cSDimitry Andric 88*349cc55cSDimitry Andric auto &Seg = 89*349cc55cSDimitry Andric IsReadOnly ? Unmapped.back().RODataAllocs : Unmapped.back().RWDataAllocs; 90*349cc55cSDimitry Andric 91*349cc55cSDimitry Andric Seg.emplace_back(Size, Alignment); 92*349cc55cSDimitry Andric return reinterpret_cast<uint8_t *>( 93*349cc55cSDimitry Andric alignAddr(Seg.back().Contents.get(), Align(Alignment))); 94*349cc55cSDimitry Andric } 95*349cc55cSDimitry Andric 96*349cc55cSDimitry Andric void EPCGenericRTDyldMemoryManager::reserveAllocationSpace( 97*349cc55cSDimitry Andric uintptr_t CodeSize, uint32_t CodeAlign, uintptr_t RODataSize, 98*349cc55cSDimitry Andric uint32_t RODataAlign, uintptr_t RWDataSize, uint32_t RWDataAlign) { 99*349cc55cSDimitry Andric 100*349cc55cSDimitry Andric { 101*349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(M); 102*349cc55cSDimitry Andric // If there's already an error then bail out. 103*349cc55cSDimitry Andric if (!ErrMsg.empty()) 104*349cc55cSDimitry Andric return; 105*349cc55cSDimitry Andric 106*349cc55cSDimitry Andric if (!isPowerOf2_32(CodeAlign) || CodeAlign > EPC.getPageSize()) { 107*349cc55cSDimitry Andric ErrMsg = "Invalid code alignment in reserveAllocationSpace"; 108*349cc55cSDimitry Andric return; 109*349cc55cSDimitry Andric } 110*349cc55cSDimitry Andric if (!isPowerOf2_32(RODataAlign) || RODataAlign > EPC.getPageSize()) { 111*349cc55cSDimitry Andric ErrMsg = "Invalid ro-data alignment in reserveAllocationSpace"; 112*349cc55cSDimitry Andric return; 113*349cc55cSDimitry Andric } 114*349cc55cSDimitry Andric if (!isPowerOf2_32(RWDataAlign) || RWDataAlign > EPC.getPageSize()) { 115*349cc55cSDimitry Andric ErrMsg = "Invalid rw-data alignment in reserveAllocationSpace"; 116*349cc55cSDimitry Andric return; 117*349cc55cSDimitry Andric } 118*349cc55cSDimitry Andric } 119*349cc55cSDimitry Andric 120*349cc55cSDimitry Andric uint64_t TotalSize = 0; 121*349cc55cSDimitry Andric TotalSize += alignTo(CodeSize, EPC.getPageSize()); 122*349cc55cSDimitry Andric TotalSize += alignTo(RODataSize, EPC.getPageSize()); 123*349cc55cSDimitry Andric TotalSize += alignTo(RWDataSize, EPC.getPageSize()); 124*349cc55cSDimitry Andric 125*349cc55cSDimitry Andric LLVM_DEBUG({ 126*349cc55cSDimitry Andric dbgs() << "Allocator " << (void *)this << " reserving " 127*349cc55cSDimitry Andric << formatv("{0:x}", TotalSize) << " bytes.\n"; 128*349cc55cSDimitry Andric }); 129*349cc55cSDimitry Andric 130*349cc55cSDimitry Andric Expected<ExecutorAddr> TargetAllocAddr((ExecutorAddr())); 131*349cc55cSDimitry Andric if (auto Err = EPC.callSPSWrapper< 132*349cc55cSDimitry Andric rt::SPSSimpleExecutorMemoryManagerReserveSignature>( 133*349cc55cSDimitry Andric SAs.Reserve, TargetAllocAddr, SAs.Instance, TotalSize)) { 134*349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(M); 135*349cc55cSDimitry Andric ErrMsg = toString(std::move(Err)); 136*349cc55cSDimitry Andric return; 137*349cc55cSDimitry Andric } 138*349cc55cSDimitry Andric if (!TargetAllocAddr) { 139*349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(M); 140*349cc55cSDimitry Andric ErrMsg = toString(TargetAllocAddr.takeError()); 141*349cc55cSDimitry Andric return; 142*349cc55cSDimitry Andric } 143*349cc55cSDimitry Andric 144*349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(M); 145*349cc55cSDimitry Andric Unmapped.push_back(AllocGroup()); 146*349cc55cSDimitry Andric Unmapped.back().RemoteCode = { 147*349cc55cSDimitry Andric *TargetAllocAddr, ExecutorAddrDiff(alignTo(CodeSize, EPC.getPageSize()))}; 148*349cc55cSDimitry Andric Unmapped.back().RemoteROData = { 149*349cc55cSDimitry Andric Unmapped.back().RemoteCode.End, 150*349cc55cSDimitry Andric ExecutorAddrDiff(alignTo(RODataSize, EPC.getPageSize()))}; 151*349cc55cSDimitry Andric Unmapped.back().RemoteRWData = { 152*349cc55cSDimitry Andric Unmapped.back().RemoteROData.End, 153*349cc55cSDimitry Andric ExecutorAddrDiff(alignTo(RWDataSize, EPC.getPageSize()))}; 154*349cc55cSDimitry Andric } 155*349cc55cSDimitry Andric 156*349cc55cSDimitry Andric bool EPCGenericRTDyldMemoryManager::needsToReserveAllocationSpace() { 157*349cc55cSDimitry Andric return true; 158*349cc55cSDimitry Andric } 159*349cc55cSDimitry Andric 160*349cc55cSDimitry Andric void EPCGenericRTDyldMemoryManager::registerEHFrames(uint8_t *Addr, 161*349cc55cSDimitry Andric uint64_t LoadAddr, 162*349cc55cSDimitry Andric size_t Size) { 163*349cc55cSDimitry Andric LLVM_DEBUG({ 164*349cc55cSDimitry Andric dbgs() << "Allocator " << (void *)this << " added unfinalized eh-frame " 165*349cc55cSDimitry Andric << formatv("[ {0:x} {1:x} ]", LoadAddr, LoadAddr + Size) << "\n"; 166*349cc55cSDimitry Andric }); 167*349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(M); 168*349cc55cSDimitry Andric // Bail out early if there's already an error. 169*349cc55cSDimitry Andric if (!ErrMsg.empty()) 170*349cc55cSDimitry Andric return; 171*349cc55cSDimitry Andric 172*349cc55cSDimitry Andric ExecutorAddr LA(LoadAddr); 173*349cc55cSDimitry Andric for (auto &Alloc : llvm::reverse(Unfinalized)) { 174*349cc55cSDimitry Andric if (Alloc.RemoteCode.contains(LA) || Alloc.RemoteROData.contains(LA) || 175*349cc55cSDimitry Andric Alloc.RemoteRWData.contains(LA)) { 176*349cc55cSDimitry Andric Alloc.UnfinalizedEHFrames.push_back({LA, Size}); 177*349cc55cSDimitry Andric return; 178*349cc55cSDimitry Andric } 179*349cc55cSDimitry Andric } 180*349cc55cSDimitry Andric ErrMsg = "eh-frame does not lie inside unfinalized alloc"; 181*349cc55cSDimitry Andric } 182*349cc55cSDimitry Andric 183*349cc55cSDimitry Andric void EPCGenericRTDyldMemoryManager::deregisterEHFrames() { 184*349cc55cSDimitry Andric // This is a no-op for us: We've registered a deallocation action for it. 185*349cc55cSDimitry Andric } 186*349cc55cSDimitry Andric 187*349cc55cSDimitry Andric void EPCGenericRTDyldMemoryManager::notifyObjectLoaded( 188*349cc55cSDimitry Andric RuntimeDyld &Dyld, const object::ObjectFile &Obj) { 189*349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(M); 190*349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << "Allocator " << (void *)this << " applied mappings:\n"); 191*349cc55cSDimitry Andric for (auto &ObjAllocs : Unmapped) { 192*349cc55cSDimitry Andric mapAllocsToRemoteAddrs(Dyld, ObjAllocs.CodeAllocs, 193*349cc55cSDimitry Andric ObjAllocs.RemoteCode.Start); 194*349cc55cSDimitry Andric mapAllocsToRemoteAddrs(Dyld, ObjAllocs.RODataAllocs, 195*349cc55cSDimitry Andric ObjAllocs.RemoteROData.Start); 196*349cc55cSDimitry Andric mapAllocsToRemoteAddrs(Dyld, ObjAllocs.RWDataAllocs, 197*349cc55cSDimitry Andric ObjAllocs.RemoteRWData.Start); 198*349cc55cSDimitry Andric Unfinalized.push_back(std::move(ObjAllocs)); 199*349cc55cSDimitry Andric } 200*349cc55cSDimitry Andric Unmapped.clear(); 201*349cc55cSDimitry Andric } 202*349cc55cSDimitry Andric 203*349cc55cSDimitry Andric bool EPCGenericRTDyldMemoryManager::finalizeMemory(std::string *ErrMsg) { 204*349cc55cSDimitry Andric LLVM_DEBUG(dbgs() << "Allocator " << (void *)this << " finalizing:\n"); 205*349cc55cSDimitry Andric 206*349cc55cSDimitry Andric // If there's an error then bail out here. 207*349cc55cSDimitry Andric std::vector<AllocGroup> Allocs; 208*349cc55cSDimitry Andric { 209*349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(M); 210*349cc55cSDimitry Andric if (ErrMsg && !this->ErrMsg.empty()) { 211*349cc55cSDimitry Andric *ErrMsg = std::move(this->ErrMsg); 212*349cc55cSDimitry Andric return true; 213*349cc55cSDimitry Andric } 214*349cc55cSDimitry Andric std::swap(Allocs, Unfinalized); 215*349cc55cSDimitry Andric } 216*349cc55cSDimitry Andric 217*349cc55cSDimitry Andric // Loop over unfinalized objects to make finalization requests. 218*349cc55cSDimitry Andric for (auto &ObjAllocs : Allocs) { 219*349cc55cSDimitry Andric 220*349cc55cSDimitry Andric tpctypes::WireProtectionFlags SegProts[3] = { 221*349cc55cSDimitry Andric tpctypes::toWireProtectionFlags( 222*349cc55cSDimitry Andric static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ | 223*349cc55cSDimitry Andric sys::Memory::MF_EXEC)), 224*349cc55cSDimitry Andric tpctypes::toWireProtectionFlags(sys::Memory::MF_READ), 225*349cc55cSDimitry Andric tpctypes::toWireProtectionFlags( 226*349cc55cSDimitry Andric static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ | 227*349cc55cSDimitry Andric sys::Memory::MF_WRITE))}; 228*349cc55cSDimitry Andric 229*349cc55cSDimitry Andric ExecutorAddrRange *RemoteAddrs[3] = {&ObjAllocs.RemoteCode, 230*349cc55cSDimitry Andric &ObjAllocs.RemoteROData, 231*349cc55cSDimitry Andric &ObjAllocs.RemoteRWData}; 232*349cc55cSDimitry Andric 233*349cc55cSDimitry Andric std::vector<Alloc> *SegSections[3] = {&ObjAllocs.CodeAllocs, 234*349cc55cSDimitry Andric &ObjAllocs.RODataAllocs, 235*349cc55cSDimitry Andric &ObjAllocs.RWDataAllocs}; 236*349cc55cSDimitry Andric 237*349cc55cSDimitry Andric tpctypes::FinalizeRequest FR; 238*349cc55cSDimitry Andric std::unique_ptr<char[]> AggregateContents[3]; 239*349cc55cSDimitry Andric 240*349cc55cSDimitry Andric for (unsigned I = 0; I != 3; ++I) { 241*349cc55cSDimitry Andric FR.Segments.push_back({}); 242*349cc55cSDimitry Andric auto &Seg = FR.Segments.back(); 243*349cc55cSDimitry Andric Seg.Prot = SegProts[I]; 244*349cc55cSDimitry Andric Seg.Addr = RemoteAddrs[I]->Start; 245*349cc55cSDimitry Andric for (auto &SecAlloc : *SegSections[I]) { 246*349cc55cSDimitry Andric Seg.Size = alignTo(Seg.Size, SecAlloc.Align); 247*349cc55cSDimitry Andric Seg.Size += SecAlloc.Size; 248*349cc55cSDimitry Andric } 249*349cc55cSDimitry Andric AggregateContents[I] = std::make_unique<char[]>(Seg.Size); 250*349cc55cSDimitry Andric size_t SecOffset = 0; 251*349cc55cSDimitry Andric for (auto &SecAlloc : *SegSections[I]) { 252*349cc55cSDimitry Andric SecOffset = alignTo(SecOffset, SecAlloc.Align); 253*349cc55cSDimitry Andric memcpy(&AggregateContents[I][SecOffset], 254*349cc55cSDimitry Andric reinterpret_cast<const char *>( 255*349cc55cSDimitry Andric alignAddr(SecAlloc.Contents.get(), Align(SecAlloc.Align))), 256*349cc55cSDimitry Andric SecAlloc.Size); 257*349cc55cSDimitry Andric SecOffset += SecAlloc.Size; 258*349cc55cSDimitry Andric // FIXME: Can we reset SecAlloc.Content here, now that it's copied into 259*349cc55cSDimitry Andric // the aggregated content? 260*349cc55cSDimitry Andric } 261*349cc55cSDimitry Andric Seg.Content = {AggregateContents[I].get(), SecOffset}; 262*349cc55cSDimitry Andric } 263*349cc55cSDimitry Andric 264*349cc55cSDimitry Andric for (auto &Frame : ObjAllocs.UnfinalizedEHFrames) 265*349cc55cSDimitry Andric FR.Actions.push_back( 266*349cc55cSDimitry Andric {{SAs.RegisterEHFrame, 267*349cc55cSDimitry Andric {ExecutorAddr(Frame.Addr), ExecutorAddrDiff(Frame.Size)}}, 268*349cc55cSDimitry Andric {SAs.DeregisterEHFrame, 269*349cc55cSDimitry Andric {ExecutorAddr(Frame.Addr), ExecutorAddrDiff(Frame.Size)}}}); 270*349cc55cSDimitry Andric 271*349cc55cSDimitry Andric // We'll also need to make an extra allocation for the eh-frame wrapper call 272*349cc55cSDimitry Andric // arguments. 273*349cc55cSDimitry Andric Error FinalizeErr = Error::success(); 274*349cc55cSDimitry Andric if (auto Err = EPC.callSPSWrapper< 275*349cc55cSDimitry Andric rt::SPSSimpleExecutorMemoryManagerFinalizeSignature>( 276*349cc55cSDimitry Andric SAs.Finalize, FinalizeErr, SAs.Instance, std::move(FR))) { 277*349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(M); 278*349cc55cSDimitry Andric this->ErrMsg = toString(std::move(Err)); 279*349cc55cSDimitry Andric dbgs() << "Serialization error: " << this->ErrMsg << "\n"; 280*349cc55cSDimitry Andric if (ErrMsg) 281*349cc55cSDimitry Andric *ErrMsg = this->ErrMsg; 282*349cc55cSDimitry Andric return true; 283*349cc55cSDimitry Andric } 284*349cc55cSDimitry Andric if (FinalizeErr) { 285*349cc55cSDimitry Andric std::lock_guard<std::mutex> Lock(M); 286*349cc55cSDimitry Andric this->ErrMsg = toString(std::move(FinalizeErr)); 287*349cc55cSDimitry Andric dbgs() << "Finalization error: " << this->ErrMsg << "\n"; 288*349cc55cSDimitry Andric if (ErrMsg) 289*349cc55cSDimitry Andric *ErrMsg = this->ErrMsg; 290*349cc55cSDimitry Andric return true; 291*349cc55cSDimitry Andric } 292*349cc55cSDimitry Andric } 293*349cc55cSDimitry Andric 294*349cc55cSDimitry Andric return false; 295*349cc55cSDimitry Andric } 296*349cc55cSDimitry Andric 297*349cc55cSDimitry Andric void EPCGenericRTDyldMemoryManager::mapAllocsToRemoteAddrs( 298*349cc55cSDimitry Andric RuntimeDyld &Dyld, std::vector<Alloc> &Allocs, ExecutorAddr NextAddr) { 299*349cc55cSDimitry Andric for (auto &Alloc : Allocs) { 300*349cc55cSDimitry Andric NextAddr.setValue(alignTo(NextAddr.getValue(), Alloc.Align)); 301*349cc55cSDimitry Andric LLVM_DEBUG({ 302*349cc55cSDimitry Andric dbgs() << " " << static_cast<void *>(Alloc.Contents.get()) << " -> " 303*349cc55cSDimitry Andric << format("0x%016" PRIx64, NextAddr.getValue()) << "\n"; 304*349cc55cSDimitry Andric }); 305*349cc55cSDimitry Andric Dyld.mapSectionAddress(reinterpret_cast<const void *>(alignAddr( 306*349cc55cSDimitry Andric Alloc.Contents.get(), Align(Alloc.Align))), 307*349cc55cSDimitry Andric NextAddr.getValue()); 308*349cc55cSDimitry Andric Alloc.RemoteAddr = NextAddr; 309*349cc55cSDimitry Andric // Only advance NextAddr if it was non-null to begin with, 310*349cc55cSDimitry Andric // otherwise leave it as null. 311*349cc55cSDimitry Andric if (NextAddr) 312*349cc55cSDimitry Andric NextAddr += ExecutorAddrDiff(Alloc.Size); 313*349cc55cSDimitry Andric } 314*349cc55cSDimitry Andric } 315*349cc55cSDimitry Andric 316*349cc55cSDimitry Andric } // end namespace orc 317*349cc55cSDimitry Andric } // end namespace llvm 318