From 6028e1765b055c6a2c51d7b8e66286aaaf138476 Mon Sep 17 00:00:00 2001 From: "mdevan.foobar" Date: Sat, 21 Feb 2009 10:02:46 +0000 Subject: [PATCH] Module.link_in and Instruction.is_volatile APIs added (Seth Warn) git-svn-id: http://llvm-py.googlecode.com/svn/trunk@62 8d1e9007-1d4e-0410-b67e-1979fd6579aa --- llvm/_core.c | 31 ++++++++++++++++++++++++++++++- llvm/core.py | 19 +++++++++++++++++++ llvm/extra.cpp | 27 +++++++++++++++++++++++++++ llvm/extra.h | 8 ++++++++ setup.py | 2 +- test/testall.py | 4 ++++ 6 files changed, 89 insertions(+), 2 deletions(-) diff --git a/llvm/_core.c b/llvm/_core.c index 6efa1b3..e7667a2 100644 --- a/llvm/_core.c +++ b/llvm/_core.c @@ -162,6 +162,33 @@ _wLLVMGetBitcodeFromModule(PyObject *self, PyObject *args) return ret; } +static PyObject * +_wLLVMLinkModules(PyObject *self, PyObject *args) +{ + PyObject *dest_obj, *src_obj, *ret; + LLVMModuleRef dest, src; + char *errmsg; + + if (!PyArg_ParseTuple(args, "OO", &dest_obj, &src_obj)) + return NULL; + + dest = (LLVMModuleRef) PyCObject_AsVoidPtr(dest_obj); + src = (LLVMModuleRef) PyCObject_AsVoidPtr(src_obj); + + if (!LLVMLinkModules(dest, src, &errmsg)) { + if (errmsg) { + ret = PyString_FromString(errmsg); + LLVMDisposeMessage(errmsg); + } else { + ret = PyString_FromString("Link error"); + } + return ret; + } + + /* note: success => None, failure => string with error message */ + Py_RETURN_NONE; +} + /*===----------------------------------------------------------------------===*/ /* Types */ /*===----------------------------------------------------------------------===*/ @@ -505,7 +532,7 @@ _wrap_obj2obj(LLVMInstIsCommutative, LLVMValueRef, int) _wrap_obj2obj(LLVMInstIsTrapping, LLVMValueRef, int) _wrap_obj2obj(LLVMInstGetOpcode, LLVMValueRef, int) _wrap_obj2str(LLVMInstGetOpcodeName, LLVMValueRef) - +_wrap_obj2obj(LLVMInstIsVolatile, LLVMValueRef, int) /*===-- Call Sites (Call or Invoke) --------------------------------------===*/ @@ -1001,6 +1028,7 @@ static PyMethodDef core_methods[] = { _method( LLVMGetBitcodeFromModule ) _method( LLVMModuleGetPointerSize ) _method( LLVMModuleGetOrInsertFunction ) + _method( LLVMLinkModules ) /* Types */ @@ -1209,6 +1237,7 @@ static PyMethodDef core_methods[] = { _method( LLVMInstIsTrapping ) _method( LLVMInstGetOpcode ) _method( LLVMInstGetOpcodeName ) + _method( LLVMInstIsVolatile ) /* Call Sites (Call or Invoke) */ _method( LLVMSetInstructionCallConv ) diff --git a/llvm/core.py b/llvm/core.py index 59db453..6f9fa90 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -918,6 +918,20 @@ class Module(llvm.Ownable): llvm::Module::AnyPointerSize.""" return _core.LLVMModuleGetPointerSize(self.ptr) + def link_in(self, other): + """Link the `other' module into this one. + + The `other' module is linked into this one such that types, + global variables, function, etc. are matched and resolved. + + The `other' module is no longer valid after this method is + invoked, and will behave in undefined ways. + """ + check_is_module(other) + ret = _core.LLVMLinkModules(self.ptr, other.ptr) + if isinstance(ret, str): + raise llvm.LLVMException, ret + def add_type_name(self, name, ty): """Map a string to a type. @@ -1842,6 +1856,11 @@ class Instruction(Value): def is_trapping(self): return _core.LLVMInstIsTrapping(self.ptr) != 0 + @property + def is_volatile(self): + """True if this is a volatile load or store.""" + return _core.LLVMInstIsVolatile(self.ptr) != 0 + @property def opcode(self): return _core.LLVMInstGetOpcode(self.ptr) diff --git a/llvm/extra.cpp b/llvm/extra.cpp index 683e8f5..b33c4f8 100644 --- a/llvm/extra.cpp +++ b/llvm/extra.cpp @@ -43,6 +43,7 @@ // LLVM includes #include "llvm/Bitcode/ReaderWriter.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Casting.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/GlobalVariable.h" @@ -60,6 +61,7 @@ #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" #include "llvm/Transforms/Instrumentation.h" +#include "llvm/Linker.h" // LLVM-C includes #include "llvm-c/Core.h" @@ -212,6 +214,15 @@ inst_checkfn(LLVMInstIsAssociative, isAssociative) inst_checkfn(LLVMInstIsCommutative, isCommutative) inst_checkfn(LLVMInstIsTrapping, isTrapping) +unsigned LLVMInstIsVolatile(LLVMValueRef v) +{ + using namespace llvm; + Instruction *ip = unwrap(v); + assert(ip); + return ((isa(*ip) && cast(*ip).isVolatile()) || + (isa(*ip) && cast(*ip).isVolatile()) ); +} + const char *LLVMInstGetOpcodeName(LLVMValueRef inst) { llvm::Instruction *instp = llvm::unwrap(inst); @@ -332,6 +343,22 @@ LLVMModuleRef LLVMGetModuleFromBitcode(const char *bitcode, unsigned bclen, return wrap(modulep); } +unsigned LLVMLinkModules(LLVMModuleRef dest, LLVMModuleRef src, char **out) +{ + llvm::Module *sourcep = llvm::unwrap(src); + assert(sourcep); + llvm::Module *destinationp = llvm::unwrap(dest); + assert(destinationp); + + std::string msg; + if (llvm::Linker::LinkModules(destinationp, sourcep, &msg)) { + *out = strdup(msg.c_str()); + return 0; + } + + return 1; +} + unsigned char *LLVMGetBitcodeFromModule(LLVMModuleRef module, unsigned *lenp) { assert(lenp); diff --git a/llvm/extra.h b/llvm/extra.h index e5482ca..2f3d538 100644 --- a/llvm/extra.h +++ b/llvm/extra.h @@ -109,6 +109,9 @@ unsigned LLVMInstIsAssociative (LLVMValueRef inst); unsigned LLVMInstIsCommutative (LLVMValueRef inst); unsigned LLVMInstIsTrapping (LLVMValueRef inst); +/* As above, but these are wrap methods from subclasses of Instruction. */ +unsigned LLVMInstIsVolatile (LLVMValueRef inst); + /* Wraps llvm::Instruction::getOpcodeName(). */ const char *LLVMInstGetOpcodeName(LLVMValueRef inst); @@ -127,6 +130,11 @@ LLVMModuleRef LLVMGetModuleFromAssembly(const char *asmtxt, unsigned txten, LLVMModuleRef LLVMGetModuleFromBitcode(const char *bc, unsigned bclen, char **out); +/* Wraps llvm::Linker::LinkModules(). Returns 0 on failure (with errmsg + * filled in) and 1 on success. Dispose error message after use with + * LLVMDisposeMessage(). */ +unsigned LLVMLinkModules(LLVMModuleRef dest, LLVMModuleRef src, char **errmsg); + /* Returns pointer to a heap-allocated block of `*len' bytes containing bit code * for the given module. NULL on error. */ unsigned char *LLVMGetBitcodeFromModule(LLVMModuleRef module, unsigned *len); diff --git a/setup.py b/setup.py index b5a28a5..ba128d8 100644 --- a/setup.py +++ b/setup.py @@ -83,7 +83,7 @@ def call_setup(llvm_config): ['core', 'analysis', 'scalaropts', 'executionengine', 'jit', 'native', 'interpreter', 'bitreader', 'bitwriter', 'instrumentation', 'ipa', 'ipo', 'transformutils', - 'asmparser' ]) + 'asmparser', 'linker', 'support']) std_libs = [ 'pthread', 'm', 'stdc++' ] if not ("openbsd" in sys.platform or "freebsd" in sys.platform): diff --git a/test/testall.py b/test/testall.py index 93faff3..c883fb9 100644 --- a/test/testall.py +++ b/test/testall.py @@ -95,6 +95,9 @@ def do_module(): m4 = Module.from_assembly(ss2) t = m4 == m t = m4.pointer_size + mA = Module.new('ma') + mB = Module.new('mb') + mA.link_in(mB) def do_type(): @@ -451,6 +454,7 @@ def do_builder(): t = i.is_associative == False t = i.is_commutative == False t = i.is_trapping == False + t = i.is_volatile == False t = i.opcode t = i.opcode_name