Skip to content

Commit 32c39b2

Browse files
author
Pavel Kosov
committed
Support Windows
After this patch LNT can be installed on Windows with preinstalled C++ compiler, e.g. Microsoft Visual Studio. OS Laboratory. Huawei Russian Research Institute. Saint-Petersburg Reviewed By: danilaml Differential Revision: https://reviews.llvm.org/D114337
1 parent 2afddc4 commit 32c39b2

File tree

1 file changed

+101
-5
lines changed

1 file changed

+101
-5
lines changed

lnt/testing/profile/cPerf.cpp

Lines changed: 101 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,15 @@
5757
//
5858
//===----------------------------------------------------------------------===//
5959

60+
#ifdef _WIN32
61+
#define WIN32_LEAN_AND_MEAN
62+
#define _CRT_SECURE_NO_WARNINGS
63+
#define strtok_r strtok_s
64+
#include <windows.h>
65+
#include <BaseTsd.h>
66+
typedef SSIZE_T ssize_t;
67+
#define PROT_EXEC 4
68+
#endif
6069
#include <Python.h>
6170
#include <algorithm>
6271
#include <cassert>
@@ -69,10 +78,12 @@
6978
#include <stdint.h>
7079
#include <stdio.h>
7180
#include <stdlib.h>
81+
#ifndef _WIN32
7282
#include <sys/mman.h>
73-
#include <sys/stat.h>
7483
#include <sys/wait.h>
7584
#include <unistd.h>
85+
#endif
86+
#include <sys/stat.h>
7687
#include <vector>
7788

7889
//===----------------------------------------------------------------------===//
@@ -106,6 +117,10 @@ uint64_t TakeU64(unsigned char *&Buf) {
106117
// Forks, execs Cmd under a shell and returns
107118
// a file descriptor reading the command's stdout.
108119
FILE *ForkAndExec(std::string Cmd) {
120+
#ifdef _WIN32
121+
Cmd = "cmd.exe /c " + Cmd;
122+
FILE *Stream = _popen(Cmd.c_str(), "rt");
123+
#else
109124
int P[2];
110125
pipe(P);
111126

@@ -118,10 +133,43 @@ FILE *ForkAndExec(std::string Cmd) {
118133
} else {
119134
close(P[1]);
120135
}
121-
136+
#endif
122137
return Stream;
123138
}
124139

140+
#ifdef _WIN32
141+
ssize_t getline(char** lineptr, size_t* n, FILE* stream) {
142+
if (lineptr == nullptr || stream == nullptr || n == nullptr) return -1;
143+
int c = fgetc(stream);
144+
if (c == EOF) return -1;
145+
char* bufptr = *lineptr;
146+
size_t size = *n;
147+
if (bufptr == nullptr) {
148+
size = 128;
149+
bufptr = (char*)malloc(size);
150+
if (bufptr == nullptr) return -1;
151+
*lineptr = bufptr;
152+
}
153+
char* p = bufptr;
154+
while (c != EOF) {
155+
size_t offset = (size_t)(p - bufptr);
156+
if ((offset + 2) > size)) {
157+
size = size + 128;
158+
bufptr = (char*)realloc(bufptr, size);
159+
if (bufptr == nullptr) return -1;
160+
*lineptr = bufptr;
161+
p = bufptr + offset;
162+
}
163+
*p++ = c;
164+
if (c == '\n') break;
165+
c = fgetc(stream);
166+
}
167+
*p = '\0';
168+
*n = size;
169+
return p - bufptr;
170+
}
171+
#endif
172+
125173
void Assert(bool Expr, const char *ExprStr, const char *File, int Line) {
126174
if (Expr)
127175
return;
@@ -228,8 +276,6 @@ struct perf_event_mmap {
228276
char filename[1];
229277
};
230278

231-
#define PROT_EXEC 4
232-
233279
struct perf_event_mmap2 {
234280
struct perf_event_header header;
235281

@@ -348,7 +394,11 @@ class NmOutput : public std::vector<Symbol> {
348394
D = "";
349395
std::string Cmd = Nm + " " + D + " -S --defined-only " +
350396
BinaryCacheRoot + std::string(M->Filename) +
397+
#ifdef _WIN32
398+
" 2> NUL";
399+
#else
351400
" 2>/dev/null";
401+
#endif
352402
auto Stream = ForkAndExec(Cmd);
353403

354404
char *Line = nullptr;
@@ -394,8 +444,12 @@ class NmOutput : public std::vector<Symbol> {
394444
if (Line)
395445
free(Line);
396446

447+
#ifdef _WIN32
448+
_pclose(Stream);
449+
#else
397450
fclose(Stream);
398451
wait(NULL);
452+
#endif
399453
}
400454

401455
void reset(Map *M) {
@@ -435,8 +489,12 @@ class ObjdumpOutput {
435489
Line(NULL), LineLen(0) {}
436490
~ObjdumpOutput() {
437491
if (Stream) {
492+
#ifdef _WIN32
493+
_pclose(Stream);
494+
#else
438495
fclose(Stream);
439496
wait(NULL);
497+
#endif
440498
}
441499
if (Line)
442500
free(Line);
@@ -446,8 +504,12 @@ class ObjdumpOutput {
446504
ThisAddress = 0;
447505
ThisText = "";
448506
if (Stream) {
507+
#ifdef _WIN32
508+
_pclose(Stream);
509+
#else
449510
fclose(Stream);
450511
wait(NULL);
512+
#endif
451513
}
452514

453515
char buf1[32], buf2[32];
@@ -458,7 +520,11 @@ class ObjdumpOutput {
458520
std::string(buf1) + " --stop-address=" +
459521
std::string(buf2) + " " +
460522
BinaryCacheRoot + std::string(M->Filename) +
523+
#ifdef _WIN32
524+
" 2> NUL";
525+
#else
461526
" 2>/dev/null";
527+
#endif
462528
Stream = ForkAndExec(Cmd);
463529

464530
EndAddress = Stop;
@@ -528,7 +594,12 @@ class PerfReader {
528594

529595
private:
530596
unsigned char *Buffer;
597+
#ifdef _WIN32
598+
HANDLE hFile;
599+
HANDLE hMapFile;
600+
#else
531601
size_t BufferLen;
602+
#endif
532603

533604
perf_header *Header;
534605
std::map<uint64_t, const char *> EventIDs;
@@ -551,6 +622,20 @@ PerfReader::PerfReader(const std::string &Filename,
551622
: Nm(Nm), Objdump(Objdump), BinaryCacheRoot(BinaryCacheRoot) {
552623
TopLevelCounters = PyDict_New();
553624
Functions = PyDict_New();
625+
#ifdef _WIN32
626+
Buffer = nullptr;
627+
hMapFile = nullptr;
628+
hFile = ::CreateFileA(Filename.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL,
629+
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
630+
assert(hFile != INVALID_HANDLE_VALUE);
631+
LARGE_INTEGER size;
632+
size.QuadPart = 0;
633+
assert(::GetFileSizeEx(hFile, &size) != FALSE);
634+
hMapFile = ::CreateFileMapping(hFile, NULL, PAGE_READONLY, size.HighPart, size.LowPart, NULL);
635+
assert(hMapFile != nullptr);
636+
Buffer = (unsigned char*)::MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
637+
assert(Buffer != nullptr);
638+
#else
554639
int fd = open(Filename.c_str(), O_RDONLY);
555640
assert(fd > 0);
556641

@@ -560,9 +645,20 @@ PerfReader::PerfReader(const std::string &Filename,
560645

561646
Buffer = (unsigned char *)mmap(NULL, BufferLen, PROT_READ, MAP_SHARED, fd, 0);
562647
assert(Buffer != MAP_FAILED);
648+
#endif
563649
}
564650

565-
PerfReader::~PerfReader() { munmap(Buffer, BufferLen); }
651+
PerfReader::~PerfReader() {
652+
#ifdef _WIN32
653+
if (hMapFile != NULL) {
654+
if (Buffer != NULL) ::UnmapViewOfFile(Buffer);
655+
::CloseHandle(hMapFile);
656+
}
657+
if (hFile != INVALID_HANDLE_VALUE) ::CloseHandle(hFile);
658+
#else
659+
munmap(Buffer, BufferLen);
660+
#endif
661+
}
566662

567663
void PerfReader::readHeader() {
568664
Header = (perf_header *)&Buffer[0];

0 commit comments

Comments
 (0)