diff --git a/README b/README index f861a66..ac15ff7 100644 --- a/README +++ b/README @@ -25,8 +25,8 @@ Quickstart: 2. Unpack llvm-py, build and install: - $ tar jxvf llvm-py-0.2.tar.bz2 - $ cd llvm-py-0.2 + $ tar jxvf llvm-py-0.3.tar.bz2 + $ cd llvm-py-0.3 # Locate llvm-config, usually under /Release/bin $ sudo python setup.py install --llvm-config=/path/to/llvm-config diff --git a/llvm/_core.c b/llvm/_core.c index 9a213a8..46df19d 100644 --- a/llvm/_core.c +++ b/llvm/_core.c @@ -62,8 +62,11 @@ _wLLVMVerifyModule(PyObject *self, PyObject *args) return ret; } +typedef LLVMModuleRef (*asm_or_bc_fn_t)(const char *A, unsigned Len, + char **OutMessage); + static PyObject * -_wLLVMGetModuleFromBitcode(PyObject *self, PyObject *args) +_get_asm_or_bc(asm_or_bc_fn_t fn, PyObject *self, PyObject *args) { PyObject *obj, *ret; Py_ssize_t len; @@ -77,7 +80,7 @@ _wLLVMGetModuleFromBitcode(PyObject *self, PyObject *args) len = PyString_Size(obj); outmsg = 0; - m = LLVMGetModuleFromBitcode(start, len, &outmsg); + m = fn(start, len, &outmsg); if (!m) { if (outmsg) { ret = PyString_FromString(outmsg); @@ -91,6 +94,18 @@ _wLLVMGetModuleFromBitcode(PyObject *self, PyObject *args) return ctor_LLVMModuleRef(m); } +static PyObject * +_wLLVMGetModuleFromAssembly(PyObject *self, PyObject *args) +{ + return _get_asm_or_bc(LLVMGetModuleFromAssembly, self, args); +} + +static PyObject * +_wLLVMGetModuleFromBitcode(PyObject *self, PyObject *args) +{ + return _get_asm_or_bc(LLVMGetModuleFromBitcode, self, args); +} + static PyObject * _wLLVMGetBitcodeFromModule(PyObject *self, PyObject *args) { @@ -910,6 +925,7 @@ static PyMethodDef core_methods[] = { _method( LLVMDisposeModule ) _method( LLVMDumpModuleToString ) _method( LLVMVerifyModule ) + _method( LLVMGetModuleFromAssembly ) _method( LLVMGetModuleFromBitcode ) _method( LLVMGetBitcodeFromModule ) diff --git a/llvm/core.py b/llvm/core.py index a4ecf7a..372d523 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -751,6 +751,21 @@ class Module(llvm.Ownable): else: return Module(ret) + @staticmethod + def from_assembly(fileobj): + """Create a Module instance from the contents of an LLVM + assembly (.ll) file.""" + + data = fileobj.read() + ret = _core.LLVMGetModuleFromAssembly(data) + if not ret: + raise llvm.LLVMException, \ + "Unable to create module from assembly" + elif isinstance(ret, str): + raise llvm.LLVMException, ret + else: + return Module(ret) + def __init__(self, ptr): """DO NOT CALL DIRECTLY. diff --git a/llvm/extra.cpp b/llvm/extra.cpp index bf78bf0..b049385 100644 --- a/llvm/extra.cpp +++ b/llvm/extra.cpp @@ -20,6 +20,7 @@ #include "llvm/Support/CallSite.h" #include "llvm/IntrinsicInst.h" #include "llvm/Analysis/Verifier.h" +#include "llvm/Assembly/Parser.h" // +includes for passes #include "llvm/PassManager.h" #include "llvm/Analysis/LoopPass.h" @@ -110,6 +111,20 @@ LLVMValueRef LLVMGetIntrinsic(LLVMModuleRef M, int ID, return wrap(intfunc); } +LLVMModuleRef LLVMGetModuleFromAssembly(const char *A, unsigned Len, + char **OutMessage) +{ + ParseError e; + + Module *MP = ParseAssemblyString(A, NULL /*unused within!*/, &e); + if (!MP) { + *OutMessage = strdup(e.getMessage().c_str()); + return NULL; + } + + return wrap(MP); +} + LLVMModuleRef LLVMGetModuleFromBitcode(const char *BC, unsigned Len, char **OutMessage) { diff --git a/llvm/extra.h b/llvm/extra.h index efd8163..85dd42a 100644 --- a/llvm/extra.h +++ b/llvm/extra.h @@ -51,6 +51,11 @@ LLVMValueRef LLVMBuildGetResult(LLVMBuilderRef, LLVMValueRef V, LLVMValueRef LLVMGetIntrinsic(LLVMModuleRef B, int ID, LLVMTypeRef *Types, unsigned Count); +/* reading llvm "assembly" */ + +LLVMModuleRef LLVMGetModuleFromAssembly(const char *A, unsigned Len, + char **OutMessage); + /* bitcode related */ LLVMModuleRef LLVMGetModuleFromBitcode(const char *BC, unsigned Len, diff --git a/setup.py b/setup.py index 051831d..dea5c35 100644 --- a/setup.py +++ b/setup.py @@ -51,7 +51,8 @@ def call_setup(llvm_config): libs_core, objs_core = get_libs_and_objs(llvm_config, ['core', 'analysis', 'scalaropts', 'executionengine', 'jit', 'native', 'interpreter', 'bitreader', 'bitwriter', - 'instrumentation', 'ipa', 'ipo', 'transformutils']) + 'instrumentation', 'ipa', 'ipo', 'transformutils', + 'asmparser' ]) std_libs = [ 'pthread', 'm' ] if not sys.platform.startswith("openbsd"): diff --git a/test/asm.py b/test/asm.py new file mode 100644 index 0000000..7b435f4 --- /dev/null +++ b/test/asm.py @@ -0,0 +1,17 @@ +#!/usr/bin/env python + +from llvm import * +from llvm.core import * + +# create a module +m = Module.new('module1') +m.add_global_variable(Type.int(), 'i') + +# write it's assembly representation to a file +asm = str(m) +print >> file("/tmp/testasm.ll", "w"), asm + +# read it back into a module +m2 = Module.from_assembly(file("/tmp/testasm.ll")) +print m2 + diff --git a/test/testall.py b/test/testall.py index 380134e..b52a2cf 100644 --- a/test/testall.py +++ b/test/testall.py @@ -74,6 +74,10 @@ def do_module(): m2.to_bitcode(ss) m3 = Module.from_bitcode(ss) t = m2 == m3 + ss2 = strstream() + ss2.write(str(m)) + m4 = Module.from_assembly(ss2) + t = m4 == m def do_type(): diff --git a/www/src/about.txt b/www/src/about.txt index 5cbda80..28b0b0a 100644 --- a/www/src/about.txt +++ b/www/src/about.txt @@ -1,9 +1,9 @@ About ===== -llvm-py is developed by Mahadevan R, in his spare time, without being -paid for it. He can be reached at mdevan.foobar@gmail.com, on the -llvm-dev mailing list and irc.oftc.net#llvm (mdevan). +llvm-py is developed by Mahadevan R, in his spare time. He can be +reached at mdevan.foobar@gmail.com, on the llvm-dev mailing list and +irc.oftc.net#llvm (mdevan). Many thanks to the guys over at LLVM for all the nifty software. diff --git a/www/src/contribute.txt b/www/src/contribute.txt index 886d0b4..a96ba84 100644 --- a/www/src/contribute.txt +++ b/www/src/contribute.txt @@ -5,7 +5,7 @@ llvm-py is just hatching. It needs your patches and suggestions to grow up. Please contribute! All patches are welcome. Here are some links to start hacking away: -`75`25~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +`25`75~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Google code hosting, http://code.google.com/p/llvm-py/[http://code.google.com/p/llvm-py/] Browse SVN, http://code.google.com/p/llvm-py/source/browse/[http://code.google.com/p/llvm-py/source/browse] Issues tracker, http://code.google.com/p/llvm-py/issues/list[http://code.google.com/p/llvm-py/issues/list] @@ -20,13 +20,4 @@ $ svn checkout http://llvm-py.googlecode.com/svn/trunk/ llvm-py Mahadevan R (mdevan.foobar@gmail.com) is available to answer your queries. -Current Next Steps ------------------- -- Wrap GenericValue, function call args for execution engine. - * done. -- Add APIs to read/write `.bc` and `.ll` files. -- Wrap `lto`. -- Add examples. -- Update documentation. -- Improve tests.