summaryrefslogtreecommitdiff
path: root/lib/Support
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Support')
-rw-r--r--lib/Support/Alarm.cpp33
-rw-r--r--lib/Support/Allocator.cpp4
-rw-r--r--lib/Support/Atomic.cpp112
-rw-r--r--lib/Support/CMakeLists.txt50
-rw-r--r--lib/Support/CommandLine.cpp4
-rw-r--r--lib/Support/CrashRecoveryContext.cpp4
-rw-r--r--lib/Support/Debug.cpp2
-rw-r--r--lib/Support/Disassembler.cpp75
-rw-r--r--lib/Support/DynamicLibrary.cpp177
-rw-r--r--lib/Support/Errno.cpp74
-rw-r--r--lib/Support/ErrorHandling.cpp4
-rw-r--r--lib/Support/FileUtilities.cpp2
-rw-r--r--lib/Support/FoldingSet.cpp2
-rw-r--r--lib/Support/GraphWriter.cpp4
-rw-r--r--lib/Support/Host.cpp307
-rw-r--r--lib/Support/IncludeFile.cpp20
-rw-r--r--lib/Support/Makefile5
-rw-r--r--lib/Support/ManagedStatic.cpp2
-rw-r--r--lib/Support/Memory.cpp74
-rw-r--r--lib/Support/MemoryBuffer.cpp18
-rw-r--r--lib/Support/Mutex.cpp156
-rw-r--r--lib/Support/Path.cpp296
-rw-r--r--lib/Support/PluginLoader.cpp4
-rw-r--r--lib/Support/PrettyStackTrace.cpp4
-rw-r--r--lib/Support/Process.cpp33
-rw-r--r--lib/Support/Program.cpp56
-rw-r--r--lib/Support/README.txt.system43
-rw-r--r--lib/Support/RWMutex.cpp157
-rw-r--r--lib/Support/SearchForAddressOfSpecialSymbol.cpp68
-rw-r--r--lib/Support/Signals.cpp34
-rw-r--r--lib/Support/Statistic.cpp2
-rw-r--r--lib/Support/SystemUtils.cpp4
-rw-r--r--lib/Support/TargetRegistry.cpp2
-rw-r--r--lib/Support/ThreadLocal.cpp84
-rw-r--r--lib/Support/Threading.cpp116
-rw-r--r--lib/Support/TimeValue.cpp57
-rw-r--r--lib/Support/Timer.cpp4
-rw-r--r--lib/Support/ToolOutputFile.cpp2
-rw-r--r--lib/Support/Unix/Alarm.inc72
-rw-r--r--lib/Support/Unix/Host.inc96
-rw-r--r--lib/Support/Unix/Memory.inc151
-rw-r--r--lib/Support/Unix/Mutex.inc43
-rw-r--r--lib/Support/Unix/Path.inc896
-rw-r--r--lib/Support/Unix/Process.inc295
-rw-r--r--lib/Support/Unix/Program.inc422
-rw-r--r--lib/Support/Unix/README.txt16
-rw-r--r--lib/Support/Unix/RWMutex.inc43
-rw-r--r--lib/Support/Unix/Signals.inc303
-rw-r--r--lib/Support/Unix/ThreadLocal.inc26
-rw-r--r--lib/Support/Unix/TimeValue.inc56
-rw-r--r--lib/Support/Unix/Unix.h87
-rw-r--r--lib/Support/Unix/system_error.inc34
-rw-r--r--lib/Support/Valgrind.cpp54
-rw-r--r--lib/Support/Windows/Alarm.inc43
-rw-r--r--lib/Support/Windows/DynamicLibrary.inc199
-rw-r--r--lib/Support/Windows/Host.inc23
-rw-r--r--lib/Support/Windows/Memory.inc73
-rw-r--r--lib/Support/Windows/Mutex.inc58
-rw-r--r--lib/Support/Windows/Path.inc918
-rw-r--r--lib/Support/Windows/Process.inc222
-rw-r--r--lib/Support/Windows/Program.inc412
-rw-r--r--lib/Support/Windows/RWMutex.inc58
-rw-r--r--lib/Support/Windows/Signals.inc325
-rw-r--r--lib/Support/Windows/ThreadLocal.inc54
-rw-r--r--lib/Support/Windows/TimeValue.inc51
-rw-r--r--lib/Support/Windows/Windows.h60
-rw-r--r--lib/Support/Windows/system_error.inc140
-rw-r--r--lib/Support/raw_ostream.cpp4
-rw-r--r--lib/Support/system_error.cpp121
69 files changed, 7414 insertions, 36 deletions
diff --git a/lib/Support/Alarm.cpp b/lib/Support/Alarm.cpp
new file mode 100644
index 0000000000..58ad609cd2
--- /dev/null
+++ b/lib/Support/Alarm.cpp
@@ -0,0 +1,33 @@
+//===- Alarm.cpp - Alarm Generation Support ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Alarm functionality
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Alarm.h"
+#include "llvm/Config/config.h"
+
+namespace llvm {
+using namespace sys;
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only TRULY operating system
+//=== independent code.
+//===----------------------------------------------------------------------===//
+
+}
+
+// Include the platform-specific parts of this class.
+#ifdef LLVM_ON_UNIX
+#include "Unix/Alarm.inc"
+#endif
+#ifdef LLVM_ON_WIN32
+#include "Windows/Alarm.inc"
+#endif
diff --git a/lib/Support/Allocator.cpp b/lib/Support/Allocator.cpp
index 02b45d8af9..5e27df6628 100644
--- a/lib/Support/Allocator.cpp
+++ b/lib/Support/Allocator.cpp
@@ -12,10 +12,10 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/Allocator.h"
-#include "llvm/System/DataTypes.h"
+#include "llvm/Support/DataTypes.h"
#include "llvm/Support/Recycler.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/System/Memory.h"
+#include "llvm/Support/Memory.h"
#include <cstring>
namespace llvm {
diff --git a/lib/Support/Atomic.cpp b/lib/Support/Atomic.cpp
new file mode 100644
index 0000000000..c7b4bff279
--- /dev/null
+++ b/lib/Support/Atomic.cpp
@@ -0,0 +1,112 @@
+//===-- Atomic.cpp - Atomic Operations --------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header file implements atomic operations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Atomic.h"
+#include "llvm/Config/config.h"
+
+using namespace llvm;
+
+#if defined(_MSC_VER)
+#include <windows.h>
+#undef MemoryFence
+#endif
+
+void sys::MemoryFence() {
+#if LLVM_MULTITHREADED==0
+ return;
+#else
+# if defined(__GNUC__)
+ __sync_synchronize();
+# elif defined(_MSC_VER)
+ MemoryBarrier();
+# else
+# error No memory fence implementation for your platform!
+# endif
+#endif
+}
+
+sys::cas_flag sys::CompareAndSwap(volatile sys::cas_flag* ptr,
+ sys::cas_flag new_value,
+ sys::cas_flag old_value) {
+#if LLVM_MULTITHREADED==0
+ sys::cas_flag result = *ptr;
+ if (result == old_value)
+ *ptr = new_value;
+ return result;
+#elif defined(__GNUC__)
+ return __sync_val_compare_and_swap(ptr, old_value, new_value);
+#elif defined(_MSC_VER)
+ return InterlockedCompareExchange(ptr, new_value, old_value);
+#else
+# error No compare-and-swap implementation for your platform!
+#endif
+}
+
+sys::cas_flag sys::AtomicIncrement(volatile sys::cas_flag* ptr) {
+#if LLVM_MULTITHREADED==0
+ ++(*ptr);
+ return *ptr;
+#elif defined(__GNUC__)
+ return __sync_add_and_fetch(ptr, 1);
+#elif defined(_MSC_VER)
+ return InterlockedIncrement(ptr);
+#else
+# error No atomic increment implementation for your platform!
+#endif
+}
+
+sys::cas_flag sys::AtomicDecrement(volatile sys::cas_flag* ptr) {
+#if LLVM_MULTITHREADED==0
+ --(*ptr);
+ return *ptr;
+#elif defined(__GNUC__)
+ return __sync_sub_and_fetch(ptr, 1);
+#elif defined(_MSC_VER)
+ return InterlockedDecrement(ptr);
+#else
+# error No atomic decrement implementation for your platform!
+#endif
+}
+
+sys::cas_flag sys::AtomicAdd(volatile sys::cas_flag* ptr, sys::cas_flag val) {
+#if LLVM_MULTITHREADED==0
+ *ptr += val;
+ return *ptr;
+#elif defined(__GNUC__)
+ return __sync_add_and_fetch(ptr, val);
+#elif defined(_MSC_VER)
+ return InterlockedExchangeAdd(ptr, val) + val;
+#else
+# error No atomic add implementation for your platform!
+#endif
+}
+
+sys::cas_flag sys::AtomicMul(volatile sys::cas_flag* ptr, sys::cas_flag val) {
+ sys::cas_flag original, result;
+ do {
+ original = *ptr;
+ result = original * val;
+ } while (sys::CompareAndSwap(ptr, result, original) != original);
+
+ return result;
+}
+
+sys::cas_flag sys::AtomicDiv(volatile sys::cas_flag* ptr, sys::cas_flag val) {
+ sys::cas_flag original, result;
+ do {
+ original = *ptr;
+ result = original / val;
+ } while (sys::CompareAndSwap(ptr, result, original) != original);
+
+ return result;
+}
diff --git a/lib/Support/CMakeLists.txt b/lib/Support/CMakeLists.txt
index 8a6ed6fa6d..105a507abd 100644
--- a/lib/Support/CMakeLists.txt
+++ b/lib/Support/CMakeLists.txt
@@ -1,5 +1,8 @@
## FIXME: This only requires RTTI because tblgen uses it. Fix that.
set(LLVM_REQUIRES_RTTI 1)
+if( MINGW )
+ set(LLVM_REQUIRES_EH 1)
+endif()
add_llvm_library(LLVMSupport
APFloat.cpp
@@ -49,4 +52,51 @@ add_llvm_library(LLVMSupport
regexec.c
regfree.c
regstrlcpy.c
+
+# System
+ Alarm.cpp
+ Atomic.cpp
+ Disassembler.cpp
+ DynamicLibrary.cpp
+ Errno.cpp
+ Host.cpp
+ IncludeFile.cpp
+ Memory.cpp
+ Mutex.cpp
+ Path.cpp
+ Process.cpp
+ Program.cpp
+ RWMutex.cpp
+ SearchForAddressOfSpecialSymbol.cpp
+ Signals.cpp
+ system_error.cpp
+ ThreadLocal.cpp
+ Threading.cpp
+ TimeValue.cpp
+ Valgrind.cpp
+ Unix/Alarm.inc
+ Unix/Host.inc
+ Unix/Memory.inc
+ Unix/Mutex.inc
+ Unix/Path.inc
+ Unix/Process.inc
+ Unix/Program.inc
+ Unix/RWMutex.inc
+ Unix/Signals.inc
+ Unix/system_error.inc
+ Unix/ThreadLocal.inc
+ Unix/TimeValue.inc
+ Windows/Alarm.inc
+ Windows/DynamicLibrary.inc
+ Windows/Host.inc
+ Windows/Memory.inc
+ Windows/Mutex.inc
+ Windows/Path.inc
+ Windows/Process.inc
+ Windows/Program.inc
+ Windows/RWMutex.inc
+ Windows/Signals.inc
+ Windows/system_error.inc
+ Windows/ThreadLocal.inc
+ Windows/TimeValue.inc
)
diff --git a/lib/Support/CommandLine.cpp b/lib/Support/CommandLine.cpp
index 38ef084961..a99e46dbd1 100644
--- a/lib/Support/CommandLine.cpp
+++ b/lib/Support/CommandLine.cpp
@@ -23,8 +23,8 @@
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetRegistry.h"
-#include "llvm/System/Host.h"
-#include "llvm/System/Path.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/Path.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
diff --git a/lib/Support/CrashRecoveryContext.cpp b/lib/Support/CrashRecoveryContext.cpp
index f24d6bdad8..bf8ca3f844 100644
--- a/lib/Support/CrashRecoveryContext.cpp
+++ b/lib/Support/CrashRecoveryContext.cpp
@@ -10,8 +10,8 @@
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Config/config.h"
-#include "llvm/System/Mutex.h"
-#include "llvm/System/ThreadLocal.h"
+#include "llvm/Support/Mutex.h"
+#include "llvm/Support/ThreadLocal.h"
#include <setjmp.h>
#include <cstdio>
using namespace llvm;
diff --git a/lib/Support/Debug.cpp b/lib/Support/Debug.cpp
index 7f48f8aae7..9fdb12ecfd 100644
--- a/lib/Support/Debug.cpp
+++ b/lib/Support/Debug.cpp
@@ -26,7 +26,7 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/circular_raw_ostream.h"
-#include "llvm/System/Signals.h"
+#include "llvm/Support/Signals.h"
using namespace llvm;
diff --git a/lib/Support/Disassembler.cpp b/lib/Support/Disassembler.cpp
new file mode 100644
index 0000000000..6362aff43a
--- /dev/null
+++ b/lib/Support/Disassembler.cpp
@@ -0,0 +1,75 @@
+//===- lib/System/Disassembler.cpp ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the necessary glue to call external disassembler
+// libraries.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Config/config.h"
+#include "llvm/Support/Disassembler.h"
+
+#include <cassert>
+#include <iomanip>
+#include <string>
+#include <sstream>
+
+#if USE_UDIS86
+#include <udis86.h>
+#endif
+
+using namespace llvm;
+
+bool llvm::sys::hasDisassembler()
+{
+#if defined (__i386__) || defined (__amd64__) || defined (__x86_64__)
+ // We have option to enable udis86 library.
+# if USE_UDIS86
+ return true;
+#else
+ return false;
+#endif
+#else
+ return false;
+#endif
+}
+
+std::string llvm::sys::disassembleBuffer(uint8_t* start, size_t length,
+ uint64_t pc) {
+ std::stringstream res;
+
+#if (defined (__i386__) || defined (__amd64__) || defined (__x86_64__)) \
+ && USE_UDIS86
+ unsigned bits;
+# if defined(__i386__)
+ bits = 32;
+# else
+ bits = 64;
+# endif
+
+ ud_t ud_obj;
+
+ ud_init(&ud_obj);
+ ud_set_input_buffer(&ud_obj, start, length);
+ ud_set_mode(&ud_obj, bits);
+ ud_set_pc(&ud_obj, pc);
+ ud_set_syntax(&ud_obj, UD_SYN_ATT);
+
+ res << std::setbase(16)
+ << std::setw(bits/4);
+
+ while (ud_disassemble(&ud_obj)) {
+ res << ud_insn_off(&ud_obj) << ":\t" << ud_insn_asm(&ud_obj) << "\n";
+ }
+#else
+ res << "No disassembler available. See configure help for options.\n";
+#endif
+
+ return res.str();
+}
diff --git a/lib/Support/DynamicLibrary.cpp b/lib/Support/DynamicLibrary.cpp
new file mode 100644
index 0000000000..cd9927a193
--- /dev/null
+++ b/lib/Support/DynamicLibrary.cpp
@@ -0,0 +1,177 @@
+//===-- DynamicLibrary.cpp - Runtime link/load libraries --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header file implements the operating system DynamicLibrary concept.
+//
+// FIXME: This file leaks the ExplicitSymbols and OpenedHandles vector, and is
+// not thread safe!
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/DynamicLibrary.h"
+#include "llvm/Support/Mutex.h"
+#include "llvm/Config/config.h"
+#include <cstdio>
+#include <cstring>
+#include <map>
+#include <vector>
+
+// Collection of symbol name/value pairs to be searched prior to any libraries.
+static std::map<std::string, void*> *ExplicitSymbols = 0;
+
+namespace {
+
+struct ExplicitSymbolsDeleter {
+ ~ExplicitSymbolsDeleter() {
+ if (ExplicitSymbols)
+ delete ExplicitSymbols;
+ }
+};
+
+}
+
+static ExplicitSymbolsDeleter Dummy;
+
+void llvm::sys::DynamicLibrary::AddSymbol(const char* symbolName,
+ void *symbolValue) {
+ if (ExplicitSymbols == 0)
+ ExplicitSymbols = new std::map<std::string, void*>();
+ (*ExplicitSymbols)[symbolName] = symbolValue;
+}
+
+#ifdef LLVM_ON_WIN32
+
+#include "Windows/DynamicLibrary.inc"
+
+#else
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+using namespace llvm;
+using namespace llvm::sys;
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only TRULY operating system
+//=== independent code.
+//===----------------------------------------------------------------------===//
+
+static SmartMutex<true>* HandlesMutex;
+static std::vector<void *> *OpenedHandles = 0;
+
+static bool InitializeMutex() {
+ HandlesMutex = new SmartMutex<true>;
+ return HandlesMutex != 0;
+}
+
+static bool EnsureMutexInitialized() {
+ static bool result = InitializeMutex();
+ return result;
+}
+
+
+bool DynamicLibrary::LoadLibraryPermanently(const char *Filename,
+ std::string *ErrMsg) {
+ void *H = dlopen(Filename, RTLD_LAZY|RTLD_GLOBAL);
+ if (H == 0) {
+ if (ErrMsg) *ErrMsg = dlerror();
+ return true;
+ }
+#ifdef __CYGWIN__
+ // Cygwin searches symbols only in the main
+ // with the handle of dlopen(NULL, RTLD_GLOBAL).
+ if (Filename == NULL)
+ H = RTLD_DEFAULT;
+#endif
+ EnsureMutexInitialized();
+ SmartScopedLock<true> Lock(*HandlesMutex);
+ if (OpenedHandles == 0)
+ OpenedHandles = new std::vector<void *>();
+ OpenedHandles->push_back(H);
+ return false;
+}
+#else
+
+using namespace llvm;
+using namespace llvm::sys;
+
+bool DynamicLibrary::LoadLibraryPermanently(const char *Filename,
+ std::string *ErrMsg) {
+ if (ErrMsg) *ErrMsg = "dlopen() not supported on this platform";
+ return true;
+}
+#endif
+
+namespace llvm {
+void *SearchForAddressOfSpecialSymbol(const char* symbolName);
+}
+
+void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) {
+ // First check symbols added via AddSymbol().
+ if (ExplicitSymbols) {
+ std::map<std::string, void *>::iterator I =
+ ExplicitSymbols->find(symbolName);
+ std::map<std::string, void *>::iterator E = ExplicitSymbols->end();
+
+ if (I != E)
+ return I->second;
+ }
+
+#if HAVE_DLFCN_H
+ // Now search the libraries.
+ EnsureMutexInitialized();
+ SmartScopedLock<true> Lock(*HandlesMutex);
+ if (OpenedHandles) {
+ for (std::vector<void *>::iterator I = OpenedHandles->begin(),
+ E = OpenedHandles->end(); I != E; ++I) {
+ //lt_ptr ptr = lt_dlsym(*I, symbolName);
+ void *ptr = dlsym(*I, symbolName);
+ if (ptr) {
+ return ptr;
+ }
+ }
+ }
+#endif
+
+ if (void *Result = llvm::SearchForAddressOfSpecialSymbol(symbolName))
+ return Result;
+
+// This macro returns the address of a well-known, explicit symbol
+#define EXPLICIT_SYMBOL(SYM) \
+ if (!strcmp(symbolName, #SYM)) return &SYM
+
+// On linux we have a weird situation. The stderr/out/in symbols are both
+// macros and global variables because of standards requirements. So, we
+// boldly use the EXPLICIT_SYMBOL macro without checking for a #define first.
+#if defined(__linux__)
+ {
+ EXPLICIT_SYMBOL(stderr);
+ EXPLICIT_SYMBOL(stdout);
+ EXPLICIT_SYMBOL(stdin);
+ }
+#else
+ // For everything else, we want to check to make sure the symbol isn't defined
+ // as a macro before using EXPLICIT_SYMBOL.
+ {
+#ifndef stdin
+ EXPLICIT_SYMBOL(stdin);
+#endif
+#ifndef stdout
+ EXPLICIT_SYMBOL(stdout);
+#endif
+#ifndef stderr
+ EXPLICIT_SYMBOL(stderr);
+#endif
+ }
+#endif
+#undef EXPLICIT_SYMBOL
+
+ return 0;
+}
+
+#endif // LLVM_ON_WIN32
diff --git a/lib/Support/Errno.cpp b/lib/Support/Errno.cpp
new file mode 100644
index 0000000000..312d91e063
--- /dev/null
+++ b/lib/Support/Errno.cpp
@@ -0,0 +1,74 @@
+//===- Errno.cpp - errno support --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the errno wrappers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Errno.h"
+#include "llvm/Config/config.h" // Get autoconf configuration settings
+
+#if HAVE_STRING_H
+#include <string.h>
+
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only TRULY operating system
+//=== independent code.
+//===----------------------------------------------------------------------===//
+
+namespace llvm {
+namespace sys {
+
+#if HAVE_ERRNO_H
+std::string StrError() {
+ return StrError(errno);
+}
+#endif // HAVE_ERRNO_H
+
+std::string StrError(int errnum) {
+ const int MaxErrStrLen = 2000;
+ char buffer[MaxErrStrLen];
+ buffer[0] = '\0';
+ char* str = buffer;
+#ifdef HAVE_STRERROR_R
+ // strerror_r is thread-safe.
+ if (errnum)
+# if defined(__GLIBC__) && defined(_GNU_SOURCE)
+ // glibc defines its own incompatible version of strerror_r
+ // which may not use the buffer supplied.
+ str = strerror_r(errnum,buffer,MaxErrStrLen-1);
+# else
+ strerror_r(errnum,buffer,MaxErrStrLen-1);
+# endif
+#elif defined(HAVE_STRERROR_S) // Windows.
+ if (errnum)
+ strerror_s(buffer, errnum);
+#elif defined(HAVE_STRERROR)
+ // Copy the thread un-safe result of strerror into
+ // the buffer as fast as possible to minimize impact
+ // of collision of strerror in multiple threads.
+ if (errnum)
+ strncpy(buffer,strerror(errnum),MaxErrStrLen-1);
+ buffer[MaxErrStrLen-1] = '\0';
+#else
+ // Strange that this system doesn't even have strerror
+ // but, oh well, just use a generic message
+ sprintf(buffer, "Error #%d", errnum);
+#endif
+ return str;
+}
+
+} // namespace sys
+} // namespace llvm
+
+#endif // HAVE_STRING_H
diff --git a/lib/Support/ErrorHandling.cpp b/lib/Support/ErrorHandling.cpp
index 66b2c83fe7..3579546d75 100644
--- a/lib/Support/ErrorHandling.cpp
+++ b/lib/Support/ErrorHandling.cpp
@@ -16,8 +16,8 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/System/Signals.h"
-#include "llvm/System/Threading.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/Threading.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Config/config.h"
#include <cassert>
diff --git a/lib/Support/FileUtilities.cpp b/lib/Support/FileUtilities.cpp
index 1bde2fe8a8..72200850c5 100644
--- a/lib/Support/FileUtilities.cpp
+++ b/lib/Support/FileUtilities.cpp
@@ -15,7 +15,7 @@
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/System/Path.h"
+#include "llvm/Support/Path.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallString.h"
#include <cstdlib>
diff --git a/lib/Support/FoldingSet.cpp b/lib/Support/FoldingSet.cpp
index 11a1de4a95..a4f80a90d6 100644
--- a/lib/Support/FoldingSet.cpp
+++ b/lib/Support/FoldingSet.cpp
@@ -18,7 +18,7 @@
#include "llvm/Support/Allocator.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
-#include "llvm/System/Host.h"
+#include "llvm/Support/Host.h"
#include <cassert>
#include <cstring>
using namespace llvm;
diff --git a/lib/Support/GraphWriter.cpp b/lib/Support/GraphWriter.cpp
index 79e978afa0..0dba28a253 100644
--- a/lib/Support/GraphWriter.cpp
+++ b/lib/Support/GraphWriter.cpp
@@ -12,8 +12,8 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/GraphWriter.h"
-#include "llvm/System/Path.h"
-#include "llvm/System/Program.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Program.h"
#include "llvm/Config/config.h"
using namespace llvm;
diff --git a/lib/Support/Host.cpp b/lib/Support/Host.cpp
new file mode 100644
index 0000000000..4dacf9691d
--- /dev/null
+++ b/lib/Support/Host.cpp
@@ -0,0 +1,307 @@
+//===-- Host.cpp - Implement OS Host Concept --------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header file implements the operating system Host concept.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Host.h"
+#include "llvm/Config/config.h"
+#include <string.h>
+
+// Include the platform-specific parts of this class.
+#ifdef LLVM_ON_UNIX
+#include "Unix/Host.inc"
+#endif
+#ifdef LLVM_ON_WIN32
+#include "Windows/Host.inc"
+#endif
+#ifdef _MSC_VER
+#include <intrin.h>
+#endif
+
+//===----------------------------------------------------------------------===//
+//
+// Implementations of the CPU detection routines
+//
+//===----------------------------------------------------------------------===//
+
+using namespace llvm;
+
+#if defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)\
+ || defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64)
+
+/// GetX86CpuIDAndInfo - Execute the specified cpuid and return the 4 values in the
+/// specified arguments. If we can't run cpuid on the host, return true.
+static bool GetX86CpuIDAndInfo(unsigned value, unsigned *rEAX,
+ unsigned *rEBX, unsigned *rECX, unsigned *rEDX) {
+#if defined(__x86_64__) || defined(_M_AMD64) || defined (_M_X64)
+ #if defined(__GNUC__)
+ // gcc doesn't know cpuid would clobber ebx/rbx. Preseve it manually.
+ asm ("movq\t%%rbx, %%rsi\n\t"
+ "cpuid\n\t"
+ "xchgq\t%%rbx, %%rsi\n\t"
+ : "=a" (*rEAX),
+ "=S" (*rEBX),
+ "=c" (*rECX),
+ "=d" (*rEDX)
+ : "a" (value));
+ return false;
+ #elif defined(_MSC_VER)
+ int registers[4];
+ __cpuid(registers, value);
+ *rEAX = registers[0];
+ *rEBX = registers[1];
+ *rECX = registers[2];
+ *rEDX = registers[3];
+ return false;
+ #endif
+#elif defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)
+ #if defined(__GNUC__)
+ asm ("movl\t%%ebx, %%esi\n\t"
+ "cpuid\n\t"
+ "xchgl\t%%ebx, %%esi\n\t"
+ : "=a" (*rEAX),
+ "=S" (*rEBX),
+ "=c" (*rECX),
+ "=d" (*rEDX)
+ : "a" (value));
+ return false;
+ #elif defined(_MSC_VER)
+ __asm {
+ mov eax,value
+ cpuid
+ mov esi,rEAX
+ mov dword ptr [esi],eax
+ mov esi,rEBX
+ mov dword ptr [esi],ebx
+ mov esi,rECX
+ mov dword ptr [esi],ecx
+ mov esi,rEDX
+ mov dword ptr [esi],edx
+ }
+ return false;
+ #endif
+#endif
+ return true;
+}
+
+static void DetectX86FamilyModel(unsigned EAX, unsigned &Family,
+ unsigned &Model) {
+ Family = (EAX >> 8) & 0xf; // Bits 8 - 11
+ Model = (EAX >> 4) & 0xf; // Bits 4 - 7
+ if (Family == 6 || Family == 0xf) {
+ if (Family == 0xf)
+ // Examine extended family ID if family ID is F.
+ Family += (EAX >> 20) & 0xff; // Bits 20 - 27
+ // Examine extended model ID if family ID is 6 or F.
+ Model += ((EAX >> 16) & 0xf) << 4; // Bits 16 - 19
+ }
+}
+
+std::string sys::getHostCPUName() {
+ unsigned EAX = 0, EBX = 0, ECX = 0, EDX = 0;
+ if (GetX86CpuIDAndInfo(0x1, &EAX, &EBX, &ECX, &EDX))
+ return "generic";
+ unsigned Family = 0;
+ unsigned Model = 0;
+ DetectX86FamilyModel(EAX, Family, Model);
+
+ bool HasSSE3 = (ECX & 0x1);
+ GetX86CpuIDAndInfo(0x80000001, &EAX, &EBX, &ECX, &EDX);
+ bool Em64T = (EDX >> 29) & 0x1;
+
+ union {
+ unsigned u[3];
+ char c[12];
+ } text;
+
+ GetX86CpuIDAndInfo(0, &EAX, text.u+0, text.u+2, text.u+1);
+ if (memcmp(text.c, "GenuineIntel", 12) == 0) {
+ switch (Family) {
+ case 3:
+ return "i386";
+ case 4:
+ switch (Model) {
+ case 0: // Intel486 DX processors
+ case 1: // Intel486 DX processors
+ case 2: // Intel486 SX processors
+ case 3: // Intel487 processors, IntelDX2 OverDrive processors,
+ // IntelDX2 processors
+ case 4: // Intel486 SL processor
+ case 5: // IntelSX2 processors
+ case 7: // Write-Back Enhanced IntelDX2 processors
+ case 8: // IntelDX4 OverDrive processors, IntelDX4 processors
+ default: return "i486";
+ }
+ case 5:
+ switch (Model) {
+ case 1: // Pentium OverDrive processor for Pentium processor (60, 66),
+ // Pentium processors (60, 66)
+ case 2: // Pentium OverDrive processor for Pentium processor (75, 90,
+ // 100, 120, 133), Pentium processors (75, 90, 100, 120, 133,
+ // 150, 166, 200)
+ case 3: // Pentium OverDrive processors for Intel486 processor-based
+ // systems
+ return "pentium";
+
+ case 4: // Pentium OverDrive processor with MMX technology for Pentium
+ // processor (75, 90, 100, 120, 133), Pentium processor with
+ // MMX technology (166, 200)
+ return "pentium-mmx";
+
+ default: return "pentium";
+ }
+ case 6:
+ switch (Model) {
+ case 1: // Pentium Pro processor
+ return "pentiumpro";
+
+ case 3: // Intel Pentium II OverDrive processor, Pentium II processor,
+ // model 03
+ case 5: // Pentium II processor, model 05, Pentium II Xeon processor,
+ // model 05, and Intel Celeron processor, model 05
+ case 6: // Celeron processor, model 06
+ return "pentium2";
+
+ case 7: // Pentium III processor, model 07, and Pentium III Xeon
+ // processor, model 07
+ case 8: // Pentium III processor, model 08, Pentium III Xeon processor,
+ // model 08, and Celeron processor, model 08
+ case 10: // Pentium III Xeon processor, model 0Ah
+ case 11: // Pentium III processor, model 0Bh
+ return "pentium3";
+
+ case 9: // Intel Pentium M processor, Intel Celeron M processor model 09.
+ case 13: // Intel Pentium M processor, Intel Celeron M processor, model
+ // 0Dh. All processors are manufactured using the 90 nm process.
+ return "pentium-m";
+
+ case 14: // Intel Core Duo processor, Intel Core Solo processor, model
+ // 0Eh. All processors are manufactured using the 65 nm process.
+ return "yonah";
+
+ case 15: // Intel Core 2 Duo processor, Intel Core 2 Duo mobile
+ // processor, Intel Core 2 Quad processor, Intel Core 2 Quad
+ // mobile processor, Intel Core 2 Extreme processor, Intel
+ // Pentium Dual-Core processor, Intel Xeon processor, model
+ // 0Fh. All processors are manufactured using the 65 nm process.
+ case 22: // Intel Celeron processor model 16h. All processors are
+ // manufactured using the 65 nm process
+ return "core2";
+
+ case 21: // Intel EP80579 Integrated Processor and Intel EP80579
+ // Integrated Processor with Intel QuickAssist Technology
+ return "i686"; // FIXME: ???
+
+ case 23: // Intel Core 2 Extreme processor, Intel Xeon processor, model
+ // 17h. All processors are manufactured using the 45 nm process.
+ //
+ // 45nm: Penryn , Wolfdale, Yorkfield (XE)
+ return "penryn";
+
+ case 26: // Intel Core i7 processor and Intel Xeon processor. All
+ // processors are manufactured using the 45 nm process.
+ case 29: // Intel Xeon processor MP. All processors are manufactured using
+ // the 45 nm process.
+ case 30: // Intel(R) Core(TM) i7 CPU 870 @ 2.93GHz.
+ // As found in a Summer 2010 model iMac.
+ case 37: // Intel Core i7, laptop version.
+ return "corei7";
+
+ case 28: // Intel Atom processor. All processors are manufactured using
+ // the 45 nm process
+ return "atom";
+
+ default: return "i686";
+ }
+ case 15: {
+ switch (Model) {
+ case 0: // Pentium 4 processor, Intel Xeon processor. All processors are
+ // model 00h and manufactured using the 0.18 micron process.
+ case 1: // Pentium 4 processor, Intel Xeon processor, Intel Xeon
+ // processor MP, and Intel Celeron processor. All processors are
+ // model 01h and manufactured using the 0.18 micron process.
+ case 2: // Pentium 4 processor, Mobile Intel Pentium 4 processor - M,
+ // Intel Xeon processor, Intel Xeon processor MP, Intel Celeron
+ // processor, and Mobile Intel Celeron processor. All processors
+ // are model 02h and manufactured using the 0.13 micron process.
+ return (Em64T) ? "x86-64" : "pentium4";
+
+ case 3: // Pentium 4 processor, Intel Xeon processor, Intel Celeron D
+ // processor. All processors are model 03h and manufactured using
+ // the 90 nm process.
+ case 4: // Pentium 4 processor, Pentium 4 processor Extreme Edition,
+ // Pentium D processor, Intel Xeon processor, Intel Xeon
+ // processor MP, Intel Celeron D processor. All processors are
+ // model 04h and manufactured using the 90 nm process.
+ case 6: // Pentium 4 processor, Pentium D processor, Pentium processor
+ // Extreme Edition, Intel Xeon processor, Intel Xeon processor
+ // MP, Intel Celeron D processor. All processors are model 06h
+ // and manufactured using the 65 nm process.
+ return (Em64T) ? "nocona" : "prescott";
+
+ default:
+ return (Em64T) ? "x86-64" : "pentium4";
+ }
+ }
+
+ default:
+ return "generic";
+ }
+ } else if (memcmp(text.c, "AuthenticAMD", 12) == 0) {
+ // FIXME: this poorly matches the generated SubtargetFeatureKV table. There
+ // appears to be no way to generate the wide variety of AMD-specific targets
+ // from the information returned from CPUID.
+ switch (Family) {
+ case 4:
+ return "i486";
+ case 5:
+ switch (Model) {
+ case 6:
+ case 7: return "k6";
+ case 8: return "k6-2";
+ case 9:
+ case 13: return "k6-3";
+ default: return "pentium";
+ }
+ case 6:
+ switch (Model) {
+ case 4: return "athlon-tbird";
+ case 6:
+ case 7:
+ case 8: return "athlon-mp";
+ case 10: return "athlon-xp";
+ default: return "athlon";
+ }
+ case 15:
+ if (HasSSE3)
+ return "k8-sse3";
+ switch (Model) {
+ case 1: return "opteron";
+ case 5: return "athlon-fx"; // also opteron
+ default: return "athlon64";
+ }
+ case 16:
+ return "amdfam10";
+ default:
+ return "generic";
+ }
+ }
+ return "generic";
+}
+#else
+std::string sys::getHostCPUName() {
+ return "generic";
+}
+#endif
+
+bool sys::getHostCPUFeatures(StringMap<bool> &Features){
+ return false;
+}
diff --git a/lib/Support/IncludeFile.cpp b/lib/Support/IncludeFile.cpp
new file mode 100644
index 0000000000..e41d1f0a81
--- /dev/null
+++ b/lib/Support/IncludeFile.cpp
@@ -0,0 +1,20 @@
+//===- lib/System/IncludeFile.cpp - Ensure Linking Of Implementation -----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the IncludeFile constructor.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/IncludeFile.h"
+
+using namespace llvm;
+
+// This constructor is used to ensure linking of other modules. See the
+// llvm/System/IncludeFile.h header for details.
+IncludeFile::IncludeFile(const void*) {}
diff --git a/lib/Support/Makefile b/lib/Support/Makefile
index 48c21f4fd9..d68e500ca5 100644
--- a/lib/Support/Makefile
+++ b/lib/Support/Makefile
@@ -14,4 +14,9 @@ BUILD_ARCHIVE = 1
## FIXME: This only requires RTTI because tblgen uses it. Fix that.
REQUIRES_RTTI = 1
+EXTRA_DIST = Unix Win32 README.txt
+
include $(LEVEL)/Makefile.common
+
+CompileCommonOpts := $(filter-out -pedantic,$(CompileCommonOpts))
+CompileCommonOpts := $(filter-out -Wno-long-long,$(CompileCommonOpts))
diff --git a/lib/Support/ManagedStatic.cpp b/lib/Support/ManagedStatic.cpp
index 4e655a0f9e..c767c15e71 100644
--- a/lib/Support/ManagedStatic.cpp
+++ b/lib/Support/ManagedStatic.cpp
@@ -13,7 +13,7 @@
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Config/config.h"
-#include "llvm/System/Atomic.h"
+#include "llvm/Support/Atomic.h"
#include <cassert>
using namespace llvm;
diff --git a/lib/Support/Memory.cpp b/lib/Support/Memory.cpp
new file mode 100644
index 0000000000..a9689b2c39
--- /dev/null
+++ b/lib/Support/Memory.cpp
@@ -0,0 +1,74 @@
+//===- Memory.cpp - Memory Handling Support ---------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines some helpful functions for allocating memory and dealing
+// with memory mapped files
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Memory.h"
+#include "llvm/Support/Valgrind.h"
+#include "llvm/Config/config.h"
+
+namespace llvm {
+using namespace sys;
+}
+
+// Include the platform-specific parts of this class.
+#ifdef LLVM_ON_UNIX
+#include "Unix/Memory.inc"
+#endif
+#ifdef LLVM_ON_WIN32
+#include "Windows/Memory.inc"
+#endif
+
+extern "C" void sys_icache_invalidate(const void *Addr, size_t len);
+
+/// InvalidateInstructionCache - Before the JIT can run a block of code
+/// that has been emitted it must invalidate the instruction cache on some
+/// platforms.
+void llvm::sys::Memory::InvalidateInstructionCache(const void *Addr,
+ size_t Len) {
+
+// icache invalidation for PPC and ARM.
+#if defined(__APPLE__)
+
+# if (defined(__POWERPC__) || defined (__ppc__) || \
+ defined(_POWER) || defined(_ARCH_PPC)) || defined(__arm__)
+ sys_icache_invalidate(Addr, Len);
+# endif
+
+#else
+
+# if (defined(__POWERPC__) || defined (__ppc__) || \
+ defined(_POWER) || defined(_ARCH_PPC)) && defined(__GNUC__)
+ const size_t LineSize = 32;
+
+ const intptr_t Mask = ~(LineSize - 1);
+ const intptr_t StartLine = ((intptr_t) Addr) & Mask;
+ const intptr_t EndLine = ((intptr_t) Addr + Len + LineSize - 1) & Mask;
+
+ for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize)
+ asm volatile("dcbf 0, %0" : : "r"(Line));
+ asm volatile("sync");
+
+ for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize)
+ asm volatile("icbi 0, %0" : : "r"(Line));
+ asm volatile("isync");
+# elif defined(__arm__) && defined(__GNUC__)
+ // FIXME: Can we safely always call this for __GNUC__ everywhere?
+ char *Start = (char*) Addr;
+ char *End = Start + Len;
+ __clear_cache(Start, End);
+# endif
+
+#endif // end apple
+
+ ValgrindDiscardTranslations(Addr, Len);
+}
diff --git a/lib/Support/MemoryBuffer.cpp b/lib/Support/MemoryBuffer.cpp
index 5b701a5c60..07a5ed478c 100644
--- a/lib/Support/MemoryBuffer.cpp
+++ b/lib/Support/MemoryBuffer.cpp
@@ -15,10 +15,10 @@
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/MathExtras.h"
-#include "llvm/System/Errno.h"
-#include "llvm/System/Path.h"
-#include "llvm/System/Process.h"
-#include "llvm/System/Program.h"
+#include "llvm/Support/Errno.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/Program.h"
#include <cassert>
#include <cstdio>
#include <cstring>
@@ -203,14 +203,14 @@ MemoryBuffer *MemoryBuffer::getFile(const char *Filename, std::string *ErrStr,
if (ErrStr) *ErrStr = sys::StrError();
return 0;
}
-
+
return getOpenFile(FD, Filename, ErrStr, FileSize);
}
-
+
MemoryBuffer *MemoryBuffer::getOpenFile(int FD, const char *Filename,
std::string *ErrStr, int64_t FileSize) {
FileCloser FC(FD); // Close FD on return.
-
+
// If we don't know the file size, use fstat to find out. fstat on an open
// file descriptor is cheaper than stat on a random path.
if (FileSize == -1) {
@@ -222,8 +222,8 @@ MemoryBuffer *MemoryBuffer::getOpenFile(int FD, const char *Filename,
}
FileSize = FileInfo.st_size;
}
-
-
+
+
// If the file is large, try to use mmap to read it in. We don't use mmap
// for small files, because this can severely fragment our address space. Also
// don't try to map files that are exactly a multiple of the system page size,
diff --git a/lib/Support/Mutex.cpp b/lib/Support/Mutex.cpp
new file mode 100644
index 0000000000..488868febe
--- /dev/null
+++ b/lib/Support/Mutex.cpp
@@ -0,0 +1,156 @@
+//===- Mutex.cpp - Mutual Exclusion Lock ------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the llvm::sys::Mutex class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Config/config.h"
+#include "llvm/Support/Mutex.h"
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only TRULY operating system
+//=== independent code.
+//===----------------------------------------------------------------------===//
+
+#if !defined(ENABLE_THREADS) || ENABLE_THREADS == 0
+// Define all methods as no-ops if threading is explicitly disabled
+namespace llvm {
+using namespace sys;
+MutexImpl::MutexImpl( bool recursive) { }
+MutexImpl::~MutexImpl() { }
+bool MutexImpl::acquire() { return true; }
+bool MutexImpl::release() { return true; }
+bool MutexImpl::tryacquire() { return true; }
+}
+#else
+
+#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_MUTEX_LOCK)
+
+#include <cassert>
+#include <pthread.h>
+#include <stdlib.h>
+
+namespace llvm {
+using namespace sys;
+
+
+// This variable is useful for situations where the pthread library has been
+// compiled with weak linkage for its interface symbols. This allows the
+// threading support to be turned off by simply not linking against -lpthread.
+// In that situation, the value of pthread_mutex_init will be 0 and
+// consequently pthread_enabled will be false. In such situations, all the
+// pthread operations become no-ops and the functions all return false. If
+// pthread_mutex_init does have an address, then mutex support is enabled.
+// Note: all LLVM tools will link against -lpthread if its available since it
+// is configured into the LIBS variable.
+// Note: this line of code generates a warning if pthread_mutex_init is not
+// declared with weak linkage. It's safe to ignore the warning.
+static const bool pthread_enabled = true;
+
+// Construct a Mutex using pthread calls
+MutexImpl::MutexImpl( bool recursive)
+ : data_(0)
+{
+ if (pthread_enabled)
+ {
+ // Declare the pthread_mutex data structures
+ pthread_mutex_t* mutex =
+ static_cast<pthread_mutex_t*>(malloc(sizeof(pthread_mutex_t)));
+ pthread_mutexattr_t attr;
+
+ // Initialize the mutex attributes
+ int errorcode = pthread_mutexattr_init(&attr);
+ assert(errorcode == 0);
+
+ // Initialize the mutex as a recursive mutex, if requested, or normal
+ // otherwise.
+ int kind = ( recursive ? PTHREAD_MUTEX_RECURSIVE : PTHREAD_MUTEX_NORMAL );
+ errorcode = pthread_mutexattr_settype(&attr, kind);
+ assert(errorcode == 0);
+
+#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__DragonFly__)
+ // Make it a process local mutex
+ errorcode = pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_PRIVATE);
+#endif
+
+ // Initialize the mutex
+ errorcode = pthread_mutex_init(mutex, &attr);
+ assert(errorcode == 0);
+
+ // Destroy the attributes
+ errorcode = pthread_mutexattr_destroy(&attr);
+ assert(errorcode == 0);
+
+ // Assign the data member
+ data_ = mutex;
+ }
+}
+
+// Destruct a Mutex
+MutexImpl::~MutexImpl()
+{
+ if (pthread_enabled)
+ {
+ pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
+ assert(mutex != 0);
+ pthread_mutex_destroy(mutex);
+ free(mutex);
+ }
+}
+
+bool
+MutexImpl::acquire()
+{
+ if (pthread_enabled)
+ {
+ pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
+ assert(mutex != 0);
+
+ int errorcode = pthread_mutex_lock(mutex);
+ return errorcode == 0;
+ } else return false;
+}
+
+bool
+MutexImpl::release()
+{
+ if (pthread_enabled)
+ {
+ pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
+ assert(mutex != 0);
+
+ int errorcode = pthread_mutex_unlock(mutex);
+ return errorcode == 0;
+ } else return false;
+}
+
+bool
+MutexImpl::tryacquire()
+{
+ if (pthread_enabled)
+ {
+ pthread_mutex_t* mutex = static_cast<pthread_mutex_t*>(data_);
+ assert(mutex != 0);
+
+ int errorcode = pthread_mutex_trylock(mutex);
+ return errorcode == 0;
+ } else return false;
+}
+
+}
+
+#elif defined(LLVM_ON_UNIX)
+#include "Unix/Mutex.inc"
+#elif defined( LLVM_ON_WIN32)
+#include "Windows/Mutex.inc"
+#else
+#warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 was set in System/Mutex.cpp
+#endif
+#endif
diff --git a/lib/Support/Path.cpp b/lib/Support/Path.cpp
new file mode 100644
index 0000000000..394e013b8b
--- /dev/null
+++ b/lib/Support/Path.cpp
@@ -0,0 +1,296 @@
+//===-- Path.cpp - Implement OS Path Concept --------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header file implements the operating system Path concept.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Path.h"
+#include "llvm/Config/config.h"
+#include <cassert>
+#include <cstring>
+#include <ostream>
+using namespace llvm;
+using namespace sys;
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only TRULY operating system
+//=== independent code.
+//===----------------------------------------------------------------------===//
+
+bool Path::operator==(const Path &that) const {
+ return path == that.path;
+}
+
+bool Path::operator<(const Path& that) const {
+ return path < that.path;
+}
+
+Path
+Path::GetLLVMConfigDir() {
+ Path result;
+#ifdef LLVM_ETCDIR
+ if (result.set(LLVM_ETCDIR))
+ return result;
+#endif
+ return GetLLVMDefaultConfigDir();
+}
+
+LLVMFileType
+sys::IdentifyFileType(const char *magic, unsigned length) {
+ assert(magic && "Invalid magic number string");
+ assert(length >=4 && "Invalid magic number length");
+ switch ((unsigned char)magic[0]) {
+ case 0xDE: // 0x0B17C0DE = BC wraper
+ if (magic[1] == (char)0xC0 && magic[2] == (char)0x17 &&
+ magic[3] == (char)0x0B)
+ return Bitcode_FileType;
+ break;
+ case 'B':
+ if (magic[1] == 'C' && magic[2] == (char)0xC0 && magic[3] == (char)0xDE)
+ return Bitcode_FileType;
+ break;
+ case '!':
+ if (length >= 8)
+ if (memcmp(magic,"!<arch>\n",8) == 0)
+ return Archive_FileType;
+ break;
+
+ case '\177':
+ if (magic[1] == 'E' && magic[2] == 'L' && magic[3] == 'F') {
+ if (length >= 18 && magic[17] == 0)
+ switch (magic[16]) {
+ default: break;
+ case 1: return ELF_Relocatable_FileType;
+ case 2: return ELF_Executable_FileType;
+ case 3: return ELF_SharedObject_FileType;
+ case 4: return ELF_Core_FileType;
+ }
+ }
+ break;
+
+ case 0xCA:
+ if (magic[1] == char(0xFE) && magic[2] == char(0xBA) &&
+ magic[3] == char(0xBE)) {
+ // This is complicated by an overlap with Java class files.
+ // See the Mach-O section in /usr/share/file/magic for details.
+ if (length >= 8 && magic[7] < 43)
+ // FIXME: Universal Binary of any type.
+ return Mach_O_DynamicallyLinkedSharedLib_FileType;
+ }
+ break;
+
+ case 0xFE:
+ case 0xCE: {
+ uint16_t type = 0;
+ if (magic[0] == char(0xFE) && magic[1] == char(0xED) &&
+ magic[2] == char(0xFA) && magic[3] == char(0xCE)) {
+ /* Native endian */
+ if (length >= 16) type = magic[14] << 8 | magic[15];
+ } else if (magic[0] == char(0xCE) && magic[1] == char(0xFA) &&
+ magic[2] == char(0xED) && magic[3] == char(0xFE)) {
+ /* Reverse endian */
+ if (length >= 14) type = magic[13] << 8 | magic[12];
+ }
+ switch (type) {
+ default: break;
+ case 1: return Mach_O_Object_FileType;
+ case 2: return Mach_O_Executable_FileType;
+ case 3: return Mach_O_FixedVirtualMemorySharedLib_FileType;
+ case 4: return Mach_O_Core_FileType;
+ case 5: return Mach_O_PreloadExecutable_FileType;
+ case 6: return Mach_O_DynamicallyLinkedSharedLib_FileType;
+ case 7: return Mach_O_DynamicLinker_FileType;
+ case 8: return Mach_O_Bundle_FileType;
+ case 9: return Mach_O_DynamicallyLinkedSharedLibStub_FileType;
+ case 10: break; // FIXME: MH_DSYM companion file with only debug.
+ }
+ break;
+ }
+ case 0xF0: // PowerPC Windows
+ case 0x83: // Alpha 32-bit
+ case 0x84: // Alpha 64-bit
+ case 0x66: // MPS R4000 Windows
+ case 0x50: // mc68K
+ case 0x4c: // 80386 Windows
+ if (magic[1] == 0x01)
+ return COFF_FileType;
+
+ case 0x90: // PA-RISC Windows
+ case 0x68: // mc68K Windows
+ if (magic[1] == 0x02)
+ return COFF_FileType;
+ break;
+ case 0x64: // x86-64 Windows.
+ if (magic[1] == char(0x86))
+ return COFF_FileType;
+ break;
+
+ default:
+ break;
+ }
+ return Unknown_FileType;
+}
+
+bool
+Path::isArchive() const {
+ return hasMagicNumber("!<arch>\012");
+}
+
+bool
+Path::isDynamicLibrary() const {
+ std::string Magic;
+ if (getMagicNumber(Magic, 64))
+ switch (IdentifyFileType(Magic.c_str(),
+ static_cast<unsigned>(Magic.length()))) {
+ default: return false;
+ case Mach_O_FixedVirtualMemorySharedLib_FileType:
+ case Mach_O_DynamicallyLinkedSharedLib_FileType:
+ case Mach_O_DynamicallyLinkedSharedLibStub_FileType:
+ case ELF_SharedObject_FileType:
+ case COFF_FileType: return true;
+ }
+
+ return false;
+}
+
+bool
+Path::isObjectFile() const {
+ std::string Magic;
+ if (getMagicNumber(Magic, 64))
+ if (IdentifyFileType(Magic.c_str(),
+ static_cast<unsigned>(Magic.length()))
+ != Unknown_FileType) {
+ // Everything in LLVMFileType is currently an object file.
+ return true;
+ }
+
+ return false;
+}
+
+Path
+Path::FindLibrary(std::string& name) {
+ std::vector<sys::Path> LibPaths;
+ GetSystemLibraryPaths(LibPaths);
+ for (unsigned i = 0; i < LibPaths.size(); ++i) {
+ sys::Path FullPath(LibPaths[i]);
+ FullPath.appendComponent("lib" + name + LTDL_SHLIB_EXT);
+ if (FullPath.isDynamicLibrary())
+ return FullPath;
+ FullPath.eraseSuffix();
+ FullPath.appendSuffix("a");
+ if (FullPath.isArchive())
+ return FullPath;
+ }
+ return sys::Path();
+}
+
+StringRef Path::GetDLLSuffix() {
+ return &(LTDL_SHLIB_EXT[1]);
+}
+
+bool
+Path::appendSuffix(StringRef suffix) {
+ if (!suffix.empty()) {
+ std::string save(path);
+ path.append(".");
+ path.append(suffix);
+ if (!isValid()) {
+ path = save;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool
+Path::isBitcodeFile() const {
+ std::string actualMagic;
+ if (!getMagicNumber(actualMagic, 4))
+ return false;
+ LLVMFileType FT =
+ IdentifyFileType(actualMagic.c_str(),
+ static_cast<unsigned>(actualMagic.length()));
+ return FT == Bitcode_FileType;
+}
+
+bool Path::hasMagicNumber(StringRef Magic) const {
+ std::string actualMagic;
+ if (getMagicNumber(actualMagic, static_cast<unsigned>(Magic.size())))
+ return Magic == actualMagic;
+ return false;
+}
+
+static void getPathList(const char*path, std::vector<Path>& Paths) {
+ const char* at = path;
+ const char* delim = strchr(at, PathSeparator);
+ Path tmpPath;
+ while (delim != 0) {
+ std::string tmp(at, size_t(delim-at));
+ if (tmpPath.set(tmp))
+ if (tmpPath.canRead())
+ Paths.push_back(tmpPath);
+ at = delim + 1;
+ delim = strchr(at, PathSeparator);
+ }
+
+ if (*at != 0)
+ if (tmpPath.set(std::string(at)))
+ if (tmpPath.canRead())
+ Paths.push_back(tmpPath);
+}
+
+static StringRef getDirnameCharSep(StringRef path, const char *Sep) {
+ assert(Sep[0] != '\0' && Sep[1] == '\0' &&
+ "Sep must be a 1-character string literal.");
+ if (path.empty())
+ return ".";
+
+ // If the path is all slashes, return a single slash.
+ // Otherwise, remove all trailing slashes.
+
+ signed pos = static_cast<signed>(path.size()) - 1;
+
+ while (pos >= 0 && path[pos] == Sep[0])
+ --pos;
+
+ if (pos < 0)
+ return path[0] == Sep[0] ? Sep : ".";
+
+ // Any slashes left?
+ signed i = 0;
+
+ while (i < pos && path[i] != Sep[0])
+ ++i;
+
+ if (i == pos) // No slashes? Return "."
+ return ".";
+
+ // There is at least one slash left. Remove all trailing non-slashes.
+ while (pos >= 0 && path[pos] != Sep[0])
+ --pos;
+
+ // Remove any trailing slashes.
+ while (pos >= 0 && path[pos] == Sep[0])
+ --pos;
+
+ if (pos < 0)
+ return path[0] == Sep[0] ? Sep : ".";
+
+ return path.substr(0, pos+1);
+}
+
+// Include the truly platform-specific parts of this class.
+#if defined(LLVM_ON_UNIX)
+#include "Unix/Path.inc"
+#endif
+#if defined(LLVM_ON_WIN32)
+#include "Windows/Path.inc"
+#endif
diff --git a/lib/Support/PluginLoader.cpp b/lib/Support/PluginLoader.cpp
index 36caecffee..2924cfa388 100644
--- a/lib/Support/PluginLoader.cpp
+++ b/lib/Support/PluginLoader.cpp
@@ -15,8 +15,8 @@
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/System/DynamicLibrary.h"
-#include "llvm/System/Mutex.h"
+#include "llvm/Support/DynamicLibrary.h"
+#include "llvm/Support/Mutex.h"
#include <vector>
using namespace llvm;
diff --git a/lib/Support/PrettyStackTrace.cpp b/lib/Support/PrettyStackTrace.cpp
index 3c8a10849d..2f46b9e2b9 100644
--- a/lib/Support/PrettyStackTrace.cpp
+++ b/lib/Support/PrettyStackTrace.cpp
@@ -15,8 +15,8 @@
#include "llvm/Config/config.h" // Get autoconf configuration settings
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/System/Signals.h"
-#include "llvm/System/ThreadLocal.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/ThreadLocal.h"
#include "llvm/ADT/SmallString.h"
#ifdef HAVE_CRASHREPORTERCLIENT_H
diff --git a/lib/Support/Process.cpp b/lib/Support/Process.cpp
new file mode 100644
index 0000000000..88ca7c3f22
--- /dev/null
+++ b/lib/Support/Process.cpp
@@ -0,0 +1,33 @@
+//===-- Process.cpp - Implement OS Process Concept --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header file implements the operating system Process concept.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Process.h"
+#include "llvm/Config/config.h"
+
+namespace llvm {
+using namespace sys;
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only TRULY operating system
+//=== independent code.
+//===----------------------------------------------------------------------===//
+
+}
+
+// Include the platform-specific parts of this class.
+#ifdef LLVM_ON_UNIX
+#include "Unix/Process.inc"
+#endif
+#ifdef LLVM_ON_WIN32
+#include "Windows/Process.inc"
+#endif
diff --git a/lib/Support/Program.cpp b/lib/Support/Program.cpp
new file mode 100644
index 0000000000..01860b082d
--- /dev/null
+++ b/lib/Support/Program.cpp
@@ -0,0 +1,56 @@
+//===-- Program.cpp - Implement OS Program Concept --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This header file implements the operating system Program concept.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Program.h"
+#include "llvm/Config/config.h"
+using namespace llvm;
+using namespace sys;
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only TRULY operating system
+//=== independent code.
+//===----------------------------------------------------------------------===//
+
+int
+Program::ExecuteAndWait(const Path& path,
+ const char** args,
+ const char** envp,
+ const Path** redirects,
+ unsigned secondsToWait,
+ unsigned memoryLimit,
+ std::string* ErrMsg) {
+ Program prg;
+ if (prg.Execute(path, args, envp, redirects, memoryLimit, ErrMsg))
+ return prg.Wait(path, secondsToWait, ErrMsg);
+ else
+ return -1;
+}
+
+void
+Program::ExecuteNoWait(const Path& path,
+ const char** args,
+ const char** envp,
+ const Path** redirects,
+ unsigned memoryLimit,
+ std::string* ErrMsg) {
+ Program prg;
+ prg.Execute(path, args, envp, redirects, memoryLimit, ErrMsg);
+}
+
+// Include the platform-specific parts of this class.
+#ifdef LLVM_ON_UNIX
+#include "Unix/Program.inc"
+#endif
+#ifdef LLVM_ON_WIN32
+#include "Windows/Program.inc"
+#endif
diff --git a/lib/Support/README.txt.system b/lib/Support/README.txt.system
new file mode 100644
index 0000000000..7a906b8dba
--- /dev/null
+++ b/lib/Support/README.txt.system
@@ -0,0 +1,43 @@
+Design Of lib/System
+====================
+
+The software in this directory is designed to completely shield LLVM from any
+and all operating system specific functionality. It is not intended to be a
+complete operating system wrapper (such as ACE), but only to provide the
+functionality necessary to support LLVM.
+
+The software located here, of necessity, has very specific and stringent design
+rules. Violation of these rules means that cracks in the shield could form and
+the primary goal of the library is defeated. By consistently using this library,
+LLVM becomes more easily ported to new platforms since the only thing requiring
+porting is this library.
+
+Complete documentation for the library can be found in the file:
+ llvm/docs/SystemLibrary.html
+or at this URL:
+ http://llvm.org/docs/SystemLibrary.html
+
+While we recommend that you read the more detailed documentation, for the
+impatient, here's a high level summary of the library's requirements.
+
+ 1. No system header files are to be exposed through the interface.
+ 2. Std C++ and Std C header files are okay to be exposed through the interface.
+ 3. No exposed system-specific functions.
+ 4. No exposed system-specific data.
+ 5. Data in lib/System classes must use only simple C++ intrinsic types.
+ 6. Errors are handled by returning "true" and setting an optional std::string
+ 7. Library must not throw any exceptions, period.
+ 8. Interface functions must not have throw() specifications.
+ 9. No duplicate function impementations are permitted within an operating
+ system class.
+
+To accomplish these requirements, the library has numerous design criteria that
+must be satisfied. Here's a high level summary of the library's design criteria:
+
+ 1. No unused functionality (only what LLVM needs)
+ 2. High-Level Interfaces
+ 3. Use Opaque Classes
+ 4. Common Implementations
+ 5. Multiple Implementations
+ 6. Minimize Memory Allocation
+ 7. No Virtual Methods
diff --git a/lib/Support/RWMutex.cpp b/lib/Support/RWMutex.cpp
new file mode 100644
index 0000000000..fc02f9cf7c
--- /dev/null
+++ b/lib/Support/RWMutex.cpp
@@ -0,0 +1,157 @@
+//===- RWMutex.cpp - Reader/Writer Mutual Exclusion Lock --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the llvm::sys::RWMutex class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Config/config.h"
+#include "llvm/Support/RWMutex.h"
+#include <cstring>
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only TRULY operating system
+//=== independent code.
+//===----------------------------------------------------------------------===//
+
+#if !defined(ENABLE_THREADS) || ENABLE_THREADS == 0
+// Define all methods as no-ops if threading is explicitly disabled
+namespace llvm {
+using namespace sys;
+RWMutexImpl::RWMutexImpl() { }
+RWMutexImpl::~RWMutexImpl() { }
+bool RWMutexImpl::reader_acquire() { return true; }
+bool RWMutexImpl::reader_release() { return true; }
+bool RWMutexImpl::writer_acquire() { return true; }
+bool RWMutexImpl::writer_release() { return true; }
+}
+#else
+
+#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_RWLOCK_INIT)
+
+#include <cassert>
+#include <pthread.h>
+#include <stdlib.h>
+
+namespace llvm {
+using namespace sys;
+
+
+// This variable is useful for situations where the pthread library has been
+// compiled with weak linkage for its interface symbols. This allows the
+// threading support to be turned off by simply not linking against -lpthread.
+// In that situation, the value of pthread_mutex_init will be 0 and
+// consequently pthread_enabled will be false. In such situations, all the
+// pthread operations become no-ops and the functions all return false. If
+// pthread_rwlock_init does have an address, then rwlock support is enabled.
+// Note: all LLVM tools will link against -lpthread if its available since it
+// is configured into the LIBS variable.
+// Note: this line of code generates a warning if pthread_rwlock_init is not
+// declared with weak linkage. It's safe to ignore the warning.
+static const bool pthread_enabled = true;
+
+// Construct a RWMutex using pthread calls
+RWMutexImpl::RWMutexImpl()
+ : data_(0)
+{
+ if (pthread_enabled)
+ {
+ // Declare the pthread_rwlock data structures
+ pthread_rwlock_t* rwlock =
+ static_cast<pthread_rwlock_t*>(malloc(sizeof(pthread_rwlock_t)));
+
+#ifdef __APPLE__
+ // Workaround a bug/mis-feature in Darwin's pthread_rwlock_init.
+ bzero(rwlock, sizeof(pthread_rwlock_t));
+#endif
+
+ // Initialize the rwlock
+ int errorcode = pthread_rwlock_init(rwlock, NULL);
+ (void)errorcode;
+ assert(errorcode == 0);
+
+ // Assign the data member
+ data_ = rwlock;
+ }
+}
+
+// Destruct a RWMutex
+RWMutexImpl::~RWMutexImpl()
+{
+ if (pthread_enabled)
+ {
+ pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
+ assert(rwlock != 0);
+ pthread_rwlock_destroy(rwlock);
+ free(rwlock);
+ }
+}
+
+bool
+RWMutexImpl::reader_acquire()
+{
+ if (pthread_enabled)
+ {
+ pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
+ assert(rwlock != 0);
+
+ int errorcode = pthread_rwlock_rdlock(rwlock);
+ return errorcode == 0;
+ } else return false;
+}
+
+bool
+RWMutexImpl::reader_release()
+{
+ if (pthread_enabled)
+ {
+ pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
+ assert(rwlock != 0);
+
+ int errorcode = pthread_rwlock_unlock(rwlock);
+ return errorcode == 0;
+ } else return false;
+}
+
+bool
+RWMutexImpl::writer_acquire()
+{
+ if (pthread_enabled)
+ {
+ pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
+ assert(rwlock != 0);
+
+ int errorcode = pthread_rwlock_wrlock(rwlock);
+ return errorcode == 0;
+ } else return false;
+}
+
+bool
+RWMutexImpl::writer_release()
+{
+ if (pthread_enabled)
+ {
+ pthread_rwlock_t* rwlock = static_cast<pthread_rwlock_t*>(data_);
+ assert(rwlock != 0);
+
+ int errorcode = pthread_rwlock_unlock(rwlock);
+ return errorcode == 0;
+ } else return false;
+}
+
+}
+
+#elif defined(LLVM_ON_UNIX)
+#include "Unix/RWMutex.inc"
+#elif defined( LLVM_ON_WIN32)
+#include "Windows/RWMutex.inc"
+#else
+#warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 was set in System/Mutex.cpp
+#endif
+#endif
diff --git a/lib/Support/SearchForAddressOfSpecialSymbol.cpp b/lib/Support/SearchForAddressOfSpecialSymbol.cpp
new file mode 100644
index 0000000000..51ba417c21
--- /dev/null
+++ b/lib/Support/SearchForAddressOfSpecialSymbol.cpp
@@ -0,0 +1,68 @@
+//===- SearchForAddressOfSpecialSymbol.cpp - Function addresses -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file pulls the addresses of certain symbols out of the linker. It must
+// include as few header files as possible because it declares the symbols as
+// void*, which would conflict with the actual symbol type if any header
+// declared it.
+//
+//===----------------------------------------------------------------------===//
+
+#include <string.h>
+
+// Must declare the symbols in the global namespace.
+static void *DoSearch(const char* symbolName) {
+#define EXPLICIT_SYMBOL(SYM) \
+ extern void *SYM; if (!strcmp(symbolName, #SYM)) return &SYM
+
+ // If this is darwin, it has some funky issues, try to solve them here. Some
+ // important symbols are marked 'private external' which doesn't allow
+ // SearchForAddressOfSymbol to find them. As such, we special case them here,
+ // there is only a small handful of them.
+
+#ifdef __APPLE__
+ {
+ EXPLICIT_SYMBOL(__ashldi3);
+ EXPLICIT_SYMBOL(__ashrdi3);
+ EXPLICIT_SYMBOL(__cmpdi2);
+ EXPLICIT_SYMBOL(__divdi3);
+ EXPLICIT_SYMBOL(__fixdfdi);
+ EXPLICIT_SYMBOL(__fixsfdi);
+ EXPLICIT_SYMBOL(__fixunsdfdi);
+ EXPLICIT_SYMBOL(__fixunssfdi);
+ EXPLICIT_SYMBOL(__floatdidf);
+ EXPLICIT_SYMBOL(__floatdisf);
+ EXPLICIT_SYMBOL(__lshrdi3);
+ EXPLICIT_SYMBOL(__moddi3);
+ EXPLICIT_SYMBOL(__udivdi3);
+ EXPLICIT_SYMBOL(__umoddi3);
+
+ // __eprintf is sometimes used for assert() handling on x86.
+#ifdef __i386__
+ EXPLICIT_SYMBOL(__eprintf);
+#endif
+ }
+#endif
+
+#ifdef __CYGWIN__
+ {
+ EXPLICIT_SYMBOL(_alloca);
+ EXPLICIT_SYMBOL(__main);
+ }
+#endif
+
+#undef EXPLICIT_SYMBOL
+ return 0;
+}
+
+namespace llvm {
+void *SearchForAddressOfSpecialSymbol(const char* symbolName) {
+ return DoSearch(symbolName);
+}
+} // namespace llvm
diff --git a/lib/Support/Signals.cpp b/lib/Support/Signals.cpp
new file mode 100644
index 0000000000..a3af37d5fe
--- /dev/null
+++ b/lib/Support/Signals.cpp
@@ -0,0 +1,34 @@
+//===- Signals.cpp - Signal Handling support --------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines some helpful functions for dealing with the possibility of
+// Unix signals occuring while your program is running.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Signals.h"
+#include "llvm/Config/config.h"
+
+namespace llvm {
+using namespace sys;
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only TRULY operating system
+//=== independent code.
+//===----------------------------------------------------------------------===//
+
+}
+
+// Include the platform-specific parts of this class.
+#ifdef LLVM_ON_UNIX
+#include "Unix/Signals.inc"
+#endif
+#ifdef LLVM_ON_WIN32
+#include "Windows/Signals.inc"
+#endif
diff --git a/lib/Support/Statistic.cpp b/lib/Support/Statistic.cpp
index e32ab74a2d..f0ed62690f 100644
--- a/lib/Support/Statistic.cpp
+++ b/lib/Support/Statistic.cpp
@@ -26,7 +26,7 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/System/Mutex.h"
+#include "llvm/Support/Mutex.h"
#include "llvm/ADT/StringExtras.h"
#include <algorithm>
#include <cstring>
diff --git a/lib/Support/SystemUtils.cpp b/lib/Support/SystemUtils.cpp
index 9646d75bd2..54b5e97bfe 100644
--- a/lib/Support/SystemUtils.cpp
+++ b/lib/Support/SystemUtils.cpp
@@ -13,8 +13,8 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/SystemUtils.h"
-#include "llvm/System/Process.h"
-#include "llvm/System/Program.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
diff --git a/lib/Support/TargetRegistry.cpp b/lib/Support/TargetRegistry.cpp
index 5896447f5e..293a5d7a01 100644
--- a/lib/Support/TargetRegistry.cpp
+++ b/lib/Support/TargetRegistry.cpp
@@ -8,7 +8,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/Target/TargetRegistry.h"
-#include "llvm/System/Host.h"
+#include "llvm/Support/Host.h"
#include <cassert>
using namespace llvm;
diff --git a/lib/Support/ThreadLocal.cpp b/lib/Support/ThreadLocal.cpp
new file mode 100644
index 0000000000..6b43048da1
--- /dev/null
+++ b/lib/Support/ThreadLocal.cpp
@@ -0,0 +1,84 @@
+//===- ThreadLocal.cpp - Thread Local Data ----------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the llvm::sys::ThreadLocal class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Config/config.h"
+#include "llvm/Support/ThreadLocal.h"
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only TRULY operating system
+//=== independent code.
+//===----------------------------------------------------------------------===//
+
+#if !defined(ENABLE_THREADS) || ENABLE_THREADS == 0
+// Define all methods as no-ops if threading is explicitly disabled
+namespace llvm {
+using namespace sys;
+ThreadLocalImpl::ThreadLocalImpl() { }
+ThreadLocalImpl::~ThreadLocalImpl() { }
+void ThreadLocalImpl::setInstance(const void* d) { data = const_cast<void*>(d);}
+const void* ThreadLocalImpl::getInstance() { return data; }
+void ThreadLocalImpl::removeInstance() { data = 0; }
+}
+#else
+
+#if defined(HAVE_PTHREAD_H) && defined(HAVE_PTHREAD_GETSPECIFIC)
+
+#include <cassert>
+#include <pthread.h>
+#include <stdlib.h>
+
+namespace llvm {
+using namespace sys;
+
+ThreadLocalImpl::ThreadLocalImpl() : data(0) {
+ pthread_key_t* key = new pthread_key_t;
+ int errorcode = pthread_key_create(key, NULL);
+ assert(errorcode == 0);
+ (void) errorcode;
+ data = (void*)key;
+}
+
+ThreadLocalImpl::~ThreadLocalImpl() {
+ pthread_key_t* key = static_cast<pthread_key_t*>(data);
+ int errorcode = pthread_key_delete(*key);
+ assert(errorcode == 0);
+ (void) errorcode;
+ delete key;
+}
+
+void ThreadLocalImpl::setInstance(const void* d) {
+ pthread_key_t* key = static_cast<pthread_key_t*>(data);
+ int errorcode = pthread_setspecific(*key, d);
+ assert(errorcode == 0);
+ (void) errorcode;
+}
+
+const void* ThreadLocalImpl::getInstance() {
+ pthread_key_t* key = static_cast<pthread_key_t*>(data);
+ return pthread_getspecific(*key);
+}
+
+void ThreadLocalImpl::removeInstance() {
+ setInstance(0);
+}
+
+}
+
+#elif defined(LLVM_ON_UNIX)
+#include "Unix/ThreadLocal.inc"
+#elif defined( LLVM_ON_WIN32)
+#include "Windows/ThreadLocal.inc"
+#else
+#warning Neither LLVM_ON_UNIX nor LLVM_ON_WIN32 was set in System/ThreadLocal.cpp
+#endif
+#endif
diff --git a/lib/Support/Threading.cpp b/lib/Support/Threading.cpp
new file mode 100644
index 0000000000..c2f85549f4
--- /dev/null
+++ b/lib/Support/Threading.cpp
@@ -0,0 +1,116 @@
+//===-- llvm/System/Threading.cpp- Control multithreading mode --*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements llvm_start_multithreaded() and friends.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Threading.h"
+#include "llvm/Support/Atomic.h"
+#include "llvm/Support/Mutex.h"
+#include "llvm/Config/config.h"
+#include <cassert>
+
+using namespace llvm;
+
+static bool multithreaded_mode = false;
+
+static sys::Mutex* global_lock = 0;
+
+bool llvm::llvm_start_multithreaded() {
+#ifdef LLVM_MULTITHREADED
+ assert(!multithreaded_mode && "Already multithreaded!");
+ multithreaded_mode = true;
+ global_lock = new sys::Mutex(true);
+
+ // We fence here to ensure that all initialization is complete BEFORE we
+ // return from llvm_start_multithreaded().
+ sys::MemoryFence();
+ return true;
+#else
+ return false;
+#endif
+}
+
+void llvm::llvm_stop_multithreaded() {
+#ifdef LLVM_MULTITHREADED
+ assert(multithreaded_mode && "Not currently multithreaded!");
+
+ // We fence here to insure that all threaded operations are complete BEFORE we
+ // return from llvm_stop_multithreaded().
+ sys::MemoryFence();
+
+ multithreaded_mode = false;
+ delete global_lock;
+#endif
+}
+
+bool llvm::llvm_is_multithreaded() {
+ return multithreaded_mode;
+}
+
+void llvm::llvm_acquire_global_lock() {
+ if (multithreaded_mode) global_lock->acquire();
+}
+
+void llvm::llvm_release_global_lock() {
+ if (multithreaded_mode) global_lock->release();
+}
+
+#if defined(LLVM_MULTITHREADED) && defined(HAVE_PTHREAD_H)
+#include <pthread.h>
+
+struct ThreadInfo {
+ void (*UserFn)(void *);
+ void *UserData;
+};
+static void *ExecuteOnThread_Dispatch(void *Arg) {
+ ThreadInfo *TI = reinterpret_cast<ThreadInfo*>(Arg);
+ TI->UserFn(TI->UserData);
+ return 0;
+}
+
+void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData,
+ unsigned RequestedStackSize) {
+ ThreadInfo Info = { Fn, UserData };
+ pthread_attr_t Attr;
+ pthread_t Thread;
+
+ // Construct the attributes object.
+ if (::pthread_attr_init(&Attr) != 0)
+ return;
+
+ // Set the requested stack size, if given.
+ if (RequestedStackSize != 0) {
+ if (::pthread_attr_setstacksize(&Attr, RequestedStackSize) != 0)
+ goto error;
+ }
+
+ // Construct and execute the thread.
+ if (::pthread_create(&Thread, &Attr, ExecuteOnThread_Dispatch, &Info) != 0)
+ goto error;
+
+ // Wait for the thread and clean up.
+ ::pthread_join(Thread, 0);
+
+ error:
+ ::pthread_attr_destroy(&Attr);
+}
+
+#else
+
+// No non-pthread implementation, currently.
+
+void llvm::llvm_execute_on_thread(void (*Fn)(void*), void *UserData,
+ unsigned RequestedStackSize) {
+ (void) RequestedStackSize;
+ Fn(UserData);
+}
+
+#endif
diff --git a/lib/Support/TimeValue.cpp b/lib/Support/TimeValue.cpp
new file mode 100644
index 0000000000..1a0f7bc363
--- /dev/null
+++ b/lib/Support/TimeValue.cpp
@@ -0,0 +1,57 @@
+//===-- TimeValue.cpp - Implement OS TimeValue Concept ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the operating system TimeValue concept.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/TimeValue.h"
+#include "llvm/Config/config.h"
+
+namespace llvm {
+using namespace sys;
+
+const TimeValue TimeValue::MinTime = TimeValue ( INT64_MIN,0 );
+const TimeValue TimeValue::MaxTime = TimeValue ( INT64_MAX,0 );
+const TimeValue TimeValue::ZeroTime = TimeValue ( 0,0 );
+const TimeValue TimeValue::PosixZeroTime = TimeValue ( -946684800,0 );
+const TimeValue TimeValue::Win32ZeroTime = TimeValue ( -12591158400ULL,0 );
+
+void
+TimeValue::normalize( void ) {
+ if ( nanos_ >= NANOSECONDS_PER_SECOND ) {
+ do {
+ seconds_++;
+ nanos_ -= NANOSECONDS_PER_SECOND;
+ } while ( nanos_ >= NANOSECONDS_PER_SECOND );
+ } else if (nanos_ <= -NANOSECONDS_PER_SECOND ) {
+ do {
+ seconds_--;
+ nanos_ += NANOSECONDS_PER_SECOND;
+ } while (nanos_ <= -NANOSECONDS_PER_SECOND);
+ }
+
+ if (seconds_ >= 1 && nanos_ < 0) {
+ seconds_--;
+ nanos_ += NANOSECONDS_PER_SECOND;
+ } else if (seconds_ < 0 && nanos_ > 0) {
+ seconds_++;
+ nanos_ -= NANOSECONDS_PER_SECOND;
+ }
+}
+
+}
+
+/// Include the platform specific portion of TimeValue class
+#ifdef LLVM_ON_UNIX
+#include "Unix/TimeValue.inc"
+#endif
+#ifdef LLVM_ON_WIN32
+#include "Windows/TimeValue.inc"
+#endif
diff --git a/lib/Support/Timer.cpp b/lib/Support/Timer.cpp
index 44ee1777cb..a9ed5eecfa 100644
--- a/lib/Support/Timer.cpp
+++ b/lib/Support/Timer.cpp
@@ -17,8 +17,8 @@
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Format.h"
-#include "llvm/System/Mutex.h"
-#include "llvm/System/Process.h"
+#include "llvm/Support/Mutex.h"
+#include "llvm/Support/Process.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringMap.h"
using namespace llvm;
diff --git a/lib/Support/ToolOutputFile.cpp b/lib/Support/ToolOutputFile.cpp
index 5b5ee6610a..e7ca927ea5 100644
--- a/lib/Support/ToolOutputFile.cpp
+++ b/lib/Support/ToolOutputFile.cpp
@@ -12,7 +12,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/ToolOutputFile.h"
-#include "llvm/System/Signals.h"
+#include "llvm/Support/Signals.h"
using namespace llvm;
tool_output_file::CleanupInstaller::CleanupInstaller(const char *filename)
diff --git a/lib/Support/Unix/Alarm.inc b/lib/Support/Unix/Alarm.inc
new file mode 100644
index 0000000000..fb42b6c65d
--- /dev/null
+++ b/lib/Support/Unix/Alarm.inc
@@ -0,0 +1,72 @@
+//===-- Alarm.inc - Implement Unix Alarm Support ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the UNIX Alarm support.
+//
+//===----------------------------------------------------------------------===//
+
+#include <signal.h>
+#include <unistd.h>
+#include <cassert>
+using namespace llvm;
+
+/// AlarmCancelled - This flag is set by the SIGINT signal handler if the
+/// user presses CTRL-C.
+static volatile bool AlarmCancelled = false;
+
+/// AlarmTriggered - This flag is set by the SIGALRM signal handler if the
+/// alarm was triggered.
+static volatile bool AlarmTriggered = false;
+
+/// NestedSOI - Sanity check. Alarms cannot be nested or run in parallel.
+/// This ensures that they never do.
+static bool NestedSOI = false;
+
+static RETSIGTYPE SigIntHandler(int Sig) {
+ AlarmCancelled = true;
+ signal(SIGINT, SigIntHandler);
+}
+
+static RETSIGTYPE SigAlarmHandler(int Sig) {
+ AlarmTriggered = true;
+}
+
+static void (*OldSigIntHandler) (int);
+
+void sys::SetupAlarm(unsigned seconds) {
+ assert(!NestedSOI && "sys::SetupAlarm calls cannot be nested!");
+ NestedSOI = true;
+ AlarmCancelled = false;
+ AlarmTriggered = false;
+ ::signal(SIGALRM, SigAlarmHandler);
+ OldSigIntHandler = ::signal(SIGINT, SigIntHandler);
+ ::alarm(seconds);
+}
+
+void sys::TerminateAlarm() {
+ assert(NestedSOI && "sys::TerminateAlarm called without sys::SetupAlarm!");
+ ::alarm(0);
+ ::signal(SIGALRM, SIG_DFL);
+ ::signal(SIGINT, OldSigIntHandler);
+ AlarmCancelled = false;
+ AlarmTriggered = false;
+ NestedSOI = false;
+}
+
+int sys::AlarmStatus() {
+ if (AlarmCancelled)
+ return -1;
+ if (AlarmTriggered)
+ return 1;
+ return 0;
+}
+
+void sys::Sleep(unsigned n) {
+ ::sleep(n);
+}
diff --git a/lib/Support/Unix/Host.inc b/lib/Support/Unix/Host.inc
new file mode 100644
index 0000000000..ca0de9ca9a
--- /dev/null
+++ b/lib/Support/Unix/Host.inc
@@ -0,0 +1,96 @@
+ //===- llvm/System/Unix/Host.inc -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the UNIX Host support.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only generic UNIX code that
+//=== is guaranteed to work on *all* UNIX variants.
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Config/config.h"
+#include "llvm/ADT/StringRef.h"
+#include "Unix.h"
+#include <sys/utsname.h>
+#include <string>
+
+using namespace llvm;
+
+static std::string getOSVersion() {
+ struct utsname info;
+
+ if (uname(&info))
+ return "";
+
+ return info.release;
+}
+
+std::string sys::getHostTriple() {
+ // FIXME: Derive directly instead of relying on the autoconf generated
+ // variable.
+
+ StringRef HostTripleString(LLVM_HOSTTRIPLE);
+ std::pair<StringRef, StringRef> ArchSplit = HostTripleString.split('-');
+
+ // Normalize the arch, since the host triple may not actually match the host.
+ std::string Arch = ArchSplit.first;
+
+ // It would be nice to do this in terms of llvm::Triple, but that is in
+ // Support which is layered above us.
+#if defined(__x86_64__)
+ Arch = "x86_64";
+#elif defined(__i386__)
+ Arch = "i386";
+#elif defined(__ppc64__)
+ Arch = "powerpc64";
+#elif defined(__ppc__)
+ Arch = "powerpc";
+#elif defined(__arm__)
+
+ // FIXME: We need to pick the right ARM triple (which involves querying the
+ // chip). However, for now this is most important for LLVM arch selection, so
+ // we only need to make sure to distinguish ARM and Thumb.
+# if defined(__thumb__)
+ Arch = "thumb";
+# else
+ Arch = "arm";
+# endif
+
+#else
+
+ // FIXME: When enough auto-detection is in place, this should just
+ // #error. Then at least the arch selection is done, and we only need the OS
+ // etc selection to kill off the use of LLVM_HOSTTRIPLE.
+
+#endif
+
+ std::string Triple(Arch);
+ Triple += '-';
+ Triple += ArchSplit.second;
+
+ // Force i<N>86 to i386.
+ if (Triple[0] == 'i' && isdigit(Triple[1]) &&
+ Triple[2] == '8' && Triple[3] == '6')
+ Triple[1] = '3';
+
+ // On darwin, we want to update the version to match that of the
+ // host.
+ std::string::size_type DarwinDashIdx = Triple.find("-darwin");
+ if (DarwinDashIdx != std::string::npos) {
+ Triple.resize(DarwinDashIdx + strlen("-darwin"));
+
+ // Only add the major part of the os version.
+ std::string Version = getOSVersion();
+ Triple += Version.substr(0, Version.find('.'));
+ }
+
+ return Triple;
+}
diff --git a/lib/Support/Unix/Memory.inc b/lib/Support/Unix/Memory.inc
new file mode 100644
index 0000000000..4312d67183
--- /dev/null
+++ b/lib/Support/Unix/Memory.inc
@@ -0,0 +1,151 @@
+//===- Unix/Memory.cpp - Generic UNIX System Configuration ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines some functions for various memory management utilities.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Unix.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Process.h"
+
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
+#ifdef __APPLE__
+#include <mach/mach.h>
+#endif
+
+/// AllocateRWX - Allocate a slab of memory with read/write/execute
+/// permissions. This is typically used for JIT applications where we want
+/// to emit code to the memory then jump to it. Getting this type of memory
+/// is very OS specific.
+///
+llvm::sys::MemoryBlock
+llvm::sys::Memory::AllocateRWX(size_t NumBytes, const MemoryBlock* NearBlock,
+ std::string *ErrMsg) {
+ if (NumBytes == 0) return MemoryBlock();
+
+ size_t pageSize = Process::GetPageSize();
+ size_t NumPages = (NumBytes+pageSize-1)/pageSize;
+
+ int fd = -1;
+#ifdef NEED_DEV_ZERO_FOR_MMAP
+ static int zero_fd = open("/dev/zero", O_RDWR);
+ if (zero_fd == -1) {
+ MakeErrMsg(ErrMsg, "Can't open /dev/zero device");
+ return MemoryBlock();
+ }
+ fd = zero_fd;
+#endif
+
+ int flags = MAP_PRIVATE |
+#ifdef HAVE_MMAP_ANONYMOUS
+ MAP_ANONYMOUS
+#else
+ MAP_ANON
+#endif
+ ;
+
+ void* start = NearBlock ? (unsigned char*)NearBlock->base() +
+ NearBlock->size() : 0;
+
+#if defined(__APPLE__) && defined(__arm__)
+ void *pa = ::mmap(start, pageSize*NumPages, PROT_READ|PROT_EXEC,
+ flags, fd, 0);
+#else
+ void *pa = ::mmap(start, pageSize*NumPages, PROT_READ|PROT_WRITE|PROT_EXEC,
+ flags, fd, 0);
+#endif
+ if (pa == MAP_FAILED) {
+ if (NearBlock) //Try again without a near hint
+ return AllocateRWX(NumBytes, 0);
+
+ MakeErrMsg(ErrMsg, "Can't allocate RWX Memory");
+ return MemoryBlock();
+ }
+
+#if defined(__APPLE__) && defined(__arm__)
+ kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)pa,
+ (vm_size_t)(pageSize*NumPages), 0,
+ VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_COPY);
+ if (KERN_SUCCESS != kr) {
+ MakeErrMsg(ErrMsg, "vm_protect max RX failed");
+ return sys::MemoryBlock();
+ }
+
+ kr = vm_protect(mach_task_self(), (vm_address_t)pa,
+ (vm_size_t)(pageSize*NumPages), 0,
+ VM_PROT_READ | VM_PROT_WRITE);
+ if (KERN_SUCCESS != kr) {
+ MakeErrMsg(ErrMsg, "vm_protect RW failed");
+ return sys::MemoryBlock();
+ }
+#endif
+
+ MemoryBlock result;
+ result.Address = pa;
+ result.Size = NumPages*pageSize;
+
+ return result;
+}
+
+bool llvm::sys::Memory::ReleaseRWX(MemoryBlock &M, std::string *ErrMsg) {
+ if (M.Address == 0 || M.Size == 0) return false;
+ if (0 != ::munmap(M.Address, M.Size))
+ return MakeErrMsg(ErrMsg, "Can't release RWX Memory");
+ return false;
+}
+
+bool llvm::sys::Memory::setWritable (MemoryBlock &M, std::string *ErrMsg) {
+#if defined(__APPLE__) && defined(__arm__)
+ if (M.Address == 0 || M.Size == 0) return false;
+ sys::Memory::InvalidateInstructionCache(M.Address, M.Size);
+ kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)M.Address,
+ (vm_size_t)M.Size, 0, VM_PROT_READ | VM_PROT_WRITE);
+ return KERN_SUCCESS == kr;
+#else
+ return true;
+#endif
+}
+
+bool llvm::sys::Memory::setExecutable (MemoryBlock &M, std::string *ErrMsg) {
+#if defined(__APPLE__) && defined(__arm__)
+ if (M.Address == 0 || M.Size == 0) return false;
+ sys::Memory::InvalidateInstructionCache(M.Address, M.Size);
+ kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)M.Address,
+ (vm_size_t)M.Size, 0, VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_COPY);
+ return KERN_SUCCESS == kr;
+#else
+ return false;
+#endif
+}
+
+bool llvm::sys::Memory::setRangeWritable(const void *Addr, size_t Size) {
+#if defined(__APPLE__) && defined(__arm__)
+ kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)Addr,
+ (vm_size_t)Size, 0,
+ VM_PROT_READ | VM_PROT_WRITE);
+ return KERN_SUCCESS == kr;
+#else
+ return true;
+#endif
+}
+
+bool llvm::sys::Memory::setRangeExecutable(const void *Addr, size_t Size) {
+#if defined(__APPLE__) && defined(__arm__)
+ kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)Addr,
+ (vm_size_t)Size, 0,
+ VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_COPY);
+ return KERN_SUCCESS == kr;
+#else
+ return true;
+#endif
+}
diff --git a/lib/Support/Unix/Mutex.inc b/lib/Support/Unix/Mutex.inc
new file mode 100644
index 0000000000..5c50697fd0
--- /dev/null
+++ b/lib/Support/Unix/Mutex.inc
@@ -0,0 +1,43 @@
+//===- llvm/System/Unix/Mutex.inc - Unix Mutex 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 implements the Unix specific (non-pthread) Mutex class.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only generic UNIX code that
+//=== is guaranteed to work on *all* UNIX variants.
+//===----------------------------------------------------------------------===//
+
+namespace llvm
+{
+using namespace sys;
+
+MutexImpl::MutexImpl( bool recursive)
+{
+}
+
+MutexImpl::~MutexImpl()
+{
+}
+
+bool
+MutexImpl::release()
+{
+ return true;
+}
+
+bool
+MutexImpl::tryacquire( void )
+{
+ return true;
+}
+
+}
diff --git a/lib/Support/Unix/Path.inc b/lib/Support/Unix/Path.inc
new file mode 100644
index 0000000000..5ee3adc4d2
--- /dev/null
+++ b/lib/Support/Unix/Path.inc
@@ -0,0 +1,896 @@
+//===- llvm/System/Unix/Path.cpp - Unix Path 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 implements the Unix specific portion of the Path class.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only generic UNIX code that
+//=== is guaranteed to work on *all* UNIX variants.
+//===----------------------------------------------------------------------===//
+
+#include "Unix.h"
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_UTIME_H
+#include <utime.h>
+#endif
+#if HAVE_TIME_H
+#include <time.h>
+#endif
+#if HAVE_DIRENT_H
+# include <dirent.h>
+# define NAMLEN(dirent) strlen((dirent)->d_name)
+#else
+# define dirent direct
+# define NAMLEN(dirent) (dirent)->d_namlen
+# if HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# endif
+# if HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif
+# if HAVE_NDIR_H
+# include <ndir.h>
+# endif
+#endif
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#ifdef __APPLE__
+#include <mach-o/dyld.h>
+#endif
+
+// Put in a hack for Cygwin which falsely reports that the mkdtemp function
+// is available when it is not.
+#ifdef __CYGWIN__
+# undef HAVE_MKDTEMP
+#endif
+
+namespace {
+inline bool lastIsSlash(const std::string& path) {
+ return !path.empty() && path[path.length() - 1] == '/';
+}
+
+}
+
+namespace llvm {
+using namespace sys;
+
+const char sys::PathSeparator = ':';
+
+StringRef Path::GetEXESuffix() {
+ return StringRef();
+}
+
+Path::Path(StringRef p)
+ : path(p) {}
+
+Path::Path(const char *StrStart, unsigned StrLen)
+ : path(StrStart, StrLen) {}
+
+Path&
+Path::operator=(StringRef that) {
+ path.assign(that.data(), that.size());
+ return *this;
+}
+
+bool
+Path::isValid() const {
+ // Empty paths are considered invalid here.
+ // This code doesn't check MAXPATHLEN because there's no need. Nothing in
+ // LLVM manipulates Paths with fixed-sizes arrays, and if the OS can't
+ // handle names longer than some limit, it'll report this on demand using
+ // ENAMETOLONG.
+ return !path.empty();
+}
+
+bool
+Path::isAbsolute(const char *NameStart, unsigned NameLen) {
+ assert(NameStart);
+ if (NameLen == 0)
+ return false;
+ return NameStart[0] == '/';
+}
+
+bool
+Path::isAbsolute() const {
+ if (path.empty())
+ return false;
+ return path[0] == '/';
+}
+
+void Path::makeAbsolute() {
+ if (isAbsolute())
+ return;
+
+ Path CWD = Path::GetCurrentDirectory();
+ assert(CWD.isAbsolute() && "GetCurrentDirectory returned relative path!");
+
+ CWD.appendComponent(path);
+
+ path = CWD.str();
+}
+
+Path
+Path::GetRootDirectory() {
+ Path result;
+ result.set("/");
+ return result;
+}
+
+Path
+Path::GetTemporaryDirectory(std::string *ErrMsg) {
+#if defined(HAVE_MKDTEMP)
+ // The best way is with mkdtemp but that's not available on many systems,
+ // Linux and FreeBSD have it. Others probably won't.
+ char pathname[] = "/tmp/llvm_XXXXXX";
+ if (0 == mkdtemp(pathname)) {
+ MakeErrMsg(ErrMsg,
+ std::string(pathname) + ": can't create temporary directory");
+ return Path();
+ }
+ return Path(pathname);
+#elif defined(HAVE_MKSTEMP)
+ // If no mkdtemp is available, mkstemp can be used to create a temporary file
+ // which is then removed and created as a directory. We prefer this over
+ // mktemp because of mktemp's inherent security and threading risks. We still
+ // have a slight race condition from the time the temporary file is created to
+ // the time it is re-created as a directoy.
+ char pathname[] = "/tmp/llvm_XXXXXX";
+ int fd = 0;
+ if (-1 == (fd = mkstemp(pathname))) {
+ MakeErrMsg(ErrMsg,
+ std::string(pathname) + ": can't create temporary directory");
+ return Path();
+ }
+ ::close(fd);
+ ::unlink(pathname); // start race condition, ignore errors
+ if (-1 == ::mkdir(pathname, S_IRWXU)) { // end race condition
+ MakeErrMsg(ErrMsg,
+ std::string(pathname) + ": can't create temporary directory");
+ return Path();
+ }
+ return Path(pathname);
+#elif defined(HAVE_MKTEMP)
+ // If a system doesn't have mkdtemp(3) or mkstemp(3) but it does have
+ // mktemp(3) then we'll assume that system (e.g. AIX) has a reasonable
+ // implementation of mktemp(3) and doesn't follow BSD 4.3's lead of replacing
+ // the XXXXXX with the pid of the process and a letter. That leads to only
+ // twenty six temporary files that can be generated.
+ char pathname[] = "/tmp/llvm_XXXXXX";
+ char *TmpName = ::mktemp(pathname);
+ if (TmpName == 0) {
+ MakeErrMsg(ErrMsg,
+ std::string(TmpName) + ": can't create unique directory name");
+ return Path();
+ }
+ if (-1 == ::mkdir(TmpName, S_IRWXU)) {
+ MakeErrMsg(ErrMsg,
+ std::string(TmpName) + ": can't create temporary directory");
+ return Path();
+ }
+ return Path(TmpName);
+#else
+ // This is the worst case implementation. tempnam(3) leaks memory unless its
+ // on an SVID2 (or later) system. On BSD 4.3 it leaks. tmpnam(3) has thread
+ // issues. The mktemp(3) function doesn't have enough variability in the
+ // temporary name generated. So, we provide our own implementation that
+ // increments an integer from a random number seeded by the current time. This
+ // should be sufficiently unique that we don't have many collisions between
+ // processes. Generally LLVM processes don't run very long and don't use very
+ // many temporary files so this shouldn't be a big issue for LLVM.
+ static time_t num = ::time(0);
+ char pathname[MAXPATHLEN];
+ do {
+ num++;
+ sprintf(pathname, "/tmp/llvm_%010u", unsigned(num));
+ } while ( 0 == access(pathname, F_OK ) );
+ if (-1 == ::mkdir(pathname, S_IRWXU)) {
+ MakeErrMsg(ErrMsg,
+ std::string(pathname) + ": can't create temporary directory");
+ return Path();
+ }
+ return Path(pathname);
+#endif
+}
+
+void
+Path::GetSystemLibraryPaths(std::vector<sys::Path>& Paths) {
+#ifdef LTDL_SHLIBPATH_VAR
+ char* env_var = getenv(LTDL_SHLIBPATH_VAR);
+ if (env_var != 0) {
+ getPathList(env_var,Paths);
+ }
+#endif
+ // FIXME: Should this look at LD_LIBRARY_PATH too?
+ Paths.push_back(sys::Path("/usr/local/lib/"));
+ Paths.push_back(sys::Path("/usr/X11R6/lib/"));
+ Paths.push_back(sys::Path("/usr/lib/"));
+ Paths.push_back(sys::Path("/lib/"));
+}
+
+void
+Path::GetBitcodeLibraryPaths(std::vector<sys::Path>& Paths) {
+ char * env_var = getenv("LLVM_LIB_SEARCH_PATH");
+ if (env_var != 0) {
+ getPathList(env_var,Paths);
+ }
+#ifdef LLVM_LIBDIR
+ {
+ Path tmpPath;
+ if (tmpPath.set(LLVM_LIBDIR))
+ if (tmpPath.canRead())
+ Paths.push_back(tmpPath);
+ }
+#endif
+ GetSystemLibraryPaths(Paths);
+}
+
+Path
+Path::GetLLVMDefaultConfigDir() {
+ return Path("/etc/llvm/");
+}
+
+Path
+Path::GetUserHomeDirectory() {
+ const char* home = getenv("HOME");
+ if (home) {
+ Path result;
+ if (result.set(home))
+ return result;
+ }
+ return GetRootDirectory();
+}
+
+Path
+Path::GetCurrentDirectory() {
+ char pathname[MAXPATHLEN];
+ if (!getcwd(pathname,MAXPATHLEN)) {
+ assert (false && "Could not query current working directory.");
+ return Path();
+ }
+
+ return Path(pathname);
+}
+
+#if defined(__FreeBSD__) || defined (__NetBSD__) || defined(__minix)
+static int
+test_dir(char buf[PATH_MAX], char ret[PATH_MAX],
+ const char *dir, const char *bin)
+{
+ struct stat sb;
+
+ snprintf(buf, PATH_MAX, "%s/%s", dir, bin);
+ if (realpath(buf, ret) == NULL)
+ return (1);
+ if (stat(buf, &sb) != 0)
+ return (1);
+
+ return (0);
+}
+
+static char *
+getprogpath(char ret[PATH_MAX], const char *bin)
+{
+ char *pv, *s, *t, buf[PATH_MAX];
+
+ /* First approach: absolute path. */
+ if (bin[0] == '/') {
+ if (test_dir(buf, ret, "/", bin) == 0)
+ return (ret);
+ return (NULL);
+ }
+
+ /* Second approach: relative path. */
+ if (strchr(bin, '/') != NULL) {
+ if (getcwd(buf, PATH_MAX) == NULL)
+ return (NULL);
+ if (test_dir(buf, ret, buf, bin) == 0)
+ return (ret);
+ return (NULL);
+ }
+
+ /* Third approach: $PATH */
+ if ((pv = getenv("PATH")) == NULL)
+ return (NULL);
+ s = pv = strdup(pv);
+ if (pv == NULL)
+ return (NULL);
+ while ((t = strsep(&s, ":")) != NULL) {
+ if (test_dir(buf, ret, t, bin) == 0) {
+ free(pv);
+ return (ret);
+ }
+ }
+ free(pv);
+ return (NULL);
+}
+#endif // __FreeBSD__ || __NetBSD__
+
+/// GetMainExecutable - Return the path to the main executable, given the
+/// value of argv[0] from program startup.
+Path Path::GetMainExecutable(const char *argv0, void *MainAddr) {
+#if defined(__APPLE__)
+ // On OS X the executable path is saved to the stack by dyld. Reading it
+ // from there is much faster than calling dladdr, especially for large
+ // binaries with symbols.
+ char exe_path[MAXPATHLEN];
+ uint32_t size = sizeof(exe_path);
+ if (_NSGetExecutablePath(exe_path, &size) == 0) {
+ char link_path[MAXPATHLEN];
+ if (realpath(exe_path, link_path))
+ return Path(link_path);
+ }
+#elif defined(__FreeBSD__) || defined (__NetBSD__) || defined(__minix)
+ char exe_path[PATH_MAX];
+
+ if (getprogpath(exe_path, argv0) != NULL)
+ return Path(exe_path);
+#elif defined(__linux__) || defined(__CYGWIN__)
+ char exe_path[MAXPATHLEN];
+ ssize_t len = readlink("/proc/self/exe", exe_path, sizeof(exe_path));
+ if (len >= 0)
+ return Path(StringRef(exe_path, len));
+#elif defined(HAVE_DLFCN_H)
+ // Use dladdr to get executable path if available.
+ Dl_info DLInfo;
+ int err = dladdr(MainAddr, &DLInfo);
+ if (err == 0)
+ return Path();
+
+ // If the filename is a symlink, we need to resolve and return the location of
+ // the actual executable.
+ char link_path[MAXPATHLEN];
+ if (realpath(DLInfo.dli_fname, link_path))
+ return Path(link_path);
+#else
+#error GetMainExecutable is not implemented on this host yet.
+#endif
+ return Path();
+}
+
+
+StringRef Path::getDirname() const {
+ return getDirnameCharSep(path, "/");
+}
+
+StringRef
+Path::getBasename() const {
+ // Find the last slash
+ std::string::size_type slash = path.rfind('/');
+ if (slash == std::string::npos)
+ slash = 0;
+ else
+ slash++;
+
+ std::string::size_type dot = path.rfind('.');
+ if (dot == std::string::npos || dot < slash)
+ return StringRef(path).substr(slash);
+ else
+ return StringRef(path).substr(slash, dot - slash);
+}
+
+StringRef
+Path::getSuffix() const {
+ // Find the last slash
+ std::string::size_type slash = path.rfind('/');
+ if (slash == std::string::npos)
+ slash = 0;
+ else
+ slash++;
+
+ std::string::size_type dot = path.rfind('.');
+ if (dot == std::string::npos || dot < slash)
+ return StringRef();
+ else
+ return StringRef(path).substr(dot + 1);
+}
+
+bool Path::getMagicNumber(std::string &Magic, unsigned len) const {
+ assert(len < 1024 && "Request for magic string too long");
+ char Buf[1025];
+ int fd = ::open(path.c_str(), O_RDONLY);
+ if (fd < 0)
+ return false;
+ ssize_t bytes_read = ::read(fd, Buf, len);
+ ::close(fd);
+ if (ssize_t(len) != bytes_read)
+ return false;
+ Magic.assign(Buf, len);
+ return true;
+}
+
+bool
+Path::exists() const {
+ return 0 == access(path.c_str(), F_OK );
+}
+
+bool
+Path::isDirectory() const {
+ struct stat buf;
+ if (0 != stat(path.c_str(), &buf))
+ return false;
+ return ((buf.st_mode & S_IFMT) == S_IFDIR) ? true : false;
+}
+
+bool
+Path::isSymLink() const {
+ struct stat buf;
+ if (0 != lstat(path.c_str(), &buf))
+ return false;
+ return S_ISLNK(buf.st_mode);
+}
+
+
+bool
+Path::canRead() const {
+ return 0 == access(path.c_str(), R_OK);
+}
+
+bool
+Path::canWrite() const {
+ return 0 == access(path.c_str(), W_OK);
+}
+
+bool
+Path::isRegularFile() const {
+ // Get the status so we can determine if it's a file or directory
+ struct stat buf;
+
+ if (0 != stat(path.c_str(), &buf))
+ return false;
+
+ if (S_ISREG(buf.st_mode))
+ return true;
+
+ return false;
+}
+
+bool
+Path::canExecute() const {
+ if (0 != access(path.c_str(), R_OK | X_OK ))
+ return false;
+ struct stat buf;
+ if (0 != stat(path.c_str(), &buf))
+ return false;
+ if (!S_ISREG(buf.st_mode))
+ return false;
+ return true;
+}
+
+StringRef
+Path::getLast() const {
+ // Find the last slash
+ size_t pos = path.rfind('/');
+
+ // Handle the corner cases
+ if (pos == std::string::npos)
+ return path;
+
+ // If the last character is a slash
+ if (pos == path.length()-1) {
+ // Find the second to last slash
+ size_t pos2 = path.rfind('/', pos-1);
+ if (pos2 == std::string::npos)
+ return StringRef(path).substr(0,pos);
+ else
+ return StringRef(path).substr(pos2+1,pos-pos2-1);
+ }
+ // Return everything after the last slash
+ return StringRef(path).substr(pos+1);
+}
+
+const FileStatus *
+PathWithStatus::getFileStatus(bool update, std::string *ErrStr) const {
+ if (!fsIsValid || update) {
+ struct stat buf;
+ if (0 != stat(path.c_str(), &buf)) {
+ MakeErrMsg(ErrStr, path + ": can't get status of file");
+ return 0;
+ }
+ status.fileSize = buf.st_size;
+ status.modTime.fromEpochTime(buf.st_mtime);
+ status.mode = buf.st_mode;
+ status.user = buf.st_uid;
+ status.group = buf.st_gid;
+ status.uniqueID = uint64_t(buf.st_ino);
+ status.isDir = S_ISDIR(buf.st_mode);
+ status.isFile = S_ISREG(buf.st_mode);
+ fsIsValid = true;
+ }
+ return &status;
+}
+
+static bool AddPermissionBits(const Path &File, int bits) {
+ // Get the umask value from the operating system. We want to use it
+ // when changing the file's permissions. Since calling umask() sets
+ // the umask and returns its old value, we must call it a second
+ // time to reset it to the user's preference.
+ int mask = umask(0777); // The arg. to umask is arbitrary.
+ umask(mask); // Restore the umask.
+
+ // Get the file's current mode.
+ struct stat buf;
+ if (0 != stat(File.c_str(), &buf))
+ return false;
+ // Change the file to have whichever permissions bits from 'bits'
+ // that the umask would not disable.
+ if ((chmod(File.c_str(), (buf.st_mode | (bits & ~mask)))) == -1)
+ return false;
+ return true;
+}
+
+bool Path::makeReadableOnDisk(std::string* ErrMsg) {
+ if (!AddPermissionBits(*this, 0444))
+ return MakeErrMsg(ErrMsg, path + ": can't make file readable");
+ return false;
+}
+
+bool Path::makeWriteableOnDisk(std::string* ErrMsg) {
+ if (!AddPermissionBits(*this, 0222))
+ return MakeErrMsg(ErrMsg, path + ": can't make file writable");
+ return false;
+}
+
+bool Path::makeExecutableOnDisk(std::string* ErrMsg) {
+ if (!AddPermissionBits(*this, 0111))
+ return MakeErrMsg(ErrMsg, path + ": can't make file executable");
+ return false;
+}
+
+bool
+Path::getDirectoryContents(std::set<Path>& result, std::string* ErrMsg) const {
+ DIR* direntries = ::opendir(path.c_str());
+ if (direntries == 0)
+ return MakeErrMsg(ErrMsg, path + ": can't open directory");
+
+ std::string dirPath = path;
+ if (!lastIsSlash(dirPath))
+ dirPath += '/';
+
+ result.clear();
+ struct dirent* de = ::readdir(direntries);
+ for ( ; de != 0; de = ::readdir(direntries)) {
+ if (de->d_name[0] != '.') {
+ Path aPath(dirPath + (const char*)de->d_name);
+ struct stat st;
+ if (0 != lstat(aPath.path.c_str(), &st)) {
+ if (S_ISLNK(st.st_mode))
+ continue; // dangling symlink -- ignore
+ return MakeErrMsg(ErrMsg,
+ aPath.path + ": can't determine file object type");
+ }
+ result.insert(aPath);
+ }
+ }
+
+ closedir(direntries);
+ return false;
+}
+
+bool
+Path::set(StringRef a_path) {
+ if (a_path.empty())
+ return false;
+ path = a_path;
+ return true;
+}
+
+bool
+Path::appendComponent(StringRef name) {
+ if (name.empty())
+ return false;
+ if (!lastIsSlash(path))
+ path += '/';
+ path += name;
+ return true;
+}
+
+bool
+Path::eraseComponent() {
+ size_t slashpos = path.rfind('/',path.size());
+ if (slashpos == 0 || slashpos == std::string::npos) {
+ path.erase();
+ return true;
+ }
+ if (slashpos == path.size() - 1)
+ slashpos = path.rfind('/',slashpos-1);
+ if (slashpos == std::string::npos) {
+ path.erase();
+ return true;
+ }
+ path.erase(slashpos);
+ return true;
+}
+
+bool
+Path::eraseSuffix() {
+ size_t dotpos = path.rfind('.',path.size());
+ size_t slashpos = path.rfind('/',path.size());
+ if (dotpos != std::string::npos) {
+ if (slashpos == std::string::npos || dotpos > slashpos+1) {
+ path.erase(dotpos, path.size()-dotpos);
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool createDirectoryHelper(char* beg, char* end, bool create_parents) {
+
+ if (access(beg, R_OK | W_OK) == 0)
+ return false;
+
+ if (create_parents) {
+
+ char* c = end;
+
+ for (; c != beg; --c)
+ if (*c == '/') {
+
+ // Recurse to handling the parent directory.
+ *c = '\0';
+ bool x = createDirectoryHelper(beg, c, create_parents);
+ *c = '/';
+
+ // Return if we encountered an error.
+ if (x)
+ return true;
+
+ break;
+ }
+ }
+
+ return mkdir(beg, S_IRWXU | S_IRWXG) != 0;
+}
+
+bool
+Path::createDirectoryOnDisk( bool create_parents, std::string* ErrMsg ) {
+ // Get a writeable copy of the path name
+ std::string pathname(path);
+
+ // Null-terminate the last component
+ size_t lastchar = path.length() - 1 ;
+
+ if (pathname[lastchar] != '/')
+ ++lastchar;
+
+ pathname[lastchar] = '\0';
+
+ if (createDirectoryHelper(&pathname[0], &pathname[lastchar], create_parents))
+ return MakeErrMsg(ErrMsg, pathname + ": can't create directory");
+
+ return false;
+}
+
+bool
+Path::createFileOnDisk(std::string* ErrMsg) {
+ // Create the file
+ int fd = ::creat(path.c_str(), S_IRUSR | S_IWUSR);
+ if (fd < 0)
+ return MakeErrMsg(ErrMsg, path + ": can't create file");
+ ::close(fd);
+ return false;
+}
+
+bool
+Path::createTemporaryFileOnDisk(bool reuse_current, std::string* ErrMsg) {
+ // Make this into a unique file name
+ if (makeUnique( reuse_current, ErrMsg ))
+ return true;
+
+ // create the file
+ int fd = ::open(path.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0666);
+ if (fd < 0)
+ return MakeErrMsg(ErrMsg, path + ": can't create temporary file");
+ ::close(fd);
+ return false;
+}
+
+bool
+Path::eraseFromDisk(bool remove_contents, std::string *ErrStr) const {
+ // Get the status so we can determine if it's a file or directory.
+ struct stat buf;
+ if (0 != stat(path.c_str(), &buf)) {
+ MakeErrMsg(ErrStr, path + ": can't get status of file");
+ return true;
+ }
+
+ // Note: this check catches strange situations. In all cases, LLVM should
+ // only be involved in the creation and deletion of regular files. This
+ // check ensures that what we're trying to erase is a regular file. It
+ // effectively prevents LLVM from erasing things like /dev/null, any block
+ // special file, or other things that aren't "regular" files.
+ if (S_ISREG(buf.st_mode)) {
+ if (unlink(path.c_str()) != 0)
+ return MakeErrMsg(ErrStr, path + ": can't destroy file");
+ return false;
+ }
+
+ if (!S_ISDIR(buf.st_mode)) {
+ if (ErrStr) *ErrStr = "not a file or directory";
+ return true;
+ }
+
+ if (remove_contents) {
+ // Recursively descend the directory to remove its contents.
+ std::string cmd = "/bin/rm -rf " + path;
+ if (system(cmd.c_str()) != 0) {
+ MakeErrMsg(ErrStr, path + ": failed to recursively remove directory.");
+ return true;
+ }
+ return false;
+ }
+
+ // Otherwise, try to just remove the one directory.
+ std::string pathname(path);
+ size_t lastchar = path.length() - 1;
+ if (pathname[lastchar] == '/')
+ pathname[lastchar] = '\0';
+ else
+ pathname[lastchar+1] = '\0';
+
+ if (rmdir(pathname.c_str()) != 0)
+ return MakeErrMsg(ErrStr, pathname + ": can't erase directory");
+ return false;
+}
+
+bool
+Path::renamePathOnDisk(const Path& newName, std::string* ErrMsg) {
+ if (0 != ::rename(path.c_str(), newName.c_str()))
+ return MakeErrMsg(ErrMsg, std::string("can't rename '") + path + "' as '" +
+ newName.str() + "'");
+ return false;
+}
+
+bool
+Path::setStatusInfoOnDisk(const FileStatus &si, std::string *ErrStr) const {
+ struct utimbuf utb;
+ utb.actime = si.modTime.toPosixTime();
+ utb.modtime = utb.actime;
+ if (0 != ::utime(path.c_str(),&utb))
+ return MakeErrMsg(ErrStr, path + ": can't set file modification time");
+ if (0 != ::chmod(path.c_str(),si.mode))
+ return MakeErrMsg(ErrStr, path + ": can't set mode");
+ return false;
+}
+
+bool
+sys::CopyFile(const sys::Path &Dest, const sys::Path &Src, std::string* ErrMsg){
+ int inFile = -1;
+ int outFile = -1;
+ inFile = ::open(Src.c_str(), O_RDONLY);
+ if (inFile == -1)
+ return MakeErrMsg(ErrMsg, Src.str() +
+ ": can't open source file to copy");
+
+ outFile = ::open(Dest.c_str(), O_WRONLY|O_CREAT, 0666);
+ if (outFile == -1) {
+ ::close(inFile);
+ return MakeErrMsg(ErrMsg, Dest.str() +
+ ": can't create destination file for copy");
+ }
+
+ char Buffer[16*1024];
+ while (ssize_t Amt = ::read(inFile, Buffer, 16*1024)) {
+ if (Amt == -1) {
+ if (errno != EINTR && errno != EAGAIN) {
+ ::close(inFile);
+ ::close(outFile);
+ return MakeErrMsg(ErrMsg, Src.str()+": can't read source file");
+ }
+ } else {
+ char *BufPtr = Buffer;
+ while (Amt) {
+ ssize_t AmtWritten = ::write(outFile, BufPtr, Amt);
+ if (AmtWritten == -1) {
+ if (errno != EINTR && errno != EAGAIN) {
+ ::close(inFile);
+ ::close(outFile);
+ return MakeErrMsg(ErrMsg, Dest.str() +
+ ": can't write destination file");
+ }
+ } else {
+ Amt -= AmtWritten;
+ BufPtr += AmtWritten;
+ }
+ }
+ }
+ }
+ ::close(inFile);
+ ::close(outFile);
+ return false;
+}
+
+bool
+Path::makeUnique(bool reuse_current, std::string* ErrMsg) {
+ if (reuse_current && !exists())
+ return false; // File doesn't exist already, just use it!
+
+ // Append an XXXXXX pattern to the end of the file for use with mkstemp,
+ // mktemp or our own implementation.
+ // This uses std::vector instead of SmallVector to avoid a dependence on
+ // libSupport. And performance isn't critical here.
+ std::vector<char> Buf;
+ Buf.resize(path.size()+8);
+ char *FNBuffer = &Buf[0];
+ path.copy(FNBuffer,path.size());
+ if (isDirectory())
+ strcpy(FNBuffer+path.size(), "/XXXXXX");
+ else
+ strcpy(FNBuffer+path.size(), "-XXXXXX");
+
+#if defined(HAVE_MKSTEMP)
+ int TempFD;
+ if ((TempFD = mkstemp(FNBuffer)) == -1)
+ return MakeErrMsg(ErrMsg, path + ": can't make unique filename");
+
+ // We don't need to hold the temp file descriptor... we will trust that no one
+ // will overwrite/delete the file before we can open it again.
+ close(TempFD);
+
+ // Save the name
+ path = FNBuffer;
+#elif defined(HAVE_MKTEMP)
+ // If we don't have mkstemp, use the old and obsolete mktemp function.
+ if (mktemp(FNBuffer) == 0)
+ return MakeErrMsg(ErrMsg, path + ": can't make unique filename");
+
+ // Save the name
+ path = FNBuffer;
+#else
+ // Okay, looks like we have to do it all by our lonesome.
+ static unsigned FCounter = 0;
+ // Try to initialize with unique value.
+ if (FCounter == 0) FCounter = ((unsigned)getpid() & 0xFFFF) << 8;
+ char* pos = strstr(FNBuffer, "XXXXXX");
+ do {
+ if (++FCounter > 0xFFFFFF) {
+ return MakeErrMsg(ErrMsg,
+ path + ": can't make unique filename: too many files");
+ }
+ sprintf(pos, "%06X", FCounter);
+ path = FNBuffer;
+ } while (exists());
+ // POSSIBLE SECURITY BUG: An attacker can easily guess the name and exploit
+ // LLVM.
+#endif
+ return false;
+}
+
+const char *Path::MapInFilePages(int FD, uint64_t FileSize) {
+ int Flags = MAP_PRIVATE;
+#ifdef MAP_FILE
+ Flags |= MAP_FILE;
+#endif
+ void *BasePtr = ::mmap(0, FileSize, PROT_READ, Flags, FD, 0);
+ if (BasePtr == MAP_FAILED)
+ return 0;
+ return (const char*)BasePtr;
+}
+
+void Path::UnMapFilePages(const char *BasePtr, uint64_t FileSize) {
+ ::munmap((void*)BasePtr, FileSize);
+}
+
+} // end llvm namespace
diff --git a/lib/Support/Unix/Process.inc b/lib/Support/Unix/Process.inc
new file mode 100644
index 0000000000..5cdb11cceb
--- /dev/null
+++ b/lib/Support/Unix/Process.inc
@@ -0,0 +1,295 @@
+//===- Unix/Process.cpp - Unix Process 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 generic Unix implementation of the Process class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Unix.h"
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#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__)
+#include <malloc.h>
+#endif
+#ifdef HAVE_MALLOC_MALLOC_H
+#include <malloc/malloc.h>
+#endif
+#ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+#ifdef HAVE_TERMIOS_H
+# include <termios.h>
+#endif
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only generic UNIX code that
+//=== is guaranteed to work on *all* UNIX variants.
+//===----------------------------------------------------------------------===//
+
+using namespace llvm;
+using namespace sys;
+
+unsigned
+Process::GetPageSize()
+{
+#if defined(__CYGWIN__)
+ // On Cygwin, getpagesize() returns 64k but the page size for the purposes of
+ // memory protection and mmap() is 4k.
+ // See http://www.cygwin.com/ml/cygwin/2009-01/threads.html#00492
+ const int page_size = 0x1000;
+#elif defined(HAVE_GETPAGESIZE)
+ const int page_size = ::getpagesize();
+#elif defined(HAVE_SYSCONF)
+ long page_size = ::sysconf(_SC_PAGE_SIZE);
+#else
+#warning Cannot get the page size on this machine
+#endif
+ return static_cast<unsigned>(page_size);
+}
+
+size_t Process::GetMallocUsage() {
+#if defined(HAVE_MALLINFO)
+ struct mallinfo mi;
+ mi = ::mallinfo();
+ return mi.uordblks;
+#elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
+ malloc_statistics_t Stats;
+ malloc_zone_statistics(malloc_default_zone(), &Stats);
+ return Stats.size_in_use; // darwin
+#elif defined(HAVE_SBRK)
+ // Note this is only an approximation and more closely resembles
+ // the value returned by mallinfo in the arena field.
+ static char *StartOfMemory = reinterpret_cast<char*>(::sbrk(0));
+ char *EndOfMemory = (char*)sbrk(0);
+ if (EndOfMemory != ((char*)-1) && StartOfMemory != ((char*)-1))
+ return EndOfMemory - StartOfMemory;
+ else
+ return 0;
+#else
+#warning Cannot get malloc info on this platform
+ return 0;
+#endif
+}
+
+size_t
+Process::GetTotalMemoryUsage()
+{
+#if defined(HAVE_MALLINFO)
+ struct mallinfo mi = ::mallinfo();
+ return mi.uordblks + mi.hblkhd;
+#elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H)
+ malloc_statistics_t Stats;
+ malloc_zone_statistics(malloc_default_zone(), &Stats);
+ return Stats.size_allocated; // darwin
+#elif defined(HAVE_GETRUSAGE) && !defined(__HAIKU__)
+ struct rusage usage;
+ ::getrusage(RUSAGE_SELF, &usage);
+ return usage.ru_maxrss;
+#else
+#warning Cannot get total memory size on this platform
+ return 0;
+#endif
+}
+
+void
+Process::GetTimeUsage(TimeValue& elapsed, TimeValue& user_time,
+ TimeValue& sys_time)
+{
+ elapsed = TimeValue::now();
+#if defined(HAVE_GETRUSAGE)
+ struct rusage usage;
+ ::getrusage(RUSAGE_SELF, &usage);
+ user_time = TimeValue(
+ static_cast<TimeValue::SecondsType>( usage.ru_utime.tv_sec ),
+ static_cast<TimeValue::NanoSecondsType>( usage.ru_utime.tv_usec *
+ TimeValue::NANOSECONDS_PER_MICROSECOND ) );
+ sys_time = TimeValue(
+ static_cast<TimeValue::SecondsType>( usage.ru_stime.tv_sec ),
+ static_cast<TimeValue::NanoSecondsType>( usage.ru_stime.tv_usec *
+ TimeValue::NANOSECONDS_PER_MICROSECOND ) );
+#else
+#warning Cannot get usage times on this platform
+ user_time.seconds(0);
+ user_time.microseconds(0);
+ sys_time.seconds(0);
+ sys_time.microseconds(0);
+#endif
+}
+
+int Process::GetCurrentUserId() {
+ return getuid();
+}
+
+int Process::GetCurrentGroupId() {
+ return getgid();
+}
+
+#ifdef HAVE_MACH_MACH_H
+#include <mach/mach.h>
+#endif
+
+// Some LLVM programs such as bugpoint produce core files as a normal part of
+// their operation. To prevent the disk from filling up, this function
+// does what's necessary to prevent their generation.
+void Process::PreventCoreFiles() {
+#if HAVE_SETRLIMIT
+ struct rlimit rlim;
+ rlim.rlim_cur = rlim.rlim_max = 0;
+ setrlimit(RLIMIT_CORE, &rlim);
+#endif
+
+#ifdef HAVE_MACH_MACH_H
+ // Disable crash reporting on Mac OS X 10.0-10.4
+
+ // get information about the original set of exception ports for the task
+ mach_msg_type_number_t Count = 0;
+ exception_mask_t OriginalMasks[EXC_TYPES_COUNT];
+ exception_port_t OriginalPorts[EXC_TYPES_COUNT];
+ exception_behavior_t OriginalBehaviors[EXC_TYPES_COUNT];
+ thread_state_flavor_t OriginalFlavors[EXC_TYPES_COUNT];
+ kern_return_t err =
+ task_get_exception_ports(mach_task_self(), EXC_MASK_ALL, OriginalMasks,
+ &Count, OriginalPorts, OriginalBehaviors,
+ OriginalFlavors);
+ if (err == KERN_SUCCESS) {
+ // replace each with MACH_PORT_NULL.
+ for (unsigned i = 0; i != Count; ++i)
+ task_set_exception_ports(mach_task_self(), OriginalMasks[i],
+ MACH_PORT_NULL, OriginalBehaviors[i],
+ OriginalFlavors[i]);
+ }
+
+ // Disable crash reporting on Mac OS X 10.5
+ signal(SIGABRT, _exit);
+ signal(SIGILL, _exit);
+ signal(SIGFPE, _exit);
+ signal(SIGSEGV, _exit);
+ signal(SIGBUS, _exit);
+#endif
+}
+
+bool Process::StandardInIsUserInput() {
+ return FileDescriptorIsDisplayed(STDIN_FILENO);
+}
+
+bool Process::StandardOutIsDisplayed() {
+ return FileDescriptorIsDisplayed(STDOUT_FILENO);
+}
+
+bool Process::StandardErrIsDisplayed() {
+ return FileDescriptorIsDisplayed(STDERR_FILENO);
+}
+
+bool Process::FileDescriptorIsDisplayed(int fd) {
+#if HAVE_ISATTY
+ return isatty(fd);
+#else
+ // If we don't have isatty, just return false.
+ return false;
+#endif
+}
+
+static unsigned getColumns(int FileID) {
+ // If COLUMNS is defined in the environment, wrap to that many columns.
+ if (const char *ColumnsStr = std::getenv("COLUMNS")) {
+ int Columns = std::atoi(ColumnsStr);
+ if (Columns > 0)
+ return Columns;
+ }
+
+ unsigned Columns = 0;
+
+#if defined(HAVE_SYS_IOCTL_H) && defined(HAVE_TERMIOS_H)
+ // Try to determine the width of the terminal.
+ struct winsize ws;
+ if (ioctl(FileID, TIOCGWINSZ, &ws) == 0)
+ Columns = ws.ws_col;
+#endif
+
+ return Columns;
+}
+
+unsigned Process::StandardOutColumns() {
+ if (!StandardOutIsDisplayed())
+ return 0;
+
+ return getColumns(1);
+}
+
+unsigned Process::StandardErrColumns() {
+ if (!StandardErrIsDisplayed())
+ return 0;
+
+ return getColumns(2);
+}
+
+static bool terminalHasColors() {
+ if (const char *term = std::getenv("TERM")) {
+ // Most modern terminals support ANSI escape sequences for colors.
+ // We could check terminfo, or have a list of known terms that support
+ // colors, but that would be overkill.
+ // The user can always ask for no colors by setting TERM to dumb, or
+ // using a commandline flag.
+ return strcmp(term, "dumb") != 0;
+ }
+ return false;
+}
+
+bool Process::StandardOutHasColors() {
+ if (!StandardOutIsDisplayed())
+ return false;
+ return terminalHasColors();
+}
+
+bool Process::StandardErrHasColors() {
+ if (!StandardErrIsDisplayed())
+ return false;
+ return terminalHasColors();
+}
+
+bool Process::ColorNeedsFlush() {
+ // No, we use ANSI escape sequences.
+ return false;
+}
+
+#define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m"
+
+#define ALLCOLORS(FGBG,BOLD) {\
+ COLOR(FGBG, "0", BOLD),\
+ COLOR(FGBG, "1", BOLD),\
+ COLOR(FGBG, "2", BOLD),\
+ COLOR(FGBG, "3", BOLD),\
+ COLOR(FGBG, "4", BOLD),\
+ COLOR(FGBG, "5", BOLD),\
+ COLOR(FGBG, "6", BOLD),\
+ COLOR(FGBG, "7", BOLD)\
+ }
+
+static const char colorcodes[2][2][8][10] = {
+ { ALLCOLORS("3",""), ALLCOLORS("3","1;") },
+ { ALLCOLORS("4",""), ALLCOLORS("4","1;") }
+};
+
+const char *Process::OutputColor(char code, bool bold, bool bg) {
+ return colorcodes[bg?1:0][bold?1:0][code&7];
+}
+
+const char *Process::OutputBold(bool bg) {
+ return "\033[1m";
+}
+
+const char *Process::ResetColor() {
+ return "\033[0m";
+}
diff --git a/lib/Support/Unix/Program.inc b/lib/Support/Unix/Program.inc
new file mode 100644
index 0000000000..e06f80ba83
--- /dev/null
+++ b/lib/Support/Unix/Program.inc
@@ -0,0 +1,422 @@
+//===- llvm/System/Unix/Program.cpp -----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Unix specific portion of the Program class.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only generic UNIX code that
+//=== is guaranteed to work on *all* UNIX variants.
+//===----------------------------------------------------------------------===//
+
+#include <llvm/Config/config.h>
+#include "Unix.h"
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+#if HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_POSIX_SPAWN
+#include <spawn.h>
+#if !defined(__APPLE__)
+ extern char **environ;
+#else
+#include <crt_externs.h> // _NSGetEnviron
+#endif
+#endif
+
+namespace llvm {
+using namespace sys;
+
+Program::Program() : Data_(0) {}
+
+Program::~Program() {}
+
+unsigned Program::GetPid() const {
+ uint64_t pid = reinterpret_cast<uint64_t>(Data_);
+ return static_cast<unsigned>(pid);
+}
+
+// This function just uses the PATH environment variable to find the program.
+Path
+Program::FindProgramByName(const std::string& progName) {
+
+ // Check some degenerate cases
+ if (progName.length() == 0) // no program
+ return Path();
+ Path temp;
+ if (!temp.set(progName)) // invalid name
+ return Path();
+ // Use the given path verbatim if it contains any slashes; this matches
+ // the behavior of sh(1) and friends.
+ if (progName.find('/') != std::string::npos)
+ return temp;
+
+ // At this point, the file name is valid and does not contain slashes. Search
+ // for it through the directories specified in the PATH environment variable.
+
+ // Get the path. If its empty, we can't do anything to find it.
+ const char *PathStr = getenv("PATH");
+ if (PathStr == 0)
+ return Path();
+
+ // Now we have a colon separated list of directories to search; try them.
+ size_t PathLen = strlen(PathStr);
+ while (PathLen) {
+ // Find the first colon...
+ const char *Colon = std::find(PathStr, PathStr+PathLen, ':');
+
+ // Check to see if this first directory contains the executable...
+ Path FilePath;
+ if (FilePath.set(std::string(PathStr,Colon))) {
+ FilePath.appendComponent(progName);
+ if (FilePath.canExecute())
+ return FilePath; // Found the executable!
+ }
+
+ // Nope it wasn't in this directory, check the next path in the list!
+ PathLen -= Colon-PathStr;
+ PathStr = Colon;
+
+ // Advance past duplicate colons
+ while (*PathStr == ':') {
+ PathStr++;
+ PathLen--;
+ }
+ }
+ return Path();
+}
+
+static bool RedirectIO(const Path *Path, int FD, std::string* ErrMsg) {
+ if (Path == 0) // Noop
+ return false;
+ const char *File;
+ if (Path->isEmpty())
+ // Redirect empty paths to /dev/null
+ File = "/dev/null";
+ else
+ File = Path->c_str();
+
+ // Open the file
+ int InFD = open(File, FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666);
+ if (InFD == -1) {
+ MakeErrMsg(ErrMsg, "Cannot open file '" + std::string(File) + "' for "
+ + (FD == 0 ? "input" : "output"));
+ return true;
+ }
+
+ // Install it as the requested FD
+ if (dup2(InFD, FD) == -1) {
+ MakeErrMsg(ErrMsg, "Cannot dup2");
+ close(InFD);
+ return true;
+ }
+ close(InFD); // Close the original FD
+ return false;
+}
+
+#ifdef HAVE_POSIX_SPAWN
+static bool RedirectIO_PS(const Path *Path, int FD, std::string *ErrMsg,
+ posix_spawn_file_actions_t &FileActions) {
+ if (Path == 0) // Noop
+ return false;
+ const char *File;
+ if (Path->isEmpty())
+ // Redirect empty paths to /dev/null
+ File = "/dev/null";
+ else
+ File = Path->c_str();
+
+ if (int Err = posix_spawn_file_actions_addopen(&FileActions, FD,
+ File, FD == 0 ? O_RDONLY : O_WRONLY|O_CREAT, 0666))
+ return MakeErrMsg(ErrMsg, "Cannot dup2", Err);
+ return false;
+}
+#endif
+
+static void TimeOutHandler(int Sig) {
+}
+
+static void SetMemoryLimits (unsigned size)
+{
+#if HAVE_SYS_RESOURCE_H && HAVE_GETRLIMIT && HAVE_SETRLIMIT
+ struct rlimit r;
+ __typeof__ (r.rlim_cur) limit = (__typeof__ (r.rlim_cur)) (size) * 1048576;
+
+ // Heap size
+ getrlimit (RLIMIT_DATA, &r);
+ r.rlim_cur = limit;
+ setrlimit (RLIMIT_DATA, &r);
+#ifdef RLIMIT_RSS
+ // Resident set size.
+ getrlimit (RLIMIT_RSS, &r);
+ r.rlim_cur = limit;
+ setrlimit (RLIMIT_RSS, &r);
+#endif
+#ifdef RLIMIT_AS // e.g. NetBSD doesn't have it.
+ // Virtual memory.
+ getrlimit (RLIMIT_AS, &r);
+ r.rlim_cur = limit;
+ setrlimit (RLIMIT_AS, &r);
+#endif
+#endif
+}
+
+bool
+Program::Execute(const Path &path, const char **args, const char **envp,
+ const Path **redirects, unsigned memoryLimit,
+ std::string *ErrMsg) {
+ // If this OS has posix_spawn and there is no memory limit being implied, use
+ // posix_spawn. It is more efficient than fork/exec.
+#ifdef HAVE_POSIX_SPAWN
+ if (memoryLimit == 0) {
+ posix_spawn_file_actions_t FileActions;
+ posix_spawn_file_actions_init(&FileActions);
+
+ if (redirects) {
+ // Redirect stdin/stdout.
+ if (RedirectIO_PS(redirects[0], 0, ErrMsg, FileActions) ||
+ RedirectIO_PS(redirects[1], 1, ErrMsg, FileActions))
+ return false;
+ if (redirects[1] == 0 || redirects[2] == 0 ||
+ *redirects[1] != *redirects[2]) {
+ // Just redirect stderr
+ if (RedirectIO_PS(redirects[2], 2, ErrMsg, FileActions)) return false;
+ } else {
+ // If stdout and stderr should go to the same place, redirect stderr
+ // to the FD already open for stdout.
+ if (int Err = posix_spawn_file_actions_adddup2(&FileActions, 1, 2))
+ return !MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout", Err);
+ }
+ }
+
+ if (!envp)
+#if !defined(__APPLE__)
+ envp = const_cast<const char **>(environ);
+#else
+ // environ is missing in dylibs.
+ envp = const_cast<const char **>(*_NSGetEnviron());
+#endif
+
+ // Explicitly initialized to prevent what appears to be a valgrind false
+ // positive.
+ pid_t PID = 0;
+ int Err = posix_spawn(&PID, path.c_str(), &FileActions, /*attrp*/0,
+ const_cast<char **>(args), const_cast<char **>(envp));
+
+ posix_spawn_file_actions_destroy(&FileActions);
+
+ if (Err)
+ return !MakeErrMsg(ErrMsg, "posix_spawn failed", Err);
+
+ Data_ = reinterpret_cast<void*>(PID);
+ return true;
+ }
+#endif
+
+ // Create a child process.
+ int child = fork();
+ switch (child) {
+ // An error occured: Return to the caller.
+ case -1:
+ MakeErrMsg(ErrMsg, "Couldn't fork");
+ return false;
+
+ // Child process: Execute the program.
+ case 0: {
+ // Redirect file descriptors...
+ if (redirects) {
+ // Redirect stdin
+ if (RedirectIO(redirects[0], 0, ErrMsg)) { return false; }
+ // Redirect stdout
+ if (RedirectIO(redirects[1], 1, ErrMsg)) { return false; }
+ if (redirects[1] && redirects[2] &&
+ *(redirects[1]) == *(redirects[2])) {
+ // If stdout and stderr should go to the same place, redirect stderr
+ // to the FD already open for stdout.
+ if (-1 == dup2(1,2)) {
+ MakeErrMsg(ErrMsg, "Can't redirect stderr to stdout");
+ return false;
+ }
+ } else {
+ // Just redirect stderr
+ if (RedirectIO(redirects[2], 2, ErrMsg)) { return false; }
+ }
+ }
+
+ // Set memory limits
+ if (memoryLimit!=0) {
+ SetMemoryLimits(memoryLimit);
+ }
+
+ // Execute!
+ if (envp != 0)
+ execve(path.c_str(),
+ const_cast<char **>(args),
+ const_cast<char **>(envp));
+ else
+ execv(path.c_str(),
+ const_cast<char **>(args));
+ // If the execve() failed, we should exit. Follow Unix protocol and
+ // return 127 if the executable was not found, and 126 otherwise.
+ // Use _exit rather than exit so that atexit functions and static
+ // object destructors cloned from the parent process aren't
+ // redundantly run, and so that any data buffered in stdio buffers
+ // cloned from the parent aren't redundantly written out.
+ _exit(errno == ENOENT ? 127 : 126);
+ }
+
+ // Parent process: Break out of the switch to do our processing.
+ default:
+ break;
+ }
+
+ Data_ = reinterpret_cast<void*>(child);
+
+ return true;
+}
+
+int
+Program::Wait(const sys::Path &path,
+ unsigned secondsToWait,
+ std::string* ErrMsg)
+{
+#ifdef HAVE_SYS_WAIT_H
+ struct sigaction Act, Old;
+
+ if (Data_ == 0) {
+ MakeErrMsg(ErrMsg, "Process not started!");
+ return -1;
+ }
+
+ // Install a timeout handler. The handler itself does nothing, but the simple
+ // fact of having a handler at all causes the wait below to return with EINTR,
+ // unlike if we used SIG_IGN.
+ if (secondsToWait) {
+ memset(&Act, 0, sizeof(Act));
+ Act.sa_handler = TimeOutHandler;
+ sigemptyset(&Act.sa_mask);
+ sigaction(SIGALRM, &Act, &Old);
+ alarm(secondsToWait);
+ }
+
+ // Parent process: Wait for the child process to terminate.
+ int status;
+ uint64_t pid = reinterpret_cast<uint64_t>(Data_);
+ pid_t child = static_cast<pid_t>(pid);
+ while (waitpid(pid, &status, 0) != child)
+ if (secondsToWait && errno == EINTR) {
+ // Kill the child.
+ kill(child, SIGKILL);
+
+ // Turn off the alarm and restore the signal handler
+ alarm(0);
+ sigaction(SIGALRM, &Old, 0);
+
+ // Wait for child to die
+ if (wait(&status) != child)
+ MakeErrMsg(ErrMsg, "Child timed out but wouldn't die");
+ else
+ MakeErrMsg(ErrMsg, "Child timed out", 0);
+
+ return -1; // Timeout detected
+ } else if (errno != EINTR) {
+ MakeErrMsg(ErrMsg, "Error waiting for child process");
+ return -1;
+ }
+
+ // We exited normally without timeout, so turn off the timer.
+ if (secondsToWait) {
+ alarm(0);
+ sigaction(SIGALRM, &Old, 0);
+ }
+
+ // Return the proper exit status. Detect error conditions
+ // so we can return -1 for them and set ErrMsg informatively.
+ int result = 0;
+ if (WIFEXITED(status)) {
+ result = WEXITSTATUS(status);
+#ifdef HAVE_POSIX_SPAWN
+ // The posix_spawn child process returns 127 on any kind of error.
+ // Following the POSIX convention for command-line tools (which posix_spawn
+ // itself apparently does not), check to see if the failure was due to some
+ // reason other than the file not existing, and return 126 in this case.
+ if (result == 127 && path.exists())
+ result = 126;
+#endif
+ if (result == 127) {
+ if (ErrMsg)
+ *ErrMsg = llvm::sys::StrError(ENOENT);
+ return -1;
+ }
+ if (result == 126) {
+ if (ErrMsg)
+ *ErrMsg = "Program could not be executed";
+ return -1;
+ }
+ } else if (WIFSIGNALED(status)) {
+ if (ErrMsg) {
+ *ErrMsg = strsignal(WTERMSIG(status));
+#ifdef WCOREDUMP
+ if (WCOREDUMP(status))
+ *ErrMsg += " (core dumped)";
+#endif
+ }
+ return -1;
+ }
+ return result;
+#else
+ if (ErrMsg)
+ *ErrMsg = "Program::Wait is not implemented on this platform yet!";
+ return -1;
+#endif
+}
+
+bool
+Program::Kill(std::string* ErrMsg) {
+ if (Data_ == 0) {
+ MakeErrMsg(ErrMsg, "Process not started!");
+ return true;
+ }
+
+ uint64_t pid64 = reinterpret_cast<uint64_t>(Data_);
+ pid_t pid = static_cast<pid_t>(pid64);
+
+ if (kill(pid, SIGKILL) != 0) {
+ MakeErrMsg(ErrMsg, "The process couldn't be killed!");
+ return true;
+ }
+
+ return false;
+}
+
+bool Program::ChangeStdinToBinary(){
+ // Do nothing, as Unix doesn't differentiate between text and binary.
+ return false;
+}
+
+bool Program::ChangeStdoutToBinary(){
+ // Do nothing, as Unix doesn't differentiate between text and binary.
+ return false;
+}
+
+bool Program::ChangeStderrToBinary(){
+ // Do nothing, as Unix doesn't differentiate between text and binary.
+ return false;
+}
+
+}
diff --git a/lib/Support/Unix/README.txt b/lib/Support/Unix/README.txt
new file mode 100644
index 0000000000..3d547c2990
--- /dev/null
+++ b/lib/Support/Unix/README.txt
@@ -0,0 +1,16 @@
+llvm/lib/Support/Unix README
+===========================
+
+This directory provides implementations of the lib/System classes that
+are common to two or more variants of UNIX. For example, the directory
+structure underneath this directory could look like this:
+
+Unix - only code that is truly generic to all UNIX platforms
+ Posix - code that is specific to Posix variants of UNIX
+ SUS - code that is specific to the Single Unix Specification
+ SysV - code that is specific to System V variants of UNIX
+
+As a rule, only those directories actually needing to be created should be
+created. Also, further subdirectories could be created to reflect versions of
+the various standards. For example, under SUS there could be v1, v2, and v3
+subdirectories to reflect the three major versions of SUS.
diff --git a/lib/Support/Unix/RWMutex.inc b/lib/Support/Unix/RWMutex.inc
new file mode 100644
index 0000000000..ee9853e5af
--- /dev/null
+++ b/lib/Support/Unix/RWMutex.inc
@@ -0,0 +1,43 @@
+//= llvm/System/Unix/RWMutex.inc - Unix Reader/Writer Mutual Exclusion Lock =//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Unix specific (non-pthread) RWMutex class.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only generic UNIX code that
+//=== is guaranteed to work on *all* UNIX variants.
+//===----------------------------------------------------------------------===//
+
+namespace llvm {
+
+using namespace sys;
+
+RWMutexImpl::RWMutexImpl() { }
+
+RWMutexImpl::~RWMutexImpl() { }
+
+bool RWMutexImpl::reader_acquire() {
+ return true;
+}
+
+bool RWMutexImpl::reader_release() {
+ return true;
+}
+
+bool RWMutexImpl::writer_acquire() {
+ return true;
+}
+
+bool RWMutexImpl::writer_release() {
+ return true;
+}
+
+}
diff --git a/lib/Support/Unix/Signals.inc b/lib/Support/Unix/Signals.inc
new file mode 100644
index 0000000000..0a61759155
--- /dev/null
+++ b/lib/Support/Unix/Signals.inc
@@ -0,0 +1,303 @@
+//===- Signals.cpp - Generic Unix Signals 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 defines some helpful functions for dealing with the possibility of
+// Unix signals occuring while your program is running.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Unix.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Mutex.h"
+#include <vector>
+#include <algorithm>
+#if HAVE_EXECINFO_H
+# include <execinfo.h> // For backtrace().
+#endif
+#if HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_DLFCN_H && __GNUG__
+#include <dlfcn.h>
+#include <cxxabi.h>
+#endif
+using namespace llvm;
+
+static RETSIGTYPE SignalHandler(int Sig); // defined below.
+
+static SmartMutex<true> SignalsMutex;
+
+/// InterruptFunction - The function to call if ctrl-c is pressed.
+static void (*InterruptFunction)() = 0;
+
+static std::vector<sys::Path> FilesToRemove;
+static std::vector<std::pair<void(*)(void*), void*> > CallBacksToRun;
+
+// IntSigs - Signals that may interrupt the program at any time.
+static const int IntSigs[] = {
+ SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGTERM, SIGUSR1, SIGUSR2
+};
+static const int *const IntSigsEnd =
+ IntSigs + sizeof(IntSigs) / sizeof(IntSigs[0]);
+
+// KillSigs - Signals that are synchronous with the program that will cause it
+// to die.
+static const int KillSigs[] = {
+ SIGILL, SIGTRAP, SIGABRT, SIGFPE, SIGBUS, SIGSEGV
+#ifdef SIGSYS
+ , SIGSYS
+#endif
+#ifdef SIGXCPU
+ , SIGXCPU
+#endif
+#ifdef SIGXFSZ
+ , SIGXFSZ
+#endif
+#ifdef SIGEMT
+ , SIGEMT
+#endif
+};
+static const int *const KillSigsEnd =
+ KillSigs + sizeof(KillSigs) / sizeof(KillSigs[0]);
+
+static unsigned NumRegisteredSignals = 0;
+static struct {
+ struct sigaction SA;
+ int SigNo;
+} RegisteredSignalInfo[(sizeof(IntSigs)+sizeof(KillSigs))/sizeof(KillSigs[0])];
+
+
+static void RegisterHandler(int Signal) {
+ assert(NumRegisteredSignals <
+ sizeof(RegisteredSignalInfo)/sizeof(RegisteredSignalInfo[0]) &&
+ "Out of space for signal handlers!");
+
+ struct sigaction NewHandler;
+
+ NewHandler.sa_handler = SignalHandler;
+ NewHandler.sa_flags = SA_NODEFER|SA_RESETHAND;
+ sigemptyset(&NewHandler.sa_mask);
+
+ // Install the new handler, save the old one in RegisteredSignalInfo.
+ sigaction(Signal, &NewHandler,
+ &RegisteredSignalInfo[NumRegisteredSignals].SA);
+ RegisteredSignalInfo[NumRegisteredSignals].SigNo = Signal;
+ ++NumRegisteredSignals;
+}
+
+static void RegisterHandlers() {
+ // If the handlers are already registered, we're done.
+ if (NumRegisteredSignals != 0) return;
+
+ std::for_each(IntSigs, IntSigsEnd, RegisterHandler);
+ std::for_each(KillSigs, KillSigsEnd, RegisterHandler);
+}
+
+static void UnregisterHandlers() {
+ // Restore all of the signal handlers to how they were before we showed up.
+ for (unsigned i = 0, e = NumRegisteredSignals; i != e; ++i)
+ sigaction(RegisteredSignalInfo[i].SigNo,
+ &RegisteredSignalInfo[i].SA, 0);
+ NumRegisteredSignals = 0;
+}
+
+
+/// RemoveFilesToRemove - Process the FilesToRemove list. This function
+/// should be called with the SignalsMutex lock held.
+static void RemoveFilesToRemove() {
+ while (!FilesToRemove.empty()) {
+ FilesToRemove.back().eraseFromDisk(true);
+ FilesToRemove.pop_back();
+ }
+}
+
+// SignalHandler - The signal handler that runs.
+static RETSIGTYPE SignalHandler(int Sig) {
+ // Restore the signal behavior to default, so that the program actually
+ // crashes when we return and the signal reissues. This also ensures that if
+ // we crash in our signal handler that the program will terminate immediately
+ // instead of recursing in the signal handler.
+ UnregisterHandlers();
+
+ // Unmask all potentially blocked kill signals.
+ sigset_t SigMask;
+ sigfillset(&SigMask);
+ sigprocmask(SIG_UNBLOCK, &SigMask, 0);
+
+ SignalsMutex.acquire();
+ RemoveFilesToRemove();
+
+ if (std::find(IntSigs, IntSigsEnd, Sig) != IntSigsEnd) {
+ if (InterruptFunction) {
+ void (*IF)() = InterruptFunction;
+ SignalsMutex.release();
+ InterruptFunction = 0;
+ IF(); // run the interrupt function.
+ return;
+ }
+
+ SignalsMutex.release();
+ raise(Sig); // Execute the default handler.
+ return;
+ }
+
+ SignalsMutex.release();
+
+ // Otherwise if it is a fault (like SEGV) run any handler.
+ for (unsigned i = 0, e = CallBacksToRun.size(); i != e; ++i)
+ CallBacksToRun[i].first(CallBacksToRun[i].second);
+}
+
+void llvm::sys::RunInterruptHandlers() {
+ SignalsMutex.acquire();
+ RemoveFilesToRemove();
+ SignalsMutex.release();
+}
+
+void llvm::sys::SetInterruptFunction(void (*IF)()) {
+ SignalsMutex.acquire();
+ InterruptFunction = IF;
+ SignalsMutex.release();
+ RegisterHandlers();
+}
+
+// RemoveFileOnSignal - The public API
+bool llvm::sys::RemoveFileOnSignal(const sys::Path &Filename,
+ std::string* ErrMsg) {
+ SignalsMutex.acquire();
+ FilesToRemove.push_back(Filename);
+
+ SignalsMutex.release();
+
+ RegisterHandlers();
+ return false;
+}
+
+// DontRemoveFileOnSignal - The public API
+void llvm::sys::DontRemoveFileOnSignal(const sys::Path &Filename) {
+ SignalsMutex.acquire();
+ std::vector<sys::Path>::reverse_iterator I =
+ std::find(FilesToRemove.rbegin(), FilesToRemove.rend(), Filename);
+ if (I != FilesToRemove.rend())
+ FilesToRemove.erase(I.base()-1);
+ SignalsMutex.release();
+}
+
+/// AddSignalHandler - Add a function to be called when a signal is delivered
+/// to the process. The handler can have a cookie passed to it to identify
+/// what instance of the handler it is.
+void llvm::sys::AddSignalHandler(void (*FnPtr)(void *), void *Cookie) {
+ CallBacksToRun.push_back(std::make_pair(FnPtr, Cookie));
+ RegisterHandlers();
+}
+
+
+// PrintStackTrace - In the case of a program crash or fault, print out a stack
+// trace so that the user has an indication of why and where we died.
+//
+// On glibc systems we have the 'backtrace' function, which works nicely, but
+// doesn't demangle symbols.
+static void PrintStackTrace(void *) {
+#ifdef HAVE_BACKTRACE
+ static void* StackTrace[256];
+ // Use backtrace() to output a backtrace on Linux systems with glibc.
+ int depth = backtrace(StackTrace,
+ static_cast<int>(array_lengthof(StackTrace)));
+#if HAVE_DLFCN_H && __GNUG__
+ int width = 0;
+ for (int i = 0; i < depth; ++i) {
+ Dl_info dlinfo;
+ dladdr(StackTrace[i], &dlinfo);
+ const char* name = strrchr(dlinfo.dli_fname, '/');
+
+ int nwidth;
+ if (name == NULL) nwidth = strlen(dlinfo.dli_fname);
+ else nwidth = strlen(name) - 1;
+
+ if (nwidth > width) width = nwidth;
+ }
+
+ for (int i = 0; i < depth; ++i) {
+ Dl_info dlinfo;
+ dladdr(StackTrace[i], &dlinfo);
+
+ fprintf(stderr, "%-2d", i);
+
+ const char* name = strrchr(dlinfo.dli_fname, '/');
+ if (name == NULL) fprintf(stderr, " %-*s", width, dlinfo.dli_fname);
+ else fprintf(stderr, " %-*s", width, name+1);
+
+ fprintf(stderr, " %#0*lx",
+ (int)(sizeof(void*) * 2) + 2, (unsigned long)StackTrace[i]);
+
+ if (dlinfo.dli_sname != NULL) {
+ int res;
+ fputc(' ', stderr);
+ char* d = abi::__cxa_demangle(dlinfo.dli_sname, NULL, NULL, &res);
+ if (d == NULL) fputs(dlinfo.dli_sname, stderr);
+ else fputs(d, stderr);
+ free(d);
+
+ fprintf(stderr, " + %tu",(char*)StackTrace[i]-(char*)dlinfo.dli_saddr);
+ }
+ fputc('\n', stderr);
+ }
+#else
+ backtrace_symbols_fd(StackTrace, depth, STDERR_FILENO);
+#endif
+#endif
+}
+
+/// PrintStackTraceOnErrorSignal - When an error signal (such as SIBABRT or
+/// SIGSEGV) is delivered to the process, print a stack trace and then exit.
+void llvm::sys::PrintStackTraceOnErrorSignal() {
+ AddSignalHandler(PrintStackTrace, 0);
+}
+
+
+/***/
+
+// On Darwin, raise sends a signal to the main thread instead of the current
+// thread. This has the unfortunate effect that assert() and abort() will end up
+// bypassing our crash recovery attempts. We work around this for anything in
+// the same linkage unit by just defining our own versions of the assert handler
+// and abort.
+
+#ifdef __APPLE__
+
+int raise(int sig) {
+ return pthread_kill(pthread_self(), sig);
+}
+
+void __assert_rtn(const char *func,
+ const char *file,
+ int line,
+ const char *expr) {
+ if (func)
+ fprintf(stderr, "Assertion failed: (%s), function %s, file %s, line %d.\n",
+ expr, func, file, line);
+ else
+ fprintf(stderr, "Assertion failed: (%s), file %s, line %d.\n",
+ expr, file, line);
+ abort();
+}
+
+#include <signal.h>
+#include <pthread.h>
+
+void abort() {
+ raise(SIGABRT);
+ usleep(1000);
+ __builtin_trap();
+}
+
+#endif
diff --git a/lib/Support/Unix/ThreadLocal.inc b/lib/Support/Unix/ThreadLocal.inc
new file mode 100644
index 0000000000..f009b72f10
--- /dev/null
+++ b/lib/Support/Unix/ThreadLocal.inc
@@ -0,0 +1,26 @@
+//=== llvm/System/Unix/ThreadLocal.inc - Unix Thread Local Data -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Unix specific (non-pthread) ThreadLocal class.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only generic UNIX code that
+//=== is guaranteed to work on *all* UNIX variants.
+//===----------------------------------------------------------------------===//
+
+namespace llvm {
+using namespace sys;
+ThreadLocalImpl::ThreadLocalImpl() { }
+ThreadLocalImpl::~ThreadLocalImpl() { }
+void ThreadLocalImpl::setInstance(const void* d) { data = const_cast<void*>(d);}
+const void* ThreadLocalImpl::getInstance() { return data; }
+void ThreadLocalImpl::removeInstance() { setInstance(0); }
+}
diff --git a/lib/Support/Unix/TimeValue.inc b/lib/Support/Unix/TimeValue.inc
new file mode 100644
index 0000000000..5cf5a9d44e
--- /dev/null
+++ b/lib/Support/Unix/TimeValue.inc
@@ -0,0 +1,56 @@
+//===- Unix/TimeValue.cpp - Unix TimeValue 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 implements the Unix specific portion of the TimeValue class.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only generic UNIX code that
+//=== is guaranteed to work on *all* UNIX variants.
+//===----------------------------------------------------------------------===//
+
+#include "Unix.h"
+
+namespace llvm {
+ using namespace sys;
+
+std::string TimeValue::str() const {
+ char buffer[32];
+
+ time_t ourTime = time_t(this->toEpochTime());
+#ifdef __hpux
+// note that the following line needs -D_REENTRANT on HP-UX to be picked up
+ asctime_r(localtime(&ourTime), buffer);
+#else
+ ::asctime_r(::localtime(&ourTime), buffer);
+#endif
+
+ std::string result(buffer);
+ return result.substr(0,24);
+}
+
+TimeValue TimeValue::now() {
+ struct timeval the_time;
+ timerclear(&the_time);
+ if (0 != ::gettimeofday(&the_time,0)) {
+ // This is *really* unlikely to occur because the only gettimeofday
+ // errors concern the timezone parameter which we're passing in as 0.
+ // In the unlikely case it does happen, just return MinTime, no error
+ // message needed.
+ return MinTime;
+ }
+
+ return TimeValue(
+ static_cast<TimeValue::SecondsType>( the_time.tv_sec + PosixZeroTime.seconds_ ),
+ static_cast<TimeValue::NanoSecondsType>( the_time.tv_usec *
+ NANOSECONDS_PER_MICROSECOND ) );
+}
+
+}
diff --git a/lib/Support/Unix/Unix.h b/lib/Support/Unix/Unix.h
new file mode 100644
index 0000000000..c15866f3d9
--- /dev/null
+++ b/lib/Support/Unix/Unix.h
@@ -0,0 +1,87 @@
+//===- llvm/System/Unix/Unix.h - Common Unix Include File -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines things specific to Unix implementations.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SYSTEM_UNIX_UNIX_H
+#define LLVM_SYSTEM_UNIX_UNIX_H
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only generic UNIX code that
+//=== is guaranteed to work on all UNIX variants.
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Config/config.h" // Get autoconf configuration settings
+#include "llvm/System/Errno.h"
+#include <cstdlib>
+#include <cstdio>
+#include <cstring>
+#include <cerrno>
+#include <string>
+#include <algorithm>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#ifdef HAVE_ASSERT_H
+#include <assert.h>
+#endif
+
+#ifdef TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+
+#ifdef HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+#endif
+
+#ifndef WEXITSTATUS
+# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
+#endif
+
+#ifndef WIFEXITED
+# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+#endif
+
+/// This function builds an error message into \p ErrMsg using the \p prefix
+/// string and the Unix error number given by \p errnum. If errnum is -1, the
+/// default then the value of errno is used.
+/// @brief Make an error message
+///
+/// If the error number can be converted to a string, it will be
+/// separated from prefix by ": ".
+static inline bool MakeErrMsg(
+ std::string* ErrMsg, const std::string& prefix, int errnum = -1) {
+ if (!ErrMsg)
+ return true;
+ if (errnum == -1)
+ errnum = errno;
+ *ErrMsg = prefix + ": " + llvm::sys::StrError(errnum);
+ return true;
+}
+
+#endif
diff --git a/lib/Support/Unix/system_error.inc b/lib/Support/Unix/system_error.inc
new file mode 100644
index 0000000000..a382214877
--- /dev/null
+++ b/lib/Support/Unix/system_error.inc
@@ -0,0 +1,34 @@
+//===- llvm/System/Unix/system_error.inc - Unix error_code ------*- 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 Unix specific implementation of the error_code
+// and error_condition classes.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only generic UNIX code that
+//=== is guaranteed to work on *all* UNIX variants.
+//===----------------------------------------------------------------------===//
+
+using namespace llvm;
+
+std::string
+_system_error_category::message(int ev) const {
+ return _do_message::message(ev);
+}
+
+error_condition
+_system_error_category::default_error_condition(int ev) const {
+#ifdef ELAST
+ if (ev > ELAST)
+ return error_condition(ev, system_category());
+#endif // ELAST
+ return error_condition(ev, generic_category());
+}
diff --git a/lib/Support/Valgrind.cpp b/lib/Support/Valgrind.cpp
new file mode 100644
index 0000000000..703448524e
--- /dev/null
+++ b/lib/Support/Valgrind.cpp
@@ -0,0 +1,54 @@
+//===-- Valgrind.cpp - Implement Valgrind communication ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines Valgrind communication methods, if HAVE_VALGRIND_VALGRIND_H is
+// defined. If we have valgrind.h but valgrind isn't running, its macros are
+// no-ops.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Valgrind.h"
+#include "llvm/Config/config.h"
+
+#if HAVE_VALGRIND_VALGRIND_H
+#include <valgrind/valgrind.h>
+
+static bool InitNotUnderValgrind() {
+ return !RUNNING_ON_VALGRIND;
+}
+
+// This bool is negated from what we'd expect because code may run before it
+// gets initialized. If that happens, it will appear to be 0 (false), and we
+// want that to cause the rest of the code in this file to run the
+// Valgrind-provided macros.
+static const bool NotUnderValgrind = InitNotUnderValgrind();
+
+bool llvm::sys::RunningOnValgrind() {
+ if (NotUnderValgrind)
+ return false;
+ return RUNNING_ON_VALGRIND;
+}
+
+void llvm::sys::ValgrindDiscardTranslations(const void *Addr, size_t Len) {
+ if (NotUnderValgrind)
+ return;
+
+ VALGRIND_DISCARD_TRANSLATIONS(Addr, Len);
+}
+
+#else // !HAVE_VALGRIND_VALGRIND_H
+
+bool llvm::sys::RunningOnValgrind() {
+ return false;
+}
+
+void llvm::sys::ValgrindDiscardTranslations(const void *Addr, size_t Len) {
+}
+
+#endif // !HAVE_VALGRIND_VALGRIND_H
diff --git a/lib/Support/Windows/Alarm.inc b/lib/Support/Windows/Alarm.inc
new file mode 100644
index 0000000000..e0d00a0142
--- /dev/null
+++ b/lib/Support/Windows/Alarm.inc
@@ -0,0 +1,43 @@
+//===-- Alarm.inc - Implement Win32 Alarm Support ---------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Win32 Alarm support.
+//
+//===----------------------------------------------------------------------===//
+
+#include <cassert>
+using namespace llvm;
+
+/// NestedSOI - Sanity check. Alarms cannot be nested or run in parallel.
+/// This ensures that they never do.
+static bool NestedSOI = false;
+
+void sys::SetupAlarm(unsigned seconds) {
+ assert(!NestedSOI && "sys::SetupAlarm calls cannot be nested!");
+ NestedSOI = true;
+ // FIXME: Implement for Win32
+}
+
+void sys::TerminateAlarm() {
+ assert(NestedSOI && "sys::TerminateAlarm called without sys::SetupAlarm!");
+ // FIXME: Implement for Win32
+ NestedSOI = false;
+}
+
+int sys::AlarmStatus() {
+ // FIXME: Implement for Win32
+ return 0;
+}
+
+// Don't pull in all of the Windows headers.
+extern "C" void __stdcall Sleep(unsigned long);
+
+void sys::Sleep(unsigned n) {
+ ::Sleep(n*1000);
+}
diff --git a/lib/Support/Windows/DynamicLibrary.inc b/lib/Support/Windows/DynamicLibrary.inc
new file mode 100644
index 0000000000..5fad37a1fe
--- /dev/null
+++ b/lib/Support/Windows/DynamicLibrary.inc
@@ -0,0 +1,199 @@
+//===- Win32/DynamicLibrary.cpp - Win32 DL 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 DynamicLibrary.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Windows.h"
+
+#ifdef __MINGW32__
+ #include <imagehlp.h>
+#else
+ #include <dbghelp.h>
+#endif
+
+#ifdef _MSC_VER
+ #include <ntverp.h>
+#endif
+
+#ifdef __MINGW32__
+ #if (HAVE_LIBIMAGEHLP != 1)
+ #error "libimagehlp.a should be present"
+ #endif
+#else
+ #pragma comment(lib, "dbghelp.lib")
+#endif
+
+namespace llvm {
+using namespace sys;
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only Win32 specific code
+//=== and must not be UNIX code.
+//===----------------------------------------------------------------------===//
+
+static std::vector<HMODULE> OpenedHandles;
+
+#ifdef _WIN64
+ typedef DWORD64 ModuleBaseType;
+#else
+ typedef ULONG ModuleBaseType;
+#endif
+
+extern "C" {
+// Use old callback if:
+// - Not using Visual Studio
+// - Visual Studio 2005 or earlier but only if we are not using the Windows SDK
+// or Windows SDK version is older than 6.0
+// Use new callback if:
+// - Newer Visual Studio (comes with newer SDK).
+// - Visual Studio 2005 with Windows SDK 6.0+
+#if !defined(_MSC_VER) || _MSC_VER < 1500 && (!defined(VER_PRODUCTBUILD) || VER_PRODUCTBUILD < 6000)
+ static BOOL CALLBACK ELM_Callback(PSTR ModuleName,
+ ModuleBaseType ModuleBase,
+ ULONG ModuleSize,
+ PVOID UserContext)
+#else
+ static BOOL CALLBACK ELM_Callback(PCSTR ModuleName,
+ ModuleBaseType ModuleBase,
+ ULONG ModuleSize,
+ PVOID UserContext)
+#endif
+ {
+ // Ignore VC++ runtimes prior to 7.1. Somehow some of them get loaded
+ // into the process.
+ if (stricmp(ModuleName, "msvci70") != 0 &&
+ stricmp(ModuleName, "msvcirt") != 0 &&
+ stricmp(ModuleName, "msvcp50") != 0 &&
+ stricmp(ModuleName, "msvcp60") != 0 &&
+ stricmp(ModuleName, "msvcp70") != 0 &&
+ stricmp(ModuleName, "msvcr70") != 0 &&
+#ifndef __MINGW32__
+ // Mingw32 uses msvcrt.dll by default. Don't ignore it.
+ // Otherwise, user should be aware, what he's doing :)
+ stricmp(ModuleName, "msvcrt") != 0 &&
+#endif
+ stricmp(ModuleName, "msvcrt20") != 0 &&
+ stricmp(ModuleName, "msvcrt40") != 0) {
+ OpenedHandles.push_back((HMODULE)ModuleBase);
+ }
+ return TRUE;
+ }
+}
+
+bool DynamicLibrary::LoadLibraryPermanently(const char *filename,
+ std::string *ErrMsg) {
+ if (filename) {
+ HMODULE a_handle = LoadLibrary(filename);
+
+ if (a_handle == 0)
+ return MakeErrMsg(ErrMsg, std::string(filename) + ": Can't open : ");
+
+ OpenedHandles.push_back(a_handle);
+ } else {
+ // When no file is specified, enumerate all DLLs and EXEs in the
+ // process.
+ EnumerateLoadedModules(GetCurrentProcess(), ELM_Callback, 0);
+ }
+
+ // Because we don't remember the handle, we will never free it; hence,
+ // it is loaded permanently.
+ return false;
+}
+
+// Stack probing routines are in the support library (e.g. libgcc), but we don't
+// have dynamic linking on windows. Provide a hook.
+#if defined(__MINGW32__) || defined (_MSC_VER)
+ #define EXPLICIT_SYMBOL(SYM) \
+ if (!strcmp(symbolName, #SYM)) return (void*)&SYM
+ #define EXPLICIT_SYMBOL2(SYMFROM, SYMTO) \
+ if (!strcmp(symbolName, #SYMFROM)) return (void*)&SYMTO
+ #define EXPLICIT_SYMBOL_DEF(SYM) \
+ extern "C" { extern void *SYM; }
+
+ #if defined(__MINGW32__)
+ EXPLICIT_SYMBOL_DEF(_alloca)
+ EXPLICIT_SYMBOL_DEF(__main)
+ EXPLICIT_SYMBOL_DEF(__ashldi3)
+ EXPLICIT_SYMBOL_DEF(__ashrdi3)
+ EXPLICIT_SYMBOL_DEF(__cmpdi2)
+ EXPLICIT_SYMBOL_DEF(__divdi3)
+ EXPLICIT_SYMBOL_DEF(__fixdfdi)
+ EXPLICIT_SYMBOL_DEF(__fixsfdi)
+ EXPLICIT_SYMBOL_DEF(__fixunsdfdi)
+ EXPLICIT_SYMBOL_DEF(__fixunssfdi)
+ EXPLICIT_SYMBOL_DEF(__floatdidf)
+ EXPLICIT_SYMBOL_DEF(__floatdisf)
+ EXPLICIT_SYMBOL_DEF(__lshrdi3)
+ EXPLICIT_SYMBOL_DEF(__moddi3)
+ EXPLICIT_SYMBOL_DEF(__udivdi3)
+ EXPLICIT_SYMBOL_DEF(__umoddi3)
+ #elif defined(_MSC_VER)
+ EXPLICIT_SYMBOL_DEF(_alloca_probe)
+ #endif
+#endif
+
+void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) {
+ // First check symbols added via AddSymbol().
+ if (ExplicitSymbols) {
+ std::map<std::string, void *>::iterator I =
+ ExplicitSymbols->find(symbolName);
+ std::map<std::string, void *>::iterator E = ExplicitSymbols->end();
+ if (I != E)
+ return I->second;
+ }
+
+ // Now search the libraries.
+ for (std::vector<HMODULE>::iterator I = OpenedHandles.begin(),
+ E = OpenedHandles.end(); I != E; ++I) {
+ FARPROC ptr = GetProcAddress((HMODULE)*I, symbolName);
+ if (ptr) {
+ return (void *) ptr;
+ }
+ }
+
+#if defined(__MINGW32__)
+ {
+ EXPLICIT_SYMBOL(_alloca);
+ EXPLICIT_SYMBOL(__main);
+ EXPLICIT_SYMBOL(__ashldi3);
+ EXPLICIT_SYMBOL(__ashrdi3);
+ EXPLICIT_SYMBOL(__cmpdi2);
+ EXPLICIT_SYMBOL(__divdi3);
+ EXPLICIT_SYMBOL(__fixdfdi);
+ EXPLICIT_SYMBOL(__fixsfdi);
+ EXPLICIT_SYMBOL(__fixunsdfdi);
+ EXPLICIT_SYMBOL(__fixunssfdi);
+ EXPLICIT_SYMBOL(__floatdidf);
+ EXPLICIT_SYMBOL(__floatdisf);
+ EXPLICIT_SYMBOL(__lshrdi3);
+ EXPLICIT_SYMBOL(__moddi3);
+ EXPLICIT_SYMBOL(__udivdi3);
+ EXPLICIT_SYMBOL(__umoddi3);
+
+ EXPLICIT_SYMBOL2(alloca, _alloca);
+#undef EXPLICIT_SYMBOL
+#undef EXPLICIT_SYMBOL2
+#undef EXPLICIT_SYMBOL_DEF
+ }
+#elif defined(_MSC_VER)
+ {
+ EXPLICIT_SYMBOL2(alloca, _alloca_probe);
+ EXPLICIT_SYMBOL2(_alloca, _alloca_probe);
+#undef EXPLICIT_SYMBOL
+#undef EXPLICIT_SYMBOL2
+#undef EXPLICIT_SYMBOL_DEF
+ }
+#endif
+
+ return 0;
+}
+
+}
diff --git a/lib/Support/Windows/Host.inc b/lib/Support/Windows/Host.inc
new file mode 100644
index 0000000000..5377c77f03
--- /dev/null
+++ b/lib/Support/Windows/Host.inc
@@ -0,0 +1,23 @@
+//===- llvm/System/Win32/Host.inc -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Win32 Host support.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Windows.h"
+#include <cstdio>
+#include <string>
+
+using namespace llvm;
+
+std::string sys::getHostTriple() {
+ // FIXME: Adapt to running version.
+ return LLVM_HOSTTRIPLE;
+}
diff --git a/lib/Support/Windows/Memory.inc b/lib/Support/Windows/Memory.inc
new file mode 100644
index 0000000000..9f69e7367e
--- /dev/null
+++ b/lib/Support/Windows/Memory.inc
@@ -0,0 +1,73 @@
+//===- 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 "Windows.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Process.h"
+
+namespace llvm {
+using namespace sys;
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only Win32 specific code
+//=== and must not be UNIX code
+//===----------------------------------------------------------------------===//
+
+MemoryBlock Memory::AllocateRWX(size_t NumBytes,
+ const MemoryBlock *NearBlock,
+ std::string *ErrMsg) {
+ if (NumBytes == 0) return MemoryBlock();
+
+ static const size_t pageSize = Process::GetPageSize();
+ size_t NumPages = (NumBytes+pageSize-1)/pageSize;
+
+ //FIXME: support NearBlock if ever needed on Win64.
+
+ void *pa = VirtualAlloc(NULL, NumPages*pageSize, MEM_COMMIT,
+ PAGE_EXECUTE_READWRITE);
+ if (pa == NULL) {
+ MakeErrMsg(ErrMsg, "Can't allocate RWX Memory: ");
+ return MemoryBlock();
+ }
+
+ MemoryBlock result;
+ result.Address = pa;
+ result.Size = NumPages*pageSize;
+ return result;
+}
+
+bool Memory::ReleaseRWX(MemoryBlock &M, std::string *ErrMsg) {
+ if (M.Address == 0 || M.Size == 0) return false;
+ if (!VirtualFree(M.Address, 0, MEM_RELEASE))
+ return MakeErrMsg(ErrMsg, "Can't release RWX Memory: ");
+ return false;
+}
+
+bool Memory::setWritable(MemoryBlock &M, std::string *ErrMsg) {
+ return true;
+}
+
+bool Memory::setExecutable(MemoryBlock &M, std::string *ErrMsg) {
+ return false;
+}
+
+bool Memory::setRangeWritable(const void *Addr, size_t Size) {
+ return true;
+}
+
+bool Memory::setRangeExecutable(const void *Addr, size_t Size) {
+ return false;
+}
+
+}
diff --git a/lib/Support/Windows/Mutex.inc b/lib/Support/Windows/Mutex.inc
new file mode 100644
index 0000000000..ff7d642998
--- /dev/null
+++ b/lib/Support/Windows/Mutex.inc
@@ -0,0 +1,58 @@
+//===- llvm/System/Win32/Mutex.inc - Win32 Mutex 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 implements the Win32 specific (non-pthread) Mutex class.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only generic Win32 code that
+//=== is guaranteed to work on *all* Win32 variants.
+//===----------------------------------------------------------------------===//
+
+#include "Windows.h"
+#include "llvm/Support/Mutex.h"
+
+namespace llvm {
+using namespace sys;
+
+MutexImpl::MutexImpl(bool /*recursive*/)
+{
+ data_ = new CRITICAL_SECTION;
+ InitializeCriticalSection((LPCRITICAL_SECTION)data_);
+}
+
+MutexImpl::~MutexImpl()
+{
+ DeleteCriticalSection((LPCRITICAL_SECTION)data_);
+ delete (LPCRITICAL_SECTION)data_;
+ data_ = 0;
+}
+
+bool
+MutexImpl::acquire()
+{
+ EnterCriticalSection((LPCRITICAL_SECTION)data_);
+ return true;
+}
+
+bool
+MutexImpl::release()
+{
+ LeaveCriticalSection((LPCRITICAL_SECTION)data_);
+ return true;
+}
+
+bool
+MutexImpl::tryacquire()
+{
+ return TryEnterCriticalSection((LPCRITICAL_SECTION)data_);
+}
+
+}
diff --git a/lib/Support/Windows/Path.inc b/lib/Support/Windows/Path.inc
new file mode 100644
index 0000000000..e517eece73
--- /dev/null
+++ b/lib/Support/Windows/Path.inc
@@ -0,0 +1,918 @@
+//===- llvm/System/Win32/Path.cpp - Win32 Path 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 the Path class.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only generic Win32 code that
+//=== is guaranteed to work on *all* Win32 variants.
+//===----------------------------------------------------------------------===//
+
+#include "Windows.h"
+#include <malloc.h>
+#include <cstdio>
+
+// We need to undo a macro defined in Windows.h, otherwise we won't compile:
+#undef CopyFile
+#undef GetCurrentDirectory
+
+// Windows happily accepts either forward or backward slashes, though any path
+// returned by a Win32 API will have backward slashes. As LLVM code basically
+// assumes forward slashes are used, backward slashs are converted where they
+// can be introduced into a path.
+//
+// Another invariant is that a path ends with a slash if and only if the path
+// is a root directory. Any other use of a trailing slash is stripped. Unlike
+// in Unix, Windows has a rather complicated notion of a root path and this
+// invariant helps simply the code.
+
+static void FlipBackSlashes(std::string& s) {
+ for (size_t i = 0; i < s.size(); i++)
+ if (s[i] == '\\')
+ s[i] = '/';
+}
+
+namespace llvm {
+namespace sys {
+
+const char PathSeparator = ';';
+
+StringRef Path::GetEXESuffix() {
+ return "exe";
+}
+
+Path::Path(llvm::StringRef p)
+ : path(p) {
+ FlipBackSlashes(path);
+}
+
+Path::Path(const char *StrStart, unsigned StrLen)
+ : path(StrStart, StrLen) {
+ FlipBackSlashes(path);
+}
+
+Path&
+Path::operator=(StringRef that) {
+ path.assign(that.data(), that.size());
+ FlipBackSlashes(path);
+ return *this;
+}
+
+// push_back 0 on create, and pop_back on delete.
+struct ScopedNullTerminator {
+ std::string &str;
+ ScopedNullTerminator(std::string &s) : str(s) { str.push_back(0); }
+ ~ScopedNullTerminator() {
+ // str.pop_back(); But wait, C++03 doesn't have this...
+ assert(!str.empty() && str[str.size() - 1] == 0
+ && "Null char not present!");
+ str.resize(str.size() - 1);
+ }
+};
+
+bool
+Path::isValid() const {
+ if (path.empty())
+ return false;
+
+ // If there is a colon, it must be the second character, preceded by a letter
+ // and followed by something.
+ size_t len = path.size();
+ // This code assumes that path is null terminated, so make sure it is.
+ ScopedNullTerminator snt(path);
+ size_t pos = path.rfind(':',len);
+ size_t rootslash = 0;
+ if (pos != std::string::npos) {
+ if (pos != 1 || !isalpha(path[0]) || len < 3)
+ return false;
+ rootslash = 2;
+ }
+
+ // Look for a UNC path, and if found adjust our notion of the root slash.
+ if (len > 3 && path[0] == '/' && path[1] == '/') {
+ rootslash = path.find('/', 2);
+ if (rootslash == std::string::npos)
+ rootslash = 0;
+ }
+
+ // Check for illegal characters.
+ if (path.find_first_of("\\<>\"|\001\002\003\004\005\006\007\010\011\012"
+ "\013\014\015\016\017\020\021\022\023\024\025\026"
+ "\027\030\031\032\033\034\035\036\037")
+ != std::string::npos)
+ return false;
+
+ // Remove trailing slash, unless it's a root slash.
+ if (len > rootslash+1 && path[len-1] == '/')
+ path.erase(--len);
+
+ // Check each component for legality.
+ for (pos = 0; pos < len; ++pos) {
+ // A component may not end in a space.
+ if (path[pos] == ' ') {
+ if (path[pos+1] == '/' || path[pos+1] == '\0')
+ return false;
+ }
+
+ // A component may not end in a period.
+ if (path[pos] == '.') {
+ if (path[pos+1] == '/' || path[pos+1] == '\0') {
+ // Unless it is the pseudo-directory "."...
+ if (pos == 0 || path[pos-1] == '/' || path[pos-1] == ':')
+ return true;
+ // or "..".
+ if (pos > 0 && path[pos-1] == '.') {
+ if (pos == 1 || path[pos-2] == '/' || path[pos-2] == ':')
+ return true;
+ }
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+void Path::makeAbsolute() {
+ TCHAR FullPath[MAX_PATH + 1] = {0};
+ LPTSTR FilePart = NULL;
+
+ DWORD RetLength = ::GetFullPathNameA(path.c_str(),
+ sizeof(FullPath)/sizeof(FullPath[0]),
+ FullPath, &FilePart);
+
+ if (0 == RetLength) {
+ // FIXME: Report the error GetLastError()
+ assert(0 && "Unable to make absolute path!");
+ } else if (RetLength > MAX_PATH) {
+ // FIXME: Report too small buffer (needed RetLength bytes).
+ assert(0 && "Unable to make absolute path!");
+ } else {
+ path = FullPath;
+ }
+}
+
+bool
+Path::isAbsolute(const char *NameStart, unsigned NameLen) {
+ assert(NameStart);
+ // FIXME: This does not handle correctly an absolute path starting from
+ // a drive letter or in UNC format.
+ switch (NameLen) {
+ case 0:
+ return false;
+ case 1:
+ case 2:
+ return NameStart[0] == '/';
+ default:
+ return
+ (NameStart[0] == '/' || (NameStart[1] == ':' && NameStart[2] == '/')) ||
+ (NameStart[0] == '\\' || (NameStart[1] == ':' && NameStart[2] == '\\'));
+ }
+}
+
+bool
+Path::isAbsolute() const {
+ // FIXME: This does not handle correctly an absolute path starting from
+ // a drive letter or in UNC format.
+ switch (path.length()) {
+ case 0:
+ return false;
+ case 1:
+ case 2:
+ return path[0] == '/';
+ default:
+ return path[0] == '/' || (path[1] == ':' && path[2] == '/');
+ }
+}
+
+static Path *TempDirectory;
+
+Path
+Path::GetTemporaryDirectory(std::string* ErrMsg) {
+ if (TempDirectory)
+ return *TempDirectory;
+
+ char pathname[MAX_PATH];
+ if (!GetTempPath(MAX_PATH, pathname)) {
+ if (ErrMsg)
+ *ErrMsg = "Can't determine temporary directory";
+ return Path();
+ }
+
+ Path result;
+ result.set(pathname);
+
+ // Append a subdirectory passed on our process id so multiple LLVMs don't
+ // step on each other's toes.
+#ifdef __MINGW32__
+ // Mingw's Win32 header files are broken.
+ sprintf(pathname, "LLVM_%u", unsigned(GetCurrentProcessId()));
+#else
+ sprintf(pathname, "LLVM_%u", GetCurrentProcessId());
+#endif
+ result.appendComponent(pathname);
+
+ // If there's a directory left over from a previous LLVM execution that
+ // happened to have the same process id, get rid of it.
+ result.eraseFromDisk(true);
+
+ // And finally (re-)create the empty directory.
+ result.createDirectoryOnDisk(false);
+ TempDirectory = new Path(result);
+ return *TempDirectory;
+}
+
+// FIXME: the following set of functions don't map to Windows very well.
+Path
+Path::GetRootDirectory() {
+ // This is the only notion that that Windows has of a root directory. Nothing
+ // is here except for drives.
+ return Path("file:///");
+}
+
+void
+Path::GetSystemLibraryPaths(std::vector<sys::Path>& Paths) {
+ char buff[MAX_PATH];
+ // Generic form of C:\Windows\System32
+ HRESULT res = SHGetFolderPathA(NULL,
+ CSIDL_FLAG_CREATE | CSIDL_SYSTEM,
+ NULL,
+ SHGFP_TYPE_CURRENT,
+ buff);
+ if (res != S_OK) {
+ assert(0 && "Failed to get system directory");
+ return;
+ }
+ Paths.push_back(sys::Path(buff));
+
+ // Reset buff.
+ buff[0] = 0;
+ // Generic form of C:\Windows
+ res = SHGetFolderPathA(NULL,
+ CSIDL_FLAG_CREATE | CSIDL_WINDOWS,
+ NULL,
+ SHGFP_TYPE_CURRENT,
+ buff);
+ if (res != S_OK) {
+ assert(0 && "Failed to get windows directory");
+ return;
+ }
+ Paths.push_back(sys::Path(buff));
+}
+
+void
+Path::GetBitcodeLibraryPaths(std::vector<sys::Path>& Paths) {
+ char * env_var = getenv("LLVM_LIB_SEARCH_PATH");
+ if (env_var != 0) {
+ getPathList(env_var,Paths);
+ }
+#ifdef LLVM_LIBDIR
+ {
+ Path tmpPath;
+ if (tmpPath.set(LLVM_LIBDIR))
+ if (tmpPath.canRead())
+ Paths.push_back(tmpPath);
+ }
+#endif
+ GetSystemLibraryPaths(Paths);
+}
+
+Path
+Path::GetLLVMDefaultConfigDir() {
+ Path ret = GetUserHomeDirectory();
+ if (!ret.appendComponent(".llvm"))
+ assert(0 && "Failed to append .llvm");
+ return ret;
+}
+
+Path
+Path::GetUserHomeDirectory() {
+ char buff[MAX_PATH];
+ HRESULT res = SHGetFolderPathA(NULL,
+ CSIDL_FLAG_CREATE | CSIDL_APPDATA,
+ NULL,
+ SHGFP_TYPE_CURRENT,
+ buff);
+ if (res != S_OK)
+ assert(0 && "Failed to get user home directory");
+ return Path(buff);
+}
+
+Path
+Path::GetCurrentDirectory() {
+ char pathname[MAX_PATH];
+ ::GetCurrentDirectoryA(MAX_PATH,pathname);
+ return Path(pathname);
+}
+
+/// GetMainExecutable - Return the path to the main executable, given the
+/// value of argv[0] from program startup.
+Path Path::GetMainExecutable(const char *argv0, void *MainAddr) {
+ char pathname[MAX_PATH];
+ DWORD ret = ::GetModuleFileNameA(NULL, pathname, MAX_PATH);
+ return ret != MAX_PATH ? Path(pathname) : Path();
+}
+
+
+// FIXME: the above set of functions don't map to Windows very well.
+
+
+StringRef Path::getDirname() const {
+ return getDirnameCharSep(path, "/");
+}
+
+StringRef
+Path::getBasename() const {
+ // Find the last slash
+ size_t slash = path.rfind('/');
+ if (slash == std::string::npos)
+ slash = 0;
+ else
+ slash++;
+
+ size_t dot = path.rfind('.');
+ if (dot == std::string::npos || dot < slash)
+ return StringRef(path).substr(slash);
+ else
+ return StringRef(path).substr(slash, dot - slash);
+}
+
+StringRef
+Path::getSuffix() const {
+ // Find the last slash
+ size_t slash = path.rfind('/');
+ if (slash == std::string::npos)
+ slash = 0;
+ else
+ slash++;
+
+ size_t dot = path.rfind('.');
+ if (dot == std::string::npos || dot < slash)
+ return StringRef("");
+ else
+ return StringRef(path).substr(dot + 1);
+}
+
+bool
+Path::exists() const {
+ DWORD attr = GetFileAttributes(path.c_str());
+ return attr != INVALID_FILE_ATTRIBUTES;
+}
+
+bool
+Path::isDirectory() const {
+ DWORD attr = GetFileAttributes(path.c_str());
+ return (attr != INVALID_FILE_ATTRIBUTES) &&
+ (attr & FILE_ATTRIBUTE_DIRECTORY);
+}
+
+bool
+Path::isSymLink() const {
+ DWORD attributes = GetFileAttributes(path.c_str());
+
+ if (attributes == INVALID_FILE_ATTRIBUTES)
+ // There's no sane way to report this :(.
+ assert(0 && "GetFileAttributes returned INVALID_FILE_ATTRIBUTES");
+
+ // This isn't exactly what defines a NTFS symlink, but it is only true for
+ // paths that act like a symlink.
+ return attributes & FILE_ATTRIBUTE_REPARSE_POINT;
+}
+
+bool
+Path::canRead() const {
+ // FIXME: take security attributes into account.
+ DWORD attr = GetFileAttributes(path.c_str());
+ return attr != INVALID_FILE_ATTRIBUTES;
+}
+
+bool
+Path::canWrite() const {
+ // FIXME: take security attributes into account.
+ DWORD attr = GetFileAttributes(path.c_str());
+ return (attr != INVALID_FILE_ATTRIBUTES) && !(attr & FILE_ATTRIBUTE_READONLY);
+}
+
+bool
+Path::canExecute() const {
+ // FIXME: take security attributes into account.
+ DWORD attr = GetFileAttributes(path.c_str());
+ return attr != INVALID_FILE_ATTRIBUTES;
+}
+
+bool
+Path::isRegularFile() const {
+ if (isDirectory())
+ return false;
+ return true;
+}
+
+StringRef
+Path::getLast() const {
+ // Find the last slash
+ size_t pos = path.rfind('/');
+
+ // Handle the corner cases
+ if (pos == std::string::npos)
+ return path;
+
+ // If the last character is a slash, we have a root directory
+ if (pos == path.length()-1)
+ return path;
+
+ // Return everything after the last slash
+ return StringRef(path).substr(pos+1);
+}
+
+const FileStatus *
+PathWithStatus::getFileStatus(bool update, std::string *ErrStr) const {
+ if (!fsIsValid || update) {
+ WIN32_FILE_ATTRIBUTE_DATA fi;
+ if (!GetFileAttributesEx(path.c_str(), GetFileExInfoStandard, &fi)) {
+ MakeErrMsg(ErrStr, "getStatusInfo():" + std::string(path) +
+ ": Can't get status: ");
+ return 0;
+ }
+
+ status.fileSize = fi.nFileSizeHigh;
+ status.fileSize <<= sizeof(fi.nFileSizeHigh)*8;
+ status.fileSize += fi.nFileSizeLow;
+
+ status.mode = fi.dwFileAttributes & FILE_ATTRIBUTE_READONLY ? 0555 : 0777;
+ status.user = 9999; // Not applicable to Windows, so...
+ status.group = 9999; // Not applicable to Windows, so...
+
+ // FIXME: this is only unique if the file is accessed by the same file path.
+ // How do we do this for C:\dir\file and ..\dir\file ? Unix has inode
+ // numbers, but the concept doesn't exist in Windows.
+ status.uniqueID = 0;
+ for (unsigned i = 0; i < path.length(); ++i)
+ status.uniqueID += path[i];
+
+ ULARGE_INTEGER ui;
+ ui.LowPart = fi.ftLastWriteTime.dwLowDateTime;
+ ui.HighPart = fi.ftLastWriteTime.dwHighDateTime;
+ status.modTime.fromWin32Time(ui.QuadPart);
+
+ status.isDir = fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
+ fsIsValid = true;
+ }
+ return &status;
+}
+
+bool Path::makeReadableOnDisk(std::string* ErrMsg) {
+ // All files are readable on Windows (ignoring security attributes).
+ return false;
+}
+
+bool Path::makeWriteableOnDisk(std::string* ErrMsg) {
+ DWORD attr = GetFileAttributes(path.c_str());
+
+ // If it doesn't exist, we're done.
+ if (attr == INVALID_FILE_ATTRIBUTES)
+ return false;
+
+ if (attr & FILE_ATTRIBUTE_READONLY) {
+ if (!SetFileAttributes(path.c_str(), attr & ~FILE_ATTRIBUTE_READONLY)) {
+ MakeErrMsg(ErrMsg, std::string(path) + ": Can't make file writable: ");
+ return true;
+ }
+ }
+ return false;
+}
+
+bool Path::makeExecutableOnDisk(std::string* ErrMsg) {
+ // All files are executable on Windows (ignoring security attributes).
+ return false;
+}
+
+bool
+Path::getDirectoryContents(std::set<Path>& result, std::string* ErrMsg) const {
+ WIN32_FILE_ATTRIBUTE_DATA fi;
+ if (!GetFileAttributesEx(path.c_str(), GetFileExInfoStandard, &fi)) {
+ MakeErrMsg(ErrMsg, path + ": can't get status of file");
+ return true;
+ }
+
+ if (!(fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
+ if (ErrMsg)
+ *ErrMsg = path + ": not a directory";
+ return true;
+ }
+
+ result.clear();
+ WIN32_FIND_DATA fd;
+ std::string searchpath = path;
+ if (path.size() == 0 || searchpath[path.size()-1] == '/')
+ searchpath += "*";
+ else
+ searchpath += "/*";
+
+ HANDLE h = FindFirstFile(searchpath.c_str(), &fd);
+ if (h == INVALID_HANDLE_VALUE) {
+ if (GetLastError() == ERROR_FILE_NOT_FOUND)
+ return true; // not really an error, now is it?
+ MakeErrMsg(ErrMsg, path + ": Can't read directory: ");
+ return true;
+ }
+
+ do {
+ if (fd.cFileName[0] == '.')
+ continue;
+ Path aPath(path);
+ aPath.appendComponent(&fd.cFileName[0]);
+ result.insert(aPath);
+ } while (FindNextFile(h, &fd));
+
+ DWORD err = GetLastError();
+ FindClose(h);
+ if (err != ERROR_NO_MORE_FILES) {
+ SetLastError(err);
+ MakeErrMsg(ErrMsg, path + ": Can't read directory: ");
+ return true;
+ }
+ return false;
+}
+
+bool
+Path::set(StringRef a_path) {
+ if (a_path.empty())
+ return false;
+ std::string save(path);
+ path = a_path;
+ FlipBackSlashes(path);
+ if (!isValid()) {
+ path = save;
+ return false;
+ }
+ return true;
+}
+
+bool
+Path::appendComponent(StringRef name) {
+ if (name.empty())
+ return false;
+ std::string save(path);
+ if (!path.empty()) {
+ size_t last = path.size() - 1;
+ if (path[last] != '/')
+ path += '/';
+ }
+ path += name;
+ if (!isValid()) {
+ path = save;
+ return false;
+ }
+ return true;
+}
+
+bool
+Path::eraseComponent() {
+ size_t slashpos = path.rfind('/',path.size());
+ if (slashpos == path.size() - 1 || slashpos == std::string::npos)
+ return false;
+ std::string save(path);
+ path.erase(slashpos);
+ if (!isValid()) {
+ path = save;
+ return false;
+ }
+ return true;
+}
+
+bool
+Path::eraseSuffix() {
+ size_t dotpos = path.rfind('.',path.size());
+ size_t slashpos = path.rfind('/',path.size());
+ if (dotpos != std::string::npos) {
+ if (slashpos == std::string::npos || dotpos > slashpos+1) {
+ std::string save(path);
+ path.erase(dotpos, path.size()-dotpos);
+ if (!isValid()) {
+ path = save;
+ return false;
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+inline bool PathMsg(std::string* ErrMsg, const char* pathname, const char*msg) {
+ if (ErrMsg)
+ *ErrMsg = std::string(pathname) + ": " + std::string(msg);
+ return true;
+}
+
+bool
+Path::createDirectoryOnDisk(bool create_parents, std::string* ErrMsg) {
+ // Get a writeable copy of the path name
+ size_t len = path.length();
+ char *pathname = reinterpret_cast<char *>(_alloca(len+2));
+ path.copy(pathname, len);
+ pathname[len] = 0;
+
+ // Make sure it ends with a slash.
+ if (len == 0 || pathname[len - 1] != '/') {
+ pathname[len] = '/';
+ pathname[++len] = 0;
+ }
+
+ // Determine starting point for initial / search.
+ char *next = pathname;
+ if (pathname[0] == '/' && pathname[1] == '/') {
+ // Skip host name.
+ next = strchr(pathname+2, '/');
+ if (next == NULL)
+ return PathMsg(ErrMsg, pathname, "badly formed remote directory");
+
+ // Skip share name.
+ next = strchr(next+1, '/');
+ if (next == NULL)
+ return PathMsg(ErrMsg, pathname,"badly formed remote directory");
+
+ next++;
+ if (*next == 0)
+ return PathMsg(ErrMsg, pathname, "badly formed remote directory");
+
+ } else {
+ if (pathname[1] == ':')
+ next += 2; // skip drive letter
+ if (*next == '/')
+ next++; // skip root directory
+ }
+
+ // If we're supposed to create intermediate directories
+ if (create_parents) {
+ // Loop through the directory components until we're done
+ while (*next) {
+ next = strchr(next, '/');
+ *next = 0;
+ if (!CreateDirectory(pathname, NULL) &&
+ GetLastError() != ERROR_ALREADY_EXISTS)
+ return MakeErrMsg(ErrMsg,
+ std::string(pathname) + ": Can't create directory: ");
+ *next++ = '/';
+ }
+ } else {
+ // Drop trailing slash.
+ pathname[len-1] = 0;
+ if (!CreateDirectory(pathname, NULL) &&
+ GetLastError() != ERROR_ALREADY_EXISTS) {
+ return MakeErrMsg(ErrMsg, std::string(pathname) +
+ ": Can't create directory: ");
+ }
+ }
+ return false;
+}
+
+bool
+Path::createFileOnDisk(std::string* ErrMsg) {
+ // Create the file
+ HANDLE h = CreateFile(path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ return MakeErrMsg(ErrMsg, path + ": Can't create file: ");
+
+ CloseHandle(h);
+ return false;
+}
+
+bool
+Path::eraseFromDisk(bool remove_contents, std::string *ErrStr) const {
+ WIN32_FILE_ATTRIBUTE_DATA fi;
+ if (!GetFileAttributesEx(path.c_str(), GetFileExInfoStandard, &fi))
+ return true;
+
+ if (fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ // If it doesn't exist, we're done.
+ if (!exists())
+ return false;
+
+ char *pathname = reinterpret_cast<char *>(_alloca(path.length()+3));
+ int lastchar = path.length() - 1 ;
+ path.copy(pathname, lastchar+1);
+
+ // Make path end with '/*'.
+ if (pathname[lastchar] != '/')
+ pathname[++lastchar] = '/';
+ pathname[lastchar+1] = '*';
+ pathname[lastchar+2] = 0;
+
+ if (remove_contents) {
+ WIN32_FIND_DATA fd;
+ HANDLE h = FindFirstFile(pathname, &fd);
+
+ // It's a bad idea to alter the contents of a directory while enumerating
+ // its contents. So build a list of its contents first, then destroy them.
+
+ if (h != INVALID_HANDLE_VALUE) {
+ std::vector<Path> list;
+
+ do {
+ if (strcmp(fd.cFileName, ".") == 0)
+ continue;
+ if (strcmp(fd.cFileName, "..") == 0)
+ continue;
+
+ Path aPath(path);
+ aPath.appendComponent(&fd.cFileName[0]);
+ list.push_back(aPath);
+ } while (FindNextFile(h, &fd));
+
+ DWORD err = GetLastError();
+ FindClose(h);
+ if (err != ERROR_NO_MORE_FILES) {
+ SetLastError(err);
+ return MakeErrMsg(ErrStr, path + ": Can't read directory: ");
+ }
+
+ for (std::vector<Path>::iterator I = list.begin(); I != list.end();
+ ++I) {
+ Path &aPath = *I;
+ aPath.eraseFromDisk(true);
+ }
+ } else {
+ if (GetLastError() != ERROR_FILE_NOT_FOUND)
+ return MakeErrMsg(ErrStr, path + ": Can't read directory: ");
+ }
+ }
+
+ pathname[lastchar] = 0;
+ if (!RemoveDirectory(pathname))
+ return MakeErrMsg(ErrStr,
+ std::string(pathname) + ": Can't destroy directory: ");
+ return false;
+ } else {
+ // Read-only files cannot be deleted on Windows. Must remove the read-only
+ // attribute first.
+ if (fi.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
+ if (!SetFileAttributes(path.c_str(),
+ fi.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY))
+ return MakeErrMsg(ErrStr, path + ": Can't destroy file: ");
+ }
+
+ if (!DeleteFile(path.c_str()))
+ return MakeErrMsg(ErrStr, path + ": Can't destroy file: ");
+ return false;
+ }
+}
+
+bool Path::getMagicNumber(std::string& Magic, unsigned len) const {
+ assert(len < 1024 && "Request for magic string too long");
+ char* buf = reinterpret_cast<char*>(alloca(len));
+
+ HANDLE h = CreateFile(path.c_str(),
+ GENERIC_READ,
+ FILE_SHARE_READ,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ return false;
+
+ DWORD nRead = 0;
+ BOOL ret = ReadFile(h, buf, len, &nRead, NULL);
+ CloseHandle(h);
+
+ if (!ret || nRead != len)
+ return false;
+
+ Magic = std::string(buf, len);
+ return true;
+}
+
+bool
+Path::renamePathOnDisk(const Path& newName, std::string* ErrMsg) {
+ if (!MoveFileEx(path.c_str(), newName.c_str(), MOVEFILE_REPLACE_EXISTING))
+ return MakeErrMsg(ErrMsg, "Can't move '" + path + "' to '" + newName.path
+ + "': ");
+ return false;
+}
+
+bool
+Path::setStatusInfoOnDisk(const FileStatus &si, std::string *ErrMsg) const {
+ // FIXME: should work on directories also.
+ if (!si.isFile) {
+ return true;
+ }
+
+ HANDLE h = CreateFile(path.c_str(),
+ FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ return true;
+
+ BY_HANDLE_FILE_INFORMATION bhfi;
+ if (!GetFileInformationByHandle(h, &bhfi)) {
+ DWORD err = GetLastError();
+ CloseHandle(h);
+ SetLastError(err);
+ return MakeErrMsg(ErrMsg, path + ": GetFileInformationByHandle: ");
+ }
+
+ ULARGE_INTEGER ui;
+ ui.QuadPart = si.modTime.toWin32Time();
+ FILETIME ft;
+ ft.dwLowDateTime = ui.LowPart;
+ ft.dwHighDateTime = ui.HighPart;
+ BOOL ret = SetFileTime(h, NULL, &ft, &ft);
+ DWORD err = GetLastError();
+ CloseHandle(h);
+ if (!ret) {
+ SetLastError(err);
+ return MakeErrMsg(ErrMsg, path + ": SetFileTime: ");
+ }
+
+ // Best we can do with Unix permission bits is to interpret the owner
+ // writable bit.
+ if (si.mode & 0200) {
+ if (bhfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
+ if (!SetFileAttributes(path.c_str(),
+ bhfi.dwFileAttributes & ~FILE_ATTRIBUTE_READONLY))
+ return MakeErrMsg(ErrMsg, path + ": SetFileAttributes: ");
+ }
+ } else {
+ if (!(bhfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) {
+ if (!SetFileAttributes(path.c_str(),
+ bhfi.dwFileAttributes | FILE_ATTRIBUTE_READONLY))
+ return MakeErrMsg(ErrMsg, path + ": SetFileAttributes: ");
+ }
+ }
+
+ return false;
+}
+
+bool
+CopyFile(const sys::Path &Dest, const sys::Path &Src, std::string* ErrMsg) {
+ // Can't use CopyFile macro defined in Windows.h because it would mess up the
+ // above line. We use the expansion it would have in a non-UNICODE build.
+ if (!::CopyFileA(Src.c_str(), Dest.c_str(), false))
+ return MakeErrMsg(ErrMsg, "Can't copy '" + Src.str() +
+ "' to '" + Dest.str() + "': ");
+ return false;
+}
+
+bool
+Path::makeUnique(bool reuse_current, std::string* ErrMsg) {
+ if (reuse_current && !exists())
+ return false; // File doesn't exist already, just use it!
+
+ // Reserve space for -XXXXXX at the end.
+ char *FNBuffer = (char*) alloca(path.size()+8);
+ unsigned offset = path.size();
+ path.copy(FNBuffer, offset);
+
+ // Find a numeric suffix that isn't used by an existing file. Assume there
+ // won't be more than 1 million files with the same prefix. Probably a safe
+ // bet.
+ static unsigned FCounter = 0;
+ do {
+ sprintf(FNBuffer+offset, "-%06u", FCounter);
+ if (++FCounter > 999999)
+ FCounter = 0;
+ path = FNBuffer;
+ } while (exists());
+ return false;
+}
+
+bool
+Path::createTemporaryFileOnDisk(bool reuse_current, std::string* ErrMsg) {
+ // Make this into a unique file name
+ makeUnique(reuse_current, ErrMsg);
+
+ // Now go and create it
+ HANDLE h = CreateFile(path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_NEW,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ return MakeErrMsg(ErrMsg, path + ": can't create file");
+
+ CloseHandle(h);
+ return false;
+}
+
+/// MapInFilePages - Not yet implemented on win32.
+const char *Path::MapInFilePages(int FD, uint64_t FileSize) {
+ return 0;
+}
+
+/// MapInFilePages - Not yet implemented on win32.
+void Path::UnMapFilePages(const char *Base, uint64_t FileSize) {
+ assert(0 && "NOT IMPLEMENTED");
+}
+
+}
+}
diff --git a/lib/Support/Windows/Process.inc b/lib/Support/Windows/Process.inc
new file mode 100644
index 0000000000..06a7f0054d
--- /dev/null
+++ b/lib/Support/Windows/Process.inc
@@ -0,0 +1,222 @@
+//===- Win32/Process.cpp - Win32 Process 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 the Process class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Windows.h"
+#include <psapi.h>
+#include <malloc.h>
+#include <io.h>
+
+#ifdef __MINGW32__
+ #if (HAVE_LIBPSAPI != 1)
+ #error "libpsapi.a should be present"
+ #endif
+#else
+ #pragma comment(lib, "psapi.lib")
+#endif
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only Win32 specific code
+//=== and must not be UNIX code
+//===----------------------------------------------------------------------===//
+
+#ifdef __MINGW32__
+// This ban should be lifted when MinGW 1.0+ has defined this value.
+# define _HEAPOK (-2)
+#endif
+
+namespace llvm {
+using namespace sys;
+
+// This function retrieves the page size using GetSystemInfo and is present
+// solely so it can be called once in Process::GetPageSize to initialize the
+// static variable PageSize.
+inline unsigned GetPageSizeOnce() {
+ // NOTE: A 32-bit application running under WOW64 is supposed to use
+ // GetNativeSystemInfo. However, this interface is not present prior
+ // to Windows XP so to use it requires dynamic linking. It is not clear
+ // how this affects the reported page size, if at all. One could argue
+ // that LLVM ought to run as 64-bits on a 64-bit system, anyway.
+ SYSTEM_INFO info;
+ GetSystemInfo(&info);
+ return static_cast<unsigned>(info.dwPageSize);
+}
+
+unsigned
+Process::GetPageSize() {
+ static const unsigned PageSize = GetPageSizeOnce();
+ return PageSize;
+}
+
+size_t
+Process::GetMallocUsage()
+{
+ _HEAPINFO hinfo;
+ hinfo._pentry = NULL;
+
+ size_t size = 0;
+
+ while (_heapwalk(&hinfo) == _HEAPOK)
+ size += hinfo._size;
+
+ return size;
+}
+
+size_t
+Process::GetTotalMemoryUsage()
+{
+ PROCESS_MEMORY_COUNTERS pmc;
+ GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc));
+ return pmc.PagefileUsage;
+}
+
+void
+Process::GetTimeUsage(
+ TimeValue& elapsed, TimeValue& user_time, TimeValue& sys_time)
+{
+ elapsed = TimeValue::now();
+
+ uint64_t ProcCreate, ProcExit, KernelTime, UserTime;
+ GetProcessTimes(GetCurrentProcess(), (FILETIME*)&ProcCreate,
+ (FILETIME*)&ProcExit, (FILETIME*)&KernelTime,
+ (FILETIME*)&UserTime);
+
+ // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond)
+ user_time.seconds( UserTime / 10000000 );
+ user_time.nanoseconds( unsigned(UserTime % 10000000) * 100 );
+ sys_time.seconds( KernelTime / 10000000 );
+ sys_time.nanoseconds( unsigned(KernelTime % 10000000) * 100 );
+}
+
+int Process::GetCurrentUserId()
+{
+ return 65536;
+}
+
+int Process::GetCurrentGroupId()
+{
+ return 65536;
+}
+
+// Some LLVM programs such as bugpoint produce core files as a normal part of
+// their operation. To prevent the disk from filling up, this configuration item
+// does what's necessary to prevent their generation.
+void Process::PreventCoreFiles() {
+ // Windows doesn't do core files, but it does do modal pop-up message
+ // boxes. As this method is used by bugpoint, preventing these pop-ups
+ // is the moral equivalent of suppressing core files.
+ SetErrorMode(SEM_FAILCRITICALERRORS |
+ SEM_NOGPFAULTERRORBOX |
+ SEM_NOOPENFILEERRORBOX);
+}
+
+bool Process::StandardInIsUserInput() {
+ return FileDescriptorIsDisplayed(0);
+}
+
+bool Process::StandardOutIsDisplayed() {
+ return FileDescriptorIsDisplayed(1);
+}
+
+bool Process::StandardErrIsDisplayed() {
+ return FileDescriptorIsDisplayed(2);
+}
+
+bool Process::FileDescriptorIsDisplayed(int fd) {
+ DWORD Mode; // Unused
+ return (GetConsoleMode((HANDLE)_get_osfhandle(fd), &Mode) != 0);
+}
+
+unsigned Process::StandardOutColumns() {
+ unsigned Columns = 0;
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+ if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
+ Columns = csbi.dwSize.X;
+ return Columns;
+}
+
+unsigned Process::StandardErrColumns() {
+ unsigned Columns = 0;
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+ if (GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE), &csbi))
+ Columns = csbi.dwSize.X;
+ return Columns;
+}
+
+// It always has colors.
+bool Process::StandardErrHasColors() {
+ return StandardErrIsDisplayed();
+}
+
+bool Process::StandardOutHasColors() {
+ return StandardOutIsDisplayed();
+}
+
+namespace {
+class DefaultColors
+{
+ private:
+ WORD defaultColor;
+ public:
+ DefaultColors()
+ :defaultColor(GetCurrentColor()) {}
+ static unsigned GetCurrentColor() {
+ CONSOLE_SCREEN_BUFFER_INFO csbi;
+ if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
+ return csbi.wAttributes;
+ return 0;
+ }
+ WORD operator()() const { return defaultColor; }
+};
+
+DefaultColors defaultColors;
+}
+
+bool Process::ColorNeedsFlush() {
+ return true;
+}
+
+const char *Process::OutputBold(bool bg) {
+ WORD colors = DefaultColors::GetCurrentColor();
+ if (bg)
+ colors |= BACKGROUND_INTENSITY;
+ else
+ colors |= FOREGROUND_INTENSITY;
+ SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors);
+ return 0;
+}
+
+const char *Process::OutputColor(char code, bool bold, bool bg) {
+ WORD colors;
+ if (bg) {
+ colors = ((code&1) ? BACKGROUND_RED : 0) |
+ ((code&2) ? BACKGROUND_GREEN : 0 ) |
+ ((code&4) ? BACKGROUND_BLUE : 0);
+ if (bold)
+ colors |= BACKGROUND_INTENSITY;
+ } else {
+ colors = ((code&1) ? FOREGROUND_RED : 0) |
+ ((code&2) ? FOREGROUND_GREEN : 0 ) |
+ ((code&4) ? FOREGROUND_BLUE : 0);
+ if (bold)
+ colors |= FOREGROUND_INTENSITY;
+ }
+ SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors);
+ return 0;
+}
+
+const char *Process::ResetColor() {
+ SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), defaultColors());
+ return 0;
+}
+
+}
diff --git a/lib/Support/Windows/Program.inc b/lib/Support/Windows/Program.inc
new file mode 100644
index 0000000000..0b92c78dc8
--- /dev/null
+++ b/lib/Support/Windows/Program.inc
@@ -0,0 +1,412 @@
+//===- Win32/Program.cpp - Win32 Program 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 the Program class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Windows.h"
+#include <cstdio>
+#include <malloc.h>
+#include <io.h>
+#include <fcntl.h>
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only Win32 specific code
+//=== and must not be UNIX code
+//===----------------------------------------------------------------------===//
+
+#ifdef __MINGW32__
+// Ancient mingw32's w32api might not have this declaration.
+extern "C"
+BOOL WINAPI SetInformationJobObject(HANDLE hJob,
+ JOBOBJECTINFOCLASS JobObjectInfoClass,
+ LPVOID lpJobObjectInfo,
+ DWORD cbJobObjectInfoLength);
+#endif
+
+namespace {
+ struct Win32ProcessInfo {
+ HANDLE hProcess;
+ DWORD dwProcessId;
+ };
+}
+
+namespace llvm {
+using namespace sys;
+
+Program::Program() : Data_(0) {}
+
+Program::~Program() {
+ if (Data_) {
+ Win32ProcessInfo* wpi = reinterpret_cast<Win32ProcessInfo*>(Data_);
+ CloseHandle(wpi->hProcess);
+ delete wpi;
+ Data_ = 0;
+ }
+}
+
+unsigned Program::GetPid() const {
+ Win32ProcessInfo* wpi = reinterpret_cast<Win32ProcessInfo*>(Data_);
+ return wpi->dwProcessId;
+}
+
+// This function just uses the PATH environment variable to find the program.
+Path
+Program::FindProgramByName(const std::string& progName) {
+
+ // Check some degenerate cases
+ if (progName.length() == 0) // no program
+ return Path();
+ Path temp;
+ if (!temp.set(progName)) // invalid name
+ return Path();
+ // Return paths with slashes verbatim.
+ if (progName.find('\\') != std::string::npos ||
+ progName.find('/') != std::string::npos)
+ return temp;
+
+ // At this point, the file name is valid and does not contain slashes.
+ // Let Windows search for it.
+ char buffer[MAX_PATH];
+ char *dummy = NULL;
+ DWORD len = SearchPath(NULL, progName.c_str(), ".exe", MAX_PATH,
+ buffer, &dummy);
+
+ // See if it wasn't found.
+ if (len == 0)
+ return Path();
+
+ // See if we got the entire path.
+ if (len < MAX_PATH)
+ return Path(buffer);
+
+ // Buffer was too small; grow and retry.
+ while (true) {
+ char *b = reinterpret_cast<char *>(_alloca(len+1));
+ DWORD len2 = SearchPath(NULL, progName.c_str(), ".exe", len+1, b, &dummy);
+
+ // It is unlikely the search failed, but it's always possible some file
+ // was added or removed since the last search, so be paranoid...
+ if (len2 == 0)
+ return Path();
+ else if (len2 <= len)
+ return Path(b);
+
+ len = len2;
+ }
+}
+
+static HANDLE RedirectIO(const Path *path, int fd, std::string* ErrMsg) {
+ HANDLE h;
+ if (path == 0) {
+ DuplicateHandle(GetCurrentProcess(), (HANDLE)_get_osfhandle(fd),
+ GetCurrentProcess(), &h,
+ 0, TRUE, DUPLICATE_SAME_ACCESS);
+ return h;
+ }
+
+ const char *fname;
+ if (path->isEmpty())
+ fname = "NUL";
+ else
+ fname = path->c_str();
+
+ SECURITY_ATTRIBUTES sa;
+ sa.nLength = sizeof(sa);
+ sa.lpSecurityDescriptor = 0;
+ sa.bInheritHandle = TRUE;
+
+ h = CreateFile(fname, fd ? GENERIC_WRITE : GENERIC_READ, FILE_SHARE_READ,
+ &sa, fd == 0 ? OPEN_EXISTING : CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+ if (h == INVALID_HANDLE_VALUE) {
+ MakeErrMsg(ErrMsg, std::string(fname) + ": Can't open file for " +
+ (fd ? "input: " : "output: "));
+ }
+
+ return h;
+}
+
+/// ArgNeedsQuotes - Check whether argument needs to be quoted when calling
+/// CreateProcess.
+static bool ArgNeedsQuotes(const char *Str) {
+ return Str[0] == '\0' || strchr(Str, ' ') != 0;
+}
+
+
+/// ArgLenWithQuotes - Check whether argument needs to be quoted when calling
+/// CreateProcess and returns length of quoted arg with escaped quotes
+static unsigned int ArgLenWithQuotes(const char *Str) {
+ unsigned int len = ArgNeedsQuotes(Str) ? 2 : 0;
+
+ while (*Str != '\0') {
+ if (*Str == '\"')
+ ++len;
+
+ ++len;
+ ++Str;
+ }
+
+ return len;
+}
+
+
+bool
+Program::Execute(const Path& path,
+ const char** args,
+ const char** envp,
+ const Path** redirects,
+ unsigned memoryLimit,
+ std::string* ErrMsg) {
+ if (Data_) {
+ Win32ProcessInfo* wpi = reinterpret_cast<Win32ProcessInfo*>(Data_);
+ CloseHandle(wpi->hProcess);
+ delete wpi;
+ Data_ = 0;
+ }
+
+ if (!path.canExecute()) {
+ if (ErrMsg)
+ *ErrMsg = "program not executable";
+ return false;
+ }
+
+ // Windows wants a command line, not an array of args, to pass to the new
+ // process. We have to concatenate them all, while quoting the args that
+ // have embedded spaces (or are empty).
+
+ // First, determine the length of the command line.
+ unsigned len = 0;
+ for (unsigned i = 0; args[i]; i++) {
+ len += ArgLenWithQuotes(args[i]) + 1;
+ }
+
+ // Now build the command line.
+ char *command = reinterpret_cast<char *>(_alloca(len+1));
+ char *p = command;
+
+ for (unsigned i = 0; args[i]; i++) {
+ const char *arg = args[i];
+
+ bool needsQuoting = ArgNeedsQuotes(arg);
+ if (needsQuoting)
+ *p++ = '"';
+
+ while (*arg != '\0') {
+ if (*arg == '\"')
+ *p++ = '\\';
+
+ *p++ = *arg++;
+ }
+
+ if (needsQuoting)
+ *p++ = '"';
+ *p++ = ' ';
+ }
+
+ *p = 0;
+
+ // The pointer to the environment block for the new process.
+ char *envblock = 0;
+
+ if (envp) {
+ // An environment block consists of a null-terminated block of
+ // null-terminated strings. Convert the array of environment variables to
+ // an environment block by concatenating them.
+
+ // First, determine the length of the environment block.
+ len = 0;
+ for (unsigned i = 0; envp[i]; i++)
+ len += strlen(envp[i]) + 1;
+
+ // Now build the environment block.
+ envblock = reinterpret_cast<char *>(_alloca(len+1));
+ p = envblock;
+
+ for (unsigned i = 0; envp[i]; i++) {
+ const char *ev = envp[i];
+ size_t len = strlen(ev) + 1;
+ memcpy(p, ev, len);
+ p += len;
+ }
+
+ *p = 0;
+ }
+
+ // Create a child process.
+ STARTUPINFO si;
+ memset(&si, 0, sizeof(si));
+ si.cb = sizeof(si);
+ si.hStdInput = INVALID_HANDLE_VALUE;
+ si.hStdOutput = INVALID_HANDLE_VALUE;
+ si.hStdError = INVALID_HANDLE_VALUE;
+
+ if (redirects) {
+ si.dwFlags = STARTF_USESTDHANDLES;
+
+ si.hStdInput = RedirectIO(redirects[0], 0, ErrMsg);
+ if (si.hStdInput == INVALID_HANDLE_VALUE) {
+ MakeErrMsg(ErrMsg, "can't redirect stdin");
+ return false;
+ }
+ si.hStdOutput = RedirectIO(redirects[1], 1, ErrMsg);
+ if (si.hStdOutput == INVALID_HANDLE_VALUE) {
+ CloseHandle(si.hStdInput);
+ MakeErrMsg(ErrMsg, "can't redirect stdout");
+ return false;
+ }
+ if (redirects[1] && redirects[2] && *(redirects[1]) == *(redirects[2])) {
+ // If stdout and stderr should go to the same place, redirect stderr
+ // to the handle already open for stdout.
+ DuplicateHandle(GetCurrentProcess(), si.hStdOutput,
+ GetCurrentProcess(), &si.hStdError,
+ 0, TRUE, DUPLICATE_SAME_ACCESS);
+ } else {
+ // Just redirect stderr
+ si.hStdError = RedirectIO(redirects[2], 2, ErrMsg);
+ if (si.hStdError == INVALID_HANDLE_VALUE) {
+ CloseHandle(si.hStdInput);
+ CloseHandle(si.hStdOutput);
+ MakeErrMsg(ErrMsg, "can't redirect stderr");
+ return false;
+ }
+ }
+ }
+
+ PROCESS_INFORMATION pi;
+ memset(&pi, 0, sizeof(pi));
+
+ fflush(stdout);
+ fflush(stderr);
+ BOOL rc = CreateProcess(path.c_str(), command, NULL, NULL, TRUE, 0,
+ envblock, NULL, &si, &pi);
+ DWORD err = GetLastError();
+
+ // Regardless of whether the process got created or not, we are done with
+ // the handles we created for it to inherit.
+ CloseHandle(si.hStdInput);
+ CloseHandle(si.hStdOutput);
+ CloseHandle(si.hStdError);
+
+ // Now return an error if the process didn't get created.
+ if (!rc) {
+ SetLastError(err);
+ MakeErrMsg(ErrMsg, std::string("Couldn't execute program '") +
+ path.str() + "'");
+ return false;
+ }
+ Win32ProcessInfo* wpi = new Win32ProcessInfo;
+ wpi->hProcess = pi.hProcess;
+ wpi->dwProcessId = pi.dwProcessId;
+ Data_ = wpi;
+
+ // Make sure these get closed no matter what.
+ AutoHandle hThread(pi.hThread);
+
+ // Assign the process to a job if a memory limit is defined.
+ AutoHandle hJob(0);
+ if (memoryLimit != 0) {
+ hJob = CreateJobObject(0, 0);
+ bool success = false;
+ if (hJob != 0) {
+ JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli;
+ memset(&jeli, 0, sizeof(jeli));
+ jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_PROCESS_MEMORY;
+ jeli.ProcessMemoryLimit = uintptr_t(memoryLimit) * 1048576;
+ if (SetInformationJobObject(hJob, JobObjectExtendedLimitInformation,
+ &jeli, sizeof(jeli))) {
+ if (AssignProcessToJobObject(hJob, pi.hProcess))
+ success = true;
+ }
+ }
+ if (!success) {
+ SetLastError(GetLastError());
+ MakeErrMsg(ErrMsg, std::string("Unable to set memory limit"));
+ TerminateProcess(pi.hProcess, 1);
+ WaitForSingleObject(pi.hProcess, INFINITE);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+int
+Program::Wait(const Path &path,
+ unsigned secondsToWait,
+ std::string* ErrMsg) {
+ if (Data_ == 0) {
+ MakeErrMsg(ErrMsg, "Process not started!");
+ return -1;
+ }
+
+ Win32ProcessInfo* wpi = reinterpret_cast<Win32ProcessInfo*>(Data_);
+ HANDLE hProcess = wpi->hProcess;
+
+ // Wait for the process to terminate.
+ DWORD millisecondsToWait = INFINITE;
+ if (secondsToWait > 0)
+ millisecondsToWait = secondsToWait * 1000;
+
+ if (WaitForSingleObject(hProcess, millisecondsToWait) == WAIT_TIMEOUT) {
+ if (!TerminateProcess(hProcess, 1)) {
+ MakeErrMsg(ErrMsg, "Failed to terminate timed-out program.");
+ return -1;
+ }
+ WaitForSingleObject(hProcess, INFINITE);
+ }
+
+ // Get its exit status.
+ DWORD status;
+ BOOL rc = GetExitCodeProcess(hProcess, &status);
+ DWORD err = GetLastError();
+
+ if (!rc) {
+ SetLastError(err);
+ MakeErrMsg(ErrMsg, "Failed getting status for program.");
+ return -1;
+ }
+
+ return status;
+}
+
+bool
+Program::Kill(std::string* ErrMsg) {
+ if (Data_ == 0) {
+ MakeErrMsg(ErrMsg, "Process not started!");
+ return true;
+ }
+
+ Win32ProcessInfo* wpi = reinterpret_cast<Win32ProcessInfo*>(Data_);
+ HANDLE hProcess = wpi->hProcess;
+ if (TerminateProcess(hProcess, 1) == 0) {
+ MakeErrMsg(ErrMsg, "The process couldn't be killed!");
+ return true;
+ }
+
+ return false;
+}
+
+bool Program::ChangeStdinToBinary(){
+ int result = _setmode( _fileno(stdin), _O_BINARY );
+ return result == -1;
+}
+
+bool Program::ChangeStdoutToBinary(){
+ int result = _setmode( _fileno(stdout), _O_BINARY );
+ return result == -1;
+}
+
+bool Program::ChangeStderrToBinary(){
+ int result = _setmode( _fileno(stderr), _O_BINARY );
+ return result == -1;
+}
+
+}
diff --git a/lib/Support/Windows/RWMutex.inc b/lib/Support/Windows/RWMutex.inc
new file mode 100644
index 0000000000..82ae8af1e5
--- /dev/null
+++ b/lib/Support/Windows/RWMutex.inc
@@ -0,0 +1,58 @@
+//= llvm/System/Win32/Mutex.inc - Win32 Reader/Writer Mutual Exclusion Lock =//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Win32 specific (non-pthread) RWMutex class.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only generic Win32 code that
+//=== is guaranteed to work on *all* Win32 variants.
+//===----------------------------------------------------------------------===//
+
+#include "Windows.h"
+
+// FIXME: Windows does not have reader-writer locks pre-Vista. If you want
+// real reader-writer locks, you a threads implementation for Windows.
+
+namespace llvm {
+using namespace sys;
+
+RWMutexImpl::RWMutexImpl() {
+ data_ = calloc(1, sizeof(CRITICAL_SECTION));
+ InitializeCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
+}
+
+RWMutexImpl::~RWMutexImpl() {
+ DeleteCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
+ free(data_);
+}
+
+bool RWMutexImpl::reader_acquire() {
+ EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
+ return true;
+}
+
+bool RWMutexImpl::reader_release() {
+ LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
+ return true;
+}
+
+bool RWMutexImpl::writer_acquire() {
+ EnterCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
+ return true;
+}
+
+bool RWMutexImpl::writer_release() {
+ LeaveCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
+ return true;
+}
+
+
+}
diff --git a/lib/Support/Windows/Signals.inc b/lib/Support/Windows/Signals.inc
new file mode 100644
index 0000000000..c0e3eca3d3
--- /dev/null
+++ b/lib/Support/Windows/Signals.inc
@@ -0,0 +1,325 @@
+//===- Win32/Signals.cpp - Win32 Signals 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 the Signals class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Windows.h"
+#include <stdio.h>
+#include <vector>
+#include <algorithm>
+
+#ifdef __MINGW32__
+ #include <imagehlp.h>
+#else
+ #include <dbghelp.h>
+#endif
+#include <psapi.h>
+
+#ifdef __MINGW32__
+ #if ((HAVE_LIBIMAGEHLP != 1) || (HAVE_LIBPSAPI != 1))
+ #error "libimagehlp.a & libpsapi.a should be present"
+ #endif
+#else
+ #pragma comment(lib, "psapi.lib")
+ #pragma comment(lib, "dbghelp.lib")
+#endif
+
+// Forward declare.
+static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep);
+static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType);
+
+// InterruptFunction - The function to call if ctrl-c is pressed.
+static void (*InterruptFunction)() = 0;
+
+static std::vector<llvm::sys::Path> *FilesToRemove = NULL;
+static std::vector<std::pair<void(*)(void*), void*> > *CallBacksToRun = 0;
+static bool RegisteredUnhandledExceptionFilter = false;
+static bool CleanupExecuted = false;
+static bool ExitOnUnhandledExceptions = false;
+static PTOP_LEVEL_EXCEPTION_FILTER OldFilter = NULL;
+
+// Windows creates a new thread to execute the console handler when an event
+// (such as CTRL/C) occurs. This causes concurrency issues with the above
+// globals which this critical section addresses.
+static CRITICAL_SECTION CriticalSection;
+
+namespace llvm {
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only Win32 specific code
+//=== and must not be UNIX code
+//===----------------------------------------------------------------------===//
+
+#ifdef _MSC_VER
+/// CRTReportHook - Function called on a CRT debugging event.
+static int CRTReportHook(int ReportType, char *Message, int *Return) {
+ // Don't cause a DebugBreak() on return.
+ if (Return)
+ *Return = 0;
+
+ switch (ReportType) {
+ default:
+ case _CRT_ASSERT:
+ fprintf(stderr, "CRT assert: %s\n", Message);
+ // FIXME: Is there a way to just crash? Perhaps throw to the unhandled
+ // exception code? Perhaps SetErrorMode() handles this.
+ _exit(3);
+ break;
+ case _CRT_ERROR:
+ fprintf(stderr, "CRT error: %s\n", Message);
+ // FIXME: Is there a way to just crash? Perhaps throw to the unhandled
+ // exception code? Perhaps SetErrorMode() handles this.
+ _exit(3);
+ break;
+ case _CRT_WARN:
+ fprintf(stderr, "CRT warn: %s\n", Message);
+ break;
+ }
+
+ // Don't call _CrtDbgReport.
+ return TRUE;
+}
+#endif
+
+static void RegisterHandler() {
+ if (RegisteredUnhandledExceptionFilter) {
+ EnterCriticalSection(&CriticalSection);
+ return;
+ }
+
+ // Now's the time to create the critical section. This is the first time
+ // through here, and there's only one thread.
+ InitializeCriticalSection(&CriticalSection);
+
+ // Enter it immediately. Now if someone hits CTRL/C, the console handler
+ // can't proceed until the globals are updated.
+ EnterCriticalSection(&CriticalSection);
+
+ RegisteredUnhandledExceptionFilter = true;
+ OldFilter = SetUnhandledExceptionFilter(LLVMUnhandledExceptionFilter);
+ SetConsoleCtrlHandler(LLVMConsoleCtrlHandler, TRUE);
+
+ // Environment variable to disable any kind of crash dialog.
+ if (getenv("LLVM_DISABLE_CRT_DEBUG")) {
+#ifdef _MSC_VER
+ _CrtSetReportHook(CRTReportHook);
+#endif
+ ExitOnUnhandledExceptions = true;
+ }
+
+ // IMPORTANT NOTE: Caller must call LeaveCriticalSection(&CriticalSection) or
+ // else multi-threading problems will ensue.
+}
+
+// RemoveFileOnSignal - The public API
+bool sys::RemoveFileOnSignal(const sys::Path &Filename, std::string* ErrMsg) {
+ RegisterHandler();
+
+ if (CleanupExecuted) {
+ if (ErrMsg)
+ *ErrMsg = "Process terminating -- cannot register for removal";
+ return true;
+ }
+
+ if (FilesToRemove == NULL)
+ FilesToRemove = new std::vector<sys::Path>;
+
+ FilesToRemove->push_back(Filename);
+
+ LeaveCriticalSection(&CriticalSection);
+ return false;
+}
+
+// DontRemoveFileOnSignal - The public API
+void sys::DontRemoveFileOnSignal(const sys::Path &Filename) {
+ if (FilesToRemove == NULL)
+ return;
+
+ RegisterHandler();
+
+ FilesToRemove->push_back(Filename);
+ std::vector<sys::Path>::reverse_iterator I =
+ std::find(FilesToRemove->rbegin(), FilesToRemove->rend(), Filename);
+ if (I != FilesToRemove->rend())
+ FilesToRemove->erase(I.base()-1);
+
+ LeaveCriticalSection(&CriticalSection);
+}
+
+/// PrintStackTraceOnErrorSignal - When an error signal (such as SIBABRT or
+/// SIGSEGV) is delivered to the process, print a stack trace and then exit.
+void sys::PrintStackTraceOnErrorSignal() {
+ RegisterHandler();
+ LeaveCriticalSection(&CriticalSection);
+}
+
+
+void sys::SetInterruptFunction(void (*IF)()) {
+ RegisterHandler();
+ InterruptFunction = IF;
+ LeaveCriticalSection(&CriticalSection);
+}
+
+
+/// AddSignalHandler - Add a function to be called when a signal is delivered
+/// to the process. The handler can have a cookie passed to it to identify
+/// what instance of the handler it is.
+void sys::AddSignalHandler(void (*FnPtr)(void *), void *Cookie) {
+ if (CallBacksToRun == 0)
+ CallBacksToRun = new std::vector<std::pair<void(*)(void*), void*> >();
+ CallBacksToRun->push_back(std::make_pair(FnPtr, Cookie));
+ RegisterHandler();
+ LeaveCriticalSection(&CriticalSection);
+}
+}
+
+static void Cleanup() {
+ EnterCriticalSection(&CriticalSection);
+
+ // Prevent other thread from registering new files and directories for
+ // removal, should we be executing because of the console handler callback.
+ CleanupExecuted = true;
+
+ // FIXME: open files cannot be deleted.
+
+ if (FilesToRemove != NULL)
+ while (!FilesToRemove->empty()) {
+ FilesToRemove->back().eraseFromDisk();
+ FilesToRemove->pop_back();
+ }
+
+ if (CallBacksToRun)
+ for (unsigned i = 0, e = CallBacksToRun->size(); i != e; ++i)
+ (*CallBacksToRun)[i].first((*CallBacksToRun)[i].second);
+
+ LeaveCriticalSection(&CriticalSection);
+}
+
+void llvm::sys::RunInterruptHandlers() {
+ Cleanup();
+}
+
+static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) {
+ Cleanup();
+
+#ifdef _WIN64
+ // TODO: provide a x64 friendly version of the following
+#else
+
+ // Initialize the STACKFRAME structure.
+ STACKFRAME StackFrame;
+ memset(&StackFrame, 0, sizeof(StackFrame));
+
+ StackFrame.AddrPC.Offset = ep->ContextRecord->Eip;
+ StackFrame.AddrPC.Mode = AddrModeFlat;
+ StackFrame.AddrStack.Offset = ep->ContextRecord->Esp;
+ StackFrame.AddrStack.Mode = AddrModeFlat;
+ StackFrame.AddrFrame.Offset = ep->ContextRecord->Ebp;
+ StackFrame.AddrFrame.Mode = AddrModeFlat;
+
+ HANDLE hProcess = GetCurrentProcess();
+ HANDLE hThread = GetCurrentThread();
+
+ // Initialize the symbol handler.
+ SymSetOptions(SYMOPT_DEFERRED_LOADS|SYMOPT_LOAD_LINES);
+ SymInitialize(hProcess, NULL, TRUE);
+
+ while (true) {
+ if (!StackWalk(IMAGE_FILE_MACHINE_I386, hProcess, hThread, &StackFrame,
+ ep->ContextRecord, NULL, SymFunctionTableAccess,
+ SymGetModuleBase, NULL)) {
+ break;
+ }
+
+ if (StackFrame.AddrFrame.Offset == 0)
+ break;
+
+ // Print the PC in hexadecimal.
+ DWORD PC = StackFrame.AddrPC.Offset;
+ fprintf(stderr, "%08lX", PC);
+
+ // Print the parameters. Assume there are four.
+ fprintf(stderr, " (0x%08lX 0x%08lX 0x%08lX 0x%08lX)",
+ StackFrame.Params[0],
+ StackFrame.Params[1], StackFrame.Params[2], StackFrame.Params[3]);
+
+ // Verify the PC belongs to a module in this process.
+ if (!SymGetModuleBase(hProcess, PC)) {
+ fputs(" <unknown module>\n", stderr);
+ continue;
+ }
+
+ // Print the symbol name.
+ char buffer[512];
+ IMAGEHLP_SYMBOL *symbol = reinterpret_cast<IMAGEHLP_SYMBOL *>(buffer);
+ memset(symbol, 0, sizeof(IMAGEHLP_SYMBOL));
+ symbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL);
+ symbol->MaxNameLength = 512 - sizeof(IMAGEHLP_SYMBOL);
+
+ DWORD dwDisp;
+ if (!SymGetSymFromAddr(hProcess, PC, &dwDisp, symbol)) {
+ fputc('\n', stderr);
+ continue;
+ }
+
+ buffer[511] = 0;
+ if (dwDisp > 0)
+ fprintf(stderr, ", %s()+%04lu bytes(s)", symbol->Name, dwDisp);
+ else
+ fprintf(stderr, ", %s", symbol->Name);
+
+ // Print the source file and line number information.
+ IMAGEHLP_LINE line;
+ memset(&line, 0, sizeof(line));
+ line.SizeOfStruct = sizeof(line);
+ if (SymGetLineFromAddr(hProcess, PC, &dwDisp, &line)) {
+ fprintf(stderr, ", %s, line %lu", line.FileName, line.LineNumber);
+ if (dwDisp > 0)
+ fprintf(stderr, "+%04lu byte(s)", dwDisp);
+ }
+
+ fputc('\n', stderr);
+ }
+
+#endif
+
+ if (ExitOnUnhandledExceptions)
+ _exit(-3);
+
+ // Allow dialog box to pop up allowing choice to start debugger.
+ if (OldFilter)
+ return (*OldFilter)(ep);
+ else
+ return EXCEPTION_CONTINUE_SEARCH;
+}
+
+static BOOL WINAPI LLVMConsoleCtrlHandler(DWORD dwCtrlType) {
+ // We are running in our very own thread, courtesy of Windows.
+ EnterCriticalSection(&CriticalSection);
+ Cleanup();
+
+ // If an interrupt function has been set, go and run one it; otherwise,
+ // the process dies.
+ void (*IF)() = InterruptFunction;
+ InterruptFunction = 0; // Don't run it on another CTRL-C.
+
+ if (IF) {
+ // Note: if the interrupt function throws an exception, there is nothing
+ // to catch it in this thread so it will kill the process.
+ IF(); // Run it now.
+ LeaveCriticalSection(&CriticalSection);
+ return TRUE; // Don't kill the process.
+ }
+
+ // Allow normal processing to take place; i.e., the process dies.
+ LeaveCriticalSection(&CriticalSection);
+ return FALSE;
+}
diff --git a/lib/Support/Windows/ThreadLocal.inc b/lib/Support/Windows/ThreadLocal.inc
new file mode 100644
index 0000000000..53070ead54
--- /dev/null
+++ b/lib/Support/Windows/ThreadLocal.inc
@@ -0,0 +1,54 @@
+//= llvm/System/Win32/ThreadLocal.inc - Win32 Thread Local Data -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Win32 specific (non-pthread) ThreadLocal class.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only generic Win32 code that
+//=== is guaranteed to work on *all* Win32 variants.
+//===----------------------------------------------------------------------===//
+
+#include "Windows.h"
+#include "llvm/Support/ThreadLocal.h"
+
+namespace llvm {
+using namespace sys;
+
+ThreadLocalImpl::ThreadLocalImpl() {
+ DWORD* tls = new DWORD;
+ *tls = TlsAlloc();
+ assert(*tls != TLS_OUT_OF_INDEXES);
+ data = tls;
+}
+
+ThreadLocalImpl::~ThreadLocalImpl() {
+ DWORD* tls = static_cast<DWORD*>(data);
+ TlsFree(*tls);
+ delete tls;
+}
+
+const void* ThreadLocalImpl::getInstance() {
+ DWORD* tls = static_cast<DWORD*>(data);
+ return TlsGetValue(*tls);
+}
+
+void ThreadLocalImpl::setInstance(const void* d){
+ DWORD* tls = static_cast<DWORD*>(data);
+ int errorcode = TlsSetValue(*tls, const_cast<void*>(d));
+ assert(errorcode != 0);
+ (void)errorcode;
+}
+
+void ThreadLocalImpl::removeInstance() {
+ setInstance(0);
+}
+
+}
diff --git a/lib/Support/Windows/TimeValue.inc b/lib/Support/Windows/TimeValue.inc
new file mode 100644
index 0000000000..12275526f1
--- /dev/null
+++ b/lib/Support/Windows/TimeValue.inc
@@ -0,0 +1,51 @@
+//===- Win32/TimeValue.cpp - Win32 TimeValue 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 implementation of the TimeValue class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Windows.h"
+#include <time.h>
+
+namespace llvm {
+using namespace sys;
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only Win32 specific code.
+//===----------------------------------------------------------------------===//
+
+TimeValue TimeValue::now() {
+ uint64_t ft;
+ GetSystemTimeAsFileTime(reinterpret_cast<FILETIME *>(&ft));
+
+ TimeValue t(0, 0);
+ t.fromWin32Time(ft);
+ return t;
+}
+
+std::string TimeValue::str() const {
+#ifdef __MINGW32__
+ // This ban may be lifted by either:
+ // (i) a future MinGW version other than 1.0 inherents the __time64_t type, or
+ // (ii) configure tests for either the time_t or __time64_t type.
+ time_t ourTime = time_t(this->toEpochTime());
+ struct tm *lt = ::localtime(&ourTime);
+#else
+ __time64_t ourTime = this->toEpochTime();
+ struct tm *lt = ::_localtime64(&ourTime);
+#endif
+
+ char buffer[25];
+ strftime(buffer, 25, "%a %b %d %H:%M:%S %Y", lt);
+ return std::string(buffer);
+}
+
+
+}
diff --git a/lib/Support/Windows/Windows.h b/lib/Support/Windows/Windows.h
new file mode 100644
index 0000000000..00a7e75fc2
--- /dev/null
+++ b/lib/Support/Windows/Windows.h
@@ -0,0 +1,60 @@
+//===- Win32/Win32.h - Common Win32 Include File ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines things specific to Win32 implementations.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only generic Win32 code that
+//=== is guaranteed to work on *all* Win32 variants.
+//===----------------------------------------------------------------------===//
+
+// Require at least Windows 2000 API.
+#define _WIN32_WINNT 0x0500
+#define _WIN32_IE 0x0500 // MinGW at it again.
+#define WIN32_LEAN_AND_MEAN
+
+#include "llvm/Config/config.h" // Get build system configuration settings
+#include <Windows.h>
+#include <ShlObj.h>
+#include <cassert>
+#include <string>
+
+inline bool MakeErrMsg(std::string* ErrMsg, const std::string& prefix) {
+ if (!ErrMsg)
+ return true;
+ char *buffer = NULL;
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, GetLastError(), 0, (LPSTR)&buffer, 1, NULL);
+ *ErrMsg = prefix + buffer;
+ LocalFree(buffer);
+ return true;
+}
+
+class AutoHandle {
+ HANDLE handle;
+
+public:
+ AutoHandle(HANDLE h) : handle(h) {}
+
+ ~AutoHandle() {
+ if (handle)
+ CloseHandle(handle);
+ }
+
+ operator HANDLE() {
+ return handle;
+ }
+
+ AutoHandle &operator=(HANDLE h) {
+ handle = h;
+ return *this;
+ }
+};
diff --git a/lib/Support/Windows/system_error.inc b/lib/Support/Windows/system_error.inc
new file mode 100644
index 0000000000..db02582899
--- /dev/null
+++ b/lib/Support/Windows/system_error.inc
@@ -0,0 +1,140 @@
+//===- llvm/System/Win32/system_error.inc - Windows error_code --*- 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 Windows specific implementation of the error_code
+// and error_condition classes.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+//=== WARNING: Implementation here must contain only generic Windows code that
+//=== is guaranteed to work on *all* Windows variants.
+//===----------------------------------------------------------------------===//
+
+#include <Windows.h>
+#include <WinError.h>
+
+using namespace llvm;
+
+std::string
+_system_error_category::message(int ev) const {
+ LPVOID lpMsgBuf = 0;
+ DWORD retval = ::FormatMessageA(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ ev,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
+ (LPSTR) &lpMsgBuf,
+ 0,
+ NULL);
+ if (retval == 0) {
+ ::LocalFree(lpMsgBuf);
+ return std::string("Unknown error");
+ }
+
+ std::string str( static_cast<LPCSTR>(lpMsgBuf) );
+ ::LocalFree(lpMsgBuf);
+
+ while (str.size()
+ && (str[str.size()-1] == '\n' || str[str.size()-1] == '\r'))
+ str.erase( str.size()-1 );
+ if (str.size() && str[str.size()-1] == '.')
+ str.erase( str.size()-1 );
+ return str;
+}
+
+// I'd rather not double the line count of the following.
+#define MAP_ERR_TO_COND(x, y) case x: return make_error_condition(errc::y)
+
+error_condition
+_system_error_category::default_error_condition(int ev) const {
+ switch (ev) {
+ MAP_ERR_TO_COND(0, success);
+ // Windows system -> posix_errno decode table ---------------------------//
+ // see WinError.h comments for descriptions of errors
+ MAP_ERR_TO_COND(ERROR_ACCESS_DENIED, permission_denied);
+ MAP_ERR_TO_COND(ERROR_ALREADY_EXISTS, file_exists);
+ MAP_ERR_TO_COND(ERROR_BAD_UNIT, no_such_device);
+ MAP_ERR_TO_COND(ERROR_BUFFER_OVERFLOW, filename_too_long);
+ MAP_ERR_TO_COND(ERROR_BUSY, device_or_resource_busy);
+ MAP_ERR_TO_COND(ERROR_BUSY_DRIVE, device_or_resource_busy);
+ MAP_ERR_TO_COND(ERROR_CANNOT_MAKE, permission_denied);
+ MAP_ERR_TO_COND(ERROR_CANTOPEN, io_error);
+ MAP_ERR_TO_COND(ERROR_CANTREAD, io_error);
+ MAP_ERR_TO_COND(ERROR_CANTWRITE, io_error);
+ MAP_ERR_TO_COND(ERROR_CURRENT_DIRECTORY, permission_denied);
+ MAP_ERR_TO_COND(ERROR_DEV_NOT_EXIST, no_such_device);
+ MAP_ERR_TO_COND(ERROR_DEVICE_IN_USE, device_or_resource_busy);
+ MAP_ERR_TO_COND(ERROR_DIR_NOT_EMPTY, directory_not_empty);
+ MAP_ERR_TO_COND(ERROR_DIRECTORY, invalid_argument);
+ MAP_ERR_TO_COND(ERROR_DISK_FULL, no_space_on_device);
+ MAP_ERR_TO_COND(ERROR_FILE_EXISTS, file_exists);
+ MAP_ERR_TO_COND(ERROR_FILE_NOT_FOUND, no_such_file_or_directory);
+ MAP_ERR_TO_COND(ERROR_HANDLE_DISK_FULL, no_space_on_device);
+ MAP_ERR_TO_COND(ERROR_INVALID_ACCESS, permission_denied);
+ MAP_ERR_TO_COND(ERROR_INVALID_DRIVE, no_such_device);
+ MAP_ERR_TO_COND(ERROR_INVALID_FUNCTION, function_not_supported);
+ MAP_ERR_TO_COND(ERROR_INVALID_HANDLE, invalid_argument);
+ MAP_ERR_TO_COND(ERROR_INVALID_NAME, invalid_argument);
+ MAP_ERR_TO_COND(ERROR_LOCK_VIOLATION, no_lock_available);
+ MAP_ERR_TO_COND(ERROR_LOCKED, no_lock_available);
+ MAP_ERR_TO_COND(ERROR_NEGATIVE_SEEK, invalid_argument);
+ MAP_ERR_TO_COND(ERROR_NOACCESS, permission_denied);
+ MAP_ERR_TO_COND(ERROR_NOT_ENOUGH_MEMORY, not_enough_memory);
+ MAP_ERR_TO_COND(ERROR_NOT_READY, resource_unavailable_try_again);
+ MAP_ERR_TO_COND(ERROR_NOT_SAME_DEVICE, cross_device_link);
+ MAP_ERR_TO_COND(ERROR_OPEN_FAILED, io_error);
+ MAP_ERR_TO_COND(ERROR_OPEN_FILES, device_or_resource_busy);
+ MAP_ERR_TO_COND(ERROR_OPERATION_ABORTED, operation_canceled);
+ MAP_ERR_TO_COND(ERROR_OUTOFMEMORY, not_enough_memory);
+ MAP_ERR_TO_COND(ERROR_PATH_NOT_FOUND, no_such_file_or_directory);
+ MAP_ERR_TO_COND(ERROR_READ_FAULT, io_error);
+ MAP_ERR_TO_COND(ERROR_RETRY, resource_unavailable_try_again);
+ MAP_ERR_TO_COND(ERROR_SEEK, io_error);
+ MAP_ERR_TO_COND(ERROR_SHARING_VIOLATION, permission_denied);
+ MAP_ERR_TO_COND(ERROR_TOO_MANY_OPEN_FILES, too_many_files_open);
+ MAP_ERR_TO_COND(ERROR_WRITE_FAULT, io_error);
+ MAP_ERR_TO_COND(ERROR_WRITE_PROTECT, permission_denied);
+ MAP_ERR_TO_COND(ERROR_SEM_TIMEOUT, timed_out);
+ MAP_ERR_TO_COND(WSAEACCES, permission_denied);
+ MAP_ERR_TO_COND(WSAEADDRINUSE, address_in_use);
+ MAP_ERR_TO_COND(WSAEADDRNOTAVAIL, address_not_available);
+ MAP_ERR_TO_COND(WSAEAFNOSUPPORT, address_family_not_supported);
+ MAP_ERR_TO_COND(WSAEALREADY, connection_already_in_progress);
+ MAP_ERR_TO_COND(WSAEBADF, bad_file_descriptor);
+ MAP_ERR_TO_COND(WSAECONNABORTED, connection_aborted);
+ MAP_ERR_TO_COND(WSAECONNREFUSED, connection_refused);
+ MAP_ERR_TO_COND(WSAECONNRESET, connection_reset);
+ MAP_ERR_TO_COND(WSAEDESTADDRREQ, destination_address_required);
+ MAP_ERR_TO_COND(WSAEFAULT, bad_address);
+ MAP_ERR_TO_COND(WSAEHOSTUNREACH, host_unreachable);
+ MAP_ERR_TO_COND(WSAEINPROGRESS, operation_in_progress);
+ MAP_ERR_TO_COND(WSAEINTR, interrupted);
+ MAP_ERR_TO_COND(WSAEINVAL, invalid_argument);
+ MAP_ERR_TO_COND(WSAEISCONN, already_connected);
+ MAP_ERR_TO_COND(WSAEMFILE, too_many_files_open);
+ MAP_ERR_TO_COND(WSAEMSGSIZE, message_size);
+ MAP_ERR_TO_COND(WSAENAMETOOLONG, filename_too_long);
+ MAP_ERR_TO_COND(WSAENETDOWN, network_down);
+ MAP_ERR_TO_COND(WSAENETRESET, network_reset);
+ MAP_ERR_TO_COND(WSAENETUNREACH, network_unreachable);
+ MAP_ERR_TO_COND(WSAENOBUFS, no_buffer_space);
+ MAP_ERR_TO_COND(WSAENOPROTOOPT, no_protocol_option);
+ MAP_ERR_TO_COND(WSAENOTCONN, not_connected);
+ MAP_ERR_TO_COND(WSAENOTSOCK, not_a_socket);
+ MAP_ERR_TO_COND(WSAEOPNOTSUPP, operation_not_supported);
+ MAP_ERR_TO_COND(WSAEPROTONOSUPPORT, protocol_not_supported);
+ MAP_ERR_TO_COND(WSAEPROTOTYPE, wrong_protocol_type);
+ MAP_ERR_TO_COND(WSAETIMEDOUT, timed_out);
+ MAP_ERR_TO_COND(WSAEWOULDBLOCK, operation_would_block);
+ default: return error_condition(ev, system_category());
+ }
+}
diff --git a/lib/Support/raw_ostream.cpp b/lib/Support/raw_ostream.cpp
index d3d653983b..0279f40cab 100644
--- a/lib/Support/raw_ostream.cpp
+++ b/lib/Support/raw_ostream.cpp
@@ -13,8 +13,8 @@
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Format.h"
-#include "llvm/System/Program.h"
-#include "llvm/System/Process.h"
+#include "llvm/Support/Program.h"
+#include "llvm/Support/Process.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Config/config.h"
diff --git a/lib/Support/system_error.cpp b/lib/Support/system_error.cpp
new file mode 100644
index 0000000000..cd18906f06
--- /dev/null
+++ b/lib/Support/system_error.cpp
@@ -0,0 +1,121 @@
+//===---------------------- system_error.cpp ------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This was lifted from libc++ and modified for C++03.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/system_error.h"
+#include "llvm/Support/Errno.h"
+#include <string>
+#include <cstring>
+
+namespace llvm {
+
+// class error_category
+
+error_category::error_category() {
+}
+
+error_category::~error_category() {
+}
+
+error_condition
+error_category::default_error_condition(int ev) const {
+ return error_condition(ev, *this);
+}
+
+bool
+error_category::equivalent(int code, const error_condition& condition) const {
+ return default_error_condition(code) == condition;
+}
+
+bool
+error_category::equivalent(const error_code& code, int condition) const {
+ return *this == code.category() && code.value() == condition;
+}
+
+std::string
+_do_message::message(int ev) const {
+ return std::string(sys::StrError(ev));
+}
+
+class _generic_error_category : public _do_message {
+public:
+ virtual const char* name() const;
+ virtual std::string message(int ev) const;
+};
+
+const char*
+_generic_error_category::name() const {
+ return "generic";
+}
+
+std::string
+_generic_error_category::message(int ev) const {
+#ifdef ELAST
+ if (ev > ELAST)
+ return std::string("unspecified generic_category error");
+#endif // ELAST
+ return _do_message::message(ev);
+}
+
+const error_category&
+generic_category() {
+ static _generic_error_category s;
+ return s;
+}
+
+class _system_error_category : public _do_message {
+public:
+ virtual const char* name() const;
+ virtual std::string message(int ev) const;
+ virtual error_condition default_error_condition(int ev) const;
+};
+
+const char*
+_system_error_category::name() const {
+ return "system";
+}
+
+// std::string _system_error_category::message(int ev) const {
+// Is in Platform/system_error.inc
+
+// error_condition _system_error_category::default_error_condition(int ev) const
+// Is in Platform/system_error.inc
+
+const error_category&
+system_category() {
+ static _system_error_category s;
+ return s;
+}
+
+// error_condition
+
+std::string
+error_condition::message() const {
+ return _cat_->message(_val_);
+}
+
+// error_code
+
+std::string
+error_code::message() const {
+ return _cat_->message(_val_);
+}
+
+} // end namespace llvm
+
+// Include the truly platform-specific parts of this class.
+#if defined(LLVM_ON_UNIX)
+#include "Unix/system_error.inc"
+#endif
+#if defined(LLVM_ON_WIN32)
+#include "Windows/system_error.inc"
+#endif