Home | History | Annotate | Download | only in llvm
      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