//===---- RemoteMemoryManager.cpp - Recording memory manager --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This memory manager allocates local storage and keeps a record of each
// allocation. Iterators are provided for all data and code allocations.
//
//===----------------------------------------------------------------------===//

#include "RemoteMemoryManager.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"

using namespace llvm;

#define DEBUG_TYPE "lli"

RemoteMemoryManager::~RemoteMemoryManager() {
  for (SmallVector<Allocation, 2>::iterator
         I = AllocatedSections.begin(), E = AllocatedSections.end();
       I != E; ++I)
    sys::Memory::releaseMappedMemory(I->MB);
}

uint8_t *RemoteMemoryManager::
allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID,
                    StringRef SectionName) {
  // The recording memory manager is just a local copy of the remote target.
  // The alignment requirement is just stored here for later use. Regular
  // heap storage is sufficient here, but we're using mapped memory to work
  // around a bug in MCJIT.
  sys::MemoryBlock Block = allocateSection(Size);
  // AllocatedSections will own this memory.
  AllocatedSections.push_back( Allocation(Block, Alignment, true) );
  // UnmappedSections has the same information but does not own the memory.
  UnmappedSections.push_back( Allocation(Block, Alignment, true) );
  return (uint8_t*)Block.base();
}

uint8_t *RemoteMemoryManager::
allocateDataSection(uintptr_t Size, unsigned Alignment,
                    unsigned SectionID, StringRef SectionName,
                    bool IsReadOnly) {
  // The recording memory manager is just a local copy of the remote target.
  // The alignment requirement is just stored here for later use. Regular
  // heap storage is sufficient here, but we're using mapped memory to work
  // around a bug in MCJIT.
  sys::MemoryBlock Block = allocateSection(Size);
  // AllocatedSections will own this memory.
  AllocatedSections.push_back( Allocation(Block, Alignment, false) );
  // UnmappedSections has the same information but does not own the memory.
  UnmappedSections.push_back( Allocation(Block, Alignment, false) );
  return (uint8_t*)Block.base();
}

sys::MemoryBlock RemoteMemoryManager::allocateSection(uintptr_t Size) {
  std::error_code ec;
  sys::MemoryBlock MB = sys::Memory::allocateMappedMemory(Size,
                                                          &Near,
                                                          sys::Memory::MF_READ |
                                                          sys::Memory::MF_WRITE,
                                                          ec);
  assert(!ec && MB.base());

  // FIXME: This is part of a work around to keep sections near one another
  // when MCJIT performs relocations after code emission but before
  // the generated code is moved to the remote target.
  // Save this address as the basis for our next request
  Near = MB;
  return MB;
}

void RemoteMemoryManager::notifyObjectLoaded(ExecutionEngine *EE,
                                             const object::ObjectFile &Obj) {
  // The client should have called setRemoteTarget() before triggering any
  // code generation.
  assert(Target);
  if (!Target)
    return;

  // FIXME: Make this function thread safe.

  // Lay out our sections in order, with all the code sections first, then
  // all the data sections.
  uint64_t CurOffset = 0;
  unsigned MaxAlign = Target->getPageAlignment();
  SmallVector<std::pair<Allocation, uint64_t>, 16> Offsets;
  unsigned NumSections = UnmappedSections.size();
  // We're going to go through the list twice to separate code and data, but
  // it's a very small list, so that's OK.
  for (size_t i = 0, e = NumSections; i != e; ++i) {
    Allocation &Section = UnmappedSections[i];
    if (Section.IsCode) {
      unsigned Size = Section.MB.size();
      unsigned Align = Section.Alignment;
      DEBUG(dbgs() << "code region: size " << Size
                  << ", alignment " << Align << "\n");
      // Align the current offset up to whatever is needed for the next
      // section.
      CurOffset = (CurOffset + Align - 1) / Align * Align;
      // Save off the address of the new section and allocate its space.
      Offsets.push_back(std::pair<Allocation,uint64_t>(Section, CurOffset));
      CurOffset += Size;
    }
  }
  // Adjust to keep code and data aligned on separate pages.
  CurOffset = (CurOffset + MaxAlign - 1) / MaxAlign * MaxAlign;
  for (size_t i = 0, e = NumSections; i != e; ++i) {
    Allocation &Section = UnmappedSections[i];
    if (!Section.IsCode) {
      unsigned Size = Section.MB.size();
      unsigned Align = Section.Alignment;
      DEBUG(dbgs() << "data region: size " << Size
                  << ", alignment " << Align << "\n");
      // Align the current offset up to whatever is needed for the next
      // section.
      CurOffset = (CurOffset + Align - 1) / Align * Align;
      // Save off the address of the new section and allocate its space.
      Offsets.push_back(std::pair<Allocation,uint64_t>(Section, CurOffset));
      CurOffset += Size;
    }
  }

  // Allocate space in the remote target.
  uint64_t RemoteAddr;
  if (!Target->allocateSpace(CurOffset, MaxAlign, RemoteAddr))
    report_fatal_error(Target->getErrorMsg());

  // Map the section addresses so relocations will get updated in the local
  // copies of the sections.
  for (unsigned i = 0, e = Offsets.size(); i != e; ++i) {
    uint64_t Addr = RemoteAddr + Offsets[i].second;
    EE->mapSectionAddress(const_cast<void*>(Offsets[i].first.MB.base()), Addr);

    DEBUG(dbgs() << "  Mapping local: " << Offsets[i].first.MB.base()
                 << " to remote: 0x" << format("%llx", Addr) << "\n");

    MappedSections[Addr] = Offsets[i].first;
  }

  UnmappedSections.clear();
}

bool RemoteMemoryManager::finalizeMemory(std::string *ErrMsg) {
  // FIXME: Make this function thread safe.
  for (DenseMap<uint64_t, Allocation>::iterator
         I = MappedSections.begin(), E = MappedSections.end();
       I != E; ++I) {
    uint64_t RemoteAddr = I->first;
    const Allocation &Section = I->second;
    if (Section.IsCode) {
      if (!Target->loadCode(RemoteAddr, Section.MB.base(), Section.MB.size()))
        report_fatal_error(Target->getErrorMsg());
      DEBUG(dbgs() << "  loading code: " << Section.MB.base()
            << " to remote: 0x" << format("%llx", RemoteAddr) << "\n");
    } else {
      if (!Target->loadData(RemoteAddr, Section.MB.base(), Section.MB.size()))
        report_fatal_error(Target->getErrorMsg());
      DEBUG(dbgs() << "  loading data: " << Section.MB.base()
            << " to remote: 0x" << format("%llx", RemoteAddr) << "\n");
    }
  }

  MappedSections.clear();

  return false;
}
