Re-sort all of the includes with ./utils/sort_includes.py so that
[oota-llvm.git] / lib / Support / Windows / Process.inc
1 //===- Win32/Process.cpp - Win32 Process Implementation ------- -*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file provides the Win32 specific implementation of the Process class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/Support/Allocator.h"
15 #include <direct.h>
16 #include <io.h>
17 #include <malloc.h>
18 #include <psapi.h>
19 #include <shellapi.h>
20
21 // The Windows.h header must be the last one included.
22 #include "Windows.h"
23
24 #ifdef __MINGW32__
25  #if (HAVE_LIBPSAPI != 1)
26   #error "libpsapi.a should be present"
27  #endif
28  #if (HAVE_LIBSHELL32 != 1)
29   #error "libshell32.a should be present"
30  #endif
31 #else
32  #pragma comment(lib, "psapi.lib")
33  #pragma comment(lib, "shell32.lib")
34 #endif
35
36 //===----------------------------------------------------------------------===//
37 //=== WARNING: Implementation here must contain only Win32 specific code
38 //===          and must not be UNIX code
39 //===----------------------------------------------------------------------===//
40
41 #ifdef __MINGW32__
42 // This ban should be lifted when MinGW 1.0+ has defined this value.
43 #  define _HEAPOK (-2)
44 #endif
45
46 using namespace llvm;
47 using namespace sys;
48
49
50 process::id_type self_process::get_id() {
51   return GetCurrentProcessId();
52 }
53
54 static TimeValue getTimeValueFromFILETIME(FILETIME Time) {
55   ULARGE_INTEGER TimeInteger;
56   TimeInteger.LowPart = Time.dwLowDateTime;
57   TimeInteger.HighPart = Time.dwHighDateTime;
58
59   // FILETIME's are # of 100 nanosecond ticks (1/10th of a microsecond)
60   return TimeValue(
61       static_cast<TimeValue::SecondsType>(TimeInteger.QuadPart / 10000000),
62       static_cast<TimeValue::NanoSecondsType>(
63           (TimeInteger.QuadPart % 10000000) * 100));
64 }
65
66 TimeValue self_process::get_user_time() const {
67   FILETIME ProcCreate, ProcExit, KernelTime, UserTime;
68   if (GetProcessTimes(GetCurrentProcess(), &ProcCreate, &ProcExit, &KernelTime,
69                       &UserTime) == 0)
70     return TimeValue();
71
72   return getTimeValueFromFILETIME(UserTime);
73 }
74
75 TimeValue self_process::get_system_time() const {
76   FILETIME ProcCreate, ProcExit, KernelTime, UserTime;
77   if (GetProcessTimes(GetCurrentProcess(), &ProcCreate, &ProcExit, &KernelTime,
78                       &UserTime) == 0)
79     return TimeValue();
80
81   return getTimeValueFromFILETIME(KernelTime);
82 }
83
84 // This function retrieves the page size using GetSystemInfo and is present
85 // solely so it can be called once to initialize the self_process member below.
86 static unsigned getPageSize() {
87   // NOTE: A 32-bit application running under WOW64 is supposed to use
88   // GetNativeSystemInfo.  However, this interface is not present prior
89   // to Windows XP so to use it requires dynamic linking.  It is not clear
90   // how this affects the reported page size, if at all.  One could argue
91   // that LLVM ought to run as 64-bits on a 64-bit system, anyway.
92   SYSTEM_INFO info;
93   GetSystemInfo(&info);
94   // FIXME: FileOffset in MapViewOfFile() should be aligned to not dwPageSize,
95   // but dwAllocationGranularity.
96   return static_cast<unsigned>(info.dwPageSize);
97 }
98
99 // This constructor guaranteed to be run exactly once on a single thread, and
100 // sets up various process invariants that can be queried cheaply from then on.
101 self_process::self_process() : PageSize(getPageSize()) {
102 }
103
104
105 size_t
106 Process::GetMallocUsage()
107 {
108   _HEAPINFO hinfo;
109   hinfo._pentry = NULL;
110
111   size_t size = 0;
112
113   while (_heapwalk(&hinfo) == _HEAPOK)
114     size += hinfo._size;
115
116   return size;
117 }
118
119 void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time,
120                            TimeValue &sys_time) {
121   elapsed = TimeValue::now();
122
123   FILETIME ProcCreate, ProcExit, KernelTime, UserTime;
124   if (GetProcessTimes(GetCurrentProcess(), &ProcCreate, &ProcExit, &KernelTime,
125                       &UserTime) == 0)
126     return;
127
128   user_time = getTimeValueFromFILETIME(UserTime);
129   sys_time = getTimeValueFromFILETIME(KernelTime);
130 }
131
132 // Some LLVM programs such as bugpoint produce core files as a normal part of
133 // their operation. To prevent the disk from filling up, this configuration
134 // item does what's necessary to prevent their generation.
135 void Process::PreventCoreFiles() {
136   // Windows does have the concept of core files, called minidumps.  However,
137   // disabling minidumps for a particular application extends past the lifetime
138   // of that application, which is the incorrect behavior for this API.
139   // Additionally, the APIs require elevated privileges to disable and re-
140   // enable minidumps, which makes this untenable. For more information, see
141   // WerAddExcludedApplication and WerRemoveExcludedApplication (Vista and
142   // later).
143   //
144   // Windows also has modal pop-up message boxes.  As this method is used by
145   // bugpoint, preventing these pop-ups is additionally important.
146   SetErrorMode(SEM_FAILCRITICALERRORS |
147                SEM_NOGPFAULTERRORBOX |
148                SEM_NOOPENFILEERRORBOX);
149 }
150
151 /// Returns the environment variable \arg Name's value as a string encoded in
152 /// UTF-8. \arg Name is assumed to be in UTF-8 encoding.
153 Optional<std::string> Process::GetEnv(StringRef Name) {
154   // Convert the argument to UTF-16 to pass it to _wgetenv().
155   SmallVector<wchar_t, 128> NameUTF16;
156   if (error_code ec = windows::UTF8ToUTF16(Name, NameUTF16))
157     return None;
158
159   // Environment variable can be encoded in non-UTF8 encoding, and there's no
160   // way to know what the encoding is. The only reliable way to look up
161   // multibyte environment variable is to use GetEnvironmentVariableW().
162   SmallVector<wchar_t, MAX_PATH> Buf;
163   size_t Size = MAX_PATH;
164   do {
165     Buf.reserve(Size);
166     Size =
167         GetEnvironmentVariableW(NameUTF16.data(), Buf.data(), Buf.capacity());
168     if (Size == 0)
169       return None;
170
171     // Try again with larger buffer.
172   } while (Size > Buf.capacity());
173   Buf.set_size(Size);
174
175   // Convert the result from UTF-16 to UTF-8.
176   SmallVector<char, MAX_PATH> Res;
177   if (error_code ec = windows::UTF16ToUTF8(Buf.data(), Size, Res))
178     return None;
179   return std::string(Res.data());
180 }
181
182 error_code
183 Process::GetArgumentVector(SmallVectorImpl<const char *> &Args,
184                            ArrayRef<const char *>,
185                            SpecificBumpPtrAllocator<char> &ArgAllocator) {
186   int NewArgCount;
187   error_code ec;
188
189   wchar_t **UnicodeCommandLine = CommandLineToArgvW(GetCommandLineW(),
190                                                     &NewArgCount);
191   if (!UnicodeCommandLine)
192     return windows_error(::GetLastError());
193
194   Args.reserve(NewArgCount);
195
196   for (int i = 0; i < NewArgCount; ++i) {
197     SmallVector<char, MAX_PATH> NewArgString;
198     ec = windows::UTF16ToUTF8(UnicodeCommandLine[i],
199                               wcslen(UnicodeCommandLine[i]),
200                               NewArgString);
201     if (ec)
202       break;
203
204     char *Buffer = ArgAllocator.Allocate(NewArgString.size() + 1);
205     ::memcpy(Buffer, NewArgString.data(), NewArgString.size() + 1);
206     Args.push_back(Buffer);
207   }
208   LocalFree(UnicodeCommandLine);
209   if (ec)
210     return ec;
211
212   return error_code::success();
213 }
214
215 bool Process::StandardInIsUserInput() {
216   return FileDescriptorIsDisplayed(0);
217 }
218
219 bool Process::StandardOutIsDisplayed() {
220   return FileDescriptorIsDisplayed(1);
221 }
222
223 bool Process::StandardErrIsDisplayed() {
224   return FileDescriptorIsDisplayed(2);
225 }
226
227 bool Process::FileDescriptorIsDisplayed(int fd) {
228   DWORD Mode;  // Unused
229   return (GetConsoleMode((HANDLE)_get_osfhandle(fd), &Mode) != 0);
230 }
231
232 unsigned Process::StandardOutColumns() {
233   unsigned Columns = 0;
234   CONSOLE_SCREEN_BUFFER_INFO csbi;
235   if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
236     Columns = csbi.dwSize.X;
237   return Columns;
238 }
239
240 unsigned Process::StandardErrColumns() {
241   unsigned Columns = 0;
242   CONSOLE_SCREEN_BUFFER_INFO csbi;
243   if (GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE), &csbi))
244     Columns = csbi.dwSize.X;
245   return Columns;
246 }
247
248 // The terminal always has colors.
249 bool Process::FileDescriptorHasColors(int fd) {
250   return FileDescriptorIsDisplayed(fd);
251 }
252
253 bool Process::StandardOutHasColors() {
254   return FileDescriptorHasColors(1);
255 }
256
257 bool Process::StandardErrHasColors() {
258   return FileDescriptorHasColors(2);
259 }
260
261 static bool UseANSI = false;
262 void Process::UseANSIEscapeCodes(bool enable) {
263   UseANSI = enable;
264 }
265
266 namespace {
267 class DefaultColors
268 {
269   private:
270     WORD defaultColor;
271   public:
272     DefaultColors()
273      :defaultColor(GetCurrentColor()) {}
274     static unsigned GetCurrentColor() {
275       CONSOLE_SCREEN_BUFFER_INFO csbi;
276       if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
277         return csbi.wAttributes;
278       return 0;
279     }
280     WORD operator()() const { return defaultColor; }
281 };
282
283 DefaultColors defaultColors;
284 }
285
286 bool Process::ColorNeedsFlush() {
287   return !UseANSI;
288 }
289
290 const char *Process::OutputBold(bool bg) {
291   if (UseANSI) return "\033[1m";
292
293   WORD colors = DefaultColors::GetCurrentColor();
294   if (bg)
295     colors |= BACKGROUND_INTENSITY;
296   else
297     colors |= FOREGROUND_INTENSITY;
298   SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors);
299   return 0;
300 }
301
302 const char *Process::OutputColor(char code, bool bold, bool bg) {
303   if (UseANSI) return colorcodes[bg?1:0][bold?1:0][code&7];
304
305   WORD colors;
306   if (bg) {
307     colors = ((code&1) ? BACKGROUND_RED : 0) |
308       ((code&2) ? BACKGROUND_GREEN : 0 ) |
309       ((code&4) ? BACKGROUND_BLUE : 0);
310     if (bold)
311       colors |= BACKGROUND_INTENSITY;
312   } else {
313     colors = ((code&1) ? FOREGROUND_RED : 0) |
314       ((code&2) ? FOREGROUND_GREEN : 0 ) |
315       ((code&4) ? FOREGROUND_BLUE : 0);
316     if (bold)
317       colors |= FOREGROUND_INTENSITY;
318   }
319   SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors);
320   return 0;
321 }
322
323 static WORD GetConsoleTextAttribute(HANDLE hConsoleOutput) {
324   CONSOLE_SCREEN_BUFFER_INFO info;
325   GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
326   return info.wAttributes;
327 }
328
329 const char *Process::OutputReverse() {
330   if (UseANSI) return "\033[7m";
331
332   const WORD attributes
333    = GetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE));
334
335   const WORD foreground_mask = FOREGROUND_BLUE | FOREGROUND_GREEN |
336     FOREGROUND_RED | FOREGROUND_INTENSITY;
337   const WORD background_mask = BACKGROUND_BLUE | BACKGROUND_GREEN |
338     BACKGROUND_RED | BACKGROUND_INTENSITY;
339   const WORD color_mask = foreground_mask | background_mask;
340
341   WORD new_attributes =
342     ((attributes & FOREGROUND_BLUE     )?BACKGROUND_BLUE     :0) |
343     ((attributes & FOREGROUND_GREEN    )?BACKGROUND_GREEN    :0) |
344     ((attributes & FOREGROUND_RED      )?BACKGROUND_RED      :0) |
345     ((attributes & FOREGROUND_INTENSITY)?BACKGROUND_INTENSITY:0) |
346     ((attributes & BACKGROUND_BLUE     )?FOREGROUND_BLUE     :0) |
347     ((attributes & BACKGROUND_GREEN    )?FOREGROUND_GREEN    :0) |
348     ((attributes & BACKGROUND_RED      )?FOREGROUND_RED      :0) |
349     ((attributes & BACKGROUND_INTENSITY)?FOREGROUND_INTENSITY:0) |
350     0;
351   new_attributes = (attributes & ~color_mask) | (new_attributes & color_mask);
352
353   SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), new_attributes);
354   return 0;
355 }
356
357 const char *Process::ResetColor() {
358   if (UseANSI) return "\033[0m";
359   SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), defaultColors());
360   return 0;
361 }