first commit for modified ptxgen

This commit is contained in:
evghenii
2015-01-29 11:38:50 +01:00
parent 5d7c147a6a
commit 24acd3f492
2 changed files with 103 additions and 184 deletions

View File

@@ -33,7 +33,7 @@
all: ptxcc ptxgen
CXX=clang++
CXXFLAGS += -O3
CXXFLAGS += -O3 --std=c++11
CXXFLAGS += -I/opt/local/include
LD=clang++

View File

@@ -56,39 +56,44 @@ static std::string lValueToString(const T& value)
return oss.str();
}
typedef struct stat Stat;
#define PTXGENStatus int
enum {
PTXGEN_SUCCESS = 0x0000,
PTXGEN_FILE_IO_ERROR = 0x0001,
PTXGEN_BAD_ALLOC_ERROR = 0x0002,
PTXGEN_LIBNVVM_COMPILATION_ERROR = 0x0004,
PTXGEN_LIBNVVM_ERROR = 0x0008,
PTXGEN_INVALID_USAGE = 0x0010,
PTXGEN_LIBNVVM_HOME_UNDEFINED = 0x0020,
PTXGEN_LIBNVVM_VERIFICATION_ERROR = 0x0040
struct Exception : public std::exception
{
std::string s;
Exception(std::string ss) : s(ss) {}
~Exception() throw () {} // Updated
const char* what() const throw() { return s.c_str(); }
};
struct NVVMProg
{
nvvmProgram prog;
NVVMProg()
{
if (nvvmCreateProgram(&prog) != NVVM_SUCCESS)
throw Exception(std::string("Failed to create the compilation unit."));
}
~NVVMProg() { nvvmDestroyProgram(&prog); }
nvvmProgram get() const {return prog; }
};
static PTXGENStatus getLibDeviceName(const int computeArch, std::string &libDeviceName)
static std::string getLibDeviceName(const int computeArch)
{
const char *env = getenv("LIBNVVM_HOME");
#ifdef LIBNVVM_HOME
#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
const std::string libnvvmPath(env ? env : TOSTRING(LIBNVVM_HOME));
const std::string libnvvmPath1(env ? env : TOSTRING(LIBNVVM_HOME));
#undef TOSTRING
#undef STRINGIFY
#else
const std::string libnvvmPath(env);
const std::string libnvvmPath1(env);
#endif
const std::string libnvvmPath(env == nullptr ? libnvvmPath1 : std::string(env));
if (libnvvmPath.empty())
{
fprintf(stderr, "The environment variable LIBNVVM_HOME is undefined\n");
return PTXGEN_LIBNVVM_HOME_UNDEFINED;
}
throw Exception("The environment variable LIBNVVM_HOME is undefined");
/* Use libdevice for compute_20, if the target is not compute_20, compute_30,
* or compute_35. */
@@ -99,194 +104,101 @@ static PTXGENStatus getLibDeviceName(const int computeArch, std::string &libDevi
lValueToString(LIBDEVICE_MINOR_VERSION) +
".bc";
libDeviceName = libnvvmPath + libdevice;
return PTXGEN_SUCCESS;
return libnvvmPath + libdevice;
}
static PTXGENStatus addFileToProgram(const std::string &filename, nvvmProgram prog)
static void addFileToProgram(const std::string &filename, NVVMProg &prog)
{
char *buffer;
size_t size;
Stat fileStat;
/* Open the input file. */
FILE *f = fopen(filename.c_str(), "rb");
if (f == NULL) {
fprintf(stderr, "Failed to open %s\n", filename.c_str());
return PTXGEN_FILE_IO_ERROR;
}
if (f == NULL)
throw Exception(std::string("Failed to open ") + filename);
/* Allocate buffer for the input. */
struct stat fileStat;
fstat(fileno(f), &fileStat);
buffer = (char *) malloc(fileStat.st_size);
if (buffer == NULL) {
fprintf(stderr, "Failed to allocate memory\n");
return PTXGEN_BAD_ALLOC_ERROR;
}
size = fread(buffer, 1, fileStat.st_size, f);
if (ferror(f)) {
fprintf(stderr, "Failed to read %s\n", filename.c_str());
fclose(f);
free(buffer);
return PTXGEN_FILE_IO_ERROR;
}
std::string buffer(fileStat.st_size,0);
/* Read input file */
const size_t size = fread(&buffer[0], 1, fileStat.st_size, f);
const auto error = ferror(f);
fclose(f);
if (error)
throw Exception(std::string("Failed to read ") + filename + ".");
if (nvvmAddModuleToProgram(prog, buffer, size, filename.c_str()) != NVVM_SUCCESS) {
fprintf(stderr,
"Failed to add the module %s to the compilation unit\n",
filename.c_str());
free(buffer);
return PTXGEN_LIBNVVM_ERROR;
}
free(buffer);
return PTXGEN_SUCCESS;
/* Add IR block to a program */
if (nvvmAddModuleToProgram(prog.get(), buffer.c_str(), size, filename.c_str()) != NVVM_SUCCESS)
throw Exception(
std::string("Failed to add the module ") + filename + " to the compilation unit.");
}
static PTXGENStatus generatePTX(
std::vector<std::string> nvvmOptions,
std::vector<std::string> nvvmFiles,
std::ostream &out,
static void printWarningsAndErrors(NVVMProg &prog)
{
size_t logSize;
if (nvvmGetProgramLogSize(prog.get(), &logSize) == NVVM_SUCCESS)
{
std::string log(logSize,0);
if (nvvmGetProgramLog(prog.get(), &log[0]) == NVVM_SUCCESS && logSize > 1)
{
std::cerr << "--------------------------------------\n";
std::cerr << log << std::endl;
std::cerr << "--------------------------------------\n";
}
else throw Exception("Failed to get the compilation log.");
}
else throw Exception("Failed to get the compilation log size.");
}
static std::string generatePTX(
const std::vector<std::string> &nvvmOptions,
const std::vector<std::string> &nvvmFiles,
const int computeArch)
{
nvvmProgram prog;
PTXGENStatus status;
std::string ptxString;
/* Create the compiliation unit. */
if (nvvmCreateProgram(&prog) != NVVM_SUCCESS)
{
fprintf(stderr, "Failed to create the compilation unit\n");
return PTXGEN_LIBNVVM_ERROR;
}
NVVMProg prog;
/* Add libdevice. */
std::string libDeviceName;
status = getLibDeviceName(computeArch, libDeviceName);
if (status != PTXGEN_SUCCESS)
try
{
nvvmDestroyProgram(&prog);
return status;
}
status = addFileToProgram(libDeviceName, prog);
if (status != PTXGEN_SUCCESS)
{
fprintf(stderr, "Please double-check LIBNVVM_HOME environmental variable.\n");
nvvmDestroyProgram(&prog);
return status;
}
const std::string &libDeviceName = getLibDeviceName(computeArch);
addFileToProgram(libDeviceName, prog);
/* Add the module to the compilation unit. */
for (int i = 0; i < (int)nvvmFiles.size(); ++i)
{
status = addFileToProgram(nvvmFiles[i], prog);
if (status != PTXGEN_SUCCESS)
{
nvvmDestroyProgram(&prog);
return status;
}
}
for (const auto &f : nvvmFiles)
addFileToProgram(f, prog);
const int numOptions = nvvmOptions.size();
std::vector<const char*> options(numOptions);
for (int i = 0; i < numOptions; i++)
options[i] = nvvmOptions[i].c_str();
/* Verify the compilation unit. */
if (nvvmVerifyProgram(prog, numOptions, &options[0]) != NVVM_SUCCESS)
{
fprintf(stderr, "Failed to verify the compilation unit\n");
status |= PTXGEN_LIBNVVM_VERIFICATION_ERROR;
}
/* Print warnings and errors. */
{
size_t logSize;
if (nvvmGetProgramLogSize(prog, &logSize) != NVVM_SUCCESS)
{
fprintf(stderr, "Failed to get the compilation log size\n");
status |= PTXGEN_LIBNVVM_ERROR;
}
else
{
std::string log(logSize,0);
if (nvvmGetProgramLog(prog, &log[0]) != NVVM_SUCCESS)
{
fprintf(stderr, "Failed to get the compilation log\n");
status |= PTXGEN_LIBNVVM_ERROR;
}
else
{
fprintf(stderr, "%s\n", log.c_str());
}
}
}
if (status & PTXGEN_LIBNVVM_VERIFICATION_ERROR)
{
nvvmDestroyProgram(&prog);
return status;
}
std::vector<const char*> options;
for (const auto &o : nvvmOptions)
options.push_back(o.c_str());
/* Compile the compilation unit. */
if (nvvmCompileProgram(prog, numOptions, &options[0]) != NVVM_SUCCESS)
{
fprintf(stderr, "Failed to generate PTX from the compilation unit\n");
status |= PTXGEN_LIBNVVM_COMPILATION_ERROR;
}
else
{
size_t ptxSize;
if (nvvmGetCompiledResultSize(prog, &ptxSize) != NVVM_SUCCESS)
if (nvvmVerifyProgram(prog.get(), options.size(), &options[0]) != NVVM_SUCCESS)
throw Exception("Failed to verify the compilation unit.");
/* Compile the compilation unit. */
if (nvvmCompileProgram(prog.get(), options.size(), &options[0]) == NVVM_SUCCESS)
{
fprintf(stderr, "Failed to get the PTX output size\n");
status |= PTXGEN_LIBNVVM_ERROR;
}
else
{
std::string ptx(ptxSize,0);
if (nvvmGetCompiledResult(prog, &ptx[0]) != NVVM_SUCCESS)
size_t ptxSize;
if (nvvmGetCompiledResultSize(prog.get(), &ptxSize) == NVVM_SUCCESS)
{
fprintf(stderr, "Failed to get the PTX output\n");
status |= PTXGEN_LIBNVVM_ERROR;
}
else
{
out << ptx;
ptxString.resize(ptxSize);
if (nvvmGetCompiledResult(prog.get(), &ptxString[0]) != NVVM_SUCCESS)
throw Exception("Failed to get the PTX output.");
}
else throw Exception("Failed to get the PTX output size.");
}
else throw Exception("Failed to generate PTX from the compilation unit.");
}
catch (const std::exception &ex)
{
printWarningsAndErrors(prog);
throw Exception(ex.what());
}
/* Print warnings and errors. */
{
size_t logSize;
if (nvvmGetProgramLogSize(prog, &logSize) != NVVM_SUCCESS)
{
fprintf(stderr, "Failed to get the compilation log size\n");
status |= PTXGEN_LIBNVVM_ERROR;
}
else
{
std::string log(logSize,0);
if (nvvmGetProgramLog(prog, &log[0]) != NVVM_SUCCESS)
{
fprintf(stderr, "Failed to get the compilation log\n");
status |= PTXGEN_LIBNVVM_ERROR;
}
else
{
fprintf(stderr, "%s\n", log.c_str());
}
}
}
return ptxString;
};
/* Release the resources. */
nvvmDestroyProgram(&prog);
return PTXGEN_SUCCESS;
}
static void showUsage()
{
@@ -434,11 +346,18 @@ int main(int argc, char *argv[])
std::vector<std::string> nvvmFiles;
nvvmFiles.push_back(fileIR);
std::ofstream outputPTX(filePTX.c_str());
assert(outputPTX);
const int ret = generatePTX(nvvmOptions, nvvmFiles, outputPTX, computeArch);
outputPTX.open(filePTX.c_str());
return ret;
try
{
std::ofstream outputPTX(filePTX.c_str());
outputPTX << generatePTX(nvvmOptions, nvvmFiles, computeArch);
}
catch (const std::exception &ex)
{
std::cerr << "Error: ptxgen failed with exception \n " << ex.what() << std::endl;
return -1;
}
return 0;
}