diff --git a/newbinding/gen/binding.py b/newbinding/gen/binding.py index 142c8ef..d9b44af 100644 --- a/newbinding/gen/binding.py +++ b/newbinding/gen/binding.py @@ -26,6 +26,11 @@ class Namespace(object): self.functions.append(fn) return fn + def CustomFunction(self, *args): + fn = CustomFunction(self, *args) + self.functions.append(fn) + return fn + def Enum(self, name, *value_names): enum = Enum(*value_names) enum.parent = self @@ -444,13 +449,22 @@ class Function(Method): with writer.function(self.name, varargs='args') as varargs: unwrapped = writer.unwrap_many(varargs) self.process_ownedptr_args(writer, unwrapped) - func = self.fullname.split('::', 1)[1].replace('::', '.') + func = self.name ret = writer.call('_api.%s' % func, varargs=unwrapped) wrapped = writer.wrap(ret, self.is_return_ownedptr()) writer.return_value(wrapped) writer.println() +class CustomFunction(Function): + def __init__(self, parent, name, realname, return_type=Void, *args): + super(CustomFunction, self).__init__(parent, name, return_type, *args) + self.realname = realname + + @property + def fullname(self): + return self.realname + class Destructor(Method): _kind_ = 'dtor' diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index c69f177..e8f39cb 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -3,6 +3,8 @@ #include #include #include +#include +#include #include #include @@ -405,3 +407,61 @@ PyObject* EngineBuilder_selectTarget(llvm::EngineBuilder* eb, return pycapsule_new(eb, "llvm::EngineBuilder"); } + +static +PyObject* llvm_ParseBitCodeFile(llvm::StringRef Buf, llvm::LLVMContext& Ctx, + PyObject* FObj=NULL) +{ + using namespace llvm; + MemoryBuffer* MB = MemoryBuffer::getMemBuffer(Buf); + Module* M; + if (FObj) { + std::string ErrStr; + M = ParseBitcodeFile(MB, Ctx, &ErrStr); + if (-1 == PyFile_WriteString(ErrStr.c_str(), FObj)) { + return NULL; + } + } else { + M = ParseBitcodeFile(MB, Ctx); + } + delete MB; + return pycapsule_new(M, "llvm::Module"); +} + + +static +PyObject* llvm_WriteBitcodeToFile(const llvm::Module *M, PyObject* FObj) +{ + using namespace llvm; + llvm::SmallVector sv; + llvm::raw_svector_ostream rso(sv); + llvm::WriteBitcodeToFile(M, rso); + rso.flush(); + StringRef ref = rso.str(); + PyObject* buf = PyString_FromStringAndSize(ref.data(), ref.size()); + if (-1 == PyFile_WriteObject(buf, FObj, Py_PRINT_RAW)){ + return NULL; + } + Py_RETURN_NONE; +} + +static +PyObject* llvm_getBitcodeTargetTriple(llvm::StringRef Buf, + llvm::LLVMContext& Ctx, + PyObject* FObj = NULL) +{ + using namespace llvm; + MemoryBuffer* MB = MemoryBuffer::getMemBuffer(Buf); + std::string Triple; + if (FObj) { + std::string ErrStr; + Triple = getBitcodeTargetTriple(MB, Ctx, &ErrStr); + if (-1 == PyFile_WriteString(ErrStr.c_str(), FObj)) { + return NULL; + } + } else { + Triple = getBitcodeTargetTriple(MB, Ctx); + } + delete MB; + return PyString_FromString(Triple.c_str()); +} diff --git a/newbinding/src/Bitcode/ReaderWriter.py b/newbinding/src/Bitcode/ReaderWriter.py new file mode 100644 index 0000000..a8e8c43 --- /dev/null +++ b/newbinding/src/Bitcode/ReaderWriter.py @@ -0,0 +1,30 @@ +from binding import * +from ..namespace import llvm +from ..ADT.StringRef import StringRef +from ..Module import Module +from ..LLVMContext import LLVMContext + +llvm.includes.add('llvm/Bitcode/ReaderWriter.h') + +ParseBitCodeFile = llvm.CustomFunction('ParseBitCodeFile', + 'llvm_ParseBitCodeFile', + PyObjectPtr, # returns Module* + cast(str, StringRef), + ref(LLVMContext), + PyObjectPtr, # file-like object + ).require_only(2) + +WriteBitcodeToFile = llvm.CustomFunction('WriteBitcodeToFile', + 'llvm_WriteBitcodeToFile', + PyObjectPtr, # return None + ptr(Module), + PyObjectPtr, # file-like object + ) + +getBitcodeTargetTriple = llvm.CustomFunction('getBitcodeTargetTriple', + 'llvm_getBitcodeTargetTriple', + PyObjectPtr, # return str + cast(str, StringRef), + ref(LLVMContext), + PyObjectPtr, # file-like object + ).require_only(2) diff --git a/newbinding/src/Bitcode/__init__.py b/newbinding/src/Bitcode/__init__.py new file mode 100644 index 0000000..da0beed --- /dev/null +++ b/newbinding/src/Bitcode/__init__.py @@ -0,0 +1,10 @@ +import os.path, importlib + +def _init(): + for fname in os.listdir(os.path.dirname(__file__)): + if ((fname.endswith('.py') or fname.endswith('.pyc')) and + not fname.startswith('__init__')): + modname = os.path.basename(fname).rsplit('.', 1)[0] + importlib.import_module('.' + modname, __name__) + +_init() diff --git a/newbinding/src/Support/MemoryBuffer.py b/newbinding/src/Support/MemoryBuffer.py deleted file mode 100644 index b960fe6..0000000 --- a/newbinding/src/Support/MemoryBuffer.py +++ /dev/null @@ -1,9 +0,0 @@ -from binding import * -from ..namespace import llvm - -MemoryBuffer = llvm.Class() - -@MemoryBuffer -class MemoryBuffer: - _include_ = 'llvm/Support/MemoryBuffer.h' - diff --git a/newbinding/src/__init__.py b/newbinding/src/__init__.py index 8a1b356..98c06fc 100644 --- a/newbinding/src/__init__.py +++ b/newbinding/src/__init__.py @@ -1,12 +1,15 @@ import os.path, importlib def _init(): - for fname in os.listdir(os.path.dirname(__file__)): - if ((fname.endswith('.py') or fname.endswith('.pyc')) and - not fname.startswith('__init__')): + base = os.path.dirname(__file__) + for fname in os.listdir(base): + print fname + is_python_script = fname.endswith('.py') or fname.endswith('.pyc') + is_init_script = fname.startswith('__init__') + is_directory = os.path.isdir(os.path.join(base, fname)) + if (is_directory or is_python_script) and not is_init_script : modname = os.path.basename(fname).rsplit('.', 1)[0] importlib.import_module('.' + modname, __name__) _init() -import Transforms, ADT, Support, Assembly, ExecutionEngine, CodeGen, Target diff --git a/newbinding/test_binding.py b/newbinding/test_binding.py index 248e32a..8a72aef 100644 --- a/newbinding/test_binding.py +++ b/newbinding/test_binding.py @@ -135,6 +135,22 @@ def test_basic_jit_use(): assert 44 == gvR.toUnsignedInt() + # write bitcode + bc_buffer = StringIO() + api.WriteBitcodeToFile(m, bc_buffer) + bc = bc_buffer.getvalue() + bc_buffer.close() + + # read bitcode + errbuf = StringIO() + m2 = api.ParseBitCodeFile(bc, context, errbuf) + if not m2: + raise Exception(errbuf.getvalue()) + else: + m2.setModuleIdentifier(m.getModuleIdentifier()) + assert str(m2) == str(m) + + def test_engine_builder(): api.InitializeNativeTarget() context = api.getGlobalContext()