From ca0a2b9fddd9e8224b5a919de6fbccc80492a04c Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 1 Feb 2013 11:45:19 -0600 Subject: [PATCH] binding for EngineBuilder --- newbinding/binding.py | 3 +- newbinding/capsule.py | 7 +- newbinding/include/llvm_binding/extra.h | 41 ++++++ newbinding/src/EngineBuilder.py | 49 +++++++ newbinding/src/TargetMachine.py | 11 ++ newbinding/test2.py | 170 ++++++++++++++---------- 6 files changed, 206 insertions(+), 75 deletions(-) create mode 100644 newbinding/src/EngineBuilder.py create mode 100644 newbinding/src/TargetMachine.py diff --git a/newbinding/binding.py b/newbinding/binding.py index 9ddedf3..1f980d1 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -358,7 +358,8 @@ class Method(object): argtys = self.signatures[0][1:] for i, ty in enumerate(argtys): if isinstance(ty, ownedptr): - writer.release_ownership('%s[%d]' % (unwrapped, i)) + with writer.block('if len(%s) > %d:' % (unwrapped, i)): + writer.release_ownership('%s[%d]' % (unwrapped, i)) class CustomMethod(Method): def __init__(self, methodname, retty, *argtys): diff --git a/newbinding/capsule.py b/newbinding/capsule.py index 907fa15..8c2f10e 100644 --- a/newbinding/capsule.py +++ b/newbinding/capsule.py @@ -91,7 +91,12 @@ _cache = defaultdict(WeakValueDictionary) def release_ownership(old): logger.debug('Release %s', old) - _addr2dtor[Capsule.getPointer(old)] = None + addr = Capsule.getPointer(old) + if _addr2dtor[addr] is None: + # Guard deduplicated release + raise Exception("Already released") + _addr2dtor[addr] = None + def has_ownership(cap): addr = Capsule.getPointer(cap) diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index 7aacfde..10a4361 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -340,3 +340,44 @@ PyObject* ExecutionEngine_RunFunction(llvm::ExecutionEngine* EE, return pycapsule_new(new GenericValue(ret), GVN); } +static +PyObject* EngineBuilder_setErrorStr(llvm::EngineBuilder* eb, PyObject* fileobj) +{ + + if (!PyFile_Check(fileobj)) { + PyErr_SetString(PyExc_TypeError, "Expecting a file object."); + return NULL; + } + + std::string buffer; + eb->setErrorStr(&buffer); + + if (-1 == PyFile_WriteString(buffer.c_str(), fileobj)) { + return NULL; + } + + return pycapsule_new(eb, "llvm::EngineBuilder"); +} + +static +PyObject* EngineBuilder_setMAttrs(llvm::EngineBuilder* eb, + PyObject* strlist) +{ + if (!PyList_Check(strlist)) { + PyErr_SetString(PyExc_TypeError, "Expecting a list of string."); + return NULL; + } + std::vector tmp; + const int N = PyList_Size(strlist); + tmp.reserve(N); + for (int i = 0; i < N; ++i) { + const char * elem = PyString_AsString(PyList_GetItem(strlist, i)); + if (!elem) { + return NULL; + } + tmp.push_back(elem); + } + eb->setMAttrs(tmp); + return pycapsule_new(eb, "llvm::EngineBuilder"); +} + diff --git a/newbinding/src/EngineBuilder.py b/newbinding/src/EngineBuilder.py new file mode 100644 index 0000000..0e8388e --- /dev/null +++ b/newbinding/src/EngineBuilder.py @@ -0,0 +1,49 @@ +from binding import * +from namespace import llvm +from Module import Module +from JITMemoryManager import JITMemoryManager +from CodeGen import CodeGenOpt, Reloc, CodeModel +from StringRef import StringRef +from ExecutionEngine import ExecutionEngine +from TargetMachine import TargetMachine + +EngineBuilder = llvm.Class() + +@llvm.Class() # a fake class (actually a namespace) +class EngineKind: + Kind = Enum('JIT', 'Interpreter') + +@EngineBuilder +class EngineBuilder: + new = Constructor(ownedptr(Module)) + delete = Destructor() + + def _setter(*args): + return Method(ref(EngineBuilder), *args) + + setEngineKind = _setter(EngineKind.Kind) + setJITMemoryManager = _setter(ptr(JITMemoryManager)) + + setErrorStr = CustomMethod('EngineBuilder_setErrorStr', + PyObjectPtr, PyObjectPtr) + + setOptLevel = _setter(CodeGenOpt.Level) + #setTargetOptions = + setRelocationModel = _setter(Reloc.Model) + setCodeModel = _setter(CodeModel.Model) + setAllocateGVsWithCode = _setter(cast(bool, Bool)) + setMArch = _setter(cast(str, StringRef)) + setMCPU = _setter(cast(str, StringRef)) + setUseMCJIT = _setter(cast(bool, Bool)) + _setMAttrs = CustomMethod('EngineBuilder_setMAttrs', + PyObjectPtr, PyObjectPtr) + @CustomPythonMethod + def setMAttrs(self, attrs): + attrlist = list(str(a) for a in attrs) + return self._setMAttrs(attrlist) + + create = Method(ptr(ExecutionEngine), + ownedptr(TargetMachine)).require_only(0) + + selectTarget = Method(ptr(TargetMachine)) + diff --git a/newbinding/src/TargetMachine.py b/newbinding/src/TargetMachine.py new file mode 100644 index 0000000..e53cd33 --- /dev/null +++ b/newbinding/src/TargetMachine.py @@ -0,0 +1,11 @@ +from binding import * +from namespace import llvm + +TargetMachine = llvm.Class() + +@TargetMachine +class TargetMachine: + _include_ = 'llvm/Target/TargetMachine.h' + delete = Destructor() + + diff --git a/newbinding/test2.py b/newbinding/test2.py index 7902df4..a304426 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -4,111 +4,135 @@ import _capsule from StringIO import StringIO api.capsule.set_debug(True) - -api.InitializeNativeTarget() -context = api.getGlobalContext() +def test_basic_jit_use(): + api.InitializeNativeTarget() + context = api.getGlobalContext() -m = api.Module.new("modname", context) -print m.getModuleIdentifier() -m.setModuleIdentifier('modname2') -print m.getModuleIdentifier() -print 'endianness', m.getEndianness() -assert m.getEndianness() == api.Module.Endianness.AnyEndianness -print 'pointer-size', m.getPointerSize() -assert m.getPointerSize() == api.Module.PointerSize.AnyPointerSize -m.dump() + m = api.Module.new("modname", context) + print m.getModuleIdentifier() + m.setModuleIdentifier('modname2') + print m.getModuleIdentifier() + print 'endianness', m.getEndianness() + assert m.getEndianness() == api.Module.Endianness.AnyEndianness + print 'pointer-size', m.getPointerSize() + assert m.getPointerSize() == api.Module.PointerSize.AnyPointerSize + m.dump() -os = extra.make_raw_ostream_for_printing() -m.print_(os, None) -print os.str() + os = extra.make_raw_ostream_for_printing() + m.print_(os, None) + print os.str() -int1ty = api.Type.getInt1Ty(context) -int1ty.dump() + int1ty = api.Type.getInt1Ty(context) + int1ty.dump() -assert int1ty.isIntegerTy(1) + assert int1ty.isIntegerTy(1) -fnty = api.FunctionType.get(int1ty, False) -fnty.dump() + fnty = api.FunctionType.get(int1ty, False) + fnty.dump() -types = [api.Type.getIntNTy(context, 8), api.Type.getIntNTy(context, 32)] -fnty = api.FunctionType.get(api.Type.getIntNTy(context, 8), types, False) + types = [api.Type.getIntNTy(context, 8), api.Type.getIntNTy(context, 32)] + fnty = api.FunctionType.get(api.Type.getIntNTy(context, 8), types, False) -print fnty + print fnty -const = m.getOrInsertFunction("foo", fnty) -fn = const._downcast(api.Function) -print fn -assert fn.hasName() -assert 'foo' == fn.getName() -fn.setName('bar') -assert 'bar' == fn.getName() + const = m.getOrInsertFunction("foo", fnty) + fn = const._downcast(api.Function) + print fn + assert fn.hasName() + assert 'foo' == fn.getName() + fn.setName('bar') + assert 'bar' == fn.getName() -assert fn.getReturnType().isIntegerTy(8) + assert fn.getReturnType().isIntegerTy(8) -assert fnty is fn.getFunctionType() + assert fnty is fn.getFunctionType() -assert fn.isVarArg() == False -assert fn.getIntrinsicID() == 0 -assert not fn.isIntrinsic() + assert fn.isVarArg() == False + assert fn.getIntrinsicID() == 0 + assert not fn.isIntrinsic() -fn_uselist = fn.list_use() -assert isinstance(fn_uselist, list) -assert len(fn_uselist) == 0 + fn_uselist = fn.list_use() + assert isinstance(fn_uselist, list) + assert len(fn_uselist) == 0 -builder = api.IRBuilder.new(context) -print builder + builder = api.IRBuilder.new(context) + print builder -bb = api.BasicBlock.Create(context, "entry", fn, None) -assert bb.empty() -builder.SetInsertPoint(bb) + bb = api.BasicBlock.Create(context, "entry", fn, None) + assert bb.empty() + builder.SetInsertPoint(bb) -assert bb.getTerminator() is None + assert bb.getTerminator() is None -arg0, arg1 = fn.getArgumentList() -print arg0, arg1 + arg0, arg1 = fn.getArgumentList() + print arg0, arg1 -extended = builder.CreateZExt(arg0, arg1.getType()) -result = builder.CreateAdd(extended, arg1) -ret = builder.CreateTrunc(result, fn.getReturnType()) -builder.CreateRet(ret) + extended = builder.CreateZExt(arg0, arg1.getType()) + result = builder.CreateAdd(extended, arg1) + ret = builder.CreateTrunc(result, fn.getReturnType()) + builder.CreateRet(ret) -print arg0.list_use() + print arg0.list_use() -print fn + print fn -errio = StringIO() -print m + errio = StringIO() + print m -ee = api.ExecutionEngine.createJIT(m, errio) -print ee, errio.getvalue() -print ee.getDataLayout().getStringRepresentation() + ee = api.ExecutionEngine.createJIT(m, errio) + print ee, errio.getvalue() + print ee.getDataLayout().getStringRepresentation() -datalayout_str = 'e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64' + datalayout_str = 'e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f16:16:16-f32:32:32-f64:64:64-f128:128:128-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64' -assert datalayout_str == str(api.DataLayout.new(datalayout_str)) -assert datalayout_str == str(api.DataLayout.new(str(api.DataLayout.new(datalayout_str)))) + assert datalayout_str == str(api.DataLayout.new(datalayout_str)) + assert datalayout_str == str(api.DataLayout.new(str(api.DataLayout.new(datalayout_str)))) -fn2 = ee.FindFunctionNamed(fn.getName()) -assert fn2 is fn + fn2 = ee.FindFunctionNamed(fn.getName()) + assert fn2 is fn -assert ee.getPointerToFunction(fn) -assert ee.getPointerToNamedFunction('printf') + assert ee.getPointerToFunction(fn) + assert ee.getPointerToNamedFunction('printf') -gv0 = api.GenericValue.CreateInt(arg0.getType(), 12, False) -gv1 = api.GenericValue.CreateInt(arg1.getType(), -32, True) + gv0 = api.GenericValue.CreateInt(arg0.getType(), 12, False) + gv1 = api.GenericValue.CreateInt(arg1.getType(), -32, True) -assert gv0.valueIntWidth() == arg0.getType().getIntegerBitWidth() -assert gv1.valueIntWidth() == arg1.getType().getIntegerBitWidth() + assert gv0.valueIntWidth() == arg0.getType().getIntegerBitWidth() + assert gv1.valueIntWidth() == arg1.getType().getIntegerBitWidth() -assert gv0.toUnsignedInt() == 12 -assert gv1.toSignedInt() == -32 + assert gv0.toUnsignedInt() == 12 + assert gv1.toSignedInt() == -32 -gv1 = api.GenericValue.CreateInt(arg1.getType(), 32, False) + gv1 = api.GenericValue.CreateInt(arg1.getType(), 32, False) -gvR = ee.runFunction(fn, (gv0, gv1)) + gvR = ee.runFunction(fn, (gv0, gv1)) -assert 44 == gvR.toUnsignedInt() + assert 44 == gvR.toUnsignedInt() + +def test_engine_builder(): + api.InitializeNativeTarget() + context = api.getGlobalContext() + + m = api.Module.new("modname", context) + + eb = api.EngineBuilder.new(m) + eb2 = eb.setEngineKind(api.EngineKind.Kind.JIT) + assert eb is eb2 + eb.setOptLevel(api.CodeGenOpt.Level.Aggressive).setUseMCJIT(False) + + tm = eb.selectTarget() + ee = eb.create(tm) + + +def main(): + for name, value in globals().items(): + if name.startswith('test_') and callable(value): + print name.center(80, '-') + value() + +if __name__ == '__main__': + main()