Reduce I/O operations caused by the check of address validity.

This commit is contained in:
CristinaCristescu 2016-04-08 15:07:46 +02:00 committed by sftnight
parent 1bd499bb15
commit fc500ad68e
4 changed files with 77 additions and 39 deletions

View File

@ -10,50 +10,12 @@
#ifndef CLING_UTILS_VALIDATION_H
#define CLING_UTILS_VALIDATION_H
#include "llvm/Config/config.h" // for LLVM_ON_WIN32
#include <assert.h>
#include <errno.h>
#ifdef LLVM_ON_WIN32
# define WIN32_LEAN_AND_MEAN
# define NOGDI
# include <Windows.h>
#else
# include <unistd.h>
#endif
namespace cling {
namespace utils{
// Checking whether the pointer points to a valid memory location
// Used for checking of void* output
// Should be moved to earlier stages (ex. IR) in the future
static bool isAddressValid(const void *P) {
if (!P || P == (void *) -1)
return false;
#ifdef LLVM_ON_WIN32
MEMORY_BASIC_INFORMATION MBI;
if (!VirtualQuery(P, &MBI, sizeof(MBI)))
return false;
if (MBI.State != MEM_COMMIT)
return false;
return true;
#else
// There is a POSIX way of finding whether an address can be accessed for
// reading: write() will return EFAULT if not.
int FD[2];
if (pipe(FD))
return false; // error in pipe()? Be conservative...
int NBytes = write(FD[1], P, 1/*byte*/);
close(FD[0]);
close(FD[1]);
if (NBytes != 1) {
assert(errno == EFAULT && "unexpected pipe write error");
return false;
}
return true;
#endif
}
bool isAddressValid(const void *P);
}
}

View File

@ -92,6 +92,12 @@ namespace cling {
return true;
}
bool VisitDecl (Decl* D)
{
printf("%ld\n", *(long*)D);
return true;
}
bool VisitFunctionDecl(FunctionDecl* FD) {
if (!FD->isConstexpr()) {
CompoundStmt* CS = dyn_cast_or_null<CompoundStmt>(FD->getBody());

View File

@ -8,6 +8,7 @@
add_cling_library(clingUtils
AST.cpp
Validation.cpp
LINK_LIBS
clangCodeGen

69
lib/Utils/Validation.cpp Normal file
View File

@ -0,0 +1,69 @@
//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// author: Vassil Vassilev <vasil.georgiev.vasilev@cern.ch>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------
#include "cling/Utils/Validation.h"
#include <assert.h>
#include <errno.h>
#ifdef LLVM_ON_WIN32
# include <Windows.h>
#else
#include <fcntl.h>
# include <unistd.h>
#endif
namespace cling {
namespace utils {
static int getNullDevFileDescriptor() {
#ifdef LLVM_ON_WIN32
return 0;
#else
struct FileDescriptor {
int FD;
const char* file = "/dev/null";
FileDescriptor() { FD = open(file, O_WRONLY); }
~FileDescriptor() {
close(FD);
}
};
static FileDescriptor nullDev;
return nullDev.FD;
#endif
}
// Checking whether the pointer points to a valid memory location
// Used for checking of void* output
// Should be moved to earlier stages (ex. IR) in the future
bool isAddressValid(const void *P) {
if (!P || P == (void *) -1)
return false;
#ifdef LLVM_ON_WIN32
MEMORY_BASIC_INFORMATION MBI;
if (!VirtualQuery(P, &MBI, sizeof(MBI)))
return false;
if (MBI.State != MEM_COMMIT)
return false;
return true;
#else
// There is a POSIX way of finding whether an address can be accessed for
// reading: write() will return EFAULT if not.
int NBytes = write(getNullDevFileDescriptor(), P, 1/*byte*/);
if (NBytes != 1) {
assert(errno == EFAULT && "unexpected pipe write error");
return false;
}
return true;
#endif
}
}
}