//===- Win32/Memory.cpp - Win32 Memory Implementation -----------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file provides the Win32 specific implementation of various Memory
// management utilities
//
//===----------------------------------------------------------------------===//

#include "llvm/Support/DataTypes.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Process.h"

// The Windows.h header must be the last one included.
#include "Windows.h"

namespace {

DWORD getWindowsProtectionFlags(unsigned Flags) {
  switch (Flags) {
  // Contrary to what you might expect, the Windows page protection flags
  // are not a bitwise combination of RWX values
  case llvm::sys::Memory::MF_READ:
    return PAGE_READONLY;
  case llvm::sys::Memory::MF_WRITE:
    // Note: PAGE_WRITE is not supported by VirtualProtect
    return PAGE_READWRITE;
  case llvm::sys::Memory::MF_READ|llvm::sys::Memory::MF_WRITE:
    return PAGE_READWRITE;
  case llvm::sys::Memory::MF_READ|llvm::sys::Memory::MF_EXEC:
    return PAGE_EXECUTE_READ;
  case llvm::sys::Memory::MF_READ |
         llvm::sys::Memory::MF_WRITE |
         llvm::sys::Memory::MF_EXEC:
    return PAGE_EXECUTE_READWRITE;
  case llvm::sys::Memory::MF_EXEC:
    return PAGE_EXECUTE;
  default:
    llvm_unreachable("Illegal memory protection flag specified!");
  }
  // Provide a default return value as required by some compilers.
  return PAGE_NOACCESS;
}

size_t getAllocationGranularity() {
  SYSTEM_INFO  Info;
  ::GetSystemInfo(&Info);
  if (Info.dwPageSize > Info.dwAllocationGranularity)
    return Info.dwPageSize;
  else
    return Info.dwAllocationGranularity;
}

} // namespace

namespace llvm {
namespace sys {

//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only Win32 specific code
//===          and must not be UNIX code
//===----------------------------------------------------------------------===//

MemoryBlock Memory::allocateMappedMemory(size_t NumBytes,
                                         const MemoryBlock *const NearBlock,
                                         unsigned Flags,
                                         error_code &EC) {
  EC = error_code::success();
  if (NumBytes == 0)
    return MemoryBlock();

  // While we'd be happy to allocate single pages, the Windows allocation
  // granularity may be larger than a single page (in practice, it is 64K)
  // so mapping less than that will create an unreachable fragment of memory.
  static const size_t Granularity = getAllocationGranularity();
  const size_t NumBlocks = (NumBytes+Granularity-1)/Granularity;

  uintptr_t Start = NearBlock ? reinterpret_cast<uintptr_t>(NearBlock->base()) +
                                NearBlock->size()
                           : NULL;

  // If the requested address is not aligned to the allocation granularity,
  // round up to get beyond NearBlock. VirtualAlloc would have rounded down.
  if (Start && Start % Granularity != 0)
    Start += Granularity - Start % Granularity;

  DWORD Protect = getWindowsProtectionFlags(Flags);

  void *PA = ::VirtualAlloc(reinterpret_cast<void*>(Start),
                            NumBlocks*Granularity,
                            MEM_RESERVE | MEM_COMMIT, Protect);
  if (PA == NULL) {
    if (NearBlock) {
      // Try again without the NearBlock hint
      return allocateMappedMemory(NumBytes, NULL, Flags, EC);
    }
    EC = error_code(::GetLastError(), system_category());
    return MemoryBlock();
  }

  MemoryBlock Result;
  Result.Address = PA;
  Result.Size = NumBlocks*Granularity;
                                 ;
  if (Flags & MF_EXEC)
    Memory::InvalidateInstructionCache(Result.Address, Result.Size);

  return Result;
}

error_code Memory::releaseMappedMemory(MemoryBlock &M) {
  if (M.Address == 0 || M.Size == 0)
    return error_code::success();

  if (!VirtualFree(M.Address, 0, MEM_RELEASE))
    return error_code(::GetLastError(), system_category());

  M.Address = 0;
  M.Size = 0;

  return error_code::success();
}

error_code Memory::protectMappedMemory(const MemoryBlock &M,
                                       unsigned Flags) {
  if (M.Address == 0 || M.Size == 0)
    return error_code::success();

  DWORD Protect = getWindowsProtectionFlags(Flags);

  DWORD OldFlags;
  if (!VirtualProtect(M.Address, M.Size, Protect, &OldFlags))
    return error_code(::GetLastError(), system_category());

  if (Flags & MF_EXEC)
    Memory::InvalidateInstructionCache(M.Address, M.Size);

  return error_code::success();
}

/// InvalidateInstructionCache - Before the JIT can run a block of code
/// that has been emitted it must invalidate the instruction cache on some
/// platforms.
void Memory::InvalidateInstructionCache(
    const void *Addr, size_t Len) {
  FlushInstructionCache(GetCurrentProcess(), Addr, Len);
}


MemoryBlock Memory::AllocateRWX(size_t NumBytes,
                                const MemoryBlock *NearBlock,
                                std::string *ErrMsg) {
  MemoryBlock MB;
  error_code EC;
  MB = allocateMappedMemory(NumBytes, NearBlock,
                            MF_READ|MF_WRITE|MF_EXEC, EC);
  if (EC != error_code::success() && ErrMsg) {
    MakeErrMsg(ErrMsg, EC.message());
  }
  return MB;
}

bool Memory::ReleaseRWX(MemoryBlock &M, std::string *ErrMsg) {
  error_code EC = releaseMappedMemory(M);
  if (EC == error_code::success())
    return false;
  MakeErrMsg(ErrMsg, EC.message());
  return true;
}

static DWORD getProtection(const void *addr) {
  MEMORY_BASIC_INFORMATION info;
  if (sizeof(info) == ::VirtualQuery(addr, &info, sizeof(info))) {
    return info.Protect;
  }
  return 0;
}

bool Memory::setWritable(MemoryBlock &M, std::string *ErrMsg) {
  if (!setRangeWritable(M.Address, M.Size)) {
    return MakeErrMsg(ErrMsg, "Cannot set memory to writeable: ");
  }
  return true;
}

bool Memory::setExecutable(MemoryBlock &M, std::string *ErrMsg) {
  if (!setRangeExecutable(M.Address, M.Size)) {
    return MakeErrMsg(ErrMsg, "Cannot set memory to executable: ");
  }
  return true;
}

bool Memory::setRangeWritable(const void *Addr, size_t Size) {
  DWORD prot = getProtection(Addr);
  if (!prot)
    return false;

  if (prot == PAGE_EXECUTE || prot == PAGE_EXECUTE_READ) {
    prot = PAGE_EXECUTE_READWRITE;
  } else if (prot == PAGE_NOACCESS || prot == PAGE_READONLY) {
    prot = PAGE_READWRITE;
  }

  DWORD oldProt;
  Memory::InvalidateInstructionCache(Addr, Size);
  return ::VirtualProtect(const_cast<LPVOID>(Addr), Size, prot, &oldProt)
            == TRUE;
}

bool Memory::setRangeExecutable(const void *Addr, size_t Size) {
  DWORD prot = getProtection(Addr);
  if (!prot)
    return false;

  if (prot == PAGE_NOACCESS) {
    prot = PAGE_EXECUTE;
  } else if (prot == PAGE_READONLY) {
    prot = PAGE_EXECUTE_READ;
  } else if (prot == PAGE_READWRITE) {
    prot = PAGE_EXECUTE_READWRITE;
  }

  DWORD oldProt;
  Memory::InvalidateInstructionCache(Addr, Size);
  return ::VirtualProtect(const_cast<LPVOID>(Addr), Size, prot, &oldProt)
            == TRUE;
}

} // namespace sys
} // namespace llvm
