diff --git a/llvm/_core.c b/llvm/_core.c index d91f6fa..50790bb 100644 --- a/llvm/_core.c +++ b/llvm/_core.c @@ -42,15 +42,14 @@ _wrap_dumper(LLVMDumpModuleToString, LLVMModuleRef) static PyObject * _wLLVMVerifyModule(PyObject *self, PyObject *args) { - PyObject *obj; - char *outmsg = 0; + char *outmsg; PyObject *ret; LLVMModuleRef m; - if (!PyArg_ParseTuple(args, "O", &obj)) + if (!(m = (LLVMModuleRef)get_object_arg(args))) return NULL; - m = (LLVMModuleRef) PyCObject_AsVoidPtr(obj); + outmsg = 0; (void) LLVMVerifyModule(m, LLVMReturnStatusAction, &outmsg); if (outmsg) { @@ -63,6 +62,53 @@ _wLLVMVerifyModule(PyObject *self, PyObject *args) return ret; } +static PyObject * +_wLLVMGetModuleFromBitcode(PyObject *self, PyObject *args) +{ + PyObject *obj, *ret; + Py_ssize_t len; + char *start, *outmsg; + LLVMModuleRef m; + + if (!PyArg_ParseTuple(args, "O", &obj)) + return NULL; + + start = PyString_AsString(obj); + len = PyString_Size(obj); + + outmsg = 0; + m = LLVMGetModuleFromBitcode(start, len, &outmsg); + if (!m) { + if (outmsg) { + ret = PyString_FromString(outmsg); + LLVMDisposeMessage(outmsg); + return ret; + } else { + Py_RETURN_NONE; + } + } + + return ctor_LLVMModuleRef(m); +} + +static PyObject * +_wLLVMGetBitcodeFromModule(PyObject *self, PyObject *args) +{ + PyObject *ret; + unsigned len; + unsigned char *bytes; + LLVMModuleRef m; + + if (!(m = (LLVMModuleRef)get_object_arg(args))) + return NULL; + + if (!(bytes = LLVMGetBitcodeFromModule(m, &len))) + Py_RETURN_NONE; + + ret = PyString_FromStringAndSize((char *)bytes, (Py_ssize_t)len); + LLVMDisposeMessage((char *)bytes); + return ret; +} /*===----------------------------------------------------------------------===*/ /* Types */ @@ -805,6 +851,8 @@ static PyMethodDef core_methods[] = { _method( LLVMDisposeModule ) _method( LLVMDumpModuleToString ) _method( LLVMVerifyModule ) + _method( LLVMGetModuleFromBitcode ) + _method( LLVMGetBitcodeFromModule ) /* Types */ diff --git a/llvm/core.py b/llvm/core.py index 2161fef..4afb2fc 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -721,6 +721,20 @@ class Module(llvm.Ownable): """ return Module(_core.LLVMModuleCreateWithName(id)) + @staticmethod + def from_bitcode(fileobj): + """Create a Module instance from the contents of a bitcode + file.""" + + data = fileobj.read() + ret = _core.LLVMGetModuleFromBitcode(data) + if not ret: + raise llvm.LLVMException, "Unable to create module from bitcode" + elif isinstance(ret, str): + raise llvm.LLVMException, ret + else: + return Module(ret) + def __init__(self, ptr): """DO NOT CALL DIRECTLY. @@ -837,6 +851,15 @@ class Module(llvm.Ownable): if ret != "": raise llvm.LLVMException, ret + def to_bitcode(self, fileobj): + """Write bitcode representation of module to given file-like + object.""" + + data = _core.LLVMGetBitcodeFromModule(self.ptr) + if not data: + raise llvm.LLVMException, "Unable to create bitcode" + fileobj.write(data) + #===----------------------------------------------------------------------=== # Types diff --git a/llvm/extra.cpp b/llvm/extra.cpp index 7f22998..4596fa9 100644 --- a/llvm/extra.cpp +++ b/llvm/extra.cpp @@ -4,7 +4,13 @@ * Python bindings. */ +#include +#include +#include +#include + #include "llvm/Bitcode/ReaderWriter.h" +#include "llvm/Support/MemoryBuffer.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/GlobalVariable.h" @@ -13,13 +19,10 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/CallSite.h" #include "llvm/IntrinsicInst.h" -#include -#include -#include -#include +#include "llvm/Analysis/Verifier.h" #include "llvm-c/Core.h" -#include "llvm/Analysis/Verifier.h" + #include "extra.h" using namespace llvm; @@ -99,3 +102,32 @@ LLVMValueRef LLVMGetIntrinsic(LLVMModuleRef M, int ID, return wrap(intfunc); } +LLVMModuleRef LLVMGetModuleFromBitcode(const char *BC, unsigned Len, + char **OutMessage) +{ + MemoryBuffer *mb = MemoryBuffer::getMemBufferCopy(BC, BC+Len); + if (!mb) + return NULL; + + std::string msg; + LLVMModuleRef mr = wrap(ParseBitcodeFile(mb, &msg)); + if (!mr) + *OutMessage = strdup(msg.c_str()); + + delete mb; + return mr; +} + +unsigned char *LLVMGetBitcodeFromModule(LLVMModuleRef M, unsigned *Len) +{ + std::ostringstream buf; + WriteBitcodeToFile(unwrap(M), buf); + const std::string& s = buf.str(); + size_t len = s.size(); + unsigned char *bytes = (unsigned char *)malloc(len); + if (!bytes) + return NULL; + memcpy(bytes, s.data(), len); + *Len = len; + return bytes; +} diff --git a/llvm/extra.h b/llvm/extra.h index 6c2fd37..c90f93a 100644 --- a/llvm/extra.h +++ b/llvm/extra.h @@ -47,7 +47,11 @@ LLVMValueRef LLVMBuildGetResult(LLVMBuilderRef, LLVMValueRef V, unsigned Index, const char *Name); LLVMValueRef LLVMGetIntrinsic(LLVMModuleRef B, int ID, - LLVMTypeRef *Types, unsigned Count); + LLVMTypeRef *Types, unsigned Count); + +LLVMModuleRef LLVMGetModuleFromBitcode(const char *BC, unsigned Len, + char **OutMessage); +unsigned char *LLVMGetBitcodeFromModule(LLVMModuleRef M, unsigned *Len); #ifdef __cplusplus } /* extern "C" */ diff --git a/setup.py b/setup.py index 494d413..acf36f5 100644 --- a/setup.py +++ b/setup.py @@ -50,7 +50,7 @@ def call_setup(llvm_config): ldflags = _run(llvm_config + ' --ldflags') libs_core, objs_core = get_libs_and_objs(llvm_config, ['core', 'analysis', 'scalaropts', 'executionengine', - 'jit', 'native', 'interpreter']) + 'jit', 'native', 'interpreter', 'bitreader', 'bitwriter']) std_libs = [ 'pthread', 'm' ] if not sys.platform.startswith("openbsd"):