added ptxgen

This commit is contained in:
Evghenii
2014-02-20 08:52:37 +01:00
parent 01cbe3d289
commit dea856b7e3
2 changed files with 330 additions and 7 deletions

View File

@@ -1,26 +1,49 @@
all: ptxcc
all: ptxcc ptxgen
CXX=clang++
CXXFLAGS += -O3
CXXFLAGS += -I/opt/local/include
LD=clang++
LDFLAGS += -L/opt/local/lib
FLEX=flex
BISON=bison
CUDATK=/usr/local/cuda
LIBDEVICE_MAJOR=1
LIBDEVICE_MINOR=0
ptxgrammar.cc : ptxgrammar.yy
bison -d -v -t ptxgrammar.yy -o ptxgrammar.cc
$(BISON) -d -v -t ptxgrammar.yy -o ptxgrammar.cc
ptx.cc: ptx.ll ptxgrammar.cc
flex -t ptx.ll > ptx.cc
$(FLEX) -t ptx.ll > ptx.cc
%.o: %.cc
clang++ -O3 -c $< -o $@ -I/opt/local/include
$(CXX) $(CXXFLAGS) -c $< -o $@
%.o: %.cpp
clang++ -O3 -c $< -o $@ -I/opt/local/include
$(CXX) $(CXXFLAGS) -c $< -o $@
OBJ= ptxcc.o \
ptx.o \
ptxgrammar.o
ptxcc: $(OBJ)
clang++ $^ -o $@ -L/opt/local/lib
$(LD) $(LDFLAGS) $^ -o $@
ptxgen: ptxgen.cpp
$(CXX) $(CXXFLAGS) -o $@ $< \
-L$(CUDATK)/nvvm/lib64 -lnvvm \
-I$(CUDATK)/nvvm/include \
-I$(CUDATK)/include \
-DLIBDEVICE_MAJOR_VERSION=$(LIBDEVICE_MAJOR) \
-DLIBDEVICE_MINOR_VERSION=$(LIBDEVICE_MINOR) \
-DLIBNVVM_HOME=$(CUDATK)/nvvm -Wl,-rpath,$(CUDATK)/nvvm/lib64
clean:
/bin/rm -f ptxcc $(OBJ) ptxgrammar.hh ptxgrammar.cc ptx.cc ptxgrammar.output
/bin/rm -f ptxgen ptxcc $(OBJ) ptxgrammar.hh ptxgrammar.cc ptx.cc ptxgrammar.output
$(OBJ): ptxgrammar.cc ptx.cc PTXParser.h PTXLexer.h

View File

@@ -0,0 +1,300 @@
/*
* Copyright 1993-2012 NVIDIA Corporation. All rights reserved.
*
* Please refer to the NVIDIA end user license agreement (EULA) associated
* with this source code for terms and conditions that govern your use of
* this software. Any use, reproduction, disclosure, or distribution of
* this software and related documentation outside the terms of the EULA
* is strictly prohibited.
*
*/
#include <nvvm.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
/* Two levels of indirection to stringify LIBDEVICE_MAJOR_VERSION and
* LIBDEVICE_MINOR_VERSION correctly. */
#define getLibDeviceNameForArch(ARCH) \
_getLibDeviceNameForArch(ARCH, \
LIBDEVICE_MAJOR_VERSION, \
LIBDEVICE_MINOR_VERSION)
#define _getLibDeviceNameForArch(ARCH, MAJOR, MINOR) \
__getLibDeviceNameForArch(ARCH, MAJOR, MINOR)
#define __getLibDeviceNameForArch(ARCH, MAJOR, MINOR) \
("/libdevice/libdevice.compute_" #ARCH "." #MAJOR #MINOR ".bc")
#define getLibnvvmHome _getLibnvvmHome(LIBNVVM_HOME)
#define _getLibnvvmHome(NVVM_HOME) __getLibnvvmHome(NVVM_HOME)
#define __getLibnvvmHome(NVVM_HOME) (#NVVM_HOME)
typedef struct stat Stat;
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
};
#define PTXGENStatus int
static PTXGENStatus getLibDeviceName(int computeArch, char **buffer)
{
const char *libnvvmPath = getLibnvvmHome;
const char *libdevice = NULL;
if (libnvvmPath == NULL) {
fprintf(stderr, "The environment variable LIBNVVM_HOME undefined\n");
return PTXGEN_LIBNVVM_HOME_UNDEFINED;
}
/* Use libdevice for compute_20, if the target is not compute_20, compute_30,
* or compute_35. */
switch (computeArch) {
default:
libdevice = getLibDeviceNameForArch(20);
break;
case 30:
libdevice = getLibDeviceNameForArch(30);
break;
case 35:
libdevice = getLibDeviceNameForArch(35);
break;
}
*buffer = (char *) malloc(strlen(libnvvmPath) + strlen(libdevice) + 1);
if (*buffer == NULL) {
fprintf(stderr, "Failed to allocate memory\n");
return PTXGEN_BAD_ALLOC_ERROR;
}
/* Concatenate libnvvmPath and name. */
*buffer = strcat(strcpy(*buffer, libnvvmPath), libdevice);
return PTXGEN_SUCCESS;
}
static PTXGENStatus addFileToProgram(const char *filename, nvvmProgram prog)
{
char *buffer;
size_t size;
Stat fileStat;
/* Open the input file. */
FILE *f = fopen(filename, "rb");
if (f == NULL) {
fprintf(stderr, "Failed to open %s\n", filename);
return PTXGEN_FILE_IO_ERROR;
}
/* Allocate buffer for the input. */
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);
fclose(f);
free(buffer);
return PTXGEN_FILE_IO_ERROR;
}
fclose(f);
if (nvvmAddModuleToProgram(prog, buffer, size, filename) != NVVM_SUCCESS) {
fprintf(stderr,
"Failed to add the module %s to the compilation unit\n",
filename);
free(buffer);
return PTXGEN_LIBNVVM_ERROR;
}
free(buffer);
return PTXGEN_SUCCESS;
}
static PTXGENStatus generatePTX(int numOptions, const char **options,
int numFilenames, const char **filenames,
int computeArch)
{
PTXGENStatus status;
nvvmProgram prog;
char *libDeviceName;
int i;
/* Create the compiliation unit. */
if (nvvmCreateProgram(&prog) != NVVM_SUCCESS) {
fprintf(stderr, "Failed to create the compilation unit\n");
return PTXGEN_LIBNVVM_ERROR;
}
/* Add libdevice. */
status = getLibDeviceName(computeArch, &libDeviceName);
if (status != PTXGEN_SUCCESS) {
nvvmDestroyProgram(&prog);
return status;
}
status = addFileToProgram(libDeviceName, prog);
free(libDeviceName);
if (status != PTXGEN_SUCCESS) {
nvvmDestroyProgram(&prog);
return status;
}
/* Add the module to the compilation unit. */
for (i = 0; i < numFilenames; ++i) {
status = addFileToProgram(filenames[i], prog);
if (status != PTXGEN_SUCCESS) {
nvvmDestroyProgram(&prog);
return status;
}
}
/* Verify the compilation unit. */
if (nvvmVerifyProgram(prog, numOptions, options) != NVVM_SUCCESS) {
fprintf(stderr, "Failed to verify the compilation unit\n");
status |= PTXGEN_LIBNVVM_VERIFICATION_ERROR;
}
/* Print warnings and errors. */
{
size_t logSize;
char *log;
if (nvvmGetProgramLogSize(prog, &logSize) != NVVM_SUCCESS) {
fprintf(stderr, "Failed to get the compilation log size\n");
status |= PTXGEN_LIBNVVM_ERROR;
} else {
log = (char *) malloc(logSize);
if (log == NULL) {
fprintf(stderr, "Failed to allocate memory\n");
status |= PTXGEN_BAD_ALLOC_ERROR;
} else if (nvvmGetProgramLog(prog, log) != NVVM_SUCCESS) {
fprintf(stderr, "Failed to get the compilation log\n");
status |= PTXGEN_LIBNVVM_ERROR;
} else {
fprintf(stderr, "%s\n", log);
}
free(log);
}
}
if (status & PTXGEN_LIBNVVM_VERIFICATION_ERROR) {
nvvmDestroyProgram(&prog);
return status;
}
/* Compile the compilation unit. */
if (nvvmCompileProgram(prog, numOptions, options) != NVVM_SUCCESS) {
fprintf(stderr, "Failed to generate PTX from the compilation unit\n");
status |= PTXGEN_LIBNVVM_COMPILATION_ERROR;
} else {
size_t ptxSize;
char *ptx;
if (nvvmGetCompiledResultSize(prog, &ptxSize) != NVVM_SUCCESS) {
fprintf(stderr, "Failed to get the PTX output size\n");
status |= PTXGEN_LIBNVVM_ERROR;
} else {
ptx = (char *) malloc(ptxSize);
if (ptx == NULL) {
fprintf(stderr, "Failed to allocate memory\n");
status |= PTXGEN_BAD_ALLOC_ERROR;
} else if (nvvmGetCompiledResult(prog, ptx) != NVVM_SUCCESS) {
fprintf(stderr, "Failed to get the PTX output\n");
status |= PTXGEN_LIBNVVM_ERROR;
} else {
fprintf(stdout, "%s\n", ptx);
}
free(ptx);
}
}
/* Print warnings and errors. */
{
size_t logSize;
char *log;
if (nvvmGetProgramLogSize(prog, &logSize) != NVVM_SUCCESS) {
fprintf(stderr, "Failed to get the compilation log size\n");
status |= PTXGEN_LIBNVVM_ERROR;
} else {
log = (char *) malloc(logSize);
if (log == NULL) {
fprintf(stderr, "Failed to allocate memory\n");
status |= PTXGEN_BAD_ALLOC_ERROR;
} else if (nvvmGetProgramLog(prog, log) != NVVM_SUCCESS) {
fprintf(stderr, "Failed to get the compilation log\n");
status |= PTXGEN_LIBNVVM_ERROR;
} else {
fprintf(stderr, "%s\n", log);
}
free(log);
}
}
/* Release the resources. */
nvvmDestroyProgram(&prog);
return PTXGEN_SUCCESS;
}
static void showUsage()
{
fprintf(stderr,"Usage: ptxgen [OPTION]... [FILE]...\n"
" [FILE] could be a .bc file or a .ll file\n");
}
int main(int argc, char *argv[])
{
PTXGENStatus status = PTXGEN_SUCCESS;
int numOptions = 0;
char **options = NULL;
int numFilenames = 0;
char **filenames = NULL;
int computeArch = 35;
int i;
/* Process the command-line arguments to extract the libnvvm options and the
* input file names. */
if (argc == 1) {
showUsage();
return PTXGEN_INVALID_USAGE;
}
options = (char **) malloc((argc ) * sizeof (char *));
filenames = (char **) malloc((argc - 1) * sizeof (char *));
for (i = 1; i < argc; ++i) {
if (argv[i][0] == '-') {
options[numOptions] = argv[i];
++numOptions;
} else {
filenames[numFilenames] = argv[i];
++numFilenames;
}
}
static char sm_35opt[] = "-arch=compute_35";
options[numOptions] = sm_35opt;
numOptions++;
if (numFilenames == 0) {
/* If no input filename is found, then show the usage. */
showUsage();
status = PTXGEN_INVALID_USAGE;
} else {
/* Run libnvvm to generate PTX. */
status = generatePTX(numOptions, (const char **) options,
numFilenames, (const char **) filenames,
computeArch);
}
free(options);
free(filenames);
return status;
}