diff --git a/CHANGELOG b/CHANGELOG index 48b5877..45d6a5f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,15 @@ +2014-04-28 0.12.5: +--------------------- + * Fixes memory leaks (#92) + * Fixes tarball (#99) + +2014-03-20 0.12.4: +--------------------- + * Add dylib_import_library and friends + * Fix BasicBlock downcast + * Module hashing + * Fix test script + 2014-02-18 0.12.3: --------------------- * Fix deprecation message for py2.6 diff --git a/MANIFEST.in b/MANIFEST.in index 295794c..25a211d 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,5 +1,6 @@ -include CHANGELOG LICENSE README setup.py MANIFEST.in +include CHANGELOG LICENSE README.rst setup.py MANIFEST.in versioneer.py recursive-include llvm * +recursive-include llvmpy * recursive-include www * recursive-include test * recursive-include tools * diff --git a/README.rst b/README.rst index 0fbcd24..a1abf84 100644 --- a/README.rst +++ b/README.rst @@ -30,10 +30,13 @@ Quickstart to separate your custom build from the default system package. Please replace ``LLVM_INSTALL_PATH`` with your own path. -3. Run ``REQUIRES_RTTI=1 make`` to build. +3. Run ``REQUIRES_RTTI=1 make install`` to build and install. **Note**: With LLVM 3.2, the default build configuration has C++ RTTI disabled. However, llvmpy requires RTTI. + + **Note**: Use ``make -j2 install`` to enable concurrent build. + Replace ``2`` with the actual number of processor you have. 4. Get llvm-py and install it:: diff --git a/buildscripts/condarecipe/run_test.py b/buildscripts/condarecipe/run_test.py index 653515f..682b8d4 100644 --- a/buildscripts/condarecipe/run_test.py +++ b/buildscripts/condarecipe/run_test.py @@ -15,8 +15,8 @@ if sys.platform == 'darwin': s = {'64bit': 'x86_64', '32bit': 'x86'}[platform.architecture()[0]] assert target.triple.startswith(s + '-apple-darwin') -assert llvm.test(verbosity=2) == 0 -check_intrinsics.main() +assert llvm.test(verbosity=2, run_isolated=False) == 0 +#check_intrinsics.main() print('llvm.__version__: %s' % llvm.__version__) #assert llvm.__version__ == '0.12.0' diff --git a/llvm/__init__.py b/llvm/__init__.py index 11cf7bc..9b24112 100644 --- a/llvm/__init__.py +++ b/llvm/__init__.py @@ -34,14 +34,14 @@ def _extract_ptrs(objs): class LLVMException(Exception): pass -def test(verbosity=3): +def test(verbosity=3, run_isolated=True): """test(verbosity=1) -> TextTestResult Run self-test, and return the number of failures + errors """ from llvm.tests import run - result = run(verbosity=verbosity) + result = run(verbosity=verbosity, run_isolated=run_isolated) errct = len(result.failures) + len(result.errors) return errct diff --git a/llvm/core.py b/llvm/core.py index 650bb90..4db8135 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -452,12 +452,12 @@ class Module(llvm.Wrapper): """ return str(self._ptr) + def __hash__(self): + return id(self._ptr) + def __eq__(self, rhs): - assert isinstance(rhs, Module), type(rhs) if isinstance(rhs, Module): - return str(self) == str(rhs) - else: - return False + return self._ptr == rhs._ptr def __ne__(self, rhs): return not (self == rhs) diff --git a/llvm/ee.py b/llvm/ee.py index c687eaa..f615b61 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -238,3 +238,27 @@ def dylib_add_symbol(name, ptr): def dylib_address_of_symbol(name): return api.llvm.sys.DynamicLibrary.SearchForAddressOfSymbol(name) + +def dylib_import_library(filename): + """Permanently import a dynamic library. + + Returns a DynamicLibrary object + + Raises RuntimeError + """ + return DynamicLibrary(filename) + + +class DynamicLibrary(object): + def __init__(self, filename): + """ + Raises RuntimeError + """ + self._ptr = api.llvm.sys.DynamicLibrary.getPermanentLibrary( + filename) + + def get_address_of_symbol(self, symbol): + """ + Get the address of `symbol` (str) as integer + """ + return self._ptr.getAddressOfSymbol(symbol) diff --git a/llvm/tests/__init__.py b/llvm/tests/__init__.py index 67102c7..0bc4223 100644 --- a/llvm/tests/__init__.py +++ b/llvm/tests/__init__.py @@ -12,7 +12,7 @@ tests = [] # stores unittest.TestCase objects isolated_tests = [] # stores modue name -def run(verbosity=1): +def run(verbosity=1, run_isolated=True): print('llvmpy is installed in: ' + os.path.dirname(__file__)) print('llvmpy version: ' + llvm.__version__) print(sys.version) @@ -48,7 +48,7 @@ def run(verbosity=1): testresult = runner.run(suite) print(hp.heap()) - if testresult: + if testresult and run_isolated: # Run isolated tests print("run isolated tests".center(80, '-')) diff --git a/llvmpy/include/llvm_binding/extra.h b/llvmpy/include/llvm_binding/extra.h index f8f7766..bdd86d3 100644 --- a/llvmpy/include/llvm_binding/extra.h +++ b/llvmpy/include/llvm_binding/extra.h @@ -40,7 +40,7 @@ namespace extra{ using namespace llvm; - + class raw_svector_ostream_helper: public raw_svector_ostream { SmallVectorImpl *SV; public: @@ -85,7 +85,7 @@ PyObject* make_raw_ostream_for_printing(PyObject* self, PyObject* args) { using extra::raw_svector_ostream_helper; using llvm::raw_svector_ostream; - + if (!PyArg_ParseTuple(args, "")) { return NULL; } @@ -99,7 +99,7 @@ PyObject* make_small_vector_from_types(PyObject* self, PyObject* args) { using llvm::Type; typedef llvm::SmallVector SmallVector_Type; - + SmallVector_Type* SV = new SmallVector_Type; Py_ssize_t size = PyTuple_Size(args); for (Py_ssize_t i = 0; i < size; ++i) { @@ -186,8 +186,8 @@ PyObject* iterator_to_pylist_deref(iterator begin, iterator end, { PyObject* list = PyList_New(0); for(; begin != end; ++begin) { - PyObject* cap = pycapsule_new(&*begin, capsuleName, className); - PyList_Append(list, cap); + auto_pyobject cap = pycapsule_new(&*begin, capsuleName, className); + PyList_Append(list, *cap); } return list; } @@ -198,8 +198,8 @@ PyObject* iterator_to_pylist(iterator begin, iterator end, { PyObject* list = PyList_New(0); for(; begin != end; ++begin) { - PyObject* cap = pycapsule_new(*begin, capsuleName, className); - PyList_Append(list, cap); + auto_pyobject cap = pycapsule_new(*begin, capsuleName, className); + PyList_Append(list, *cap); } return list; } @@ -420,7 +420,7 @@ PyObject* ExecutionEngine_RunFunction(llvm::ExecutionEngine* EE, PyErr_SetString(PyExc_RuntimeError, "Failed to index into args?"); return NULL; } - + GenericValue* gv = static_cast( PyCapsule_GetPointer(obj, GVN)); @@ -575,11 +575,11 @@ PyObject* TargetMachine_addPassesToEmitFile( bool status = TM->addPassesToEmitFile(PM, fso, FTy, disableVerify); if (status) { StringRef sr = rso.str(); - PyObject* buf = PyString_FromStringAndSize(sr.data(), sr.size()); + auto_pyobject buf = PyString_FromStringAndSize(sr.data(), sr.size()); if (!buf) { return NULL; } - if (-1 == PyFile_WriteObject(buf, Out, Py_PRINT_RAW)){ + if (-1 == PyFile_WriteObject(*buf, Out, Py_PRINT_RAW)){ return NULL; } Py_RETURN_TRUE; @@ -626,7 +626,7 @@ PyObject* Linker_LinkInModule(llvm::Linker* Linker, if (! failed) { Py_RETURN_FALSE; } else { - + auto_pyobject buf = PyBytes_FromString(errmsg.c_str()); if (NULL == callwrite(ErrMsg, *buf)){ return NULL; @@ -861,6 +861,27 @@ PyObject* DynamicLibrary_LoadLibraryPermanently(const char * Filename, } } +static +PyObject* DynamicLibrary_getPermanentLibrary(const char * Filename, + PyObject* ErrMsg = 0) +{ + using namespace llvm::sys; + std::string errmsg; + DynamicLibrary dylib = DynamicLibrary::getPermanentLibrary(Filename, &errmsg); + if (!dylib.isValid()) { + if (ErrMsg) { + auto_pyobject buf = PyBytes_FromString(errmsg.c_str()); + if (!callwrite(ErrMsg, *buf)) + return NULL; + } + PyErr_SetString(PyExc_RuntimeError, errmsg.c_str()); + return NULL; + } + return pycapsule_new(new DynamicLibrary(dylib), + "llvm::sys::DynamicLibrary", + "llvm::sys::DynamicLibrary"); +} + class PassRegistryEnumerator : public llvm::PassRegistrationListener{ public: PyObject* List; @@ -870,7 +891,8 @@ public: inline virtual void passEnumerate(const llvm::PassInfo * pass_info){ PyObject* passArg = PyString_FromString(pass_info->getPassArgument()); PyObject* passName = PyString_FromString(pass_info->getPassName()); - PyList_Append(List, Py_BuildValue("(OO)", passArg, passName)); + auto_pyobject pair = Py_BuildValue("(OO)", passArg, passName); + PyList_Append(List, *pair); } }; @@ -988,7 +1010,7 @@ fail: } static -PyObject* MCDisassembler_getInstruction(llvm::MCDisassembler *disasm, +PyObject* MCDisassembler_getInstruction(llvm::MCDisassembler *disasm, llvm::MCInst &instr, const llvm::MemoryObject ®ion, uint64_t address @@ -998,7 +1020,7 @@ PyObject* MCDisassembler_getInstruction(llvm::MCDisassembler *disasm, llvm::MCDisassembler::DecodeStatus status; size = 0; - status = disasm->getInstruction(instr, size, region, address, + status = disasm->getInstruction(instr, size, region, address, llvm::nulls(), llvm::nulls()); return Py_BuildValue("(i,i)", int(status), size); } @@ -1046,5 +1068,5 @@ PyObject* llvm_sys_isBigEndianHost() else Py_RETURN_FALSE; } -#endif +#endif diff --git a/llvmpy/src/BasicBlock.py b/llvmpy/src/BasicBlock.py index 6efe704..3c82e17 100644 --- a/llvmpy/src/BasicBlock.py +++ b/llvmpy/src/BasicBlock.py @@ -1,12 +1,13 @@ from binding import * from .namespace import llvm -from .Value import Function, BasicBlock +from .Value import Function, BasicBlock, Value from .Instruction import Instruction, TerminatorInst from .LLVMContext import LLVMContext from .ADT.StringRef import StringRef @BasicBlock class BasicBlock: + _downcast_ = Value Create = StaticMethod(ptr(BasicBlock), ref(LLVMContext), cast(str, StringRef), ptr(Function), diff --git a/llvmpy/src/Support/DynamicLibrary.py b/llvmpy/src/Support/DynamicLibrary.py index 7dce97a..e3b1d37 100644 --- a/llvmpy/src/Support/DynamicLibrary.py +++ b/llvmpy/src/Support/DynamicLibrary.py @@ -26,3 +26,10 @@ class DynamicLibrary: cast(str, StringRef), # symbolName cast(int, VoidPtr), # address ) + + getPermanentLibrary = CustomStaticMethod( + 'DynamicLibrary_getPermanentLibrary', + PyObjectPtr, + cast(str, ConstCharPtr), # filename + PyObjectPtr, # std::string * errmsg = 0 + ).require_only(1)