]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
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 | |
970d7e83 LB |
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. | |
1a4d82fc | 19 | LLVM_VERSION = '3.4' |
223e47cc LB |
20 | |
21 | __all__ = [ | |
22 | 'c_object_p', | |
223e47cc LB |
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 | ||
223e47cc LB |
94 | def get_library(): |
95 | """Obtain a reference to the llvm library.""" | |
223e47cc | 96 | |
970d7e83 LB |
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!') |