├── LICENSE ├── README ├── pynvvm ├── __init__.py ├── compiler.py └── interface.py ├── run-tests.py ├── samples └── ptxgen.py ├── setup.py └── tests ├── compile-tests.py ├── import-test.py └── util.py /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 NVIDIA Corporation 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | SOFTWARE. 21 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | 2 | pynvvm - Python Bindings to libNVVM 3 | 4 | 5 | Introduction 6 | ============ 7 | 8 | The pynvvm package is a Python binding for the libNVVM compiler library from 9 | NVIDIA. This library takes LLVM (NVVM) IR input and produces NVIDIA PTX 10 | output suitable for execution on NVIDIA GPUs on any platform. Please see the 11 | CUDA 5.5 documentation for a complete description of libNVVM. 12 | 13 | 14 | Installation 15 | ============ 16 | 17 | The pynvvm package does not have any external dependencies and can be 18 | installed with ``pip`` or ``easy_install``. 19 | 20 | $ pip install pynvvm 21 | 22 | Note, however, that the package does require the libNVVM binary to be present 23 | at runtime. See below for instructions on how to set the search path. 24 | 25 | 26 | Using pynvvm 27 | ============ 28 | 29 | There are two primary interfaces with pynvvm; a low-level interface which 30 | provides users with direct access to the libNVVM API, and a high-level 31 | interface which provides a Pythonic API for the compiler routines in libNVVM. 32 | 33 | 34 | Low-Level Interface 35 | ------------------- 36 | 37 | The low-level interface can be found in the ``pynvvm.interface`` module. An 38 | instance of the interface can be obtained by calling the ``NVVMInterface`` 39 | constructor: 40 | 41 | from pynvvm.interface import NVVMInterface 42 | 43 | inter = NVVMInterface() 44 | 45 | By default, the ``NVVMInterface`` object will attempt to load the libNVVM 46 | shared library from ``LD_LIBRARY_PATH`` on Linux, ``DYLD_LIBRARY_PATH`` on 47 | Mac, or ``PATH`` on Windows. An optional parameter to the ``NVVMInterface`` 48 | constructor provides the absolute path to the libNVVM shared library and 49 | overwrites the system search path. For example, on Linux: 50 | 51 | from pynvvm.interface import NVVMInterface 52 | 53 | inter = NVVMInterface('/usr/local/cuda-5.5/nvvm/lib64/libnvvm.so') 54 | 55 | **NOTE**: It is important that the specified binary match the architecture of 56 | the Python interpreter under which your program is running. 57 | 58 | Once an interface object is created, it provides access to all of the libNVVM 59 | API functions as regular Python functions. However, instead of returning a 60 | libNVVM status code, each function returns either a string (for output 61 | functions) or None. If an error occurs within libNVVM, an ``NVVMException`` 62 | exception is raised with the corresponding status code. 63 | 64 | Note that the ``nvvmGetProgramLogSize`` and ``nvvmGetCompiledResultSize`` 65 | functions are *not* exposed. Instead, the ``nvvmGetProgramLog`` and 66 | ``nvvmGetCompiledResult`` functions automatically determine the correct size 67 | and return a UTF-8 encoded Python string. 68 | 69 | Full Example: 70 | 71 | from pynvvm.interface import NVVMInterface, NVVMException 72 | 73 | module = ... ## Populate NVVM IR or bitcode 74 | 75 | inter = NVVMInterface() 76 | prog = inter.nvvmCreateProgram() 77 | try: 78 | inter.nvvmAddModuleToProgram(prog, module, 'mymodule') 79 | inter.nvvmCompileProgram(prog, ['-ftz=1']) 80 | ptx = inter.nvvmGetCompiledResult(prog) 81 | except NVVMException as e: 82 | print('Error: %s' % repr(e)) 83 | 84 | 85 | 86 | High-Level Interface 87 | -------------------- 88 | 89 | For clients wanting a higher-level interface to libNVVM, the ``Program`` class 90 | in ``pynvvm.compiler`` provides such an interface. The usage is similar to 91 | that of the ``NVVMInterface`` class, but the API is more Pythonic and you do 92 | not need to worry about maintaining NVVM objects. 93 | 94 | 95 | from pynvvm.compiler import Program, ProgramException 96 | 97 | module = ... ## Populate NVVM IR or bitcode 98 | 99 | try: 100 | prog = Program() 101 | prog.add_module(module, 'mymodule') 102 | ptx = prog.compile(['-ftz=1']) 103 | except ProgramException as e: 104 | print('Error: %s' % repr(e)) 105 | 106 | As with ``NVVMInterface``, the ``Program`` constructor accepts an optional 107 | path to the libNVVM binary. 108 | 109 | Please see ``samples/ptxgen.py`` for a complete example of an NVVM IR -> PTX 110 | compiler using the higher-level interface. 111 | -------------------------------------------------------------------------------- /pynvvm/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2013 NVIDIA Corporation 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy 4 | # of this software and associated documentation files (the "Software"), to deal 5 | # in the Software without restriction, including without limitation the rights 6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | # copies of the Software, and to permit persons to whom the Software is 8 | # furnished to do so, subject to the following conditions: 9 | # 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | 22 | __version__ = '1.0-dev' 23 | -------------------------------------------------------------------------------- /pynvvm/compiler.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2013 NVIDIA Corporation 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy 4 | # of this software and associated documentation files (the "Software"), to deal 5 | # in the Software without restriction, including without limitation the rights 6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | # copies of the Software, and to permit persons to whom the Software is 8 | # furnished to do so, subject to the following conditions: 9 | # 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | 22 | from .interface import NVVMException, NVVMInterface 23 | 24 | class ProgramException(Exception): 25 | def __init__(self, msg): 26 | self._msg = msg 27 | 28 | def __repr__(self): 29 | return str(self) 30 | 31 | def __str__(self): 32 | return self.get_message() 33 | 34 | def get_message(self): 35 | return self._msg 36 | 37 | 38 | class Program(object): 39 | """ 40 | An NVVM program object. 41 | 42 | This is a high-level wrapper around the libNVVM program API. 43 | """ 44 | 45 | def __init__(self, lib_name=''): 46 | self._interface = NVVMInterface(lib_name) 47 | self._program = self._interface.nvvmCreateProgram() 48 | 49 | def __del__(self): 50 | if hasattr(self, '_interface'): 51 | self._interface.nvvmDestroyProgram(self._program) 52 | 53 | def add_module(self, buf, name=''): 54 | """ 55 | Adds an LLVM IR module `buf` to the program, optionally giving it 56 | the name `name`. 57 | """ 58 | self._interface.nvvmAddModuleToProgram(self._program, buf, name) 59 | 60 | def compile(self, options=[]): 61 | """ 62 | Compiles the program object to PTX using the compiler options 63 | specified in `options`. 64 | """ 65 | try: 66 | self._interface.nvvmCompileProgram(self._program, options) 67 | ptx = self._interface.nvvmGetCompiledResult(self._program) 68 | return ptx 69 | except NVVMException as e: 70 | log = self._interface.nvvmGetProgramLog(self._program) 71 | raise ProgramException(log) 72 | 73 | def verify(self, options=[]): 74 | """ 75 | Verifies the program object using the compiler options specified 76 | in `options`. 77 | """ 78 | try: 79 | self._interface.nvvmVerifyProgram(self._program, options) 80 | except NVVMException as e: 81 | log = self._interface.nvvmGetProgramLog(self._program) 82 | raise ProgramException(log) 83 | 84 | -------------------------------------------------------------------------------- /pynvvm/interface.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2013 NVIDIA Corporation 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy 4 | # of this software and associated documentation files (the "Software"), to deal 5 | # in the Software without restriction, including without limitation the rights 6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | # copies of the Software, and to permit persons to whom the Software is 8 | # furnished to do so, subject to the following conditions: 9 | # 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | 22 | 23 | from ctypes import ( 24 | POINTER, 25 | c_int, 26 | c_void_p, 27 | byref, 28 | create_string_buffer, 29 | c_char_p, 30 | c_size_t, 31 | sizeof, 32 | cdll, 33 | ) 34 | from platform import system 35 | 36 | # libNVVM status codes 37 | NVVM_SUCCESS = 0 38 | NVVM_ERROR_OUT_OF_MEMORY = 1 39 | NVVM_ERROR_PROGRAM_CREATION_FAILURE = 2 40 | NVVM_ERROR_IR_VERSION_MISMATCH = 3 41 | NVVM_ERROR_INVALID_INPUT = 4 42 | NVVM_ERROR_INVALID_PROGRAM = 5 43 | NVVM_ERROR_INVALID_IR = 6 44 | NVVM_ERROR_INVALID_OPTION = 7 45 | NVVM_ERROR_NO_MODULE_IN_PROGRAM = 8 46 | NVVM_ERROR_COMPILATION = 9 47 | 48 | 49 | class NVVMException(Exception): 50 | """ 51 | Exception wrapper for libNVVM error codes. 52 | """ 53 | def __init__(self, msg): 54 | Exception.__init__(self) 55 | self._msg = msg 56 | 57 | def __str__(self): 58 | return 'NVVM Error: %s' % self._msg 59 | 60 | def __repr__(self): 61 | return str(self) 62 | 63 | 64 | 65 | class NVVMInterface(object): 66 | """ 67 | Low-level interface to libNVVM. This class is primarily designed for 68 | interfacing the high-level API with the libNVVM binary, but clients 69 | are free to use libNVVM directly through this class. 70 | """ 71 | def __init__(self, lib_path=''): 72 | self._lib = None 73 | self._load_nvvm_lib(lib_path) 74 | 75 | def _load_nvvm_lib(self, lib_path): 76 | """ 77 | Loads the libNVVM shared library, with an optional search path in 78 | lib_path. 79 | """ 80 | if system() == 'Windows': 81 | if sizeof(c_void_p) == 8: 82 | def_lib_name = 'nvvm64_20_0.dll' 83 | else: 84 | def_lib_name = 'nvvm32_20_0.dll' 85 | elif system() == 'Darwin': 86 | def_lib_name = 'libnvvm.dylib' 87 | else: 88 | def_lib_name = 'libnvvm.so' 89 | 90 | if len(lib_path) == 0: 91 | name = def_lib_name 92 | else: 93 | name = lib_path 94 | 95 | self._lib = cdll.LoadLibrary(name) 96 | 97 | self._lib.nvvmCreateProgram.argtypes = [ POINTER(c_void_p) ] 98 | self._lib.nvvmCreateProgram.restype = c_int 99 | 100 | self._lib.nvvmDestroyProgram.argtypes = [ POINTER(c_void_p) ] 101 | self._lib.nvvmDestroyProgram.restype = c_int 102 | 103 | self._lib.nvvmAddModuleToProgram.argtypes = [ 104 | c_void_p, 105 | c_char_p, 106 | c_size_t, 107 | c_char_p 108 | ] 109 | self._lib.nvvmAddModuleToProgram.restype = c_int 110 | 111 | self._lib.nvvmVerifyProgram.argtypes = [ 112 | c_void_p, 113 | c_int, POINTER(c_char_p) 114 | ] 115 | self._lib.nvvmVerifyProgram.restype = c_int 116 | 117 | self._lib.nvvmCompileProgram.argtypes = [ 118 | c_void_p, 119 | c_int, 120 | POINTER(c_char_p) 121 | ] 122 | self._lib.nvvmCompileProgram.restype = c_int 123 | 124 | self._lib.nvvmGetCompiledResultSize.argtypes = [ 125 | c_void_p, 126 | POINTER(c_size_t) 127 | ] 128 | self._lib.nvvmGetCompiledResultSize.restype = c_int 129 | 130 | self._lib.nvvmGetCompiledResult.argtypes = [ c_void_p, c_char_p ] 131 | self._lib.nvvmGetCompiledResult.restype = c_int 132 | 133 | self._lib.nvvmGetProgramLogSize.argtypes = [ 134 | c_void_p, 135 | POINTER(c_size_t) 136 | ] 137 | self._lib.nvvmGetProgramLogSize.restype = c_int 138 | 139 | self._lib.nvvmGetProgramLog.argtypes = [ c_void_p, c_char_p ] 140 | self._lib.nvvmGetProgramLog.restype = c_int 141 | 142 | self._lib.nvvmGetErrorString.argtypes = [ c_int ] 143 | self._lib.nvvmGetErrorString.restype = c_char_p 144 | 145 | self._lib.nvvmVersion.argtypes = [ POINTER(c_int), POINTER(c_int) ] 146 | self._lib.nvvmVersion.restype = c_int 147 | 148 | def _throw_on_error(self, code): 149 | """ 150 | Raises an NVVMException is the given code is not NVVM_SUCCESS. 151 | """ 152 | if code == NVVM_SUCCESS: 153 | return 154 | else: 155 | raise NVVMException(self.nvvmGetErrorString(code)) 156 | 157 | def nvvmCreateProgram(self): 158 | """ 159 | Creates and returns a new NVVM program object. 160 | """ 161 | res = c_void_p() 162 | code = self._lib.nvvmCreateProgram(byref(res)) 163 | self._throw_on_error(code) 164 | return res 165 | 166 | def nvvmDestroyProgram(self, prog): 167 | """ 168 | Destroys the given NVVM program object. 169 | """ 170 | code = self._lib.nvvmDestroyProgram(byref(prog)) 171 | self._throw_on_error(code) 172 | return 173 | 174 | def nvvmAddModuleToProgram(self, prog, buf, name): 175 | """ 176 | Adds an LLVM IR module to the given NVVM program object. 177 | 178 | The LLVM IR can be either a text LL buffer or a bitcode buffer. 179 | """ 180 | raw_buf = create_string_buffer(buf, len(buf)) 181 | name_buf = create_string_buffer(name) 182 | code = self._lib.nvvmAddModuleToProgram(prog, raw_buf, 183 | c_size_t(len(buf)), name_buf) 184 | self._throw_on_error(code) 185 | return 186 | 187 | def nvvmVerifyProgram(self, prog, options): 188 | """ 189 | Verifies that the NVVM program object is made up of well-formed NVVM IR 190 | objects. Raises an NVVMException if not. 191 | """ 192 | options_array = (c_char_p * len(options))() 193 | options_array[:] = options 194 | code = self._lib.nvvmVerifyProgram(prog, len(options), options_array) 195 | self._throw_on_error(code) 196 | return 197 | 198 | def nvvmCompileProgram(self, prog, options): 199 | """ 200 | Compiles the NVVM program object into PTX, using the provided options 201 | array. See the libNVVM API documentation for accepted options. 202 | """ 203 | options_array = (c_char_p * len(options))() 204 | options_array[:] = options 205 | code = self._lib.nvvmCompileProgram(prog, len(options), options_array) 206 | self._throw_on_error(code) 207 | return 208 | 209 | def nvvmGetCompiledResult(self, prog): 210 | """ 211 | Returns the compiled PTX for the NVVM program object. 212 | """ 213 | size = c_size_t() 214 | code = self._lib.nvvmGetCompiledResultSize(prog, byref(size)) 215 | self._throw_on_error(code) 216 | 217 | buf = create_string_buffer(size.value) 218 | code = self._lib.nvvmGetCompiledResult(prog, buf) 219 | self._throw_on_error(code) 220 | 221 | return buf.value.decode('utf-8') 222 | 223 | def nvvmGetProgramLog(self, prog): 224 | """ 225 | Returns the log for the NVVM program object. 226 | 227 | Only useful after calls to nvvmCompileProgram or nvvmVerifyProgram. 228 | """ 229 | size = c_size_t() 230 | code = self._lib.nvvmGetProgramLogSize(prog, byref(size)) 231 | self._throw_on_error(code) 232 | 233 | buf = create_string_buffer(size.value) 234 | code = self._lib.nvvmGetProgramLog(prog, buf) 235 | self._throw_on_error(code) 236 | 237 | return buf.value.decode('utf-8') 238 | 239 | def nvvmGetErrorString(self, code): 240 | """ 241 | Returns a text identifier for the given NVVM status code. 242 | """ 243 | code_int = c_int(code) 244 | res = self._lib.nvvmGetErrorString(code_int) 245 | return res.decode('utf-8') 246 | 247 | def nvvmVersion(self): 248 | """ 249 | Returns the loaded libNVVM library version as a (major, minor) tuple. 250 | """ 251 | major = c_int() 252 | minor = c_int() 253 | code = self._lib.nvvmVersion(byref(major), byref(minor)) 254 | self._throw_on_error(code) 255 | return (major.value, minor.value) 256 | 257 | def __str__(self): 258 | (major, minor) = self.nvvmVersion() 259 | return 'NVVM Interface (Version: %d.%d)' % (major, minor) 260 | 261 | def __repr__(self): 262 | return str(self) 263 | -------------------------------------------------------------------------------- /run-tests.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2013 NVIDIA Corporation 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy 4 | # of this software and associated documentation files (the "Software"), to deal 5 | # in the Software without restriction, including without limitation the rights 6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | # copies of the Software, and to permit persons to whom the Software is 8 | # furnished to do so, subject to the following conditions: 9 | # 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | 22 | import nose 23 | import os 24 | 25 | if 'LIBNVVM_BINARY' not in os.environ: 26 | print('WARNING: LIBNVVM_BINARY is not set, assuming it is in [DY]LD_LIBRARY_PATH/PATH') 27 | 28 | os.chdir('tests') 29 | nose.run() 30 | -------------------------------------------------------------------------------- /samples/ptxgen.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2013 NVIDIA Corporation 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy 4 | # of this software and associated documentation files (the "Software"), to deal 5 | # in the Software without restriction, including without limitation the rights 6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | # copies of the Software, and to permit persons to whom the Software is 8 | # furnished to do so, subject to the following conditions: 9 | # 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | 22 | """ 23 | This sample illustrates a simple LLVM IR -> PTX compiler implemented using 24 | libNVVM. All command-line options are passed along to libNVVM. Arguments that 25 | start with '-' are assumed to be options and are passed along accordingly. 26 | Otherwise, options are treated as file names and are read as IR input(s). All 27 | inputs will be linked together into a final PTX module. 28 | 29 | NOTE: If you get errors about not being able to load libnvvm, please make sure 30 | your [DY]LD_LIBRARY_PATH/PATH environment variable points to the libnvvm binary 31 | in your CUDA installation, e.g. 32 | 33 | $ export LD_LIBRARY_PATH=/usr/local/cuda-5.5/nvvm/lib64 34 | """ 35 | 36 | import sys 37 | from pynvvm.compiler import Program, ProgramException 38 | 39 | 40 | if len(sys.argv) < 2: 41 | print('Usage: %s [options] ir-file-1 [ir-file-2 [ir-file-3 ...]]' % sys.argv[0]) 42 | sys.exit(1) 43 | 44 | try: 45 | # Create program object 46 | p = Program() 47 | options = [] 48 | 49 | # Parse all options 50 | for a in sys.argv[1:]: 51 | if a.startswith('-'): 52 | # Treat as compiler option 53 | options.append(a) 54 | else: 55 | # Treat as compiler input 56 | with open(a, 'rb') as f: 57 | p.add_module(f.read()) 58 | 59 | # Verify the input 60 | p.verify() 61 | 62 | # Run the compile 63 | ptx = p.compile(options) 64 | 65 | # Dump the output to stdout 66 | print(ptx) 67 | 68 | sys.exit(0) 69 | 70 | except ProgramException as e: 71 | # An error occurred, dump it to stdout 72 | print('ERROR:\n%s\n' % repr(e)) 73 | 74 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2013 NVIDIA Corporation 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy 4 | # of this software and associated documentation files (the "Software"), to deal 5 | # in the Software without restriction, including without limitation the rights 6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | # copies of the Software, and to permit persons to whom the Software is 8 | # furnished to do so, subject to the following conditions: 9 | # 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | 22 | from setuptools import setup 23 | 24 | setup( 25 | name='pynvvm', 26 | version='1.0.2', 27 | author='Justin Holewinski', 28 | author_email='jholewinski@nvidia.com', 29 | packages=['pynvvm'], 30 | url='https://github.com/nvidia-compiler-sdk/pynvvm/', 31 | license='MIT', 32 | description='Python bindings to libNVVM.', 33 | long_description=open('README').read(), 34 | classifiers=[ 35 | 'Development Status :: 5 - Production/Stable', 36 | 'Environment :: Console', 37 | 'Intended Audience :: Science/Research', 38 | 'Intended Audience :: Developers', 39 | 'License :: OSI Approved :: MIT License', 40 | 'Operating System :: MacOS :: MacOS X', 41 | 'Operating System :: Microsoft :: Windows', 42 | 'Operating System :: POSIX', 43 | 'Programming Language :: Python', 44 | 'Topic :: Software Development :: Compilers', 45 | 'Topic :: Software Development :: Libraries', 46 | ], 47 | ) 48 | -------------------------------------------------------------------------------- /tests/compile-tests.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2013 NVIDIA Corporation 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy 4 | # of this software and associated documentation files (the "Software"), to deal 5 | # in the Software without restriction, including without limitation the rights 6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | # copies of the Software, and to permit persons to whom the Software is 8 | # furnished to do so, subject to the following conditions: 9 | # 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | 22 | import unittest 23 | from util import get_interface 24 | 25 | ### Low-level interface tests 26 | class CompileTests(unittest.TestCase): 27 | def test_create_program(self): 28 | i = get_interface() 29 | 30 | prog = i.nvvmCreateProgram() 31 | i.nvvmDestroyProgram(prog) 32 | 33 | def test_compile_empty_program(self): 34 | i = get_interface() 35 | 36 | prog = i.nvvmCreateProgram() 37 | i.nvvmAddModuleToProgram(prog, """ 38 | target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64" 39 | define void @foo() { 40 | ret void 41 | }""", 'mymodule') 42 | i.nvvmCompileProgram(prog, []) 43 | i.nvvmDestroyProgram(prog) 44 | 45 | def test_verify_empty_program(self): 46 | i = get_interface() 47 | 48 | prog = i.nvvmCreateProgram() 49 | i.nvvmAddModuleToProgram(prog, """ 50 | target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64" 51 | define void @foo() { 52 | ret void 53 | }""", 'mymodule') 54 | i.nvvmVerifyProgram(prog, []) 55 | i.nvvmDestroyProgram(prog) 56 | 57 | def test_verify_failure(self): 58 | import pynvvm.interface 59 | i = get_interface() 60 | 61 | prog = i.nvvmCreateProgram() 62 | i.nvvmAddModuleToProgram(prog, """ 63 | target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64" 64 | declare void @bar() 65 | define void @foo() { 66 | invoke void @bar() 67 | ret void 68 | }""", 'mymodule') 69 | self.assertRaises(pynvvm.interface.NVVMException, i.nvvmVerifyProgram, prog, []) 70 | i.nvvmDestroyProgram(prog) 71 | 72 | def test_program_log(self): 73 | import pynvvm.interface 74 | i = get_interface() 75 | 76 | prog = i.nvvmCreateProgram() 77 | i.nvvmAddModuleToProgram(prog, """ 78 | target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64" 79 | define void @foo() { 80 | ; No terminator 81 | }""", 'mymodule') 82 | self.assertRaises(pynvvm.interface.NVVMException, i.nvvmCompileProgram, prog, []) 83 | log = i.nvvmGetProgramLog(prog) 84 | self.assertTrue(len(log) > 0) 85 | i.nvvmDestroyProgram(prog) 86 | 87 | def test_program_output(self): 88 | import pynvvm.interface 89 | i = get_interface() 90 | 91 | prog = i.nvvmCreateProgram() 92 | i.nvvmAddModuleToProgram(prog, """ 93 | target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64" 94 | define void @foo() { 95 | ret void 96 | }""", 'mymodule') 97 | i.nvvmCompileProgram(prog, []) 98 | ptx = i.nvvmGetCompiledResult(prog) 99 | self.assertTrue(len(ptx) > 0) 100 | i.nvvmDestroyProgram(prog) 101 | -------------------------------------------------------------------------------- /tests/import-test.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2013 NVIDIA Corporation 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy 4 | # of this software and associated documentation files (the "Software"), to deal 5 | # in the Software without restriction, including without limitation the rights 6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | # copies of the Software, and to permit persons to whom the Software is 8 | # furnished to do so, subject to the following conditions: 9 | # 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | 22 | import unittest 23 | from util import get_interface 24 | 25 | class ImportTest(unittest.TestCase): 26 | def test_simple_import(self): 27 | get_interface() 28 | 29 | 30 | -------------------------------------------------------------------------------- /tests/util.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2013 NVIDIA Corporation 2 | # 3 | # Permission is hereby granted, free of charge, to any person obtaining a copy 4 | # of this software and associated documentation files (the "Software"), to deal 5 | # in the Software without restriction, including without limitation the rights 6 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | # copies of the Software, and to permit persons to whom the Software is 8 | # furnished to do so, subject to the following conditions: 9 | # 10 | # 11 | # The above copyright notice and this permission notice shall be included in 12 | # all copies or substantial portions of the Software. 13 | # 14 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 | # SOFTWARE. 21 | 22 | import os 23 | 24 | def get_interface(): 25 | import pynvvm.interface 26 | # Grab the libnvvm location from the environment 27 | if 'LIBNVVM_BINARY' in os.environ: 28 | return pynvvm.interface.NVVMInterface(os.environ['LIBNVVM_BINARY']) 29 | else: 30 | return pynvvm.interface.NVVMInterface() 31 | --------------------------------------------------------------------------------