aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Support
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Support')
-rw-r--r--lib/Support/APFloat.cpp56
-rw-r--r--lib/Support/CMakeLists.txt1
-rw-r--r--lib/Support/DataExtractor.cpp6
-rw-r--r--lib/Support/Debug.cpp10
-rw-r--r--lib/Support/FileOutputBuffer.cpp148
-rw-r--r--lib/Support/Mutex.cpp3
-rw-r--r--lib/Support/Triple.cpp2
-rw-r--r--lib/Support/Unix/Path.inc4
-rw-r--r--lib/Support/Unix/PathV2.inc118
-rw-r--r--lib/Support/Unix/Process.inc7
-rw-r--r--lib/Support/Windows/PathV2.inc199
11 files changed, 530 insertions, 24 deletions
diff --git a/lib/Support/APFloat.cpp b/lib/Support/APFloat.cpp
index 409d4fb..ed261a4 100644
--- a/lib/Support/APFloat.cpp
+++ b/lib/Support/APFloat.cpp
@@ -1765,6 +1765,50 @@ APFloat::fusedMultiplyAdd(const APFloat &multiplicand,
return fs;
}
+/* Rounding-mode corrrect round to integral value. */
+APFloat::opStatus APFloat::roundToIntegral(roundingMode rounding_mode) {
+ opStatus fs;
+ assertArithmeticOK(*semantics);
+
+ // If the exponent is large enough, we know that this value is already
+ // integral, and the arithmetic below would potentially cause it to saturate
+ // to +/-Inf. Bail out early instead.
+ if (exponent+1 >= (int)semanticsPrecision(*semantics))
+ return opOK;
+
+ // The algorithm here is quite simple: we add 2^(p-1), where p is the
+ // precision of our format, and then subtract it back off again. The choice
+ // of rounding modes for the addition/subtraction determines the rounding mode
+ // for our integral rounding as well.
+ // NOTE: When the input value is negative, we do subtraction followed by
+ // addition instead.
+ APInt IntegerConstant(NextPowerOf2(semanticsPrecision(*semantics)), 1);
+ IntegerConstant <<= semanticsPrecision(*semantics)-1;
+ APFloat MagicConstant(*semantics);
+ fs = MagicConstant.convertFromAPInt(IntegerConstant, false,
+ rmNearestTiesToEven);
+ MagicConstant.copySign(*this);
+
+ if (fs != opOK)
+ return fs;
+
+ // Preserve the input sign so that we can handle 0.0/-0.0 cases correctly.
+ bool inputSign = isNegative();
+
+ fs = add(MagicConstant, rounding_mode);
+ if (fs != opOK && fs != opInexact)
+ return fs;
+
+ fs = subtract(MagicConstant, rounding_mode);
+
+ // Restore the input sign.
+ if (inputSign != isNegative())
+ changeSign();
+
+ return fs;
+}
+
+
/* Comparison requires normalized numbers. */
APFloat::cmpResult
APFloat::compare(const APFloat &rhs) const
@@ -3278,16 +3322,8 @@ APFloat::APFloat(double d) : exponent2(0), sign2(0) {
}
namespace {
- static void append(SmallVectorImpl<char> &Buffer,
- unsigned N, const char *Str) {
- unsigned Start = Buffer.size();
- Buffer.set_size(Start + N);
- memcpy(&Buffer[Start], Str, N);
- }
-
- template <unsigned N>
- void append(SmallVectorImpl<char> &Buffer, const char (&Str)[N]) {
- append(Buffer, N, Str);
+ void append(SmallVectorImpl<char> &Buffer, StringRef Str) {
+ Buffer.append(Str.begin(), Str.end());
}
/// Removes data from the given significand until it is no more
diff --git a/lib/Support/CMakeLists.txt b/lib/Support/CMakeLists.txt
index 9103327..83baf60 100644
--- a/lib/Support/CMakeLists.txt
+++ b/lib/Support/CMakeLists.txt
@@ -23,6 +23,7 @@ add_llvm_library(LLVMSupport
Dwarf.cpp
ErrorHandling.cpp
FileUtilities.cpp
+ FileOutputBuffer.cpp
FoldingSet.cpp
FormattedStream.cpp
GraphWriter.cpp
diff --git a/lib/Support/DataExtractor.cpp b/lib/Support/DataExtractor.cpp
index dc21155..3d5cce0 100644
--- a/lib/Support/DataExtractor.cpp
+++ b/lib/Support/DataExtractor.cpp
@@ -139,7 +139,7 @@ uint64_t DataExtractor::getULEB128(uint32_t *offset_ptr) const {
while (isValidOffset(offset)) {
byte = Data[offset++];
- result |= (byte & 0x7f) << shift;
+ result |= uint64_t(byte & 0x7f) << shift;
shift += 7;
if ((byte & 0x80) == 0)
break;
@@ -160,7 +160,7 @@ int64_t DataExtractor::getSLEB128(uint32_t *offset_ptr) const {
while (isValidOffset(offset)) {
byte = Data[offset++];
- result |= (byte & 0x7f) << shift;
+ result |= uint64_t(byte & 0x7f) << shift;
shift += 7;
if ((byte & 0x80) == 0)
break;
@@ -168,7 +168,7 @@ int64_t DataExtractor::getSLEB128(uint32_t *offset_ptr) const {
// Sign bit of byte is 2nd high order bit (0x40)
if (shift < 64 && (byte & 0x40))
- result |= -(1 << shift);
+ result |= -(1ULL << shift);
*offset_ptr = offset;
return result;
diff --git a/lib/Support/Debug.cpp b/lib/Support/Debug.cpp
index 9fdb12e..c8e8900 100644
--- a/lib/Support/Debug.cpp
+++ b/lib/Support/Debug.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This file implements a handle way of adding debugging information to your
+// This file implements a handy way of adding debugging information to your
// code, without it being enabled all of the time, and without having to add
// command line options to enable it.
//
@@ -18,8 +18,8 @@
// can specify '-debug-only=foo' to enable JUST the debug information for the
// foo class.
//
-// When compiling in release mode, the -debug-* options and all code in DEBUG()
-// statements disappears, so it does not effect the runtime of the code.
+// When compiling without assertions, the -debug-* options and all code in
+// DEBUG() statements disappears, so it does not affect the runtime of the code.
//
//===----------------------------------------------------------------------===//
@@ -89,11 +89,11 @@ bool llvm::isCurrentDebugType(const char *DebugType) {
return CurrentDebugType.empty() || DebugType == CurrentDebugType;
}
-/// SetCurrentDebugType - Set the current debug type, as if the -debug-only=X
+/// setCurrentDebugType - Set the current debug type, as if the -debug-only=X
/// option were specified. Note that DebugFlag also needs to be set to true for
/// debug output to be produced.
///
-void llvm::SetCurrentDebugType(const char *Type) {
+void llvm::setCurrentDebugType(const char *Type) {
CurrentDebugType = Type;
}
diff --git a/lib/Support/FileOutputBuffer.cpp b/lib/Support/FileOutputBuffer.cpp
new file mode 100644
index 0000000..7dc9587
--- /dev/null
+++ b/lib/Support/FileOutputBuffer.cpp
@@ -0,0 +1,148 @@
+//===- FileOutputBuffer.cpp - File Output Buffer ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Utility for creating a in-memory buffer that will be written to a file.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/FileOutputBuffer.h"
+
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/system_error.h"
+
+
+namespace llvm {
+
+
+FileOutputBuffer::FileOutputBuffer(uint8_t *Start, uint8_t *End,
+ StringRef Path, StringRef TmpPath)
+ : BufferStart(Start), BufferEnd(End) {
+ FinalPath.assign(Path);
+ TempPath.assign(TmpPath);
+}
+
+
+FileOutputBuffer::~FileOutputBuffer() {
+ // If not already commited, delete buffer and remove temp file.
+ if ( BufferStart != NULL ) {
+ sys::fs::unmap_file_pages((void*)BufferStart, getBufferSize());
+ bool Existed;
+ sys::fs::remove(Twine(TempPath), Existed);
+ }
+}
+
+
+error_code FileOutputBuffer::create(StringRef FilePath,
+ size_t Size,
+ OwningPtr<FileOutputBuffer> &Result,
+ unsigned Flags) {
+ // If file already exists, it must be a regular file (to be mappable).
+ sys::fs::file_status Stat;
+ error_code EC = sys::fs::status(FilePath, Stat);
+ switch (Stat.type()) {
+ case sys::fs::file_type::file_not_found:
+ // If file does not exist, we'll create one.
+ break;
+ case sys::fs::file_type::regular_file: {
+ // If file is not currently writable, error out.
+ // FIXME: There is no sys::fs:: api for checking this.
+ // FIXME: In posix, you use the access() call to check this.
+ }
+ break;
+ default:
+ if (EC)
+ return EC;
+ else
+ return make_error_code(errc::operation_not_permitted);
+ }
+
+ // Delete target file.
+ bool Existed;
+ EC = sys::fs::remove(FilePath, Existed);
+ if (EC)
+ return EC;
+
+ // Create new file in same directory but with random name.
+ SmallString<128> TempFilePath;
+ int FD;
+ EC = sys::fs::unique_file(Twine(FilePath) + ".tmp%%%%%%%",
+ FD, TempFilePath, false, 0644);
+ if (EC)
+ return EC;
+
+ // The unique_file() interface leaks lower layers and returns a file
+ // descriptor. There is no way to directly close it, so use this hack
+ // to hand it off to raw_fd_ostream to close for us.
+ {
+ raw_fd_ostream Dummy(FD, /*shouldClose=*/true);
+ }
+
+ // Resize file to requested initial size
+ EC = sys::fs::resize_file(Twine(TempFilePath), Size);
+ if (EC)
+ return EC;
+
+ // If requested, make the output file executable.
+ if ( Flags & F_executable ) {
+ sys::fs::file_status Stat2;
+ EC = sys::fs::status(Twine(TempFilePath), Stat2);
+ if (EC)
+ return EC;
+
+ sys::fs::perms new_perms = Stat2.permissions();
+ if ( new_perms & sys::fs::owner_read )
+ new_perms |= sys::fs::owner_exe;
+ if ( new_perms & sys::fs::group_read )
+ new_perms |= sys::fs::group_exe;
+ if ( new_perms & sys::fs::others_read )
+ new_perms |= sys::fs::others_exe;
+ new_perms |= sys::fs::add_perms;
+ EC = sys::fs::permissions(Twine(TempFilePath), new_perms);
+ if (EC)
+ return EC;
+ }
+
+ // Memory map new file.
+ void *Base;
+ EC = sys::fs::map_file_pages(Twine(TempFilePath), 0, Size, true, Base);
+ if (EC)
+ return EC;
+
+ // Create FileOutputBuffer object to own mapped range.
+ uint8_t *Start = reinterpret_cast<uint8_t*>(Base);
+ Result.reset(new FileOutputBuffer(Start, Start+Size, FilePath, TempFilePath));
+
+ return error_code::success();
+}
+
+
+error_code FileOutputBuffer::commit(int64_t NewSmallerSize) {
+ // Unmap buffer, letting OS flush dirty pages to file on disk.
+ void *Start = reinterpret_cast<void*>(BufferStart);
+ error_code EC = sys::fs::unmap_file_pages(Start, getBufferSize());
+ if (EC)
+ return EC;
+
+ // If requested, resize file as part of commit.
+ if ( NewSmallerSize != -1 ) {
+ EC = sys::fs::resize_file(Twine(TempPath), NewSmallerSize);
+ if (EC)
+ return EC;
+ }
+
+ // Rename file to final name.
+ return sys::fs::rename(Twine(TempPath), Twine(FinalPath));
+}
+
+
+} // namespace
+
diff --git a/lib/Support/Mutex.cpp b/lib/Support/Mutex.cpp
index da5baab..4e4a026 100644
--- a/lib/Support/Mutex.cpp
+++ b/lib/Support/Mutex.cpp
@@ -59,7 +59,8 @@ MutexImpl::MutexImpl( bool recursive)
errorcode = pthread_mutexattr_settype(&attr, kind);
assert(errorcode == 0);
-#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__DragonFly__)
+#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && \
+ !defined(__DragonFly__) && !defined(__Bitrig__)
// Make it a process local mutex
errorcode = pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE);
assert(errorcode == 0);
diff --git a/lib/Support/Triple.cpp b/lib/Support/Triple.cpp
index 7b26ea9..cca549d 100644
--- a/lib/Support/Triple.cpp
+++ b/lib/Support/Triple.cpp
@@ -124,6 +124,7 @@ const char *Triple::getOSTypeName(OSType Kind) {
case RTEMS: return "rtems";
case NativeClient: return "nacl";
case CNK: return "cnk";
+ case Bitrig: return "bitrig";
}
llvm_unreachable("Invalid OSType");
@@ -293,6 +294,7 @@ static Triple::OSType parseOS(StringRef OSName) {
.StartsWith("rtems", Triple::RTEMS)
.StartsWith("nacl", Triple::NativeClient)
.StartsWith("cnk", Triple::CNK)
+ .StartsWith("bitrig", Triple::Bitrig)
.Default(Triple::UnknownOS);
}
diff --git a/lib/Support/Unix/Path.inc b/lib/Support/Unix/Path.inc
index b41390a..6bddbdf 100644
--- a/lib/Support/Unix/Path.inc
+++ b/lib/Support/Unix/Path.inc
@@ -260,7 +260,7 @@ Path::GetCurrentDirectory() {
return Path(pathname);
}
-#if defined(__FreeBSD__) || defined (__NetBSD__) || \
+#if defined(__FreeBSD__) || defined (__NetBSD__) || defined(__Bitrig__) || \
defined(__OpenBSD__) || defined(__minix) || defined(__FreeBSD_kernel__)
static int
test_dir(char buf[PATH_MAX], char ret[PATH_MAX],
@@ -329,7 +329,7 @@ Path Path::GetMainExecutable(const char *argv0, void *MainAddr) {
if (realpath(exe_path, link_path))
return Path(link_path);
}
-#elif defined(__FreeBSD__) || defined (__NetBSD__) || \
+#elif defined(__FreeBSD__) || defined (__NetBSD__) || defined(__Bitrig__) || \
defined(__OpenBSD__) || defined(__minix) || defined(__FreeBSD_kernel__)
char exe_path[PATH_MAX];
diff --git a/lib/Support/Unix/PathV2.inc b/lib/Support/Unix/PathV2.inc
index 93ccd1a..f59551e 100644
--- a/lib/Support/Unix/PathV2.inc
+++ b/lib/Support/Unix/PathV2.inc
@@ -50,6 +50,12 @@
#include <limits.h>
#endif
+// Both stdio.h and cstdio are included via different pathes and
+// stdcxx's cstdio doesn't include stdio.h, so it doesn't #undef the macros
+// either.
+#undef ferror
+#undef feof
+
// For GNU Hurd
#if defined(__GNU__) && !defined(PATH_MAX)
# define PATH_MAX 4096
@@ -461,6 +467,118 @@ rety_open_create:
return error_code::success();
}
+error_code mapped_file_region::init(int fd, uint64_t offset) {
+ AutoFD FD(fd);
+
+ // Figure out how large the file is.
+ struct stat FileInfo;
+ if (fstat(fd, &FileInfo) == -1)
+ return error_code(errno, system_category());
+ uint64_t FileSize = FileInfo.st_size;
+
+ if (Size == 0)
+ Size = FileSize;
+ else if (FileSize < Size) {
+ // We need to grow the file.
+ if (ftruncate(fd, Size) == -1)
+ return error_code(errno, system_category());
+ }
+
+ int flags = (Mode == readwrite) ? MAP_SHARED : MAP_PRIVATE;
+ int prot = (Mode == readonly) ? PROT_READ : (PROT_READ | PROT_WRITE);
+#ifdef MAP_FILE
+ flags |= MAP_FILE;
+#endif
+ Mapping = ::mmap(0, Size, prot, flags, fd, offset);
+ if (Mapping == MAP_FAILED)
+ return error_code(errno, system_category());
+ return error_code::success();
+}
+
+mapped_file_region::mapped_file_region(const Twine &path,
+ mapmode mode,
+ uint64_t length,
+ uint64_t offset,
+ error_code &ec)
+ : Mode(mode)
+ , Size(length)
+ , Mapping() {
+ // Make sure that the requested size fits within SIZE_T.
+ if (length > std::numeric_limits<size_t>::max()) {
+ ec = make_error_code(errc::invalid_argument);
+ return;
+ }
+
+ SmallString<128> path_storage;
+ StringRef name = path.toNullTerminatedStringRef(path_storage);
+ int oflags = (mode == readonly) ? O_RDONLY : O_RDWR;
+ int ofd = ::open(name.begin(), oflags);
+ if (ofd == -1) {
+ ec = error_code(errno, system_category());
+ return;
+ }
+
+ ec = init(ofd, offset);
+ if (ec)
+ Mapping = 0;
+}
+
+mapped_file_region::mapped_file_region(int fd,
+ mapmode mode,
+ uint64_t length,
+ uint64_t offset,
+ error_code &ec)
+ : Mode(mode)
+ , Size(length)
+ , Mapping() {
+ // Make sure that the requested size fits within SIZE_T.
+ if (length > std::numeric_limits<size_t>::max()) {
+ ec = make_error_code(errc::invalid_argument);
+ return;
+ }
+
+ ec = init(fd, offset);
+ if (ec)
+ Mapping = 0;
+}
+
+mapped_file_region::~mapped_file_region() {
+ if (Mapping)
+ ::munmap(Mapping, Size);
+}
+
+#if LLVM_USE_RVALUE_REFERENCES
+mapped_file_region::mapped_file_region(mapped_file_region &&other)
+ : Mode(other.Mode), Size(other.Size), Mapping(other.Mapping) {
+ other.Mapping = 0;
+}
+#endif
+
+mapped_file_region::mapmode mapped_file_region::flags() const {
+ assert(Mapping && "Mapping failed but used anyway!");
+ return Mode;
+}
+
+uint64_t mapped_file_region::size() const {
+ assert(Mapping && "Mapping failed but used anyway!");
+ return Size;
+}
+
+char *mapped_file_region::data() const {
+ assert(Mapping && "Mapping failed but used anyway!");
+ assert(Mode != readonly && "Cannot get non const data for readonly mapping!");
+ return reinterpret_cast<char*>(Mapping);
+}
+
+const char *mapped_file_region::const_data() const {
+ assert(Mapping && "Mapping failed but used anyway!");
+ return reinterpret_cast<const char*>(Mapping);
+}
+
+int mapped_file_region::alignment() {
+ return Process::GetPageSize();
+}
+
error_code detail::directory_iterator_construct(detail::DirIterState &it,
StringRef path){
SmallString<128> path_null(path);
diff --git a/lib/Support/Unix/Process.inc b/lib/Support/Unix/Process.inc
index 174112e..5204147 100644
--- a/lib/Support/Unix/Process.inc
+++ b/lib/Support/Unix/Process.inc
@@ -20,9 +20,10 @@
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
#endif
-// DragonFly BSD has deprecated <malloc.h> for <stdlib.h> instead,
-// Unix.h includes this for us already.
-#if defined(HAVE_MALLOC_H) && !defined(__DragonFly__)
+// DragonFlyBSD, OpenBSD, and Bitrig have deprecated <malloc.h> for
+// <stdlib.h> instead. Unix.h includes this for us already.
+#if defined(HAVE_MALLOC_H) && !defined(__DragonFly__) && \
+ !defined(__OpenBSD__) && !defined(__Bitrig__)
#include <malloc.h>
#endif
#ifdef HAVE_MALLOC_MALLOC_H
diff --git a/lib/Support/Windows/PathV2.inc b/lib/Support/Windows/PathV2.inc
index 66eeab0..696768b 100644
--- a/lib/Support/Windows/PathV2.inc
+++ b/lib/Support/Windows/PathV2.inc
@@ -22,6 +22,8 @@
#include <sys/stat.h>
#include <sys/types.h>
+#undef max
+
// MinGW doesn't define this.
#ifndef _ERRNO_T_DEFINED
#define _ERRNO_T_DEFINED
@@ -703,6 +705,203 @@ error_code get_magic(const Twine &path, uint32_t len,
return error_code::success();
}
+error_code mapped_file_region::init(int FD, uint64_t Offset) {
+ FileDescriptor = FD;
+ // Make sure that the requested size fits within SIZE_T.
+ if (Size > std::numeric_limits<SIZE_T>::max()) {
+ if (FileDescriptor)
+ _close(FileDescriptor);
+ else
+ ::CloseHandle(FileHandle);
+ return make_error_code(errc::invalid_argument);
+ }
+
+ DWORD flprotect;
+ switch (Mode) {
+ case readonly: flprotect = PAGE_READONLY; break;
+ case readwrite: flprotect = PAGE_READWRITE; break;
+ case priv: flprotect = PAGE_WRITECOPY; break;
+ default: llvm_unreachable("invalid mapping mode");
+ }
+
+ FileMappingHandle = ::CreateFileMapping(FileHandle,
+ 0,
+ flprotect,
+ Size >> 32,
+ Size & 0xffffffff,
+ 0);
+ if (FileMappingHandle == NULL) {
+ error_code ec = windows_error(GetLastError());
+ if (FileDescriptor)
+ _close(FileDescriptor);
+ else
+ ::CloseHandle(FileHandle);
+ return ec;
+ }
+
+ DWORD dwDesiredAccess;
+ switch (Mode) {
+ case readonly: dwDesiredAccess = FILE_MAP_READ; break;
+ case readwrite: dwDesiredAccess = FILE_MAP_WRITE; break;
+ case priv: dwDesiredAccess = FILE_MAP_COPY; break;
+ default: llvm_unreachable("invalid mapping mode");
+ }
+ Mapping = ::MapViewOfFile(FileMappingHandle,
+ dwDesiredAccess,
+ Offset >> 32,
+ Offset & 0xffffffff,
+ Size);
+ if (Mapping == NULL) {
+ error_code ec = windows_error(GetLastError());
+ ::CloseHandle(FileMappingHandle);
+ if (FileDescriptor)
+ _close(FileDescriptor);
+ else
+ ::CloseHandle(FileHandle);
+ return ec;
+ }
+
+ if (Size == 0) {
+ MEMORY_BASIC_INFORMATION mbi;
+ SIZE_T Result = VirtualQuery(Mapping, &mbi, sizeof(mbi));
+ if (Result == 0) {
+ error_code ec = windows_error(GetLastError());
+ ::UnmapViewOfFile(Mapping);
+ ::CloseHandle(FileMappingHandle);
+ if (FileDescriptor)
+ _close(FileDescriptor);
+ else
+ ::CloseHandle(FileHandle);
+ return ec;
+ }
+ Size = mbi.RegionSize;
+ }
+ return error_code::success();
+}
+
+mapped_file_region::mapped_file_region(const Twine &path,
+ mapmode mode,
+ uint64_t length,
+ uint64_t offset,
+ error_code &ec)
+ : Mode(mode)
+ , Size(length)
+ , Mapping()
+ , FileDescriptor()
+ , FileHandle(INVALID_HANDLE_VALUE)
+ , FileMappingHandle() {
+ SmallString<128> path_storage;
+ SmallVector<wchar_t, 128> path_utf16;
+
+ // Convert path to UTF-16.
+ if (ec = UTF8ToUTF16(path.toStringRef(path_storage), path_utf16))
+ return;
+
+ // Get file handle for creating a file mapping.
+ FileHandle = ::CreateFileW(c_str(path_utf16),
+ Mode == readonly ? GENERIC_READ
+ : GENERIC_READ | GENERIC_WRITE,
+ Mode == readonly ? FILE_SHARE_READ
+ : 0,
+ 0,
+ Mode == readonly ? OPEN_EXISTING
+ : OPEN_ALWAYS,
+ Mode == readonly ? FILE_ATTRIBUTE_READONLY
+ : FILE_ATTRIBUTE_NORMAL,
+ 0);
+ if (FileHandle == INVALID_HANDLE_VALUE) {
+ ec = windows_error(::GetLastError());
+ return;
+ }
+
+ FileDescriptor = 0;
+ ec = init(FileDescriptor, offset);
+ if (ec) {
+ Mapping = FileMappingHandle = 0;
+ FileHandle = INVALID_HANDLE_VALUE;
+ FileDescriptor = 0;
+ }
+}
+
+mapped_file_region::mapped_file_region(int fd,
+ mapmode mode,
+ uint64_t length,
+ uint64_t offset,
+ error_code &ec)
+ : Mode(mode)
+ , Size(length)
+ , Mapping()
+ , FileDescriptor(fd)
+ , FileHandle(INVALID_HANDLE_VALUE)
+ , FileMappingHandle() {
+ FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
+ if (FileHandle == INVALID_HANDLE_VALUE) {
+ _close(FileDescriptor);
+ FileDescriptor = 0;
+ ec = make_error_code(errc::bad_file_descriptor);
+ return;
+ }
+
+ ec = init(FileDescriptor, offset);
+ if (ec) {
+ Mapping = FileMappingHandle = 0;
+ FileHandle = INVALID_HANDLE_VALUE;
+ FileDescriptor = 0;
+ }
+}
+
+mapped_file_region::~mapped_file_region() {
+ if (Mapping)
+ ::UnmapViewOfFile(Mapping);
+ if (FileMappingHandle)
+ ::CloseHandle(FileMappingHandle);
+ if (FileDescriptor)
+ _close(FileDescriptor);
+ else if (FileHandle != INVALID_HANDLE_VALUE)
+ ::CloseHandle(FileHandle);
+}
+
+#if LLVM_USE_RVALUE_REFERENCES
+mapped_file_region::mapped_file_region(mapped_file_region &&other)
+ : Mode(other.Mode)
+ , Size(other.Size)
+ , Mapping(other.Mapping)
+ , FileDescriptor(other.FileDescriptor)
+ , FileHandle(other.FileHandle)
+ , FileMappingHandle(other.FileMappingHandle) {
+ other.Mapping = other.FileMappingHandle = 0;
+ other.FileHandle = INVALID_HANDLE_VALUE;
+ other.FileDescriptor = 0;
+}
+#endif
+
+mapped_file_region::mapmode mapped_file_region::flags() const {
+ assert(Mapping && "Mapping failed but used anyway!");
+ return Mode;
+}
+
+uint64_t mapped_file_region::size() const {
+ assert(Mapping && "Mapping failed but used anyway!");
+ return Size;
+}
+
+char *mapped_file_region::data() const {
+ assert(Mode != readonly && "Cannot get non const data for readonly mapping!");
+ assert(Mapping && "Mapping failed but used anyway!");
+ return reinterpret_cast<char*>(Mapping);
+}
+
+const char *mapped_file_region::const_data() const {
+ assert(Mapping && "Mapping failed but used anyway!");
+ return reinterpret_cast<const char*>(Mapping);
+}
+
+int mapped_file_region::alignment() {
+ SYSTEM_INFO SysInfo;
+ ::GetSystemInfo(&SysInfo);
+ return SysInfo.dwAllocationGranularity;
+}
+
error_code detail::directory_iterator_construct(detail::DirIterState &it,
StringRef path){
SmallVector<wchar_t, 128> path_utf16;