1 #===- common.py - Python LLVM Bindings -----------------------*- python -*--===# 2 # 3 # The LLVM Compiler Infrastructure 4 # 5 # This file is distributed under the University of Illinois Open Source 6 # License. See LICENSE.TXT for details. 7 # 8 #===------------------------------------------------------------------------===# 9 10 from ctypes import POINTER 11 from ctypes import c_void_p 12 from ctypes import cdll 13 14 import ctypes.util 15 import platform 16 17 # LLVM_VERSION: sync with PACKAGE_VERSION in autoconf/configure.ac and CMakeLists.txt 18 # but leave out the 'svn' suffix. 19 LLVM_VERSION = '3.4' 20 21 __all__ = [ 22 'c_object_p', 23 'get_library', 24 ] 25 26 c_object_p = POINTER(c_void_p) 27 28 class LLVMObject(object): 29 """Base class for objects that are backed by an LLVM data structure. 30 31 This class should never be instantiated outside of this package. 32 """ 33 def __init__(self, ptr, ownable=True, disposer=None): 34 assert isinstance(ptr, c_object_p) 35 36 self._ptr = self._as_parameter_ = ptr 37 38 self._self_owned = True 39 self._ownable = ownable 40 self._disposer = disposer 41 42 self._owned_objects = [] 43 44 def take_ownership(self, obj): 45 """Take ownership of another object. 46 47 When you take ownership of another object, you are responsible for 48 destroying that object. In addition, a reference to that object is 49 placed inside this object so the Python garbage collector will not 50 collect the object while it is still alive in libLLVM. 51 52 This method should likely only be called from within modules inside 53 this package. 54 """ 55 assert isinstance(obj, LLVMObject) 56 57 self._owned_objects.append(obj) 58 obj._self_owned = False 59 60 def from_param(self): 61 """ctypes function that converts this object to a function parameter.""" 62 return self._as_parameter_ 63 64 def __del__(self): 65 if not hasattr(self, '_self_owned') or not hasattr(self, '_disposer'): 66 return 67 68 if self._self_owned and self._disposer: 69 self._disposer(self) 70 71 class CachedProperty(object): 72 """Decorator that caches the result of a property lookup. 73 74 This is a useful replacement for @property. It is recommended to use this 75 decorator on properties that invoke C API calls for which the result of the 76 call will be idempotent. 77 """ 78 def __init__(self, wrapped): 79 self.wrapped = wrapped 80 try: 81 self.__doc__ = wrapped.__doc__ 82 except: # pragma: no cover 83 pass 84 85 def __get__(self, instance, instance_type=None): 86 if instance is None: 87 return self 88 89 value = self.wrapped(instance) 90 setattr(instance, self.wrapped.__name__, value) 91 92 return value 93 94 def get_library(): 95 """Obtain a reference to the llvm library.""" 96 97 # On Linux, ctypes.cdll.LoadLibrary() respects LD_LIBRARY_PATH 98 # while ctypes.util.find_library() doesn't. 99 # See http://docs.python.org/2/library/ctypes.html#finding-shared-libraries 100 # 101 # To make it possible to run the unit tests without installing the LLVM shared 102 # library into a default linker search path. Always Try ctypes.cdll.LoadLibrary() 103 # with all possible library names first, then try ctypes.util.find_library(). 104 105 names = ['LLVM-' + LLVM_VERSION, 'LLVM-' + LLVM_VERSION + 'svn'] 106 t = platform.system() 107 if t == 'Darwin': 108 pfx, ext = 'lib', '.dylib' 109 elif t == 'Windows': 110 pfx, ext = '', '.dll' 111 else: 112 pfx, ext = 'lib', '.so' 113 114 for i in names: 115 try: 116 lib = cdll.LoadLibrary(pfx + i + ext) 117 except OSError: 118 pass 119 else: 120 return lib 121 122 for i in names: 123 t = ctypes.util.find_library(i) 124 if t: 125 return cdll.LoadLibrary(t) 126 raise Exception('LLVM shared library not found!') 127