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