From a12c4da93d1147384c08f8d4ffed16ddcb383e99 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 22 Jan 2013 10:09:14 -0600 Subject: [PATCH 01/85] Init commit for work on new binding This contains the foundation for the new binding as well as early work on Module and Type. --- newbinding/Makefile | 18 + .../binding/AssemblyAnnotationWriter.py | 6 + newbinding/binding/DerivedTypes.py | 13 + newbinding/binding/LLVMContext.py | 8 + newbinding/binding/Makefile | 0 newbinding/binding/Module.py | 25 + newbinding/binding/StringRef.py | 6 + newbinding/binding/Type.py | 96 ++++ newbinding/binding/_Debug.py | 3 + newbinding/binding/binding.py | 498 ++++++++++++++++++ newbinding/binding/gen.py | 206 ++++++++ newbinding/binding/namespace.py | 4 + newbinding/binding/raw_ostream.py | 17 + newbinding/binding/utils.py | 6 + newbinding/capsule.cpp | 143 +++++ newbinding/capsule.py | 74 +++ newbinding/include/llvm_binding/binding.h | 73 +++ .../include/llvm_binding/capsule_context.h | 48 ++ newbinding/include/llvm_binding/conversion.h | 93 ++++ newbinding/include/llvm_binding/extra.h | 34 ++ newbinding/setup.py | 54 ++ newbinding/test.py | 32 ++ newbinding/test2.py | 20 + 23 files changed, 1477 insertions(+) create mode 100644 newbinding/Makefile create mode 100644 newbinding/binding/AssemblyAnnotationWriter.py create mode 100644 newbinding/binding/DerivedTypes.py create mode 100644 newbinding/binding/LLVMContext.py create mode 100644 newbinding/binding/Makefile create mode 100644 newbinding/binding/Module.py create mode 100644 newbinding/binding/StringRef.py create mode 100644 newbinding/binding/Type.py create mode 100644 newbinding/binding/_Debug.py create mode 100644 newbinding/binding/binding.py create mode 100644 newbinding/binding/gen.py create mode 100644 newbinding/binding/namespace.py create mode 100644 newbinding/binding/raw_ostream.py create mode 100644 newbinding/binding/utils.py create mode 100644 newbinding/capsule.cpp create mode 100644 newbinding/capsule.py create mode 100644 newbinding/include/llvm_binding/binding.h create mode 100644 newbinding/include/llvm_binding/capsule_context.h create mode 100644 newbinding/include/llvm_binding/conversion.h create mode 100644 newbinding/include/llvm_binding/extra.h create mode 100644 newbinding/setup.py create mode 100644 newbinding/test.py create mode 100644 newbinding/test2.py diff --git a/newbinding/Makefile b/newbinding/Makefile new file mode 100644 index 0000000..ba902e3 --- /dev/null +++ b/newbinding/Makefile @@ -0,0 +1,18 @@ +PYMODS = _Debug raw_ostream Type DerivedTypes LLVMContext StringRef AssemblyAnnotationWriter Module + +all: _api.so _capsule.so + +_api.so _capsule.so: api.cpp capsule.cpp + python setup.py build_ext --inplace + + +api.cpp api.py: binding/*.py include/llvm_binding/*.h + cd binding; python gen.py api $(PYMODS) + mv binding/api.cpp api.cpp + mv binding/api.py api.py + +clean: + rm -f _api.so _capsule.so + rm -f api.cpp api.py + + diff --git a/newbinding/binding/AssemblyAnnotationWriter.py b/newbinding/binding/AssemblyAnnotationWriter.py new file mode 100644 index 0000000..5641232 --- /dev/null +++ b/newbinding/binding/AssemblyAnnotationWriter.py @@ -0,0 +1,6 @@ +from binding import * +from namespace import llvm + +AssemblyAnnotationWriter = llvm.Class() +AssemblyAnnotationWriter.include.add("llvm/Assembly/AssemblyAnnotationWriter.h") + diff --git a/newbinding/binding/DerivedTypes.py b/newbinding/binding/DerivedTypes.py new file mode 100644 index 0000000..10d5fbf --- /dev/null +++ b/newbinding/binding/DerivedTypes.py @@ -0,0 +1,13 @@ +from binding import * +from namespace import llvm +from LLVMContext import LLVMContext +from Type import Type + +FunctionType = Type.Subclass() +FunctionType.include.add('llvm/DerivedTypes.h') + +get = FunctionType.staticmethod(FunctionType.Pointer, Type.Pointer, Bool.From(bool)) +isVarArg = FunctionType.method(Bool.To(bool)) +getReturnType = FunctionType.method(Type.Pointer) +getParamType = FunctionType.method(Type.Pointer, Unsigned.From(int)) +getNumParams = FunctionType.method(Unsigned.To(int)) diff --git a/newbinding/binding/LLVMContext.py b/newbinding/binding/LLVMContext.py new file mode 100644 index 0000000..0965748 --- /dev/null +++ b/newbinding/binding/LLVMContext.py @@ -0,0 +1,8 @@ +from binding import * +from namespace import llvm + +LLVMContext = llvm.Class() +LLVMContext.include.add("llvm/LLVMContext.h") + +getGlobalContext = llvm.Function(LLVMContext.Ref) + diff --git a/newbinding/binding/Makefile b/newbinding/binding/Makefile new file mode 100644 index 0000000..e69de29 diff --git a/newbinding/binding/Module.py b/newbinding/binding/Module.py new file mode 100644 index 0000000..a458401 --- /dev/null +++ b/newbinding/binding/Module.py @@ -0,0 +1,25 @@ +from binding import * +from namespace import llvm +from LLVMContext import LLVMContext +from StringRef import StringRef +from raw_ostream import raw_svector_ostream_helper +from AssemblyAnnotationWriter import AssemblyAnnotationWriter + +Module = llvm.Class() +Module.include.add("llvm/Module.h") + +new = Module.new(StringRef.From(str), LLVMContext.Ref) +delete = Module.delete() +getModuleIdentifier = Module.method(ConstStdString.To(str)) +setModuleIdentifier = Module.method(Void, StringRef.From(str)) +setDataLayout = Module.method(Void, StringRef.From(str)) +setTargetTriple = Module.method(Void, StringRef.From(str)) +setModuleInlineAsm = Module.method(Void, StringRef.From(str)) +appendModuleInlineAsm = Module.method(Void, StringRef.From(str)) +getContext = Module.method(LLVMContext.Ref) +dump = Module.method(Void) +print_ = Module.method(Void, raw_svector_ostream_helper.Ref, + AssemblyAnnotationWriter.Pointer) +print_.realname = 'print' +#getOrInsertFunction = Module.method(Constant, StringRef.From(str), FunctionType.Pointer) + diff --git a/newbinding/binding/StringRef.py b/newbinding/binding/StringRef.py new file mode 100644 index 0000000..554629b --- /dev/null +++ b/newbinding/binding/StringRef.py @@ -0,0 +1,6 @@ +from binding import * +from namespace import llvm + +StringRef = llvm.Class() +StringRef.include.add("llvm/ADT/StringRef.h") + diff --git a/newbinding/binding/Type.py b/newbinding/binding/Type.py new file mode 100644 index 0000000..19f6d61 --- /dev/null +++ b/newbinding/binding/Type.py @@ -0,0 +1,96 @@ +from binding import * +from namespace import llvm +from LLVMContext import LLVMContext +from raw_ostream import raw_svector_ostream_helper + +Type = llvm.Class() +Type.include.add('llvm/Type.h') + +IntegerType = Type.Subclass() +CompositeType = Type.Subclass() +SequentialType = CompositeType.Subclass() +PointerType = SequentialType.Subclass() + +getContext = Type.method(LLVMContext.Ref) +dump = Type.method(Void) +print_ = Type.method(Void, raw_svector_ostream_helper.Ref) +print_.realname = 'print' + +def type_checker(): + return Type.method(Bool.To(bool)) + +isVoidTy = type_checker() +isHalfTy = type_checker() +isFloatTy = type_checker() +isDoubleTy = type_checker() +isX86_FP80Ty = type_checker() +isFP128Ty = type_checker() +isPPC_FP128Ty = type_checker() +isFloatingPointTy = type_checker() +isX86_MMXTy = type_checker() +isFPOrFPVectorTy = type_checker() +isLabelTy = type_checker() +isMetadataTy = type_checker() +isIntOrIntVectorTy = type_checker() +isFunctionTy = type_checker() +isStructTy = type_checker() +isArrayTy = type_checker() +isPointerTy = type_checker() +isPtrOrPtrVectorTy = type_checker() +isVectorTy = type_checker() +isEmptyTy = type_checker() +isPrimitiveType = type_checker() +isDerivedType = type_checker() +isFirstClassType = type_checker() +isSingleValueType = type_checker() +isAggregateType = type_checker() +isSized = type_checker() + +isIntegerTy = Type.multimethod([Bool.To(bool)], + [Bool.To(bool), Unsigned.From(int)]) + + +def type_factory(): + return Type.staticmethod(Type.Pointer, LLVMContext.Ref) + +getVoidTy = type_factory() +getLabelTy = type_factory() +getHalfTy = type_factory() +getFloatTy = type_factory() +getDoubleTy = type_factory() +getMetadataTy = type_factory() +getX86_FP80Ty = type_factory() +getFP128Ty = type_factory() +getPPC_FP128Ty = type_factory() +getX86_MMXTy = type_factory() + +getIntNTy = Type.staticmethod(IntegerType.Pointer, LLVMContext.Ref, Unsigned.From(int)) + +def integer_factory(): + return Type.staticmethod(IntegerType.Pointer, LLVMContext.Ref) + +getInt1Ty = integer_factory() +getInt8Ty = integer_factory() +getInt16Ty = integer_factory() +getInt32Ty = integer_factory() +getInt64Ty = integer_factory() + +def pointer_factory(): + return Type.staticmethod(PointerType.Pointer, LLVMContext.Ref) + +getHalfPtrTy = pointer_factory() +getFloatPtrTy = pointer_factory() +getDoublePtrTy = pointer_factory() +getX86_FP80PtrTy = pointer_factory() +getFP128PtrTy = pointer_factory() +getPPC_FP128PtrTy = pointer_factory() +getX86_MMXPtrTy = pointer_factory() +getInt1PtrTy = pointer_factory() +getInt8PtrTy = pointer_factory() +getInt16PtrTy = pointer_factory() +getInt32PtrTy = pointer_factory() +getInt64PtrTy = pointer_factory() +getIntNPtrTy = Type.staticmethod(PointerType.Pointer, + LLVMContext.Ref, Unsigned.From(int)) + + diff --git a/newbinding/binding/_Debug.py b/newbinding/binding/_Debug.py new file mode 100644 index 0000000..be092f3 --- /dev/null +++ b/newbinding/binding/_Debug.py @@ -0,0 +1,3 @@ +from binding import * + +enable_capsule_dtor_debug = Function('', Void, Bool.From(bool)) diff --git a/newbinding/binding/binding.py b/newbinding/binding/binding.py new file mode 100644 index 0000000..1230813 --- /dev/null +++ b/newbinding/binding/binding.py @@ -0,0 +1,498 @@ +from utils import * + +_py2capi_fmtmap = { + str: 's#', +} + +NULL = 'NULL' + +_symbols = set() + +def new_symbol(name): + if name in _symbols: + ct = 1 + orig = name + while name in _symbols: + name = '%s%d' % (orig, ct) + ct += 1 + _symbols.add(name) + return name + +def parse_arguments(println, var, *args): + typecodes = [] + holders = [] + argvals = [] + for arg in args: + typecodes.append(arg.format) + val = declare(println, 'PyObject*') + argvals.append(val) + holders.append('&' + val) + + items = [var, '"%s"' % (''.join(typecodes))] + holders + println('if(!PyArg_ParseTuple(%s)) return NULL;' % ', '.join(items)) + + # unwrap + unwrapped = [] + for arg, val in zip(args, argvals): + unwrapped.append(arg.unwrap(println, val)) + + return unwrapped + +def mangle(name): + name = name.replace('_', '__').replace(' ', '_') + return name.replace('::', '_').rstrip('*&') + +def pycapsule_new(println, ptr, name, clsname, dtor='capsule_destructor'): + # build capsule + name_soften = mangle(name) + var = new_symbol('pycap_%s' % name_soften) + fmt = 'PyObject* %(var)s = PyCapsule_New(%(ptr)s, "%(name)s", %(dtor)s);' + println(fmt % locals()) + + # build context + fmt = 'new CapsuleContext("%(clsname)s")' + context = declare(println, 'CapsuleContext*', fmt % locals()) + + fmt = 'PyCapsule_SetContext(%(var)s, (void*)%(context)s)' + err = declare(println, 'int', fmt % locals()) + + println('if (%(err)s) return NULL;' % locals()) + return var + + +def declare(println, typ, init=None): + typ_soften = mangle(typ) + var = new_symbol('var_%s' % typ_soften) + if init is None: + println('%(typ)s %(var)s;' % locals()) + else: + println('%(typ)s %(var)s = %(init)s;' % locals()) + return var + + +def return_value(println, var): + println('return %(var)s;' % locals()) + + +def return_none(println): + println('Py_RETURN_NONE;') + + +def die_if_null(println, var): + println('if (!%(var)s) return NULL;' % locals()) + + +class Binding(object): + __rank_global = 0 + def __init__(self): + self.rank = Binding.__rank_global + Binding.__rank_global += 1 + self.include = set() + + def compile(self, name, println): + raise NotImplementedError(type(self)) + +class Ref(object): + def __init__(self, elem): + self.element = elem + + @property + def fullname(self): + return '%s&' % self.element.fullname + + @property + def capsule_name(self): + return self.element.capsule_name + + @property + def pointer(self): + return self.element.pointer + + def as_pointer(self, println, var): + init = '&%s' % (var) + casted = declare(println, self.pointer, init) + return casted + + @property + def format(self): + return 'O' + + def unwrap(self, println, var): + ptr = self.element.unwrap(println, var) + return declare(println, self.fullname, '*%s' % ptr) + + def wrap(self, println, var): + return self.element.wrap(println, self.as_pointer(println, var)) + + +class Pointer(object): + def __init__(self, elem): + self.element = elem + + @property + def fullname(self): + return '%s*' % self.element.fullname + + @property + def capsule_name(self): + return self.element.capsule_name + + @property + def pointer(self): + return self.element.pointer + + @property + def format(self): + return 'O' + + def unwrap(self, println, var): + ret = declare(println, self.fullname) + println2 = indent_println(println) + println('if (%(var)s == Py_None) {' % locals()) + println2('%(ret)s = NULL;' % locals()) + println('} else {') + ptr = self.element.unwrap(println2, var) + println2('%(ret)s = %(ptr)s;' % locals()) + println('}') + return ret + + def wrap(self, println, var): + return self.element.wrap(println, var) + + +class BuiltinType(object): + def __init__(self, name): + self.name = name + self.Ref = Ref(self) + self.Pointer = Pointer(self) + + @property + def fullname(self): + return self.name + + @property + def capsule_name(self): + return self.fullname + + def To(self, pytype): + return Wrapper(self, pytype) + + def From(self, pytype): + return Unwrapper(self, pytype) + +Void = BuiltinType('void') +Bool = BuiltinType('bool') +Unsigned = BuiltinType('unsigned') +ConstStdString = BuiltinType('const std::string') + +class Unwrapper(object): + def __init__(self, cls, pytype): + self.cls = cls + self.pytype = pytype + + @property + def fullname(self): + return str(self.pytype) + + @property + def format(self): + return 'O' + + def unwrap(self, println, var): + out = declare(println, self.cls.fullname) + conv = 'py_%s_to' % (self.pytype.__name__) + status = '%(conv)s(%(var)s, %(out)s)' % locals() + println('if (!%(status)s) return NULL;' % locals()) + return out + + +class Wrapper(object): + def __init__(self, cls, pytype): + self.cls = cls + self.pytype = pytype + + @property + def fullname(self): + return self.cls.fullname + + def wrap(self, println, var): + conv = 'py_%s_from' % (self.pytype.__name__) + func = '%(conv)s(%(var)s)' % locals() + out = declare(println, 'PyObject*', func) + println('if (!%(out)s) return NULL;' % locals()) + return out + +class Class(Binding): + def __init__(self, ns): + super(Class, self).__init__() + self.ctor = None + self.Ref = Ref(self) + self.Pointer = Pointer(self) + self.Subclass = lambda: Subclass(self) + self.ns = ns + self.methods = [] + self.name = None + + def To(self, pytype): + return Wrapper(self, pytype) + + def From(self, pytype): + return Unwrapper(self, pytype) + + def new(self, *args): + method = Constructor(self, self.Pointer, *args) + self.methods.append(method) + return method + + def delete(self): + method = Destructor(self, Void, self.Pointer) + self.methods.append(method) + return method + + def method(self, return_type, *args): + method = Method(self, return_type, self.Pointer, *args) + self.methods.append(method) + return method + + def staticmethod(self, return_type, *args): + sm = StaticMethod(self, return_type, *args) + self.methods.append(sm) + return sm + + def multimethod(self, *signatures): + mm = MultiMethod(self, signatures) + self.methods.append(mm) + return mm + + def compile(self, name, println): + # set name + self.name = self.name or name + + @property + def capsule_name(self): + return self.fullname + + @property + def pointer(self): + return '%s*' % self.fullname + + @property + def fullname(self): + return '::'.join([self.ns, self.name]) + + @property + def mangled_name(self): + return mangle(self.fullname) + + @property + def format(self): + return 'O' + + def unwrap(self, println, var): + typ = self.pointer + elty = self.fullname + cap = self.capsule_name + capptr = 'PyCapsule_GetPointer(%(var)s, "%(cap)s")' % locals() + ptr = declare(println, 'void*', capptr) + unwrapped = 'typecast<%(elty)s>::from(%(ptr)s)' % locals() + var = declare(println, typ, unwrapped) + println('if (!%(var)s) {' % locals()) + println2 = indent_println(println) + println2('PyErr_SetString(PyExc_TypeError, "Invalid cast");') + println2('return NULL;') + println('}') + die_if_null(println, var) + return var + + def wrap(self, println, var): + return pycapsule_new(println, var, self.capsule_name, self.fullname) + +class Subclass(Class): + def __init__(self, parent): + super(Subclass, self).__init__(parent.ns) + self.parent = parent + self.ns = self.parent.ns + + @property + def capsule_name(self): + return self.parent.capsule_name + +class Function(Binding): + def __init__(self, ns, return_type, *args): + super(Function, self).__init__() + self.return_type = return_type + self.args = args + self.ns = ns + self.name = None + + def compile(self, name, println): + # set name + self.name = self.name or name + # generate wrapper + println('static') + println('PyObject*') + println('%(name)s(PyObject* self, PyObject* args)' % locals()) + println('{') + self.compile_body(indent_println(println)) + println('}') + + def compile_body(self, println): + args = parse_arguments(println, 'args', *self.args) + call = '%s(%s)' % (self.fullname, ', '.join(args)) + if self.return_type is not Void: + callres = declare(println, self.return_type.fullname, call) + pycap = self.return_type.wrap(println, callres) + return_value(println, pycap) + else: + println('%s;' % call) + return_none(println) + + + @property + def fullname(self): + return '::'.join([self.ns, self.name]) + +class Method(Binding): + def __init__(self, cls, return_type, *args): + super(Method, self).__init__() + self.cls = cls + self.return_type = return_type + self.args = args + self.name = None + self._realname = None + + def compile(self, name, println): + # set name + self.name = self.name or name + # generate wrapper + println('static') + println('PyObject*') + mangled = self.mangled_name + println('%(mangled)s(PyObject* self, PyObject* args)' % locals()) + println('{') + self.compile_body(indent_println(println)) + println('}') + + def compile_body(self, println): + args = parse_arguments(println, 'args', *self.args) + this = args[0] + args = ', '.join(args[1:]) + name = self.realname + call = '%(this)s->%(name)s(%(args)s)' % locals() + if self.return_type is not Void: + obj = declare(println, self.return_type.fullname, call) + ret = self.return_type.wrap(println, obj) + return_value(println, ret) + else: + println('%s;' % call) + return_none(println) + + @property + def fullname(self): + return '::'.join([self.cls.fullname, self.name]) + + @property + def realname(self): + if not self._realname: + return self.name + else: + return self._realname + + @realname.setter + def realname(self, v): + self._realname = v + + + @property + def mangled_name(self): + return mangle(self.fullname) + +class MultiMethod(Binding): + '''Can only differs by the number of arguments. + ''' + def __init__(self, cls, signatures): + super(MultiMethod, self).__init__() + nargs = set() + for sig in signatures: + n = len(sig) + if n in nargs: + raise TypeError("MultiMethod only supports overloaded version" + "with different number of arguments") + nargs.add(n) + self.cls = cls + self.signatures = signatures + self.name = None + + def compile(self, name, println): + # set name + self.name = self.name or name + # generate wrapper + println('static') + println('PyObject*') + mangled = self.mangled_name + println('%(mangled)s(PyObject* self, PyObject* args)' % locals()) + println('{') + println2 = indent_println(println) + nargs = declare(println2, 'Py_ssize_t', 'PyTuple_Size(args)') + for sig in self.signatures: + expect = len(sig) + println2('if (%(nargs)s == %(expect)d) {' % locals()) + method = Method(self.cls, sig[0], self.cls.Pointer, *sig[1:]) + method.name = self.name + method.compile_body(indent_println(println2)) + println2('}') + println2('PyErr_SetString(PyExc_TypeError, "Wrong # of args");') + println2('return NULL;') + println('}') + + @property + def fullname(self): + return '::'.join([self.cls.fullname, self.name]) + + @property + def mangled_name(self): + return mangle(self.fullname) + +class StaticMethod(Method): + def compile_body(self, println): + args = parse_arguments(println, 'args', *self.args) + args = ', '.join(args) + fullname = self.fullname + call = '%(fullname)s(%(args)s)' % locals() + if self.return_type is not Void: + obj = declare(println, self.return_type.fullname, call) + ret = self.return_type.wrap(println, obj) + return_value(println, ret) + else: + println('%s;' % call) + return_none(println) + +class Constructor(StaticMethod): + def compile_body(self, println): + args = parse_arguments(println, 'args', *self.args) + args = ', '.join(args) + name = self.cls.fullname + ctor = 'new %(name)s(%(args)s)' % locals() + obj = declare(println, self.cls.pointer, ctor) + ret = self.return_type.wrap(println, obj) + return_value(println, ret) + +class Destructor(Method): + def compile_body(self, println): + args = parse_arguments(println, 'args', *self.args) + assert len(args) == 1 + dtor = 'delete %s;' % args[0] + println(dtor) + return_none(println) + + +class Namespace(object): + def __init__(self, name): + self.name = name + + def Class(self, *args, **kwargs): + return Class(self.name, *args, **kwargs) + + def Function(self, *args, **kwargs): + return Function(self.name, *args, **kwargs) + diff --git a/newbinding/binding/gen.py b/newbinding/binding/gen.py new file mode 100644 index 0000000..f662979 --- /dev/null +++ b/newbinding/binding/gen.py @@ -0,0 +1,206 @@ +import sys +from binding import * +from utils import * +from cStringIO import StringIO + +extension_entry = ''' + +extern "C" { + +#if (PY_MAJOR_VERSION >= 3) + +PyObject * +PyInit_%(module)s(void) +{ + PyObject *module = create_python_module("%(module)s", %(methtable)s); + if (module) { + if (populate_submodules(module, submodules)) + return module; + } + return NULL; +} + +#else + +PyMODINIT_FUNC +init%(module)s(void) +{ + PyObject *module = create_python_module("%(module)s", %(methtable)s); + if (module) { + populate_submodules(module, submodules); + } +} +#endif + +} // end extern C + +''' + +def build_methoddef(name, defns, println): + println('static PyMethodDef %s[] = {' % name) + for name, func in defns: + println('{ "%(name)s", (PyCFunction)%(func)s, METH_VARARGS, NULL },' % + locals()) + else: + println('{ NULL }') + println('};') + println('') + + +class Context(object): + def __init__(self): + self.includes = set() + self.functions = {} + self.classes = {} + self.definitions = [] + + def generate_cpp(self, println): + for i in self.includes: + println('#include "%s"' % i) + + println('\n'.join(self.definitions)) + + # global function + defns = [] + for name, func in self.functions.items(): + defns.append((name, func.name)) + build_methoddef('global_functions', defns, println) + + # classes + for name, cls in self.classes.items(): + defns = [] + for meth in cls.methods: + defns.append((meth.name, meth.mangled_name)) + println("// %s" % cls.fullname) + build_methoddef(cls.mangled_name, defns, println) + + println('static SubModuleEntry submodules[] = {') + for name, cls in self.classes.items(): + table = cls.mangled_name + println('{ "%(name)s", %(table)s },' % locals()) + println('{ NULL },') + println('};') + println('') + + # generate entry + println(extension_entry % {'module': '_api', + 'methtable': 'global_functions',}) + + def generate_py(self, println): + println('import _api, capsule') + println('') + # global function + for name in self.functions: + println('def %(name)s(*args):' % locals()) + println2 = indent_println(println) + println2('args = map(capsule.unwrap, args)') + println2('ptr = _api.%(name)s(*args)' % locals()) + println2('return capsule.wrap(ptr)') + println('') + # classes + classes = sorted(self.classes.items(), key=lambda x: x[1].rank) + + for name, cls in classes: + if isinstance(cls, Subclass): + parent = cls.parent.name + else: + parent = 'capsule.Wrapper' + println('@capsule.register_class') + println('class %(name)s(%(parent)s):' % locals()) + self.generate_py_class(indent_println(println), cls) + println('') + + def generate_py_class(self, println, cls): + if len(cls.methods) == 0: + println('pass') + else: + mod = cls.name + for method in cls.methods: + name = method.name + if isinstance(method, StaticMethod): + println('@staticmethod') + println('def %(name)s(*args):' % locals()) + println2 = indent_println(println) + println2('args = map(capsule.unwrap, args)') + println2('ret = _api.%(mod)s.%(name)s(*args)' % locals()) + println2('return capsule.wrap(ret)') + elif isinstance(method, Destructor): + println('_delete_ = _api.%(mod)s.%(name)s' % locals()) + else: + println('def %(name)s(self, *args):' % locals()) + println2 = indent_println(println) + println2('args = map(capsule.unwrap, args)') + println2('ret = _api.%(mod)s.%(name)s(self._ptr, *args)' % + locals()) + println2('return capsule.wrap(ret)') + println('') + + + def add_module(self, modname): + module = __import__(modname) + allsyms = [(k, v) for k, v in vars(module).items() + if isinstance(v, Binding)] + symtab = sorted(allsyms, key=lambda x: x[1].rank) + + # generate includes + for k, v in symtab: + self.includes |= v.include + + # compile everything + for k, v in symtab: + buf = StringIO() + def println_to_def(s): + buf.write(s) + buf.write('\n') + v.compile(k, println_to_def) + self.definitions.append(buf.getvalue()) + buf.close() + + # generate py defintion table for global functions + for k, v in symtab: + if isinstance(v, Function): + if v.name in self.functions: + raise NameError("Duplicated function name: %s" % v.name) + self.functions[v.name] = v + + # generate sub module tables for classes + submodules = [] + for k, v in symtab: + if isinstance(v, Class): + if v.name in self.classes: + if v is not self.classes[v.name]: + raise NameError("Duplicated class: %s" % v.name) + self.classes[v.name] = v + + +def populate_headers(println): + includes = [ + 'llvm_binding/conversion.h', + 'llvm_binding/binding.h', + 'llvm_binding/extra.h', + 'llvm_binding/capsule_context.h', + ] + for inc in includes: + println('#include "%s"' % inc) + +def wrap_println(f): + def println(s): + f.write(s) + f.write('\n') + return println + +if __name__ == '__main__': + + context = Context() + for mod in sys.argv[2:]: + context.add_module(mod) + + filename = sys.argv[1] + with open('%s.cpp' % filename, 'w') as outfile: + println = wrap_println(outfile) + populate_headers(println) + context.generate_cpp(println) + with open('%s.py' % filename, 'w') as outfile: + println = wrap_println(outfile) + context.generate_py(println) + diff --git a/newbinding/binding/namespace.py b/newbinding/binding/namespace.py new file mode 100644 index 0000000..02af8c9 --- /dev/null +++ b/newbinding/binding/namespace.py @@ -0,0 +1,4 @@ +from binding import * + +extra = Namespace('llvm_extra') +llvm = Namespace('llvm') diff --git a/newbinding/binding/raw_ostream.py b/newbinding/binding/raw_ostream.py new file mode 100644 index 0000000..0275db4 --- /dev/null +++ b/newbinding/binding/raw_ostream.py @@ -0,0 +1,17 @@ +from binding import * +from namespace import llvm +from LLVMContext import LLVMContext +from StringRef import StringRef + +raw_ostream = llvm.Class() +raw_ostream.include.add("llvm/Support/raw_ostream.h") + +raw_svector_ostream = raw_ostream.Subclass() +raw_svector_ostream.include.add("llvm/Support/raw_os_ostream.h") + +# extra class to help binding +raw_svector_ostream_helper = raw_svector_ostream.Subclass() +create = raw_svector_ostream_helper.staticmethod( + raw_svector_ostream_helper.Pointer) +delete = raw_svector_ostream_helper.delete() +str = raw_svector_ostream_helper.method(StringRef.To(str)) diff --git a/newbinding/binding/utils.py b/newbinding/binding/utils.py new file mode 100644 index 0000000..6c39990 --- /dev/null +++ b/newbinding/binding/utils.py @@ -0,0 +1,6 @@ + +def indent_println(println): + def _println(s): + println("%s%s" % (' '* 4, s)) + return _println + diff --git a/newbinding/capsule.cpp b/newbinding/capsule.cpp new file mode 100644 index 0000000..40d135b --- /dev/null +++ b/newbinding/capsule.cpp @@ -0,0 +1,143 @@ +#include +#include + +static +PyObject* getName(PyObject* self, PyObject* args) { + PyObject* obj; + if (!PyArg_ParseTuple(args, "O", &obj)){ + return NULL; + } + const char* name = PyCapsule_GetName(obj); + if (!name) return NULL; + + return PyString_FromString(name); +} + +static +PyObject* getPointer(PyObject* self, PyObject* args) { + PyObject* obj; + if (!PyArg_ParseTuple(args, "O", &obj)){ + return NULL; + } + void* pointer = PyCapsule_GetPointer(obj, PyCapsule_GetName(obj)); + if (!pointer) return NULL; + + return PyLong_FromVoidPtr(pointer); +} + +static +PyObject* check(PyObject* self, PyObject* args) { + PyObject* obj; + if (!PyArg_ParseTuple(args, "O", &obj)){ + return NULL; + } + if (PyCapsule_CheckExact(obj)) { + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } +} + +// ------------------ +// PyCapsule Context +// ------------------ + +static +CapsuleContext* getContext(PyObject* self, PyObject* args) { + PyObject* obj; + if (!PyArg_ParseTuple(args, "O", &obj)) { + return NULL; + } + void* context = PyCapsule_GetContext(obj); + if (!context) { + PyErr_SetString(PyExc_TypeError, "PyCapsule has no context."); + return NULL; + } + return (CapsuleContext*)context; +} + +static +PyObject* getClassName(PyObject* self, PyObject* args) { + CapsuleContext* context = getContext(self, args); + if (!context) { + return NULL; + } else { + return PyString_FromString(context->className); + } +} + +static +PyObject* setDestructor(PyObject* self, PyObject* args) { + PyObject* cap; + PyObject* callable; + if (!PyArg_ParseTuple(args, "OO", &cap, &callable)) { + return NULL; + } + PyObject* arglist = Py_BuildValue("(O)", cap); + CapsuleContext* context = getContext(self, arglist); + Py_DECREF(arglist); + if (!context) { + return NULL; + } else { + void* ptr; + if (callable != Py_None) { + if (PyCallable_Check(callable)) { + ptr = callable; + } else { + PyErr_SetString(PyExc_TypeError, "Argument is not callable."); + return NULL; + } + } else { + ptr = NULL; + } + context->destructor = (Destructor_Fn)ptr; + } + Py_RETURN_NONE; +} + +static PyMethodDef core_methods[] = { +#define declmethod(func) { #func , ( PyCFunction )func , METH_VARARGS , NULL } + declmethod(getName), + declmethod(getPointer), + declmethod(check), + declmethod(getClassName), + declmethod(setDestructor), + { NULL }, +#undef declmethod +}; + +// Module main function, hairy because of py3k port +extern "C" { + +#if (PY_MAJOR_VERSION >= 3) + struct PyModuleDef module_def = { + PyModuleDef_HEAD_INIT, + "_capsule", + NULL, + -1, + core_methods, + NULL, NULL, NULL, NULL + }; +#define INITERROR return NULL + PyObject * + PyInit__capsule(void) +#else +#define INITERROR return + PyMODINIT_FUNC + init_capsule(void) +#endif + { +#if PY_MAJOR_VERSION >= 3 + PyObject *module = PyModule_Create( &module_def ); +#else + PyObject *module = Py_InitModule("_capsule", core_methods); +#endif + if (module == NULL) + INITERROR; +#if PY_MAJOR_VERSION >= 3 + + return module; +#endif + } + +} // end extern C diff --git a/newbinding/capsule.py b/newbinding/capsule.py new file mode 100644 index 0000000..b82154b --- /dev/null +++ b/newbinding/capsule.py @@ -0,0 +1,74 @@ +import _capsule +from weakref import WeakValueDictionary + +_pyclasses = {} +_addr2obj = WeakValueDictionary() + + +def _sentry(ptr): + assert _capsule.check(ptr) + + +def classof(cap): + cls = _capsule.getClassName(cap) + return _pyclasses[cls] + + +def wrap(cap): + '''Wrap a PyCapsule with the corresponding Wrapper class. + If `cap` is not a PyCapsule, returns `cap` + ''' + if not _capsule.check(cap): # bypass if cap is not a PyCapsule + return cap + addr = _capsule.getPointer(cap) + try: + # find cached object by pointer address + obj = _addr2obj[addr] + except KeyError: + # create new object and cache it + cls = classof(cap) + obj = cls(cap) + _addr2obj[addr] = obj # cache object by address + # set destructor if cls.delete is defined + if hasattr(cls, '_delete_'): + _capsule.setDestructor(cap, cls._delete_) + else: + assert classof(obj._ptr) is classof(cap) + # Unset destructor for capsules that are repeated + _capsule.setDestructor(cap, None) + return obj + + +def unwrap(obj): + '''Unwrap a Wrapper instance into the underlying PyCapsule. + If `obj` is not a Wrapper instance, returns `obj`. + ''' + if isinstance(obj, Wrapper): + return obj._ptr + else: + return obj + + +def register_class(cls): + clsname = cls.__name__ + _pyclasses['llvm::%s' % clsname] = cls + return cls + + +class Wrapper(object): + + __slots__ = '__ptr' + + def __init__(self, ptr): + _sentry(ptr) + self.__ptr = ptr + + @property + def _ptr(self): + return self.__ptr + + def _release_ownership(self): + _capsule.setDestructor(self._ptr, None) + + + diff --git a/newbinding/include/llvm_binding/binding.h b/newbinding/include/llvm_binding/binding.h new file mode 100644 index 0000000..f7bfde6 --- /dev/null +++ b/newbinding/include/llvm_binding/binding.h @@ -0,0 +1,73 @@ +#include +#include + +#if (PY_MAJOR_VERSION >= 3) + +static +PyObject* +create_python_module(const char *name, PyMethodDef* methtable){ + PyModuleDef module_def_tmp = { + PyModuleDef_HEAD_INIT, + name, + NULL, + -1, + methtable, + NULL, NULL, NULL, NULL + }; + + PyModuleDef* module_def = new PyModuleDef(module_def_tmp); // will leak?? + PyObject* module = PyModule_Create(module_def); + if (module == NULL){ + delete module_def; + return NULL; + } + return module; +} + +#else + +static +PyObject* +create_python_module(const char *name, PyMethodDef* methtable){ + PyObject* module = Py_InitModule(name, methtable); + if (module == NULL) return NULL; + return module; +} + +#endif + +static +PyObject* +create_python_submodule(PyObject* parent, const char* name, + PyMethodDef* methtable) +{ + const char* parentname = PyModule_GetName(parent); + const unsigned len_parent = strlen(parentname); + const unsigned len_sub = strlen(name); + const unsigned len = len_parent + 1 + len_sub; + char* fullname = new char[len + 1]; + strcpy(fullname, parentname); + fullname[len_parent] = '.'; + strcpy(fullname + len_parent + 1, name); + PyObject* submod = create_python_module(fullname, methtable); + delete [] fullname; + if (!submod) + return NULL; + if( -1 == PyModule_AddObject(parent, name, submod) ) + return NULL; + return submod; +} + +struct SubModuleEntry{ + const char* name; + PyMethodDef* methtable; +}; + +static +int populate_submodules(PyObject* parent, SubModuleEntry* entries){ + for(SubModuleEntry* iter = entries; iter->name; ++iter){ + if (!create_python_submodule(parent, iter->name, iter->methtable)) + return 0; + } + return 1; +} \ No newline at end of file diff --git a/newbinding/include/llvm_binding/capsule_context.h b/newbinding/include/llvm_binding/capsule_context.h new file mode 100644 index 0000000..bb45566 --- /dev/null +++ b/newbinding/include/llvm_binding/capsule_context.h @@ -0,0 +1,48 @@ +#ifndef LLVMPY_CAPSULE_CONTEXT_H_ +#define LLVMPY_CAPSULE_CONTEXT_H_ +#include +#include + +typedef PyObject* Destructor_Fn; + +static bool CapsuleContextDebug = false; + +struct CapsuleContext { + const char* className; + Destructor_Fn destructor; + + CapsuleContext(const char* cn, Destructor_Fn dtor=NULL) + : className(cn), destructor(dtor) { } +}; + +void capsule_destructor(PyObject* capsule){ + using std::cerr; + using std::endl; + CapsuleContext* context = (CapsuleContext*)PyCapsule_GetContext(capsule); + if (context->destructor) { + if (CapsuleContextDebug) { + cerr << clock() + << " == DEBUG ==" + << " destroy pointer: " + << context->className + << endl; + } + PyObject_CallMethodObjArgs(context->destructor, capsule, NULL); + } else { + if (CapsuleContextDebug) { + cerr << clock() + << " == DEBUG ==" + << " keep pointer alive: " + << context->className + << endl; + } + } + delete context; +} + +void enable_capsule_dtor_debug(bool enabled){ + CapsuleContextDebug = enabled; +} + +#endif //LLVMPY_CAPSULE_CONTEXT_H_ + diff --git a/newbinding/include/llvm_binding/conversion.h b/newbinding/include/llvm_binding/conversion.h new file mode 100644 index 0000000..c3d6e36 --- /dev/null +++ b/newbinding/include/llvm_binding/conversion.h @@ -0,0 +1,93 @@ +#include +#include +#include + +// python object unwrapper + +static +int py_str_to(PyObject *strobj, llvm::StringRef &strref){ + // type check + if (!PyString_Check(strobj)) { + // raises TypeError + PyErr_SetString(PyExc_TypeError, "Expecting a str"); + return 0; + } + // get len and buffer + const Py_ssize_t len = PyString_Size(strobj); + const char * buf = PyString_AsString(strobj); + if (!buf) { + // raises TypeError + return 0; + } + // set output + strref = llvm::StringRef(buf, len); + // success + return 1; +} + +static +int py_int_to(PyObject *intobj, unsigned & val){ + if (!PyInt_Check(intobj)) { + // raise TypeError + PyErr_SetString(PyExc_TypeError, "Expecting an int"); + return 0; + } + val = PyInt_AsUnsignedLongMask(intobj); + // success + return 1; +} + +static +int py_bool_to(PyObject *boolobj, bool & val){ + if (!PyBool_Check(boolobj)) { + // raise TypeError + PyErr_SetString(PyExc_TypeError, "Expecting a bool"); + return 0; + } + if (boolobj == Py_True) { + val = true; + } else if (boolobj == Py_False) { + val = false; + } else { + PyErr_SetString(PyExc_TypeError, "Invalid boolean object"); + return 0; + } + // success + return 1; +} + +// python object wrapper + +static +PyObject* py_str_from(const std::string &str){ + return PyString_FromStringAndSize(str.c_str(), str.size()); +} + +static +PyObject* py_bool_from(bool val){ + if (val) { + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } +} + +static +PyObject* py_int_from(int val){ + return PyInt_FromLong(val); +} + +// casting +template +struct typecast { + template static + Td* from(Ts* src) { + return llvm::dyn_cast(src); + } + + static + Td* from(void* src) { + return static_cast(src); + } +}; + diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h new file mode 100644 index 0000000..a7388a2 --- /dev/null +++ b/newbinding/include/llvm_binding/extra.h @@ -0,0 +1,34 @@ +#include +#include +#include + +namespace llvm{ + +class raw_svector_ostream_helper: public raw_svector_ostream { + SmallVectorImpl *SV; +public: + static + raw_svector_ostream_helper* create(){ + SmallVectorImpl* sv = new SmallVector(); + return new raw_svector_ostream_helper(sv); + } + + ~raw_svector_ostream_helper(){ + delete SV; + } + +protected: + + explicit + raw_svector_ostream_helper(SmallVectorImpl* sv) + : raw_svector_ostream(*sv), SV(sv) {} + +private: + // no copy + raw_svector_ostream_helper(const raw_svector_ostream_helper&); + // no assign + void operator = (const raw_svector_ostream_helper&); +}; + +} + diff --git a/newbinding/setup.py b/newbinding/setup.py new file mode 100644 index 0000000..6e2ceb5 --- /dev/null +++ b/newbinding/setup.py @@ -0,0 +1,54 @@ +import sys, os +from distutils.core import setup, Extension + +llvm_config = os.environ.get('LLVM_CONFIG_PATH') + +def run_llvm_config(args): + cmd = llvm_config + ' ' + ' '.join(args) + return os.popen(cmd).read().rstrip() + +def get_libs_and_objs(components): + parts = run_llvm_config(['--libs'] + components).split() + libs = [] + objs = [] + for part in parts: + if part.startswith('-l'): + libs.append(part[2:]) + elif part.endswith('.o'): + objs.append(part) + return libs, objs + +incdir = run_llvm_config(['--includedir']) +libdir = run_llvm_config(['--libdir']) +ldflags = run_llvm_config(['--ldflags']) +macros = [('__STDC_CONSTANT_MACROS', None), + ('__STDC_LIMIT_MACROS', None)] + +extra_link_args = ldflags.split() + +libs_core, objs_core = get_libs_and_objs(['core', 'analysis', 'scalaropts', + 'executionengine', 'jit', 'native', + 'interpreter', 'bitreader', + 'bitwriter', 'instrumentation', 'ipa', + 'ipo', 'transformutils', 'asmparser', + 'linker', 'support', 'vectorize']) + +ext_modules = [Extension(name='_api', + sources=['api.cpp'], + include_dirs = ['include', incdir], + library_dirs = [libdir], + libraries = libs_core, + define_macros = macros, + extra_objects = objs_core, + extra_link_args = extra_link_args), + Extension(name='_capsule', + sources=['capsule.cpp'], + include_dirs = ['include'],), + ] + + +setup(name = 'llvmpy2', + description = 'Python bindings for LLVM', + author = 'Siu Kwan Lam', + ext_modules = ext_modules, + license = "BSD") diff --git a/newbinding/test.py b/newbinding/test.py new file mode 100644 index 0000000..bed9e1a --- /dev/null +++ b/newbinding/test.py @@ -0,0 +1,32 @@ +import _api + +context = _api.getGlobalContext() +modname = "modname" +module = _api.Module.new(modname, context) +assert modname == _api.Module.getModuleIdentifier(module) +modname2 = "newmodname" +_api.Module.setModuleIdentifier(module, modname2) +assert modname2 == _api.Module.getModuleIdentifier(module) + +_api.Module.dump(module) + +_api.Module.delete(module) + +voidty = _api.Type.getVoidTy(context) +assert _api.Type.isVoidTy(voidty) +assert not _api.Type.isLabelTy(voidty) + +int21ty = _api.Type.getIntNTy(context, 21) +assert _api.Type.isIntegerTy(int21ty) +assert _api.Type.isIntegerTy(int21ty, 21) +_api.Type.dump(int21ty) + +halfty = _api.Type.getHalfTy(context) +assert _api.Type.isHalfTy(halfty) +_api.Type.dump(halfty) + +fnty = _api.FunctionType.get(halfty, False) +_api.Type.dump(fnty) + + + diff --git a/newbinding/test2.py b/newbinding/test2.py new file mode 100644 index 0000000..25a59d7 --- /dev/null +++ b/newbinding/test2.py @@ -0,0 +1,20 @@ +import api +#api.enable_capsule_dtor_debug(True) +context = api.getGlobalContext() + +m = api.Module.new("modname", context) +print m.getModuleIdentifier() +m.setModuleIdentifier('modname2') +print m.getModuleIdentifier() +m.dump() +os = api.raw_svector_ostream_helper.create() +m.print_(os, None) +print os.str() + +int1ty = api.Type.getInt1Ty(context) +int1ty.dump() + +print int1ty.isIntegerTy(1) + + + From 47771d8dbcd61d86c01dab07696e1238b7d64d9b Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 22 Jan 2013 10:13:41 -0600 Subject: [PATCH 02/85] Add README --- newbinding/README | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 newbinding/README diff --git a/newbinding/README b/newbinding/README new file mode 100644 index 0000000..2bfabcd --- /dev/null +++ b/newbinding/README @@ -0,0 +1,5 @@ +# README + +This is a reimplementation of the LLVM binding, aiming to provide a more familiar interface to the C++ API whenever possible. + +The implementation uses a custom DSL in python to describe the interface (under binding directory). The DSL serves as input to *gen.py* for generation of the .cpp and .py files for the actual binding. From 5c1e8985a13f2ef4deb44015d74a856ec7977d29 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 22 Jan 2013 10:16:15 -0600 Subject: [PATCH 03/85] Delete empty unused Makefile --- newbinding/binding/Makefile | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 newbinding/binding/Makefile diff --git a/newbinding/binding/Makefile b/newbinding/binding/Makefile deleted file mode 100644 index e69de29..0000000 From d0935fe53383a3916d3fdd62aeb448c0339726af Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 22 Jan 2013 10:41:22 -0600 Subject: [PATCH 04/85] Organize code layout --- newbinding/Makefile | 10 ++++---- newbinding/{binding => }/binding.py | 0 newbinding/{binding => }/gen.py | 23 ++++++++++++++----- .../AssemblyAnnotationWriter.py | 0 newbinding/{binding => src}/DerivedTypes.py | 0 newbinding/{binding => src}/LLVMContext.py | 0 newbinding/{binding => src}/Module.py | 0 newbinding/{binding => src}/StringRef.py | 0 newbinding/{binding => src}/Type.py | 0 newbinding/{binding => src}/_Debug.py | 0 newbinding/src/__init__.py | 0 newbinding/{binding => src}/namespace.py | 0 newbinding/{binding => src}/raw_ostream.py | 0 newbinding/{binding => }/utils.py | 0 14 files changed, 22 insertions(+), 11 deletions(-) rename newbinding/{binding => }/binding.py (100%) rename newbinding/{binding => }/gen.py (92%) rename newbinding/{binding => src}/AssemblyAnnotationWriter.py (100%) rename newbinding/{binding => src}/DerivedTypes.py (100%) rename newbinding/{binding => src}/LLVMContext.py (100%) rename newbinding/{binding => src}/Module.py (100%) rename newbinding/{binding => src}/StringRef.py (100%) rename newbinding/{binding => src}/Type.py (100%) rename newbinding/{binding => src}/_Debug.py (100%) create mode 100644 newbinding/src/__init__.py rename newbinding/{binding => src}/namespace.py (100%) rename newbinding/{binding => src}/raw_ostream.py (100%) rename newbinding/{binding => }/utils.py (100%) diff --git a/newbinding/Makefile b/newbinding/Makefile index ba902e3..0db1f29 100644 --- a/newbinding/Makefile +++ b/newbinding/Makefile @@ -5,14 +5,14 @@ all: _api.so _capsule.so _api.so _capsule.so: api.cpp capsule.cpp python setup.py build_ext --inplace - -api.cpp api.py: binding/*.py include/llvm_binding/*.h - cd binding; python gen.py api $(PYMODS) - mv binding/api.cpp api.cpp - mv binding/api.py api.py +api.cpp api.py: src/*.py include/llvm_binding/*.h + python gen.py api src $(PYMODS) clean: rm -f _api.so _capsule.so rm -f api.cpp api.py +check: _api.so api.py + python test2.py +@PHONY: all clean check diff --git a/newbinding/binding/binding.py b/newbinding/binding.py similarity index 100% rename from newbinding/binding/binding.py rename to newbinding/binding.py diff --git a/newbinding/binding/gen.py b/newbinding/gen.py similarity index 92% rename from newbinding/binding/gen.py rename to newbinding/gen.py index f662979..c2126ab 100644 --- a/newbinding/binding/gen.py +++ b/newbinding/gen.py @@ -136,8 +136,7 @@ class Context(object): println('') - def add_module(self, modname): - module = __import__(modname) + def add_module(self, module): allsyms = [(k, v) for k, v in vars(module).items() if isinstance(v, Binding)] symtab = sorted(allsyms, key=lambda x: x[1].rank) @@ -190,17 +189,29 @@ def wrap_println(f): return println if __name__ == '__main__': + outputfilename = sys.argv[1] + srcdir = sys.argv[2] + modnames = sys.argv[3:] + + modules = [] + for m in modnames: + path = '%s.%s' % (srcdir, m) + print path + module = __import__(path) + for token in path.split('.')[1:]: + module = getattr(module, token) + modules.append(module) context = Context() - for mod in sys.argv[2:]: + + for mod in modules: context.add_module(mod) - filename = sys.argv[1] - with open('%s.cpp' % filename, 'w') as outfile: + with open('%s.cpp' % outputfilename, 'w') as outfile: println = wrap_println(outfile) populate_headers(println) context.generate_cpp(println) - with open('%s.py' % filename, 'w') as outfile: + with open('%s.py' % outputfilename, 'w') as outfile: println = wrap_println(outfile) context.generate_py(println) diff --git a/newbinding/binding/AssemblyAnnotationWriter.py b/newbinding/src/AssemblyAnnotationWriter.py similarity index 100% rename from newbinding/binding/AssemblyAnnotationWriter.py rename to newbinding/src/AssemblyAnnotationWriter.py diff --git a/newbinding/binding/DerivedTypes.py b/newbinding/src/DerivedTypes.py similarity index 100% rename from newbinding/binding/DerivedTypes.py rename to newbinding/src/DerivedTypes.py diff --git a/newbinding/binding/LLVMContext.py b/newbinding/src/LLVMContext.py similarity index 100% rename from newbinding/binding/LLVMContext.py rename to newbinding/src/LLVMContext.py diff --git a/newbinding/binding/Module.py b/newbinding/src/Module.py similarity index 100% rename from newbinding/binding/Module.py rename to newbinding/src/Module.py diff --git a/newbinding/binding/StringRef.py b/newbinding/src/StringRef.py similarity index 100% rename from newbinding/binding/StringRef.py rename to newbinding/src/StringRef.py diff --git a/newbinding/binding/Type.py b/newbinding/src/Type.py similarity index 100% rename from newbinding/binding/Type.py rename to newbinding/src/Type.py diff --git a/newbinding/binding/_Debug.py b/newbinding/src/_Debug.py similarity index 100% rename from newbinding/binding/_Debug.py rename to newbinding/src/_Debug.py diff --git a/newbinding/src/__init__.py b/newbinding/src/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/newbinding/binding/namespace.py b/newbinding/src/namespace.py similarity index 100% rename from newbinding/binding/namespace.py rename to newbinding/src/namespace.py diff --git a/newbinding/binding/raw_ostream.py b/newbinding/src/raw_ostream.py similarity index 100% rename from newbinding/binding/raw_ostream.py rename to newbinding/src/raw_ostream.py diff --git a/newbinding/binding/utils.py b/newbinding/utils.py similarity index 100% rename from newbinding/binding/utils.py rename to newbinding/utils.py From 36df29ba71df48beb838e60d9a5a2616fb3a8fb3 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 22 Jan 2013 11:49:41 -0600 Subject: [PATCH 05/85] Add enum support --- newbinding/binding.py | 46 +++++++++++++++++++++++++++++++++++++++++++ newbinding/gen.py | 8 ++++++++ 2 files changed, 54 insertions(+) diff --git a/newbinding/binding.py b/newbinding/binding.py index 1230813..fa9ce90 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -222,6 +222,50 @@ class Wrapper(object): println('if (!%(out)s) return NULL;' % locals()) return out +class Enum(Binding): + def __init__(self, ns, *values): + super(Enum, self).__init__() + self.values = values + self.ns = ns + self.name = None + + def compile(self, name, println): + self.name = self.name or name + + @property + def fullname(self): + return '::'.join([self.ns, self.name]) + +class ClassEnum(Enum): + def __init__(self, cls, *values): + super(ClassEnum, self).__init__(None, *values) + self.cls = cls + self.cls.enums.append(self) + + def compile(self, name, println): + self.ns = self.cls.fullname + super(ClassEnum, self).compile(name, println) + + def wrap(self, println, var): + println2 = indent_println(println) + ret = declare(println, 'PyObject*', NULL) + println('switch(%s) { ' % var) + for v in self.values: + println('case %s::%s:' % (self.ns, v)) + println2('%(ret)s = PyString_FromString("%(v)s");' % locals()) + println2('break;') + else: + println('default:') + println2('PyErr_SetString(PyExc_TypeError, "Invalid enum: %s");' % + v) + println2('return NULL;') + println('}') + return ret + + def unwrap(self, println, var): + pass + + class Class(Binding): def __init__(self, ns): super(Class, self).__init__() @@ -229,6 +273,8 @@ class Class(Binding): self.Ref = Ref(self) self.Pointer = Pointer(self) self.Subclass = lambda: Subclass(self) + self.Enum = lambda *v: ClassEnum(self, *v) + self.enums = [] self.ns = ns self.methods = [] self.name = None diff --git a/newbinding/gen.py b/newbinding/gen.py index c2126ab..87c0697 100644 --- a/newbinding/gen.py +++ b/newbinding/gen.py @@ -115,6 +115,14 @@ class Context(object): println('pass') else: mod = cls.name + # generate class enums + for enum in cls.enums: + println('class %s:' % enum.name) + println2 = indent_println(println) + for v in enum.values: + println2('%(v)s = "%(v)s"' % locals()) + println('') + # generate class methods for method in cls.methods: name = method.name if isinstance(method, StaticMethod): From e39e1c72057981f2cf3bbc42354e3f85e7592c62 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 22 Jan 2013 11:50:06 -0600 Subject: [PATCH 06/85] Add logging --- newbinding/binding.py | 3 +++ newbinding/gen.py | 11 +++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/newbinding/binding.py b/newbinding/binding.py index fa9ce90..ab0e1c0 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -1,5 +1,8 @@ +import logging from utils import * +logger = logging.getLogger(__name__) + _py2capi_fmtmap = { str: 's#', } diff --git a/newbinding/gen.py b/newbinding/gen.py index 87c0697..81a4815 100644 --- a/newbinding/gen.py +++ b/newbinding/gen.py @@ -1,8 +1,11 @@ -import sys +import sys, logging from binding import * from utils import * from cStringIO import StringIO +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + extension_entry = ''' extern "C" { @@ -143,7 +146,6 @@ class Context(object): println2('return capsule.wrap(ret)') println('') - def add_module(self, module): allsyms = [(k, v) for k, v in vars(module).items() if isinstance(v, Binding)] @@ -159,6 +161,7 @@ class Context(object): def println_to_def(s): buf.write(s) buf.write('\n') + logger.info('compiling %s', k) v.compile(k, println_to_def) self.definitions.append(buf.getvalue()) buf.close() @@ -200,11 +203,11 @@ if __name__ == '__main__': outputfilename = sys.argv[1] srcdir = sys.argv[2] modnames = sys.argv[3:] - + modules = [] for m in modnames: path = '%s.%s' % (srcdir, m) - print path + logger.info("import module %s", path) module = __import__(path) for token in path.split('.')[1:]: module = getattr(module, token) From 089c825b0cdd89384b639f1f1b233f8aab59074d Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 22 Jan 2013 11:50:39 -0600 Subject: [PATCH 07/85] Add cleantemp rule in Makefile --- newbinding/Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/newbinding/Makefile b/newbinding/Makefile index 0db1f29..77a012b 100644 --- a/newbinding/Makefile +++ b/newbinding/Makefile @@ -8,9 +8,13 @@ _api.so _capsule.so: api.cpp capsule.cpp api.cpp api.py: src/*.py include/llvm_binding/*.h python gen.py api src $(PYMODS) -clean: +clean: cleantemp rm -f _api.so _capsule.so + +cleantemp: rm -f api.cpp api.py + rm -f src/*.pyc + check: _api.so api.py python test2.py From f88036274a3d9e7de2a7cbcd3e064f16e847962e Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 22 Jan 2013 15:31:13 -0600 Subject: [PATCH 08/85] Fix and rewrite the memory management for capsules. --- newbinding/Makefile | 3 +- newbinding/binding.py | 4 +- newbinding/capsule.cpp | 29 -------------- newbinding/capsule.py | 39 ++++++++++++++++--- .../include/llvm_binding/capsule_context.h | 39 +++---------------- newbinding/src/_Debug.py | 3 -- newbinding/test2.py | 26 ++++++++++++- 7 files changed, 69 insertions(+), 74 deletions(-) delete mode 100644 newbinding/src/_Debug.py diff --git a/newbinding/Makefile b/newbinding/Makefile index 77a012b..49e244b 100644 --- a/newbinding/Makefile +++ b/newbinding/Makefile @@ -1,4 +1,5 @@ -PYMODS = _Debug raw_ostream Type DerivedTypes LLVMContext StringRef AssemblyAnnotationWriter Module +PYTHON = python +PYMODS = raw_ostream Type DerivedTypes LLVMContext StringRef AssemblyAnnotationWriter Module all: _api.so _capsule.so diff --git a/newbinding/binding.py b/newbinding/binding.py index ab0e1c0..63fcf9e 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -45,13 +45,15 @@ def mangle(name): name = name.replace('_', '__').replace(' ', '_') return name.replace('::', '_').rstrip('*&') -def pycapsule_new(println, ptr, name, clsname, dtor='capsule_destructor'): +def pycapsule_new(println, ptr, name, clsname, dtor=NULL): # build capsule name_soften = mangle(name) var = new_symbol('pycap_%s' % name_soften) fmt = 'PyObject* %(var)s = PyCapsule_New(%(ptr)s, "%(name)s", %(dtor)s);' println(fmt % locals()) + println('if (!%(var)s) return NULL;' % locals()) + # build context fmt = 'new CapsuleContext("%(clsname)s")' context = declare(println, 'CapsuleContext*', fmt % locals()) diff --git a/newbinding/capsule.cpp b/newbinding/capsule.cpp index 40d135b..e7e4932 100644 --- a/newbinding/capsule.cpp +++ b/newbinding/capsule.cpp @@ -66,34 +66,6 @@ PyObject* getClassName(PyObject* self, PyObject* args) { } } -static -PyObject* setDestructor(PyObject* self, PyObject* args) { - PyObject* cap; - PyObject* callable; - if (!PyArg_ParseTuple(args, "OO", &cap, &callable)) { - return NULL; - } - PyObject* arglist = Py_BuildValue("(O)", cap); - CapsuleContext* context = getContext(self, arglist); - Py_DECREF(arglist); - if (!context) { - return NULL; - } else { - void* ptr; - if (callable != Py_None) { - if (PyCallable_Check(callable)) { - ptr = callable; - } else { - PyErr_SetString(PyExc_TypeError, "Argument is not callable."); - return NULL; - } - } else { - ptr = NULL; - } - context->destructor = (Destructor_Fn)ptr; - } - Py_RETURN_NONE; -} static PyMethodDef core_methods[] = { #define declmethod(func) { #func , ( PyCFunction )func , METH_VARARGS , NULL } @@ -101,7 +73,6 @@ static PyMethodDef core_methods[] = { declmethod(getPointer), declmethod(check), declmethod(getClassName), - declmethod(setDestructor), { NULL }, #undef declmethod }; diff --git a/newbinding/capsule.py b/newbinding/capsule.py index b82154b..509b4c4 100644 --- a/newbinding/capsule.py +++ b/newbinding/capsule.py @@ -1,18 +1,44 @@ import _capsule -from weakref import WeakValueDictionary +from weakref import WeakValueDictionary, ref +import logging +logger = logging.getLogger(__name__) + +def set_debug(enabled): + ''' + Side-effect: configure logger with it is not configured. + ''' + if enabled: + # If no handlers are configured for the root logger, + # build a default handler for debugging. + # Can we do better? + if not logger.root.handlers: + logging.basicConfig() + logger.setLevel(logging.DEBUG) + else: + logger.setLevel(logging.WARNING) + + +class WeakRef(ref): + __slots__ = 'capsule', 'dtor' _pyclasses = {} _addr2obj = WeakValueDictionary() - +_owners = {} def _sentry(ptr): assert _capsule.check(ptr) - def classof(cap): cls = _capsule.getClassName(cap) return _pyclasses[cls] +def _capsule_destructor(weak): + cap = weak.capsule + addr = _capsule.getPointer(cap) + cls = _capsule.getClassName(cap) + logger.debug("destroy pointer %s to %s", addr, cls) + weak.dtor(cap) + del _owners[addr] def wrap(cap): '''Wrap a PyCapsule with the corresponding Wrapper class. @@ -29,9 +55,12 @@ def wrap(cap): cls = classof(cap) obj = cls(cap) _addr2obj[addr] = obj # cache object by address - # set destructor if cls.delete is defined + # set ownership if *cls* defines *_delete_* if hasattr(cls, '_delete_'): - _capsule.setDestructor(cap, cls._delete_) + weak = WeakRef(obj, _capsule_destructor) + _owners[addr] = weak + weak.capsule = cap + weak.dtor = cls._delete_ else: assert classof(obj._ptr) is classof(cap) # Unset destructor for capsules that are repeated diff --git a/newbinding/include/llvm_binding/capsule_context.h b/newbinding/include/llvm_binding/capsule_context.h index bb45566..dacfc89 100644 --- a/newbinding/include/llvm_binding/capsule_context.h +++ b/newbinding/include/llvm_binding/capsule_context.h @@ -1,48 +1,19 @@ #ifndef LLVMPY_CAPSULE_CONTEXT_H_ #define LLVMPY_CAPSULE_CONTEXT_H_ + #include #include typedef PyObject* Destructor_Fn; -static bool CapsuleContextDebug = false; - struct CapsuleContext { const char* className; - Destructor_Fn destructor; - - CapsuleContext(const char* cn, Destructor_Fn dtor=NULL) - : className(cn), destructor(dtor) { } + + CapsuleContext(const char* cn) + : className(cn) + { } }; -void capsule_destructor(PyObject* capsule){ - using std::cerr; - using std::endl; - CapsuleContext* context = (CapsuleContext*)PyCapsule_GetContext(capsule); - if (context->destructor) { - if (CapsuleContextDebug) { - cerr << clock() - << " == DEBUG ==" - << " destroy pointer: " - << context->className - << endl; - } - PyObject_CallMethodObjArgs(context->destructor, capsule, NULL); - } else { - if (CapsuleContextDebug) { - cerr << clock() - << " == DEBUG ==" - << " keep pointer alive: " - << context->className - << endl; - } - } - delete context; -} - -void enable_capsule_dtor_debug(bool enabled){ - CapsuleContextDebug = enabled; -} #endif //LLVMPY_CAPSULE_CONTEXT_H_ diff --git a/newbinding/src/_Debug.py b/newbinding/src/_Debug.py deleted file mode 100644 index be092f3..0000000 --- a/newbinding/src/_Debug.py +++ /dev/null @@ -1,3 +0,0 @@ -from binding import * - -enable_capsule_dtor_debug = Function('', Void, Bool.From(bool)) diff --git a/newbinding/test2.py b/newbinding/test2.py index 25a59d7..872dfc0 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -1,20 +1,44 @@ import api -#api.enable_capsule_dtor_debug(True) +#api.capsule.set_debug(True) context = api.getGlobalContext() +def test(): + print '*' * 80 + 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 = api.raw_svector_ostream_helper.create() m.print_(os, None) print os.str() + int1ty = api.Type.getInt1Ty(context) int1ty.dump() print int1ty.isIntegerTy(1) +fnty = api.FunctionType.get(int1ty, False) +os2 = api.raw_svector_ostream_helper.create() +fnty.print_(os2) +print os2.str() From bd550e3c0ed70dfe4c55864c3ea3b95a4c250d24 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 22 Jan 2013 15:33:23 -0600 Subject: [PATCH 09/85] Implement StaticMultiMethod --- newbinding/binding.py | 52 ++++++++++++++++++++++++++++++++++ newbinding/gen.py | 3 +- newbinding/src/DerivedTypes.py | 6 +++- 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/newbinding/binding.py b/newbinding/binding.py index 63fcf9e..de68b55 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -314,6 +314,11 @@ class Class(Binding): mm = MultiMethod(self, signatures) self.methods.append(mm) return mm + + def staticmultimethod(self, *signatures): + smm = StaticMultiMethod(self, signatures) + self.methods.append(smm) + return smm def compile(self, name, println): # set name @@ -518,6 +523,53 @@ class StaticMethod(Method): println('%s;' % call) return_none(println) +class StaticMultiMethod(Binding): + '''Can only differs by the number of arguments. + ''' + def __init__(self, cls, signatures): + super(StaticMultiMethod, self).__init__() + nargs = set() + for sig in signatures: + n = len(sig) + if n in nargs: + raise TypeError("StaticMultiMethod only supports overloaded " + "version with different number of arguments") + nargs.add(n) + self.cls = cls + self.signatures = signatures + self.name = None + + + def compile(self, name, println): + # set name + self.name = self.name or name + # generate wrapper + println('static') + println('PyObject*') + mangled = self.mangled_name + println('%(mangled)s(PyObject* self, PyObject* args)' % locals()) + println('{') + println2 = indent_println(println) + nargs = declare(println2, 'Py_ssize_t', 'PyTuple_Size(args)') + for sig in self.signatures: + expect = len(sig) - 1 + println2('if (%(nargs)s == %(expect)d) {' % locals()) + method = StaticMethod(self.cls, sig[0], *sig[1:]) + method.name = self.name + method.compile_body(indent_println(println2)) + println2('}') + println2('PyErr_SetString(PyExc_TypeError, "Wrong # of args");') + println2('return NULL;') + println('}') + + @property + def fullname(self): + return '::'.join([self.cls.fullname, self.name]) + + @property + def mangled_name(self): + return mangle(self.fullname) + class Constructor(StaticMethod): def compile_body(self, println): args = parse_arguments(println, 'args', *self.args) diff --git a/newbinding/gen.py b/newbinding/gen.py index 81a4815..4081f01 100644 --- a/newbinding/gen.py +++ b/newbinding/gen.py @@ -128,7 +128,8 @@ class Context(object): # generate class methods for method in cls.methods: name = method.name - if isinstance(method, StaticMethod): + if(isinstance(method, StaticMethod) or + isinstance(method, StaticMultiMethod)): println('@staticmethod') println('def %(name)s(*args):' % locals()) println2 = indent_println(println) diff --git a/newbinding/src/DerivedTypes.py b/newbinding/src/DerivedTypes.py index 10d5fbf..edf4297 100644 --- a/newbinding/src/DerivedTypes.py +++ b/newbinding/src/DerivedTypes.py @@ -6,7 +6,11 @@ from Type import Type FunctionType = Type.Subclass() FunctionType.include.add('llvm/DerivedTypes.h') -get = FunctionType.staticmethod(FunctionType.Pointer, Type.Pointer, Bool.From(bool)) +get = FunctionType.staticmultimethod([FunctionType.Pointer, + Type.Pointer, Bool.From(bool)],) +# (FunctionType.Pointer, +# Type.Pointer, )]) + isVarArg = FunctionType.method(Bool.To(bool)) getReturnType = FunctionType.method(Type.Pointer) getParamType = FunctionType.method(Type.Pointer, Unsigned.From(int)) From 3e89a97fdb22e97c529f55380ca632dd53f18fb0 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 22 Jan 2013 15:33:50 -0600 Subject: [PATCH 10/85] Improve Makefile --- newbinding/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/newbinding/Makefile b/newbinding/Makefile index 49e244b..3996d8b 100644 --- a/newbinding/Makefile +++ b/newbinding/Makefile @@ -4,10 +4,10 @@ PYMODS = raw_ostream Type DerivedTypes LLVMContext StringRef AssemblyAnnotationW all: _api.so _capsule.so _api.so _capsule.so: api.cpp capsule.cpp - python setup.py build_ext --inplace + $(PYTHON) setup.py build_ext --inplace api.cpp api.py: src/*.py include/llvm_binding/*.h - python gen.py api src $(PYMODS) + $(PYTHON) gen.py api src $(PYMODS) clean: cleantemp rm -f _api.so _capsule.so @@ -18,6 +18,6 @@ cleantemp: check: _api.so api.py - python test2.py + $(PYTHON) test2.py @PHONY: all clean check From f95b691b61520f8f0d6a7be12ca112ab8bf6e841 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 22 Jan 2013 15:35:05 -0600 Subject: [PATCH 11/85] Expand Module binding --- newbinding/src/Module.py | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/newbinding/src/Module.py b/newbinding/src/Module.py index a458401..5923859 100644 --- a/newbinding/src/Module.py +++ b/newbinding/src/Module.py @@ -5,21 +5,42 @@ from StringRef import StringRef from raw_ostream import raw_svector_ostream_helper from AssemblyAnnotationWriter import AssemblyAnnotationWriter +# class Module Module = llvm.Class() Module.include.add("llvm/Module.h") +# Enumerators +Endianness = Module.Enum('AnyEndianness', 'LittleEndian', 'BigEndian') +PointerSize = Module.Enum('AnyPointerSize', 'Pointer32', 'Pointer64') + +# Constructors & Destructors new = Module.new(StringRef.From(str), LLVMContext.Ref) delete = Module.delete() + +# Module Level Accessor getModuleIdentifier = Module.method(ConstStdString.To(str)) +getDataLayout = Module.method(ConstStdString.To(str)) +getTargetTriple = Module.method(ConstStdString.To(str)) +getEndianness = Module.method(Endianness) +getPointerSize = Module.method(PointerSize) +getContext = Module.method(LLVMContext.Ref) +getModuleInlineAsm = Module.method(ConstStdString.To(str)) + +# Module Level Mutators setModuleIdentifier = Module.method(Void, StringRef.From(str)) setDataLayout = Module.method(Void, StringRef.From(str)) setTargetTriple = Module.method(Void, StringRef.From(str)) setModuleInlineAsm = Module.method(Void, StringRef.From(str)) appendModuleInlineAsm = Module.method(Void, StringRef.From(str)) -getContext = Module.method(LLVMContext.Ref) + +# Function Accessors +#getOrInsertFunction = Module.method(Constant, StringRef.From(str), FunctionType.Pointer) + + + +# Utilities dump = Module.method(Void) print_ = Module.method(Void, raw_svector_ostream_helper.Ref, AssemblyAnnotationWriter.Pointer) print_.realname = 'print' -#getOrInsertFunction = Module.method(Constant, StringRef.From(str), FunctionType.Pointer) - +dropAllReferences = Module.method(Void) From ce103975b853d5fc53246153f617a392a6a79a8d Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 22 Jan 2013 15:40:44 -0600 Subject: [PATCH 12/85] Clean up test --- newbinding/test2.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/newbinding/test2.py b/newbinding/test2.py index 872dfc0..0d64716 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -2,17 +2,6 @@ import api #api.capsule.set_debug(True) context = api.getGlobalContext() -def test(): - print '*' * 80 - 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() From 6b88ffbaed4757f95814aa650c7297bd8e6d8f6a Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 22 Jan 2013 21:23:20 -0600 Subject: [PATCH 13/85] Add custom binding to SmallVector --- newbinding/Makefile | 4 +++- newbinding/binding.py | 10 ++++++++++ newbinding/include/llvm_binding/extra.h | 24 +++++++++++++++++++++++- newbinding/src/DerivedTypes.py | 11 +++++++---- newbinding/test2.py | 10 ++++++++-- 5 files changed, 51 insertions(+), 8 deletions(-) diff --git a/newbinding/Makefile b/newbinding/Makefile index 3996d8b..6ae50be 100644 --- a/newbinding/Makefile +++ b/newbinding/Makefile @@ -1,5 +1,7 @@ PYTHON = python -PYMODS = raw_ostream Type DerivedTypes LLVMContext StringRef AssemblyAnnotationWriter Module + +PYMODS = raw_ostream SmallVector Type DerivedTypes StringRef +PYMODS += LLVMContext AssemblyAnnotationWriter Module all: _api.so _capsule.so diff --git a/newbinding/binding.py b/newbinding/binding.py index de68b55..adeb284 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -190,6 +190,16 @@ Bool = BuiltinType('bool') Unsigned = BuiltinType('unsigned') ConstStdString = BuiltinType('const std::string') +class PyObjectImpl(object): + name = 'PyObject*' + fullname = name + format = 'O' + + def unwrap(self, println, var): + return var + +PyObject = PyObjectImpl() + class Unwrapper(object): def __init__(self, cls, pytype): self.cls = cls diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index a7388a2..e78f0e2 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -4,6 +4,8 @@ namespace llvm{ +class Type; //forward declaration + class raw_svector_ostream_helper: public raw_svector_ostream { SmallVectorImpl *SV; public: @@ -30,5 +32,25 @@ private: void operator = (const raw_svector_ostream_helper&); }; -} + +class SmallVector_Type : public SmallVector { +public: + static + SmallVector_Type* fromPySequence(PyObject* obj) { + SmallVector_Type* SV = new SmallVector_Type; + Py_ssize_t sz = PySequence_Size(obj); + for (Py_ssize_t i = 0; i < sz; ++i) { + PyObject* item = PySequence_GetItem(obj, i); + PyObject* cap = PyObject_GetAttrString(item, "_ptr"); + Type* type = (Type*)PyCapsule_GetPointer(cap, "llvm::Type"); + SV->push_back(type); + Py_XDECREF(cap); + Py_XDECREF(item); + } + return SV; + } +}; + + +} // end namespace llvm diff --git a/newbinding/src/DerivedTypes.py b/newbinding/src/DerivedTypes.py index edf4297..d9dbb53 100644 --- a/newbinding/src/DerivedTypes.py +++ b/newbinding/src/DerivedTypes.py @@ -2,14 +2,17 @@ from binding import * from namespace import llvm from LLVMContext import LLVMContext from Type import Type +from SmallVector import SmallVector_Type FunctionType = Type.Subclass() FunctionType.include.add('llvm/DerivedTypes.h') -get = FunctionType.staticmultimethod([FunctionType.Pointer, - Type.Pointer, Bool.From(bool)],) -# (FunctionType.Pointer, -# Type.Pointer, )]) +_get_signatures = [(FunctionType.Pointer, + Type.Pointer, Bool.From(bool)), + (FunctionType.Pointer, + Type.Pointer, SmallVector_Type.Ref, Bool.From(bool))] + +get = FunctionType.staticmultimethod(*_get_signatures) isVarArg = FunctionType.method(Bool.To(bool)) getReturnType = FunctionType.method(Type.Pointer) diff --git a/newbinding/test2.py b/newbinding/test2.py index 0d64716..6cb8a06 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -1,5 +1,5 @@ import api -#api.capsule.set_debug(True) +api.capsule.set_debug(True) context = api.getGlobalContext() @@ -14,7 +14,6 @@ assert m.getPointerSize() == api.Module.PointerSize.AnyPointerSize m.dump() - os = api.raw_svector_ostream_helper.create() m.print_(os, None) print os.str() @@ -26,6 +25,13 @@ int1ty.dump() print int1ty.isIntegerTy(1) fnty = api.FunctionType.get(int1ty, False) +fnty.dump() +print + +types = [int1ty, api.Type.getIntNTy(context, 21)] +sv = api.SmallVector_Type.fromPySequence(types) + +fnty = api.FunctionType.get(int1ty, sv, False) os2 = api.raw_svector_ostream_helper.create() fnty.print_(os2) From 6afab6268cca2ff0bdd3c689a22e98dfc1395cb9 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 22 Jan 2013 21:24:14 -0600 Subject: [PATCH 14/85] Refactor mangle --- newbinding/binding.py | 17 +++++++++++++++-- newbinding/capsule.py | 2 +- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/newbinding/binding.py b/newbinding/binding.py index adeb284..57d7c7d 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -1,4 +1,5 @@ import logging +import re from utils import * logger = logging.getLogger(__name__) @@ -41,9 +42,21 @@ def parse_arguments(println, var, *args): return unwrapped +_re_mangle_pattern = re.compile(r'[ _<>\*&]') + def mangle(name): - name = name.replace('_', '__').replace(' ', '_') - return name.replace('::', '_').rstrip('*&') + def repl(m): + s = m.group(0) + if s in '<>*&': + return '' + elif s in ' ': + return '_' + elif s in '_': + return '__' + else: + assert False + name = _re_mangle_pattern.sub(repl, name) + return name.replace('::', '_') def pycapsule_new(println, ptr, name, clsname, dtor=NULL): # build capsule diff --git a/newbinding/capsule.py b/newbinding/capsule.py index 509b4c4..e4cd4fa 100644 --- a/newbinding/capsule.py +++ b/newbinding/capsule.py @@ -36,7 +36,7 @@ def _capsule_destructor(weak): cap = weak.capsule addr = _capsule.getPointer(cap) cls = _capsule.getClassName(cap) - logger.debug("destroy pointer %s to %s", addr, cls) + logger.debug("destroy pointer 0x%08X to %s", addr, cls) weak.dtor(cap) del _owners[addr] From ef4c0d3be395a3c756d414667b4f07ec4a3a48e1 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 23 Jan 2013 11:18:06 -0600 Subject: [PATCH 15/85] Rename extra.h to llvm_extra.h --- newbinding/gen.py | 10 +++++----- .../include/llvm_binding/{extra.h => llvm_extra.h} | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) rename newbinding/include/llvm_binding/{extra.h => llvm_extra.h} (98%) diff --git a/newbinding/gen.py b/newbinding/gen.py index 4081f01..bfde891 100644 --- a/newbinding/gen.py +++ b/newbinding/gen.py @@ -186,11 +186,11 @@ class Context(object): def populate_headers(println): includes = [ - 'llvm_binding/conversion.h', - 'llvm_binding/binding.h', - 'llvm_binding/extra.h', - 'llvm_binding/capsule_context.h', - ] + 'llvm_binding/conversion.h', + 'llvm_binding/binding.h', + 'llvm_binding/llvm_extra.h', + 'llvm_binding/capsule_context.h', + ] for inc in includes: println('#include "%s"' % inc) diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/llvm_extra.h similarity index 98% rename from newbinding/include/llvm_binding/extra.h rename to newbinding/include/llvm_binding/llvm_extra.h index e78f0e2..620c3e2 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/llvm_extra.h @@ -2,10 +2,10 @@ #include #include -namespace llvm{ +namespace llvm{ class Type; //forward declaration - + class raw_svector_ostream_helper: public raw_svector_ostream { SmallVectorImpl *SV; public: @@ -51,6 +51,6 @@ public: } }; - + } // end namespace llvm From 6a861d82e6a46fca38565946dac1e604c8bcd093 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 23 Jan 2013 14:50:17 -0600 Subject: [PATCH 16/85] Implement SmallVector_Type, pycapsule_new --- newbinding/binding.py | 14 ++--------- newbinding/gen.py | 21 ++++++++++++++++- newbinding/include/llvm_binding/binding.h | 9 +++++--- .../include/llvm_binding/capsule_context.h | 22 ++++++++++++++++++ newbinding/include/llvm_binding/extra.h | 23 +++++++++++++++++++ newbinding/include/llvm_binding/llvm_extra.h | 20 +--------------- newbinding/src/SmallVector.py | 5 ++++ newbinding/test2.py | 7 +++--- 8 files changed, 82 insertions(+), 39 deletions(-) create mode 100644 newbinding/include/llvm_binding/extra.h create mode 100644 newbinding/src/SmallVector.py diff --git a/newbinding/binding.py b/newbinding/binding.py index 57d7c7d..c9de593 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -58,23 +58,13 @@ def mangle(name): name = _re_mangle_pattern.sub(repl, name) return name.replace('::', '_') -def pycapsule_new(println, ptr, name, clsname, dtor=NULL): +def pycapsule_new(println, ptr, name, clsname): # build capsule name_soften = mangle(name) var = new_symbol('pycap_%s' % name_soften) - fmt = 'PyObject* %(var)s = PyCapsule_New(%(ptr)s, "%(name)s", %(dtor)s);' + fmt = 'PyObject* %(var)s = pycapsule_new(%(ptr)s, "%(name)s", "%(clsname)s");' println(fmt % locals()) - println('if (!%(var)s) return NULL;' % locals()) - - # build context - fmt = 'new CapsuleContext("%(clsname)s")' - context = declare(println, 'CapsuleContext*', fmt % locals()) - - fmt = 'PyCapsule_SetContext(%(var)s, (void*)%(context)s)' - err = declare(println, 'int', fmt % locals()) - - println('if (%(err)s) return NULL;' % locals()) return var diff --git a/newbinding/gen.py b/newbinding/gen.py index bfde891..d73b29a 100644 --- a/newbinding/gen.py +++ b/newbinding/gen.py @@ -81,7 +81,8 @@ class Context(object): for name, cls in self.classes.items(): table = cls.mangled_name println('{ "%(name)s", %(table)s },' % locals()) - println('{ NULL },') + println('{ "extra", extra_methodtable },') + println('{ NULL }') println('};') println('') @@ -92,6 +93,23 @@ class Context(object): def generate_py(self, println): println('import _api, capsule') println('') + # wraps all extras + extra_wrapper = ''' +def _init_extra_wrapper(): + def wrap(callee): + def _wrapped(*args): + args = map(capsule.unwrap, args) + ret = callee(*args) + return capsule.wrap(ret) + return _wrapped + for k in dir(_api.extra): + v = getattr(_api.extra, k) + if not k.startswith('__') and callable(v): + globals()[k] = wrap(v) +_init_extra_wrapper() + ''' + println(extra_wrapper) + println('') # global function for name in self.functions: println('def %(name)s(*args):' % locals()) @@ -190,6 +208,7 @@ def populate_headers(println): 'llvm_binding/binding.h', 'llvm_binding/llvm_extra.h', 'llvm_binding/capsule_context.h', + 'llvm_binding/extra.h', # extra submodule to add ] for inc in includes: println('#include "%s"' % inc) diff --git a/newbinding/include/llvm_binding/binding.h b/newbinding/include/llvm_binding/binding.h index f7bfde6..58a8ad0 100644 --- a/newbinding/include/llvm_binding/binding.h +++ b/newbinding/include/llvm_binding/binding.h @@ -51,10 +51,12 @@ create_python_submodule(PyObject* parent, const char* name, strcpy(fullname + len_parent + 1, name); PyObject* submod = create_python_module(fullname, methtable); delete [] fullname; - if (!submod) + if (!submod){ return NULL; - if( -1 == PyModule_AddObject(parent, name, submod) ) + } + if (-1 == PyModule_AddObject(parent, name, submod)) { return NULL; + } return submod; } @@ -70,4 +72,5 @@ int populate_submodules(PyObject* parent, SubModuleEntry* entries){ return 0; } return 1; -} \ No newline at end of file +} + diff --git a/newbinding/include/llvm_binding/capsule_context.h b/newbinding/include/llvm_binding/capsule_context.h index dacfc89..a4070dc 100644 --- a/newbinding/include/llvm_binding/capsule_context.h +++ b/newbinding/include/llvm_binding/capsule_context.h @@ -15,5 +15,27 @@ struct CapsuleContext { }; +static +PyObject* pycapsule_new(void* ptr, + const char* basename, + const char* classname=NULL) +{ + if (!classname) { + classname = basename; + } + PyObject* cap = PyCapsule_New(ptr, basename, NULL); + if (!cap) { + PyErr_SetString(PyExc_TypeError, "Error creating new PyCapsule"); + return NULL; + } + CapsuleContext* context = new CapsuleContext(classname); + if (PyCapsule_SetContext(cap, context)) { + return NULL; + } + return cap; +} + + + #endif //LLVMPY_CAPSULE_CONTEXT_H_ diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h new file mode 100644 index 0000000..23548ff --- /dev/null +++ b/newbinding/include/llvm_binding/extra.h @@ -0,0 +1,23 @@ +#include +#include + +static +PyObject* small_vector_from_types(PyObject* self, PyObject* args) { + using llvm::Type; + using llvm::SmallVector_Type; + SmallVector_Type* SV = new SmallVector_Type; + Py_ssize_t size = PyTuple_Size(args); + for (Py_ssize_t i = 0; i < size; ++i) { + PyObject* cap = PyTuple_GetItem(args, i); + Type* type = (Type*)PyCapsule_GetPointer(cap, "llvm::Type"); + SV->push_back(type); + } + return pycapsule_new(SV, "llvm::SmallVector_Type"); +} + +static PyMethodDef extra_methodtable[] = { +#define method(func) { #func, (PyCFunction)func, METH_VARARGS, NULL } +method( small_vector_from_types ), +{ NULL } +#undef method +}; diff --git a/newbinding/include/llvm_binding/llvm_extra.h b/newbinding/include/llvm_binding/llvm_extra.h index 620c3e2..f920a47 100644 --- a/newbinding/include/llvm_binding/llvm_extra.h +++ b/newbinding/include/llvm_binding/llvm_extra.h @@ -32,25 +32,7 @@ private: void operator = (const raw_svector_ostream_helper&); }; +typedef SmallVector SmallVector_Type; -class SmallVector_Type : public SmallVector { -public: - static - SmallVector_Type* fromPySequence(PyObject* obj) { - SmallVector_Type* SV = new SmallVector_Type; - Py_ssize_t sz = PySequence_Size(obj); - for (Py_ssize_t i = 0; i < sz; ++i) { - PyObject* item = PySequence_GetItem(obj, i); - PyObject* cap = PyObject_GetAttrString(item, "_ptr"); - Type* type = (Type*)PyCapsule_GetPointer(cap, "llvm::Type"); - SV->push_back(type); - Py_XDECREF(cap); - Py_XDECREF(item); - } - return SV; - } -}; - - } // end namespace llvm diff --git a/newbinding/src/SmallVector.py b/newbinding/src/SmallVector.py new file mode 100644 index 0000000..225c720 --- /dev/null +++ b/newbinding/src/SmallVector.py @@ -0,0 +1,5 @@ +from binding import * +from namespace import llvm + +SmallVector_Type = llvm.Class() +delete = SmallVector_Type.delete() diff --git a/newbinding/test2.py b/newbinding/test2.py index 6cb8a06..6f087c2 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -1,4 +1,5 @@ import api +import _capsule api.capsule.set_debug(True) context = api.getGlobalContext() @@ -26,12 +27,10 @@ print int1ty.isIntegerTy(1) fnty = api.FunctionType.get(int1ty, False) fnty.dump() -print types = [int1ty, api.Type.getIntNTy(context, 21)] -sv = api.SmallVector_Type.fromPySequence(types) - -fnty = api.FunctionType.get(int1ty, sv, False) +svt = api.small_vector_from_types(*types) +fnty = api.FunctionType.get(int1ty, svt, False) os2 = api.raw_svector_ostream_helper.create() fnty.print_(os2) From e9be14ca0e18fbe8fe4b79af20288db8f9dcad4f Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 23 Jan 2013 15:24:37 -0600 Subject: [PATCH 17/85] Refactor raw_svector_stream_helper --- newbinding/include/llvm_binding/extra.h | 26 +++++++++++++++++++++++-- newbinding/src/Module.py | 11 +++++------ newbinding/src/Type.py | 4 ++-- newbinding/src/raw_ostream.py | 9 ++------- newbinding/test2.py | 14 ++++++++----- 5 files changed, 42 insertions(+), 22 deletions(-) diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index 23548ff..417c0f8 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -1,15 +1,36 @@ #include #include +#include static -PyObject* small_vector_from_types(PyObject* self, PyObject* args) { +PyObject* make_raw_ostream_for_printing(PyObject* self, PyObject* args) { + using llvm::raw_svector_ostream_helper; + using llvm::raw_svector_ostream; + + if (!PyArg_ParseTuple(args, "")) { + return NULL; + } + raw_svector_ostream* RSOH = raw_svector_ostream_helper::create(); + return pycapsule_new(RSOH, "llvm::raw_ostream", + "llvm::raw_svector_ostream"); +} + +static +PyObject* make_small_vector_from_types(PyObject* self, PyObject* args) { using llvm::Type; using llvm::SmallVector_Type; + SmallVector_Type* SV = new SmallVector_Type; Py_ssize_t size = PyTuple_Size(args); for (Py_ssize_t i = 0; i < size; ++i) { PyObject* cap = PyTuple_GetItem(args, i); + if (!cap) { + return NULL; + } Type* type = (Type*)PyCapsule_GetPointer(cap, "llvm::Type"); + if (!type) { + return NULL; + } SV->push_back(type); } return pycapsule_new(SV, "llvm::SmallVector_Type"); @@ -17,7 +38,8 @@ PyObject* small_vector_from_types(PyObject* self, PyObject* args) { static PyMethodDef extra_methodtable[] = { #define method(func) { #func, (PyCFunction)func, METH_VARARGS, NULL } -method( small_vector_from_types ), +method( make_raw_ostream_for_printing ), +method( make_small_vector_from_types ), { NULL } #undef method }; diff --git a/newbinding/src/Module.py b/newbinding/src/Module.py index 5923859..67ac8b0 100644 --- a/newbinding/src/Module.py +++ b/newbinding/src/Module.py @@ -2,7 +2,9 @@ from binding import * from namespace import llvm from LLVMContext import LLVMContext from StringRef import StringRef -from raw_ostream import raw_svector_ostream_helper +from Constant import Constant +from DerivedTypes import FunctionType +from raw_ostream import raw_ostream from AssemblyAnnotationWriter import AssemblyAnnotationWriter # class Module @@ -34,13 +36,10 @@ setModuleInlineAsm = Module.method(Void, StringRef.From(str)) appendModuleInlineAsm = Module.method(Void, StringRef.From(str)) # Function Accessors -#getOrInsertFunction = Module.method(Constant, StringRef.From(str), FunctionType.Pointer) - - +getOrInsertFunction = Module.method(Constant.Pointer, StringRef.From(str), FunctionType.Pointer) # Utilities dump = Module.method(Void) -print_ = Module.method(Void, raw_svector_ostream_helper.Ref, - AssemblyAnnotationWriter.Pointer) +print_ = Module.method(Void, raw_ostream.Ref, AssemblyAnnotationWriter.Pointer) print_.realname = 'print' dropAllReferences = Module.method(Void) diff --git a/newbinding/src/Type.py b/newbinding/src/Type.py index 19f6d61..3703200 100644 --- a/newbinding/src/Type.py +++ b/newbinding/src/Type.py @@ -1,7 +1,7 @@ from binding import * from namespace import llvm from LLVMContext import LLVMContext -from raw_ostream import raw_svector_ostream_helper +from raw_ostream import raw_ostream Type = llvm.Class() Type.include.add('llvm/Type.h') @@ -13,7 +13,7 @@ PointerType = SequentialType.Subclass() getContext = Type.method(LLVMContext.Ref) dump = Type.method(Void) -print_ = Type.method(Void, raw_svector_ostream_helper.Ref) +print_ = Type.method(Void, raw_ostream.Ref) print_.realname = 'print' def type_checker(): diff --git a/newbinding/src/raw_ostream.py b/newbinding/src/raw_ostream.py index 0275db4..64e8046 100644 --- a/newbinding/src/raw_ostream.py +++ b/newbinding/src/raw_ostream.py @@ -5,13 +5,8 @@ from StringRef import StringRef raw_ostream = llvm.Class() raw_ostream.include.add("llvm/Support/raw_ostream.h") +delete = raw_ostream.delete() raw_svector_ostream = raw_ostream.Subclass() raw_svector_ostream.include.add("llvm/Support/raw_os_ostream.h") - -# extra class to help binding -raw_svector_ostream_helper = raw_svector_ostream.Subclass() -create = raw_svector_ostream_helper.staticmethod( - raw_svector_ostream_helper.Pointer) -delete = raw_svector_ostream_helper.delete() -str = raw_svector_ostream_helper.method(StringRef.To(str)) +str = raw_svector_ostream.method(StringRef.To(str)) diff --git a/newbinding/test2.py b/newbinding/test2.py index 6f087c2..b866f59 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -15,7 +15,7 @@ assert m.getPointerSize() == api.Module.PointerSize.AnyPointerSize m.dump() -os = api.raw_svector_ostream_helper.create() +os = api.make_raw_ostream_for_printing() m.print_(os, None) print os.str() @@ -29,10 +29,14 @@ fnty = api.FunctionType.get(int1ty, False) fnty.dump() types = [int1ty, api.Type.getIntNTy(context, 21)] -svt = api.small_vector_from_types(*types) +svt = api.make_small_vector_from_types(*types) fnty = api.FunctionType.get(int1ty, svt, False) -os2 = api.raw_svector_ostream_helper.create() -fnty.print_(os2) -print os2.str() +os = api.make_raw_ostream_for_printing() +fnty.print_(os) +print os.str() +fn = m.getOrInsertFunction("foo", fnty) +os = api.make_raw_ostream_for_printing() +fn.print_(os, None) +print os.str() From e9e1f5703dd43b850735397bd005173a8ae9831d Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 23 Jan 2013 15:25:04 -0600 Subject: [PATCH 18/85] Add Value, User, Constant --- newbinding/Makefile | 2 ++ newbinding/src/Constant.py | 5 +++++ newbinding/src/User.py | 5 +++++ newbinding/src/Value.py | 8 ++++++++ 4 files changed, 20 insertions(+) create mode 100644 newbinding/src/Constant.py create mode 100644 newbinding/src/User.py create mode 100644 newbinding/src/Value.py diff --git a/newbinding/Makefile b/newbinding/Makefile index 6ae50be..d07bc8f 100644 --- a/newbinding/Makefile +++ b/newbinding/Makefile @@ -1,8 +1,10 @@ PYTHON = python PYMODS = raw_ostream SmallVector Type DerivedTypes StringRef +PYMODS += Value User Constant PYMODS += LLVMContext AssemblyAnnotationWriter Module + all: _api.so _capsule.so _api.so _capsule.so: api.cpp capsule.cpp diff --git a/newbinding/src/Constant.py b/newbinding/src/Constant.py new file mode 100644 index 0000000..24045bb --- /dev/null +++ b/newbinding/src/Constant.py @@ -0,0 +1,5 @@ +from binding import * +from namespace import llvm +from User import User + +Constant = User.Subclass() diff --git a/newbinding/src/User.py b/newbinding/src/User.py new file mode 100644 index 0000000..8753983 --- /dev/null +++ b/newbinding/src/User.py @@ -0,0 +1,5 @@ +from binding import * +from namespace import llvm +from Value import Value + +User = Value.Subclass() diff --git a/newbinding/src/Value.py b/newbinding/src/Value.py new file mode 100644 index 0000000..ec7aa9a --- /dev/null +++ b/newbinding/src/Value.py @@ -0,0 +1,8 @@ +from binding import * +from namespace import llvm +from raw_ostream import raw_ostream +from AssemblyAnnotationWriter import AssemblyAnnotationWriter + +Value = llvm.Class() +print_ = Value.method(Void, raw_ostream.Ref, AssemblyAnnotationWriter.Pointer) +print_.realname = 'print' From c247cf95271de8ca29d89ffcce3b94920e0599d0 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 23 Jan 2013 15:28:46 -0600 Subject: [PATCH 19/85] Update generator script so that order of modules does not matter. --- newbinding/Makefile | 4 ++-- newbinding/gen.py | 11 ++++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/newbinding/Makefile b/newbinding/Makefile index d07bc8f..61227e5 100644 --- a/newbinding/Makefile +++ b/newbinding/Makefile @@ -1,9 +1,9 @@ PYTHON = python PYMODS = raw_ostream SmallVector Type DerivedTypes StringRef -PYMODS += Value User Constant -PYMODS += LLVMContext AssemblyAnnotationWriter Module +PYMODS += LLVMContext AssemblyAnnotationWriter Module +PYMODS += Value User Constant all: _api.so _capsule.so diff --git a/newbinding/gen.py b/newbinding/gen.py index d73b29a..cee71f1 100644 --- a/newbinding/gen.py +++ b/newbinding/gen.py @@ -56,6 +56,7 @@ class Context(object): self.functions = {} self.classes = {} self.definitions = [] + self._pending_symbols = [] def generate_cpp(self, println): for i in self.includes: @@ -168,12 +169,15 @@ _init_extra_wrapper() def add_module(self, module): allsyms = [(k, v) for k, v in vars(module).items() if isinstance(v, Binding)] - symtab = sorted(allsyms, key=lambda x: x[1].rank) - # generate includes - for k, v in symtab: + for k, v in allsyms: self.includes |= v.include + self._pending_symbols.extend(allsyms) + + def materialize(self): + symtab = sorted(self._pending_symbols, key=lambda x: x[1].rank) + # compile everything for k, v in symtab: buf = StringIO() @@ -237,6 +241,7 @@ if __name__ == '__main__': for mod in modules: context.add_module(mod) + context.materialize() with open('%s.cpp' % outputfilename, 'w') as outfile: println = wrap_println(outfile) From a3da74c416579ebdc6bc1f1b72dd68c7811b53e0 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 23 Jan 2013 15:44:19 -0600 Subject: [PATCH 20/85] Expand Value class --- newbinding/src/Value.py | 18 +++++++++++++++++- newbinding/test2.py | 4 ++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/newbinding/src/Value.py b/newbinding/src/Value.py index ec7aa9a..062ad43 100644 --- a/newbinding/src/Value.py +++ b/newbinding/src/Value.py @@ -2,7 +2,23 @@ from binding import * from namespace import llvm from raw_ostream import raw_ostream from AssemblyAnnotationWriter import AssemblyAnnotationWriter - +from Type import Type +from LLVMContext import LLVMContext +from StringRef import StringRef +# Value = llvm.Class() + +dump = Value.method(Void) + print_ = Value.method(Void, raw_ostream.Ref, AssemblyAnnotationWriter.Pointer) print_.realname = 'print' + +getType = Value.method(Type.Pointer) +getContext = Value.method(LLVMContext.Ref) + +hasName = Value.method(Bool.To(bool)) +# skip getValueName, setValueName +getName = Value.method(StringRef.To(str)) +setName = Value.method(Void, StringRef.From(str)) + +replaceAllUsesWith = Value.method(Void, Value.Pointer) \ No newline at end of file diff --git a/newbinding/test2.py b/newbinding/test2.py index b866f59..ac74594 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -40,3 +40,7 @@ fn = m.getOrInsertFunction("foo", fnty) os = api.make_raw_ostream_for_printing() fn.print_(os, None) print os.str() +assert fn.hasName() +assert 'foo' == fn.getName() +fn.setName('bar') +assert 'bar' == fn.getName() From eba88b32ba5fb5597e664f8662fd6dcce00f2dc9 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 25 Jan 2013 12:29:31 -0600 Subject: [PATCH 21/85] Major refactoring --- newbinding/Makefile | 9 +- newbinding/binding.py | 924 +++++++----------- newbinding/codegen.py | 279 ++++++ newbinding/extra.py | 20 + newbinding/gen.py | 305 ++---- .../include/llvm_binding/auto_pyobject.h | 38 + newbinding/include/llvm_binding/conversion.h | 5 + newbinding/src/AssemblyAnnotationWriter.py | 5 +- newbinding/src/Constant.py | 4 +- newbinding/src/DerivedTypes.py | 22 +- newbinding/src/LLVMContext.py | 8 +- newbinding/src/Module.py | 60 +- newbinding/src/SmallVector.py | 5 +- newbinding/src/StringRef.py | 5 +- newbinding/src/Type.py | 169 ++-- newbinding/src/User.py | 5 +- newbinding/src/Value.py | 25 +- newbinding/src/__init__.py | 2 + newbinding/src/namespace.py | 1 - newbinding/src/raw_ostream.py | 17 +- newbinding/test2.py | 9 +- newbinding/utils.py | 6 - 22 files changed, 999 insertions(+), 924 deletions(-) create mode 100644 newbinding/codegen.py create mode 100644 newbinding/extra.py create mode 100644 newbinding/include/llvm_binding/auto_pyobject.h delete mode 100644 newbinding/utils.py diff --git a/newbinding/Makefile b/newbinding/Makefile index 61227e5..735d4ff 100644 --- a/newbinding/Makefile +++ b/newbinding/Makefile @@ -1,17 +1,12 @@ PYTHON = python -PYMODS = raw_ostream SmallVector Type DerivedTypes StringRef - -PYMODS += LLVMContext AssemblyAnnotationWriter Module -PYMODS += Value User Constant - all: _api.so _capsule.so _api.so _capsule.so: api.cpp capsule.cpp $(PYTHON) setup.py build_ext --inplace -api.cpp api.py: src/*.py include/llvm_binding/*.h - $(PYTHON) gen.py api src $(PYMODS) +api.cpp api.py: src/*.py include/llvm_binding/*.h gen.py binding.py + $(PYTHON) gen.py api src clean: cleantemp rm -f _api.so _capsule.so diff --git a/newbinding/binding.py b/newbinding/binding.py index c9de593..fc26d92 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -1,108 +1,352 @@ -import logging -import re -from utils import * +import functools +import codegen as cg -logger = logging.getLogger(__name__) +_rank = 0 +namespaces = {} -_py2capi_fmtmap = { - str: 's#', -} +class Namespace(object): + def __init__(self, name): + self.name = name + self.classes = [] + self.functions = [] + namespaces[name] = self -NULL = 'NULL' + def Class(self, *bases): + cls = Class(self, *bases) + self.classes.append(cls) + return cls -_symbols = set() + def Function(self, *args): + fn = Function(self, *args) + self.functions.append(fn) + return fn -def new_symbol(name): - if name in _symbols: - ct = 1 - orig = name - while name in _symbols: - name = '%s%d' % (orig, ct) - ct += 1 - _symbols.add(name) - return name + @property + def fullname(self): + return self.name -def parse_arguments(println, var, *args): - typecodes = [] - holders = [] - argvals = [] - for arg in args: - typecodes.append(arg.format) - val = declare(println, 'PyObject*') - argvals.append(val) - holders.append('&' + val) + def __str__(self): + return self.name - items = [var, '"%s"' % (''.join(typecodes))] + holders - println('if(!PyArg_ParseTuple(%s)) return NULL;' % ', '.join(items)) +class Type(object): + pass - # unwrap - unwrapped = [] - for arg, val in zip(args, argvals): - unwrapped.append(arg.unwrap(println, val)) +class BuiltinTypes(Type): + def __init__(self, name): + self.name = name - return unwrapped + @property + def fullname(self): + return self.name -_re_mangle_pattern = re.compile(r'[ _<>\*&]') + def wrap(self, writer, var): + return var -def mangle(name): - def repl(m): - s = m.group(0) - if s in '<>*&': - return '' - elif s in ' ': - return '_' - elif s in '_': - return '__' +Void = BuiltinTypes('void') +Unsigned = BuiltinTypes('unsigned') +Bool = BuiltinTypes('bool') +ConstStdString = BuiltinTypes('const std::string') + +class Class(Type): + format = 'O' + + def __init__(self, ns, *bases): + self.ns = ns + self.bases = bases + self._is_defined = False + self.methods = [] + self.enums = [] + self.includes = set() + + def __call__(self, defn): + assert not self._is_defined + self.name = defn.__name__ + for k, v in defn.__dict__.items(): + if isinstance(v, Method): + self.methods.append(v) + if isinstance(v, Constructor): + for sig in v.signatures: + sig[0] = ptr(self) + v.name = k + v.parent = self + elif isinstance(v, Enum): + self.enums.append(v) + v.name = k + v.parent = self + elif k == '_include_': + if isinstance(v, str): + self.includes.add(v) + else: + for i in v: + self.includes.add(i) + return self + + def compile_cpp(self, writer): + # generate methods + for meth in self.methods: + meth.compile_cpp(writer) + + # generate method table + writer.println('static') + writer.println('PyMethodDef %s[] = {' % cg.mangle(self.fullname)) + with writer.indent(): + fmt = '{ "%(name)s", (PyCFunction)%(func)s, METH_VARARGS, NULL },' + for meth in self.methods: + name = meth.name + func = cg.mangle(meth.fullname) + writer.println(fmt % locals()) + writer.println('{ NULL },') + writer.println('};') + writer.println() + + def compile_py(self, writer): + clsname = self.name + bases = 'capsule.Wrapper' + if self.bases: + bases = ', '.join(x.name for x in self.bases) + writer.println('@capsule.register_class') + with writer.block('class %(clsname)s(%(bases)s):' % locals()): + for enum in self.enums: + enum.compile_py(writer) + for meth in self.methods: + meth.compile_py(writer) + if not self.enums and not self.methods: + writer.println('pass') + writer.println() + + @property + def capsule_name(self): + if self.bases: + return self.bases[-1].capsule_name else: - assert False - name = _re_mangle_pattern.sub(repl, name) - return name.replace('::', '_') + return self.fullname -def pycapsule_new(println, ptr, name, clsname): - # build capsule - name_soften = mangle(name) - var = new_symbol('pycap_%s' % name_soften) - fmt = 'PyObject* %(var)s = pycapsule_new(%(ptr)s, "%(name)s", "%(clsname)s");' - println(fmt % locals()) - println('if (!%(var)s) return NULL;' % locals()) - return var + @property + def fullname(self): + try: + name = self.realname + except AttributeError: + name = self.name + return '::'.join([self.ns.fullname, name]) + + def __str__(self): + return self.fullname + + def unwrap(self, writer, val): + fmt = 'PyCapsule_GetPointer(%(val)s, "%(name)s")' + name = self.capsule_name + raw = writer.declare('void*', fmt % locals()) + writer.die_if_false(raw) + ptrty = ptr(self).fullname + ty = self.fullname + fmt = 'typecast<%(ty)s>::from(%(raw)s)' + casted = writer.declare(ptrty, fmt % locals()) + writer.die_if_false(casted) + return casted -def declare(println, typ, init=None): - typ_soften = mangle(typ) - var = new_symbol('var_%s' % typ_soften) - if init is None: - println('%(typ)s %(var)s;' % locals()) - else: - println('%(typ)s %(var)s = %(init)s;' % locals()) - return var +class Enum(object): + def __init__(self, *value_names): + self.parent = None + self.value_names = value_names + + @property + def fullname(self): + try: + name = self.realname + except AttributeError: + name = self.name + return '::'.join([self.parent.fullname, name]) + + def __str__(self): + return self.fullname + + def wrap(self, writer, val): + ret = writer.declare('PyObject*', 'NULL') + with writer.block('switch(%s) ' % val): + for v in self.value_names: + writer.println('case %s::%s:' % (self.parent, v)) + with writer.indent(): + fmt = '%(ret)s = PyString_FromString("%(v)s");' + writer.println(fmt % locals()) + writer.println('break;') + else: + writer.println('default:') + with writer.indent(): + writer.raises(ValueError, 'Invalid enum %s' % v) + return ret + + def compile_py(self, writer): + with writer.block('class %s:' % self.name): + for v in self.value_names: + writer.println('%(v)s = "%(v)s"' % locals()) + writer.println() + +class Method(object): + _kind_ = 'meth' + + def __init__(self, return_type=Void, *args): + self.parent = None + self.signatures = [] + self.includes = set() + self._add_signature(return_type, *args) + + def _add_signature(self, return_type, *args): + prev_lens = set(map(len, self.signatures)) + cur_len = len(args) + 1 + if cur_len in prev_lens: + raise Exception('Only support overloading with different number' + ' of arguments') + self.signatures.append([return_type] + list(args)) + + def __ior__(self, method): + assert type(self) is type(method) + for sig in method.signatures: + self._add_signature(sig[0], *sig[1:]) + return self + + @property + def fullname(self): + return '::'.join([self.parent.fullname, self.realname]) + + @property + def realname(self): + try: + return self.__realname + except AttributeError: + return self.name + + @realname.setter + def realname(self, v): + self.__realname = v + + def __str__(self): + return self.fullname + + def compile_cpp(self, writer): + with writer.py_function(self.fullname): + if len(self.signatures) == 1: + sig = self.signatures[0] + retty = sig[0] + argtys = sig[1:] + self.compile_cpp_body(writer, retty, argtys) + else: + nargs = writer.declare('Py_ssize_t', 'PyTuple_Size(args)') + for sig in self.signatures: + retty = sig[0] + argtys = sig[1:] + expect = len(argtys) + if (not isinstance(self, StaticMethod) and + isinstance(self.parent, Class)): + # Is a instance method, add 1 for "this". + expect += 1 + with writer.block('if (%(expect)d == %(nargs)s)' % locals()): + self.compile_cpp_body(writer, retty, argtys) + writer.raises(TypeError, 'Invalid number of args') + + def compile_cpp_body(self, writer, retty, argtys): + if isinstance(self.parent, Class): + args = writer.parse_arguments('args', ptr(self.parent), *argtys) + ret = writer.method_call(self.realname, retty.fullname, *args) + else: + args = writer.parse_arguments('args', *argtys) + ret = writer.call(self.fullname, retty.fullname, *args) + writer.return_value(retty.wrap(writer, ret)) + + def compile_py(self, writer): + decl = writer.function(self.name, args=('self',), varargs='args') + with decl as (this, varargs): + unwrap_this = writer.unwrap(this) + unwrapped = writer.unwrap_many(varargs) + func = '.'.join([self.parent.name, self.name]) + ret = writer.call('_api.%s' % func, + args=(unwrap_this,), varargs=unwrapped) + wrapped = writer.wrap(ret) + writer.return_value(wrapped) + writer.println() -def return_value(println, var): - println('return %(var)s;' % locals()) +class StaticMethod(Method): + + def compile_cpp_body(self, writer, retty, argtys): + assert isinstance(self.parent, Class) + args = writer.parse_arguments('args', *argtys) + ret = self.compile_cpp_call(writer, retty, args) + writer.return_value(retty.wrap(writer, ret)) + + def compile_cpp_call(self, writer, retty, args): + ret = writer.call(self.fullname, retty.fullname, *args) + return ret + + def compile_py(self, writer): + writer.println('@staticmethod') + decl = writer.function(self.name, varargs='args') + with decl as varargs: + unwrapped = writer.unwrap_many(varargs) + func = '.'.join([self.parent.name, self.name]) + ret = writer.call('_api.%s' % func, varargs=unwrapped) + wrapped = writer.wrap(ret) + writer.return_value(wrapped) + writer.println() -def return_none(println): - println('Py_RETURN_NONE;') +class Function(Method): + _kind_ = 'func' + + def __init__(self, parent, name, return_type=Void, *args): + super(Function, self).__init__(return_type, *args) + self.parent = parent + self.name = name + + def compile_py(self, writer): + with writer.function(self.name, varargs='args') as varargs: + unwrapped = writer.unwrap_many(varargs) + func = self.fullname.split('::', 1)[1].replace('::', '.') + ret = writer.call('_api.%s' % func, + varargs=unwrapped) + wrapped = writer.wrap(ret) + writer.return_value(wrapped) + writer.println() -def die_if_null(println, var): - println('if (!%(var)s) return NULL;' % locals()) +class Destructor(Method): + _kind_ = 'dtor' - -class Binding(object): - __rank_global = 0 def __init__(self): - self.rank = Binding.__rank_global - Binding.__rank_global += 1 - self.include = set() + super(Destructor, self).__init__() - def compile(self, name, println): - raise NotImplementedError(type(self)) + def compile_cpp_body(self, writer, retty, argtys): + assert isinstance(self.parent, Class) + assert not argtys + args = writer.parse_arguments('args', ptr(self.parent), *argtys) + writer.println('delete %s;' % args[0]) + writer.return_value(None) -class Ref(object): - def __init__(self, elem): - self.element = elem + def compile_py(self, writer): + func = '.'.join([self.parent.name, self.name]) + writer.println('_delete_ = _api.%s' % func) + + +class Constructor(StaticMethod): + _kind_ = 'ctor' + + def __init__(self, *args): + super(Constructor, self).__init__(Void, *args) + + def compile_cpp_call(self, writer, retty, args): + alloctype = retty.fullname.rstrip(' *') + arglist = ', '.join(args) + stmt = 'new %(alloctype)s(%(arglist)s)' % locals() + ret = writer.declare(retty.fullname, stmt) + return ret + +class ref(Type): + def __init__(self, element): + assert isinstance(element, Class), type(element) + self.element = element + + def __str__(self): + return self.fullname @property def fullname(self): @@ -112,503 +356,79 @@ class Ref(object): def capsule_name(self): return self.element.capsule_name - @property - def pointer(self): - return self.element.pointer - - def as_pointer(self, println, var): - init = '&%s' % (var) - casted = declare(println, self.pointer, init) - return casted - @property def format(self): - return 'O' + return self.element.format - def unwrap(self, println, var): - ptr = self.element.unwrap(println, var) - return declare(println, self.fullname, '*%s' % ptr) + def wrap(self, writer, val): + p = writer.declare(ptr(self.element).fullname, '&%s' % val) + return writer.pycapsule_new(p, self.capsule_name, self.element.fullname) - def wrap(self, println, var): - return self.element.wrap(println, self.as_pointer(println, var)) + def unwrap(self, writer, val): + p = self.element.unwrap(writer, val) + return writer.declare(self.fullname, '*%s' % p) -class Pointer(object): - def __init__(self, elem): - self.element = elem +class ptr(Type): + def __init__(self, element): + assert isinstance(element, Class) + self.element = element @property def fullname(self): - return '%s*' % self.element.fullname - - @property - def capsule_name(self): - return self.element.capsule_name - - @property - def pointer(self): - return self.element.pointer + return '%s*' % self.element @property def format(self): - return 'O' + return self.element.format - def unwrap(self, println, var): - ret = declare(println, self.fullname) - println2 = indent_println(println) - println('if (%(var)s == Py_None) {' % locals()) - println2('%(ret)s = NULL;' % locals()) - println('} else {') - ptr = self.element.unwrap(println2, var) - println2('%(ret)s = %(ptr)s;' % locals()) - println('}') + def unwrap(self, writer, val): + ret = writer.declare(self.fullname, 'NULL') + with writer.block('if (%(val)s != Py_None)' % locals()): + val = self.element.unwrap(writer, val) + writer.println('%(ret)s = %(val)s;' % locals()) return ret - def wrap(self, println, var): - return self.element.wrap(println, var) + def wrap(self, writer, val): + return writer.pycapsule_new(val, self.element.capsule_name, + self.element.fullname) - -class BuiltinType(object): - def __init__(self, name): - self.name = name - self.Ref = Ref(self) - self.Pointer = Pointer(self) - - @property - def fullname(self): - return self.name - - @property - def capsule_name(self): - return self.fullname - - def To(self, pytype): - return Wrapper(self, pytype) - - def From(self, pytype): - return Unwrapper(self, pytype) - -Void = BuiltinType('void') -Bool = BuiltinType('bool') -Unsigned = BuiltinType('unsigned') -ConstStdString = BuiltinType('const std::string') - -class PyObjectImpl(object): - name = 'PyObject*' - fullname = name +class cast(Type): format = 'O' - def unwrap(self, println, var): - return var - -PyObject = PyObjectImpl() - -class Unwrapper(object): - def __init__(self, cls, pytype): - self.cls = cls - self.pytype = pytype + def __init__(self, original, target): + self.original = original + self.target = target @property def fullname(self): - return str(self.pytype) + return self.binding_type.fullname @property - def format(self): - return 'O' - - def unwrap(self, println, var): - out = declare(println, self.cls.fullname) - conv = 'py_%s_to' % (self.pytype.__name__) - status = '%(conv)s(%(var)s, %(out)s)' % locals() - println('if (!%(status)s) return NULL;' % locals()) - return out - - -class Wrapper(object): - def __init__(self, cls, pytype): - self.cls = cls - self.pytype = pytype - - @property - def fullname(self): - return self.cls.fullname - - def wrap(self, println, var): - conv = 'py_%s_from' % (self.pytype.__name__) - func = '%(conv)s(%(var)s)' % locals() - out = declare(println, 'PyObject*', func) - println('if (!%(out)s) return NULL;' % locals()) - return out - -class Enum(Binding): - def __init__(self, ns, *values): - super(Enum, self).__init__() - self.values = values - self.ns = ns - self.name = None - - def compile(self, name, println): - self.name = self.name or name - - @property - def fullname(self): - return '::'.join([self.ns, self.name]) - -class ClassEnum(Enum): - def __init__(self, cls, *values): - super(ClassEnum, self).__init__(None, *values) - self.cls = cls - self.cls.enums.append(self) - - def compile(self, name, println): - self.ns = self.cls.fullname - super(ClassEnum, self).compile(name, println) - - def wrap(self, println, var): - println2 = indent_println(println) - ret = declare(println, 'PyObject*', NULL) - println('switch(%s) { ' % var) - for v in self.values: - println('case %s::%s:' % (self.ns, v)) - println2('%(ret)s = PyString_FromString("%(v)s");' % locals()) - println2('break;') + def python_type(self): + if not isinstance(self.target, Type): + return self.target else: - println('default:') - println2('PyErr_SetString(PyExc_TypeError, "Invalid enum: %s");' % - v) - println2('return NULL;') - println('}') + return self.original + + @property + def binding_type(self): + if isinstance(self.target, Type): + return self.target + else: + return self.original + + def wrap(self, writer, val): + dst = self.python_type.__name__ + return writer.call('py_%(dst)s_from' % locals(), 'PyObject*', val) + + def unwrap(self, writer, val): + src = self.python_type.__name__ + dst = self.binding_type.fullname + ret = writer.declare(dst) + status = writer.call('py_%(src)s_to' % locals(), 'int', val, ret) + writer.die_if_false(status) return ret - def unwrap(self, println, var): - pass -class Class(Binding): - def __init__(self, ns): - super(Class, self).__init__() - self.ctor = None - self.Ref = Ref(self) - self.Pointer = Pointer(self) - self.Subclass = lambda: Subclass(self) - self.Enum = lambda *v: ClassEnum(self, *v) - self.enums = [] - self.ns = ns - self.methods = [] - self.name = None - - def To(self, pytype): - return Wrapper(self, pytype) - - def From(self, pytype): - return Unwrapper(self, pytype) - - def new(self, *args): - method = Constructor(self, self.Pointer, *args) - self.methods.append(method) - return method - - def delete(self): - method = Destructor(self, Void, self.Pointer) - self.methods.append(method) - return method - - def method(self, return_type, *args): - method = Method(self, return_type, self.Pointer, *args) - self.methods.append(method) - return method - - def staticmethod(self, return_type, *args): - sm = StaticMethod(self, return_type, *args) - self.methods.append(sm) - return sm - - def multimethod(self, *signatures): - mm = MultiMethod(self, signatures) - self.methods.append(mm) - return mm - - def staticmultimethod(self, *signatures): - smm = StaticMultiMethod(self, signatures) - self.methods.append(smm) - return smm - - def compile(self, name, println): - # set name - self.name = self.name or name - - @property - def capsule_name(self): - return self.fullname - - @property - def pointer(self): - return '%s*' % self.fullname - - @property - def fullname(self): - return '::'.join([self.ns, self.name]) - - @property - def mangled_name(self): - return mangle(self.fullname) - - @property - def format(self): - return 'O' - - def unwrap(self, println, var): - typ = self.pointer - elty = self.fullname - cap = self.capsule_name - capptr = 'PyCapsule_GetPointer(%(var)s, "%(cap)s")' % locals() - ptr = declare(println, 'void*', capptr) - unwrapped = 'typecast<%(elty)s>::from(%(ptr)s)' % locals() - var = declare(println, typ, unwrapped) - println('if (!%(var)s) {' % locals()) - println2 = indent_println(println) - println2('PyErr_SetString(PyExc_TypeError, "Invalid cast");') - println2('return NULL;') - println('}') - die_if_null(println, var) - return var - - def wrap(self, println, var): - return pycapsule_new(println, var, self.capsule_name, self.fullname) - -class Subclass(Class): - def __init__(self, parent): - super(Subclass, self).__init__(parent.ns) - self.parent = parent - self.ns = self.parent.ns - - @property - def capsule_name(self): - return self.parent.capsule_name - -class Function(Binding): - def __init__(self, ns, return_type, *args): - super(Function, self).__init__() - self.return_type = return_type - self.args = args - self.ns = ns - self.name = None - - def compile(self, name, println): - # set name - self.name = self.name or name - # generate wrapper - println('static') - println('PyObject*') - println('%(name)s(PyObject* self, PyObject* args)' % locals()) - println('{') - self.compile_body(indent_println(println)) - println('}') - - def compile_body(self, println): - args = parse_arguments(println, 'args', *self.args) - call = '%s(%s)' % (self.fullname, ', '.join(args)) - if self.return_type is not Void: - callres = declare(println, self.return_type.fullname, call) - pycap = self.return_type.wrap(println, callres) - return_value(println, pycap) - else: - println('%s;' % call) - return_none(println) - - - @property - def fullname(self): - return '::'.join([self.ns, self.name]) - -class Method(Binding): - def __init__(self, cls, return_type, *args): - super(Method, self).__init__() - self.cls = cls - self.return_type = return_type - self.args = args - self.name = None - self._realname = None - - def compile(self, name, println): - # set name - self.name = self.name or name - # generate wrapper - println('static') - println('PyObject*') - mangled = self.mangled_name - println('%(mangled)s(PyObject* self, PyObject* args)' % locals()) - println('{') - self.compile_body(indent_println(println)) - println('}') - - def compile_body(self, println): - args = parse_arguments(println, 'args', *self.args) - this = args[0] - args = ', '.join(args[1:]) - name = self.realname - call = '%(this)s->%(name)s(%(args)s)' % locals() - if self.return_type is not Void: - obj = declare(println, self.return_type.fullname, call) - ret = self.return_type.wrap(println, obj) - return_value(println, ret) - else: - println('%s;' % call) - return_none(println) - - @property - def fullname(self): - return '::'.join([self.cls.fullname, self.name]) - - @property - def realname(self): - if not self._realname: - return self.name - else: - return self._realname - - @realname.setter - def realname(self, v): - self._realname = v - - - @property - def mangled_name(self): - return mangle(self.fullname) - -class MultiMethod(Binding): - '''Can only differs by the number of arguments. - ''' - def __init__(self, cls, signatures): - super(MultiMethod, self).__init__() - nargs = set() - for sig in signatures: - n = len(sig) - if n in nargs: - raise TypeError("MultiMethod only supports overloaded version" - "with different number of arguments") - nargs.add(n) - self.cls = cls - self.signatures = signatures - self.name = None - - def compile(self, name, println): - # set name - self.name = self.name or name - # generate wrapper - println('static') - println('PyObject*') - mangled = self.mangled_name - println('%(mangled)s(PyObject* self, PyObject* args)' % locals()) - println('{') - println2 = indent_println(println) - nargs = declare(println2, 'Py_ssize_t', 'PyTuple_Size(args)') - for sig in self.signatures: - expect = len(sig) - println2('if (%(nargs)s == %(expect)d) {' % locals()) - method = Method(self.cls, sig[0], self.cls.Pointer, *sig[1:]) - method.name = self.name - method.compile_body(indent_println(println2)) - println2('}') - println2('PyErr_SetString(PyExc_TypeError, "Wrong # of args");') - println2('return NULL;') - println('}') - - @property - def fullname(self): - return '::'.join([self.cls.fullname, self.name]) - - @property - def mangled_name(self): - return mangle(self.fullname) - -class StaticMethod(Method): - def compile_body(self, println): - args = parse_arguments(println, 'args', *self.args) - args = ', '.join(args) - fullname = self.fullname - call = '%(fullname)s(%(args)s)' % locals() - if self.return_type is not Void: - obj = declare(println, self.return_type.fullname, call) - ret = self.return_type.wrap(println, obj) - return_value(println, ret) - else: - println('%s;' % call) - return_none(println) - -class StaticMultiMethod(Binding): - '''Can only differs by the number of arguments. - ''' - def __init__(self, cls, signatures): - super(StaticMultiMethod, self).__init__() - nargs = set() - for sig in signatures: - n = len(sig) - if n in nargs: - raise TypeError("StaticMultiMethod only supports overloaded " - "version with different number of arguments") - nargs.add(n) - self.cls = cls - self.signatures = signatures - self.name = None - - - def compile(self, name, println): - # set name - self.name = self.name or name - # generate wrapper - println('static') - println('PyObject*') - mangled = self.mangled_name - println('%(mangled)s(PyObject* self, PyObject* args)' % locals()) - println('{') - println2 = indent_println(println) - nargs = declare(println2, 'Py_ssize_t', 'PyTuple_Size(args)') - for sig in self.signatures: - expect = len(sig) - 1 - println2('if (%(nargs)s == %(expect)d) {' % locals()) - method = StaticMethod(self.cls, sig[0], *sig[1:]) - method.name = self.name - method.compile_body(indent_println(println2)) - println2('}') - println2('PyErr_SetString(PyExc_TypeError, "Wrong # of args");') - println2('return NULL;') - println('}') - - @property - def fullname(self): - return '::'.join([self.cls.fullname, self.name]) - - @property - def mangled_name(self): - return mangle(self.fullname) - -class Constructor(StaticMethod): - def compile_body(self, println): - args = parse_arguments(println, 'args', *self.args) - args = ', '.join(args) - name = self.cls.fullname - ctor = 'new %(name)s(%(args)s)' % locals() - obj = declare(println, self.cls.pointer, ctor) - ret = self.return_type.wrap(println, obj) - return_value(println, ret) - -class Destructor(Method): - def compile_body(self, println): - args = parse_arguments(println, 'args', *self.args) - assert len(args) == 1 - dtor = 'delete %s;' % args[0] - println(dtor) - return_none(println) - - -class Namespace(object): - def __init__(self, name): - self.name = name - - def Class(self, *args, **kwargs): - return Class(self.name, *args, **kwargs) - - def Function(self, *args, **kwargs): - return Function(self.name, *args, **kwargs) - diff --git a/newbinding/codegen.py b/newbinding/codegen.py new file mode 100644 index 0000000..9398b14 --- /dev/null +++ b/newbinding/codegen.py @@ -0,0 +1,279 @@ +import re, contextlib + +NULL = 'NULL' + +_symbols = set() + +def indent(println): + def _println(s=''): + println("%s%s" % (' '* 4, s)) + return _println + +def quote(txt): + return '"%s"' % txt + +def new_symbol(name): + if name in _symbols: + ct = 1 + orig = name + while name in _symbols: + name = '%s%d' % (orig, ct) + ct += 1 + _symbols.add(name) + return name + +def parse_arguments(println, var, *args): + typecodes = [] + holders = [] + argvals = [] + for arg in args: + typecodes.append(arg.format) + val = declare(println, 'PyObject*') + argvals.append(val) + holders.append('&' + val) + + items = [var, '"%s"' % (''.join(typecodes))] + holders + println('if(!PyArg_ParseTuple(%s)) return NULL;' % ', '.join(items)) + + # unwrap + unwrapped = [] + for arg, val in zip(args, argvals): + unwrapped.append(arg.unwrap(println, val)) + + return unwrapped + +_re_mangle_pattern = re.compile(r'[ _<>\*&]') + +def mangle(name): + def repl(m): + s = m.group(0) + if s in '<>*&': + return '' + elif s in ' ': + return '_' + elif s in '_': + return '__' + else: + assert False + name = _re_mangle_pattern.sub(repl, name) + return name.replace('::', '_') + +def pycapsule_new(println, ptr, name, clsname): + # build capsule + name_soften = mangle(name) + var = new_symbol('pycap_%s' % name_soften) + fmt = 'PyObject* %(var)s = pycapsule_new(%(ptr)s, "%(name)s", "%(clsname)s");' + println(fmt % locals()) + println('if (!%(var)s) return NULL;' % locals()) + return var + + +def declare(println, typ, init=None): + typ_soften = mangle(typ) + var = new_symbol('var_%s' % typ_soften) + if init is None: + println('%(typ)s %(var)s;' % locals()) + else: + println('%(typ)s %(var)s = %(init)s;' % locals()) + return var + + +def return_value(println, var): + println('return %(var)s;' % locals()) + + +def return_none(println): + println('Py_RETURN_NONE;') + + +def die_if_null(println, var): + println('if (!%(var)s) return NULL;' % locals()) + + +class CodeWriterBase(object): + def __init__(self, println): + self.println = println + self.used_symbols = set() + + @contextlib.contextmanager + def indent(self): + old = self.println + self.println = indent(self.println) + yield + self.println = old + + @contextlib.contextmanager + def py_function(self, name): + mangled = mangle(name) + self.println('static') + self.println('PyObject*') + with self.block('%(mangled)s(PyObject* self, PyObject* args)' % locals()): + self.used_symbols.add('self') + self.used_symbols.add('args') + yield + self.println() + + def new_symbol(self, name): + if name in self.used_symbols: + ct = 1 + orig = name + while name in self.used_symbols: + name = '%s%d' % (orig, ct) + ct += 1 + self.used_symbols.add(name) + return name + +class CppCodeWriter(CodeWriterBase): + @contextlib.contextmanager + def block(self, lead): + self.println(lead) + self.println('{') + with self.indent(): + yield + self.println('}') + + def declare(self, typ, init=None): + typ_soften = mangle(typ) + var = self.new_symbol('var_%s' % typ_soften) + if init is None: + self.println('%(typ)s %(var)s;' % locals()) + else: + self.println('%(typ)s %(var)s = %(init)s;' % locals()) + return var + + def return_value(self, val): + if val is None: + self.println('Py_RETURN_NONE;') + else: + self.println('return %s;' % val) + + def return_null(self): + self.return_value(NULL) + + def parse_arguments(self, var, *args): + typecodes = [] + holders = [] + argvals = [] + for arg in args: + typecodes.append(arg.format) + val = self.declare('PyObject*') + argvals.append(val) + holders.append('&' + val) + + items = [var, '"%s"' % (''.join(typecodes))] + holders + with self.block('if(!PyArg_ParseTuple(%s))' % ', '.join(items)): + self.return_null() + + # unwrap + unwrapped = [] + for arg, val in zip(args, argvals): + unwrapped.append(arg.unwrap(self, val)) + + return unwrapped + + def call(self, func, retty, *args): + arglist = ', '.join(args) + stmt = '%(func)s(%(arglist)s)' % locals() + if retty == 'void': + self.println(stmt) + else: + return self.declare(retty, stmt) + + def method_call(self, func, retty, *args): + this = args[0] + arglist = ', '.join(args[1:]) + if func == 'delete': + assert not arglist + stmt = 'delete %(this)s;' % locals() + elif func == 'new': + alloctype = retty.rstrip(' *') + stmt = 'new %(alloctype)s(%(arglist)s);' % locals() + else: + stmt = '%(this)s->%(func)s(%(arglist)s);' % locals() + if retty == 'void': + self.println(stmt) + else: + return self.declare(retty, stmt) + + def pycapsule_new(self, ptr, name, clsname): + name_soften = mangle(name) + ret = self.call('pycapsule_new', 'PyObject*', ptr, quote(name), + quote(clsname)) + with self.block('if (!%(ret)s)' % locals()): + self.return_null() + return ret + + def die_if_false(self, val): + with self.block('if(!%(val)s)' % locals()): + self.return_null() + + def raises(self, exccls, msg): + exc = 'PyExc_%s' % exccls.__name__ + self.println('PyErr_SetString(%s, "%s");' % (exc, msg)) + self.return_null() + + +class PyCodeWriter(CodeWriterBase): + @contextlib.contextmanager + def block(self, lead): + self.println(lead) + with self.indent(): + yield + + @contextlib.contextmanager + def function(self, func, args=(), varargs=None): + with self.scope(): + arguments = [] + for arg in args: + arguments.append(self.new_symbol(arg)) + if varargs: + varargs = self.new_symbol(varargs) + arguments.append('*%s' % varargs) + arglist = ', '.join(arguments) + with self.block('def %(func)s(%(arglist)s):' % locals()): + if arguments: + arguments[-1] = arguments[-1].lstrip('*') + if len(arguments) > 1: + yield arguments + else: + yield arguments[0] + else: + yield + + @contextlib.contextmanager + def scope(self): + self.old = self.used_symbols + self.used_symbols = set() + yield + self.used_symbols = self.old + + def unwrap_many(self, args): + unwrapped = self.new_symbol('unwrapped') + self.println('%(unwrapped)s = map(capsule.unwrap, %(args)s)' % locals()) + return unwrapped + + def unwrap(self, val): + return self.call('capsule.unwrap', args=(val,), ret='unwrapped') + + def wrap(self, val): + wrapped = self.new_symbol('wrapped') + self.println('%(wrapped)s = capsule.wrap(%(val)s)' % locals()) + return wrapped + + def call(self, func, args=(), varargs=None, ret='ret'): + arguments = [] + for arg in args: + arguments.append(arg) + if varargs: + arguments.append('*%s' % varargs) + arglist = ', '.join(arguments) + ret = self.new_symbol(ret) + self.println('%(ret)s = %(func)s(%(arglist)s)' % locals()) + return ret + + def return_value(self, val=None): + if val is None: + val = '' + self.println('return %s' % val) + + diff --git a/newbinding/extra.py b/newbinding/extra.py new file mode 100644 index 0000000..1af4e5f --- /dev/null +++ b/newbinding/extra.py @@ -0,0 +1,20 @@ +''' +Wrapped the extra functions in _api.so +''' + +import capsule + +def _wrapper(func): + def _core(*args): + unwrapped = map(capsule.unwrap, args) + ret = func(*unwrapped) + return capsule.wrap(ret) + return _core + +def _init(glob): + from _api import extra + for k, v in extra.__dict__.items(): + glob[k] = _wrapper(v) + +_init(globals()) + diff --git a/newbinding/gen.py b/newbinding/gen.py index cee71f1..4d8709e 100644 --- a/newbinding/gen.py +++ b/newbinding/gen.py @@ -1,26 +1,23 @@ -import sys, logging +import sys from binding import * -from utils import * -from cStringIO import StringIO +import codegen -logging.basicConfig(level=logging.INFO) -logger = logging.getLogger(__name__) extension_entry = ''' - + extern "C" { #if (PY_MAJOR_VERSION >= 3) - + PyObject * PyInit_%(module)s(void) { - PyObject *module = create_python_module("%(module)s", %(methtable)s); - if (module) { - if (populate_submodules(module, submodules)) - return module; - } - return NULL; +PyObject *module = create_python_module("%(module)s", %(methtable)s); +if (module) { +if (populate_submodules(module, submodules)) +return module; +} +return NULL; } #else @@ -28,10 +25,10 @@ PyInit_%(module)s(void) PyMODINIT_FUNC init%(module)s(void) { - PyObject *module = create_python_module("%(module)s", %(methtable)s); - if (module) { - populate_submodules(module, submodules); - } +PyObject *module = create_python_module("%(module)s", %(methtable)s); +if (module) { +populate_submodules(module, submodules); +} } #endif @@ -39,172 +36,6 @@ init%(module)s(void) ''' -def build_methoddef(name, defns, println): - println('static PyMethodDef %s[] = {' % name) - for name, func in defns: - println('{ "%(name)s", (PyCFunction)%(func)s, METH_VARARGS, NULL },' % - locals()) - else: - println('{ NULL }') - println('};') - println('') - - -class Context(object): - def __init__(self): - self.includes = set() - self.functions = {} - self.classes = {} - self.definitions = [] - self._pending_symbols = [] - - def generate_cpp(self, println): - for i in self.includes: - println('#include "%s"' % i) - - println('\n'.join(self.definitions)) - - # global function - defns = [] - for name, func in self.functions.items(): - defns.append((name, func.name)) - build_methoddef('global_functions', defns, println) - - # classes - for name, cls in self.classes.items(): - defns = [] - for meth in cls.methods: - defns.append((meth.name, meth.mangled_name)) - println("// %s" % cls.fullname) - build_methoddef(cls.mangled_name, defns, println) - - println('static SubModuleEntry submodules[] = {') - for name, cls in self.classes.items(): - table = cls.mangled_name - println('{ "%(name)s", %(table)s },' % locals()) - println('{ "extra", extra_methodtable },') - println('{ NULL }') - println('};') - println('') - - # generate entry - println(extension_entry % {'module': '_api', - 'methtable': 'global_functions',}) - - def generate_py(self, println): - println('import _api, capsule') - println('') - # wraps all extras - extra_wrapper = ''' -def _init_extra_wrapper(): - def wrap(callee): - def _wrapped(*args): - args = map(capsule.unwrap, args) - ret = callee(*args) - return capsule.wrap(ret) - return _wrapped - for k in dir(_api.extra): - v = getattr(_api.extra, k) - if not k.startswith('__') and callable(v): - globals()[k] = wrap(v) -_init_extra_wrapper() - ''' - println(extra_wrapper) - println('') - # global function - for name in self.functions: - println('def %(name)s(*args):' % locals()) - println2 = indent_println(println) - println2('args = map(capsule.unwrap, args)') - println2('ptr = _api.%(name)s(*args)' % locals()) - println2('return capsule.wrap(ptr)') - println('') - # classes - classes = sorted(self.classes.items(), key=lambda x: x[1].rank) - - for name, cls in classes: - if isinstance(cls, Subclass): - parent = cls.parent.name - else: - parent = 'capsule.Wrapper' - println('@capsule.register_class') - println('class %(name)s(%(parent)s):' % locals()) - self.generate_py_class(indent_println(println), cls) - println('') - - def generate_py_class(self, println, cls): - if len(cls.methods) == 0: - println('pass') - else: - mod = cls.name - # generate class enums - for enum in cls.enums: - println('class %s:' % enum.name) - println2 = indent_println(println) - for v in enum.values: - println2('%(v)s = "%(v)s"' % locals()) - println('') - # generate class methods - for method in cls.methods: - name = method.name - if(isinstance(method, StaticMethod) or - isinstance(method, StaticMultiMethod)): - println('@staticmethod') - println('def %(name)s(*args):' % locals()) - println2 = indent_println(println) - println2('args = map(capsule.unwrap, args)') - println2('ret = _api.%(mod)s.%(name)s(*args)' % locals()) - println2('return capsule.wrap(ret)') - elif isinstance(method, Destructor): - println('_delete_ = _api.%(mod)s.%(name)s' % locals()) - else: - println('def %(name)s(self, *args):' % locals()) - println2 = indent_println(println) - println2('args = map(capsule.unwrap, args)') - println2('ret = _api.%(mod)s.%(name)s(self._ptr, *args)' % - locals()) - println2('return capsule.wrap(ret)') - println('') - - def add_module(self, module): - allsyms = [(k, v) for k, v in vars(module).items() - if isinstance(v, Binding)] - # generate includes - for k, v in allsyms: - self.includes |= v.include - - self._pending_symbols.extend(allsyms) - - def materialize(self): - symtab = sorted(self._pending_symbols, key=lambda x: x[1].rank) - - # compile everything - for k, v in symtab: - buf = StringIO() - def println_to_def(s): - buf.write(s) - buf.write('\n') - logger.info('compiling %s', k) - v.compile(k, println_to_def) - self.definitions.append(buf.getvalue()) - buf.close() - - # generate py defintion table for global functions - for k, v in symtab: - if isinstance(v, Function): - if v.name in self.functions: - raise NameError("Duplicated function name: %s" % v.name) - self.functions[v.name] = v - - # generate sub module tables for classes - submodules = [] - for k, v in symtab: - if isinstance(v, Class): - if v.name in self.classes: - if v is not self.classes[v.name]: - raise NameError("Duplicated class: %s" % v.name) - self.classes[v.name] = v - def populate_headers(println): includes = [ @@ -216,38 +47,96 @@ def populate_headers(println): ] for inc in includes: println('#include "%s"' % inc) + println() -def wrap_println(f): - def println(s): - f.write(s) - f.write('\n') + +def wrap_println_from_file(file): + def println(s=''): + file.write(s) + file.write('\n') return println -if __name__ == '__main__': +def main(): outputfilename = sys.argv[1] - srcdir = sys.argv[2] - modnames = sys.argv[3:] + entry_modname = sys.argv[2] - modules = [] - for m in modnames: - path = '%s.%s' % (srcdir, m) - logger.info("import module %s", path) - module = __import__(path) - for token in path.split('.')[1:]: - module = getattr(module, token) - modules.append(module) + entry_module = __import__(entry_modname) - context = Context() + units = [] + for ns in namespaces.values(): + print 'namespace', ns + for fn in ns.functions: + print fn + units.append(fn) + for cls in ns.classes: + print cls + units.append(cls) - for mod in modules: - context.add_module(mod) - context.materialize() + with open('%s.cpp' % outputfilename, 'w') as cppfile: + println = wrap_println_from_file(cppfile) - with open('%s.cpp' % outputfilename, 'w') as outfile: - println = wrap_println(outfile) + # extra headers populate_headers(println) - context.generate_cpp(println) - with open('%s.py' % outputfilename, 'w') as outfile: - println = wrap_println(outfile) - context.generate_py(println) + # required headers + includes = set() + for u in units: + includes |= u.includes + + for inc in includes: + println('#include "%s"' % inc) + println() + + # write methods and method tables + for u in units: + writer = codegen.CppCodeWriter(println) + u.compile_cpp(writer) + else: + del writer + + # write function table + writer = codegen.CppCodeWriter(println) + writer.println('static') + writer.println('PyMethodDef methtable[] = {') + with writer.indent(): + fmt = '{ "%(name)s", (PyCFunction)%(func)s, METH_VARARGS, NULL },' + for u in units: + if isinstance(u, Function): + name = u.name + func = codegen.mangle(u.fullname) + writer.println(fmt % locals()) + writer.println('{ NULL },') + writer.println('};') + writer.println() + del writer + + + # write submodule table + writer = codegen.CppCodeWriter(println) + writer.println('static') + writer.println('SubModuleEntry submodules[] = {') + with writer.indent(): + for cls in units: + if isinstance(cls, Class): + name = cls.name + table = codegen.mangle(cls.fullname) + writer.println('{ "%(name)s", %(table)s },' % locals()) + writer.println('{ "extra", extra_methodtable },') + writer.println('{ NULL }') + writer.println('};') + writer.println('') + del writer + + println(extension_entry % {'module': '_api', 'methtable': 'methtable'}) + + with open('%s.py' % outputfilename, 'w') as pyfile: + println = wrap_println_from_file(pyfile) + println('import _api, capsule') + println() + for u in units: + writer = codegen.PyCodeWriter(println) + u.compile_py(writer) + + +if __name__ == '__main__': + main() diff --git a/newbinding/include/llvm_binding/auto_pyobject.h b/newbinding/include/llvm_binding/auto_pyobject.h new file mode 100644 index 0000000..451f2d9 --- /dev/null +++ b/newbinding/include/llvm_binding/auto_pyobject.h @@ -0,0 +1,38 @@ +#ifndef AUTO_PYOBJECT_H_ +#define AUTO_PYOBJECT_H_ + +#include + +class auto_pyobject{ + mutable PyObject* PO; +public: + auto_pyobject(): PO(NULL) { } + + auto_pyobject(PyObject* po) : PO(po) { } + + auto_pyobject(const auto_pyobject& other) : PO(*other){ + other.PO = NULL; + } + + ~auto_pyobject() { + Py_XDECREF(PO); + } + + bool operator ! () const { + return !PO; + } + + PyObject* operator * () const { + return PO; + } + + PyObject* get() const { + return PO; + } +private: + // disable assign + void operator = (const auto_pyobject&); +}; + +#endif AUTO_PYOBJECT_H_ + diff --git a/newbinding/include/llvm_binding/conversion.h b/newbinding/include/llvm_binding/conversion.h index c3d6e36..0e30c60 100644 --- a/newbinding/include/llvm_binding/conversion.h +++ b/newbinding/include/llvm_binding/conversion.h @@ -62,6 +62,11 @@ static PyObject* py_str_from(const std::string &str){ return PyString_FromStringAndSize(str.c_str(), str.size()); } +// +//static +//PyObject* py_str_from(const llvm::StringRef *str){ +// return py_str_from(str->str()); +//} static PyObject* py_bool_from(bool val){ diff --git a/newbinding/src/AssemblyAnnotationWriter.py b/newbinding/src/AssemblyAnnotationWriter.py index 5641232..d2b5a5d 100644 --- a/newbinding/src/AssemblyAnnotationWriter.py +++ b/newbinding/src/AssemblyAnnotationWriter.py @@ -1,6 +1,7 @@ from binding import * from namespace import llvm -AssemblyAnnotationWriter = llvm.Class() -AssemblyAnnotationWriter.include.add("llvm/Assembly/AssemblyAnnotationWriter.h") +@llvm.Class() +class AssemblyAnnotationWriter: + _include_ = "llvm/Assembly/AssemblyAnnotationWriter.h" diff --git a/newbinding/src/Constant.py b/newbinding/src/Constant.py index 24045bb..14ff6bb 100644 --- a/newbinding/src/Constant.py +++ b/newbinding/src/Constant.py @@ -2,4 +2,6 @@ from binding import * from namespace import llvm from User import User -Constant = User.Subclass() +@llvm.Class(User) +class Constant: + pass diff --git a/newbinding/src/DerivedTypes.py b/newbinding/src/DerivedTypes.py index d9dbb53..c57e01b 100644 --- a/newbinding/src/DerivedTypes.py +++ b/newbinding/src/DerivedTypes.py @@ -4,17 +4,15 @@ from LLVMContext import LLVMContext from Type import Type from SmallVector import SmallVector_Type -FunctionType = Type.Subclass() -FunctionType.include.add('llvm/DerivedTypes.h') +FunctionType = llvm.Class(Type) -_get_signatures = [(FunctionType.Pointer, - Type.Pointer, Bool.From(bool)), - (FunctionType.Pointer, - Type.Pointer, SmallVector_Type.Ref, Bool.From(bool))] +@FunctionType +class FunctionType: + _include_ = 'llvm/DerivedTypes.h' + get = StaticMethod(ptr(FunctionType), ptr(Type), cast(bool, Bool)) + get |= StaticMethod(ptr(FunctionType), ptr(Type), ref(SmallVector_Type), cast(bool, Bool)) + isVarArg = Method(cast(Bool, bool)) + getReturnType = Method(ptr(Type)) + getParamType = Method(ptr(Type), cast(int, Unsigned)) + getNumParams = Method(cast(Unsigned, int)) -get = FunctionType.staticmultimethod(*_get_signatures) - -isVarArg = FunctionType.method(Bool.To(bool)) -getReturnType = FunctionType.method(Type.Pointer) -getParamType = FunctionType.method(Type.Pointer, Unsigned.From(int)) -getNumParams = FunctionType.method(Unsigned.To(int)) diff --git a/newbinding/src/LLVMContext.py b/newbinding/src/LLVMContext.py index 0965748..f2526db 100644 --- a/newbinding/src/LLVMContext.py +++ b/newbinding/src/LLVMContext.py @@ -1,8 +1,8 @@ from binding import * from namespace import llvm -LLVMContext = llvm.Class() -LLVMContext.include.add("llvm/LLVMContext.h") - -getGlobalContext = llvm.Function(LLVMContext.Ref) +@llvm.Class() +class LLVMContext: + _include_ = "llvm/LLVMContext.h" +llvm.Function('getGlobalContext', ref(LLVMContext)) diff --git a/newbinding/src/Module.py b/newbinding/src/Module.py index 67ac8b0..6a6a806 100644 --- a/newbinding/src/Module.py +++ b/newbinding/src/Module.py @@ -7,39 +7,39 @@ from DerivedTypes import FunctionType from raw_ostream import raw_ostream from AssemblyAnnotationWriter import AssemblyAnnotationWriter -# class Module -Module = llvm.Class() -Module.include.add("llvm/Module.h") +@llvm.Class() +class Module: + _include_ = "llvm/Module.h" + # Enumerators + Endianness = Enum('AnyEndianness', 'LittleEndian', 'BigEndian') + PointerSize = Enum('AnyPointerSize', 'Pointer32', 'Pointer64') -# Enumerators -Endianness = Module.Enum('AnyEndianness', 'LittleEndian', 'BigEndian') -PointerSize = Module.Enum('AnyPointerSize', 'Pointer32', 'Pointer64') + # Constructors & Destructors + new = Constructor(cast(str, StringRef), ref(LLVMContext)) + delete = Destructor() -# Constructors & Destructors -new = Module.new(StringRef.From(str), LLVMContext.Ref) -delete = Module.delete() + # Module Level Accessor + getModuleIdentifier = Method(cast(ConstStdString, str)) + getDataLayout = Method(cast(ConstStdString, str)) + getTargetTriple = Method(cast(ConstStdString, str)) + getEndianness = Method(Endianness) + getPointerSize = Method(PointerSize) + getContext = Method(ref(LLVMContext)) + getModuleInlineAsm = Method(cast(ConstStdString, str)) -# Module Level Accessor -getModuleIdentifier = Module.method(ConstStdString.To(str)) -getDataLayout = Module.method(ConstStdString.To(str)) -getTargetTriple = Module.method(ConstStdString.To(str)) -getEndianness = Module.method(Endianness) -getPointerSize = Module.method(PointerSize) -getContext = Module.method(LLVMContext.Ref) -getModuleInlineAsm = Module.method(ConstStdString.To(str)) + # Module Level Mutators + setModuleIdentifier = Method(Void, cast(str, StringRef)) + setDataLayout = Method(Void, cast(str, StringRef)) + setTargetTriple = Method(Void, cast(str, StringRef)) + setModuleInlineAsm = Method(Void, cast(str, StringRef)) + appendModuleInlineAsm = Method(Void, cast(str, StringRef)) -# Module Level Mutators -setModuleIdentifier = Module.method(Void, StringRef.From(str)) -setDataLayout = Module.method(Void, StringRef.From(str)) -setTargetTriple = Module.method(Void, StringRef.From(str)) -setModuleInlineAsm = Module.method(Void, StringRef.From(str)) -appendModuleInlineAsm = Module.method(Void, StringRef.From(str)) + # Function Accessors + getOrInsertFunction = Method(ptr(Constant), cast(str, StringRef), ptr(FunctionType)) -# Function Accessors -getOrInsertFunction = Module.method(Constant.Pointer, StringRef.From(str), FunctionType.Pointer) + # Utilities + dump = Method(Void) + print_ = Method(Void, ref(raw_ostream), ptr(AssemblyAnnotationWriter)) + print_.realname = 'print' -# Utilities -dump = Module.method(Void) -print_ = Module.method(Void, raw_ostream.Ref, AssemblyAnnotationWriter.Pointer) -print_.realname = 'print' -dropAllReferences = Module.method(Void) + dropAllReferences = Method() diff --git a/newbinding/src/SmallVector.py b/newbinding/src/SmallVector.py index 225c720..d00b294 100644 --- a/newbinding/src/SmallVector.py +++ b/newbinding/src/SmallVector.py @@ -1,5 +1,6 @@ from binding import * from namespace import llvm -SmallVector_Type = llvm.Class() -delete = SmallVector_Type.delete() +@llvm.Class() +class SmallVector_Type: + delete = Destructor() diff --git a/newbinding/src/StringRef.py b/newbinding/src/StringRef.py index 554629b..fb3b896 100644 --- a/newbinding/src/StringRef.py +++ b/newbinding/src/StringRef.py @@ -1,6 +1,7 @@ from binding import * from namespace import llvm -StringRef = llvm.Class() -StringRef.include.add("llvm/ADT/StringRef.h") +@llvm.Class() +class StringRef: + _include_ = "llvm/ADT/StringRef.h" diff --git a/newbinding/src/Type.py b/newbinding/src/Type.py index 3703200..45f9444 100644 --- a/newbinding/src/Type.py +++ b/newbinding/src/Type.py @@ -4,93 +4,112 @@ from LLVMContext import LLVMContext from raw_ostream import raw_ostream Type = llvm.Class() -Type.include.add('llvm/Type.h') +IntegerType = llvm.Class(Type) +CompositeType = llvm.Class(Type) +SequentialType = llvm.Class(CompositeType) +PointerType = llvm.Class(SequentialType) -IntegerType = Type.Subclass() -CompositeType = Type.Subclass() -SequentialType = CompositeType.Subclass() -PointerType = SequentialType.Subclass() +@Type +class Type: + _include_ = 'llvm/Type.h' -getContext = Type.method(LLVMContext.Ref) -dump = Type.method(Void) -print_ = Type.method(Void, raw_ostream.Ref) -print_.realname = 'print' + getContext = Method(ref(LLVMContext)) + dump = Method() + print_ = Method(Void, ref(raw_ostream)) + print_.realname = 'print' -def type_checker(): - return Type.method(Bool.To(bool)) + def type_checker(): + return Method(cast(Bool, bool)) -isVoidTy = type_checker() -isHalfTy = type_checker() -isFloatTy = type_checker() -isDoubleTy = type_checker() -isX86_FP80Ty = type_checker() -isFP128Ty = type_checker() -isPPC_FP128Ty = type_checker() -isFloatingPointTy = type_checker() -isX86_MMXTy = type_checker() -isFPOrFPVectorTy = type_checker() -isLabelTy = type_checker() -isMetadataTy = type_checker() -isIntOrIntVectorTy = type_checker() -isFunctionTy = type_checker() -isStructTy = type_checker() -isArrayTy = type_checker() -isPointerTy = type_checker() -isPtrOrPtrVectorTy = type_checker() -isVectorTy = type_checker() -isEmptyTy = type_checker() -isPrimitiveType = type_checker() -isDerivedType = type_checker() -isFirstClassType = type_checker() -isSingleValueType = type_checker() -isAggregateType = type_checker() -isSized = type_checker() + isVoidTy = type_checker() + isHalfTy = type_checker() + isFloatTy = type_checker() + isDoubleTy = type_checker() + isX86_FP80Ty = type_checker() + isFP128Ty = type_checker() + isPPC_FP128Ty = type_checker() + isFloatingPointTy = type_checker() + isX86_MMXTy = type_checker() + isFPOrFPVectorTy = type_checker() + isLabelTy = type_checker() + isMetadataTy = type_checker() + isIntOrIntVectorTy = type_checker() + isFunctionTy = type_checker() + isStructTy = type_checker() + isArrayTy = type_checker() + isPointerTy = type_checker() + isPtrOrPtrVectorTy = type_checker() + isVectorTy = type_checker() + isEmptyTy = type_checker() + isPrimitiveType = type_checker() + isDerivedType = type_checker() + isFirstClassType = type_checker() + isSingleValueType = type_checker() + isAggregateType = type_checker() + isSized = type_checker() -isIntegerTy = Type.multimethod([Bool.To(bool)], - [Bool.To(bool), Unsigned.From(int)]) + isIntegerTy = Method(cast(Bool, bool)) + isIntegerTy |= Method(cast(Bool, bool), cast(int, Unsigned)) -def type_factory(): - return Type.staticmethod(Type.Pointer, LLVMContext.Ref) + def type_factory(): + return StaticMethod(ptr(Type), ref(LLVMContext)) -getVoidTy = type_factory() -getLabelTy = type_factory() -getHalfTy = type_factory() -getFloatTy = type_factory() -getDoubleTy = type_factory() -getMetadataTy = type_factory() -getX86_FP80Ty = type_factory() -getFP128Ty = type_factory() -getPPC_FP128Ty = type_factory() -getX86_MMXTy = type_factory() + getVoidTy = type_factory() + getLabelTy = type_factory() + getHalfTy = type_factory() + getFloatTy = type_factory() + getDoubleTy = type_factory() + getMetadataTy = type_factory() + getX86_FP80Ty = type_factory() + getFP128Ty = type_factory() + getPPC_FP128Ty = type_factory() + getX86_MMXTy = type_factory() -getIntNTy = Type.staticmethod(IntegerType.Pointer, LLVMContext.Ref, Unsigned.From(int)) + getIntNTy = StaticMethod(ptr(IntegerType), ref(LLVMContext), cast(Unsigned, int)) -def integer_factory(): - return Type.staticmethod(IntegerType.Pointer, LLVMContext.Ref) + def integer_factory(): + return StaticMethod(ptr(IntegerType), ref(LLVMContext)) -getInt1Ty = integer_factory() -getInt8Ty = integer_factory() -getInt16Ty = integer_factory() -getInt32Ty = integer_factory() -getInt64Ty = integer_factory() + getInt1Ty = integer_factory() + getInt8Ty = integer_factory() + getInt16Ty = integer_factory() + getInt32Ty = integer_factory() + getInt64Ty = integer_factory() -def pointer_factory(): - return Type.staticmethod(PointerType.Pointer, LLVMContext.Ref) + def pointer_factory(): + return StaticMethod(ptr(PointerType), ref(LLVMContext)) -getHalfPtrTy = pointer_factory() -getFloatPtrTy = pointer_factory() -getDoublePtrTy = pointer_factory() -getX86_FP80PtrTy = pointer_factory() -getFP128PtrTy = pointer_factory() -getPPC_FP128PtrTy = pointer_factory() -getX86_MMXPtrTy = pointer_factory() -getInt1PtrTy = pointer_factory() -getInt8PtrTy = pointer_factory() -getInt16PtrTy = pointer_factory() -getInt32PtrTy = pointer_factory() -getInt64PtrTy = pointer_factory() -getIntNPtrTy = Type.staticmethod(PointerType.Pointer, - LLVMContext.Ref, Unsigned.From(int)) + getHalfPtrTy = pointer_factory() + getFloatPtrTy = pointer_factory() + getDoublePtrTy = pointer_factory() + getX86_FP80PtrTy = pointer_factory() + getFP128PtrTy = pointer_factory() + getPPC_FP128PtrTy = pointer_factory() + getX86_MMXPtrTy = pointer_factory() + getInt1PtrTy = pointer_factory() + getInt8PtrTy = pointer_factory() + getInt16PtrTy = pointer_factory() + getInt32PtrTy = pointer_factory() + getInt64PtrTy = pointer_factory() + getIntNPtrTy = StaticMethod(ptr(PointerType), + ref(LLVMContext), cast(int, Unsigned)) +@IntegerType +class IntegerType: + pass + + +@CompositeType +class CompositeType: + pass + +@SequentialType +class SequentialType: + pass + +@PointerType +class PointerType: + pass + diff --git a/newbinding/src/User.py b/newbinding/src/User.py index 8753983..dbc290d 100644 --- a/newbinding/src/User.py +++ b/newbinding/src/User.py @@ -2,4 +2,7 @@ from binding import * from namespace import llvm from Value import Value -User = Value.Subclass() +@llvm.Class(Value) +class User: + pass + diff --git a/newbinding/src/Value.py b/newbinding/src/Value.py index 062ad43..9d1a2dd 100644 --- a/newbinding/src/Value.py +++ b/newbinding/src/Value.py @@ -5,20 +5,23 @@ from AssemblyAnnotationWriter import AssemblyAnnotationWriter from Type import Type from LLVMContext import LLVMContext from StringRef import StringRef -# + Value = llvm.Class() -dump = Value.method(Void) +@Value +class Value: -print_ = Value.method(Void, raw_ostream.Ref, AssemblyAnnotationWriter.Pointer) -print_.realname = 'print' + dump = Method() -getType = Value.method(Type.Pointer) -getContext = Value.method(LLVMContext.Ref) + print_ = Method(Void, ref(raw_ostream), ptr(AssemblyAnnotationWriter)) + print_.realname = 'print' -hasName = Value.method(Bool.To(bool)) -# skip getValueName, setValueName -getName = Value.method(StringRef.To(str)) -setName = Value.method(Void, StringRef.From(str)) + getType = Method(ptr(Type)) + getContext = Method(ref(LLVMContext)) -replaceAllUsesWith = Value.method(Void, Value.Pointer) \ No newline at end of file + hasName = Method(cast(Bool, bool)) + # skip getValueName, setValueName + getName = Method(cast(StringRef, str)) + setName = Method(Void, cast(str, StringRef)) + + replaceAllUsesWith = Method(Void, ptr(Value)) \ No newline at end of file diff --git a/newbinding/src/__init__.py b/newbinding/src/__init__.py index e69de29..6e24918 100644 --- a/newbinding/src/__init__.py +++ b/newbinding/src/__init__.py @@ -0,0 +1,2 @@ +from . import Module + diff --git a/newbinding/src/namespace.py b/newbinding/src/namespace.py index 02af8c9..c50256d 100644 --- a/newbinding/src/namespace.py +++ b/newbinding/src/namespace.py @@ -1,4 +1,3 @@ from binding import * -extra = Namespace('llvm_extra') llvm = Namespace('llvm') diff --git a/newbinding/src/raw_ostream.py b/newbinding/src/raw_ostream.py index 64e8046..2f5a6f5 100644 --- a/newbinding/src/raw_ostream.py +++ b/newbinding/src/raw_ostream.py @@ -3,10 +3,15 @@ from namespace import llvm from LLVMContext import LLVMContext from StringRef import StringRef -raw_ostream = llvm.Class() -raw_ostream.include.add("llvm/Support/raw_ostream.h") -delete = raw_ostream.delete() +@llvm.Class() +class raw_ostream: + _include_ = "llvm/Support/raw_ostream.h" + delete = Destructor() + +@llvm.Class(raw_ostream) +class raw_svector_ostream: + _include_ = "llvm/Support/raw_os_ostream.h" + _base_ = raw_ostream + + str = Method(cast(str, StringRef)) -raw_svector_ostream = raw_ostream.Subclass() -raw_svector_ostream.include.add("llvm/Support/raw_os_ostream.h") -str = raw_svector_ostream.method(StringRef.To(str)) diff --git a/newbinding/test2.py b/newbinding/test2.py index ac74594..afb3608 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -1,4 +1,5 @@ import api +import extra import _capsule api.capsule.set_debug(True) context = api.getGlobalContext() @@ -15,7 +16,7 @@ assert m.getPointerSize() == api.Module.PointerSize.AnyPointerSize m.dump() -os = api.make_raw_ostream_for_printing() +os = extra.make_raw_ostream_for_printing() m.print_(os, None) print os.str() @@ -29,15 +30,15 @@ fnty = api.FunctionType.get(int1ty, False) fnty.dump() types = [int1ty, api.Type.getIntNTy(context, 21)] -svt = api.make_small_vector_from_types(*types) +svt = extra.make_small_vector_from_types(*types) fnty = api.FunctionType.get(int1ty, svt, False) -os = api.make_raw_ostream_for_printing() +os = extra.make_raw_ostream_for_printing() fnty.print_(os) print os.str() fn = m.getOrInsertFunction("foo", fnty) -os = api.make_raw_ostream_for_printing() +os = extra.make_raw_ostream_for_printing() fn.print_(os, None) print os.str() assert fn.hasName() diff --git a/newbinding/utils.py b/newbinding/utils.py deleted file mode 100644 index 6c39990..0000000 --- a/newbinding/utils.py +++ /dev/null @@ -1,6 +0,0 @@ - -def indent_println(println): - def _println(s): - println("%s%s" % (' '* 4, s)) - return _println - From 3c81157ede77dae545dea76988df117441b8bb16 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 25 Jan 2013 15:35:23 -0600 Subject: [PATCH 22/85] Add downcasting --- newbinding/binding.py | 28 +++++++++------ newbinding/capsule.py | 46 +++++++++++++++++-------- newbinding/extra.py | 27 +++++++++++++-- newbinding/gen.py | 26 ++++++++++++++ newbinding/include/llvm_binding/extra.h | 10 +++--- newbinding/src/namespace.py | 1 + 6 files changed, 106 insertions(+), 32 deletions(-) diff --git a/newbinding/binding.py b/newbinding/binding.py index fc26d92..8c58aa9 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -28,10 +28,10 @@ class Namespace(object): def __str__(self): return self.name -class Type(object): +class _Type(object): pass -class BuiltinTypes(Type): +class BuiltinTypes(_Type): def __init__(self, name): self.name = name @@ -47,7 +47,7 @@ Unsigned = BuiltinTypes('unsigned') Bool = BuiltinTypes('bool') ConstStdString = BuiltinTypes('const std::string') -class Class(Type): +class Class(_Type): format = 'O' def __init__(self, ns, *bases): @@ -57,9 +57,11 @@ class Class(Type): self.methods = [] self.enums = [] self.includes = set() + self.downcastables = set() def __call__(self, defn): assert not self._is_defined + # process the definition in "defn" self.name = defn.__name__ for k, v in defn.__dict__.items(): if isinstance(v, Method): @@ -79,6 +81,12 @@ class Class(Type): else: for i in v: self.includes.add(i) + elif k == '_downcast_': + if isinstance(v, Class): + self.downcastables.add(v) + else: + for i in v: + self.downcastables.add(i) return self def compile_cpp(self, writer): @@ -106,12 +114,11 @@ class Class(Type): bases = ', '.join(x.name for x in self.bases) writer.println('@capsule.register_class') with writer.block('class %(clsname)s(%(bases)s):' % locals()): + writer.println('_llvm_type_ = "%s"' % self.fullname) for enum in self.enums: enum.compile_py(writer) for meth in self.methods: meth.compile_py(writer) - if not self.enums and not self.methods: - writer.println('pass') writer.println() @property @@ -178,6 +185,7 @@ class Enum(object): def compile_py(self, writer): with writer.block('class %s:' % self.name): + writer.println('_llvm_type_ = "%s"' % self.fullname) for v in self.value_names: writer.println('%(v)s = "%(v)s"' % locals()) writer.println() @@ -340,7 +348,7 @@ class Constructor(StaticMethod): ret = writer.declare(retty.fullname, stmt) return ret -class ref(Type): +class ref(_Type): def __init__(self, element): assert isinstance(element, Class), type(element) self.element = element @@ -369,7 +377,7 @@ class ref(Type): return writer.declare(self.fullname, '*%s' % p) -class ptr(Type): +class ptr(_Type): def __init__(self, element): assert isinstance(element, Class) self.element = element @@ -393,7 +401,7 @@ class ptr(Type): return writer.pycapsule_new(val, self.element.capsule_name, self.element.fullname) -class cast(Type): +class cast(_Type): format = 'O' def __init__(self, original, target): @@ -406,14 +414,14 @@ class cast(Type): @property def python_type(self): - if not isinstance(self.target, Type): + if not isinstance(self.target, _Type): return self.target else: return self.original @property def binding_type(self): - if isinstance(self.target, Type): + if isinstance(self.target, _Type): return self.target else: return self.original diff --git a/newbinding/capsule.py b/newbinding/capsule.py index e4cd4fa..d999e30 100644 --- a/newbinding/capsule.py +++ b/newbinding/capsule.py @@ -19,7 +19,7 @@ def set_debug(enabled): class WeakRef(ref): - __slots__ = 'capsule', 'dtor' + __slots__ = 'capsule', 'dtor', 'owning' _pyclasses = {} _addr2obj = WeakValueDictionary() @@ -33,12 +33,20 @@ def classof(cap): return _pyclasses[cls] def _capsule_destructor(weak): - cap = weak.capsule - addr = _capsule.getPointer(cap) - cls = _capsule.getClassName(cap) - logger.debug("destroy pointer 0x%08X to %s", addr, cls) - weak.dtor(cap) - del _owners[addr] + if weak.owning: + cap = weak.capsule + addr = _capsule.getPointer(cap) + cls = _capsule.getClassName(cap) + logger.debug("destroy pointer 0x%08X to %s", addr, cls) + weak.dtor(cap) + del _owners[addr] + +def release_ownership(old): + addr = _capsule.getPointer(old) + if hasattr(old, '_delete_'): + oldweak = _owners[addr] + oldweak.owning = False # dis-own + del _owners[addr] def wrap(cap): '''Wrap a PyCapsule with the corresponding Wrapper class. @@ -60,13 +68,26 @@ def wrap(cap): weak = WeakRef(obj, _capsule_destructor) _owners[addr] = weak weak.capsule = cap + weak.owning = True weak.dtor = cls._delete_ else: - assert classof(obj._ptr) is classof(cap) - # Unset destructor for capsules that are repeated - _capsule.setDestructor(cap, None) + oldcls = classof(obj._ptr) + newcls = classof(cap) + if issubclass(oldcls, newcls): + # do auto downcast + pass + else: + assert oldcls is newcls return obj +def downcast(old, new): + assert old is not new + oldcls = classof(old) + newcls = classof(new) + assert issubclass(newcls, oldcls) + release_ownership(old) + del _addr2obj[_capsule.getPointer(old)] # clear cache + return wrap(new) def unwrap(obj): '''Unwrap a Wrapper instance into the underlying PyCapsule. @@ -96,8 +117,3 @@ class Wrapper(object): def _ptr(self): return self.__ptr - def _release_ownership(self): - _capsule.setDestructor(self._ptr, None) - - - diff --git a/newbinding/extra.py b/newbinding/extra.py index 1af4e5f..a613296 100644 --- a/newbinding/extra.py +++ b/newbinding/extra.py @@ -3,8 +3,13 @@ Wrapped the extra functions in _api.so ''' import capsule +import _api +# +# Re-export the native API from the _api.extra and wrap the functions +# def _wrapper(func): + "Wrap the re-exported functions" def _core(*args): unwrapped = map(capsule.unwrap, args) ret = func(*unwrapped) @@ -12,9 +17,27 @@ def _wrapper(func): return _core def _init(glob): - from _api import extra - for k, v in extra.__dict__.items(): + for k, v in _api.extra.__dict__.items(): glob[k] = _wrapper(v) _init(globals()) +# +# Downcasts +# + +def downcast(obj, cls): + if type(obj) is cls: + return obj + fromty = obj._llvm_type_ + toty = cls._llvm_type_ + fname = 'downcast_%s_to_%s' % (fromty, toty) + fname = fname.replace('::', '_') + try: + caster = getattr(_api, fname) + except AttributeError: + fmt = "Downcast from %s to %s is not supported" + raise TypeError(fmt % (fromty, toty)) + old = capsule.unwrap(obj) + new = caster(old) + return capsule.downcast(old, new) \ No newline at end of file diff --git a/newbinding/gen.py b/newbinding/gen.py index 4d8709e..f1af18e 100644 --- a/newbinding/gen.py +++ b/newbinding/gen.py @@ -72,6 +72,20 @@ def main(): print cls units.append(cls) + # add extra stuffs + downcastlist = [] + ## add downcast + for cls in units: + if isinstance(cls, Class): + for bcls in cls.downcastables: + from_to = bcls.fullname, cls.fullname + name = 'downcast_%s_to_%s' % tuple(map(codegen.mangle, from_to)) + fn = Function(namespaces[''], name, ptr(cls), ptr(bcls)) + downcastlist.append((from_to, fn)) + units.append(fn) + + + # generate cpp source with open('%s.cpp' % outputfilename, 'w') as cppfile: println = wrap_println_from_file(cppfile) @@ -87,6 +101,18 @@ def main(): println('#include "%s"' % inc) println() + # generate downcast + for ((fromty, toty), fn) in downcastlist: + name = fn.name + fmt = ''' +static +%(toty)s* %(name)s(%(fromty)s* arg) +{ + return typecast<%(toty)s>::from(arg); +} +''' + println(fmt % locals()) + # write methods and method tables for u in units: writer = codegen.CppCodeWriter(println) diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index 417c0f8..94887b3 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -37,9 +37,9 @@ PyObject* make_small_vector_from_types(PyObject* self, PyObject* args) { } static PyMethodDef extra_methodtable[] = { -#define method(func) { #func, (PyCFunction)func, METH_VARARGS, NULL } -method( make_raw_ostream_for_printing ), -method( make_small_vector_from_types ), -{ NULL } -#undef method + #define method(func) { #func, (PyCFunction)func, METH_VARARGS, NULL } + method( make_raw_ostream_for_printing ), + method( make_small_vector_from_types ), + #undef method + { NULL } }; diff --git a/newbinding/src/namespace.py b/newbinding/src/namespace.py index c50256d..3a081af 100644 --- a/newbinding/src/namespace.py +++ b/newbinding/src/namespace.py @@ -1,3 +1,4 @@ from binding import * llvm = Namespace('llvm') +default = Namespace('') From c76096bbcb01953d43b9a829f28d5e52b7fad9d7 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 25 Jan 2013 15:41:38 -0600 Subject: [PATCH 23/85] Add Function and some Function methods --- newbinding/src/Function.py | 19 +++++++++++++++++++ newbinding/src/GlobalValue.py | 8 ++++++++ newbinding/src/Module.py | 1 + newbinding/src/Value.py | 2 +- newbinding/test2.py | 12 +++++++++++- 5 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 newbinding/src/Function.py create mode 100644 newbinding/src/GlobalValue.py diff --git a/newbinding/src/Function.py b/newbinding/src/Function.py new file mode 100644 index 0000000..7077d3a --- /dev/null +++ b/newbinding/src/Function.py @@ -0,0 +1,19 @@ +from binding import * +from namespace import llvm +from GlobalValue import GlobalValue +from Constant import Constant +from Type import Type +from DerivedTypes import FunctionType +from LLVMContext import LLVMContext + +@llvm.Class(GlobalValue) +class Function: + _include_ = 'llvm/Function.h' + _downcast_ = GlobalValue, Constant + + getReturnType = Method(ptr(Type)) + getFunctionType = Method(ptr(FunctionType)) + getContext = Method(ref(LLVMContext)) + isVarArg = Method(cast(Bool, bool)) + getIntrinsicID = Method(cast(Unsigned, int)) + isIntrinsic = Method(cast(Bool, bool)) \ No newline at end of file diff --git a/newbinding/src/GlobalValue.py b/newbinding/src/GlobalValue.py new file mode 100644 index 0000000..f1a6827 --- /dev/null +++ b/newbinding/src/GlobalValue.py @@ -0,0 +1,8 @@ +from binding import * +from namespace import llvm +from Constant import Constant + +@llvm.Class(Constant) +class GlobalValue: + _include_ = 'llvm/GlobalValue.h' + diff --git a/newbinding/src/Module.py b/newbinding/src/Module.py index 6a6a806..730b757 100644 --- a/newbinding/src/Module.py +++ b/newbinding/src/Module.py @@ -3,6 +3,7 @@ from namespace import llvm from LLVMContext import LLVMContext from StringRef import StringRef from Constant import Constant +from Function import Function from DerivedTypes import FunctionType from raw_ostream import raw_ostream from AssemblyAnnotationWriter import AssemblyAnnotationWriter diff --git a/newbinding/src/Value.py b/newbinding/src/Value.py index 9d1a2dd..30b3f37 100644 --- a/newbinding/src/Value.py +++ b/newbinding/src/Value.py @@ -24,4 +24,4 @@ class Value: getName = Method(cast(StringRef, str)) setName = Method(Void, cast(str, StringRef)) - replaceAllUsesWith = Method(Void, ptr(Value)) \ No newline at end of file + replaceAllUsesWith = Method(Void, ptr(Value)) diff --git a/newbinding/test2.py b/newbinding/test2.py index afb3608..3429f10 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -37,7 +37,8 @@ os = extra.make_raw_ostream_for_printing() fnty.print_(os) print os.str() -fn = m.getOrInsertFunction("foo", fnty) +const = m.getOrInsertFunction("foo", fnty) +fn = extra.downcast(const, api.Function) os = extra.make_raw_ostream_for_printing() fn.print_(os, None) print os.str() @@ -45,3 +46,12 @@ assert fn.hasName() assert 'foo' == fn.getName() fn.setName('bar') assert 'bar' == fn.getName() + +os = extra.make_raw_ostream_for_printing() +assert fn.getReturnType() is int1ty + +assert fnty is fn.getFunctionType() + +assert fn.isVarArg() == False +assert fn.getIntrinsicID() == 0 +assert not fn.isIntrinsic() From 4b5cb100f71c5b9624a35e78c97324f48d0dde4f Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 28 Jan 2013 15:18:24 -0600 Subject: [PATCH 24/85] Auto discover binding modules --- newbinding/src/__init__.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/newbinding/src/__init__.py b/newbinding/src/__init__.py index 6e24918..1042826 100644 --- a/newbinding/src/__init__.py +++ b/newbinding/src/__init__.py @@ -1,2 +1,11 @@ -from . import Module +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] + topname = __name__.rsplit('.', 1)[0] + importlib.import_module('.' + modname, topname) + +_init() From 01683150760f3f0778937590eac769847f7d8b64 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 28 Jan 2013 15:19:16 -0600 Subject: [PATCH 25/85] Explicitly declare class name when registering classes --- newbinding/binding.py | 3 +-- newbinding/capsule.py | 9 +++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/newbinding/binding.py b/newbinding/binding.py index 8c58aa9..85b74e9 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -112,7 +112,7 @@ class Class(_Type): bases = 'capsule.Wrapper' if self.bases: bases = ', '.join(x.name for x in self.bases) - writer.println('@capsule.register_class') + writer.println('@capsule.register_class("%s")' % self.fullname) with writer.block('class %(clsname)s(%(bases)s):' % locals()): writer.println('_llvm_type_ = "%s"' % self.fullname) for enum in self.enums: @@ -151,7 +151,6 @@ class Class(_Type): writer.die_if_false(casted) return casted - class Enum(object): def __init__(self, *value_names): self.parent = None diff --git a/newbinding/capsule.py b/newbinding/capsule.py index d999e30..47c32fb 100644 --- a/newbinding/capsule.py +++ b/newbinding/capsule.py @@ -99,10 +99,11 @@ def unwrap(obj): return obj -def register_class(cls): - clsname = cls.__name__ - _pyclasses['llvm::%s' % clsname] = cls - return cls +def register_class(clsname): + def _wrapped(cls): + _pyclasses[clsname] = cls + return cls + return _wrapped class Wrapper(object): From d1931cc4994c2ee6adf8d611c9a59d5dbc9c0362 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 28 Jan 2013 15:20:07 -0600 Subject: [PATCH 26/85] Fix duplicated semicolon --- newbinding/codegen.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/newbinding/codegen.py b/newbinding/codegen.py index 9398b14..2a85abc 100644 --- a/newbinding/codegen.py +++ b/newbinding/codegen.py @@ -184,14 +184,14 @@ class CppCodeWriter(CodeWriterBase): arglist = ', '.join(args[1:]) if func == 'delete': assert not arglist - stmt = 'delete %(this)s;' % locals() + stmt = 'delete %(this)s' % locals() elif func == 'new': alloctype = retty.rstrip(' *') - stmt = 'new %(alloctype)s(%(arglist)s);' % locals() + stmt = 'new %(alloctype)s(%(arglist)s)' % locals() else: - stmt = '%(this)s->%(func)s(%(arglist)s);' % locals() + stmt = '%(this)s->%(func)s(%(arglist)s)' % locals() if retty == 'void': - self.println(stmt) + self.println('%s;' % stmt) else: return self.declare(retty, stmt) From 821e93783729ff74268e63c329d8a839c47fded9 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 28 Jan 2013 15:20:36 -0600 Subject: [PATCH 27/85] Add binding util for iterator to list --- newbinding/binding.py | 43 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/newbinding/binding.py b/newbinding/binding.py index 85b74e9..1764559 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -46,6 +46,7 @@ Void = BuiltinTypes('void') Unsigned = BuiltinTypes('unsigned') Bool = BuiltinTypes('bool') ConstStdString = BuiltinTypes('const std::string') +PyObjectPtr = BuiltinTypes('PyObject*') class Class(_Type): format = 'O' @@ -81,6 +82,8 @@ class Class(_Type): else: for i in v: self.includes.add(i) + elif k == '_realname_': + self.realname = v elif k == '_downcast_': if isinstance(v, Class): self.downcastables.add(v) @@ -146,7 +149,7 @@ class Class(_Type): writer.die_if_false(raw) ptrty = ptr(self).fullname ty = self.fullname - fmt = 'typecast<%(ty)s>::from(%(raw)s)' + fmt = 'typecast<%(ty)s >::from(%(raw)s)' casted = writer.declare(ptrty, fmt % locals()) writer.die_if_false(casted) return casted @@ -252,12 +255,8 @@ class Method(object): writer.raises(TypeError, 'Invalid number of args') def compile_cpp_body(self, writer, retty, argtys): - if isinstance(self.parent, Class): - args = writer.parse_arguments('args', ptr(self.parent), *argtys) - ret = writer.method_call(self.realname, retty.fullname, *args) - else: - args = writer.parse_arguments('args', *argtys) - ret = writer.call(self.fullname, retty.fullname, *args) + args = writer.parse_arguments('args', ptr(self.parent), *argtys) + ret = writer.method_call(self.realname, retty.fullname, *args) writer.return_value(retty.wrap(writer, ret)) def compile_py(self, writer): @@ -273,6 +272,29 @@ class Method(object): writer.println() +class IterToList(Method): + def __init__(self, elemty, argtys, iterty, begin, end): + super(IterToList, self).__init__(PyObjectPtr, *argtys) + self.elemty = elemty + self.iterty = iterty + self.begin = begin + self.end = end + + def compile_cpp_body(self, writer, retty, argtys): + args = writer.parse_arguments('args', ptr(self.parent), *argtys) + it = writer.method_call(self.begin, self.iterty, *args) + end = writer.method_call(self.end, self.iterty, *args) + con = writer.call('PyList_New', 'PyObject*', '0') + writer.die_if_false(con) + with writer.block('for (; %(it)s != %(end)s; ++%(it)s)' % locals()): + elem = writer.declare(self.elemty.fullname, '*%(it)s;' % locals()) + wrapped = self.elemty.wrap(writer, elem) + ok = writer.call('PyList_Append', 'int', con, wrapped) + with writer.block('if (%(ok)s == -1)' % locals()): + writer.return_value(None) + writer.return_value(con) + + class StaticMethod(Method): def compile_cpp_body(self, writer, retty, argtys): @@ -296,7 +318,6 @@ class StaticMethod(Method): writer.return_value(wrapped) writer.println() - class Function(Method): _kind_ = 'func' @@ -305,6 +326,11 @@ class Function(Method): self.parent = parent self.name = name + def compile_cpp_body(self, writer, retty, argtys): + args = writer.parse_arguments('args', *argtys) + ret = writer.call(self.fullname, retty.fullname, *args) + writer.return_value(retty.wrap(writer, ret)) + def compile_py(self, writer): with writer.function(self.name, varargs='args') as varargs: unwrapped = writer.unwrap_many(varargs) @@ -315,7 +341,6 @@ class Function(Method): writer.return_value(wrapped) writer.println() - class Destructor(Method): _kind_ = 'dtor' From fa4927e1fb6cb195206fbbf4d13d311148921690 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 28 Jan 2013 15:20:50 -0600 Subject: [PATCH 28/85] Start to work on IRBuilder --- newbinding/src/Constant.py | 5 +++-- newbinding/src/Function.py | 8 ++++---- newbinding/src/GlobalValue.py | 4 ++-- newbinding/src/User.py | 5 ++--- newbinding/src/Value.py | 13 +++++++++++++ newbinding/test2.py | 12 ++++++++++++ 6 files changed, 36 insertions(+), 11 deletions(-) diff --git a/newbinding/src/Constant.py b/newbinding/src/Constant.py index 14ff6bb..c59fef4 100644 --- a/newbinding/src/Constant.py +++ b/newbinding/src/Constant.py @@ -1,7 +1,8 @@ from binding import * from namespace import llvm -from User import User +from Value import Constant -@llvm.Class(User) +@Constant class Constant: pass + diff --git a/newbinding/src/Function.py b/newbinding/src/Function.py index 7077d3a..f069e30 100644 --- a/newbinding/src/Function.py +++ b/newbinding/src/Function.py @@ -1,12 +1,11 @@ from binding import * from namespace import llvm -from GlobalValue import GlobalValue -from Constant import Constant +from Value import GlobalValue, Constant, Function from Type import Type from DerivedTypes import FunctionType from LLVMContext import LLVMContext -@llvm.Class(GlobalValue) +@Function class Function: _include_ = 'llvm/Function.h' _downcast_ = GlobalValue, Constant @@ -16,4 +15,5 @@ class Function: getContext = Method(ref(LLVMContext)) isVarArg = Method(cast(Bool, bool)) getIntrinsicID = Method(cast(Unsigned, int)) - isIntrinsic = Method(cast(Bool, bool)) \ No newline at end of file + isIntrinsic = Method(cast(Bool, bool)) + diff --git a/newbinding/src/GlobalValue.py b/newbinding/src/GlobalValue.py index f1a6827..40825a8 100644 --- a/newbinding/src/GlobalValue.py +++ b/newbinding/src/GlobalValue.py @@ -1,8 +1,8 @@ from binding import * from namespace import llvm -from Constant import Constant +from Value import GlobalValue -@llvm.Class(Constant) +@GlobalValue class GlobalValue: _include_ = 'llvm/GlobalValue.h' diff --git a/newbinding/src/User.py b/newbinding/src/User.py index dbc290d..57d58bc 100644 --- a/newbinding/src/User.py +++ b/newbinding/src/User.py @@ -1,8 +1,7 @@ from binding import * from namespace import llvm -from Value import Value +from Value import User -@llvm.Class(Value) +@User class User: pass - diff --git a/newbinding/src/Value.py b/newbinding/src/Value.py index 30b3f37..a901946 100644 --- a/newbinding/src/Value.py +++ b/newbinding/src/Value.py @@ -7,6 +7,12 @@ from LLVMContext import LLVMContext from StringRef import StringRef Value = llvm.Class() +# forward declarations +User = llvm.Class(Value) +BasicBlock = llvm.Class(Value) +Constant = llvm.Class(User) +GlobalValue = llvm.Class(Constant) +Function = llvm.Class(GlobalValue) @Value class Value: @@ -25,3 +31,10 @@ class Value: setName = Method(Void, cast(str, StringRef)) replaceAllUsesWith = Method(Void, ptr(Value)) + + list_use = IterToList(ptr(User), (), 'llvm::Value::use_iterator', + 'use_begin', 'use_end') + + hasOneUse = Method(cast(Bool, bool)) + hasNUses = Method(cast(Bool, bool), cast(int, Unsigned)) + isUsedInBasicBlock = Method(cast(Bool, bool), BasicBlock) diff --git a/newbinding/test2.py b/newbinding/test2.py index 3429f10..810a7ba 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -55,3 +55,15 @@ assert fnty is fn.getFunctionType() assert fn.isVarArg() == False assert fn.getIntrinsicID() == 0 assert not fn.isIntrinsic() + +print fn.list_use() + +builder = api.IRBuilder.new(context) +print builder + +bb = api.BasicBlock.Create(context, "entry", fn, None) +builder.SetInsertPoint(bb) + +builder.CreateRetVoid() + +fn.dump() From d9397289383cb0f17ba088cf3946ad6deb46ab0c Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 28 Jan 2013 15:21:30 -0600 Subject: [PATCH 29/85] Forgot to push files for previous commit. --- newbinding/src/BasicBlock.py | 19 +++ newbinding/src/IRBuilder.py | 21 ++++ newbinding/src/Instruction.py | 230 ++++++++++++++++++++++++++++++++++ 3 files changed, 270 insertions(+) create mode 100644 newbinding/src/BasicBlock.py create mode 100644 newbinding/src/IRBuilder.py create mode 100644 newbinding/src/Instruction.py diff --git a/newbinding/src/BasicBlock.py b/newbinding/src/BasicBlock.py new file mode 100644 index 0000000..c7221a5 --- /dev/null +++ b/newbinding/src/BasicBlock.py @@ -0,0 +1,19 @@ +from binding import * +from namespace import llvm +from Value import Function, BasicBlock +from LLVMContext import LLVMContext +from StringRef import StringRef + +@BasicBlock +class BasicBlock: + Create = StaticMethod(ptr(BasicBlock), ref(LLVMContext), + cast(str, StringRef), + ptr(Function), + ptr(BasicBlock)) + + getParent = Method(ptr(Function)) + empty = Method(cast(Bool, bool)) + dropAllReferences = Method() + isLandingPad = Method(cast(Bool, bool)) + removePredecessor = Method(Void, ptr(BasicBlock), cast(bool, Bool)) + removePredecessor |= Method(Void, ptr(BasicBlock)) diff --git a/newbinding/src/IRBuilder.py b/newbinding/src/IRBuilder.py new file mode 100644 index 0000000..0919a67 --- /dev/null +++ b/newbinding/src/IRBuilder.py @@ -0,0 +1,21 @@ +from binding import * +from namespace import llvm +from LLVMContext import LLVMContext +from BasicBlock import BasicBlock +from Instruction import ReturnInst + +IRBuilder = llvm.Class() + +@IRBuilder +class IRBuilder: + _include_ = 'llvm/IRBuilder.h' + _realname_ = 'IRBuilder<>' + + new = Constructor(ref(LLVMContext)) + delete = Destructor() + + SetInsertPoint = Method(Void, ptr(BasicBlock)) + + isNamePreserving = Method(cast(Bool, bool)) + + CreateRetVoid = Method(ptr(ReturnInst)) diff --git a/newbinding/src/Instruction.py b/newbinding/src/Instruction.py new file mode 100644 index 0000000..310e19d --- /dev/null +++ b/newbinding/src/Instruction.py @@ -0,0 +1,230 @@ +from binding import * +from namespace import llvm +from Value import User + +Instruction = llvm.Class(User) +AtomicCmpXchgInst = llvm.Class(Instruction) +AtomicRMWInst = llvm.Class(Instruction) +BinaryOperator = llvm.Class(Instruction) +CallInst = llvm.Class(Instruction) +CmpInst = llvm.Class(Instruction) +ExtractElementInst = llvm.Class(Instruction) +FenceInst = llvm.Class(Instruction) +GetElementPtrInst = llvm.Class(Instruction) +InsertElementInst = llvm.Class(Instruction) +InsertValueInst = llvm.Class(Instruction) +LandingPadInst = llvm.Class(Instruction) +PHINode = llvm.Class(Instruction) +SelectInst = llvm.Class(Instruction) +ShuffleVectorInst = llvm.Class(Instruction) +StoreInst = llvm.Class(Instruction) +TerminatorInst = llvm.Class(Instruction) +UnaryInstruction = llvm.Class(Instruction) + +IntrinsicInst = llvm.Class(CallInst) + +FCmpInst = llvm.Class(CmpInst) +ICmpInst = llvm.Class(CmpInst) + + +BranchInst = llvm.Class(TerminatorInst) +IndirectBrInst = llvm.Class(TerminatorInst) +ResumeInst = llvm.Class(TerminatorInst) +ReturnInst = llvm.Class(TerminatorInst) +SwitchInst = llvm.Class(TerminatorInst) +UnreachableInst = llvm.Class(TerminatorInst) + +AllocaInst = llvm.Class(UnaryInstruction) +CastInst = llvm.Class(UnaryInstruction) +ExtractValueInst = llvm.Class(UnaryInstruction) +LoadInst = llvm.Class(UnaryInstruction) +VAArgInst = llvm.Class(UnaryInstruction) + +DbgInfoIntrinsic = llvm.Class(IntrinsicInst) +MemIntrinsic = llvm.Class(IntrinsicInst) +VACopyInst = llvm.Class(IntrinsicInst) +VAEndInst = llvm.Class(IntrinsicInst) +VAStartInst = llvm.Class(IntrinsicInst) + +BitCastInst = llvm.Class(CastInst) +FPExtInst = llvm.Class(CastInst) +FPToSIInst = llvm.Class(CastInst) +FPToUIInst = llvm.Class(CastInst) +FPTruncInst = llvm.Class(CastInst) + +@Instruction +class Instruction: + pass + + +@AtomicCmpXchgInst +class AtomicCmpXchgInst: + pass + +@AtomicRMWInst +class AtomicRMWInst: + pass + +@BinaryOperator +class BinaryOperator: + pass + +@CallInst +class CallInst: + pass + +@CmpInst +class CmpInst: + pass + +@ExtractElementInst +class ExtractElementInst: + pass + +@FenceInst +class FenceInst: + pass + +@GetElementPtrInst +class GetElementPtrInst: + pass + +@InsertElementInst +class InsertElementInst: + pass + +@InsertValueInst +class InsertValueInst: + pass + +@LandingPadInst +class LandingPadInst: + pass + +@PHINode +class PHINode: + pass + +@SelectInst +class SelectInst: + pass + +@ShuffleVectorInst +class ShuffleVectorInst: + pass + +@StoreInst +class StoreInst: + pass + +@TerminatorInst +class TerminatorInst: + pass + +@UnaryInstruction +class UnaryInstruction: + pass + +#call + +@IntrinsicInst +class IntrinsicInst: + pass + +#compare + +@FCmpInst +class FCmpInst: + pass + +@ICmpInst +class ICmpInst: + pass + +# terminator +@BranchInst +class BranchInst: + pass + + +@IndirectBrInst +class IndirectBrInst: + pass + +@ResumeInst +class ResumeInst: + pass + +@ReturnInst +class ReturnInst: + pass + +@SwitchInst +class SwitchInst: + pass + +@UnreachableInst +class UnreachableInst: + pass + +# unary +@AllocaInst +class AllocaInst: + pass + +@CastInst +class CastInst: + pass + +@ExtractValueInst +class ExtractValueInst: + pass + +@LoadInst +class LoadInst: + pass + +@VAArgInst +class VAArgInst: + pass + +# intrinsic +@DbgInfoIntrinsic +class DbgInfoIntrinsic: + pass + +@MemIntrinsic +class MemIntrinsic: + pass + +@VACopyInst +class VACopyInst: + pass + +@VAEndInst +class VAEndInst: + pass + +@VAStartInst +class VAStartInst: + pass + +@BitCastInst +class BitCastInst: + pass + +@FPExtInst +class FPExtInst: + pass + +@FPToSIInst +class FPToSIInst: + pass + +@FPToUIInst +class FPToUIInst: + pass + +@FPTruncInst +class FPTruncInst: + pass From af7962a2ca835a62074c7b0c881e982ac1655c1c Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 28 Jan 2013 15:53:01 -0600 Subject: [PATCH 30/85] Remove IterToList, llvm_extra.h. Add CustomMethod. --- newbinding/binding.py | 25 +++------ newbinding/codegen.py | 4 +- newbinding/gen.py | 1 - newbinding/include/llvm_binding/extra.h | 53 ++++++++++++++++++-- newbinding/include/llvm_binding/llvm_extra.h | 38 -------------- newbinding/src/SmallVector.py | 1 + newbinding/src/Value.py | 3 +- 7 files changed, 61 insertions(+), 64 deletions(-) delete mode 100644 newbinding/include/llvm_binding/llvm_extra.h diff --git a/newbinding/binding.py b/newbinding/binding.py index 1764559..3538c9a 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -272,28 +272,17 @@ class Method(object): writer.println() -class IterToList(Method): - def __init__(self, elemty, argtys, iterty, begin, end): - super(IterToList, self).__init__(PyObjectPtr, *argtys) - self.elemty = elemty - self.iterty = iterty - self.begin = begin - self.end = end +class CustomMethod(Method): + def __init__(self, methodname, retty, *argtys): + super(CustomMethod, self).__init__(retty, *argtys) + self.methodname = methodname def compile_cpp_body(self, writer, retty, argtys): args = writer.parse_arguments('args', ptr(self.parent), *argtys) - it = writer.method_call(self.begin, self.iterty, *args) - end = writer.method_call(self.end, self.iterty, *args) - con = writer.call('PyList_New', 'PyObject*', '0') - writer.die_if_false(con) - with writer.block('for (; %(it)s != %(end)s; ++%(it)s)' % locals()): - elem = writer.declare(self.elemty.fullname, '*%(it)s;' % locals()) - wrapped = self.elemty.wrap(writer, elem) - ok = writer.call('PyList_Append', 'int', con, wrapped) - with writer.block('if (%(ok)s == -1)' % locals()): - writer.return_value(None) - writer.return_value(con) + ret = writer.call(self.methodname, retty.fullname, *args) + writer.return_value(retty.wrap(writer, ret)) + class StaticMethod(Method): diff --git a/newbinding/codegen.py b/newbinding/codegen.py index 2a85abc..7652447 100644 --- a/newbinding/codegen.py +++ b/newbinding/codegen.py @@ -42,14 +42,14 @@ def parse_arguments(println, var, *args): return unwrapped -_re_mangle_pattern = re.compile(r'[ _<>\*&]') +_re_mangle_pattern = re.compile(r'[ _<>\*&,]') def mangle(name): def repl(m): s = m.group(0) if s in '<>*&': return '' - elif s in ' ': + elif s in ' ,': return '_' elif s in '_': return '__' diff --git a/newbinding/gen.py b/newbinding/gen.py index f1af18e..d9fc14f 100644 --- a/newbinding/gen.py +++ b/newbinding/gen.py @@ -41,7 +41,6 @@ def populate_headers(println): includes = [ 'llvm_binding/conversion.h', 'llvm_binding/binding.h', - 'llvm_binding/llvm_extra.h', 'llvm_binding/capsule_context.h', 'llvm_binding/extra.h', # extra submodule to add ] diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index 94887b3..639a87c 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -1,10 +1,43 @@ #include #include +#include #include + +namespace extra{ + using namespace llvm; + + class raw_svector_ostream_helper: public raw_svector_ostream { + SmallVectorImpl *SV; + public: + static + raw_svector_ostream_helper* create(){ + SmallVectorImpl* sv = new SmallVector(); + return new raw_svector_ostream_helper(sv); + } + + ~raw_svector_ostream_helper(){ + delete SV; + } + + protected: + + explicit + raw_svector_ostream_helper(SmallVectorImpl* sv) + : raw_svector_ostream(*sv), SV(sv) {} + + private: + // no copy + raw_svector_ostream_helper(const raw_svector_ostream_helper&); + // no assign + void operator = (const raw_svector_ostream_helper&); + }; + +} + static PyObject* make_raw_ostream_for_printing(PyObject* self, PyObject* args) { - using llvm::raw_svector_ostream_helper; + using extra::raw_svector_ostream_helper; using llvm::raw_svector_ostream; if (!PyArg_ParseTuple(args, "")) { @@ -18,7 +51,7 @@ PyObject* make_raw_ostream_for_printing(PyObject* self, PyObject* args) { static PyObject* make_small_vector_from_types(PyObject* self, PyObject* args) { using llvm::Type; - using llvm::SmallVector_Type; + typedef llvm::SmallVector SmallVector_Type; SmallVector_Type* SV = new SmallVector_Type; Py_ssize_t size = PyTuple_Size(args); @@ -33,7 +66,7 @@ PyObject* make_small_vector_from_types(PyObject* self, PyObject* args) { } SV->push_back(type); } - return pycapsule_new(SV, "llvm::SmallVector_Type"); + return pycapsule_new(SV, "llvm::SmallVector"); } static PyMethodDef extra_methodtable[] = { @@ -43,3 +76,17 @@ static PyMethodDef extra_methodtable[] = { #undef method { NULL } }; + + +//////////// + +PyObject* Value_use_iterator_to_list(llvm::Value* val){ + typedef llvm::Value::use_iterator iterator; + PyObject* list = PyList_New(0); + for (iterator it = val->use_begin(), end = val->use_end(); it != end; ++it) { + PyObject* cap = pycapsule_new(*it, "llvm::Value", "llvm::User"); + PyList_Append(list, cap); + } + return list; +} + diff --git a/newbinding/include/llvm_binding/llvm_extra.h b/newbinding/include/llvm_binding/llvm_extra.h deleted file mode 100644 index f920a47..0000000 --- a/newbinding/include/llvm_binding/llvm_extra.h +++ /dev/null @@ -1,38 +0,0 @@ -#include -#include -#include - -namespace llvm{ - -class Type; //forward declaration - -class raw_svector_ostream_helper: public raw_svector_ostream { - SmallVectorImpl *SV; -public: - static - raw_svector_ostream_helper* create(){ - SmallVectorImpl* sv = new SmallVector(); - return new raw_svector_ostream_helper(sv); - } - - ~raw_svector_ostream_helper(){ - delete SV; - } - -protected: - - explicit - raw_svector_ostream_helper(SmallVectorImpl* sv) - : raw_svector_ostream(*sv), SV(sv) {} - -private: - // no copy - raw_svector_ostream_helper(const raw_svector_ostream_helper&); - // no assign - void operator = (const raw_svector_ostream_helper&); -}; - -typedef SmallVector SmallVector_Type; - -} // end namespace llvm - diff --git a/newbinding/src/SmallVector.py b/newbinding/src/SmallVector.py index d00b294..55dadb1 100644 --- a/newbinding/src/SmallVector.py +++ b/newbinding/src/SmallVector.py @@ -3,4 +3,5 @@ from namespace import llvm @llvm.Class() class SmallVector_Type: + _realname_ = 'SmallVector' delete = Destructor() diff --git a/newbinding/src/Value.py b/newbinding/src/Value.py index a901946..3dd5644 100644 --- a/newbinding/src/Value.py +++ b/newbinding/src/Value.py @@ -32,8 +32,7 @@ class Value: replaceAllUsesWith = Method(Void, ptr(Value)) - list_use = IterToList(ptr(User), (), 'llvm::Value::use_iterator', - 'use_begin', 'use_end') + list_use = CustomMethod('Value_use_iterator_to_list', PyObjectPtr) hasOneUse = Method(cast(Bool, bool)) hasNUses = Method(cast(Bool, bool), cast(int, Unsigned)) From 7aa9487f2f66e7003f14fe7835de2293de4b9d60 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 28 Jan 2013 16:00:25 -0600 Subject: [PATCH 31/85] pycapsule_new should return a None object if ptr is NULL. --- newbinding/include/llvm_binding/capsule_context.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/newbinding/include/llvm_binding/capsule_context.h b/newbinding/include/llvm_binding/capsule_context.h index a4070dc..ed63e43 100644 --- a/newbinding/include/llvm_binding/capsule_context.h +++ b/newbinding/include/llvm_binding/capsule_context.h @@ -23,6 +23,9 @@ PyObject* pycapsule_new(void* ptr, if (!classname) { classname = basename; } + if (!ptr) { + Py_RETURN_NONE; + } PyObject* cap = PyCapsule_New(ptr, basename, NULL); if (!cap) { PyErr_SetString(PyExc_TypeError, "Error creating new PyCapsule"); From 895d1147300d13608763aa61b8ab2b9f56bd7662 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 28 Jan 2013 16:36:46 -0600 Subject: [PATCH 32/85] Add CustonPythonMethod and CustonPythonStaticMethod. --- newbinding/binding.py | 24 ++++++++++++++++++++++++ newbinding/src/BasicBlock.py | 3 +++ newbinding/src/DerivedTypes.py | 19 +++++++++++++++++-- newbinding/src/Value.py | 7 +++++++ newbinding/test2.py | 26 +++++++++++++++----------- 5 files changed, 66 insertions(+), 13 deletions(-) diff --git a/newbinding/binding.py b/newbinding/binding.py index 3538c9a..6668452 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -1,3 +1,4 @@ +import inspect, textwrap import functools import codegen as cg @@ -56,6 +57,7 @@ class Class(_Type): self.bases = bases self._is_defined = False self.methods = [] + self.pymethods = [] self.enums = [] self.includes = set() self.downcastables = set() @@ -76,6 +78,8 @@ class Class(_Type): self.enums.append(v) v.name = k v.parent = self + elif isinstance(v, CustomPythonMethod): + self.pymethods.append(v) elif k == '_include_': if isinstance(v, str): self.includes.add(v) @@ -122,6 +126,8 @@ class Class(_Type): enum.compile_py(writer) for meth in self.methods: meth.compile_py(writer) + for meth in self.pymethods: + meth.compile_py(writer) writer.println() @property @@ -453,3 +459,21 @@ class cast(_Type): +class CustomPythonMethod(object): + def __init__(self, fn): + src = inspect.getsource(fn) + lines = textwrap.dedent(src).splitlines() + for i, line in enumerate(lines): + if not line.startswith('@'): + break + self.sourcelines = lines[i:] + + def compile_py(self, writer): + for line in self.sourcelines: + writer.println(line) + +class CustomPythonStaticMethod(CustomPythonMethod): + def compile_py(self, writer): + writer.println('@staticmethod') + super(CustomPythonStaticMethod, self).compile_py(writer) + diff --git a/newbinding/src/BasicBlock.py b/newbinding/src/BasicBlock.py index c7221a5..b0716cd 100644 --- a/newbinding/src/BasicBlock.py +++ b/newbinding/src/BasicBlock.py @@ -1,6 +1,7 @@ from binding import * from namespace import llvm from Value import Function, BasicBlock +from Instruction import Instruction, TerminatorInst from LLVMContext import LLVMContext from StringRef import StringRef @@ -12,6 +13,8 @@ class BasicBlock: ptr(BasicBlock)) getParent = Method(ptr(Function)) + getTerminator = Method(ptr(TerminatorInst)) + empty = Method(cast(Bool, bool)) dropAllReferences = Method() isLandingPad = Method(cast(Bool, bool)) diff --git a/newbinding/src/DerivedTypes.py b/newbinding/src/DerivedTypes.py index c57e01b..efce8b8 100644 --- a/newbinding/src/DerivedTypes.py +++ b/newbinding/src/DerivedTypes.py @@ -9,8 +9,23 @@ FunctionType = llvm.Class(Type) @FunctionType class FunctionType: _include_ = 'llvm/DerivedTypes.h' - get = StaticMethod(ptr(FunctionType), ptr(Type), cast(bool, Bool)) - get |= StaticMethod(ptr(FunctionType), ptr(Type), ref(SmallVector_Type), cast(bool, Bool)) + + _get = StaticMethod(ptr(FunctionType), ptr(Type), cast(bool, Bool)) + _get |= StaticMethod(ptr(FunctionType), ptr(Type), ref(SmallVector_Type), + cast(bool, Bool)) + _get.realname = 'get' + + @CustomPythonStaticMethod + def get(*args): + import extra + if len(args) == 3: + typelist = args[1] + sv = extra.make_small_vector_from_types(*typelist) + return FunctionType._get(args[0], sv, args[2]) + else: + return FunctionType._get(*args) + + isVarArg = Method(cast(Bool, bool)) getReturnType = Method(ptr(Type)) getParamType = Method(ptr(Type), cast(int, Unsigned)) diff --git a/newbinding/src/Value.py b/newbinding/src/Value.py index 3dd5644..5345337 100644 --- a/newbinding/src/Value.py +++ b/newbinding/src/Value.py @@ -37,3 +37,10 @@ class Value: hasOneUse = Method(cast(Bool, bool)) hasNUses = Method(cast(Bool, bool), cast(int, Unsigned)) isUsedInBasicBlock = Method(cast(Bool, bool), BasicBlock) + + @CustomPythonMethod + def __str__(self): + import extra + os = extra.make_raw_ostream_for_printing() + self.print_(os, None) + return os.str() diff --git a/newbinding/test2.py b/newbinding/test2.py index 810a7ba..3e54aee 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -30,24 +30,18 @@ fnty = api.FunctionType.get(int1ty, False) fnty.dump() types = [int1ty, api.Type.getIntNTy(context, 21)] -svt = extra.make_small_vector_from_types(*types) -fnty = api.FunctionType.get(int1ty, svt, False) +fnty = api.FunctionType.get(int1ty, types, False) -os = extra.make_raw_ostream_for_printing() -fnty.print_(os) -print os.str() +print fnty const = m.getOrInsertFunction("foo", fnty) fn = extra.downcast(const, api.Function) -os = extra.make_raw_ostream_for_printing() -fn.print_(os, None) -print os.str() +print fn assert fn.hasName() assert 'foo' == fn.getName() fn.setName('bar') assert 'bar' == fn.getName() -os = extra.make_raw_ostream_for_printing() assert fn.getReturnType() is int1ty assert fnty is fn.getFunctionType() @@ -56,14 +50,24 @@ assert fn.isVarArg() == False assert fn.getIntrinsicID() == 0 assert not fn.isIntrinsic() -print fn.list_use() +fn_uselist = fn.list_use() +assert isinstance(fn_uselist, list) +assert len(fn_uselist) == 0 builder = api.IRBuilder.new(context) print builder bb = api.BasicBlock.Create(context, "entry", fn, None) +assert bb.empty() builder.SetInsertPoint(bb) +assert bb.getTerminator() is None + builder.CreateRetVoid() -fn.dump() +assert not bb.empty() +assert bb.getTerminator() is not None + +print bb + + From 59d0dfddc733f44252c244bd0a5d496337f82000 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 28 Jan 2013 17:55:52 -0600 Subject: [PATCH 33/85] Continue to implement IRBuilder --- newbinding/capsule.py | 8 ++- newbinding/include/llvm_binding/extra.h | 87 ++++++++++++++++++++++--- newbinding/src/Argument.py | 9 +++ newbinding/src/Function.py | 4 +- newbinding/src/IRBuilder.py | 19 +++++- newbinding/src/SmallVector.py | 6 ++ newbinding/src/Value.py | 1 + newbinding/test2.py | 10 +-- 8 files changed, 125 insertions(+), 19 deletions(-) create mode 100644 newbinding/src/Argument.py diff --git a/newbinding/capsule.py b/newbinding/capsule.py index 47c32fb..eaef7da 100644 --- a/newbinding/capsule.py +++ b/newbinding/capsule.py @@ -52,8 +52,10 @@ def wrap(cap): '''Wrap a PyCapsule with the corresponding Wrapper class. If `cap` is not a PyCapsule, returns `cap` ''' - if not _capsule.check(cap): # bypass if cap is not a PyCapsule - return cap + if not _capsule.check(cap): + if isinstance(cap, list): + return map(wrap, cap) + return cap # bypass if cap is not a PyCapsule and not a list addr = _capsule.getPointer(cap) try: # find cached object by pointer address @@ -77,7 +79,7 @@ def wrap(cap): # do auto downcast pass else: - assert oldcls is newcls + assert oldcls is newcls, (cap, obj, oldcls, newcls) return obj def downcast(old, new): diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index 639a87c..9f2bd70 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -1,6 +1,7 @@ #include #include #include +#include #include @@ -11,12 +12,14 @@ namespace extra{ SmallVectorImpl *SV; public: static - raw_svector_ostream_helper* create(){ + raw_svector_ostream_helper* create() + { SmallVectorImpl* sv = new SmallVector(); return new raw_svector_ostream_helper(sv); } - ~raw_svector_ostream_helper(){ + ~raw_svector_ostream_helper() + { delete SV; } @@ -36,7 +39,8 @@ namespace extra{ } static -PyObject* make_raw_ostream_for_printing(PyObject* self, PyObject* args) { +PyObject* make_raw_ostream_for_printing(PyObject* self, PyObject* args) +{ using extra::raw_svector_ostream_helper; using llvm::raw_svector_ostream; @@ -49,7 +53,8 @@ PyObject* make_raw_ostream_for_printing(PyObject* self, PyObject* args) { } static -PyObject* make_small_vector_from_types(PyObject* self, PyObject* args) { +PyObject* make_small_vector_from_types(PyObject* self, PyObject* args) +{ using llvm::Type; typedef llvm::SmallVector SmallVector_Type; @@ -69,24 +74,88 @@ PyObject* make_small_vector_from_types(PyObject* self, PyObject* args) { return pycapsule_new(SV, "llvm::SmallVector"); } +static +PyObject* make_small_vector_from_values(PyObject* self, PyObject* args) +{ + using llvm::Value; + typedef llvm::SmallVector SmallVector_Value; + + SmallVector_Value* SV = new SmallVector_Value; + Py_ssize_t size = PyTuple_Size(args); + for (Py_ssize_t i = 0; i < size; ++i) { + PyObject* cap = PyTuple_GetItem(args, i); + if (!cap) { + return NULL; + } + Value* value = (Value*)PyCapsule_GetPointer(cap, "llvm::Value"); + if (!value) { + return NULL; + } + SV->push_back(value); + } + return pycapsule_new(SV, "llvm::SmallVector"); +} + + static PyMethodDef extra_methodtable[] = { #define method(func) { #func, (PyCFunction)func, METH_VARARGS, NULL } method( make_raw_ostream_for_printing ), method( make_small_vector_from_types ), + method( make_small_vector_from_values ), #undef method { NULL } }; //////////// - -PyObject* Value_use_iterator_to_list(llvm::Value* val){ - typedef llvm::Value::use_iterator iterator; +template +PyObject* iterator_to_pylist_deref(iterator begin, iterator end, + const char *capsuleName, const char *className) +{ PyObject* list = PyList_New(0); - for (iterator it = val->use_begin(), end = val->use_end(); it != end; ++it) { - PyObject* cap = pycapsule_new(*it, "llvm::Value", "llvm::User"); + for(; begin != end; ++begin) { + PyObject* cap = pycapsule_new(&*begin, capsuleName, className); PyList_Append(list, cap); } return list; } +template +PyObject* iterator_to_pylist(iterator begin, iterator end, + const char *capsuleName, const char *className) +{ + PyObject* list = PyList_New(0); + for(; begin != end; ++begin) { + PyObject* cap = pycapsule_new(*begin, capsuleName, className); + PyList_Append(list, cap); + } + return list; +} + +template +PyObject* iplist_to_pylist(iplist &IPL, const char * capsuleName, + const char* className){ + return iterator_to_pylist_deref(IPL.begin(), IPL.end(), capsuleName, + className); +} + +static +PyObject* Value_use_iterator_to_list(llvm::Value* val) +{ + return iterator_to_pylist(val->use_begin(), val->use_end(), + "llvm::Value", "llvm::User"); +} + +static +PyObject* Function_getArgumentList(llvm::Function* fn) +{ + return iplist_to_pylist(fn->getArgumentList(), "llvm::Value", + "llvm::Argument"); +} + +static +PyObject* Function_getBasicBlockList(llvm::Function* fn) +{ + return iplist_to_pylist(fn->getBasicBlockList(), "llvm::Value", + "llvm::BasicBlock"); +} \ No newline at end of file diff --git a/newbinding/src/Argument.py b/newbinding/src/Argument.py new file mode 100644 index 0000000..08b35be --- /dev/null +++ b/newbinding/src/Argument.py @@ -0,0 +1,9 @@ +from binding import * +from namespace import llvm +from Value import Argument + +@Argument +class Argument: + _include_ = 'llvm/Argument.h' + + diff --git a/newbinding/src/Function.py b/newbinding/src/Function.py index f069e30..5cebf84 100644 --- a/newbinding/src/Function.py +++ b/newbinding/src/Function.py @@ -1,6 +1,6 @@ from binding import * from namespace import llvm -from Value import GlobalValue, Constant, Function +from Value import GlobalValue, Constant, Function, Argument from Type import Type from DerivedTypes import FunctionType from LLVMContext import LLVMContext @@ -17,3 +17,5 @@ class Function: getIntrinsicID = Method(cast(Unsigned, int)) isIntrinsic = Method(cast(Bool, bool)) + getArgumentList = CustomMethod('Function_getArgumentList', PyObjectPtr) + getBasicBlockList = CustomMethod('Function_getBasicBlockList', PyObjectPtr) diff --git a/newbinding/src/IRBuilder.py b/newbinding/src/IRBuilder.py index 0919a67..41e6681 100644 --- a/newbinding/src/IRBuilder.py +++ b/newbinding/src/IRBuilder.py @@ -2,7 +2,10 @@ from binding import * from namespace import llvm from LLVMContext import LLVMContext from BasicBlock import BasicBlock -from Instruction import ReturnInst +from Instruction import ReturnInst, CallInst +from SmallVector import SmallVector_Value +from StringRef import StringRef +from Value import Value IRBuilder = llvm.Class() @@ -19,3 +22,17 @@ class IRBuilder: isNamePreserving = Method(cast(Bool, bool)) CreateRetVoid = Method(ptr(ReturnInst)) + CreateRet = Method(ptr(ReturnInst), ptr(Value)) + + _CreateCall = Method(ptr(CallInst), ptr(Value), ref(SmallVector_Value), + cast(str, StringRef)) + _CreateCall |= Method(ptr(CallInst), ptr(Value), ref(SmallVector_Value)) + _CreateCall.realname = 'CreateCall' + + @CustomPythonMethod + def CreateCall(self, *args): + import extra + args = list(args) + valuelist = args[1] + args[1] = extra.make_small_vector_from_values(*valuelist) + return IRBuilder._CreateCall(self, *args) diff --git a/newbinding/src/SmallVector.py b/newbinding/src/SmallVector.py index 55dadb1..594faf8 100644 --- a/newbinding/src/SmallVector.py +++ b/newbinding/src/SmallVector.py @@ -5,3 +5,9 @@ from namespace import llvm class SmallVector_Type: _realname_ = 'SmallVector' delete = Destructor() + +@llvm.Class() +class SmallVector_Value: + _realname_ = 'SmallVector' + delete = Destructor() + diff --git a/newbinding/src/Value.py b/newbinding/src/Value.py index 5345337..5b907bd 100644 --- a/newbinding/src/Value.py +++ b/newbinding/src/Value.py @@ -8,6 +8,7 @@ from StringRef import StringRef Value = llvm.Class() # forward declarations +Argument = llvm.Class(Value) User = llvm.Class(Value) BasicBlock = llvm.Class(Value) Constant = llvm.Class(User) diff --git a/newbinding/test2.py b/newbinding/test2.py index 3e54aee..a7a4ddd 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -63,11 +63,11 @@ builder.SetInsertPoint(bb) assert bb.getTerminator() is None -builder.CreateRetVoid() +arg0, arg1 = fn.getArgumentList() +print arg0, arg1 -assert not bb.empty() -assert bb.getTerminator() is not None - -print bb +ret = builder.CreateCall(fn, [arg0, arg1], '') +builder.CreateRet(ret) +print fn From 437b1e949012595882f8fbb3065c0c7e4c9b0835 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 29 Jan 2013 17:47:15 -0600 Subject: [PATCH 34/85] All of DataLayout, IRBuilder and started on ExecutionEngine. --- newbinding/binding.py | 114 ++++++++- newbinding/capsule.py | 22 +- newbinding/codegen.py | 12 +- newbinding/gen.py | 11 +- .../include/llvm_binding/capsule_context.h | 10 + newbinding/include/llvm_binding/extra.h | 81 +++++- newbinding/src/CodeGen.py | 19 ++ newbinding/src/DataLayout.py | 97 +++++++ newbinding/src/ExecutionEngine.py | 34 +++ newbinding/src/GlobalVariable.py | 8 + newbinding/src/IRBuilder.py | 241 +++++++++++++++++- newbinding/src/Instruction.py | 32 ++- newbinding/src/JITMemoryManager.py | 7 + newbinding/src/Metadata.py | 7 + newbinding/src/Module.py | 3 +- newbinding/src/SmallVector.py | 4 + newbinding/src/TargetSelect.py | 8 + newbinding/src/Type.py | 4 + newbinding/src/Value.py | 1 + newbinding/test2.py | 14 + 20 files changed, 688 insertions(+), 41 deletions(-) create mode 100644 newbinding/src/CodeGen.py create mode 100644 newbinding/src/DataLayout.py create mode 100644 newbinding/src/ExecutionEngine.py create mode 100644 newbinding/src/GlobalVariable.py create mode 100644 newbinding/src/JITMemoryManager.py create mode 100644 newbinding/src/Metadata.py create mode 100644 newbinding/src/TargetSelect.py diff --git a/newbinding/binding.py b/newbinding/binding.py index 6668452..f7d5ac4 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -5,11 +5,15 @@ import codegen as cg _rank = 0 namespaces = {} +RESERVED = frozenset(['None']) + class Namespace(object): def __init__(self, name): self.name = name + self.enums = [] self.classes = [] self.functions = [] + self.includes = set() namespaces[name] = self def Class(self, *bases): @@ -22,6 +26,13 @@ class Namespace(object): self.functions.append(fn) return fn + def Enum(self, name, *value_names): + enum = Enum(*value_names) + enum.parent = self + enum.name = name + self.enums.append(enum) + return enum + @property def fullname(self): return self.name @@ -43,11 +54,16 @@ class BuiltinTypes(_Type): def wrap(self, writer, var): return var + def unwrap(self, writer, var): + return var + Void = BuiltinTypes('void') Unsigned = BuiltinTypes('unsigned') +Uint64 = BuiltinTypes('uint64_t') Bool = BuiltinTypes('bool') ConstStdString = BuiltinTypes('const std::string') PyObjectPtr = BuiltinTypes('PyObject*') +PyObjectPtr.format='O' class Class(_Type): format = 'O' @@ -78,6 +94,7 @@ class Class(_Type): self.enums.append(v) v.name = k v.parent = self + setattr(self, k, v) elif isinstance(v, CustomPythonMethod): self.pymethods.append(v) elif k == '_include_': @@ -108,7 +125,7 @@ class Class(_Type): fmt = '{ "%(name)s", (PyCFunction)%(func)s, METH_VARARGS, NULL },' for meth in self.methods: name = meth.name - func = cg.mangle(meth.fullname) + func = meth.c_name writer.println(fmt % locals()) writer.println('{ NULL },') writer.println('};') @@ -161,9 +178,12 @@ class Class(_Type): return casted class Enum(object): + format = 'O' + def __init__(self, *value_names): self.parent = None self.value_names = value_names + self.includes = set() @property def fullname(self): @@ -191,11 +211,34 @@ class Enum(object): writer.raises(ValueError, 'Invalid enum %s' % v) return ret + def unwrap(self, writer, val): + tostring = 'PyString_AsString(%(val)s)' % locals() + string = writer.declare('const char*', tostring) + ret = writer.declare('%s::%s' % (self.parent, self.name)) + parent = self.parent + iffmt = 'if (string_equal(%(string)s, "%(v)s"))' + for i, v in enumerate(self.value_names): + with writer.block(iffmt % locals()): + fmt = '%(ret)s = %(parent)s::%(v)s;' + writer.println(fmt % locals()) + if i == 0: + iffmt = 'else ' + iffmt + with writer.block('else'): + writer.raises(ValueError, 'Invalid enum.') + return ret + + def compile_cpp(self, writer): + pass + def compile_py(self, writer): with writer.block('class %s:' % self.name): writer.println('_llvm_type_ = "%s"' % self.fullname) for v in self.value_names: - writer.println('%(v)s = "%(v)s"' % locals()) + if v in RESERVED: + k = '%s_' % v + else: + k = v + writer.println('%(k)s = "%(v)s"' % locals()) writer.println() class Method(object): @@ -236,11 +279,15 @@ class Method(object): def realname(self, v): self.__realname = v + @property + def c_name(self): + return cg.mangle("%s_%s" % (self.parent, self.name)) + def __str__(self): return self.fullname def compile_cpp(self, writer): - with writer.py_function(self.fullname): + with writer.py_function(self.c_name): if len(self.signatures) == 1: sig = self.signatures[0] retty = sig[0] @@ -270,13 +317,40 @@ class Method(object): with decl as (this, varargs): unwrap_this = writer.unwrap(this) unwrapped = writer.unwrap_many(varargs) + self.process_ownedptr_args(writer, unwrapped) + func = '.'.join([self.parent.name, self.name]) ret = writer.call('_api.%s' % func, args=(unwrap_this,), varargs=unwrapped) - wrapped = writer.wrap(ret) + + wrapped = writer.wrap(ret, self.is_return_ownedptr()) + writer.return_value(wrapped) writer.println() + def require_only(self, num): + '''Require only "num" of argument. + ''' + assert len(self.signatures) == 1 + sig = self.signatures[0] + ret = sig[0] + args = sig[1:] + arg_ct = len(args) + + for i in range(num, arg_ct): + self._add_signature(ret, *args[:i]) + + return self + + def is_return_ownedptr(self): + retty = self.signatures[0][0] + return isinstance(retty, ownedptr) + + def process_ownedptr_args(self, writer, unwrapped): + argtys = self.signatures[0][1:] + for i, ty in enumerate(argtys): + if isinstance(ty, ownedptr): + writer.release_ownership('%s[%d]' % (unwrapped, i)) class CustomMethod(Method): def __init__(self, methodname, retty, *argtys): @@ -289,7 +363,6 @@ class CustomMethod(Method): writer.return_value(retty.wrap(writer, ret)) - class StaticMethod(Method): def compile_cpp_body(self, writer, retty, argtys): @@ -307,12 +380,24 @@ class StaticMethod(Method): decl = writer.function(self.name, varargs='args') with decl as varargs: unwrapped = writer.unwrap_many(varargs) + self.process_ownedptr_args(writer, unwrapped) + func = '.'.join([self.parent.name, self.name]) ret = writer.call('_api.%s' % func, varargs=unwrapped) - wrapped = writer.wrap(ret) + wrapped = writer.wrap(ret, self.is_return_ownedptr()) writer.return_value(wrapped) writer.println() +class CustomStaticMethod(StaticMethod): + def __init__(self, methodname, retty, *argtys): + super(CustomStaticMethod, self).__init__(retty, *argtys) + self.methodname = methodname + + def compile_cpp_body(self, writer, retty, argtys): + args = writer.parse_arguments('args', *argtys) + ret = writer.call(self.methodname, retty.fullname, *args) + writer.return_value(retty.wrap(writer, ret)) + class Function(Method): _kind_ = 'func' @@ -329,10 +414,11 @@ class Function(Method): def compile_py(self, writer): 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('::', '.') ret = writer.call('_api.%s' % func, varargs=unwrapped) - wrapped = writer.wrap(ret) + wrapped = writer.wrap(ret, self.is_return_ownedptr()) writer.return_value(wrapped) writer.println() @@ -400,10 +486,14 @@ class ptr(_Type): def __init__(self, element): assert isinstance(element, Class) self.element = element + self.const = False @property def fullname(self): - return '%s*' % self.element + if self.const: + return 'const %s*' % self.element + else: + return '%s*' % self.element @property def format(self): @@ -420,6 +510,13 @@ class ptr(_Type): return writer.pycapsule_new(val, self.element.capsule_name, self.element.fullname) +class ownedptr(ptr): + pass + +def const(ptr): + ptr.const = True + return ptr + class cast(_Type): format = 'O' @@ -458,7 +555,6 @@ class cast(_Type): return ret - class CustomPythonMethod(object): def __init__(self, fn): src = inspect.getsource(fn) diff --git a/newbinding/capsule.py b/newbinding/capsule.py index eaef7da..f489c7f 100644 --- a/newbinding/capsule.py +++ b/newbinding/capsule.py @@ -23,10 +23,11 @@ class WeakRef(ref): _pyclasses = {} _addr2obj = WeakValueDictionary() -_owners = {} +_owners = {} # address to weak reference def _sentry(ptr): - assert _capsule.check(ptr) + if not _capsule.check(ptr): + raise ValueError('Must provide a PyCapsule object.') def classof(cap): cls = _capsule.getClassName(cap) @@ -38,17 +39,16 @@ def _capsule_destructor(weak): addr = _capsule.getPointer(cap) cls = _capsule.getClassName(cap) logger.debug("destroy pointer 0x%08X to %s", addr, cls) - weak.dtor(cap) +# weak.dtor(cap) del _owners[addr] def release_ownership(old): addr = _capsule.getPointer(old) - if hasattr(old, '_delete_'): - oldweak = _owners[addr] - oldweak.owning = False # dis-own - del _owners[addr] + oldweak = _owners[addr] + oldweak.owning = False # dis-own + del _owners[addr] -def wrap(cap): +def wrap(cap, owned=False): '''Wrap a PyCapsule with the corresponding Wrapper class. If `cap` is not a PyCapsule, returns `cap` ''' @@ -66,7 +66,8 @@ def wrap(cap): obj = cls(cap) _addr2obj[addr] = obj # cache object by address # set ownership if *cls* defines *_delete_* - if hasattr(cls, '_delete_'): + if not owned and hasattr(cls, '_delete_'): + assert addr not in _owners, "has existing owner" weak = WeakRef(obj, _capsule_destructor) _owners[addr] = weak weak.capsule = cap @@ -84,10 +85,11 @@ def wrap(cap): def downcast(old, new): assert old is not new + assert _capsule.getPointer(old) not in _owners oldcls = classof(old) newcls = classof(new) assert issubclass(newcls, oldcls) - release_ownership(old) + # release_ownership(old) del _addr2obj[_capsule.getPointer(old)] # clear cache return wrap(new) diff --git a/newbinding/codegen.py b/newbinding/codegen.py index 7652447..5a31e38 100644 --- a/newbinding/codegen.py +++ b/newbinding/codegen.py @@ -104,10 +104,9 @@ class CodeWriterBase(object): @contextlib.contextmanager def py_function(self, name): - mangled = mangle(name) self.println('static') self.println('PyObject*') - with self.block('%(mangled)s(PyObject* self, PyObject* args)' % locals()): + with self.block('%(name)s(PyObject* self, PyObject* args)' % locals()): self.used_symbols.add('self') self.used_symbols.add('args') yield @@ -175,7 +174,7 @@ class CppCodeWriter(CodeWriterBase): arglist = ', '.join(args) stmt = '%(func)s(%(arglist)s)' % locals() if retty == 'void': - self.println(stmt) + self.println(stmt + ';') else: return self.declare(retty, stmt) @@ -247,6 +246,9 @@ class PyCodeWriter(CodeWriterBase): yield self.used_symbols = self.old + def release_ownership(self, val): + self.println('capsule.release_ownership(%(val)s)' % locals()) + def unwrap_many(self, args): unwrapped = self.new_symbol('unwrapped') self.println('%(unwrapped)s = map(capsule.unwrap, %(args)s)' % locals()) @@ -255,9 +257,9 @@ class PyCodeWriter(CodeWriterBase): def unwrap(self, val): return self.call('capsule.unwrap', args=(val,), ret='unwrapped') - def wrap(self, val): + def wrap(self, val, owned): wrapped = self.new_symbol('wrapped') - self.println('%(wrapped)s = capsule.wrap(%(val)s)' % locals()) + self.println('%(wrapped)s = capsule.wrap(%(val)s, %(owned)s)' % locals()) return wrapped def call(self, func, args=(), varargs=None, ret='ret'): diff --git a/newbinding/gen.py b/newbinding/gen.py index d9fc14f..47f5655 100644 --- a/newbinding/gen.py +++ b/newbinding/gen.py @@ -39,6 +39,7 @@ populate_submodules(module, submodules); def populate_headers(println): includes = [ + 'cstring', 'llvm_binding/conversion.h', 'llvm_binding/binding.h', 'llvm_binding/capsule_context.h', @@ -70,6 +71,9 @@ def main(): for cls in ns.classes: print cls units.append(cls) + for enum in ns.enums: + print enum + units.append(enum) # add extra stuffs downcastlist = [] @@ -84,7 +88,7 @@ def main(): units.append(fn) - # generate cpp source + # Generate C++ source with open('%s.cpp' % outputfilename, 'w') as cppfile: println = wrap_println_from_file(cppfile) @@ -93,6 +97,8 @@ def main(): # required headers includes = set() + for ns in namespaces.values(): + includes |= ns.includes for u in units: includes |= u.includes @@ -128,7 +134,7 @@ static for u in units: if isinstance(u, Function): name = u.name - func = codegen.mangle(u.fullname) + func = u.c_name writer.println(fmt % locals()) writer.println('{ NULL },') writer.println('};') @@ -154,6 +160,7 @@ static println(extension_entry % {'module': '_api', 'methtable': 'methtable'}) + # Generate Python source with open('%s.py' % outputfilename, 'w') as pyfile: println = wrap_println_from_file(pyfile) println('import _api, capsule') diff --git a/newbinding/include/llvm_binding/capsule_context.h b/newbinding/include/llvm_binding/capsule_context.h index ed63e43..6ed1381 100644 --- a/newbinding/include/llvm_binding/capsule_context.h +++ b/newbinding/include/llvm_binding/capsule_context.h @@ -39,6 +39,16 @@ PyObject* pycapsule_new(void* ptr, } +static +PyObject* pycapsule_new(const void* ptr, + const char* basename, + const char* classname=NULL) +{ + // Use const_cast to strip the constantness. + // Let the user take the responsibility. + return pycapsule_new(const_cast(ptr), basename, classname); +} + #endif //LLVMPY_CAPSULE_CONTEXT_H_ diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index 9f2bd70..b5edd2c 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -3,7 +3,7 @@ #include #include #include - +#include namespace extra{ using namespace llvm; @@ -97,11 +97,34 @@ PyObject* make_small_vector_from_values(PyObject* self, PyObject* args) } +static +PyObject* make_small_vector_from_unsigned(PyObject* self, PyObject* args) +{ + using llvm::Value; + typedef llvm::SmallVector SmallVector_Unsigned; + + SmallVector_Unsigned* SV = new SmallVector_Unsigned; + Py_ssize_t size = PyTuple_Size(args); + for (Py_ssize_t i = 0; i < size; ++i) { + PyObject* item = PyTuple_GetItem(args, i); + if (!item) { + return NULL; + } + unsigned value = PyLong_AsUnsignedLong(item); + if (PyErr_Occurred()){ + return NULL; + } + SV->push_back(value); + } + return pycapsule_new(SV, "llvm::SmallVector"); +} + static PyMethodDef extra_methodtable[] = { #define method(func) { #func, (PyCFunction)func, METH_VARARGS, NULL } method( make_raw_ostream_for_printing ), method( make_small_vector_from_types ), method( make_small_vector_from_values ), + method( make_small_vector_from_unsigned ), #undef method { NULL } }; @@ -139,11 +162,20 @@ PyObject* iplist_to_pylist(iplist &IPL, const char * capsuleName, className); } +static +bool string_equal(const char *A, const char *B){ + for (; *A and *B; ++A, ++B) { + if (*A != *B) return false; + } + return true; +} + +//////////// static PyObject* Value_use_iterator_to_list(llvm::Value* val) { return iterator_to_pylist(val->use_begin(), val->use_end(), - "llvm::Value", "llvm::User"); + "llvm::Value", "llvm::User"); } static @@ -158,4 +190,47 @@ PyObject* Function_getBasicBlockList(llvm::Function* fn) { return iplist_to_pylist(fn->getBasicBlockList(), "llvm::Value", "llvm::BasicBlock"); -} \ No newline at end of file +} + +/* + * errout --- can be any file object + * + */ +static +llvm::ExecutionEngine* ExecutionEngine_create( + llvm::Module* M, + bool ForceInterpreter = false, + PyObject* errout = 0, + llvm::CodeGenOpt::Level OptLevel = llvm::CodeGenOpt::Default, + bool GVsWithCode = true) +{ + using namespace llvm; + std::string ErrorStr; + ExecutionEngine *ee = ExecutionEngine::create(M, ForceInterpreter, + &ErrorStr, OptLevel, + GVsWithCode); + PyFile_WriteString(ErrorStr.c_str(), errout); + return ee; +} + +/* + * errout --- can be any file object + * + */ +static +llvm::ExecutionEngine* ExecutionEngine_createJIT( + llvm::Module* M, + PyObject* errout = 0, + llvm::JITMemoryManager* JMM = 0, + llvm::CodeGenOpt::Level OL = llvm::CodeGenOpt::Default, + bool GCsWithCode = true, + llvm::Reloc::Model RM = llvm::Reloc::Default, + llvm::CodeModel::Model CMM = llvm::CodeModel::JITDefault) +{ + using namespace llvm; + std::string ErrorStr; + ExecutionEngine *ee = ExecutionEngine::createJIT(M, &ErrorStr, JMM, OL, + GCsWithCode, RM, CMM); + PyFile_WriteString(ErrorStr.c_str(), errout); + return ee; +} diff --git a/newbinding/src/CodeGen.py b/newbinding/src/CodeGen.py new file mode 100644 index 0000000..06821aa --- /dev/null +++ b/newbinding/src/CodeGen.py @@ -0,0 +1,19 @@ +from binding import * +from namespace import llvm + +@llvm.Class() +class Reloc: + Model = Enum('Default', 'Static', 'PIC_', 'DynamicNoPIC') + +@llvm.Class() +class CodeModel: + Model = Enum('Default', 'JITDefault', 'Small', 'Kernel', 'Medium', 'Large') + +@llvm.Class() +class TLSModel: + Model = Enum('GeneralDynamic', 'LocalDynamic', 'InitialExec', 'LocalExec') + +@llvm.Class() +class CodeGenOpt: + 'Actually a namespace' + Level = Enum('None', 'Less', 'Default', 'Aggressive') diff --git a/newbinding/src/DataLayout.py b/newbinding/src/DataLayout.py new file mode 100644 index 0000000..a1ef8bc --- /dev/null +++ b/newbinding/src/DataLayout.py @@ -0,0 +1,97 @@ +from binding import * +from namespace import llvm +from LLVMContext import LLVMContext +from StringRef import StringRef +from Module import Module +from Type import Type, IntegerType, StructType +from SmallVector import SmallVector_Value +from GlobalVariable import GlobalVariable + +DataLayout = llvm.Class() +StructLayout = llvm.Class() + +@DataLayout +class DataLayout: + _include_ = 'llvm/DataLayout.h' + + _new_string = Constructor(cast(str, StringRef)) + _new_module = Constructor(ptr(Module)) + + @CustomPythonStaticMethod + def new(arg): + if isinstance(arg, Module): + return DataLayout._new_module(arg) + else: + return DataLayout._new_string(arg) + + delete = Destructor() + + isLittleEndian = Method(cast(Bool, bool)) + isBigEndian = Method(cast(Bool, bool)) + + getStringRepresentation = Method(cast(StringRef, str)) + + @CustomPythonMethod + def __str__(self): + return self.getStringRepresentation() + + isLegalInteger = Method(cast(Bool, bool), cast(int, Unsigned)) + isIllegalInteger = Method(cast(Bool, bool), cast(int, Unsigned)) + exceedsNaturalStackAlignment = Method(cast(Bool, bool), cast(int, Unsigned)) + fitsInLegalInteger = Method(cast(Bool, bool), cast(int, Unsigned)) + + getPointerABIAlignment = Method(cast(Unsigned, int), + cast(int, Unsigned)).require_only(0) + getPointerPrefAlignment = Method(cast(Unsigned, int), + cast(int, Unsigned)).require_only(0) + getPointerSize = Method(cast(Unsigned, int), + cast(int, Unsigned)).require_only(0) + getPointerSizeInBits = Method(cast(Unsigned, int), + cast(int, Unsigned)).require_only(0) + + getTypeSizeInBits = Method(cast(Uint64, int), ptr(Type)) + getTypeStoreSize = Method(cast(Uint64, int), ptr(Type)) + getTypeStoreSizeInBits = Method(cast(Uint64, int), ptr(Type)) + getTypeAllocSize = Method(cast(Uint64, int), ptr(Type)) + getTypeAllocSizeInBits = Method(cast(Uint64, int), ptr(Type)) + + getABITypeAlignment = Method(cast(Unsigned, int), ptr(Type)) + getABIIntegerTypeAlignment = Method(cast(Unsigned, int), cast(int, Unsigned)) + getCallFrameTypeAlignment = Method(cast(Unsigned, int), ptr(Type)) + getPrefTypeAlignment = Method(cast(Unsigned, int), ptr(Type)) + getPreferredTypeAlignmentShift = Method(cast(Unsigned, int), ptr(Type)) + + _getIntPtrType = Method(ptr(IntegerType), + ref(LLVMContext), cast(int, Unsigned)) + _getIntPtrType.require_only(1) + _getIntPtrType.realname = 'getIntPtrType' + + _getIntPtrType2 = Method(ptr(Type), ptr(Type)) + _getIntPtrType2.realname = 'getIntPtrType' + + @CustomPythonMethod + def getIntPtrType(self, *args): + if isinstance(args[0], LLVMContext): + return self._getIntPtrType(*args) + else: + return self._getIntPtrType(*args) + + _getIndexedOffset = Method(cast(Uint64, int), ptr(Type), + ref(SmallVector_Value)) + _getIndexedOffset.realname = 'getIndexedOffset' + + @CustomPythonMethod + def getIndexedOffset(self, *args): + import extra + args = list(args) + args[1] = extra.make_small_vector_from_values(args[1]) + return self.getIndexedOffset(*args) + + getStructLayout = Method(const(ptr(StructLayout)), ptr(StructType)) + + getPreferredAlignment = Method(cast(Unsigned, int), ptr(GlobalVariable)) + getPreferredAlignmentLog = Method(cast(Unsigned, int), ptr(GlobalVariable)) + +@StructLayout +class StructLayout: + pass diff --git a/newbinding/src/ExecutionEngine.py b/newbinding/src/ExecutionEngine.py new file mode 100644 index 0000000..0fbe387 --- /dev/null +++ b/newbinding/src/ExecutionEngine.py @@ -0,0 +1,34 @@ +from binding import * +from namespace import llvm +from Module import Module +from JITMemoryManager import JITMemoryManager +from CodeGen import CodeGenOpt, Reloc, CodeModel +from DataLayout import DataLayout + +ExecutionEngine = llvm.Class() + +@ExecutionEngine +class ExecutionEngine: + _include_ = ('llvm/ExecutionEngine/ExecutionEngine.h', + 'llvm/ExecutionEngine/JIT.h') # force linking of jit + + delete = Destructor() + + create = CustomStaticMethod('ExecutionEngine_create', + ptr(ExecutionEngine), + ownedptr(Module), cast(bool, Bool), + PyObjectPtr, CodeGenOpt.Level, + cast(bool, Bool)).require_only(1) + + createJIT = CustomStaticMethod('ExecutionEngine_createJIT', + ptr(ExecutionEngine), + ownedptr(Module), PyObjectPtr, + ptr(JITMemoryManager), + CodeGenOpt.Level, + cast(bool, Bool), + Reloc.Model, + CodeModel.Model).require_only(1) + + addModule = Method(Void, ptr(Module)) + getDataLayout = Method(const(ownedptr(DataLayout))) + removeModule = Method(cast(Bool, bool), ptr(Module)) diff --git a/newbinding/src/GlobalVariable.py b/newbinding/src/GlobalVariable.py new file mode 100644 index 0000000..548a8d1 --- /dev/null +++ b/newbinding/src/GlobalVariable.py @@ -0,0 +1,8 @@ +from binding import * +from namespace import llvm +from GlobalValue import GlobalValue + +@llvm.Class(GlobalValue) +class GlobalVariable: + pass + diff --git a/newbinding/src/IRBuilder.py b/newbinding/src/IRBuilder.py index 41e6681..cea94ce 100644 --- a/newbinding/src/IRBuilder.py +++ b/newbinding/src/IRBuilder.py @@ -2,10 +2,16 @@ from binding import * from namespace import llvm from LLVMContext import LLVMContext from BasicBlock import BasicBlock -from Instruction import ReturnInst, CallInst -from SmallVector import SmallVector_Value +from Instruction import ReturnInst, CallInst, BranchInst, SwitchInst +from Instruction import IndirectBrInst, InvokeInst, ResumeInst, PHINode +from Instruction import UnreachableInst, AllocaInst, LoadInst, StoreInst +from Instruction import FenceInst, AtomicCmpXchgInst, AtomicRMWInst, CmpInst +from Instruction import LandingPadInst, VAArgInst +from Instruction import AtomicOrdering, SynchronizationScope +from SmallVector import SmallVector_Value, SmallVector_Unsigned from StringRef import StringRef -from Value import Value +from Value import Value, MDNode +from Type import Type, IntegerType IRBuilder = llvm.Class() @@ -24,15 +30,238 @@ class IRBuilder: CreateRetVoid = Method(ptr(ReturnInst)) CreateRet = Method(ptr(ReturnInst), ptr(Value)) - _CreateCall = Method(ptr(CallInst), ptr(Value), ref(SmallVector_Value), + CreateBr = Method(ptr(BranchInst), ptr(BasicBlock)) + + + CreateCondBr = Method(ptr(BranchInst), ptr(Value), ptr(BasicBlock), + ptr(BasicBlock), ptr(MDNode)).require_only(3) + + CreateSwitch = Method(ptr(SwitchInst), ptr(Value), ptr(BasicBlock), + cast(int, Unsigned), ptr(MDNode)).require_only(2) + + CreateIndirectBr = Method(ptr(IndirectBrInst), ptr(Value), + cast(int, Unsigned)).require_only(1) + + CreateInvoke = Method(ptr(InvokeInst), ptr(Value), ptr(BasicBlock), + ptr(BasicBlock), ref(SmallVector_Value), + cast(str, StringRef)).require_only(4) + + CreateResume = Method(ptr(ResumeInst), ptr(Value)) + + CreateUnreachable = Method(ptr(UnreachableInst)) + + def _binop_has_nsw_nuw(): + sig = [ptr(Value), ptr(Value), ptr(Value), cast(str, StringRef), + cast(bool, Bool), cast(bool, Bool)] + op = Method(*sig).require_only(2) + return op + + CreateAdd = _binop_has_nsw_nuw() + CreateSub = _binop_has_nsw_nuw() + CreateMul = _binop_has_nsw_nuw() + CreateShl = _binop_has_nsw_nuw() + + def _binop_is_exact(): + sig = [ptr(Value), ptr(Value), ptr(Value), cast(str, StringRef), + cast(bool, Bool)] + op = Method(*sig).require_only(2) + return op + + CreateUDiv = _binop_is_exact() + CreateSDiv = _binop_is_exact() + CreateLShr = _binop_is_exact() + CreateAShr = _binop_is_exact() + + def _binop_basic(): + sig = [ptr(Value), ptr(Value), ptr(Value), cast(str, StringRef)] + op = Method(*sig).require_only(2) + return op + + CreateURem = _binop_basic() + CreateSRem = _binop_basic() + CreateAnd = _binop_basic() + CreateOr = _binop_basic() + CreateXor = _binop_basic() + + def _float_binop(): + sig = [ptr(Value), ptr(Value), ptr(Value), cast(str, StringRef), + ptr(MDNode)] + op = Method(*sig).require_only(2) + return op + + CreateFAdd = _float_binop() + CreateFSub = _float_binop() + CreateFMul = _float_binop() + CreateFDiv = _float_binop() + CreateFRem = _float_binop() + + def _unop_has_nsw_nuw(): + sig = [ptr(Value), ptr(Value), cast(str, StringRef), + cast(bool, Bool), cast(bool, Bool)] + op = Method(*sig).require_only(1) + return op + + CreateNeg = _unop_has_nsw_nuw() + + def _float_unop(): + sig = [ptr(Value), ptr(Value), cast(str, StringRef), ptr(MDNode)] + op = Method(*sig).require_only(1) + return op + + CreateFNeg = _float_unop() + + CreateNot = Method(ptr(Value), + ptr(Value), cast(str, StringRef)).require_only(1) + + + CreateAlloca = Method(ptr(AllocaInst), ptr(Type), ptr(Value), + cast(str, StringRef)).require_only(2) + + CreateLoad = Method(ptr(LoadInst), + ptr(Value), cast(str, StringRef)).require_only(1) + + CreateStore = Method(ptr(StoreInst), ptr(Value), ptr(Value), + cast(bool, Bool)).require_only(2) + + CreateAlignedLoad = Method(ptr(LoadInst), ptr(Value), cast(int, Unsigned), + cast(bool, Bool), cast(str, StringRef)) + CreateAlignedLoad.require_only(2) + + CreateAlignedStore = Method(ptr(StoreInst), ptr(Value), ptr(Value), + cast(int, Unsigned), cast(bool, Bool)) + CreateAlignedStore.require_only(3) + + CreateFence = Method(ptr(FenceInst), + AtomicOrdering, SynchronizationScope).require_only(1) + + CreateAtomicCmpXchg = Method(ptr(AtomicCmpXchgInst), ptr(Value), ptr(Value), + ptr(Value), AtomicOrdering, SynchronizationScope) + CreateAtomicCmpXchg.require_only(4) + + CreateAtomicRMW = Method(ptr(AtomicRMWInst), AtomicRMWInst.BinOp, + ptr(Value), ptr(Value), AtomicOrdering, + SynchronizationScope) + CreateAtomicRMW.require_only(4) + + _CreateGEP = Method(ptr(Value), ptr(Value), ref(SmallVector_Value), + cast(str, StringRef)) + _CreateGEP.require_only(2) + _CreateGEP.realname = 'CreateGEP' + + @CustomPythonMethod + def CreateGEP(self, *args): + import extra + args = list(args) + valuelist = args[1] + args[1] = extra.make_small_vector_from_values(*valuelist) + return self._CreateGEP(*args) + + _CreateInBoundsGEP = Method(ptr(Value), ptr(Value), ref(SmallVector_Value), cast(str, StringRef)) - _CreateCall |= Method(ptr(CallInst), ptr(Value), ref(SmallVector_Value)) + _CreateInBoundsGEP.require_only(2) + _CreateInBoundsGEP.realname = 'CreateInBoundsGEP' + + @CustomPythonMethod + def CreateInBoundsGEP(self, *args): + import extra + args = list(args) + valuelist = args[1] + args[1] = extra.make_small_vector_from_values(*valuelist) + return self._CreateInBoundsGEP(*args) + + CreateStructGEP = Method(ptr(Value), ptr(Value), cast(int, Unsigned), + cast(str, StringRef)).require_only(2) + + CreateGlobalStringPtr = Method(ptr(Value), cast(str, StringRef), + cast(str, StringRef)).require_only(1) + + def _value_type(): + sig = [ptr(Value), ptr(Value), ptr(Type), cast(str, StringRef)] + op = Method(*sig).require_only(2) + return op + + CreateTrunc = _value_type() + CreateZExt = _value_type() + CreateSExt = _value_type() + CreateZExtOrTrunc = Method(ptr(Value), ptr(Value), ptr(IntegerType), + cast(str, StringRef)).require_only(2) + CreateSExtOrTrunc = Method(ptr(Value), ptr(Value), ptr(IntegerType), + cast(str, StringRef)).require_only(2) + CreateFPToUI = _value_type() + CreateFPToSI = _value_type() + CreateUIToFP = _value_type() + CreateSIToFP = _value_type() + CreateFPTrunc = _value_type() + CreateFPExt = _value_type() + CreatePtrToInt = _value_type() + CreateIntToPtr = _value_type() + CreateBitCast = _value_type() + CreateZExtOrBitCast = _value_type() + CreateSExtOrBitCast = _value_type() + # Skip CreateCast + CreateTruncOrBitCast = _value_type() + CreateIntCast = Method(ptr(Value), ptr(Value), ptr(Type), cast(bool, Bool), + cast(str, StringRef)).require_only(3) + CreateFPCast = _value_type() + + _CreateCall = Method(ptr(CallInst), ptr(Value), ref(SmallVector_Value), + cast(str, StringRef)).require_only(2) _CreateCall.realname = 'CreateCall' + # Skip specialized CreateICmp* and CreateFCmp* + + CreateICmp = Method(ptr(Value), CmpInst.Predicate, ptr(Value), ptr(Value), + cast(str, StringRef)).require_only(3) + + CreateFCmp = Method(ptr(Value), CmpInst.Predicate, ptr(Value), ptr(Value), + cast(str, StringRef)).require_only(3) + + CreatePHI = Method(ptr(PHINode), ptr(Type), cast(int, Unsigned), + cast(str, StringRef)).require_only(2) + @CustomPythonMethod def CreateCall(self, *args): import extra args = list(args) valuelist = args[1] args[1] = extra.make_small_vector_from_values(*valuelist) - return IRBuilder._CreateCall(self, *args) + return self._CreateCall(*args) + + CreateSelect = Method(ptr(Value), ptr(Value), ptr(Value), ptr(Value), + cast(str, StringRef)).require_only(3) + + CreateVAArg = Method(ptr(VAArgInst), ptr(Value), ptr(Type), + cast(str, StringRef)).require_only(2) + + CreateExtractElement = _binop_basic() + + CreateInsertElement = Method(ptr(Value), ptr(Value), ptr(Value), ptr(Value), + cast(str, StringRef)).require_only(3) + + CreateShuffleVector = Method(ptr(Value), ptr(Value), ptr(Value), + ptr(Value), cast(str, StringRef)) + CreateShuffleVector.require_only(3) + + CreateExtractValue = Method(ptr(Value), ptr(Value), ref(SmallVector_Unsigned), + cast(str, StringRef)) + CreateExtractValue.require_only(2) + + CreateInsertValue = Method(ptr(Value), ptr(Value), ptr(Value), + ref(SmallVector_Unsigned), cast(str, StringRef)) + CreateInsertValue.require_only(3) + + CreateLandingPad = Method(ptr(LandingPadInst), ptr(Type), ptr(Value), + cast(int, Unsigned), cast(str, StringRef)) + CreateLandingPad.require_only(3) + + CreateIsNull = Method(ptr(Value), ptr(Value), cast(str, StringRef)) + CreateIsNull.require_only(1) + + CreateIsNotNull = Method(ptr(Value), ptr(Value), cast(str, StringRef)) + CreateIsNotNull.require_only(1) + + CreatePtrDiff = _binop_basic() + + # New in llvm 3.3 + #CreateVectorSplat = Method(ptr(Value), cast(int, Unsigned), ptr(Value), + # cast(str, StringRef)) diff --git a/newbinding/src/Instruction.py b/newbinding/src/Instruction.py index 310e19d..dda6b48 100644 --- a/newbinding/src/Instruction.py +++ b/newbinding/src/Instruction.py @@ -26,9 +26,9 @@ IntrinsicInst = llvm.Class(CallInst) FCmpInst = llvm.Class(CmpInst) ICmpInst = llvm.Class(CmpInst) - BranchInst = llvm.Class(TerminatorInst) IndirectBrInst = llvm.Class(TerminatorInst) +InvokeInst = llvm.Class(TerminatorInst) ResumeInst = llvm.Class(TerminatorInst) ReturnInst = llvm.Class(TerminatorInst) SwitchInst = llvm.Class(TerminatorInst) @@ -56,14 +56,14 @@ FPTruncInst = llvm.Class(CastInst) class Instruction: pass - @AtomicCmpXchgInst class AtomicCmpXchgInst: pass @AtomicRMWInst class AtomicRMWInst: - pass + BinOp = Enum('Xchg', 'Add', 'Sub', 'And', 'Nand', 'Or', 'Xor', 'Max', 'Min', + 'UMax', 'UMin', 'FIRST_BINOP', 'LAST_BINOP', 'BAD_BINOP') @BinaryOperator class BinaryOperator: @@ -75,7 +75,17 @@ class CallInst: @CmpInst class CmpInst: - pass + Predicate = Enum('FCMP_FALSE', 'FCMP_OEQ', 'FCMP_OGT', 'FCMP_OGE', + 'FCMP_OLT', 'FCMP_OLE', 'FCMP_ONE', 'FCMP_ORD', 'FCMP_UNO', + 'FCMP_UEQ', 'FCMP_UGT', 'FCMP_UGE', 'FCMP_ULT', 'FCMP_ULE', + 'FCMP_UNE', 'FCMP_TRUE', 'FIRST_FCMP_PREDICATE', + 'LAST_FCMP_PREDICATE', + 'BAD_FCMP_PREDICATE', + 'ICMP_EQ', 'ICMP_NE', 'ICMP_UGT', 'ICMP_UGE', 'ICMP_ULT', + 'ICMP_ULE', 'ICMP_SGT', 'ICMP_SGE', 'ICMP_SLT', 'ICMP_SLE', + 'FIRST_ICMP_PREDICATE', + 'LAST_ICMP_PREDICATE', + 'BAD_ICMP_PREDICATE',) @ExtractElementInst class ExtractElementInst: @@ -146,11 +156,14 @@ class ICmpInst: class BranchInst: pass - @IndirectBrInst class IndirectBrInst: pass +@InvokeInst +class InvokeInst: + pass + @ResumeInst class ResumeInst: pass @@ -228,3 +241,12 @@ class FPToUIInst: @FPTruncInst class FPTruncInst: pass + +AtomicOrdering = llvm.Enum('AtomicOrdering', + 'NotAtomic', 'Unordered', 'Monotonic', 'Acquire', + 'Release', 'AcquireRelease', + 'SequentiallyConsistent') + +SynchronizationScope = llvm.Enum('SynchronizationScope', + 'SingleThread', 'CrossThread') + diff --git a/newbinding/src/JITMemoryManager.py b/newbinding/src/JITMemoryManager.py new file mode 100644 index 0000000..f134735 --- /dev/null +++ b/newbinding/src/JITMemoryManager.py @@ -0,0 +1,7 @@ +from binding import * +from namespace import llvm + +@llvm.Class() +class JITMemoryManager: + pass + diff --git a/newbinding/src/Metadata.py b/newbinding/src/Metadata.py new file mode 100644 index 0000000..78dbe15 --- /dev/null +++ b/newbinding/src/Metadata.py @@ -0,0 +1,7 @@ +from binding import * +from namespace import llvm +from Value import MDNode + +@MDNode +class MDNode: + pass diff --git a/newbinding/src/Module.py b/newbinding/src/Module.py index 730b757..6cd6e2e 100644 --- a/newbinding/src/Module.py +++ b/newbinding/src/Module.py @@ -36,7 +36,8 @@ class Module: appendModuleInlineAsm = Method(Void, cast(str, StringRef)) # Function Accessors - getOrInsertFunction = Method(ptr(Constant), cast(str, StringRef), ptr(FunctionType)) + getOrInsertFunction = Method(ptr(Constant), cast(str, StringRef), + ptr(FunctionType)) # Utilities dump = Method(Void) diff --git a/newbinding/src/SmallVector.py b/newbinding/src/SmallVector.py index 594faf8..5b48aba 100644 --- a/newbinding/src/SmallVector.py +++ b/newbinding/src/SmallVector.py @@ -11,3 +11,7 @@ class SmallVector_Value: _realname_ = 'SmallVector' delete = Destructor() +@llvm.Class() +class SmallVector_Unsigned: + _realname_ = 'SmallVector' + delete = Destructor() diff --git a/newbinding/src/TargetSelect.py b/newbinding/src/TargetSelect.py new file mode 100644 index 0000000..cb2eb96 --- /dev/null +++ b/newbinding/src/TargetSelect.py @@ -0,0 +1,8 @@ +from binding import * +from namespace import llvm + +llvm.includes.add('llvm/Support/TargetSelect.h') + +llvm.Function('InitializeNativeTarget') +#llvm.Function('InitializeAllTargets') + diff --git a/newbinding/src/Type.py b/newbinding/src/Type.py index 45f9444..15b5e31 100644 --- a/newbinding/src/Type.py +++ b/newbinding/src/Type.py @@ -6,6 +6,7 @@ from raw_ostream import raw_ostream Type = llvm.Class() IntegerType = llvm.Class(Type) CompositeType = llvm.Class(Type) +StructType = llvm.Class(CompositeType) SequentialType = llvm.Class(CompositeType) PointerType = llvm.Class(SequentialType) @@ -113,3 +114,6 @@ class SequentialType: class PointerType: pass +@StructType +class StructType: + pass diff --git a/newbinding/src/Value.py b/newbinding/src/Value.py index 5b907bd..7460c90 100644 --- a/newbinding/src/Value.py +++ b/newbinding/src/Value.py @@ -9,6 +9,7 @@ from StringRef import StringRef Value = llvm.Class() # forward declarations Argument = llvm.Class(Value) +MDNode = llvm.Class(Value) User = llvm.Class(Value) BasicBlock = llvm.Class(Value) Constant = llvm.Class(User) diff --git a/newbinding/test2.py b/newbinding/test2.py index a7a4ddd..9492bb6 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -1,7 +1,11 @@ import api import extra import _capsule +from StringIO import StringIO api.capsule.set_debug(True) + + +api.InitializeNativeTarget() context = api.getGlobalContext() @@ -71,3 +75,13 @@ builder.CreateRet(ret) print fn +errio = StringIO() +ee = api.ExecutionEngine.createJIT(m) +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' + +assert datalayout_str == str(api.DataLayout.new(datalayout_str)) +assert datalayout_str == str(api.DataLayout.new(str(api.DataLayout.new(datalayout_str)))) + From 25b498c8fae73fa621179b76398c733b13200871 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 30 Jan 2013 14:44:17 -0600 Subject: [PATCH 35/85] Improve refct and management of capsules --- newbinding/capsule.py | 187 +++++++++++++++++++++++++++--------------- newbinding/extra.py | 18 ---- 2 files changed, 121 insertions(+), 84 deletions(-) diff --git a/newbinding/capsule.py b/newbinding/capsule.py index f489c7f..907fa15 100644 --- a/newbinding/capsule.py +++ b/newbinding/capsule.py @@ -1,5 +1,5 @@ -import _capsule -from weakref import WeakValueDictionary, ref +from weakref import WeakKeyDictionary, WeakValueDictionary, ref +from collections import defaultdict import logging logger = logging.getLogger(__name__) @@ -17,81 +17,106 @@ def set_debug(enabled): else: logger.setLevel(logging.WARNING) +def _capsule_weakref_dtor(item): + addr = item.pointer + _addr2refct[addr] -= 1 + refct = _addr2refct[addr] + assert refct >= 0, "RefCt drop below 0" + if refct == 0: + dtor = _addr2dtor.pop(addr, None) + if dtor is not None: + logger.debug('Destroy %s %s', item.name, hex(item.pointer)) + dtor(item.capsule) + +class Capsule(object): + "Wraps PyCapsule so that we can build weakref of it." + + from _capsule import check, getClassName, getName, getPointer + + def __init__(self, capsule): + assert Capsule.valid(capsule) + self.capsule = capsule + + weak = WeakRef(self, _capsule_weakref_dtor) + weak.pointer = self.pointer + weak.capsule = capsule + weak.name = self.name + _capsule2weak[self] = weak + _addr2refct[self.pointer] += 1 + + @property + def classname(self): + return Capsule.getClassName(self.capsule) + + @property + def name(self): + return Capsule.getName(self.capsule) + + @property + def pointer(self): + return Capsule.getPointer(self.capsule) + + @staticmethod + def valid(capsule): + return Capsule.check(capsule) + + def get_class(self): + return _pyclasses[self.classname] + + def instantiate(self): + cls = self.get_class() + return cls(self) + + def __eq__(self, other): + if self.pointer == other.pointer: + assert self.name == other.name + return True + else: + return False + + def __ne__(self, other): + return not (self == other) class WeakRef(ref): - __slots__ = 'capsule', 'dtor', 'owning' + pass +_addr2refct = defaultdict(lambda: 0) +_capsule2weak = WeakKeyDictionary() +_addr2dtor = {} _pyclasses = {} -_addr2obj = WeakValueDictionary() -_owners = {} # address to weak reference -def _sentry(ptr): - if not _capsule.check(ptr): - raise ValueError('Must provide a PyCapsule object.') - -def classof(cap): - cls = _capsule.getClassName(cap) - return _pyclasses[cls] - -def _capsule_destructor(weak): - if weak.owning: - cap = weak.capsule - addr = _capsule.getPointer(cap) - cls = _capsule.getClassName(cap) - logger.debug("destroy pointer 0x%08X to %s", addr, cls) -# weak.dtor(cap) - del _owners[addr] +# Cache {cls: {addr: obj}} +# NOTE: The same 'addr' may appear in multiple class bins. +_cache = defaultdict(WeakValueDictionary) def release_ownership(old): - addr = _capsule.getPointer(old) - oldweak = _owners[addr] - oldweak.owning = False # dis-own - del _owners[addr] + logger.debug('Release %s', old) + _addr2dtor[Capsule.getPointer(old)] = None + +def has_ownership(cap): + addr = Capsule.getPointer(cap) + return _addr2dtor.get(addr) is not None def wrap(cap, owned=False): '''Wrap a PyCapsule with the corresponding Wrapper class. If `cap` is not a PyCapsule, returns `cap` ''' - if not _capsule.check(cap): + if not Capsule.valid(cap): if isinstance(cap, list): return map(wrap, cap) return cap # bypass if cap is not a PyCapsule and not a list - addr = _capsule.getPointer(cap) - try: - # find cached object by pointer address - obj = _addr2obj[addr] - except KeyError: - # create new object and cache it - cls = classof(cap) - obj = cls(cap) - _addr2obj[addr] = obj # cache object by address - # set ownership if *cls* defines *_delete_* - if not owned and hasattr(cls, '_delete_'): - assert addr not in _owners, "has existing owner" - weak = WeakRef(obj, _capsule_destructor) - _owners[addr] = weak - weak.capsule = cap - weak.owning = True - weak.dtor = cls._delete_ - else: - oldcls = classof(obj._ptr) - newcls = classof(cap) - if issubclass(oldcls, newcls): - # do auto downcast - pass - else: - assert oldcls is newcls, (cap, obj, oldcls, newcls) - return obj -def downcast(old, new): - assert old is not new - assert _capsule.getPointer(old) not in _owners - oldcls = classof(old) - newcls = classof(new) - assert issubclass(newcls, oldcls) - # release_ownership(old) - del _addr2obj[_capsule.getPointer(old)] # clear cache - return wrap(new) + cap = Capsule(cap) + cls = cap.get_class() + addr = cap.pointer + try: # lookup cached object + return _cache[cls][addr] + except KeyError: + if not owned and hasattr(cls, '_delete_'): + _addr2dtor[addr] = cls._delete_ + obj = cap.instantiate() + _cache[cls][addr] = obj # cache it + return obj def unwrap(obj): '''Unwrap a Wrapper instance into the underlying PyCapsule. @@ -112,13 +137,43 @@ def register_class(clsname): class Wrapper(object): - __slots__ = '__ptr' + __slots__ = '__capsule' - def __init__(self, ptr): - _sentry(ptr) - self.__ptr = ptr + def __init__(self, capsule): + self.__capsule = capsule + + @property + def _capsule(self): + return self.__capsule @property def _ptr(self): - return self.__ptr + return self._capsule.capsule + def __eq__(self, other): + return self._capsule == other._capsule + + def __ne__(self, other): + return self._capsule != other._capsule + + def _downcast(self, newcls): + return downcast(self, newcls) + +def downcast(obj, cls): + import _api + if type(obj) is cls: + return obj + fromty = obj._llvm_type_ + toty = cls._llvm_type_ + logger.debug("Downcast %s to %s" , fromty, toty) + fname = 'downcast_%s_to_%s' % (fromty, toty) + fname = fname.replace('::', '_') + try: + caster = getattr(_api, fname) + except AttributeError: + fmt = "Downcast from %s to %s is not supported" + raise TypeError(fmt % (fromty, toty)) + old = unwrap(obj) + new = caster(old) + used_to_own = has_ownership(old) + return wrap(new, owned=not used_to_own) diff --git a/newbinding/extra.py b/newbinding/extra.py index a613296..d65f84c 100644 --- a/newbinding/extra.py +++ b/newbinding/extra.py @@ -22,22 +22,4 @@ def _init(glob): _init(globals()) -# -# Downcasts -# -def downcast(obj, cls): - if type(obj) is cls: - return obj - fromty = obj._llvm_type_ - toty = cls._llvm_type_ - fname = 'downcast_%s_to_%s' % (fromty, toty) - fname = fname.replace('::', '_') - try: - caster = getattr(_api, fname) - except AttributeError: - fmt = "Downcast from %s to %s is not supported" - raise TypeError(fmt % (fromty, toty)) - old = capsule.unwrap(obj) - new = caster(old) - return capsule.downcast(old, new) \ No newline at end of file From 78f9c9a61087f73e805d32b0a9bbb48ec5026827 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 30 Jan 2013 18:09:22 -0600 Subject: [PATCH 36/85] Completed binding for most of ExecutionEngine --- newbinding/binding.py | 8 ++ newbinding/include/llvm_binding/conversion.h | 117 ++++++++++++++++++- newbinding/include/llvm_binding/extra.h | 106 +++++++++++++++++ newbinding/src/ExecutionEngine.py | 60 ++++++++++ newbinding/src/GenericValue.py | 34 ++++++ newbinding/src/MachineCodeInfo.py | 13 +++ newbinding/src/Module.py | 7 ++ newbinding/src/Type.py | 14 +++ newbinding/test2.py | 41 +++++-- 9 files changed, 391 insertions(+), 9 deletions(-) create mode 100644 newbinding/src/GenericValue.py create mode 100644 newbinding/src/MachineCodeInfo.py diff --git a/newbinding/binding.py b/newbinding/binding.py index f7d5ac4..9ddedf3 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -59,9 +59,17 @@ class BuiltinTypes(_Type): Void = BuiltinTypes('void') Unsigned = BuiltinTypes('unsigned') +UnsignedLongLong = BuiltinTypes('unsigned long long') # used in llvm-3.2 +LongLong = BuiltinTypes('long long') +Float = BuiltinTypes('float') +Double = BuiltinTypes('double') Uint64 = BuiltinTypes('uint64_t') +Size_t = BuiltinTypes('size_t') +VoidPtr = BuiltinTypes('void*') Bool = BuiltinTypes('bool') +StdString = BuiltinTypes('std::string') ConstStdString = BuiltinTypes('const std::string') +ConstCharPtr = BuiltinTypes('const char*') PyObjectPtr = BuiltinTypes('PyObject*') PyObjectPtr.format='O' diff --git a/newbinding/include/llvm_binding/conversion.h b/newbinding/include/llvm_binding/conversion.h index 0e30c60..a1fc87c 100644 --- a/newbinding/include/llvm_binding/conversion.h +++ b/newbinding/include/llvm_binding/conversion.h @@ -25,6 +25,45 @@ int py_str_to(PyObject *strobj, llvm::StringRef &strref){ return 1; } +static +int py_str_to(PyObject *strobj, std::string &strref){ + // type check + if (!PyString_Check(strobj)) { + // raises TypeError + PyErr_SetString(PyExc_TypeError, "Expecting a str"); + return 0; + } + // get len and buffer + const char * buf = PyString_AsString(strobj); + if (!buf) { + // raises TypeError + return 0; + } + // set output + strref = std::string(buf); + // success + return 1; +} + + +static +int py_str_to(PyObject *strobj, const char* &strref){ + // type check + if (!PyString_Check(strobj)) { + // raises TypeError + PyErr_SetString(PyExc_TypeError, "Expecting a str"); + return 0; + } + // get buffer + strref = PyString_AsString(strobj); + if (!strref) { + // raises TypeError + return 0; + } + // success + return 1; +} + static int py_int_to(PyObject *intobj, unsigned & val){ if (!PyInt_Check(intobj)) { @@ -37,6 +76,70 @@ int py_int_to(PyObject *intobj, unsigned & val){ return 1; } +static +int py_int_to(PyObject *intobj, unsigned long long & val){ + if (!PyInt_Check(intobj)) { + // raise TypeError + puts(PyString_AsString(PyObject_Str(PyObject_Type(intobj)))); + PyErr_SetString(PyExc_TypeError, "Expecting an int 2"); + return 0; + } + val = PyInt_AsUnsignedLongLongMask(intobj); + // success + return 1; + +} + +static +int py_int_to(PyObject *intobj, size_t & val){ + unsigned long long ull; + if (py_int_to(intobj, ull)) { + val = (size_t)ull; + return 1; + } else { + return 0; + } +} + + +static +int py_int_to(PyObject *intobj, void* & val){ + if (!PyLong_Check(intobj)) { + // raise TypeError + PyErr_SetString(PyExc_TypeError, "Expecting an int"); + return 0; + } + val = PyLong_FromVoidPtr(intobj); + // success + return 1; +} + +static +int py_float_to(PyObject *floatobj, double & val){ + if (!PyFloat_Check(floatobj)) { + // raise TypeError + PyErr_SetString(PyExc_TypeError, "Expecting a float"); + return 0; + } + val = PyFloat_AsDouble(floatobj); + if (PyErr_Occurred()){ + return 0; + } + // success + return 1; +} + + +static +int py_float_to(PyObject *floatobj, float & val){ + double db; + int status = py_float_to(floatobj, db); + if (status) + val = db; + return status; +} + + static int py_bool_to(PyObject *boolobj, bool & val){ if (!PyBool_Check(boolobj)) { @@ -78,8 +181,18 @@ PyObject* py_bool_from(bool val){ } static -PyObject* py_int_from(int val){ - return PyInt_FromLong(val); +PyObject* py_int_from(const long long & val){ + return PyLong_FromLongLong(val); +} + +static +PyObject* py_int_from(void * addr){ + return PyLong_FromVoidPtr(addr); +} + +static +PyObject* py_float_from(const double& val) { + return PyFloat_FromDouble(val); } // casting diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index b5edd2c..7aacfde 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace extra{ using namespace llvm; @@ -234,3 +235,108 @@ llvm::ExecutionEngine* ExecutionEngine_createJIT( PyFile_WriteString(ErrorStr.c_str(), errout); return ee; } + +static +llvm::GenericValue* GenericValue_CreateInt(llvm::Type* Ty, unsigned long long N, + bool IsSigned) +{ + // Shamelessly copied from LLVM + llvm::GenericValue *GenVal = new llvm::GenericValue(); + GenVal->IntVal = llvm::APInt(Ty->getIntegerBitWidth(), N, IsSigned); + return GenVal; +} + +static +llvm::GenericValue* GenericValue_CreateFloat(float Val) +{ + llvm::GenericValue *GenVal = new llvm::GenericValue(); + GenVal->FloatVal = Val; + return GenVal; +} + +static +llvm::GenericValue* GenericValue_CreateDouble(double Val) +{ + llvm::GenericValue *GenVal = new llvm::GenericValue(); + GenVal->DoubleVal = Val; + return GenVal; +} + +static +llvm::GenericValue* GenericValue_CreatePointer(void * Ptr) +{ + llvm::GenericValue *GenVal = new llvm::GenericValue(); + GenVal->PointerVal = Ptr; + return GenVal; +} + +static +unsigned GenericValue_ValueIntWidth(llvm::GenericValue *GenValRef) +{ + return GenValRef->IntVal.getBitWidth(); +} + +static +unsigned long long GenericValue_ToUnsignedInt(llvm::GenericValue* GenVal) +{ + return GenVal->IntVal.getZExtValue(); +} + + +static +long long GenericValue_ToSignedInt(llvm::GenericValue* GenVal) +{ + return GenVal->IntVal.getSExtValue(); +} + +static +void* GenericValue_ToPointer(llvm::GenericValue* GenVal) +{ + return GenVal->PointerVal; +} + +static +double GenericValue_ToFloat(llvm::GenericValue* GenVal, llvm::Type* Ty) +{ + switch (Ty->getTypeID()) { + case llvm::Type::FloatTyID: + return GenVal->FloatVal; + default: + // Behavior undefined if type is not a float or a double + return GenVal->DoubleVal; + } +} + +static +PyObject* ExecutionEngine_RunFunction(llvm::ExecutionEngine* EE, + llvm::Function* Fn, PyObject* Args) +{ + using namespace llvm; + const char * GVN = "llvm::GenericValue"; + if (!PyTuple_Check(Args)) { + PyErr_SetString(PyExc_TypeError, "Expect a tuple of args."); + return NULL; + } + std::vector vec_args; + Py_ssize_t nargs = PyTuple_Size(Args); + vec_args.reserve(nargs); + for (Py_ssize_t i = 0; i < nargs; ++i) { + PyObject* obj = PyTuple_GetItem(Args, i); + if (!obj) { + PyErr_SetString(PyExc_RuntimeError, "Failed to index into args?"); + return NULL; + } + + GenericValue* gv = static_cast( + PyCapsule_GetPointer(obj, GVN)); + + if (!gv) { + return NULL; + } + vec_args.push_back(*gv); + } + + GenericValue ret = EE->runFunction(Fn, vec_args); + return pycapsule_new(new GenericValue(ret), GVN); +} + diff --git a/newbinding/src/ExecutionEngine.py b/newbinding/src/ExecutionEngine.py index 0fbe387..5a95a16 100644 --- a/newbinding/src/ExecutionEngine.py +++ b/newbinding/src/ExecutionEngine.py @@ -4,6 +4,11 @@ from Module import Module from JITMemoryManager import JITMemoryManager from CodeGen import CodeGenOpt, Reloc, CodeModel from DataLayout import DataLayout +from Value import Function, GlobalValue, BasicBlock, Constant +from GlobalVariable import GlobalVariable +from MachineCodeInfo import MachineCodeInfo +from GenericValue import GenericValue +from Type import Type ExecutionEngine = llvm.Class() @@ -32,3 +37,58 @@ class ExecutionEngine: addModule = Method(Void, ptr(Module)) getDataLayout = Method(const(ownedptr(DataLayout))) removeModule = Method(cast(Bool, bool), ptr(Module)) + + FindFunctionNamed = Method(ptr(Function), cast(str, ConstCharPtr)) + getPointerToNamedFunction = Method(cast(VoidPtr, int), + cast(str, StdString), + cast(bool, Bool)).require_only(1) + + runStaticConstructorsDestructors = Method(Void, cast(Bool, bool)) + runStaticConstructorsDestructors |= Method(Void, ptr(Module), + cast(Bool, bool)) + + addGlobalMapping = Method(Void, ptr(GlobalValue), cast(int, VoidPtr)) + clearAllGlobalMappings = Method() + clearGlobalMappingsFromModule = Method(Void, ptr(Module)) + updateGlobalMapping = Method(cast(VoidPtr, int), + ptr(GlobalValue), cast(int, VoidPtr)) + + getPointerToGlobalIfAvailable = Method(cast(VoidPtr, int), ptr(GlobalValue)) + getPointerToGlobal = Method(cast(VoidPtr, int), ptr(GlobalValue)) + getPointerToFunction = Method(cast(VoidPtr, int), ptr(Function)) + getPointerToBasicBlock = Method(cast(VoidPtr, int), ptr(BasicBlock)) + getPointerToFunctionOrStub = Method(cast(VoidPtr, int), ptr(Function)) + + runJITOnFunction = Method(Void, ptr(Function), ptr(MachineCodeInfo)) + runJITOnFunction.require_only(1) + + getGlobalValueAtAddress = Method(const(ptr(GlobalValue)), cast(int, VoidPtr)) + + StoreValueToMemory = Method(Void, ref(GenericValue), ptr(GenericValue), + ptr(Type)) + + InitializeMemory = Method(Void, ptr(Constant), cast(int, VoidPtr)) + + recompileAndRelinkFunction = Method(cast(int, VoidPtr), ptr(Function)) + + freeMachineCodeForFunction = Method(Void, ptr(Function)) + getOrEmitGlobalVariable = Method(cast(int, VoidPtr), ptr(GlobalVariable)) + + DisableLazyCompilation = Method(Void, cast(bool, Bool)) + isCompilingLazily = Method(cast(Bool, bool)) + isLazyCompilationDisabled = Method(cast(Bool, bool)) + DisableGVCompilation = Method(Void, cast(bool, Bool)) + isSymbolSearchingDisabled = Method(cast(Bool, bool)) + RegisterTable = Method(Void, ptr(Function), cast(int, VoidPtr)) + DeregisterTable = Method(Void, ptr(Function)) + DeregisterAllTables = Method() + + _runFunction = CustomMethod('ExecutionEngine_RunFunction', + PyObjectPtr, ptr(Function), PyObjectPtr) + + @CustomPythonMethod + def runFunction(self, fn, args): + import capsule + unwrapped = map(capsule.unwrap, args) + return self._runFunction(fn, tuple(unwrapped)) + diff --git a/newbinding/src/GenericValue.py b/newbinding/src/GenericValue.py new file mode 100644 index 0000000..74587ba --- /dev/null +++ b/newbinding/src/GenericValue.py @@ -0,0 +1,34 @@ +from binding import * +from namespace import llvm +from Type import Type + +GenericValue = llvm.Class() + +@GenericValue +class GenericValue: + delete = Destructor() + + def _factory(name, *argtys): + return CustomStaticMethod('GenericValue_' + name, + ptr(GenericValue), *argtys) + + CreateFloat = _factory('CreateFloat', cast(float, Float)) + + CreateDouble = _factory('CreateDouble', cast(float, Float)) + + CreateInt = _factory('CreateInt', ptr(Type), + cast(int, UnsignedLongLong), cast(bool, Bool)) + + CreatePointer = _factory('CreatePointer', cast(int, VoidPtr)) + + def _accessor(name, *argtys): + return CustomMethod('GenericValue_' + name, *argtys) + + valueIntWidth = _accessor('ValueIntWidth', cast(Unsigned, int)) + + toSignedInt = _accessor('ToSignedInt', cast(UnsignedLongLong, int)) + toUnsignedInt = _accessor('ToUnsignedInt', cast(LongLong, int)) + + toFloat = _accessor('ToFloat', cast(Double, float), ptr(Type)) + + toPointer = _accessor('ToPointer', cast(VoidPtr, int)) \ No newline at end of file diff --git a/newbinding/src/MachineCodeInfo.py b/newbinding/src/MachineCodeInfo.py new file mode 100644 index 0000000..5d91e3a --- /dev/null +++ b/newbinding/src/MachineCodeInfo.py @@ -0,0 +1,13 @@ +from binding import * +from namespace import llvm + +MachineCodeInfo = llvm.Class() + +@MachineCodeInfo +class MachineCodeInfo: + _include_ = 'llvm/CodeGen/MachineCodeInfo.h' + setSize = Method(Void, cast(int, Size_t)) + setAddress = Method(Void, cast(int, VoidPtr)) + size = Method(cast(Size_t, int)) + address = Method(cast(VoidPtr, int)) + diff --git a/newbinding/src/Module.py b/newbinding/src/Module.py index 6cd6e2e..9b392ca 100644 --- a/newbinding/src/Module.py +++ b/newbinding/src/Module.py @@ -44,4 +44,11 @@ class Module: print_ = Method(Void, ref(raw_ostream), ptr(AssemblyAnnotationWriter)) print_.realname = 'print' + @CustomPythonMethod + def __str__(self): + import extra + os = extra.make_raw_ostream_for_printing() + self.print_(os, None) + return os.str() + dropAllReferences = Method() diff --git a/newbinding/src/Type.py b/newbinding/src/Type.py index 15b5e31..bf51b9d 100644 --- a/newbinding/src/Type.py +++ b/newbinding/src/Type.py @@ -2,6 +2,7 @@ from binding import * from namespace import llvm from LLVMContext import LLVMContext from raw_ostream import raw_ostream +from StringRef import StringRef Type = llvm.Class() IntegerType = llvm.Class(Type) @@ -52,6 +53,19 @@ class Type: isIntegerTy = Method(cast(Bool, bool)) isIntegerTy |= Method(cast(Bool, bool), cast(int, Unsigned)) + getIntegerBitWidth = Method(cast(Unsigned, int)) + getFunctionParamType = Method(ptr(Type), cast(int, Unsigned)) + getFunctionNumParams = Method(cast(int, Unsigned)) + + isFunctionVarArg = type_checker() + + getStructName = Method(cast(StringRef, str)) + getStructNumElements = Method(cast(Unsigned, int)) + getStructElementType = Method(ptr(Type), cast(int, Unsigned)) + getSequentialElementType = Method(ptr(Type)) + + # Factories + def type_factory(): return StaticMethod(ptr(Type), ref(LLVMContext)) diff --git a/newbinding/test2.py b/newbinding/test2.py index 9492bb6..7902df4 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -28,25 +28,25 @@ print os.str() int1ty = api.Type.getInt1Ty(context) int1ty.dump() -print int1ty.isIntegerTy(1) +assert int1ty.isIntegerTy(1) fnty = api.FunctionType.get(int1ty, False) fnty.dump() -types = [int1ty, api.Type.getIntNTy(context, 21)] -fnty = api.FunctionType.get(int1ty, 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 const = m.getOrInsertFunction("foo", fnty) -fn = extra.downcast(const, api.Function) +fn = const._downcast(api.Function) print fn assert fn.hasName() assert 'foo' == fn.getName() fn.setName('bar') assert 'bar' == fn.getName() -assert fn.getReturnType() is int1ty +assert fn.getReturnType().isIntegerTy(8) assert fnty is fn.getFunctionType() @@ -70,13 +70,19 @@ assert bb.getTerminator() is None arg0, arg1 = fn.getArgumentList() print arg0, arg1 -ret = builder.CreateCall(fn, [arg0, arg1], '') +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 fn errio = StringIO() -ee = api.ExecutionEngine.createJIT(m) +print m + +ee = api.ExecutionEngine.createJIT(m, errio) print ee, errio.getvalue() print ee.getDataLayout().getStringRepresentation() @@ -85,3 +91,24 @@ datalayout_str = 'e-p:64:64:64-S128-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64- 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 + +assert ee.getPointerToFunction(fn) +assert ee.getPointerToNamedFunction('printf') + +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.toUnsignedInt() == 12 +assert gv1.toSignedInt() == -32 + +gv1 = api.GenericValue.CreateInt(arg1.getType(), 32, False) + +gvR = ee.runFunction(fn, (gv0, gv1)) + +assert 44 == gvR.toUnsignedInt() + From ca0a2b9fddd9e8224b5a919de6fbccc80492a04c Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 1 Feb 2013 11:45:19 -0600 Subject: [PATCH 37/85] 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() From 9485d03e18a226303b36bae577da37f994f61776 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 1 Feb 2013 14:19:22 -0600 Subject: [PATCH 38/85] binding for Target, Triple, TargetMachine --- newbinding/binding.py | 19 ++++++--- newbinding/include/llvm_binding/extra.h | 28 ++++++++++++- newbinding/src/CodeGen.py | 1 + newbinding/src/EngineBuilder.py | 15 ++++++- newbinding/src/Target.py | 27 ++++++++++++ newbinding/src/TargetMachine.py | 25 +++++++++++ newbinding/src/TargetTransformInfo.py | 14 +++++++ newbinding/src/Triple.py | 55 +++++++++++++++++++++++++ newbinding/test2.py | 23 +++++++++++ 9 files changed, 199 insertions(+), 8 deletions(-) create mode 100644 newbinding/src/Target.py create mode 100644 newbinding/src/TargetTransformInfo.py create mode 100644 newbinding/src/Triple.py diff --git a/newbinding/binding.py b/newbinding/binding.py index 1f980d1..69267dc 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -185,6 +185,11 @@ class Class(_Type): writer.die_if_false(casted) return casted + def wrap(self, writer, val): + copy = 'new %s(%s)' % (self.fullname, val) + return writer.pycapsule_new(copy, self.capsule_name, self.fullname) + + class Enum(object): format = 'O' @@ -466,13 +471,17 @@ class ref(_Type): def __init__(self, element): assert isinstance(element, Class), type(element) self.element = element + self.const = False def __str__(self): return self.fullname @property def fullname(self): - return '%s&' % self.element.fullname + if self.const: + return 'const %s&' % self.element.fullname + else: + return '%s&' % self.element.fullname @property def capsule_name(self): @@ -483,7 +492,7 @@ class ref(_Type): return self.element.format def wrap(self, writer, val): - p = writer.declare(ptr(self.element).fullname, '&%s' % val) + p = writer.declare(const(ptr(self.element)).fullname, '&%s' % val) return writer.pycapsule_new(p, self.capsule_name, self.element.fullname) def unwrap(self, writer, val): @@ -522,9 +531,9 @@ class ptr(_Type): class ownedptr(ptr): pass -def const(ptr): - ptr.const = True - return ptr +def const(ptr_or_ref): + ptr_or_ref.const = True + return ptr_or_ref class cast(_Type): format = 'O' diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index 10a4361..46dd42a 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -368,9 +368,9 @@ PyObject* EngineBuilder_setMAttrs(llvm::EngineBuilder* eb, return NULL; } std::vector tmp; - const int N = PyList_Size(strlist); + const Py_ssize_t N = PyList_Size(strlist); tmp.reserve(N); - for (int i = 0; i < N; ++i) { + for (Py_ssize_t i = 0; i < N; ++i) { const char * elem = PyString_AsString(PyList_GetItem(strlist, i)); if (!elem) { return NULL; @@ -381,3 +381,27 @@ PyObject* EngineBuilder_setMAttrs(llvm::EngineBuilder* eb, return pycapsule_new(eb, "llvm::EngineBuilder"); } +static +PyObject* EngineBuilder_selectTarget(llvm::EngineBuilder* eb, + const llvm::Triple& TargetTriple, + llvm::StringRef MArch, + llvm::StringRef MCPU, + PyObject* strlist) +{ + const Py_ssize_t N = PySequence_Size(strlist); + llvm::SmallVector MAttrs; + MAttrs.reserve(N); + for (Py_ssize_t i = 0; i < N; ++i) { + PyObject* str = PySequence_GetItem(strlist, i); + const char * cp = PyString_AsString(str); + if (!cp) { + Py_DECREF(str); + return NULL; + } + MAttrs.push_back(cp); + Py_DECREF(str); + } + eb->selectTarget(TargetTriple, MArch, MCPU, MAttrs); + return pycapsule_new(eb, "llvm::EngineBuilder"); +} + diff --git a/newbinding/src/CodeGen.py b/newbinding/src/CodeGen.py index 06821aa..7afcd49 100644 --- a/newbinding/src/CodeGen.py +++ b/newbinding/src/CodeGen.py @@ -17,3 +17,4 @@ class TLSModel: class CodeGenOpt: 'Actually a namespace' Level = Enum('None', 'Less', 'Default', 'Aggressive') + diff --git a/newbinding/src/EngineBuilder.py b/newbinding/src/EngineBuilder.py index 0e8388e..07ffcc0 100644 --- a/newbinding/src/EngineBuilder.py +++ b/newbinding/src/EngineBuilder.py @@ -6,6 +6,7 @@ from CodeGen import CodeGenOpt, Reloc, CodeModel from StringRef import StringRef from ExecutionEngine import ExecutionEngine from TargetMachine import TargetMachine +from Triple import Triple EngineBuilder = llvm.Class() @@ -45,5 +46,17 @@ class EngineBuilder: create = Method(ptr(ExecutionEngine), ownedptr(TargetMachine)).require_only(0) - selectTarget = Method(ptr(TargetMachine)) + _selectTarget0 = Method(ptr(TargetMachine)) + _selectTarget0.realname = 'selectTarget' + + _selectTarget1 = CustomMethod('EngineBuilder_selectTarget', + const(ref(Triple)), cast(str, StringRef), + cast(str, StringRef), PyObjectPtr), + + @CustomPythonMethod + def selectTarget(self, *args): + if not args: + return self._selectTarget0() + else: + return self._selectTarget1(*args) diff --git a/newbinding/src/Target.py b/newbinding/src/Target.py new file mode 100644 index 0000000..3c2a0e1 --- /dev/null +++ b/newbinding/src/Target.py @@ -0,0 +1,27 @@ +from binding import * +from namespace import llvm +from StringRef import StringRef +Target = llvm.Class() + +@Target +class Target: + _include_ = 'llvm/Support/TargetRegistry.h' + + getNext = Method(const(ptr(Target))) + + getName = Method(cast(StringRef, str)) + getShortDescription = Method(cast(StringRef, str)) + + def _has(): + return Method(cast(Bool, bool)) + + hasJIT = _has() + hasTargetMachine = _has() + hasMCAsmBackend = _has() + hasMCAsmParser = _has() + hasAsmPrinter = _has() + hasMCDisassembler = _has() + hasMCInstPrinter = _has() + hasMCCodeEmitter = _has() + hasMCObjectStreamer = _has() + hasAsmStreamer = _has() diff --git a/newbinding/src/TargetMachine.py b/newbinding/src/TargetMachine.py index e53cd33..5910585 100644 --- a/newbinding/src/TargetMachine.py +++ b/newbinding/src/TargetMachine.py @@ -1,5 +1,12 @@ from binding import * from namespace import llvm +from StringRef import StringRef +from CodeGen import CodeModel, TLSModel, CodeGenOpt, Reloc +from GlobalValue import GlobalValue +from Target import Target +from DataLayout import DataLayout +from TargetTransformInfo import (ScalarTargetTransformInfo, + VectorTargetTransformInfo) TargetMachine = llvm.Class() @@ -8,4 +15,22 @@ class TargetMachine: _include_ = 'llvm/Target/TargetMachine.h' delete = Destructor() + getTarget = Method(const(ref(Target))) + getTargetTriple = Method(cast(StringRef, str)) + getTargetCPU = Method(cast(StringRef, str)) + getTargetFeatureString = Method(cast(StringRef, str)) + + getRelocationModel = Method(Reloc.Model) + getCodeModel = Method(CodeModel.Model) + getTLSModel = Method(TLSModel.Model, ptr(GlobalValue)) + getOptLevel = Method(CodeGenOpt.Level) + + hasMCUseDwarfDirectory = Method(cast(Bool, bool)) + setMCUseDwarfDirectory = Method(Void, cast(bool, Bool)) + + getDataLayout = Method(const(ownedptr(DataLayout))) + getScalarTargetTransformInfo = Method(const( + ownedptr(ScalarTargetTransformInfo))) + getVectorTargetTransformInfo = Method(const( + ownedptr(VectorTargetTransformInfo))) diff --git a/newbinding/src/TargetTransformInfo.py b/newbinding/src/TargetTransformInfo.py new file mode 100644 index 0000000..8e3c17e --- /dev/null +++ b/newbinding/src/TargetTransformInfo.py @@ -0,0 +1,14 @@ +from binding import * +from namespace import llvm + +ScalarTargetTransformInfo = llvm.Class() +VectorTargetTransformInfo = llvm.Class() + +@ScalarTargetTransformInfo +class ScalarTargetTransformInfo: + delete = Destructor() + +@VectorTargetTransformInfo +class VectorTargetTransformInfo: + delete = Destructor() + diff --git a/newbinding/src/Triple.py b/newbinding/src/Triple.py new file mode 100644 index 0000000..0fd894e --- /dev/null +++ b/newbinding/src/Triple.py @@ -0,0 +1,55 @@ +from binding import * +from namespace import llvm +from StringRef import StringRef + +Triple = llvm.Class() + +@Triple +class Triple: + _include_ = 'llvm/ADT/Triple.h' + + new = Constructor() + new |= Constructor(cast(str, StringRef)) + new |= Constructor(cast(str, StringRef), + cast(str, StringRef), cast(str, StringRef)) + + def _return_str(): + return Method(cast(StringRef, str)) + + getTriple = _return_str() + getArchName = _return_str() + getVendorName = _return_str() + getOSName = _return_str() + getEnvironmentName = _return_str() + getOSAndEnvironmentName = _return_str() + + @CustomPythonMethod + def __str__(self): + return self.getTriple() + + def _return_bool(*args): + return Method(cast(bool, Bool), *args) + + isArch64Bit = _return_bool() + isArch32Bit = _return_bool() + isArch16Bit = _return_bool() + isOSVersionLT = _return_bool(cast(int, Unsigned), + cast(int, Unsigned), + cast(int, Unsigned)).require_only(1) + + isMacOSXVersionLT = _return_bool(cast(int, Unsigned), + cast(int, Unsigned), + cast(int, Unsigned)).require_only(1) + + isMacOSX = _return_bool() + isOSDarwin = _return_bool() + isOSCygMing = _return_bool() + isOSWindows = _return_bool() + # isOSNaCl = _return_bool() + isOSBinFormatELF = _return_bool() + isOSBinFormatCOFF = _return_bool() + isEnvironmentMachO = _return_bool() + + get32BitArchVariant = Method(Triple) + get64BitArchVariant = Method(Triple) + diff --git a/newbinding/test2.py b/newbinding/test2.py index a304426..93fccb8 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -124,8 +124,31 @@ def test_engine_builder(): eb.setOptLevel(api.CodeGenOpt.Level.Aggressive).setUseMCJIT(False) tm = eb.selectTarget() + + print 'target triple:', tm.getTargetTriple() + print 'target cpu:', tm.getTargetCPU() + print 'target feature string:', tm.getTargetFeatureString() + + target = tm.getTarget() + print 'target name:', target.getName() + print 'target short description:', target.getShortDescription() + + assert target.hasJIT() + assert target.hasTargetMachine() + ee = eb.create(tm) + triple = api.Triple.new('x86_64-unknown-linux') + assert triple.getArchName() == 'x86_64' + assert triple.getVendorName() == 'unknown' + assert triple.getOSName() == 'linux' + assert triple.isArch64Bit() + assert not triple.isArch32Bit() + triple_32variant = triple.get32BitArchVariant() + assert triple_32variant.isArch32Bit() + + print tm.getDataLayout() + def main(): for name, value in globals().items(): From 372d6804e4ba2b38cd10172323413b2d48417133 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 1 Feb 2013 17:02:09 -0600 Subject: [PATCH 39/85] Add bindings for Pass, PassManagers, PassManagerBuilder and TargetLibraryInfo. --- newbinding/binding.py | 2 + newbinding/src/DataLayout.py | 5 +- newbinding/src/Pass.py | 35 +++++++++++++ newbinding/src/PassManager.py | 34 +++++++++++++ newbinding/src/PassManagerBuilder.py | 19 +++++++ newbinding/src/TargetLibraryInfo.py | 76 ++++++++++++++++++++++++++++ newbinding/test2.py | 25 ++++++++- 7 files changed, 192 insertions(+), 4 deletions(-) create mode 100644 newbinding/src/Pass.py create mode 100644 newbinding/src/PassManager.py create mode 100644 newbinding/src/PassManagerBuilder.py create mode 100644 newbinding/src/TargetLibraryInfo.py diff --git a/newbinding/binding.py b/newbinding/binding.py index 69267dc..cb40d1e 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -195,6 +195,8 @@ class Enum(object): def __init__(self, *value_names): self.parent = None + if len(value_names) == 1: + value_names = filter(bool, value_names[0].replace(',', ' ').split()) self.value_names = value_names self.includes = set() diff --git a/newbinding/src/DataLayout.py b/newbinding/src/DataLayout.py index a1ef8bc..74d1ad0 100644 --- a/newbinding/src/DataLayout.py +++ b/newbinding/src/DataLayout.py @@ -6,8 +6,9 @@ from Module import Module from Type import Type, IntegerType, StructType from SmallVector import SmallVector_Value from GlobalVariable import GlobalVariable +from Pass import ImmutablePass -DataLayout = llvm.Class() +DataLayout = llvm.Class(ImmutablePass) StructLayout = llvm.Class() @DataLayout @@ -24,8 +25,6 @@ class DataLayout: else: return DataLayout._new_string(arg) - delete = Destructor() - isLittleEndian = Method(cast(Bool, bool)) isBigEndian = Method(cast(Bool, bool)) diff --git a/newbinding/src/Pass.py b/newbinding/src/Pass.py new file mode 100644 index 0000000..5842232 --- /dev/null +++ b/newbinding/src/Pass.py @@ -0,0 +1,35 @@ +from binding import * +from namespace import llvm +from StringRef import StringRef +from Module import Module +from Function import Function + +Pass = llvm.Class() +ModulePass = llvm.Class(Pass) +FunctionPass = llvm.Class(Pass) +ImmutablePass = llvm.Class(ModulePass) + + +@Pass +class Pass: + _include_ = 'llvm/Pass.h' + + delete = Destructor() + getPassName = Method(cast(StringRef, str)) + + +@ModulePass +class ModulePass: + runOnModule = Method(cast(Bool, bool), ref(Module)) + + +@FunctionPass +class FunctionPass: + doInitialization = Method(cast(Bool, bool), ref(Module)) + doFinalization = Method(cast(Bool, bool), ref(Module)) + + +@ImmutablePass +class ImmutablePass: + pass + diff --git a/newbinding/src/PassManager.py b/newbinding/src/PassManager.py new file mode 100644 index 0000000..f969192 --- /dev/null +++ b/newbinding/src/PassManager.py @@ -0,0 +1,34 @@ +from binding import * +from namespace import llvm +from Pass import Pass +from Module import Module +from Function import Function + +PassManagerBase = llvm.Class() +PassManager = llvm.Class(PassManagerBase) +FunctionPassManager = llvm.Class(PassManagerBase) + +@PassManagerBase +class PassManagerBase: + _include_ = 'llvm/PassManager.h' + + delete = Destructor() + + add = Method(Void, ownedptr(Pass)) + +@PassManager +class PassManager: + new = Constructor() + + run = Method(cast(Bool, bool), ref(Module)) + + +@FunctionPassManager +class FunctionPassManager: + new = Constructor(ptr(Module)) + + run = Method(cast(Bool, bool), ref(Function)) + + doInitialization = Method(cast(Bool, bool)) + doFinalization = Method(cast(Bool, bool)) + diff --git a/newbinding/src/PassManagerBuilder.py b/newbinding/src/PassManagerBuilder.py new file mode 100644 index 0000000..2e2ea5e --- /dev/null +++ b/newbinding/src/PassManagerBuilder.py @@ -0,0 +1,19 @@ +from binding import * +from namespace import llvm +from PassManager import PassManagerBase, FunctionPassManager + +@llvm.Class() +class PassManagerBuilder: + _include_ = 'llvm/Transforms/IPO/PassManagerBuilder.h' + + new = Constructor() + delete = Destructor() + + populateFunctionPassManager = Method(Void, ref(FunctionPassManager)) + populateModulePassManager = Method(Void, ref(PassManagerBase)) + populateLTOPassManager = Method(Void, + ref(PassManagerBase), + cast(bool, Bool), + cast(bool, Bool), + cast(bool, Bool)).require_only(3) + diff --git a/newbinding/src/TargetLibraryInfo.py b/newbinding/src/TargetLibraryInfo.py new file mode 100644 index 0000000..a5ba28d --- /dev/null +++ b/newbinding/src/TargetLibraryInfo.py @@ -0,0 +1,76 @@ +from binding import * +from namespace import llvm +from Triple import Triple +from Pass import ImmutablePass +from StringRef import StringRef + +TargetLibraryInfo = llvm.Class(ImmutablePass) + +@llvm.Class() +class LibFunc: + Func = Enum(''' + ZdaPv, ZdlPv, Znaj, ZnajRKSt9nothrow_t, + Znam, ZnamRKSt9nothrow_t, Znwj, ZnwjRKSt9nothrow_t, + Znwm, ZnwmRKSt9nothrow_t, cxa_atexit, cxa_guard_abort, + cxa_guard_acquire, cxa_guard_release, memcpy_chk, + acos, acosf, acosh, acoshf, + acoshl, acosl, asin, asinf, + asinh, asinhf, asinhl, asinl, + atan, atan2, atan2f, atan2l, + atanf, atanh, atanhf, atanhl, + atanl, calloc, cbrt, cbrtf, + cbrtl, ceil, ceilf, ceill, + copysign, copysignf, copysignl, cos, + cosf, cosh, coshf, coshl, + cosl, exp, exp10, exp10f, + exp10l, exp2, exp2f, exp2l, + expf, expl, expm1, expm1f, + expm1l, fabs, fabsf, fabsl, + fiprintf, + floor, floorf, floorl, fmod, + fmodf, fmodl, fputc, + fputs, free, fwrite, iprintf, + log, log10, log10f, log10l, + log1p, log1pf, log1pl, log2, + log2f, log2l, logb, logbf, + logbl, logf, logl, malloc, + memchr, memcmp, memcpy, memmove, + memset, memset_pattern16, nearbyint, nearbyintf, + nearbyintl, posix_memalign, pow, powf, + powl, putchar, puts, + realloc, reallocf, rint, rintf, + rintl, round, roundf, roundl, + sin, sinf, sinh, sinhf, + sinhl, sinl, siprintf, + sqrt, sqrtf, sqrtl, stpcpy, + strcat, strchr, strcmp, strcpy, + strcspn, strdup, strlen, strncat, + strncmp, strncpy, strndup, strnlen, + strpbrk, strrchr, strspn, strstr, + strtod, strtof, strtol, strtold, + strtoll, strtoul, strtoull, tan, + tanf, tanh, tanhf, tanhl, + tanl, trunc, truncf, + truncl, valloc, NumLibFuncs''') + # not in llvm-3.2 abs, ffs, ffsl, ffsll, fprintf, isascii, + # isdigit, labs, llabs, printf, sprintf, toascii + +@TargetLibraryInfo +class TargetLibraryInfo: + _include_ = 'llvm/Target/TargetLibraryInfo.h' + + new = Constructor() + new |= Constructor(ref(Triple)) + + delete = Destructor() + + has = Method(cast(bool, Bool), LibFunc.Func) + hasOptimizedCodeGen = Method(cast(bool, Bool), LibFunc.Func) + + getName = Method(cast(str, StringRef), LibFunc.Func) + + setUnavailable = Method(Void, LibFunc.Func) + setAvailable = Method(Void, LibFunc.Func) + setAvailableWithName = Method(Void, LibFunc.Func, cast(str, StringRef)) + disableAllFunctions = Method() + diff --git a/newbinding/test2.py b/newbinding/test2.py index 93fccb8..e2f8dd2 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -8,7 +8,6 @@ def test_basic_jit_use(): api.InitializeNativeTarget() context = api.getGlobalContext() - m = api.Module.new("modname", context) print m.getModuleIdentifier() m.setModuleIdentifier('modname2') @@ -82,6 +81,26 @@ def test_basic_jit_use(): errio = StringIO() print m + # build pass manager + + pmb = api.PassManagerBuilder.new() + + fpm = api.FunctionPassManager.new(m) + pm = api.PassManager.new() + + pmb.populateFunctionPassManager(fpm) + pmb.populateModulePassManager(pm) + + fpm.doInitialization() + fpm.run(fn) + fpm.doFinalization() + + pm.run(m) + + print m + + # build engine + ee = api.ExecutionEngine.createJIT(m, errio) print ee, errio.getvalue() print ee.getDataLayout().getStringRepresentation() @@ -149,6 +168,10 @@ def test_engine_builder(): print tm.getDataLayout() + pm = api.PassManager.new() + pm.add(api.DataLayout.new(str(tm.getDataLayout()))) + pm.add(api.TargetLibraryInfo.new()) + def main(): for name, value in globals().items(): From 7788346152a461142f5256f832d66d2d9347981e Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 1 Feb 2013 17:32:30 -0600 Subject: [PATCH 40/85] Improve enum implementation --- newbinding/binding.py | 48 +++++++++++++++++++------------------------ newbinding/gen.py | 7 +++++++ 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/newbinding/binding.py b/newbinding/binding.py index cb40d1e..4205c64 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -125,6 +125,8 @@ class Class(_Type): # generate methods for meth in self.methods: meth.compile_cpp(writer) + for enum in self.enums: + enum.compile_cpp(writer) # generate method table writer.println('static') @@ -135,6 +137,11 @@ class Class(_Type): name = meth.name func = meth.c_name writer.println(fmt % locals()) + for enumkind in self.enums: + for enum in enumkind.value_names: + name = enum + func = enumkind.c_name(enum) + writer.println(fmt % locals()) writer.println('{ NULL },') writer.println('};') writer.println() @@ -212,38 +219,22 @@ class Enum(object): return self.fullname def wrap(self, writer, val): - ret = writer.declare('PyObject*', 'NULL') - with writer.block('switch(%s) ' % val): - for v in self.value_names: - writer.println('case %s::%s:' % (self.parent, v)) - with writer.indent(): - fmt = '%(ret)s = PyString_FromString("%(v)s");' - writer.println(fmt % locals()) - writer.println('break;') - else: - writer.println('default:') - with writer.indent(): - writer.raises(ValueError, 'Invalid enum %s' % v) + ret = writer.declare('PyObject*', 'PyInt_FromLong(%s)' % val) return ret def unwrap(self, writer, val): - tostring = 'PyString_AsString(%(val)s)' % locals() - string = writer.declare('const char*', tostring) - ret = writer.declare('%s::%s' % (self.parent, self.name)) - parent = self.parent - iffmt = 'if (string_equal(%(string)s, "%(v)s"))' - for i, v in enumerate(self.value_names): - with writer.block(iffmt % locals()): - fmt = '%(ret)s = %(parent)s::%(v)s;' - writer.println(fmt % locals()) - if i == 0: - iffmt = 'else ' + iffmt - with writer.block('else'): - writer.raises(ValueError, 'Invalid enum.') + convert_long_to_enum = '(%s)PyInt_AsLong(%s)' % (self.fullname, val) + ret = writer.declare(self.fullname, convert_long_to_enum) return ret + def c_name(self, enum): + return cg.mangle("%s_%s_%s" % (self.parent, self.name, enum)) + def compile_cpp(self, writer): - pass + for enum in self.value_names: + with writer.py_function(self.c_name(enum)): + ret = self.wrap(writer, '::'.join([self.parent.fullname, enum])) + writer.return_value(ret) def compile_py(self, writer): with writer.block('class %s:' % self.name): @@ -251,9 +242,12 @@ class Enum(object): for v in self.value_names: if v in RESERVED: k = '%s_' % v + fmt = '%(k)s = getattr(%(p)s, "%(v)s")()' else: k = v - writer.println('%(k)s = "%(v)s"' % locals()) + fmt = '%(k)s = %(p)s.%(v)s()' + p = '.'.join(['_api'] + self.parent.fullname.split('::')[1:]) + writer.println(fmt % locals()) writer.println() class Method(object): diff --git a/newbinding/gen.py b/newbinding/gen.py index 47f5655..7c56452 100644 --- a/newbinding/gen.py +++ b/newbinding/gen.py @@ -136,6 +136,13 @@ static name = u.name func = u.c_name writer.println(fmt % locals()) + for u in units: + if isinstance(u, Enum): + for enum in u.value_names: + name = enum + func = u.c_name(enum) + writer.println(fmt % locals()) + writer.println('{ NULL },') writer.println('};') writer.println() From 1f49bb6d7c7e1fcfeb0ab47c3770ec35e65917dc Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Sun, 3 Feb 2013 12:57:13 -0600 Subject: [PATCH 41/85] Binding for PassManagerBuilder --- newbinding/binding.py | 92 +++++++++++++++++++++++++ newbinding/include/llvm_binding/extra.h | 14 ++-- newbinding/{src => }/namespace.py | 0 newbinding/src/EngineBuilder.py | 3 +- newbinding/src/PassManagerBuilder.py | 24 +++++++ newbinding/src/Transforms/IPO.py | 9 +++ newbinding/src/Transforms/__init__.py | 10 +++ newbinding/src/__init__.py | 5 +- newbinding/test2.py | 4 ++ 9 files changed, 151 insertions(+), 10 deletions(-) rename newbinding/{src => }/namespace.py (100%) create mode 100644 newbinding/src/Transforms/IPO.py create mode 100644 newbinding/src/Transforms/__init__.py diff --git a/newbinding/binding.py b/newbinding/binding.py index 4205c64..142c8ef 100644 --- a/newbinding/binding.py +++ b/newbinding/binding.py @@ -83,6 +83,7 @@ class Class(_Type): self.methods = [] self.pymethods = [] self.enums = [] + self.attrs = [] self.includes = set() self.downcastables = set() @@ -103,6 +104,10 @@ class Class(_Type): v.name = k v.parent = self setattr(self, k, v) + elif isinstance(v, Attr): + self.attrs.append(v) + v.name = k + v.parent = self elif isinstance(v, CustomPythonMethod): self.pymethods.append(v) elif k == '_include_': @@ -127,6 +132,8 @@ class Class(_Type): meth.compile_cpp(writer) for enum in self.enums: enum.compile_cpp(writer) + for attr in self.attrs: + attr.compile_cpp(writer) # generate method table writer.println('static') @@ -142,6 +149,16 @@ class Class(_Type): name = enum func = enumkind.c_name(enum) writer.println(fmt % locals()) + for attr in self.attrs: + # getter + name = attr.getter_name + func = attr.getter_c_name + writer.println(fmt % locals()) + # setter + name = attr.setter_name + func = attr.setter_c_name + writer.println(fmt % locals()) + writer.println('{ NULL },') writer.println('};') writer.println() @@ -160,6 +177,8 @@ class Class(_Type): meth.compile_py(writer) for meth in self.pymethods: meth.compile_py(writer) + for attr in self.attrs: + attr.compile_py(writer) writer.println() @property @@ -587,3 +606,76 @@ class CustomPythonStaticMethod(CustomPythonMethod): writer.println('@staticmethod') super(CustomPythonStaticMethod, self).compile_py(writer) + +class Attr(object): + def __init__(self, getter, setter): + self.getter = getter + self.setter = setter + + @property + def fullname(self): + try: + name = self.realname + except AttributeError: + name = self.name + return '::'.join([self.parent.fullname, name]) + + def __str__(self): + return self.fullname + + @property + def getter_name(self): + return '%s_get' % self.name + + @property + def setter_name(self): + return '%s_set' % self.name + + @property + def getter_c_name(self): + return cg.mangle('%s_get' % self.fullname) + + @property + def setter_c_name(self): + return cg.mangle('%s_set' % self.fullname) + + def compile_cpp(self, writer): + # getter + with writer.py_function(self.getter_c_name): + (this,) = writer.parse_arguments('args', ptr(self.parent)) + attr = self.name + ret = writer.declare(self.getter.fullname, + '%(this)s->%(attr)s' % locals()) + writer.return_value(self.getter.wrap(writer, ret)) + # setter + with writer.py_function(self.setter_c_name): + (this, value) = writer.parse_arguments('args', ptr(self.parent), + self.setter) + attr = self.name + writer.println('%(this)s->%(attr)s = %(value)s;' % locals()) + writer.return_value(None) + + def compile_py(self, writer): + name = self.name + parent = '.'.join(self.parent.fullname.split('::')[1:]) + getter = '.'.join([parent, self.getter_name]) + setter = '.'.join([parent, self.setter_name]) + writer.println('@property') + with writer.block('def %(name)s(self):' % locals()): + unself = writer.unwrap('self') + ret = writer.new_symbol('ret') + writer.println('%(ret)s = _api.%(getter)s(%(unself)s)' % locals()) + is_ownedptr = isinstance(self.getter, ownedptr) + writer.return_value(writer.wrap(ret, is_ownedptr)) + writer.println() + writer.println('@%(name)s.setter' % locals()) + with writer.block('def %(name)s(self, value):' % locals()): + unself = writer.unwrap('self') + unvalue = writer.unwrap('value') + if isinstance(self.setter, ownedptr): + writer.release_ownership(unvalue) + writer.println('return _api.%(setter)s(%(unself)s, %(unvalue)s)' % + locals()) + writer.println() + + diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index 46dd42a..c69f177 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -163,13 +163,13 @@ PyObject* iplist_to_pylist(iplist &IPL, const char * capsuleName, className); } -static -bool string_equal(const char *A, const char *B){ - for (; *A and *B; ++A, ++B) { - if (*A != *B) return false; - } - return true; -} +//static +//bool string_equal(const char *A, const char *B){ +// for (; *A and *B; ++A, ++B) { +// if (*A != *B) return false; +// } +// return true; +//} //////////// static diff --git a/newbinding/src/namespace.py b/newbinding/namespace.py similarity index 100% rename from newbinding/src/namespace.py rename to newbinding/namespace.py diff --git a/newbinding/src/EngineBuilder.py b/newbinding/src/EngineBuilder.py index 07ffcc0..d9594f0 100644 --- a/newbinding/src/EngineBuilder.py +++ b/newbinding/src/EngineBuilder.py @@ -50,8 +50,9 @@ class EngineBuilder: _selectTarget0.realname = 'selectTarget' _selectTarget1 = CustomMethod('EngineBuilder_selectTarget', + PyObjectPtr, const(ref(Triple)), cast(str, StringRef), - cast(str, StringRef), PyObjectPtr), + cast(str, StringRef), PyObjectPtr) @CustomPythonMethod def selectTarget(self, *args): diff --git a/newbinding/src/PassManagerBuilder.py b/newbinding/src/PassManagerBuilder.py index 2e2ea5e..11fedfb 100644 --- a/newbinding/src/PassManagerBuilder.py +++ b/newbinding/src/PassManagerBuilder.py @@ -1,6 +1,8 @@ from binding import * from namespace import llvm from PassManager import PassManagerBase, FunctionPassManager +from TargetLibraryInfo import TargetLibraryInfo +from Pass import Pass @llvm.Class() class PassManagerBuilder: @@ -17,3 +19,25 @@ class PassManagerBuilder: cast(bool, Bool), cast(bool, Bool)).require_only(3) + def _attr_int(): + return Attr(getter=cast(Unsigned, int), + setter=cast(int, Unsigned)) + + OptLevel = _attr_int() + SizeLevel = _attr_int() + + def _attr_bool(): + return Attr(getter=cast(Bool, bool), + setter=cast(bool, Bool)) + + DisableSimplifyLibCalls = _attr_bool() + DisableUnitAtATime = _attr_bool() + DisableUnrollLoops = _attr_bool() + Vectorize = _attr_bool() + LoopVectorize = _attr_bool() + + LibraryInfo = Attr(getter=ownedptr(TargetLibraryInfo), + setter=ownedptr(TargetLibraryInfo)) + + Inliner = Attr(getter=ownedptr(Pass), + setter=ownedptr(Pass)) diff --git a/newbinding/src/Transforms/IPO.py b/newbinding/src/Transforms/IPO.py new file mode 100644 index 0000000..6c2fc26 --- /dev/null +++ b/newbinding/src/Transforms/IPO.py @@ -0,0 +1,9 @@ +from binding import * +from namespace import llvm +from ..Pass import Pass + +llvm.includes.add('llvm/Transforms/IPO.h') + +createFunctionInliningPass = llvm.Function('createFunctionInliningPass', + ptr(Pass), + cast(int, Unsigned)).require_only(0) diff --git a/newbinding/src/Transforms/__init__.py b/newbinding/src/Transforms/__init__.py new file mode 100644 index 0000000..da0beed --- /dev/null +++ b/newbinding/src/Transforms/__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/__init__.py b/newbinding/src/__init__.py index 1042826..f67a3c4 100644 --- a/newbinding/src/__init__.py +++ b/newbinding/src/__init__.py @@ -5,7 +5,8 @@ def _init(): if ((fname.endswith('.py') or fname.endswith('.pyc')) and not fname.startswith('__init__')): modname = os.path.basename(fname).rsplit('.', 1)[0] - topname = __name__.rsplit('.', 1)[0] - importlib.import_module('.' + modname, topname) + importlib.import_module('.' + modname, __name__) _init() + +import Transforms \ No newline at end of file diff --git a/newbinding/test2.py b/newbinding/test2.py index e2f8dd2..248e32a 100644 --- a/newbinding/test2.py +++ b/newbinding/test2.py @@ -84,6 +84,10 @@ def test_basic_jit_use(): # build pass manager pmb = api.PassManagerBuilder.new() + pmb.OptLevel = 3 + assert pmb.OptLevel == 3 + pmb.LibraryInfo = api.TargetLibraryInfo.new() + pmb.Inliner = api.createFunctionInliningPass() fpm = api.FunctionPassManager.new(m) pm = api.PassManager.new() From c085bef46e4bd03ca60abff0ba46928ce7f81ad7 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Sun, 3 Feb 2013 15:01:57 -0600 Subject: [PATCH 42/85] Rename the tests --- newbinding/Makefile | 4 +-- newbinding/test.py | 32 ------------------------ newbinding/{test2.py => test_binding.py} | 0 3 files changed, 2 insertions(+), 34 deletions(-) delete mode 100644 newbinding/test.py rename newbinding/{test2.py => test_binding.py} (100%) diff --git a/newbinding/Makefile b/newbinding/Makefile index 735d4ff..8573235 100644 --- a/newbinding/Makefile +++ b/newbinding/Makefile @@ -13,10 +13,10 @@ clean: cleantemp cleantemp: rm -f api.cpp api.py - rm -f src/*.pyc + rm -f src/*.pyc src/Transforms/*.pyc check: _api.so api.py - $(PYTHON) test2.py + $(PYTHON) test_binding.py @PHONY: all clean check diff --git a/newbinding/test.py b/newbinding/test.py deleted file mode 100644 index bed9e1a..0000000 --- a/newbinding/test.py +++ /dev/null @@ -1,32 +0,0 @@ -import _api - -context = _api.getGlobalContext() -modname = "modname" -module = _api.Module.new(modname, context) -assert modname == _api.Module.getModuleIdentifier(module) -modname2 = "newmodname" -_api.Module.setModuleIdentifier(module, modname2) -assert modname2 == _api.Module.getModuleIdentifier(module) - -_api.Module.dump(module) - -_api.Module.delete(module) - -voidty = _api.Type.getVoidTy(context) -assert _api.Type.isVoidTy(voidty) -assert not _api.Type.isLabelTy(voidty) - -int21ty = _api.Type.getIntNTy(context, 21) -assert _api.Type.isIntegerTy(int21ty) -assert _api.Type.isIntegerTy(int21ty, 21) -_api.Type.dump(int21ty) - -halfty = _api.Type.getHalfTy(context) -assert _api.Type.isHalfTy(halfty) -_api.Type.dump(halfty) - -fnty = _api.FunctionType.get(halfty, False) -_api.Type.dump(fnty) - - - diff --git a/newbinding/test2.py b/newbinding/test_binding.py similarity index 100% rename from newbinding/test2.py rename to newbinding/test_binding.py From 961c5e99e1191f44fb192d226119877f695a84ce Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Sun, 3 Feb 2013 15:09:07 -0600 Subject: [PATCH 43/85] Re-organize --- newbinding/Makefile | 6 +++--- newbinding/{ => gen}/binding.py | 0 newbinding/{ => gen}/codegen.py | 0 newbinding/{ => gen}/gen.py | 4 ++-- newbinding/src/{ => ADT}/SmallVector.py | 2 +- newbinding/src/{ => ADT}/StringRef.py | 2 +- newbinding/src/{ => ADT}/Triple.py | 2 +- newbinding/src/ADT/__init__.py | 10 ++++++++++ .../AssemblyAnnotationWriter.py | 2 +- newbinding/src/Assembly/__init__.py | 10 ++++++++++ newbinding/src/BasicBlock.py | 2 +- .../src/{ => CodeGen}/MachineCodeInfo.py | 2 +- newbinding/src/CodeGen/__init__.py | 10 ++++++++++ newbinding/src/DataLayout.py | 4 ++-- newbinding/src/DerivedTypes.py | 2 +- newbinding/src/EngineBuilder.py | 10 +++++----- .../{ => ExecutionEngine}/ExecutionEngine.py | 20 +++++++++---------- newbinding/src/ExecutionEngine/__init__.py | 10 ++++++++++ newbinding/src/IRBuilder.py | 4 ++-- newbinding/src/Module.py | 6 +++--- newbinding/src/Pass.py | 2 +- newbinding/src/{ => Support}/CodeGen.py | 2 +- newbinding/src/Support/MemoryBuffer.py | 9 +++++++++ newbinding/src/{ => Support}/Target.py | 4 ++-- newbinding/src/{ => Support}/TargetSelect.py | 4 ++-- newbinding/src/Support/__init__.py | 10 ++++++++++ newbinding/src/{ => Support}/raw_ostream.py | 6 +++--- .../src/{ => Target}/TargetLibraryInfo.py | 8 ++++---- newbinding/src/{ => Target}/TargetMachine.py | 16 +++++++-------- newbinding/src/Target/__init__.py | 10 ++++++++++ newbinding/src/TargetTransformInfo.py | 2 ++ newbinding/src/Transforms/IPO.py | 2 +- .../{ => Transforms}/PassManagerBuilder.py | 8 ++++---- newbinding/src/Type.py | 4 ++-- newbinding/src/Value.py | 6 +++--- newbinding/src/__init__.py | 2 +- newbinding/{ => src}/namespace.py | 0 37 files changed, 137 insertions(+), 66 deletions(-) rename newbinding/{ => gen}/binding.py (100%) rename newbinding/{ => gen}/codegen.py (100%) rename newbinding/{ => gen}/gen.py (98%) rename newbinding/src/{ => ADT}/SmallVector.py (92%) rename newbinding/src/{ => ADT}/StringRef.py (76%) rename newbinding/src/{ => ADT}/Triple.py (98%) create mode 100644 newbinding/src/ADT/__init__.py rename newbinding/src/{ => Assembly}/AssemblyAnnotationWriter.py (81%) create mode 100644 newbinding/src/Assembly/__init__.py rename newbinding/src/{ => CodeGen}/MachineCodeInfo.py (91%) create mode 100644 newbinding/src/CodeGen/__init__.py rename newbinding/src/{ => ExecutionEngine}/ExecutionEngine.py (89%) create mode 100644 newbinding/src/ExecutionEngine/__init__.py rename newbinding/src/{ => Support}/CodeGen.py (93%) create mode 100644 newbinding/src/Support/MemoryBuffer.py rename newbinding/src/{ => Support}/Target.py (89%) rename newbinding/src/{ => Support}/TargetSelect.py (54%) create mode 100644 newbinding/src/Support/__init__.py rename newbinding/src/{ => Support}/raw_ostream.py (73%) rename newbinding/src/{ => Target}/TargetLibraryInfo.py (95%) rename newbinding/src/{ => Target}/TargetMachine.py (72%) create mode 100644 newbinding/src/Target/__init__.py rename newbinding/src/{ => Transforms}/PassManagerBuilder.py (88%) rename newbinding/{ => src}/namespace.py (100%) diff --git a/newbinding/Makefile b/newbinding/Makefile index 8573235..0e7924f 100644 --- a/newbinding/Makefile +++ b/newbinding/Makefile @@ -5,15 +5,15 @@ all: _api.so _capsule.so _api.so _capsule.so: api.cpp capsule.cpp $(PYTHON) setup.py build_ext --inplace -api.cpp api.py: src/*.py include/llvm_binding/*.h gen.py binding.py - $(PYTHON) gen.py api src +api.cpp api.py: src/*.py include/llvm_binding/*.h gen/gen.py gen/binding.py + $(PYTHON) gen/gen.py api src clean: cleantemp rm -f _api.so _capsule.so cleantemp: rm -f api.cpp api.py - rm -f src/*.pyc src/Transforms/*.pyc + rm -f src/*.pyc src/Transforms/*.pyc src/ADT/*.pyc src/Assembly/*.pyc src/CodeGen/*.pyc src/ExecutionEngine/*.pyc src/Target/*.pyc src/Transforms/*.pyc check: _api.so api.py diff --git a/newbinding/binding.py b/newbinding/gen/binding.py similarity index 100% rename from newbinding/binding.py rename to newbinding/gen/binding.py diff --git a/newbinding/codegen.py b/newbinding/gen/codegen.py similarity index 100% rename from newbinding/codegen.py rename to newbinding/gen/codegen.py diff --git a/newbinding/gen.py b/newbinding/gen/gen.py similarity index 98% rename from newbinding/gen.py rename to newbinding/gen/gen.py index 7c56452..89399f3 100644 --- a/newbinding/gen.py +++ b/newbinding/gen/gen.py @@ -1,4 +1,4 @@ -import sys +import sys, os from binding import * import codegen @@ -59,7 +59,7 @@ def wrap_println_from_file(file): def main(): outputfilename = sys.argv[1] entry_modname = sys.argv[2] - + sys.path += [os.path.dirname(os.curdir)] entry_module = __import__(entry_modname) units = [] diff --git a/newbinding/src/SmallVector.py b/newbinding/src/ADT/SmallVector.py similarity index 92% rename from newbinding/src/SmallVector.py rename to newbinding/src/ADT/SmallVector.py index 5b48aba..f52ff60 100644 --- a/newbinding/src/SmallVector.py +++ b/newbinding/src/ADT/SmallVector.py @@ -1,5 +1,5 @@ from binding import * -from namespace import llvm +from ..namespace import llvm @llvm.Class() class SmallVector_Type: diff --git a/newbinding/src/StringRef.py b/newbinding/src/ADT/StringRef.py similarity index 76% rename from newbinding/src/StringRef.py rename to newbinding/src/ADT/StringRef.py index fb3b896..e6fc8f2 100644 --- a/newbinding/src/StringRef.py +++ b/newbinding/src/ADT/StringRef.py @@ -1,5 +1,5 @@ from binding import * -from namespace import llvm +from ..namespace import llvm @llvm.Class() class StringRef: diff --git a/newbinding/src/Triple.py b/newbinding/src/ADT/Triple.py similarity index 98% rename from newbinding/src/Triple.py rename to newbinding/src/ADT/Triple.py index 0fd894e..82de57e 100644 --- a/newbinding/src/Triple.py +++ b/newbinding/src/ADT/Triple.py @@ -1,5 +1,5 @@ from binding import * -from namespace import llvm +from ..namespace import llvm from StringRef import StringRef Triple = llvm.Class() diff --git a/newbinding/src/ADT/__init__.py b/newbinding/src/ADT/__init__.py new file mode 100644 index 0000000..da0beed --- /dev/null +++ b/newbinding/src/ADT/__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/AssemblyAnnotationWriter.py b/newbinding/src/Assembly/AssemblyAnnotationWriter.py similarity index 81% rename from newbinding/src/AssemblyAnnotationWriter.py rename to newbinding/src/Assembly/AssemblyAnnotationWriter.py index d2b5a5d..6b4d694 100644 --- a/newbinding/src/AssemblyAnnotationWriter.py +++ b/newbinding/src/Assembly/AssemblyAnnotationWriter.py @@ -1,5 +1,5 @@ from binding import * -from namespace import llvm +from ..namespace import llvm @llvm.Class() class AssemblyAnnotationWriter: diff --git a/newbinding/src/Assembly/__init__.py b/newbinding/src/Assembly/__init__.py new file mode 100644 index 0000000..da0beed --- /dev/null +++ b/newbinding/src/Assembly/__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/BasicBlock.py b/newbinding/src/BasicBlock.py index b0716cd..61a09d7 100644 --- a/newbinding/src/BasicBlock.py +++ b/newbinding/src/BasicBlock.py @@ -3,7 +3,7 @@ from namespace import llvm from Value import Function, BasicBlock from Instruction import Instruction, TerminatorInst from LLVMContext import LLVMContext -from StringRef import StringRef +from ADT.StringRef import StringRef @BasicBlock class BasicBlock: diff --git a/newbinding/src/MachineCodeInfo.py b/newbinding/src/CodeGen/MachineCodeInfo.py similarity index 91% rename from newbinding/src/MachineCodeInfo.py rename to newbinding/src/CodeGen/MachineCodeInfo.py index 5d91e3a..fc3a1b6 100644 --- a/newbinding/src/MachineCodeInfo.py +++ b/newbinding/src/CodeGen/MachineCodeInfo.py @@ -1,5 +1,5 @@ from binding import * -from namespace import llvm +from ..namespace import llvm MachineCodeInfo = llvm.Class() diff --git a/newbinding/src/CodeGen/__init__.py b/newbinding/src/CodeGen/__init__.py new file mode 100644 index 0000000..da0beed --- /dev/null +++ b/newbinding/src/CodeGen/__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/DataLayout.py b/newbinding/src/DataLayout.py index 74d1ad0..704c4b1 100644 --- a/newbinding/src/DataLayout.py +++ b/newbinding/src/DataLayout.py @@ -1,10 +1,10 @@ from binding import * from namespace import llvm from LLVMContext import LLVMContext -from StringRef import StringRef +from ADT.StringRef import StringRef from Module import Module from Type import Type, IntegerType, StructType -from SmallVector import SmallVector_Value +from ADT.SmallVector import SmallVector_Value from GlobalVariable import GlobalVariable from Pass import ImmutablePass diff --git a/newbinding/src/DerivedTypes.py b/newbinding/src/DerivedTypes.py index efce8b8..af9e757 100644 --- a/newbinding/src/DerivedTypes.py +++ b/newbinding/src/DerivedTypes.py @@ -2,7 +2,7 @@ from binding import * from namespace import llvm from LLVMContext import LLVMContext from Type import Type -from SmallVector import SmallVector_Type +from ADT.SmallVector import SmallVector_Type FunctionType = llvm.Class(Type) diff --git a/newbinding/src/EngineBuilder.py b/newbinding/src/EngineBuilder.py index d9594f0..4b68a25 100644 --- a/newbinding/src/EngineBuilder.py +++ b/newbinding/src/EngineBuilder.py @@ -2,11 +2,11 @@ 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 -from Triple import Triple +from Support.CodeGen import CodeGenOpt, Reloc, CodeModel +from ADT.StringRef import StringRef +from ExecutionEngine.ExecutionEngine import ExecutionEngine +from Target.TargetMachine import TargetMachine +from ADT.Triple import Triple EngineBuilder = llvm.Class() diff --git a/newbinding/src/ExecutionEngine.py b/newbinding/src/ExecutionEngine/ExecutionEngine.py similarity index 89% rename from newbinding/src/ExecutionEngine.py rename to newbinding/src/ExecutionEngine/ExecutionEngine.py index 5a95a16..f4bdb14 100644 --- a/newbinding/src/ExecutionEngine.py +++ b/newbinding/src/ExecutionEngine/ExecutionEngine.py @@ -1,14 +1,14 @@ from binding import * -from namespace import llvm -from Module import Module -from JITMemoryManager import JITMemoryManager -from CodeGen import CodeGenOpt, Reloc, CodeModel -from DataLayout import DataLayout -from Value import Function, GlobalValue, BasicBlock, Constant -from GlobalVariable import GlobalVariable -from MachineCodeInfo import MachineCodeInfo -from GenericValue import GenericValue -from Type import Type +from ..namespace import llvm +from ..Module import Module +from ..JITMemoryManager import JITMemoryManager +from ..Support.CodeGen import CodeGenOpt, Reloc, CodeModel +from ..DataLayout import DataLayout +from ..Value import Function, GlobalValue, BasicBlock, Constant +from ..GlobalVariable import GlobalVariable +from ..CodeGen.MachineCodeInfo import MachineCodeInfo +from ..GenericValue import GenericValue +from ..Type import Type ExecutionEngine = llvm.Class() diff --git a/newbinding/src/ExecutionEngine/__init__.py b/newbinding/src/ExecutionEngine/__init__.py new file mode 100644 index 0000000..da0beed --- /dev/null +++ b/newbinding/src/ExecutionEngine/__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/IRBuilder.py b/newbinding/src/IRBuilder.py index cea94ce..61dd99b 100644 --- a/newbinding/src/IRBuilder.py +++ b/newbinding/src/IRBuilder.py @@ -8,8 +8,8 @@ from Instruction import UnreachableInst, AllocaInst, LoadInst, StoreInst from Instruction import FenceInst, AtomicCmpXchgInst, AtomicRMWInst, CmpInst from Instruction import LandingPadInst, VAArgInst from Instruction import AtomicOrdering, SynchronizationScope -from SmallVector import SmallVector_Value, SmallVector_Unsigned -from StringRef import StringRef +from ADT.SmallVector import SmallVector_Value, SmallVector_Unsigned +from ADT.StringRef import StringRef from Value import Value, MDNode from Type import Type, IntegerType diff --git a/newbinding/src/Module.py b/newbinding/src/Module.py index 9b392ca..539c486 100644 --- a/newbinding/src/Module.py +++ b/newbinding/src/Module.py @@ -1,12 +1,12 @@ from binding import * from namespace import llvm from LLVMContext import LLVMContext -from StringRef import StringRef +from ADT.StringRef import StringRef from Constant import Constant from Function import Function from DerivedTypes import FunctionType -from raw_ostream import raw_ostream -from AssemblyAnnotationWriter import AssemblyAnnotationWriter +from Support.raw_ostream import raw_ostream +from Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter @llvm.Class() class Module: diff --git a/newbinding/src/Pass.py b/newbinding/src/Pass.py index 5842232..39e894b 100644 --- a/newbinding/src/Pass.py +++ b/newbinding/src/Pass.py @@ -1,6 +1,6 @@ from binding import * from namespace import llvm -from StringRef import StringRef +from ADT.StringRef import StringRef from Module import Module from Function import Function diff --git a/newbinding/src/CodeGen.py b/newbinding/src/Support/CodeGen.py similarity index 93% rename from newbinding/src/CodeGen.py rename to newbinding/src/Support/CodeGen.py index 7afcd49..013caa1 100644 --- a/newbinding/src/CodeGen.py +++ b/newbinding/src/Support/CodeGen.py @@ -1,5 +1,5 @@ from binding import * -from namespace import llvm +from ..namespace import llvm @llvm.Class() class Reloc: diff --git a/newbinding/src/Support/MemoryBuffer.py b/newbinding/src/Support/MemoryBuffer.py new file mode 100644 index 0000000..b960fe6 --- /dev/null +++ b/newbinding/src/Support/MemoryBuffer.py @@ -0,0 +1,9 @@ +from binding import * +from ..namespace import llvm + +MemoryBuffer = llvm.Class() + +@MemoryBuffer +class MemoryBuffer: + _include_ = 'llvm/Support/MemoryBuffer.h' + diff --git a/newbinding/src/Target.py b/newbinding/src/Support/Target.py similarity index 89% rename from newbinding/src/Target.py rename to newbinding/src/Support/Target.py index 3c2a0e1..bdaeff5 100644 --- a/newbinding/src/Target.py +++ b/newbinding/src/Support/Target.py @@ -1,6 +1,6 @@ from binding import * -from namespace import llvm -from StringRef import StringRef +from ..namespace import llvm +from ..ADT.StringRef import StringRef Target = llvm.Class() @Target diff --git a/newbinding/src/TargetSelect.py b/newbinding/src/Support/TargetSelect.py similarity index 54% rename from newbinding/src/TargetSelect.py rename to newbinding/src/Support/TargetSelect.py index cb2eb96..4a2b171 100644 --- a/newbinding/src/TargetSelect.py +++ b/newbinding/src/Support/TargetSelect.py @@ -1,8 +1,8 @@ from binding import * -from namespace import llvm +from ..namespace import llvm llvm.includes.add('llvm/Support/TargetSelect.h') -llvm.Function('InitializeNativeTarget') +InitializeNativeTarget = llvm.Function('InitializeNativeTarget') #llvm.Function('InitializeAllTargets') diff --git a/newbinding/src/Support/__init__.py b/newbinding/src/Support/__init__.py new file mode 100644 index 0000000..da0beed --- /dev/null +++ b/newbinding/src/Support/__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/raw_ostream.py b/newbinding/src/Support/raw_ostream.py similarity index 73% rename from newbinding/src/raw_ostream.py rename to newbinding/src/Support/raw_ostream.py index 2f5a6f5..ecf3614 100644 --- a/newbinding/src/raw_ostream.py +++ b/newbinding/src/Support/raw_ostream.py @@ -1,7 +1,7 @@ from binding import * -from namespace import llvm -from LLVMContext import LLVMContext -from StringRef import StringRef +from ..namespace import llvm +from ..LLVMContext import LLVMContext +from ..ADT.StringRef import StringRef @llvm.Class() class raw_ostream: diff --git a/newbinding/src/TargetLibraryInfo.py b/newbinding/src/Target/TargetLibraryInfo.py similarity index 95% rename from newbinding/src/TargetLibraryInfo.py rename to newbinding/src/Target/TargetLibraryInfo.py index a5ba28d..b90c619 100644 --- a/newbinding/src/TargetLibraryInfo.py +++ b/newbinding/src/Target/TargetLibraryInfo.py @@ -1,8 +1,8 @@ from binding import * -from namespace import llvm -from Triple import Triple -from Pass import ImmutablePass -from StringRef import StringRef +from ..namespace import llvm +from ..ADT.Triple import Triple +from ..Pass import ImmutablePass +from ..ADT.StringRef import StringRef TargetLibraryInfo = llvm.Class(ImmutablePass) diff --git a/newbinding/src/TargetMachine.py b/newbinding/src/Target/TargetMachine.py similarity index 72% rename from newbinding/src/TargetMachine.py rename to newbinding/src/Target/TargetMachine.py index 5910585..3fc16e2 100644 --- a/newbinding/src/TargetMachine.py +++ b/newbinding/src/Target/TargetMachine.py @@ -1,12 +1,12 @@ from binding import * -from namespace import llvm -from StringRef import StringRef -from CodeGen import CodeModel, TLSModel, CodeGenOpt, Reloc -from GlobalValue import GlobalValue -from Target import Target -from DataLayout import DataLayout -from TargetTransformInfo import (ScalarTargetTransformInfo, - VectorTargetTransformInfo) +from ..namespace import llvm +from ..ADT.StringRef import StringRef +from ..Support.CodeGen import CodeModel, TLSModel, CodeGenOpt, Reloc +from ..GlobalValue import GlobalValue +from ..Support.Target import Target +from ..DataLayout import DataLayout +from ..TargetTransformInfo import (ScalarTargetTransformInfo, + VectorTargetTransformInfo) TargetMachine = llvm.Class() diff --git a/newbinding/src/Target/__init__.py b/newbinding/src/Target/__init__.py new file mode 100644 index 0000000..da0beed --- /dev/null +++ b/newbinding/src/Target/__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/TargetTransformInfo.py b/newbinding/src/TargetTransformInfo.py index 8e3c17e..5761281 100644 --- a/newbinding/src/TargetTransformInfo.py +++ b/newbinding/src/TargetTransformInfo.py @@ -1,6 +1,8 @@ from binding import * from namespace import llvm +llvm.includes.add('llvm/TargetTransformInfo.h') + ScalarTargetTransformInfo = llvm.Class() VectorTargetTransformInfo = llvm.Class() diff --git a/newbinding/src/Transforms/IPO.py b/newbinding/src/Transforms/IPO.py index 6c2fc26..48b34f9 100644 --- a/newbinding/src/Transforms/IPO.py +++ b/newbinding/src/Transforms/IPO.py @@ -1,5 +1,5 @@ from binding import * -from namespace import llvm +from ..namespace import llvm from ..Pass import Pass llvm.includes.add('llvm/Transforms/IPO.h') diff --git a/newbinding/src/PassManagerBuilder.py b/newbinding/src/Transforms/PassManagerBuilder.py similarity index 88% rename from newbinding/src/PassManagerBuilder.py rename to newbinding/src/Transforms/PassManagerBuilder.py index 11fedfb..a95b6df 100644 --- a/newbinding/src/PassManagerBuilder.py +++ b/newbinding/src/Transforms/PassManagerBuilder.py @@ -1,8 +1,8 @@ from binding import * -from namespace import llvm -from PassManager import PassManagerBase, FunctionPassManager -from TargetLibraryInfo import TargetLibraryInfo -from Pass import Pass +from ..namespace import llvm +from ..PassManager import PassManagerBase, FunctionPassManager +from ..Target.TargetLibraryInfo import TargetLibraryInfo +from ..Pass import Pass @llvm.Class() class PassManagerBuilder: diff --git a/newbinding/src/Type.py b/newbinding/src/Type.py index bf51b9d..8e6b381 100644 --- a/newbinding/src/Type.py +++ b/newbinding/src/Type.py @@ -1,8 +1,8 @@ from binding import * from namespace import llvm from LLVMContext import LLVMContext -from raw_ostream import raw_ostream -from StringRef import StringRef +from Support.raw_ostream import raw_ostream +from ADT.StringRef import StringRef Type = llvm.Class() IntegerType = llvm.Class(Type) diff --git a/newbinding/src/Value.py b/newbinding/src/Value.py index 7460c90..5841746 100644 --- a/newbinding/src/Value.py +++ b/newbinding/src/Value.py @@ -1,10 +1,10 @@ from binding import * from namespace import llvm -from raw_ostream import raw_ostream -from AssemblyAnnotationWriter import AssemblyAnnotationWriter +from Support.raw_ostream import raw_ostream +from Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter from Type import Type from LLVMContext import LLVMContext -from StringRef import StringRef +from ADT.StringRef import StringRef Value = llvm.Class() # forward declarations diff --git a/newbinding/src/__init__.py b/newbinding/src/__init__.py index f67a3c4..8a1b356 100644 --- a/newbinding/src/__init__.py +++ b/newbinding/src/__init__.py @@ -9,4 +9,4 @@ def _init(): _init() -import Transforms \ No newline at end of file +import Transforms, ADT, Support, Assembly, ExecutionEngine, CodeGen, Target diff --git a/newbinding/namespace.py b/newbinding/src/namespace.py similarity index 100% rename from newbinding/namespace.py rename to newbinding/src/namespace.py From 168510222fc4d0975635d6b76befaff2ed14dd55 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 4 Feb 2013 16:45:49 -0600 Subject: [PATCH 44/85] Add Module bitcode writer/parser --- newbinding/gen/binding.py | 16 ++++++- newbinding/include/llvm_binding/extra.h | 60 +++++++++++++++++++++++++ newbinding/src/Bitcode/ReaderWriter.py | 30 +++++++++++++ newbinding/src/Bitcode/__init__.py | 10 +++++ newbinding/src/Support/MemoryBuffer.py | 9 ---- newbinding/src/__init__.py | 11 +++-- newbinding/test_binding.py | 16 +++++++ 7 files changed, 138 insertions(+), 14 deletions(-) create mode 100644 newbinding/src/Bitcode/ReaderWriter.py create mode 100644 newbinding/src/Bitcode/__init__.py delete mode 100644 newbinding/src/Support/MemoryBuffer.py 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() From da85049eb9efbb6174dc73e07914e2060fc50f15 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 5 Feb 2013 13:44:59 -0600 Subject: [PATCH 45/85] Add support to emit assembly. --- newbinding/include/llvm_binding/extra.h | 31 ++++++++++++++++++++ newbinding/src/Support/FormattedStream.py | 9 ++++++ newbinding/src/Support/TargetSelect.py | 9 ++++++ newbinding/src/Support/raw_ostream.py | 1 + newbinding/src/Target/TargetMachine.py | 17 +++++++++++ newbinding/test_binding.py | 35 +++++++++++++++++++++++ 6 files changed, 102 insertions(+) create mode 100644 newbinding/src/Support/FormattedStream.py diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index e8f39cb..77b399d 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -465,3 +466,33 @@ PyObject* llvm_getBitcodeTargetTriple(llvm::StringRef Buf, delete MB; return PyString_FromString(Triple.c_str()); } + +static +PyObject* TargetMachine_addPassesToEmitFile( + llvm::TargetMachine *TM, + llvm::PassManagerBase & PM, + PyObject* Out, + llvm::TargetMachine::CodeGenFileType FTy, + bool disableVerify=true) +{ + using namespace llvm; + llvm::SmallVector sv; + raw_svector_ostream rso(sv); + formatted_raw_ostream fso(rso); + fso.flush(); + bool status = TM->addPassesToEmitFile(PM, fso, FTy, disableVerify); + if (status) { + StringRef sr = rso.str(); + PyObject* buf = PyString_FromStringAndSize(sr.data(), sr.size()); + if (!buf) { + return NULL; + } + if ( -1 == PyFile_WriteObject(buf, Out, Py_PRINT_RAW) ){ + return NULL; + } + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } +} + diff --git a/newbinding/src/Support/FormattedStream.py b/newbinding/src/Support/FormattedStream.py new file mode 100644 index 0000000..17c259b --- /dev/null +++ b/newbinding/src/Support/FormattedStream.py @@ -0,0 +1,9 @@ +from binding import * +from ..namespace import llvm +from raw_ostream import raw_ostream + +@llvm.Class(raw_ostream) +class formatted_raw_ostream: + _include_ = 'llvm/Support/FormattedStream.h' + new = Constructor(ref(raw_ostream), cast(bool, Bool)) + diff --git a/newbinding/src/Support/TargetSelect.py b/newbinding/src/Support/TargetSelect.py index 4a2b171..208ef4b 100644 --- a/newbinding/src/Support/TargetSelect.py +++ b/newbinding/src/Support/TargetSelect.py @@ -6,3 +6,12 @@ llvm.includes.add('llvm/Support/TargetSelect.h') InitializeNativeTarget = llvm.Function('InitializeNativeTarget') #llvm.Function('InitializeAllTargets') +InitializeNativeTargetAsmPrinter = llvm.Function( + 'InitializeNativeTargetAsmPrinter', cast(Bool, bool)) + +InitializeNativeTargetAsmParser = llvm.Function( + 'InitializeNativeTargetAsmParser', cast(Bool, bool)) + +InitializeNativeTargetDisassembler = llvm.Function( + 'InitializeNativeTargetDisassembler', cast(Bool, bool)) + diff --git a/newbinding/src/Support/raw_ostream.py b/newbinding/src/Support/raw_ostream.py index ecf3614..dcce73f 100644 --- a/newbinding/src/Support/raw_ostream.py +++ b/newbinding/src/Support/raw_ostream.py @@ -7,6 +7,7 @@ from ..ADT.StringRef import StringRef class raw_ostream: _include_ = "llvm/Support/raw_ostream.h" delete = Destructor() + flush = Method() @llvm.Class(raw_ostream) class raw_svector_ostream: diff --git a/newbinding/src/Target/TargetMachine.py b/newbinding/src/Target/TargetMachine.py index 3fc16e2..e60ed5c 100644 --- a/newbinding/src/Target/TargetMachine.py +++ b/newbinding/src/Target/TargetMachine.py @@ -7,12 +7,20 @@ from ..Support.Target import Target from ..DataLayout import DataLayout from ..TargetTransformInfo import (ScalarTargetTransformInfo, VectorTargetTransformInfo) +from ..PassManager import PassManagerBase +from ..Support.FormattedStream import formatted_raw_ostream TargetMachine = llvm.Class() @TargetMachine class TargetMachine: _include_ = 'llvm/Target/TargetMachine.h' + + CodeGenFileType = Enum(''' + CGFT_AssemblyFile + CGFT_ObjectFile + CGFT_Null''') + delete = Destructor() getTarget = Method(const(ref(Target))) @@ -34,3 +42,12 @@ class TargetMachine: ownedptr(ScalarTargetTransformInfo))) getVectorTargetTransformInfo = Method(const( ownedptr(VectorTargetTransformInfo))) + + addPassesToEmitFile = Method(cast(bool, Bool), + ref(PassManagerBase), + ref(formatted_raw_ostream), + CodeGenFileType, + cast(bool, Bool) + ).require_only(3) + + diff --git a/newbinding/test_binding.py b/newbinding/test_binding.py index 8a72aef..1321eb6 100644 --- a/newbinding/test_binding.py +++ b/newbinding/test_binding.py @@ -6,6 +6,7 @@ api.capsule.set_debug(True) def test_basic_jit_use(): api.InitializeNativeTarget() + api.InitializeNativeTargetAsmPrinter() context = api.getGlobalContext() m = api.Module.new("modname", context) @@ -157,6 +158,16 @@ def test_engine_builder(): m = api.Module.new("modname", context) + int32ty = api.Type.getIntNTy(context, 32) + fnty = api.FunctionType.get(int32ty, [int32ty], False) + fn = m.getOrInsertFunction("foo", fnty)._downcast(api.Function) + bb = api.BasicBlock.Create(context, "entry", fn, None) + builder = api.IRBuilder.new(context) + builder.SetInsertPoint(bb) + builder.CreateRet(fn.getArgumentList()[0]) + + print fn + eb = api.EngineBuilder.new(m) eb2 = eb.setEngineKind(api.EngineKind.Kind.JIT) assert eb is eb2 @@ -192,6 +203,30 @@ def test_engine_builder(): pm.add(api.DataLayout.new(str(tm.getDataLayout()))) pm.add(api.TargetLibraryInfo.new()) + # write assembly + pm = api.PassManager.new() + pm.add(api.DataLayout.new(str(tm.getDataLayout()))) + + raw = extra.make_raw_ostream_for_printing() + formatted = api.formatted_raw_ostream.new(raw, False) + + cgft = api.TargetMachine.CodeGenFileType.CGFT_AssemblyFile + failed = tm.addPassesToEmitFile(pm, formatted, cgft, False) + assert not failed + + pm.run(m) + + formatted.flush() + raw.flush() + asm = raw.str() + print asm + assert 'foo' in asm + + + + + + def main(): for name, value in globals().items(): From 450c29e0523fbae1b0772147d2490de33affa754 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 5 Feb 2013 15:30:43 -0600 Subject: [PATCH 46/85] Swap out old llvm code --- llvm/2.9_update.diff | 2117 ------------------------------------- llvm/__init__.py | 154 --- llvm/_core.cpp | 2212 --------------------------------------- llvm/_dwarf.cpp | 86 -- llvm/_dwarf.h | 101 -- llvm/_util.py | 108 -- llvm/_version.py | 193 ---- llvm/capsulethunk.h | 134 --- llvm/core.py | 2158 +------------------------------------- llvm/debuginfo.py | 398 ------- llvm/ee.py | 392 ------- llvm/extra.cpp | 1361 ------------------------ llvm/extra.h | 676 ------------ llvm/llvm_c_extra.h | 31 - llvm/passes.py | 417 -------- llvm/py3k_update.diff | 973 ----------------- llvm/py3k_update.output | 62 -- llvm/tbaa.py | 51 - llvm/test_llvmpy.py | 1249 ---------------------- llvm/wrap.cpp | 70 -- llvm/wrap.h | 1277 ---------------------- 21 files changed, 20 insertions(+), 14200 deletions(-) delete mode 100644 llvm/2.9_update.diff delete mode 100644 llvm/_core.cpp delete mode 100644 llvm/_dwarf.cpp delete mode 100644 llvm/_dwarf.h delete mode 100644 llvm/_util.py delete mode 100644 llvm/_version.py delete mode 100644 llvm/capsulethunk.h delete mode 100644 llvm/debuginfo.py delete mode 100644 llvm/extra.cpp delete mode 100644 llvm/extra.h delete mode 100644 llvm/llvm_c_extra.h delete mode 100644 llvm/py3k_update.diff delete mode 100644 llvm/py3k_update.output delete mode 100644 llvm/tbaa.py delete mode 100644 llvm/test_llvmpy.py delete mode 100644 llvm/wrap.cpp delete mode 100644 llvm/wrap.h diff --git a/llvm/2.9_update.diff b/llvm/2.9_update.diff deleted file mode 100644 index 5572286..0000000 --- a/llvm/2.9_update.diff +++ /dev/null @@ -1,2117 +0,0 @@ -Index: core.py -=================================================================== ---- core.py (revision 105) -+++ core.py (working copy) -@@ -51,14 +51,15 @@ - TYPE_FP128 = 4 - TYPE_PPC_FP128 = 5 - TYPE_LABEL = 6 --TYPE_INTEGER = 7 --TYPE_FUNCTION = 8 --TYPE_STRUCT = 9 --TYPE_ARRAY = 10 --TYPE_POINTER = 11 --TYPE_OPAQUE = 12 --TYPE_VECTOR = 13 --TYPE_METADATA = 14 -+TYPE_METADATA = 7 -+TYPE_X86_MMX = 8 -+TYPE_INTEGER = 9 -+TYPE_FUNCTION = 10 -+TYPE_STRUCT = 11 -+TYPE_ARRAY = 12 -+TYPE_POINTER = 13 -+TYPE_OPAQUE = 14 -+TYPE_VECTOR = 15 - - # value IDs (llvm::Value::ValueTy enum) - VALUE_ARGUMENT = 0 -@@ -140,11 +141,21 @@ - OPCODE_INSERTVALUE = 54 - - # calling conventions --CC_C = 0 --CC_FASTCALL = 8 --CC_COLDCALL = 9 --CC_X86_STDCALL = 64 --CC_X86_FASTCALL = 65 -+CC_C = 0 -+CC_FASTCALL = 8 -+CC_COLDCALL = 9 -+CC_GHC = 10 -+CC_X86_STDCALL = 64 -+CC_X86_FASTCALL = 65 -+CC_ARM_APCS = 66 -+CC_ARM_AAPCS = 67 -+CC_ARM_AAPCS_VFP = 68 -+CC_MSP430_INTR = 69 -+CC_X86_THISCALL = 70 -+CC_PTX_KERNEL = 71 -+CC_PTX_DEVICE = 72 -+CC_MBLAZE_INTR = 73 -+CC_MBLAZE_SVOL = 74 - - # int predicates - ICMP_EQ = 32 -@@ -248,11 +259,14 @@ - ATTR_OPTIMIZE_FOR_SIZE = 1<<13 - ATTR_STACK_PROTECT = 1<<14 - ATTR_STACK_PROTECT_REQ = 1<<15 -+ATTR_ALIGNMENT = 1<<16 - ATTR_NO_CAPTURE = 1<<21 - ATTR_NO_REDZONE = 1<<22 - ATTR_NO_IMPLICIT_FLOAT = 1<<23 - ATTR_NAKED = 1<<24 - ATTR_INLINE_HINT = 1<<25 -+ATTR_STACK_ALIGNMENT = 7<<26 -+ATTR_HOTPATCH = 1<<29 - - # intrinsic IDs - from llvm._intrinsic_ids import * -Index: extra.cpp -=================================================================== ---- extra.cpp (revision 105) -+++ extra.cpp (working copy) -@@ -54,7 +54,7 @@ - #include "llvm/IntrinsicInst.h" - #include "llvm/Analysis/Verifier.h" - #include "llvm/Assembly/Parser.h" --#include "llvm/System/DynamicLibrary.h" -+#include "llvm/Support/DynamicLibrary.h" - #include "llvm/PassManager.h" - #include "llvm/ExecutionEngine/ExecutionEngine.h" - #include "llvm/Analysis/LoopPass.h" -@@ -452,12 +452,19 @@ - return eep->getPointerToFunction(fnp); - } - -+ - int LLVMInlineFunction(LLVMValueRef call) - { - llvm::Value *callp = llvm::unwrap(call); - assert(callp); - -- llvm::CallSite cs = llvm::CallSite::get(callp); -+// llvm::CallSite cs = llvm::CallSite::get(callp); -+ llvm::CallSite cs; -+ llvm::Instruction *II = llvm::dyn_cast(callp); -+ if (II->getOpcode() == llvm::Instruction::Call) -+ cs = llvm::CallSite(static_cast(II)); -+ else if (II->getOpcode() == llvm::Instruction::Invoke) -+ cs = llvm::CallSite(static_cast(II)); - - llvm::InlineFunctionInfo unused; - return llvm::InlineFunction(cs, unused); -@@ -501,13 +508,13 @@ - define_pass( DomPrinter ) - define_pass( DomViewer ) - define_pass( EdgeProfiler ) --define_pass( GEPSplitter ) -+//define_pass( GEPSplitter ) - define_pass( GlobalsModRef ) - define_pass( InstCount ) - define_pass( InstructionNamer ) - define_pass( LazyValueInfo ) - define_pass( LCSSA ) --define_pass( LiveValues ) -+//define_pass( LiveValues ) - define_pass( LoopDependenceAnalysis ) - define_pass( LoopExtractor ) - define_pass( LoopSimplify ) -@@ -519,7 +526,7 @@ - define_pass( NoProfileInfo ) - define_pass( OptimalEdgeProfiler ) - define_pass( PartialInlining ) --define_pass( PartialSpecialization ) -+//define_pass( PartialSpecialization ) - define_pass( PostDomOnlyPrinter ) - define_pass( PostDomOnlyViewer ) - define_pass( PostDomPrinter ) -@@ -528,7 +535,7 @@ - define_pass( ProfileLoader ) - define_pass( ProfileVerifier ) - define_pass( ScalarEvolutionAliasAnalysis ) --define_pass( SimplifyHalfPowrLibCalls ) -+//define_pass( SimplifyHalfPowrLibCalls ) - define_pass( SingleLoopExtractor ) - define_pass( StripNonDebugSymbols ) - define_pass( StructRetPromotion ) -Index: passes.py -=================================================================== ---- passes.py (revision 105) -+++ passes.py (working copy) -@@ -68,7 +68,7 @@ - PASS_EDGE_PROFILER = 25 - PASS_FUNCTION_ATTRS = 26 - PASS_FUNCTION_INLINING = 27 --PASS_GEP_SPLITTER = 28 -+#PASS_GEP_SPLITTER = 28 - PASS_GLOBAL_DCE = 29 - PASS_GLOBAL_OPTIMIZER = 30 - PASS_GLOBALS_MOD_REF = 31 -@@ -83,11 +83,11 @@ - PASS_LAZY_VALUE_INFO = 40 - PASS_LCSSA = 41 - PASS_LICM = 42 --PASS_LIVE_VALUES = 43 -+#PASS_LIVE_VALUES = 43 - PASS_LOOP_DELETION = 44 - PASS_LOOP_DEPENDENCE_ANALYSIS = 45 - PASS_LOOP_EXTRACTOR = 46 --PASS_LOOP_INDEX_SPLIT = 47 -+#PASS_LOOP_INDEX_SPLIT = 47 - PASS_LOOP_ROTATE = 48 - PASS_LOOP_SIMPLIFY = 49 - PASS_LOOP_STRENGTH_REDUCE = 50 -@@ -102,11 +102,11 @@ - PASS_NO_PROFILE_INFO = 59 - PASS_OPTIMAL_EDGE_PROFILER = 60 - PASS_PARTIAL_INLINING = 61 --PASS_PARTIAL_SPECIALIZATION = 62 --PASS_POST_DOM_ONLY_PRINTER = 63 --PASS_POST_DOM_ONLY_VIEWER = 64 --PASS_POST_DOM_PRINTER = 65 --PASS_POST_DOM_VIEWER = 66 -+#PASS_PARTIAL_SPECIALIZATION = 62 -+#PASS_POST_DOM_ONLY_PRINTER = 63 -+#PASS_POST_DOM_ONLY_VIEWER = 64 -+#PASS_POST_DOM_PRINTER = 65 -+#PASS_POST_DOM_VIEWER = 66 - PASS_PROFILE_ESTIMATOR = 67 - PASS_PROFILE_LOADER = 68 - PASS_PROFILE_VERIFIER = 69 -@@ -116,7 +116,7 @@ - PASS_SCALAR_EVOLUTION_ALIAS_ANALYSIS = 73 - PASS_SCALAR_REPL_AGGREGATES = 74 - PASS_SCCP = 76 --PASS_SIMPLIFY_HALF_POWR_LIB_CALLS = 77 -+#PASS_SIMPLIFY_HALF_POWR_LIB_CALLS = 77 - PASS_SIMPLIFY_LIB_CALLS = 78 - PASS_SINGLE_LOOP_EXTRACTOR = 79 - PASS_STRIP_DEAD_PROTOTYPES = 82 -@@ -161,7 +161,7 @@ - PASS_EDGE_PROFILER : _core.LLVMAddEdgeProfilerPass, - PASS_FUNCTION_ATTRS : _core.LLVMAddFunctionAttrsPass, - PASS_FUNCTION_INLINING : _core.LLVMAddFunctionInliningPass, -- PASS_GEP_SPLITTER : _core.LLVMAddGEPSplitterPass, -+ #PASS_GEP_SPLITTER : _core.LLVMAddGEPSplitterPass, - PASS_GLOBAL_DCE : _core.LLVMAddGlobalDCEPass, - PASS_GLOBAL_OPTIMIZER : _core.LLVMAddGlobalOptimizerPass, - PASS_GLOBALS_MOD_REF : _core.LLVMAddGlobalsModRefPass, -@@ -176,11 +176,11 @@ - PASS_LAZY_VALUE_INFO : _core.LLVMAddLazyValueInfoPass, - PASS_LCSSA : _core.LLVMAddLCSSAPass, - PASS_LICM : _core.LLVMAddLICMPass, -- PASS_LIVE_VALUES : _core.LLVMAddLiveValuesPass, -+ #PASS_LIVE_VALUES : _core.LLVMAddLiveValuesPass, - PASS_LOOP_DELETION : _core.LLVMAddLoopDeletionPass, - PASS_LOOP_DEPENDENCE_ANALYSIS : _core.LLVMAddLoopDependenceAnalysisPass, - PASS_LOOP_EXTRACTOR : _core.LLVMAddLoopExtractorPass, -- PASS_LOOP_INDEX_SPLIT : _core.LLVMAddLoopIndexSplitPass, -+ #PASS_LOOP_INDEX_SPLIT : _core.LLVMAddLoopIndexSplitPass, - PASS_LOOP_ROTATE : _core.LLVMAddLoopRotatePass, - PASS_LOOP_SIMPLIFY : _core.LLVMAddLoopSimplifyPass, - PASS_LOOP_STRENGTH_REDUCE : _core.LLVMAddLoopStrengthReducePass, -@@ -195,11 +195,11 @@ - PASS_NO_PROFILE_INFO : _core.LLVMAddNoProfileInfoPass, - PASS_OPTIMAL_EDGE_PROFILER : _core.LLVMAddOptimalEdgeProfilerPass, - PASS_PARTIAL_INLINING : _core.LLVMAddPartialInliningPass, -- PASS_PARTIAL_SPECIALIZATION : _core.LLVMAddPartialSpecializationPass, -- PASS_POST_DOM_ONLY_PRINTER : _core.LLVMAddPostDomOnlyPrinterPass, -- PASS_POST_DOM_ONLY_VIEWER : _core.LLVMAddPostDomOnlyViewerPass, -- PASS_POST_DOM_PRINTER : _core.LLVMAddPostDomPrinterPass, -- PASS_POST_DOM_VIEWER : _core.LLVMAddPostDomViewerPass, -+ #PASS_PARTIAL_SPECIALIZATION : _core.LLVMAddPartialSpecializationPass, -+ #PASS_POST_DOM_ONLY_PRINTER : _core.LLVMAddPostDomOnlyPrinterPass, -+ #PASS_POST_DOM_ONLY_VIEWER : _core.LLVMAddPostDomOnlyViewerPass, -+ #PASS_POST_DOM_PRINTER : _core.LLVMAddPostDomPrinterPass, -+ #PASS_POST_DOM_VIEWER : _core.LLVMAddPostDomViewerPass, - PASS_PROFILE_ESTIMATOR : _core.LLVMAddProfileEstimatorPass, - PASS_PROFILE_LOADER : _core.LLVMAddProfileLoaderPass, - PASS_PROFILE_VERIFIER : _core.LLVMAddProfileVerifierPass, -@@ -209,7 +209,7 @@ - PASS_SCALAR_EVOLUTION_ALIAS_ANALYSIS : _core.LLVMAddScalarEvolutionAliasAnalysisPass, - PASS_SCALAR_REPL_AGGREGATES : _core.LLVMAddScalarReplAggregatesPass, - PASS_SCCP : _core.LLVMAddSCCPPass, -- PASS_SIMPLIFY_HALF_POWR_LIB_CALLS : _core.LLVMAddSimplifyHalfPowrLibCallsPass, -+ #PASS_SIMPLIFY_HALF_POWR_LIB_CALLS : _core.LLVMAddSimplifyHalfPowrLibCallsPass, - PASS_SIMPLIFY_LIB_CALLS : _core.LLVMAddSimplifyLibCallsPass, - PASS_SINGLE_LOOP_EXTRACTOR : _core.LLVMAddSingleLoopExtractorPass, - PASS_STRIP_DEAD_PROTOTYPES : _core.LLVMAddStripDeadPrototypesPass, -Index: _intrinsic_ids.py -=================================================================== ---- _intrinsic_ids.py (revision 105) -+++ _intrinsic_ids.py (working copy) -@@ -49,854 +49,879 @@ - INTR_ARM_NEON_VCNT = 14 - INTR_ARM_NEON_VCVTFP2FXS = 15 - INTR_ARM_NEON_VCVTFP2FXU = 16 --INTR_ARM_NEON_VCVTFXS2FP = 17 --INTR_ARM_NEON_VCVTFXU2FP = 18 --INTR_ARM_NEON_VHADDS = 19 --INTR_ARM_NEON_VHADDU = 20 --INTR_ARM_NEON_VHSUBS = 21 --INTR_ARM_NEON_VHSUBU = 22 --INTR_ARM_NEON_VLD1 = 23 --INTR_ARM_NEON_VLD2 = 24 --INTR_ARM_NEON_VLD2LANE = 25 --INTR_ARM_NEON_VLD3 = 26 --INTR_ARM_NEON_VLD3LANE = 27 --INTR_ARM_NEON_VLD4 = 28 --INTR_ARM_NEON_VLD4LANE = 29 --INTR_ARM_NEON_VMAXS = 30 --INTR_ARM_NEON_VMAXU = 31 --INTR_ARM_NEON_VMINS = 32 --INTR_ARM_NEON_VMINU = 33 --INTR_ARM_NEON_VMULLP = 34 --INTR_ARM_NEON_VMULP = 35 --INTR_ARM_NEON_VPADALS = 36 --INTR_ARM_NEON_VPADALU = 37 --INTR_ARM_NEON_VPADD = 38 --INTR_ARM_NEON_VPADDLS = 39 --INTR_ARM_NEON_VPADDLU = 40 --INTR_ARM_NEON_VPMAXS = 41 --INTR_ARM_NEON_VPMAXU = 42 --INTR_ARM_NEON_VPMINS = 43 --INTR_ARM_NEON_VPMINU = 44 --INTR_ARM_NEON_VQABS = 45 --INTR_ARM_NEON_VQADDS = 46 --INTR_ARM_NEON_VQADDU = 47 --INTR_ARM_NEON_VQDMLAL = 48 --INTR_ARM_NEON_VQDMLSL = 49 --INTR_ARM_NEON_VQDMULH = 50 --INTR_ARM_NEON_VQDMULL = 51 --INTR_ARM_NEON_VQMOVNS = 52 --INTR_ARM_NEON_VQMOVNSU = 53 --INTR_ARM_NEON_VQMOVNU = 54 --INTR_ARM_NEON_VQNEG = 55 --INTR_ARM_NEON_VQRDMULH = 56 --INTR_ARM_NEON_VQRSHIFTNS = 57 --INTR_ARM_NEON_VQRSHIFTNSU = 58 --INTR_ARM_NEON_VQRSHIFTNU = 59 --INTR_ARM_NEON_VQRSHIFTS = 60 --INTR_ARM_NEON_VQRSHIFTU = 61 --INTR_ARM_NEON_VQSHIFTNS = 62 --INTR_ARM_NEON_VQSHIFTNSU = 63 --INTR_ARM_NEON_VQSHIFTNU = 64 --INTR_ARM_NEON_VQSHIFTS = 65 --INTR_ARM_NEON_VQSHIFTSU = 66 --INTR_ARM_NEON_VQSHIFTU = 67 --INTR_ARM_NEON_VQSUBS = 68 --INTR_ARM_NEON_VQSUBU = 69 --INTR_ARM_NEON_VRADDHN = 70 --INTR_ARM_NEON_VRECPE = 71 --INTR_ARM_NEON_VRECPS = 72 --INTR_ARM_NEON_VRHADDS = 73 --INTR_ARM_NEON_VRHADDU = 74 --INTR_ARM_NEON_VRSHIFTN = 75 --INTR_ARM_NEON_VRSHIFTS = 76 --INTR_ARM_NEON_VRSHIFTU = 77 --INTR_ARM_NEON_VRSQRTE = 78 --INTR_ARM_NEON_VRSQRTS = 79 --INTR_ARM_NEON_VRSUBHN = 80 --INTR_ARM_NEON_VSHIFTINS = 81 --INTR_ARM_NEON_VSHIFTLS = 82 --INTR_ARM_NEON_VSHIFTLU = 83 --INTR_ARM_NEON_VSHIFTN = 84 --INTR_ARM_NEON_VSHIFTS = 85 --INTR_ARM_NEON_VSHIFTU = 86 --INTR_ARM_NEON_VST1 = 87 --INTR_ARM_NEON_VST2 = 88 --INTR_ARM_NEON_VST2LANE = 89 --INTR_ARM_NEON_VST3 = 90 --INTR_ARM_NEON_VST3LANE = 91 --INTR_ARM_NEON_VST4 = 92 --INTR_ARM_NEON_VST4LANE = 93 --INTR_ARM_NEON_VSUBHN = 94 --INTR_ARM_NEON_VTBL1 = 95 --INTR_ARM_NEON_VTBL2 = 96 --INTR_ARM_NEON_VTBL3 = 97 --INTR_ARM_NEON_VTBL4 = 98 --INTR_ARM_NEON_VTBX1 = 99 --INTR_ARM_NEON_VTBX2 = 100 --INTR_ARM_NEON_VTBX3 = 101 --INTR_ARM_NEON_VTBX4 = 102 --INTR_ARM_QADD = 103 --INTR_ARM_QSUB = 104 --INTR_ARM_SET_FPSCR = 105 --INTR_ARM_SSAT = 106 --INTR_ARM_THREAD_POINTER = 107 --INTR_ARM_USAT = 108 --INTR_ARM_VCVTR = 109 --INTR_ARM_VCVTRU = 110 --INTR_ATOMIC_CMP_SWAP = 111 --INTR_ATOMIC_LOAD_ADD = 112 --INTR_ATOMIC_LOAD_AND = 113 --INTR_ATOMIC_LOAD_MAX = 114 --INTR_ATOMIC_LOAD_MIN = 115 --INTR_ATOMIC_LOAD_NAND = 116 --INTR_ATOMIC_LOAD_OR = 117 --INTR_ATOMIC_LOAD_SUB = 118 --INTR_ATOMIC_LOAD_UMAX = 119 --INTR_ATOMIC_LOAD_UMIN = 120 --INTR_ATOMIC_LOAD_XOR = 121 --INTR_ATOMIC_SWAP = 122 --INTR_BSWAP = 123 --INTR_CONVERT_FROM_FP16 = 124 --INTR_CONVERT_TO_FP16 = 125 --INTR_CONVERTFF = 126 --INTR_CONVERTFSI = 127 --INTR_CONVERTFUI = 128 --INTR_CONVERTSIF = 129 --INTR_CONVERTSS = 130 --INTR_CONVERTSU = 131 --INTR_CONVERTUIF = 132 --INTR_CONVERTUS = 133 --INTR_CONVERTUU = 134 --INTR_COS = 135 --INTR_CTLZ = 136 --INTR_CTPOP = 137 --INTR_CTTZ = 138 --INTR_DBG_DECLARE = 139 --INTR_DBG_VALUE = 140 --INTR_EH_DWARF_CFA = 141 --INTR_EH_EXCEPTION = 142 --INTR_EH_RETURN_I32 = 143 --INTR_EH_RETURN_I64 = 144 --INTR_EH_SELECTOR = 145 --INTR_EH_SJLJ_CALLSITE = 146 --INTR_EH_SJLJ_LONGJMP = 147 --INTR_EH_SJLJ_LSDA = 148 --INTR_EH_SJLJ_SETJMP = 149 --INTR_EH_TYPEID_FOR = 150 --INTR_EH_UNWIND_INIT = 151 --INTR_EXP = 152 --INTR_EXP2 = 153 --INTR_FLT_ROUNDS = 154 --INTR_FRAMEADDRESS = 155 --INTR_GCREAD = 156 --INTR_GCROOT = 157 --INTR_GCWRITE = 158 --INTR_INIT_TRAMPOLINE = 159 --INTR_INVARIANT_END = 160 --INTR_INVARIANT_START = 161 --INTR_LIFETIME_END = 162 --INTR_LIFETIME_START = 163 --INTR_LOG = 164 --INTR_LOG10 = 165 --INTR_LOG2 = 166 --INTR_LONGJMP = 167 --INTR_MEMCPY = 168 --INTR_MEMMOVE = 169 --INTR_MEMORY_BARRIER = 170 --INTR_MEMSET = 171 --INTR_OBJECTSIZE = 172 --INTR_PCMARKER = 173 --INTR_POW = 174 --INTR_POWI = 175 --INTR_PPC_ALTIVEC_DSS = 176 --INTR_PPC_ALTIVEC_DSSALL = 177 --INTR_PPC_ALTIVEC_DST = 178 --INTR_PPC_ALTIVEC_DSTST = 179 --INTR_PPC_ALTIVEC_DSTSTT = 180 --INTR_PPC_ALTIVEC_DSTT = 181 --INTR_PPC_ALTIVEC_LVEBX = 182 --INTR_PPC_ALTIVEC_LVEHX = 183 --INTR_PPC_ALTIVEC_LVEWX = 184 --INTR_PPC_ALTIVEC_LVSL = 185 --INTR_PPC_ALTIVEC_LVSR = 186 --INTR_PPC_ALTIVEC_LVX = 187 --INTR_PPC_ALTIVEC_LVXL = 188 --INTR_PPC_ALTIVEC_MFVSCR = 189 --INTR_PPC_ALTIVEC_MTVSCR = 190 --INTR_PPC_ALTIVEC_STVEBX = 191 --INTR_PPC_ALTIVEC_STVEHX = 192 --INTR_PPC_ALTIVEC_STVEWX = 193 --INTR_PPC_ALTIVEC_STVX = 194 --INTR_PPC_ALTIVEC_STVXL = 195 --INTR_PPC_ALTIVEC_VADDCUW = 196 --INTR_PPC_ALTIVEC_VADDSBS = 197 --INTR_PPC_ALTIVEC_VADDSHS = 198 --INTR_PPC_ALTIVEC_VADDSWS = 199 --INTR_PPC_ALTIVEC_VADDUBS = 200 --INTR_PPC_ALTIVEC_VADDUHS = 201 --INTR_PPC_ALTIVEC_VADDUWS = 202 --INTR_PPC_ALTIVEC_VAVGSB = 203 --INTR_PPC_ALTIVEC_VAVGSH = 204 --INTR_PPC_ALTIVEC_VAVGSW = 205 --INTR_PPC_ALTIVEC_VAVGUB = 206 --INTR_PPC_ALTIVEC_VAVGUH = 207 --INTR_PPC_ALTIVEC_VAVGUW = 208 --INTR_PPC_ALTIVEC_VCFSX = 209 --INTR_PPC_ALTIVEC_VCFUX = 210 --INTR_PPC_ALTIVEC_VCMPBFP = 211 --INTR_PPC_ALTIVEC_VCMPBFP_P = 212 --INTR_PPC_ALTIVEC_VCMPEQFP = 213 --INTR_PPC_ALTIVEC_VCMPEQFP_P = 214 --INTR_PPC_ALTIVEC_VCMPEQUB = 215 --INTR_PPC_ALTIVEC_VCMPEQUB_P = 216 --INTR_PPC_ALTIVEC_VCMPEQUH = 217 --INTR_PPC_ALTIVEC_VCMPEQUH_P = 218 --INTR_PPC_ALTIVEC_VCMPEQUW = 219 --INTR_PPC_ALTIVEC_VCMPEQUW_P = 220 --INTR_PPC_ALTIVEC_VCMPGEFP = 221 --INTR_PPC_ALTIVEC_VCMPGEFP_P = 222 --INTR_PPC_ALTIVEC_VCMPGTFP = 223 --INTR_PPC_ALTIVEC_VCMPGTFP_P = 224 --INTR_PPC_ALTIVEC_VCMPGTSB = 225 --INTR_PPC_ALTIVEC_VCMPGTSB_P = 226 --INTR_PPC_ALTIVEC_VCMPGTSH = 227 --INTR_PPC_ALTIVEC_VCMPGTSH_P = 228 --INTR_PPC_ALTIVEC_VCMPGTSW = 229 --INTR_PPC_ALTIVEC_VCMPGTSW_P = 230 --INTR_PPC_ALTIVEC_VCMPGTUB = 231 --INTR_PPC_ALTIVEC_VCMPGTUB_P = 232 --INTR_PPC_ALTIVEC_VCMPGTUH = 233 --INTR_PPC_ALTIVEC_VCMPGTUH_P = 234 --INTR_PPC_ALTIVEC_VCMPGTUW = 235 --INTR_PPC_ALTIVEC_VCMPGTUW_P = 236 --INTR_PPC_ALTIVEC_VCTSXS = 237 --INTR_PPC_ALTIVEC_VCTUXS = 238 --INTR_PPC_ALTIVEC_VEXPTEFP = 239 --INTR_PPC_ALTIVEC_VLOGEFP = 240 --INTR_PPC_ALTIVEC_VMADDFP = 241 --INTR_PPC_ALTIVEC_VMAXFP = 242 --INTR_PPC_ALTIVEC_VMAXSB = 243 --INTR_PPC_ALTIVEC_VMAXSH = 244 --INTR_PPC_ALTIVEC_VMAXSW = 245 --INTR_PPC_ALTIVEC_VMAXUB = 246 --INTR_PPC_ALTIVEC_VMAXUH = 247 --INTR_PPC_ALTIVEC_VMAXUW = 248 --INTR_PPC_ALTIVEC_VMHADDSHS = 249 --INTR_PPC_ALTIVEC_VMHRADDSHS = 250 --INTR_PPC_ALTIVEC_VMINFP = 251 --INTR_PPC_ALTIVEC_VMINSB = 252 --INTR_PPC_ALTIVEC_VMINSH = 253 --INTR_PPC_ALTIVEC_VMINSW = 254 --INTR_PPC_ALTIVEC_VMINUB = 255 --INTR_PPC_ALTIVEC_VMINUH = 256 --INTR_PPC_ALTIVEC_VMINUW = 257 --INTR_PPC_ALTIVEC_VMLADDUHM = 258 --INTR_PPC_ALTIVEC_VMSUMMBM = 259 --INTR_PPC_ALTIVEC_VMSUMSHM = 260 --INTR_PPC_ALTIVEC_VMSUMSHS = 261 --INTR_PPC_ALTIVEC_VMSUMUBM = 262 --INTR_PPC_ALTIVEC_VMSUMUHM = 263 --INTR_PPC_ALTIVEC_VMSUMUHS = 264 --INTR_PPC_ALTIVEC_VMULESB = 265 --INTR_PPC_ALTIVEC_VMULESH = 266 --INTR_PPC_ALTIVEC_VMULEUB = 267 --INTR_PPC_ALTIVEC_VMULEUH = 268 --INTR_PPC_ALTIVEC_VMULOSB = 269 --INTR_PPC_ALTIVEC_VMULOSH = 270 --INTR_PPC_ALTIVEC_VMULOUB = 271 --INTR_PPC_ALTIVEC_VMULOUH = 272 --INTR_PPC_ALTIVEC_VNMSUBFP = 273 --INTR_PPC_ALTIVEC_VPERM = 274 --INTR_PPC_ALTIVEC_VPKPX = 275 --INTR_PPC_ALTIVEC_VPKSHSS = 276 --INTR_PPC_ALTIVEC_VPKSHUS = 277 --INTR_PPC_ALTIVEC_VPKSWSS = 278 --INTR_PPC_ALTIVEC_VPKSWUS = 279 --INTR_PPC_ALTIVEC_VPKUHUS = 280 --INTR_PPC_ALTIVEC_VPKUWUS = 281 --INTR_PPC_ALTIVEC_VREFP = 282 --INTR_PPC_ALTIVEC_VRFIM = 283 --INTR_PPC_ALTIVEC_VRFIN = 284 --INTR_PPC_ALTIVEC_VRFIP = 285 --INTR_PPC_ALTIVEC_VRFIZ = 286 --INTR_PPC_ALTIVEC_VRLB = 287 --INTR_PPC_ALTIVEC_VRLH = 288 --INTR_PPC_ALTIVEC_VRLW = 289 --INTR_PPC_ALTIVEC_VRSQRTEFP = 290 --INTR_PPC_ALTIVEC_VSEL = 291 --INTR_PPC_ALTIVEC_VSL = 292 --INTR_PPC_ALTIVEC_VSLB = 293 --INTR_PPC_ALTIVEC_VSLH = 294 --INTR_PPC_ALTIVEC_VSLO = 295 --INTR_PPC_ALTIVEC_VSLW = 296 --INTR_PPC_ALTIVEC_VSR = 297 --INTR_PPC_ALTIVEC_VSRAB = 298 --INTR_PPC_ALTIVEC_VSRAH = 299 --INTR_PPC_ALTIVEC_VSRAW = 300 --INTR_PPC_ALTIVEC_VSRB = 301 --INTR_PPC_ALTIVEC_VSRH = 302 --INTR_PPC_ALTIVEC_VSRO = 303 --INTR_PPC_ALTIVEC_VSRW = 304 --INTR_PPC_ALTIVEC_VSUBCUW = 305 --INTR_PPC_ALTIVEC_VSUBSBS = 306 --INTR_PPC_ALTIVEC_VSUBSHS = 307 --INTR_PPC_ALTIVEC_VSUBSWS = 308 --INTR_PPC_ALTIVEC_VSUBUBS = 309 --INTR_PPC_ALTIVEC_VSUBUHS = 310 --INTR_PPC_ALTIVEC_VSUBUWS = 311 --INTR_PPC_ALTIVEC_VSUM2SWS = 312 --INTR_PPC_ALTIVEC_VSUM4SBS = 313 --INTR_PPC_ALTIVEC_VSUM4SHS = 314 --INTR_PPC_ALTIVEC_VSUM4UBS = 315 --INTR_PPC_ALTIVEC_VSUMSWS = 316 --INTR_PPC_ALTIVEC_VUPKHPX = 317 --INTR_PPC_ALTIVEC_VUPKHSB = 318 --INTR_PPC_ALTIVEC_VUPKHSH = 319 --INTR_PPC_ALTIVEC_VUPKLPX = 320 --INTR_PPC_ALTIVEC_VUPKLSB = 321 --INTR_PPC_ALTIVEC_VUPKLSH = 322 --INTR_PPC_DCBA = 323 --INTR_PPC_DCBF = 324 --INTR_PPC_DCBI = 325 --INTR_PPC_DCBST = 326 --INTR_PPC_DCBT = 327 --INTR_PPC_DCBTST = 328 --INTR_PPC_DCBZ = 329 --INTR_PPC_DCBZL = 330 --INTR_PPC_SYNC = 331 --INTR_PREFETCH = 332 --INTR_PTR_ANNOTATION = 333 --INTR_READCYCLECOUNTER = 334 --INTR_RETURNADDRESS = 335 --INTR_SADD_WITH_OVERFLOW = 336 --INTR_SETJMP = 337 --INTR_SIGLONGJMP = 338 --INTR_SIGSETJMP = 339 --INTR_SIN = 340 --INTR_SMUL_WITH_OVERFLOW = 341 --INTR_SPU_SI_A = 342 --INTR_SPU_SI_ADDX = 343 --INTR_SPU_SI_AH = 344 --INTR_SPU_SI_AHI = 345 --INTR_SPU_SI_AI = 346 --INTR_SPU_SI_AND = 347 --INTR_SPU_SI_ANDBI = 348 --INTR_SPU_SI_ANDC = 349 --INTR_SPU_SI_ANDHI = 350 --INTR_SPU_SI_ANDI = 351 --INTR_SPU_SI_BG = 352 --INTR_SPU_SI_BGX = 353 --INTR_SPU_SI_CEQ = 354 --INTR_SPU_SI_CEQB = 355 --INTR_SPU_SI_CEQBI = 356 --INTR_SPU_SI_CEQH = 357 --INTR_SPU_SI_CEQHI = 358 --INTR_SPU_SI_CEQI = 359 --INTR_SPU_SI_CG = 360 --INTR_SPU_SI_CGT = 361 --INTR_SPU_SI_CGTB = 362 --INTR_SPU_SI_CGTBI = 363 --INTR_SPU_SI_CGTH = 364 --INTR_SPU_SI_CGTHI = 365 --INTR_SPU_SI_CGTI = 366 --INTR_SPU_SI_CGX = 367 --INTR_SPU_SI_CLGT = 368 --INTR_SPU_SI_CLGTB = 369 --INTR_SPU_SI_CLGTBI = 370 --INTR_SPU_SI_CLGTH = 371 --INTR_SPU_SI_CLGTHI = 372 --INTR_SPU_SI_CLGTI = 373 --INTR_SPU_SI_DFA = 374 --INTR_SPU_SI_DFM = 375 --INTR_SPU_SI_DFMA = 376 --INTR_SPU_SI_DFMS = 377 --INTR_SPU_SI_DFNMA = 378 --INTR_SPU_SI_DFNMS = 379 --INTR_SPU_SI_DFS = 380 --INTR_SPU_SI_FA = 381 --INTR_SPU_SI_FCEQ = 382 --INTR_SPU_SI_FCGT = 383 --INTR_SPU_SI_FCMEQ = 384 --INTR_SPU_SI_FCMGT = 385 --INTR_SPU_SI_FM = 386 --INTR_SPU_SI_FMA = 387 --INTR_SPU_SI_FMS = 388 --INTR_SPU_SI_FNMS = 389 --INTR_SPU_SI_FS = 390 --INTR_SPU_SI_FSMBI = 391 --INTR_SPU_SI_MPY = 392 --INTR_SPU_SI_MPYA = 393 --INTR_SPU_SI_MPYH = 394 --INTR_SPU_SI_MPYHH = 395 --INTR_SPU_SI_MPYHHA = 396 --INTR_SPU_SI_MPYHHAU = 397 --INTR_SPU_SI_MPYHHU = 398 --INTR_SPU_SI_MPYI = 399 --INTR_SPU_SI_MPYS = 400 --INTR_SPU_SI_MPYU = 401 --INTR_SPU_SI_MPYUI = 402 --INTR_SPU_SI_NAND = 403 --INTR_SPU_SI_NOR = 404 --INTR_SPU_SI_OR = 405 --INTR_SPU_SI_ORBI = 406 --INTR_SPU_SI_ORC = 407 --INTR_SPU_SI_ORHI = 408 --INTR_SPU_SI_ORI = 409 --INTR_SPU_SI_SF = 410 --INTR_SPU_SI_SFH = 411 --INTR_SPU_SI_SFHI = 412 --INTR_SPU_SI_SFI = 413 --INTR_SPU_SI_SFX = 414 --INTR_SPU_SI_SHLI = 415 --INTR_SPU_SI_SHLQBI = 416 --INTR_SPU_SI_SHLQBII = 417 --INTR_SPU_SI_SHLQBY = 418 --INTR_SPU_SI_SHLQBYI = 419 --INTR_SPU_SI_XOR = 420 --INTR_SPU_SI_XORBI = 421 --INTR_SPU_SI_XORHI = 422 --INTR_SPU_SI_XORI = 423 --INTR_SQRT = 424 --INTR_SSUB_WITH_OVERFLOW = 425 --INTR_STACKPROTECTOR = 426 --INTR_STACKRESTORE = 427 --INTR_STACKSAVE = 428 --INTR_TRAP = 429 --INTR_UADD_WITH_OVERFLOW = 430 --INTR_UMUL_WITH_OVERFLOW = 431 --INTR_USUB_WITH_OVERFLOW = 432 --INTR_VACOPY = 433 --INTR_VAEND = 434 --INTR_VAR_ANNOTATION = 435 --INTR_VASTART = 436 --INTR_X86_AESNI_AESDEC = 437 --INTR_X86_AESNI_AESDECLAST = 438 --INTR_X86_AESNI_AESENC = 439 --INTR_X86_AESNI_AESENCLAST = 440 --INTR_X86_AESNI_AESIMC = 441 --INTR_X86_AESNI_AESKEYGENASSIST = 442 --INTR_X86_AVX_ADDSUB_PD_256 = 443 --INTR_X86_AVX_ADDSUB_PS_256 = 444 --INTR_X86_AVX_BLEND_PD_256 = 445 --INTR_X86_AVX_BLEND_PS_256 = 446 --INTR_X86_AVX_BLENDV_PD_256 = 447 --INTR_X86_AVX_BLENDV_PS_256 = 448 --INTR_X86_AVX_CMP_PD_256 = 449 --INTR_X86_AVX_CMP_PS_256 = 450 --INTR_X86_AVX_CVT_PD2_PS_256 = 451 --INTR_X86_AVX_CVT_PD2DQ_256 = 452 --INTR_X86_AVX_CVT_PS2_PD_256 = 453 --INTR_X86_AVX_CVT_PS2DQ_256 = 454 --INTR_X86_AVX_CVTDQ2_PD_256 = 455 --INTR_X86_AVX_CVTDQ2_PS_256 = 456 --INTR_X86_AVX_CVTT_PD2DQ_256 = 457 --INTR_X86_AVX_CVTT_PS2DQ_256 = 458 --INTR_X86_AVX_DP_PS_256 = 459 --INTR_X86_AVX_HADD_PD_256 = 460 --INTR_X86_AVX_HADD_PS_256 = 461 --INTR_X86_AVX_HSUB_PD_256 = 462 --INTR_X86_AVX_HSUB_PS_256 = 463 --INTR_X86_AVX_LDU_DQ_256 = 464 --INTR_X86_AVX_LOADU_DQ_256 = 465 --INTR_X86_AVX_LOADU_PD_256 = 466 --INTR_X86_AVX_LOADU_PS_256 = 467 --INTR_X86_AVX_MASKLOAD_PD = 468 --INTR_X86_AVX_MASKLOAD_PD_256 = 469 --INTR_X86_AVX_MASKLOAD_PS = 470 --INTR_X86_AVX_MASKLOAD_PS_256 = 471 --INTR_X86_AVX_MASKSTORE_PD = 472 --INTR_X86_AVX_MASKSTORE_PD_256 = 473 --INTR_X86_AVX_MASKSTORE_PS = 474 --INTR_X86_AVX_MASKSTORE_PS_256 = 475 --INTR_X86_AVX_MAX_PD_256 = 476 --INTR_X86_AVX_MAX_PS_256 = 477 --INTR_X86_AVX_MIN_PD_256 = 478 --INTR_X86_AVX_MIN_PS_256 = 479 --INTR_X86_AVX_MOVMSK_PD_256 = 480 --INTR_X86_AVX_MOVMSK_PS_256 = 481 --INTR_X86_AVX_MOVNT_DQ_256 = 482 --INTR_X86_AVX_MOVNT_PD_256 = 483 --INTR_X86_AVX_MOVNT_PS_256 = 484 --INTR_X86_AVX_PTESTC_256 = 485 --INTR_X86_AVX_PTESTNZC_256 = 486 --INTR_X86_AVX_PTESTZ_256 = 487 --INTR_X86_AVX_RCP_PS_256 = 488 --INTR_X86_AVX_ROUND_PD_256 = 489 --INTR_X86_AVX_ROUND_PS_256 = 490 --INTR_X86_AVX_RSQRT_PS_256 = 491 --INTR_X86_AVX_SQRT_PD_256 = 492 --INTR_X86_AVX_SQRT_PS_256 = 493 --INTR_X86_AVX_STOREU_DQ_256 = 494 --INTR_X86_AVX_STOREU_PD_256 = 495 --INTR_X86_AVX_STOREU_PS_256 = 496 --INTR_X86_AVX_VBROADCAST_SD_256 = 497 --INTR_X86_AVX_VBROADCASTF128_PD_256 = 498 --INTR_X86_AVX_VBROADCASTF128_PS_256 = 499 --INTR_X86_AVX_VBROADCASTSS = 500 --INTR_X86_AVX_VBROADCASTSS_256 = 501 --INTR_X86_AVX_VEXTRACTF128_PD_256 = 502 --INTR_X86_AVX_VEXTRACTF128_PS_256 = 503 --INTR_X86_AVX_VEXTRACTF128_SI_256 = 504 --INTR_X86_AVX_VINSERTF128_PD_256 = 505 --INTR_X86_AVX_VINSERTF128_PS_256 = 506 --INTR_X86_AVX_VINSERTF128_SI_256 = 507 --INTR_X86_AVX_VPERM2F128_PD_256 = 508 --INTR_X86_AVX_VPERM2F128_PS_256 = 509 --INTR_X86_AVX_VPERM2F128_SI_256 = 510 --INTR_X86_AVX_VPERMIL_PD = 511 --INTR_X86_AVX_VPERMIL_PD_256 = 512 --INTR_X86_AVX_VPERMIL_PS = 513 --INTR_X86_AVX_VPERMIL_PS_256 = 514 --INTR_X86_AVX_VPERMILVAR_PD = 515 --INTR_X86_AVX_VPERMILVAR_PD_256 = 516 --INTR_X86_AVX_VPERMILVAR_PS = 517 --INTR_X86_AVX_VPERMILVAR_PS_256 = 518 --INTR_X86_AVX_VTESTC_PD = 519 --INTR_X86_AVX_VTESTC_PD_256 = 520 --INTR_X86_AVX_VTESTC_PS = 521 --INTR_X86_AVX_VTESTC_PS_256 = 522 --INTR_X86_AVX_VTESTNZC_PD = 523 --INTR_X86_AVX_VTESTNZC_PD_256 = 524 --INTR_X86_AVX_VTESTNZC_PS = 525 --INTR_X86_AVX_VTESTNZC_PS_256 = 526 --INTR_X86_AVX_VTESTZ_PD = 527 --INTR_X86_AVX_VTESTZ_PD_256 = 528 --INTR_X86_AVX_VTESTZ_PS = 529 --INTR_X86_AVX_VTESTZ_PS_256 = 530 --INTR_X86_AVX_VZEROALL = 531 --INTR_X86_AVX_VZEROUPPER = 532 --INTR_X86_INT = 533 --INTR_X86_MMX_CVTSI32_SI64 = 534 --INTR_X86_MMX_CVTSI64_SI32 = 535 --INTR_X86_MMX_EMMS = 536 --INTR_X86_MMX_FEMMS = 537 --INTR_X86_MMX_MASKMOVQ = 538 --INTR_X86_MMX_MOVNT_DQ = 539 --INTR_X86_MMX_PACKSSDW = 540 --INTR_X86_MMX_PACKSSWB = 541 --INTR_X86_MMX_PACKUSWB = 542 --INTR_X86_MMX_PADD_B = 543 --INTR_X86_MMX_PADD_D = 544 --INTR_X86_MMX_PADD_Q = 545 --INTR_X86_MMX_PADD_W = 546 --INTR_X86_MMX_PADDS_B = 547 --INTR_X86_MMX_PADDS_W = 548 --INTR_X86_MMX_PADDUS_B = 549 --INTR_X86_MMX_PADDUS_W = 550 --INTR_X86_MMX_PAND = 551 --INTR_X86_MMX_PANDN = 552 --INTR_X86_MMX_PAVG_B = 553 --INTR_X86_MMX_PAVG_W = 554 --INTR_X86_MMX_PCMPEQ_B = 555 --INTR_X86_MMX_PCMPEQ_D = 556 --INTR_X86_MMX_PCMPEQ_W = 557 --INTR_X86_MMX_PCMPGT_B = 558 --INTR_X86_MMX_PCMPGT_D = 559 --INTR_X86_MMX_PCMPGT_W = 560 --INTR_X86_MMX_PEXTR_W = 561 --INTR_X86_MMX_PINSR_W = 562 --INTR_X86_MMX_PMADD_WD = 563 --INTR_X86_MMX_PMAXS_W = 564 --INTR_X86_MMX_PMAXU_B = 565 --INTR_X86_MMX_PMINS_W = 566 --INTR_X86_MMX_PMINU_B = 567 --INTR_X86_MMX_PMOVMSKB = 568 --INTR_X86_MMX_PMULH_W = 569 --INTR_X86_MMX_PMULHU_W = 570 --INTR_X86_MMX_PMULL_W = 571 --INTR_X86_MMX_PMULU_DQ = 572 --INTR_X86_MMX_POR = 573 --INTR_X86_MMX_PSAD_BW = 574 --INTR_X86_MMX_PSLL_D = 575 --INTR_X86_MMX_PSLL_Q = 576 --INTR_X86_MMX_PSLL_W = 577 --INTR_X86_MMX_PSLLI_D = 578 --INTR_X86_MMX_PSLLI_Q = 579 --INTR_X86_MMX_PSLLI_W = 580 --INTR_X86_MMX_PSRA_D = 581 --INTR_X86_MMX_PSRA_W = 582 --INTR_X86_MMX_PSRAI_D = 583 --INTR_X86_MMX_PSRAI_W = 584 --INTR_X86_MMX_PSRL_D = 585 --INTR_X86_MMX_PSRL_Q = 586 --INTR_X86_MMX_PSRL_W = 587 --INTR_X86_MMX_PSRLI_D = 588 --INTR_X86_MMX_PSRLI_Q = 589 --INTR_X86_MMX_PSRLI_W = 590 --INTR_X86_MMX_PSUB_B = 591 --INTR_X86_MMX_PSUB_D = 592 --INTR_X86_MMX_PSUB_Q = 593 --INTR_X86_MMX_PSUB_W = 594 --INTR_X86_MMX_PSUBS_B = 595 --INTR_X86_MMX_PSUBS_W = 596 --INTR_X86_MMX_PSUBUS_B = 597 --INTR_X86_MMX_PSUBUS_W = 598 --INTR_X86_MMX_PUNPCKHBW = 599 --INTR_X86_MMX_PUNPCKHDQ = 600 --INTR_X86_MMX_PUNPCKHWD = 601 --INTR_X86_MMX_PUNPCKLBW = 602 --INTR_X86_MMX_PUNPCKLDQ = 603 --INTR_X86_MMX_PUNPCKLWD = 604 --INTR_X86_MMX_PXOR = 605 --INTR_X86_MMX_VEC_EXT_D = 606 --INTR_X86_MMX_VEC_INIT_B = 607 --INTR_X86_MMX_VEC_INIT_D = 608 --INTR_X86_MMX_VEC_INIT_W = 609 --INTR_X86_SSE2_ADD_SD = 610 --INTR_X86_SSE2_CLFLUSH = 611 --INTR_X86_SSE2_CMP_PD = 612 --INTR_X86_SSE2_CMP_SD = 613 --INTR_X86_SSE2_COMIEQ_SD = 614 --INTR_X86_SSE2_COMIGE_SD = 615 --INTR_X86_SSE2_COMIGT_SD = 616 --INTR_X86_SSE2_COMILE_SD = 617 --INTR_X86_SSE2_COMILT_SD = 618 --INTR_X86_SSE2_COMINEQ_SD = 619 --INTR_X86_SSE2_CVTDQ2PD = 620 --INTR_X86_SSE2_CVTDQ2PS = 621 --INTR_X86_SSE2_CVTPD2DQ = 622 --INTR_X86_SSE2_CVTPD2PS = 623 --INTR_X86_SSE2_CVTPS2DQ = 624 --INTR_X86_SSE2_CVTPS2PD = 625 --INTR_X86_SSE2_CVTSD2SI = 626 --INTR_X86_SSE2_CVTSD2SI64 = 627 --INTR_X86_SSE2_CVTSD2SS = 628 --INTR_X86_SSE2_CVTSI2SD = 629 --INTR_X86_SSE2_CVTSI642SD = 630 --INTR_X86_SSE2_CVTSS2SD = 631 --INTR_X86_SSE2_CVTTPD2DQ = 632 --INTR_X86_SSE2_CVTTPS2DQ = 633 --INTR_X86_SSE2_CVTTSD2SI = 634 --INTR_X86_SSE2_CVTTSD2SI64 = 635 --INTR_X86_SSE2_DIV_SD = 636 --INTR_X86_SSE2_LFENCE = 637 --INTR_X86_SSE2_LOADU_DQ = 638 --INTR_X86_SSE2_LOADU_PD = 639 --INTR_X86_SSE2_MASKMOV_DQU = 640 --INTR_X86_SSE2_MAX_PD = 641 --INTR_X86_SSE2_MAX_SD = 642 --INTR_X86_SSE2_MFENCE = 643 --INTR_X86_SSE2_MIN_PD = 644 --INTR_X86_SSE2_MIN_SD = 645 --INTR_X86_SSE2_MOVMSK_PD = 646 --INTR_X86_SSE2_MOVNT_DQ = 647 --INTR_X86_SSE2_MOVNT_I = 648 --INTR_X86_SSE2_MOVNT_PD = 649 --INTR_X86_SSE2_MUL_SD = 650 --INTR_X86_SSE2_PACKSSDW_128 = 651 --INTR_X86_SSE2_PACKSSWB_128 = 652 --INTR_X86_SSE2_PACKUSWB_128 = 653 --INTR_X86_SSE2_PADDS_B = 654 --INTR_X86_SSE2_PADDS_W = 655 --INTR_X86_SSE2_PADDUS_B = 656 --INTR_X86_SSE2_PADDUS_W = 657 --INTR_X86_SSE2_PAVG_B = 658 --INTR_X86_SSE2_PAVG_W = 659 --INTR_X86_SSE2_PCMPEQ_B = 660 --INTR_X86_SSE2_PCMPEQ_D = 661 --INTR_X86_SSE2_PCMPEQ_W = 662 --INTR_X86_SSE2_PCMPGT_B = 663 --INTR_X86_SSE2_PCMPGT_D = 664 --INTR_X86_SSE2_PCMPGT_W = 665 --INTR_X86_SSE2_PMADD_WD = 666 --INTR_X86_SSE2_PMAXS_W = 667 --INTR_X86_SSE2_PMAXU_B = 668 --INTR_X86_SSE2_PMINS_W = 669 --INTR_X86_SSE2_PMINU_B = 670 --INTR_X86_SSE2_PMOVMSKB_128 = 671 --INTR_X86_SSE2_PMULH_W = 672 --INTR_X86_SSE2_PMULHU_W = 673 --INTR_X86_SSE2_PMULU_DQ = 674 --INTR_X86_SSE2_PSAD_BW = 675 --INTR_X86_SSE2_PSLL_D = 676 --INTR_X86_SSE2_PSLL_DQ = 677 --INTR_X86_SSE2_PSLL_DQ_BS = 678 --INTR_X86_SSE2_PSLL_Q = 679 --INTR_X86_SSE2_PSLL_W = 680 --INTR_X86_SSE2_PSLLI_D = 681 --INTR_X86_SSE2_PSLLI_Q = 682 --INTR_X86_SSE2_PSLLI_W = 683 --INTR_X86_SSE2_PSRA_D = 684 --INTR_X86_SSE2_PSRA_W = 685 --INTR_X86_SSE2_PSRAI_D = 686 --INTR_X86_SSE2_PSRAI_W = 687 --INTR_X86_SSE2_PSRL_D = 688 --INTR_X86_SSE2_PSRL_DQ = 689 --INTR_X86_SSE2_PSRL_DQ_BS = 690 --INTR_X86_SSE2_PSRL_Q = 691 --INTR_X86_SSE2_PSRL_W = 692 --INTR_X86_SSE2_PSRLI_D = 693 --INTR_X86_SSE2_PSRLI_Q = 694 --INTR_X86_SSE2_PSRLI_W = 695 --INTR_X86_SSE2_PSUBS_B = 696 --INTR_X86_SSE2_PSUBS_W = 697 --INTR_X86_SSE2_PSUBUS_B = 698 --INTR_X86_SSE2_PSUBUS_W = 699 --INTR_X86_SSE2_SQRT_PD = 700 --INTR_X86_SSE2_SQRT_SD = 701 --INTR_X86_SSE2_STOREL_DQ = 702 --INTR_X86_SSE2_STOREU_DQ = 703 --INTR_X86_SSE2_STOREU_PD = 704 --INTR_X86_SSE2_SUB_SD = 705 --INTR_X86_SSE2_UCOMIEQ_SD = 706 --INTR_X86_SSE2_UCOMIGE_SD = 707 --INTR_X86_SSE2_UCOMIGT_SD = 708 --INTR_X86_SSE2_UCOMILE_SD = 709 --INTR_X86_SSE2_UCOMILT_SD = 710 --INTR_X86_SSE2_UCOMINEQ_SD = 711 --INTR_X86_SSE3_ADDSUB_PD = 712 --INTR_X86_SSE3_ADDSUB_PS = 713 --INTR_X86_SSE3_HADD_PD = 714 --INTR_X86_SSE3_HADD_PS = 715 --INTR_X86_SSE3_HSUB_PD = 716 --INTR_X86_SSE3_HSUB_PS = 717 --INTR_X86_SSE3_LDU_DQ = 718 --INTR_X86_SSE3_MONITOR = 719 --INTR_X86_SSE3_MWAIT = 720 --INTR_X86_SSE41_BLENDPD = 721 --INTR_X86_SSE41_BLENDPS = 722 --INTR_X86_SSE41_BLENDVPD = 723 --INTR_X86_SSE41_BLENDVPS = 724 --INTR_X86_SSE41_DPPD = 725 --INTR_X86_SSE41_DPPS = 726 --INTR_X86_SSE41_EXTRACTPS = 727 --INTR_X86_SSE41_INSERTPS = 728 --INTR_X86_SSE41_MOVNTDQA = 729 --INTR_X86_SSE41_MPSADBW = 730 --INTR_X86_SSE41_PACKUSDW = 731 --INTR_X86_SSE41_PBLENDVB = 732 --INTR_X86_SSE41_PBLENDW = 733 --INTR_X86_SSE41_PCMPEQQ = 734 --INTR_X86_SSE41_PEXTRB = 735 --INTR_X86_SSE41_PEXTRD = 736 --INTR_X86_SSE41_PEXTRQ = 737 --INTR_X86_SSE41_PHMINPOSUW = 738 --INTR_X86_SSE41_PMAXSB = 739 --INTR_X86_SSE41_PMAXSD = 740 --INTR_X86_SSE41_PMAXUD = 741 --INTR_X86_SSE41_PMAXUW = 742 --INTR_X86_SSE41_PMINSB = 743 --INTR_X86_SSE41_PMINSD = 744 --INTR_X86_SSE41_PMINUD = 745 --INTR_X86_SSE41_PMINUW = 746 --INTR_X86_SSE41_PMOVSXBD = 747 --INTR_X86_SSE41_PMOVSXBQ = 748 --INTR_X86_SSE41_PMOVSXBW = 749 --INTR_X86_SSE41_PMOVSXDQ = 750 --INTR_X86_SSE41_PMOVSXWD = 751 --INTR_X86_SSE41_PMOVSXWQ = 752 --INTR_X86_SSE41_PMOVZXBD = 753 --INTR_X86_SSE41_PMOVZXBQ = 754 --INTR_X86_SSE41_PMOVZXBW = 755 --INTR_X86_SSE41_PMOVZXDQ = 756 --INTR_X86_SSE41_PMOVZXWD = 757 --INTR_X86_SSE41_PMOVZXWQ = 758 --INTR_X86_SSE41_PMULDQ = 759 --INTR_X86_SSE41_PTESTC = 760 --INTR_X86_SSE41_PTESTNZC = 761 --INTR_X86_SSE41_PTESTZ = 762 --INTR_X86_SSE41_ROUND_PD = 763 --INTR_X86_SSE41_ROUND_PS = 764 --INTR_X86_SSE41_ROUND_SD = 765 --INTR_X86_SSE41_ROUND_SS = 766 --INTR_X86_SSE42_CRC32_16 = 767 --INTR_X86_SSE42_CRC32_32 = 768 --INTR_X86_SSE42_CRC32_8 = 769 --INTR_X86_SSE42_CRC64_64 = 770 --INTR_X86_SSE42_CRC64_8 = 771 --INTR_X86_SSE42_PCMPESTRI128 = 772 --INTR_X86_SSE42_PCMPESTRIA128 = 773 --INTR_X86_SSE42_PCMPESTRIC128 = 774 --INTR_X86_SSE42_PCMPESTRIO128 = 775 --INTR_X86_SSE42_PCMPESTRIS128 = 776 --INTR_X86_SSE42_PCMPESTRIZ128 = 777 --INTR_X86_SSE42_PCMPESTRM128 = 778 --INTR_X86_SSE42_PCMPGTQ = 779 --INTR_X86_SSE42_PCMPISTRI128 = 780 --INTR_X86_SSE42_PCMPISTRIA128 = 781 --INTR_X86_SSE42_PCMPISTRIC128 = 782 --INTR_X86_SSE42_PCMPISTRIO128 = 783 --INTR_X86_SSE42_PCMPISTRIS128 = 784 --INTR_X86_SSE42_PCMPISTRIZ128 = 785 --INTR_X86_SSE42_PCMPISTRM128 = 786 --INTR_X86_SSE_ADD_SS = 787 --INTR_X86_SSE_CMP_PS = 788 --INTR_X86_SSE_CMP_SS = 789 --INTR_X86_SSE_COMIEQ_SS = 790 --INTR_X86_SSE_COMIGE_SS = 791 --INTR_X86_SSE_COMIGT_SS = 792 --INTR_X86_SSE_COMILE_SS = 793 --INTR_X86_SSE_COMILT_SS = 794 --INTR_X86_SSE_COMINEQ_SS = 795 --INTR_X86_SSE_CVTPD2PI = 796 --INTR_X86_SSE_CVTPI2PD = 797 --INTR_X86_SSE_CVTPI2PS = 798 --INTR_X86_SSE_CVTPS2PI = 799 --INTR_X86_SSE_CVTSI2SS = 800 --INTR_X86_SSE_CVTSI642SS = 801 --INTR_X86_SSE_CVTSS2SI = 802 --INTR_X86_SSE_CVTSS2SI64 = 803 --INTR_X86_SSE_CVTTPD2PI = 804 --INTR_X86_SSE_CVTTPS2PI = 805 --INTR_X86_SSE_CVTTSS2SI = 806 --INTR_X86_SSE_CVTTSS2SI64 = 807 --INTR_X86_SSE_DIV_SS = 808 --INTR_X86_SSE_LDMXCSR = 809 --INTR_X86_SSE_LOADU_PS = 810 --INTR_X86_SSE_MAX_PS = 811 --INTR_X86_SSE_MAX_SS = 812 --INTR_X86_SSE_MIN_PS = 813 --INTR_X86_SSE_MIN_SS = 814 --INTR_X86_SSE_MOVMSK_PS = 815 --INTR_X86_SSE_MOVNT_PS = 816 --INTR_X86_SSE_MUL_SS = 817 --INTR_X86_SSE_RCP_PS = 818 --INTR_X86_SSE_RCP_SS = 819 --INTR_X86_SSE_RSQRT_PS = 820 --INTR_X86_SSE_RSQRT_SS = 821 --INTR_X86_SSE_SFENCE = 822 --INTR_X86_SSE_SQRT_PS = 823 --INTR_X86_SSE_SQRT_SS = 824 --INTR_X86_SSE_STMXCSR = 825 --INTR_X86_SSE_STOREU_PS = 826 --INTR_X86_SSE_SUB_SS = 827 --INTR_X86_SSE_UCOMIEQ_SS = 828 --INTR_X86_SSE_UCOMIGE_SS = 829 --INTR_X86_SSE_UCOMIGT_SS = 830 --INTR_X86_SSE_UCOMILE_SS = 831 --INTR_X86_SSE_UCOMILT_SS = 832 --INTR_X86_SSE_UCOMINEQ_SS = 833 --INTR_X86_SSSE3_PABS_B = 834 --INTR_X86_SSSE3_PABS_B_128 = 835 --INTR_X86_SSSE3_PABS_D = 836 --INTR_X86_SSSE3_PABS_D_128 = 837 --INTR_X86_SSSE3_PABS_W = 838 --INTR_X86_SSSE3_PABS_W_128 = 839 --INTR_X86_SSSE3_PHADD_D = 840 --INTR_X86_SSSE3_PHADD_D_128 = 841 --INTR_X86_SSSE3_PHADD_SW = 842 --INTR_X86_SSSE3_PHADD_SW_128 = 843 --INTR_X86_SSSE3_PHADD_W = 844 --INTR_X86_SSSE3_PHADD_W_128 = 845 --INTR_X86_SSSE3_PHSUB_D = 846 --INTR_X86_SSSE3_PHSUB_D_128 = 847 --INTR_X86_SSSE3_PHSUB_SW = 848 --INTR_X86_SSSE3_PHSUB_SW_128 = 849 --INTR_X86_SSSE3_PHSUB_W = 850 --INTR_X86_SSSE3_PHSUB_W_128 = 851 --INTR_X86_SSSE3_PMADD_UB_SW = 852 --INTR_X86_SSSE3_PMADD_UB_SW_128 = 853 --INTR_X86_SSSE3_PMUL_HR_SW = 854 --INTR_X86_SSSE3_PMUL_HR_SW_128 = 855 --INTR_X86_SSSE3_PSHUF_B = 856 --INTR_X86_SSSE3_PSHUF_B_128 = 857 --INTR_X86_SSSE3_PSHUF_W = 858 --INTR_X86_SSSE3_PSIGN_B = 859 --INTR_X86_SSSE3_PSIGN_B_128 = 860 --INTR_X86_SSSE3_PSIGN_D = 861 --INTR_X86_SSSE3_PSIGN_D_128 = 862 --INTR_X86_SSSE3_PSIGN_W = 863 --INTR_X86_SSSE3_PSIGN_W_128 = 864 --INTR_XCORE_BITREV = 865 --INTR_XCORE_GETID = 866 -- -+INTR_ARM_NEON_VCVTFP2HF = 17 -+INTR_ARM_NEON_VCVTFXS2FP = 18 -+INTR_ARM_NEON_VCVTFXU2FP = 19 -+INTR_ARM_NEON_VCVTHF2FP = 20 -+INTR_ARM_NEON_VHADDS = 21 -+INTR_ARM_NEON_VHADDU = 22 -+INTR_ARM_NEON_VHSUBS = 23 -+INTR_ARM_NEON_VHSUBU = 24 -+INTR_ARM_NEON_VLD1 = 25 -+INTR_ARM_NEON_VLD2 = 26 -+INTR_ARM_NEON_VLD2LANE = 27 -+INTR_ARM_NEON_VLD3 = 28 -+INTR_ARM_NEON_VLD3LANE = 29 -+INTR_ARM_NEON_VLD4 = 30 -+INTR_ARM_NEON_VLD4LANE = 31 -+INTR_ARM_NEON_VMAXS = 32 -+INTR_ARM_NEON_VMAXU = 33 -+INTR_ARM_NEON_VMINS = 34 -+INTR_ARM_NEON_VMINU = 35 -+INTR_ARM_NEON_VMULLP = 36 -+INTR_ARM_NEON_VMULP = 37 -+INTR_ARM_NEON_VPADALS = 38 -+INTR_ARM_NEON_VPADALU = 39 -+INTR_ARM_NEON_VPADD = 40 -+INTR_ARM_NEON_VPADDLS = 41 -+INTR_ARM_NEON_VPADDLU = 42 -+INTR_ARM_NEON_VPMAXS = 43 -+INTR_ARM_NEON_VPMAXU = 44 -+INTR_ARM_NEON_VPMINS = 45 -+INTR_ARM_NEON_VPMINU = 46 -+INTR_ARM_NEON_VQABS = 47 -+INTR_ARM_NEON_VQADDS = 48 -+INTR_ARM_NEON_VQADDU = 49 -+INTR_ARM_NEON_VQDMLAL = 50 -+INTR_ARM_NEON_VQDMLSL = 51 -+INTR_ARM_NEON_VQDMULH = 52 -+INTR_ARM_NEON_VQDMULL = 53 -+INTR_ARM_NEON_VQMOVNS = 54 -+INTR_ARM_NEON_VQMOVNSU = 55 -+INTR_ARM_NEON_VQMOVNU = 56 -+INTR_ARM_NEON_VQNEG = 57 -+INTR_ARM_NEON_VQRDMULH = 58 -+INTR_ARM_NEON_VQRSHIFTNS = 59 -+INTR_ARM_NEON_VQRSHIFTNSU = 60 -+INTR_ARM_NEON_VQRSHIFTNU = 61 -+INTR_ARM_NEON_VQRSHIFTS = 62 -+INTR_ARM_NEON_VQRSHIFTU = 63 -+INTR_ARM_NEON_VQSHIFTNS = 64 -+INTR_ARM_NEON_VQSHIFTNSU = 65 -+INTR_ARM_NEON_VQSHIFTNU = 66 -+INTR_ARM_NEON_VQSHIFTS = 67 -+INTR_ARM_NEON_VQSHIFTSU = 68 -+INTR_ARM_NEON_VQSHIFTU = 69 -+INTR_ARM_NEON_VQSUBS = 70 -+INTR_ARM_NEON_VQSUBU = 71 -+INTR_ARM_NEON_VRADDHN = 72 -+INTR_ARM_NEON_VRECPE = 73 -+INTR_ARM_NEON_VRECPS = 74 -+INTR_ARM_NEON_VRHADDS = 75 -+INTR_ARM_NEON_VRHADDU = 76 -+INTR_ARM_NEON_VRSHIFTN = 77 -+INTR_ARM_NEON_VRSHIFTS = 78 -+INTR_ARM_NEON_VRSHIFTU = 79 -+INTR_ARM_NEON_VRSQRTE = 80 -+INTR_ARM_NEON_VRSQRTS = 81 -+INTR_ARM_NEON_VRSUBHN = 82 -+INTR_ARM_NEON_VSHIFTINS = 83 -+INTR_ARM_NEON_VSHIFTLS = 84 -+INTR_ARM_NEON_VSHIFTLU = 85 -+INTR_ARM_NEON_VSHIFTN = 86 -+INTR_ARM_NEON_VSHIFTS = 87 -+INTR_ARM_NEON_VSHIFTU = 88 -+INTR_ARM_NEON_VST1 = 89 -+INTR_ARM_NEON_VST2 = 90 -+INTR_ARM_NEON_VST2LANE = 91 -+INTR_ARM_NEON_VST3 = 92 -+INTR_ARM_NEON_VST3LANE = 93 -+INTR_ARM_NEON_VST4 = 94 -+INTR_ARM_NEON_VST4LANE = 95 -+INTR_ARM_NEON_VSUBHN = 96 -+INTR_ARM_NEON_VTBL1 = 97 -+INTR_ARM_NEON_VTBL2 = 98 -+INTR_ARM_NEON_VTBL3 = 99 -+INTR_ARM_NEON_VTBL4 = 100 -+INTR_ARM_NEON_VTBX1 = 101 -+INTR_ARM_NEON_VTBX2 = 102 -+INTR_ARM_NEON_VTBX3 = 103 -+INTR_ARM_NEON_VTBX4 = 104 -+INTR_ARM_QADD = 105 -+INTR_ARM_QSUB = 106 -+INTR_ARM_SET_FPSCR = 107 -+INTR_ARM_SSAT = 108 -+INTR_ARM_THREAD_POINTER = 109 -+INTR_ARM_USAT = 110 -+INTR_ARM_VCVTR = 111 -+INTR_ARM_VCVTRU = 112 -+INTR_ATOMIC_CMP_SWAP = 113 -+INTR_ATOMIC_LOAD_ADD = 114 -+INTR_ATOMIC_LOAD_AND = 115 -+INTR_ATOMIC_LOAD_MAX = 116 -+INTR_ATOMIC_LOAD_MIN = 117 -+INTR_ATOMIC_LOAD_NAND = 118 -+INTR_ATOMIC_LOAD_OR = 119 -+INTR_ATOMIC_LOAD_SUB = 120 -+INTR_ATOMIC_LOAD_UMAX = 121 -+INTR_ATOMIC_LOAD_UMIN = 122 -+INTR_ATOMIC_LOAD_XOR = 123 -+INTR_ATOMIC_SWAP = 124 -+INTR_BSWAP = 125 -+INTR_CONVERT_FROM_FP16 = 126 -+INTR_CONVERT_TO_FP16 = 127 -+INTR_CONVERTFF = 128 -+INTR_CONVERTFSI = 129 -+INTR_CONVERTFUI = 130 -+INTR_CONVERTSIF = 131 -+INTR_CONVERTSS = 132 -+INTR_CONVERTSU = 133 -+INTR_CONVERTUIF = 134 -+INTR_CONVERTUS = 135 -+INTR_CONVERTUU = 136 -+INTR_COS = 137 -+INTR_CTLZ = 138 -+INTR_CTPOP = 139 -+INTR_CTTZ = 140 -+INTR_DBG_DECLARE = 141 -+INTR_DBG_VALUE = 142 -+INTR_EH_DWARF_CFA = 143 -+INTR_EH_EXCEPTION = 144 -+INTR_EH_RETURN_I32 = 145 -+INTR_EH_RETURN_I64 = 146 -+INTR_EH_SELECTOR = 147 -+INTR_EH_SJLJ_CALLSITE = 148 -+INTR_EH_SJLJ_DISPATCH_SETUP = 149 -+INTR_EH_SJLJ_LONGJMP = 150 -+INTR_EH_SJLJ_LSDA = 151 -+INTR_EH_SJLJ_SETJMP = 152 -+INTR_EH_TYPEID_FOR = 153 -+INTR_EH_UNWIND_INIT = 154 -+INTR_EXP = 155 -+INTR_EXP2 = 156 -+INTR_FLT_ROUNDS = 157 -+INTR_FRAMEADDRESS = 158 -+INTR_GCREAD = 159 -+INTR_GCROOT = 160 -+INTR_GCWRITE = 161 -+INTR_INIT_TRAMPOLINE = 162 -+INTR_INVARIANT_END = 163 -+INTR_INVARIANT_START = 164 -+INTR_LIFETIME_END = 165 -+INTR_LIFETIME_START = 166 -+INTR_LOG = 167 -+INTR_LOG10 = 168 -+INTR_LOG2 = 169 -+INTR_LONGJMP = 170 -+INTR_MEMCPY = 171 -+INTR_MEMMOVE = 172 -+INTR_MEMORY_BARRIER = 173 -+INTR_MEMSET = 174 -+INTR_OBJECTSIZE = 175 -+INTR_PCMARKER = 176 -+INTR_POW = 177 -+INTR_POWI = 178 -+INTR_PPC_ALTIVEC_DSS = 179 -+INTR_PPC_ALTIVEC_DSSALL = 180 -+INTR_PPC_ALTIVEC_DST = 181 -+INTR_PPC_ALTIVEC_DSTST = 182 -+INTR_PPC_ALTIVEC_DSTSTT = 183 -+INTR_PPC_ALTIVEC_DSTT = 184 -+INTR_PPC_ALTIVEC_LVEBX = 185 -+INTR_PPC_ALTIVEC_LVEHX = 186 -+INTR_PPC_ALTIVEC_LVEWX = 187 -+INTR_PPC_ALTIVEC_LVSL = 188 -+INTR_PPC_ALTIVEC_LVSR = 189 -+INTR_PPC_ALTIVEC_LVX = 190 -+INTR_PPC_ALTIVEC_LVXL = 191 -+INTR_PPC_ALTIVEC_MFVSCR = 192 -+INTR_PPC_ALTIVEC_MTVSCR = 193 -+INTR_PPC_ALTIVEC_STVEBX = 194 -+INTR_PPC_ALTIVEC_STVEHX = 195 -+INTR_PPC_ALTIVEC_STVEWX = 196 -+INTR_PPC_ALTIVEC_STVX = 197 -+INTR_PPC_ALTIVEC_STVXL = 198 -+INTR_PPC_ALTIVEC_VADDCUW = 199 -+INTR_PPC_ALTIVEC_VADDSBS = 200 -+INTR_PPC_ALTIVEC_VADDSHS = 201 -+INTR_PPC_ALTIVEC_VADDSWS = 202 -+INTR_PPC_ALTIVEC_VADDUBS = 203 -+INTR_PPC_ALTIVEC_VADDUHS = 204 -+INTR_PPC_ALTIVEC_VADDUWS = 205 -+INTR_PPC_ALTIVEC_VAVGSB = 206 -+INTR_PPC_ALTIVEC_VAVGSH = 207 -+INTR_PPC_ALTIVEC_VAVGSW = 208 -+INTR_PPC_ALTIVEC_VAVGUB = 209 -+INTR_PPC_ALTIVEC_VAVGUH = 210 -+INTR_PPC_ALTIVEC_VAVGUW = 211 -+INTR_PPC_ALTIVEC_VCFSX = 212 -+INTR_PPC_ALTIVEC_VCFUX = 213 -+INTR_PPC_ALTIVEC_VCMPBFP = 214 -+INTR_PPC_ALTIVEC_VCMPBFP_P = 215 -+INTR_PPC_ALTIVEC_VCMPEQFP = 216 -+INTR_PPC_ALTIVEC_VCMPEQFP_P = 217 -+INTR_PPC_ALTIVEC_VCMPEQUB = 218 -+INTR_PPC_ALTIVEC_VCMPEQUB_P = 219 -+INTR_PPC_ALTIVEC_VCMPEQUH = 220 -+INTR_PPC_ALTIVEC_VCMPEQUH_P = 221 -+INTR_PPC_ALTIVEC_VCMPEQUW = 222 -+INTR_PPC_ALTIVEC_VCMPEQUW_P = 223 -+INTR_PPC_ALTIVEC_VCMPGEFP = 224 -+INTR_PPC_ALTIVEC_VCMPGEFP_P = 225 -+INTR_PPC_ALTIVEC_VCMPGTFP = 226 -+INTR_PPC_ALTIVEC_VCMPGTFP_P = 227 -+INTR_PPC_ALTIVEC_VCMPGTSB = 228 -+INTR_PPC_ALTIVEC_VCMPGTSB_P = 229 -+INTR_PPC_ALTIVEC_VCMPGTSH = 230 -+INTR_PPC_ALTIVEC_VCMPGTSH_P = 231 -+INTR_PPC_ALTIVEC_VCMPGTSW = 232 -+INTR_PPC_ALTIVEC_VCMPGTSW_P = 233 -+INTR_PPC_ALTIVEC_VCMPGTUB = 234 -+INTR_PPC_ALTIVEC_VCMPGTUB_P = 235 -+INTR_PPC_ALTIVEC_VCMPGTUH = 236 -+INTR_PPC_ALTIVEC_VCMPGTUH_P = 237 -+INTR_PPC_ALTIVEC_VCMPGTUW = 238 -+INTR_PPC_ALTIVEC_VCMPGTUW_P = 239 -+INTR_PPC_ALTIVEC_VCTSXS = 240 -+INTR_PPC_ALTIVEC_VCTUXS = 241 -+INTR_PPC_ALTIVEC_VEXPTEFP = 242 -+INTR_PPC_ALTIVEC_VLOGEFP = 243 -+INTR_PPC_ALTIVEC_VMADDFP = 244 -+INTR_PPC_ALTIVEC_VMAXFP = 245 -+INTR_PPC_ALTIVEC_VMAXSB = 246 -+INTR_PPC_ALTIVEC_VMAXSH = 247 -+INTR_PPC_ALTIVEC_VMAXSW = 248 -+INTR_PPC_ALTIVEC_VMAXUB = 249 -+INTR_PPC_ALTIVEC_VMAXUH = 250 -+INTR_PPC_ALTIVEC_VMAXUW = 251 -+INTR_PPC_ALTIVEC_VMHADDSHS = 252 -+INTR_PPC_ALTIVEC_VMHRADDSHS = 253 -+INTR_PPC_ALTIVEC_VMINFP = 254 -+INTR_PPC_ALTIVEC_VMINSB = 255 -+INTR_PPC_ALTIVEC_VMINSH = 256 -+INTR_PPC_ALTIVEC_VMINSW = 257 -+INTR_PPC_ALTIVEC_VMINUB = 258 -+INTR_PPC_ALTIVEC_VMINUH = 259 -+INTR_PPC_ALTIVEC_VMINUW = 260 -+INTR_PPC_ALTIVEC_VMLADDUHM = 261 -+INTR_PPC_ALTIVEC_VMSUMMBM = 262 -+INTR_PPC_ALTIVEC_VMSUMSHM = 263 -+INTR_PPC_ALTIVEC_VMSUMSHS = 264 -+INTR_PPC_ALTIVEC_VMSUMUBM = 265 -+INTR_PPC_ALTIVEC_VMSUMUHM = 266 -+INTR_PPC_ALTIVEC_VMSUMUHS = 267 -+INTR_PPC_ALTIVEC_VMULESB = 268 -+INTR_PPC_ALTIVEC_VMULESH = 269 -+INTR_PPC_ALTIVEC_VMULEUB = 270 -+INTR_PPC_ALTIVEC_VMULEUH = 271 -+INTR_PPC_ALTIVEC_VMULOSB = 272 -+INTR_PPC_ALTIVEC_VMULOSH = 273 -+INTR_PPC_ALTIVEC_VMULOUB = 274 -+INTR_PPC_ALTIVEC_VMULOUH = 275 -+INTR_PPC_ALTIVEC_VNMSUBFP = 276 -+INTR_PPC_ALTIVEC_VPERM = 277 -+INTR_PPC_ALTIVEC_VPKPX = 278 -+INTR_PPC_ALTIVEC_VPKSHSS = 279 -+INTR_PPC_ALTIVEC_VPKSHUS = 280 -+INTR_PPC_ALTIVEC_VPKSWSS = 281 -+INTR_PPC_ALTIVEC_VPKSWUS = 282 -+INTR_PPC_ALTIVEC_VPKUHUS = 283 -+INTR_PPC_ALTIVEC_VPKUWUS = 284 -+INTR_PPC_ALTIVEC_VREFP = 285 -+INTR_PPC_ALTIVEC_VRFIM = 286 -+INTR_PPC_ALTIVEC_VRFIN = 287 -+INTR_PPC_ALTIVEC_VRFIP = 288 -+INTR_PPC_ALTIVEC_VRFIZ = 289 -+INTR_PPC_ALTIVEC_VRLB = 290 -+INTR_PPC_ALTIVEC_VRLH = 291 -+INTR_PPC_ALTIVEC_VRLW = 292 -+INTR_PPC_ALTIVEC_VRSQRTEFP = 293 -+INTR_PPC_ALTIVEC_VSEL = 294 -+INTR_PPC_ALTIVEC_VSL = 295 -+INTR_PPC_ALTIVEC_VSLB = 296 -+INTR_PPC_ALTIVEC_VSLH = 297 -+INTR_PPC_ALTIVEC_VSLO = 298 -+INTR_PPC_ALTIVEC_VSLW = 299 -+INTR_PPC_ALTIVEC_VSR = 300 -+INTR_PPC_ALTIVEC_VSRAB = 301 -+INTR_PPC_ALTIVEC_VSRAH = 302 -+INTR_PPC_ALTIVEC_VSRAW = 303 -+INTR_PPC_ALTIVEC_VSRB = 304 -+INTR_PPC_ALTIVEC_VSRH = 305 -+INTR_PPC_ALTIVEC_VSRO = 306 -+INTR_PPC_ALTIVEC_VSRW = 307 -+INTR_PPC_ALTIVEC_VSUBCUW = 308 -+INTR_PPC_ALTIVEC_VSUBSBS = 309 -+INTR_PPC_ALTIVEC_VSUBSHS = 310 -+INTR_PPC_ALTIVEC_VSUBSWS = 311 -+INTR_PPC_ALTIVEC_VSUBUBS = 312 -+INTR_PPC_ALTIVEC_VSUBUHS = 313 -+INTR_PPC_ALTIVEC_VSUBUWS = 314 -+INTR_PPC_ALTIVEC_VSUM2SWS = 315 -+INTR_PPC_ALTIVEC_VSUM4SBS = 316 -+INTR_PPC_ALTIVEC_VSUM4SHS = 317 -+INTR_PPC_ALTIVEC_VSUM4UBS = 318 -+INTR_PPC_ALTIVEC_VSUMSWS = 319 -+INTR_PPC_ALTIVEC_VUPKHPX = 320 -+INTR_PPC_ALTIVEC_VUPKHSB = 321 -+INTR_PPC_ALTIVEC_VUPKHSH = 322 -+INTR_PPC_ALTIVEC_VUPKLPX = 323 -+INTR_PPC_ALTIVEC_VUPKLSB = 324 -+INTR_PPC_ALTIVEC_VUPKLSH = 325 -+INTR_PPC_DCBA = 326 -+INTR_PPC_DCBF = 327 -+INTR_PPC_DCBI = 328 -+INTR_PPC_DCBST = 329 -+INTR_PPC_DCBT = 330 -+INTR_PPC_DCBTST = 331 -+INTR_PPC_DCBZ = 332 -+INTR_PPC_DCBZL = 333 -+INTR_PPC_SYNC = 334 -+INTR_PREFETCH = 335 -+INTR_PTR_ANNOTATION = 336 -+INTR_PTX_BAR_SYNC = 337 -+INTR_PTX_READ_TID_R64 = 338 -+INTR_PTX_READ_TID_V4I16 = 339 -+INTR_PTX_READ_TID_W = 340 -+INTR_PTX_READ_TID_X = 341 -+INTR_PTX_READ_TID_Y = 342 -+INTR_PTX_READ_TID_Z = 343 -+INTR_READCYCLECOUNTER = 344 -+INTR_RETURNADDRESS = 345 -+INTR_SADD_WITH_OVERFLOW = 346 -+INTR_SETJMP = 347 -+INTR_SIGLONGJMP = 348 -+INTR_SIGSETJMP = 349 -+INTR_SIN = 350 -+INTR_SMUL_WITH_OVERFLOW = 351 -+INTR_SPU_SI_A = 352 -+INTR_SPU_SI_ADDX = 353 -+INTR_SPU_SI_AH = 354 -+INTR_SPU_SI_AHI = 355 -+INTR_SPU_SI_AI = 356 -+INTR_SPU_SI_AND = 357 -+INTR_SPU_SI_ANDBI = 358 -+INTR_SPU_SI_ANDC = 359 -+INTR_SPU_SI_ANDHI = 360 -+INTR_SPU_SI_ANDI = 361 -+INTR_SPU_SI_BG = 362 -+INTR_SPU_SI_BGX = 363 -+INTR_SPU_SI_CEQ = 364 -+INTR_SPU_SI_CEQB = 365 -+INTR_SPU_SI_CEQBI = 366 -+INTR_SPU_SI_CEQH = 367 -+INTR_SPU_SI_CEQHI = 368 -+INTR_SPU_SI_CEQI = 369 -+INTR_SPU_SI_CG = 370 -+INTR_SPU_SI_CGT = 371 -+INTR_SPU_SI_CGTB = 372 -+INTR_SPU_SI_CGTBI = 373 -+INTR_SPU_SI_CGTH = 374 -+INTR_SPU_SI_CGTHI = 375 -+INTR_SPU_SI_CGTI = 376 -+INTR_SPU_SI_CGX = 377 -+INTR_SPU_SI_CLGT = 378 -+INTR_SPU_SI_CLGTB = 379 -+INTR_SPU_SI_CLGTBI = 380 -+INTR_SPU_SI_CLGTH = 381 -+INTR_SPU_SI_CLGTHI = 382 -+INTR_SPU_SI_CLGTI = 383 -+INTR_SPU_SI_DFA = 384 -+INTR_SPU_SI_DFM = 385 -+INTR_SPU_SI_DFMA = 386 -+INTR_SPU_SI_DFMS = 387 -+INTR_SPU_SI_DFNMA = 388 -+INTR_SPU_SI_DFNMS = 389 -+INTR_SPU_SI_DFS = 390 -+INTR_SPU_SI_FA = 391 -+INTR_SPU_SI_FCEQ = 392 -+INTR_SPU_SI_FCGT = 393 -+INTR_SPU_SI_FCMEQ = 394 -+INTR_SPU_SI_FCMGT = 395 -+INTR_SPU_SI_FM = 396 -+INTR_SPU_SI_FMA = 397 -+INTR_SPU_SI_FMS = 398 -+INTR_SPU_SI_FNMS = 399 -+INTR_SPU_SI_FS = 400 -+INTR_SPU_SI_FSMBI = 401 -+INTR_SPU_SI_MPY = 402 -+INTR_SPU_SI_MPYA = 403 -+INTR_SPU_SI_MPYH = 404 -+INTR_SPU_SI_MPYHH = 405 -+INTR_SPU_SI_MPYHHA = 406 -+INTR_SPU_SI_MPYHHAU = 407 -+INTR_SPU_SI_MPYHHU = 408 -+INTR_SPU_SI_MPYI = 409 -+INTR_SPU_SI_MPYS = 410 -+INTR_SPU_SI_MPYU = 411 -+INTR_SPU_SI_MPYUI = 412 -+INTR_SPU_SI_NAND = 413 -+INTR_SPU_SI_NOR = 414 -+INTR_SPU_SI_OR = 415 -+INTR_SPU_SI_ORBI = 416 -+INTR_SPU_SI_ORC = 417 -+INTR_SPU_SI_ORHI = 418 -+INTR_SPU_SI_ORI = 419 -+INTR_SPU_SI_SF = 420 -+INTR_SPU_SI_SFH = 421 -+INTR_SPU_SI_SFHI = 422 -+INTR_SPU_SI_SFI = 423 -+INTR_SPU_SI_SFX = 424 -+INTR_SPU_SI_SHLI = 425 -+INTR_SPU_SI_SHLQBI = 426 -+INTR_SPU_SI_SHLQBII = 427 -+INTR_SPU_SI_SHLQBY = 428 -+INTR_SPU_SI_SHLQBYI = 429 -+INTR_SPU_SI_XOR = 430 -+INTR_SPU_SI_XORBI = 431 -+INTR_SPU_SI_XORHI = 432 -+INTR_SPU_SI_XORI = 433 -+INTR_SQRT = 434 -+INTR_SSUB_WITH_OVERFLOW = 435 -+INTR_STACKPROTECTOR = 436 -+INTR_STACKRESTORE = 437 -+INTR_STACKSAVE = 438 -+INTR_TRAP = 439 -+INTR_UADD_WITH_OVERFLOW = 440 -+INTR_UMUL_WITH_OVERFLOW = 441 -+INTR_USUB_WITH_OVERFLOW = 442 -+INTR_VACOPY = 443 -+INTR_VAEND = 444 -+INTR_VAR_ANNOTATION = 445 -+INTR_VASTART = 446 -+INTR_X86_AESNI_AESDEC = 447 -+INTR_X86_AESNI_AESDECLAST = 448 -+INTR_X86_AESNI_AESENC = 449 -+INTR_X86_AESNI_AESENCLAST = 450 -+INTR_X86_AESNI_AESIMC = 451 -+INTR_X86_AESNI_AESKEYGENASSIST = 452 -+INTR_X86_AVX_ADDSUB_PD_256 = 453 -+INTR_X86_AVX_ADDSUB_PS_256 = 454 -+INTR_X86_AVX_BLEND_PD_256 = 455 -+INTR_X86_AVX_BLEND_PS_256 = 456 -+INTR_X86_AVX_BLENDV_PD_256 = 457 -+INTR_X86_AVX_BLENDV_PS_256 = 458 -+INTR_X86_AVX_CMP_PD_256 = 459 -+INTR_X86_AVX_CMP_PS_256 = 460 -+INTR_X86_AVX_CVT_PD2_PS_256 = 461 -+INTR_X86_AVX_CVT_PD2DQ_256 = 462 -+INTR_X86_AVX_CVT_PS2_PD_256 = 463 -+INTR_X86_AVX_CVT_PS2DQ_256 = 464 -+INTR_X86_AVX_CVTDQ2_PD_256 = 465 -+INTR_X86_AVX_CVTDQ2_PS_256 = 466 -+INTR_X86_AVX_CVTT_PD2DQ_256 = 467 -+INTR_X86_AVX_CVTT_PS2DQ_256 = 468 -+INTR_X86_AVX_DP_PS_256 = 469 -+INTR_X86_AVX_HADD_PD_256 = 470 -+INTR_X86_AVX_HADD_PS_256 = 471 -+INTR_X86_AVX_HSUB_PD_256 = 472 -+INTR_X86_AVX_HSUB_PS_256 = 473 -+INTR_X86_AVX_LDU_DQ_256 = 474 -+INTR_X86_AVX_LOADU_DQ_256 = 475 -+INTR_X86_AVX_LOADU_PD_256 = 476 -+INTR_X86_AVX_LOADU_PS_256 = 477 -+INTR_X86_AVX_MASKLOAD_PD = 478 -+INTR_X86_AVX_MASKLOAD_PD_256 = 479 -+INTR_X86_AVX_MASKLOAD_PS = 480 -+INTR_X86_AVX_MASKLOAD_PS_256 = 481 -+INTR_X86_AVX_MASKSTORE_PD = 482 -+INTR_X86_AVX_MASKSTORE_PD_256 = 483 -+INTR_X86_AVX_MASKSTORE_PS = 484 -+INTR_X86_AVX_MASKSTORE_PS_256 = 485 -+INTR_X86_AVX_MAX_PD_256 = 486 -+INTR_X86_AVX_MAX_PS_256 = 487 -+INTR_X86_AVX_MIN_PD_256 = 488 -+INTR_X86_AVX_MIN_PS_256 = 489 -+INTR_X86_AVX_MOVMSK_PD_256 = 490 -+INTR_X86_AVX_MOVMSK_PS_256 = 491 -+INTR_X86_AVX_MOVNT_DQ_256 = 492 -+INTR_X86_AVX_MOVNT_PD_256 = 493 -+INTR_X86_AVX_MOVNT_PS_256 = 494 -+INTR_X86_AVX_PTESTC_256 = 495 -+INTR_X86_AVX_PTESTNZC_256 = 496 -+INTR_X86_AVX_PTESTZ_256 = 497 -+INTR_X86_AVX_RCP_PS_256 = 498 -+INTR_X86_AVX_ROUND_PD_256 = 499 -+INTR_X86_AVX_ROUND_PS_256 = 500 -+INTR_X86_AVX_RSQRT_PS_256 = 501 -+INTR_X86_AVX_SQRT_PD_256 = 502 -+INTR_X86_AVX_SQRT_PS_256 = 503 -+INTR_X86_AVX_STOREU_DQ_256 = 504 -+INTR_X86_AVX_STOREU_PD_256 = 505 -+INTR_X86_AVX_STOREU_PS_256 = 506 -+INTR_X86_AVX_VBROADCAST_SD_256 = 507 -+INTR_X86_AVX_VBROADCASTF128_PD_256 = 508 -+INTR_X86_AVX_VBROADCASTF128_PS_256 = 509 -+INTR_X86_AVX_VBROADCASTSS = 510 -+INTR_X86_AVX_VBROADCASTSS_256 = 511 -+INTR_X86_AVX_VEXTRACTF128_PD_256 = 512 -+INTR_X86_AVX_VEXTRACTF128_PS_256 = 513 -+INTR_X86_AVX_VEXTRACTF128_SI_256 = 514 -+INTR_X86_AVX_VINSERTF128_PD_256 = 515 -+INTR_X86_AVX_VINSERTF128_PS_256 = 516 -+INTR_X86_AVX_VINSERTF128_SI_256 = 517 -+INTR_X86_AVX_VPERM2F128_PD_256 = 518 -+INTR_X86_AVX_VPERM2F128_PS_256 = 519 -+INTR_X86_AVX_VPERM2F128_SI_256 = 520 -+INTR_X86_AVX_VPERMIL_PD = 521 -+INTR_X86_AVX_VPERMIL_PD_256 = 522 -+INTR_X86_AVX_VPERMIL_PS = 523 -+INTR_X86_AVX_VPERMIL_PS_256 = 524 -+INTR_X86_AVX_VPERMILVAR_PD = 525 -+INTR_X86_AVX_VPERMILVAR_PD_256 = 526 -+INTR_X86_AVX_VPERMILVAR_PS = 527 -+INTR_X86_AVX_VPERMILVAR_PS_256 = 528 -+INTR_X86_AVX_VTESTC_PD = 529 -+INTR_X86_AVX_VTESTC_PD_256 = 530 -+INTR_X86_AVX_VTESTC_PS = 531 -+INTR_X86_AVX_VTESTC_PS_256 = 532 -+INTR_X86_AVX_VTESTNZC_PD = 533 -+INTR_X86_AVX_VTESTNZC_PD_256 = 534 -+INTR_X86_AVX_VTESTNZC_PS = 535 -+INTR_X86_AVX_VTESTNZC_PS_256 = 536 -+INTR_X86_AVX_VTESTZ_PD = 537 -+INTR_X86_AVX_VTESTZ_PD_256 = 538 -+INTR_X86_AVX_VTESTZ_PS = 539 -+INTR_X86_AVX_VTESTZ_PS_256 = 540 -+INTR_X86_AVX_VZEROALL = 541 -+INTR_X86_AVX_VZEROUPPER = 542 -+INTR_X86_INT = 543 -+INTR_X86_MMX_EMMS = 544 -+INTR_X86_MMX_FEMMS = 545 -+INTR_X86_MMX_MASKMOVQ = 546 -+INTR_X86_MMX_MOVNT_DQ = 547 -+INTR_X86_MMX_PACKSSDW = 548 -+INTR_X86_MMX_PACKSSWB = 549 -+INTR_X86_MMX_PACKUSWB = 550 -+INTR_X86_MMX_PADD_B = 551 -+INTR_X86_MMX_PADD_D = 552 -+INTR_X86_MMX_PADD_Q = 553 -+INTR_X86_MMX_PADD_W = 554 -+INTR_X86_MMX_PADDS_B = 555 -+INTR_X86_MMX_PADDS_W = 556 -+INTR_X86_MMX_PADDUS_B = 557 -+INTR_X86_MMX_PADDUS_W = 558 -+INTR_X86_MMX_PALIGNR_B = 559 -+INTR_X86_MMX_PAND = 560 -+INTR_X86_MMX_PANDN = 561 -+INTR_X86_MMX_PAVG_B = 562 -+INTR_X86_MMX_PAVG_W = 563 -+INTR_X86_MMX_PCMPEQ_B = 564 -+INTR_X86_MMX_PCMPEQ_D = 565 -+INTR_X86_MMX_PCMPEQ_W = 566 -+INTR_X86_MMX_PCMPGT_B = 567 -+INTR_X86_MMX_PCMPGT_D = 568 -+INTR_X86_MMX_PCMPGT_W = 569 -+INTR_X86_MMX_PEXTR_W = 570 -+INTR_X86_MMX_PINSR_W = 571 -+INTR_X86_MMX_PMADD_WD = 572 -+INTR_X86_MMX_PMAXS_W = 573 -+INTR_X86_MMX_PMAXU_B = 574 -+INTR_X86_MMX_PMINS_W = 575 -+INTR_X86_MMX_PMINU_B = 576 -+INTR_X86_MMX_PMOVMSKB = 577 -+INTR_X86_MMX_PMULH_W = 578 -+INTR_X86_MMX_PMULHU_W = 579 -+INTR_X86_MMX_PMULL_W = 580 -+INTR_X86_MMX_PMULU_DQ = 581 -+INTR_X86_MMX_POR = 582 -+INTR_X86_MMX_PSAD_BW = 583 -+INTR_X86_MMX_PSLL_D = 584 -+INTR_X86_MMX_PSLL_Q = 585 -+INTR_X86_MMX_PSLL_W = 586 -+INTR_X86_MMX_PSLLI_D = 587 -+INTR_X86_MMX_PSLLI_Q = 588 -+INTR_X86_MMX_PSLLI_W = 589 -+INTR_X86_MMX_PSRA_D = 590 -+INTR_X86_MMX_PSRA_W = 591 -+INTR_X86_MMX_PSRAI_D = 592 -+INTR_X86_MMX_PSRAI_W = 593 -+INTR_X86_MMX_PSRL_D = 594 -+INTR_X86_MMX_PSRL_Q = 595 -+INTR_X86_MMX_PSRL_W = 596 -+INTR_X86_MMX_PSRLI_D = 597 -+INTR_X86_MMX_PSRLI_Q = 598 -+INTR_X86_MMX_PSRLI_W = 599 -+INTR_X86_MMX_PSUB_B = 600 -+INTR_X86_MMX_PSUB_D = 601 -+INTR_X86_MMX_PSUB_Q = 602 -+INTR_X86_MMX_PSUB_W = 603 -+INTR_X86_MMX_PSUBS_B = 604 -+INTR_X86_MMX_PSUBS_W = 605 -+INTR_X86_MMX_PSUBUS_B = 606 -+INTR_X86_MMX_PSUBUS_W = 607 -+INTR_X86_MMX_PUNPCKHBW = 608 -+INTR_X86_MMX_PUNPCKHDQ = 609 -+INTR_X86_MMX_PUNPCKHWD = 610 -+INTR_X86_MMX_PUNPCKLBW = 611 -+INTR_X86_MMX_PUNPCKLDQ = 612 -+INTR_X86_MMX_PUNPCKLWD = 613 -+INTR_X86_MMX_PXOR = 614 -+INTR_X86_SSE2_ADD_SD = 615 -+INTR_X86_SSE2_CLFLUSH = 616 -+INTR_X86_SSE2_CMP_PD = 617 -+INTR_X86_SSE2_CMP_SD = 618 -+INTR_X86_SSE2_COMIEQ_SD = 619 -+INTR_X86_SSE2_COMIGE_SD = 620 -+INTR_X86_SSE2_COMIGT_SD = 621 -+INTR_X86_SSE2_COMILE_SD = 622 -+INTR_X86_SSE2_COMILT_SD = 623 -+INTR_X86_SSE2_COMINEQ_SD = 624 -+INTR_X86_SSE2_CVTDQ2PD = 625 -+INTR_X86_SSE2_CVTDQ2PS = 626 -+INTR_X86_SSE2_CVTPD2DQ = 627 -+INTR_X86_SSE2_CVTPD2PS = 628 -+INTR_X86_SSE2_CVTPS2DQ = 629 -+INTR_X86_SSE2_CVTPS2PD = 630 -+INTR_X86_SSE2_CVTSD2SI = 631 -+INTR_X86_SSE2_CVTSD2SI64 = 632 -+INTR_X86_SSE2_CVTSD2SS = 633 -+INTR_X86_SSE2_CVTSI2SD = 634 -+INTR_X86_SSE2_CVTSI642SD = 635 -+INTR_X86_SSE2_CVTSS2SD = 636 -+INTR_X86_SSE2_CVTTPD2DQ = 637 -+INTR_X86_SSE2_CVTTPS2DQ = 638 -+INTR_X86_SSE2_CVTTSD2SI = 639 -+INTR_X86_SSE2_CVTTSD2SI64 = 640 -+INTR_X86_SSE2_DIV_SD = 641 -+INTR_X86_SSE2_LFENCE = 642 -+INTR_X86_SSE2_LOADU_DQ = 643 -+INTR_X86_SSE2_LOADU_PD = 644 -+INTR_X86_SSE2_MASKMOV_DQU = 645 -+INTR_X86_SSE2_MAX_PD = 646 -+INTR_X86_SSE2_MAX_SD = 647 -+INTR_X86_SSE2_MFENCE = 648 -+INTR_X86_SSE2_MIN_PD = 649 -+INTR_X86_SSE2_MIN_SD = 650 -+INTR_X86_SSE2_MOVMSK_PD = 651 -+INTR_X86_SSE2_MOVNT_DQ = 652 -+INTR_X86_SSE2_MOVNT_I = 653 -+INTR_X86_SSE2_MOVNT_PD = 654 -+INTR_X86_SSE2_MUL_SD = 655 -+INTR_X86_SSE2_PACKSSDW_128 = 656 -+INTR_X86_SSE2_PACKSSWB_128 = 657 -+INTR_X86_SSE2_PACKUSWB_128 = 658 -+INTR_X86_SSE2_PADDS_B = 659 -+INTR_X86_SSE2_PADDS_W = 660 -+INTR_X86_SSE2_PADDUS_B = 661 -+INTR_X86_SSE2_PADDUS_W = 662 -+INTR_X86_SSE2_PAVG_B = 663 -+INTR_X86_SSE2_PAVG_W = 664 -+INTR_X86_SSE2_PCMPEQ_B = 665 -+INTR_X86_SSE2_PCMPEQ_D = 666 -+INTR_X86_SSE2_PCMPEQ_W = 667 -+INTR_X86_SSE2_PCMPGT_B = 668 -+INTR_X86_SSE2_PCMPGT_D = 669 -+INTR_X86_SSE2_PCMPGT_W = 670 -+INTR_X86_SSE2_PMADD_WD = 671 -+INTR_X86_SSE2_PMAXS_W = 672 -+INTR_X86_SSE2_PMAXU_B = 673 -+INTR_X86_SSE2_PMINS_W = 674 -+INTR_X86_SSE2_PMINU_B = 675 -+INTR_X86_SSE2_PMOVMSKB_128 = 676 -+INTR_X86_SSE2_PMULH_W = 677 -+INTR_X86_SSE2_PMULHU_W = 678 -+INTR_X86_SSE2_PMULU_DQ = 679 -+INTR_X86_SSE2_PSAD_BW = 680 -+INTR_X86_SSE2_PSLL_D = 681 -+INTR_X86_SSE2_PSLL_DQ = 682 -+INTR_X86_SSE2_PSLL_DQ_BS = 683 -+INTR_X86_SSE2_PSLL_Q = 684 -+INTR_X86_SSE2_PSLL_W = 685 -+INTR_X86_SSE2_PSLLI_D = 686 -+INTR_X86_SSE2_PSLLI_Q = 687 -+INTR_X86_SSE2_PSLLI_W = 688 -+INTR_X86_SSE2_PSRA_D = 689 -+INTR_X86_SSE2_PSRA_W = 690 -+INTR_X86_SSE2_PSRAI_D = 691 -+INTR_X86_SSE2_PSRAI_W = 692 -+INTR_X86_SSE2_PSRL_D = 693 -+INTR_X86_SSE2_PSRL_DQ = 694 -+INTR_X86_SSE2_PSRL_DQ_BS = 695 -+INTR_X86_SSE2_PSRL_Q = 696 -+INTR_X86_SSE2_PSRL_W = 697 -+INTR_X86_SSE2_PSRLI_D = 698 -+INTR_X86_SSE2_PSRLI_Q = 699 -+INTR_X86_SSE2_PSRLI_W = 700 -+INTR_X86_SSE2_PSUBS_B = 701 -+INTR_X86_SSE2_PSUBS_W = 702 -+INTR_X86_SSE2_PSUBUS_B = 703 -+INTR_X86_SSE2_PSUBUS_W = 704 -+INTR_X86_SSE2_SQRT_PD = 705 -+INTR_X86_SSE2_SQRT_SD = 706 -+INTR_X86_SSE2_STOREL_DQ = 707 -+INTR_X86_SSE2_STOREU_DQ = 708 -+INTR_X86_SSE2_STOREU_PD = 709 -+INTR_X86_SSE2_SUB_SD = 710 -+INTR_X86_SSE2_UCOMIEQ_SD = 711 -+INTR_X86_SSE2_UCOMIGE_SD = 712 -+INTR_X86_SSE2_UCOMIGT_SD = 713 -+INTR_X86_SSE2_UCOMILE_SD = 714 -+INTR_X86_SSE2_UCOMILT_SD = 715 -+INTR_X86_SSE2_UCOMINEQ_SD = 716 -+INTR_X86_SSE3_ADDSUB_PD = 717 -+INTR_X86_SSE3_ADDSUB_PS = 718 -+INTR_X86_SSE3_HADD_PD = 719 -+INTR_X86_SSE3_HADD_PS = 720 -+INTR_X86_SSE3_HSUB_PD = 721 -+INTR_X86_SSE3_HSUB_PS = 722 -+INTR_X86_SSE3_LDU_DQ = 723 -+INTR_X86_SSE3_MONITOR = 724 -+INTR_X86_SSE3_MWAIT = 725 -+INTR_X86_SSE41_BLENDPD = 726 -+INTR_X86_SSE41_BLENDPS = 727 -+INTR_X86_SSE41_BLENDVPD = 728 -+INTR_X86_SSE41_BLENDVPS = 729 -+INTR_X86_SSE41_DPPD = 730 -+INTR_X86_SSE41_DPPS = 731 -+INTR_X86_SSE41_EXTRACTPS = 732 -+INTR_X86_SSE41_INSERTPS = 733 -+INTR_X86_SSE41_MOVNTDQA = 734 -+INTR_X86_SSE41_MPSADBW = 735 -+INTR_X86_SSE41_PACKUSDW = 736 -+INTR_X86_SSE41_PBLENDVB = 737 -+INTR_X86_SSE41_PBLENDW = 738 -+INTR_X86_SSE41_PCMPEQQ = 739 -+INTR_X86_SSE41_PEXTRB = 740 -+INTR_X86_SSE41_PEXTRD = 741 -+INTR_X86_SSE41_PEXTRQ = 742 -+INTR_X86_SSE41_PHMINPOSUW = 743 -+INTR_X86_SSE41_PMAXSB = 744 -+INTR_X86_SSE41_PMAXSD = 745 -+INTR_X86_SSE41_PMAXUD = 746 -+INTR_X86_SSE41_PMAXUW = 747 -+INTR_X86_SSE41_PMINSB = 748 -+INTR_X86_SSE41_PMINSD = 749 -+INTR_X86_SSE41_PMINUD = 750 -+INTR_X86_SSE41_PMINUW = 751 -+INTR_X86_SSE41_PMOVSXBD = 752 -+INTR_X86_SSE41_PMOVSXBQ = 753 -+INTR_X86_SSE41_PMOVSXBW = 754 -+INTR_X86_SSE41_PMOVSXDQ = 755 -+INTR_X86_SSE41_PMOVSXWD = 756 -+INTR_X86_SSE41_PMOVSXWQ = 757 -+INTR_X86_SSE41_PMOVZXBD = 758 -+INTR_X86_SSE41_PMOVZXBQ = 759 -+INTR_X86_SSE41_PMOVZXBW = 760 -+INTR_X86_SSE41_PMOVZXDQ = 761 -+INTR_X86_SSE41_PMOVZXWD = 762 -+INTR_X86_SSE41_PMOVZXWQ = 763 -+INTR_X86_SSE41_PMULDQ = 764 -+INTR_X86_SSE41_PTESTC = 765 -+INTR_X86_SSE41_PTESTNZC = 766 -+INTR_X86_SSE41_PTESTZ = 767 -+INTR_X86_SSE41_ROUND_PD = 768 -+INTR_X86_SSE41_ROUND_PS = 769 -+INTR_X86_SSE41_ROUND_SD = 770 -+INTR_X86_SSE41_ROUND_SS = 771 -+INTR_X86_SSE42_CRC32_16 = 772 -+INTR_X86_SSE42_CRC32_32 = 773 -+INTR_X86_SSE42_CRC32_8 = 774 -+INTR_X86_SSE42_CRC64_64 = 775 -+INTR_X86_SSE42_CRC64_8 = 776 -+INTR_X86_SSE42_PCMPESTRI128 = 777 -+INTR_X86_SSE42_PCMPESTRIA128 = 778 -+INTR_X86_SSE42_PCMPESTRIC128 = 779 -+INTR_X86_SSE42_PCMPESTRIO128 = 780 -+INTR_X86_SSE42_PCMPESTRIS128 = 781 -+INTR_X86_SSE42_PCMPESTRIZ128 = 782 -+INTR_X86_SSE42_PCMPESTRM128 = 783 -+INTR_X86_SSE42_PCMPGTQ = 784 -+INTR_X86_SSE42_PCMPISTRI128 = 785 -+INTR_X86_SSE42_PCMPISTRIA128 = 786 -+INTR_X86_SSE42_PCMPISTRIC128 = 787 -+INTR_X86_SSE42_PCMPISTRIO128 = 788 -+INTR_X86_SSE42_PCMPISTRIS128 = 789 -+INTR_X86_SSE42_PCMPISTRIZ128 = 790 -+INTR_X86_SSE42_PCMPISTRM128 = 791 -+INTR_X86_SSE_ADD_SS = 792 -+INTR_X86_SSE_CMP_PS = 793 -+INTR_X86_SSE_CMP_SS = 794 -+INTR_X86_SSE_COMIEQ_SS = 795 -+INTR_X86_SSE_COMIGE_SS = 796 -+INTR_X86_SSE_COMIGT_SS = 797 -+INTR_X86_SSE_COMILE_SS = 798 -+INTR_X86_SSE_COMILT_SS = 799 -+INTR_X86_SSE_COMINEQ_SS = 800 -+INTR_X86_SSE_CVTPD2PI = 801 -+INTR_X86_SSE_CVTPI2PD = 802 -+INTR_X86_SSE_CVTPI2PS = 803 -+INTR_X86_SSE_CVTPS2PI = 804 -+INTR_X86_SSE_CVTSI2SS = 805 -+INTR_X86_SSE_CVTSI642SS = 806 -+INTR_X86_SSE_CVTSS2SI = 807 -+INTR_X86_SSE_CVTSS2SI64 = 808 -+INTR_X86_SSE_CVTTPD2PI = 809 -+INTR_X86_SSE_CVTTPS2PI = 810 -+INTR_X86_SSE_CVTTSS2SI = 811 -+INTR_X86_SSE_CVTTSS2SI64 = 812 -+INTR_X86_SSE_DIV_SS = 813 -+INTR_X86_SSE_LDMXCSR = 814 -+INTR_X86_SSE_LOADU_PS = 815 -+INTR_X86_SSE_MAX_PS = 816 -+INTR_X86_SSE_MAX_SS = 817 -+INTR_X86_SSE_MIN_PS = 818 -+INTR_X86_SSE_MIN_SS = 819 -+INTR_X86_SSE_MOVMSK_PS = 820 -+INTR_X86_SSE_MOVNT_PS = 821 -+INTR_X86_SSE_MUL_SS = 822 -+INTR_X86_SSE_PSHUF_W = 823 -+INTR_X86_SSE_RCP_PS = 824 -+INTR_X86_SSE_RCP_SS = 825 -+INTR_X86_SSE_RSQRT_PS = 826 -+INTR_X86_SSE_RSQRT_SS = 827 -+INTR_X86_SSE_SFENCE = 828 -+INTR_X86_SSE_SQRT_PS = 829 -+INTR_X86_SSE_SQRT_SS = 830 -+INTR_X86_SSE_STMXCSR = 831 -+INTR_X86_SSE_STOREU_PS = 832 -+INTR_X86_SSE_SUB_SS = 833 -+INTR_X86_SSE_UCOMIEQ_SS = 834 -+INTR_X86_SSE_UCOMIGE_SS = 835 -+INTR_X86_SSE_UCOMIGT_SS = 836 -+INTR_X86_SSE_UCOMILE_SS = 837 -+INTR_X86_SSE_UCOMILT_SS = 838 -+INTR_X86_SSE_UCOMINEQ_SS = 839 -+INTR_X86_SSSE3_PABS_B = 840 -+INTR_X86_SSSE3_PABS_B_128 = 841 -+INTR_X86_SSSE3_PABS_D = 842 -+INTR_X86_SSSE3_PABS_D_128 = 843 -+INTR_X86_SSSE3_PABS_W = 844 -+INTR_X86_SSSE3_PABS_W_128 = 845 -+INTR_X86_SSSE3_PHADD_D = 846 -+INTR_X86_SSSE3_PHADD_D_128 = 847 -+INTR_X86_SSSE3_PHADD_SW = 848 -+INTR_X86_SSSE3_PHADD_SW_128 = 849 -+INTR_X86_SSSE3_PHADD_W = 850 -+INTR_X86_SSSE3_PHADD_W_128 = 851 -+INTR_X86_SSSE3_PHSUB_D = 852 -+INTR_X86_SSSE3_PHSUB_D_128 = 853 -+INTR_X86_SSSE3_PHSUB_SW = 854 -+INTR_X86_SSSE3_PHSUB_SW_128 = 855 -+INTR_X86_SSSE3_PHSUB_W = 856 -+INTR_X86_SSSE3_PHSUB_W_128 = 857 -+INTR_X86_SSSE3_PMADD_UB_SW = 858 -+INTR_X86_SSSE3_PMADD_UB_SW_128 = 859 -+INTR_X86_SSSE3_PMUL_HR_SW = 860 -+INTR_X86_SSSE3_PMUL_HR_SW_128 = 861 -+INTR_X86_SSSE3_PSHUF_B = 862 -+INTR_X86_SSSE3_PSHUF_B_128 = 863 -+INTR_X86_SSSE3_PSIGN_B = 864 -+INTR_X86_SSSE3_PSIGN_B_128 = 865 -+INTR_X86_SSSE3_PSIGN_D = 866 -+INTR_X86_SSSE3_PSIGN_D_128 = 867 -+INTR_X86_SSSE3_PSIGN_W = 868 -+INTR_X86_SSSE3_PSIGN_W_128 = 869 -+INTR_XCORE_BITREV = 870 -+INTR_XCORE_CHKCT = 871 -+INTR_XCORE_CLRE = 872 -+INTR_XCORE_EEU = 873 -+INTR_XCORE_FREER = 874 -+INTR_XCORE_GETID = 875 -+INTR_XCORE_GETR = 876 -+INTR_XCORE_GETTS = 877 -+INTR_XCORE_IN = 878 -+INTR_XCORE_INCT = 879 -+INTR_XCORE_INSHR = 880 -+INTR_XCORE_INT = 881 -+INTR_XCORE_OUT = 882 -+INTR_XCORE_OUTCT = 883 -+INTR_XCORE_OUTSHR = 884 -+INTR_XCORE_OUTT = 885 -+INTR_XCORE_SETC = 886 -+INTR_XCORE_SETD = 887 -+INTR_XCORE_SETPT = 888 -+INTR_XCORE_SETTW = 889 -+INTR_XCORE_SETV = 890 -+INTR_XCORE_SYNCR = 891 -+INTR_XCORE_WAITEVENT = 892 -Index: _core.c -=================================================================== ---- _core.c (revision 105) -+++ _core.c (working copy) -@@ -807,7 +807,7 @@ - _wrap_pass( EdgeProfiler ) - _wrap_pass( FunctionAttrs ) - _wrap_pass( FunctionInlining ) --_wrap_pass( GEPSplitter ) -+//_wrap_pass( GEPSplitter ) - _wrap_pass( GlobalDCE ) - _wrap_pass( GlobalOptimizer ) - _wrap_pass( GlobalsModRef ) -@@ -822,11 +822,11 @@ - _wrap_pass( LazyValueInfo ) - _wrap_pass( LCSSA ) - _wrap_pass( LICM ) --_wrap_pass( LiveValues ) -+//_wrap_pass( LiveValues ) - _wrap_pass( LoopDeletion ) - _wrap_pass( LoopDependenceAnalysis ) - _wrap_pass( LoopExtractor ) --_wrap_pass( LoopIndexSplit ) -+//_wrap_pass( LoopIndexSplit ) - _wrap_pass( LoopRotate ) - _wrap_pass( LoopSimplify ) - _wrap_pass( LoopStrengthReduce ) -@@ -841,7 +841,7 @@ - _wrap_pass( NoProfileInfo ) - _wrap_pass( OptimalEdgeProfiler ) - _wrap_pass( PartialInlining ) --_wrap_pass( PartialSpecialization ) -+//_wrap_pass( PartialSpecialization ) - _wrap_pass( PostDomOnlyPrinter ) - _wrap_pass( PostDomOnlyViewer ) - _wrap_pass( PostDomPrinter ) -@@ -855,7 +855,7 @@ - _wrap_pass( ScalarEvolutionAliasAnalysis ) - _wrap_pass( ScalarReplAggregates ) - _wrap_pass( SCCP ) --_wrap_pass( SimplifyHalfPowrLibCalls ) -+//_wrap_pass( SimplifyHalfPowrLibCalls ) - _wrap_pass( SimplifyLibCalls ) - _wrap_pass( SingleLoopExtractor ) - _wrap_pass( StripDeadPrototypes ) -@@ -1162,7 +1162,7 @@ - Py_RETURN_NONE; - } - --_wrap_obj2obj(LLVMInlineFunction, LLVMValueRef, int) -+//_wrap_obj2obj(LLVMInlineFunction, LLVMValueRef, int) - - /* Expose the void* inside a PyCObject as a PyLong. This allows us to - * use it as a unique ID. */ -@@ -1569,7 +1569,7 @@ - _pass( EdgeProfiler ) - _pass( FunctionAttrs ) - _pass( FunctionInlining ) -- _pass( GEPSplitter ) -+ //_pass( GEPSplitter ) - _pass( GlobalDCE ) - _pass( GlobalOptimizer ) - _pass( GlobalsModRef ) -@@ -1584,11 +1584,11 @@ - _pass( LazyValueInfo ) - _pass( LCSSA ) - _pass( LICM ) -- _pass( LiveValues ) -+ //_pass( LiveValues ) - _pass( LoopDeletion ) - _pass( LoopDependenceAnalysis ) - _pass( LoopExtractor ) -- _pass( LoopIndexSplit ) -+ //_pass( LoopIndexSplit ) - _pass( LoopRotate ) - _pass( LoopSimplify ) - _pass( LoopStrengthReduce ) -@@ -1603,7 +1603,7 @@ - _pass( NoProfileInfo ) - _pass( OptimalEdgeProfiler ) - _pass( PartialInlining ) -- _pass( PartialSpecialization ) -+ //_pass( PartialSpecialization ) - _pass( PostDomOnlyPrinter ) - _pass( PostDomOnlyViewer ) - _pass( PostDomPrinter ) -@@ -1617,7 +1617,7 @@ - _pass( ScalarEvolutionAliasAnalysis ) - _pass( ScalarReplAggregates ) - _pass( SCCP ) -- _pass( SimplifyHalfPowrLibCalls ) -+ //_pass( SimplifyHalfPowrLibCalls ) - _pass( SimplifyLibCalls ) - _pass( SingleLoopExtractor ) - _pass( StripDeadPrototypes ) -@@ -1672,7 +1672,7 @@ - /* Misc */ - _method( LLVMGetIntrinsic ) - _method( LLVMLoadLibraryPermanently ) -- _method( LLVMInlineFunction ) -+ //_method( LLVMInlineFunction ) - _method( PyCObjectVoidPtrToPyLong ) - - { NULL } -Index: extra.h -=================================================================== ---- extra.h (revision 105) -+++ extra.h (working copy) -@@ -181,7 +181,7 @@ - /* Wraps llvm::InlineFunction(). Inlines a function. C is the call - * instruction, created by LLVMBuildCall. Even if it fails, the Function - * containing the call is still in a proper state (not changed). */ --int LLVMInlineFunction(LLVMValueRef call); -+//int LLVMInlineFunction(LLVMValueRef call); - - /* Wraps llvm::getAlignmentFromAttrs from Attributes.h. Compliments the - * already available LLVMSetParamAlignment(). */ -@@ -209,13 +209,13 @@ - declare_pass( DomPrinter ) - declare_pass( DomViewer ) - declare_pass( EdgeProfiler ) --declare_pass( GEPSplitter ) -+//declare_pass( GEPSplitter ) - declare_pass( GlobalsModRef ) - declare_pass( InstCount ) - declare_pass( InstructionNamer ) - declare_pass( LazyValueInfo ) - declare_pass( LCSSA ) --declare_pass( LiveValues ) -+//declare_pass( LiveValues ) - declare_pass( LoopDependenceAnalysis ) - declare_pass( LoopExtractor ) - declare_pass( LoopSimplify ) -@@ -227,7 +227,7 @@ - declare_pass( NoProfileInfo ) - declare_pass( OptimalEdgeProfiler ) - declare_pass( PartialInlining ) --declare_pass( PartialSpecialization ) -+//declare_pass( PartialSpecialization ) - declare_pass( PostDomOnlyPrinter ) - declare_pass( PostDomOnlyViewer ) - declare_pass( PostDomPrinter ) diff --git a/llvm/__init__.py b/llvm/__init__.py index 8f61f35..e69de29 100644 --- a/llvm/__init__.py +++ b/llvm/__init__.py @@ -1,154 +0,0 @@ -""" -Common classes related to LLVM. -""" - -from ._version import get_versions -__version__ = get_versions()['version'] -del get_versions - - -from weakref import WeakValueDictionary -from . import _core - -#===----------------------------------------------------------------------=== -# LLVM Version -#===----------------------------------------------------------------------=== - -version = _core.LLVMGetVersion() - -def require_version_at_least(major, minor): - '''Sentry to guard version requirement - ''' - if version < (major, minor): - raise Exception(major, minor) - -#===----------------------------------------------------------------------=== -# Exceptions -#===----------------------------------------------------------------------=== - -class LLVMException(Exception): - """Generic LLVM exception.""" - - def __init__(self, msg=""): - Exception.__init__(self, msg) - - -#===----------------------------------------------------------------------=== -# Ownables -#===----------------------------------------------------------------------=== - -class Ownable(object): - """Objects that can be owned. - - Modules and Module Providers can be owned, i.e., the responsibility of - destruction of ownable objects can be handed over to other objects. The - llvm.Ownable class represents objects that can be so owned. This class - is NOT intended for public use. - """ - - def __init__(self, ptr, del_fn): - self.ptr = ptr - self.owner = None - self.del_fn = del_fn - - def _own(self, owner): - if self.owner: - raise LLVMException("object already owned") - self.owner = owner - - def _disown(self): - if not self.owner: - raise LLVMException("not owned") - self.owner = None - - def __del__(self): - if not self.owner: - self.del_fn(self.ptr) - - -#===----------------------------------------------------------------------=== -# Dummy owner, will not delete ownee. Be careful. -#===----------------------------------------------------------------------=== - -class DummyOwner(object): - pass - - -#===----------------------------------------------------------------------=== -# A metaclass to prevent aliasing. It stores a (weak) reference to objects -# constructed based on a PyCObject. If an object is constructed based on a -# PyCObject with the same underlying pointer as a previous object, a reference -# to the previous object is returned rather than a new one. -#===----------------------------------------------------------------------=== - -class _ObjectCache(type): - """A metaclass to prevent aliasing. - - Classes using 'ObjectCache' as a metaclass must have constructors - that take a PyCObject as their first argument. When the class is - called (to create a new instance of the class), the value of the - pointer wrapped by the PyCObj is checked: - - If no previous object has been created based on the same - underlying pointer (note that different PyCObject objects can - wrap the same pointer), the object will be initialized as - usual and returned. - - If a previous has been created based on the same pointer, - then a reference to that object will be returned, and no - object initialization is performed. - """ - - __instances = WeakValueDictionary() - - def __call__(cls, ptr, *args, **kwargs): - objid = _core.PyCObjectVoidPtrToPyLong(ptr) - key = "%s:%d" % (cls.__name__, objid) - obj = _ObjectCache.__instances.get(key) - if obj is None: - obj = super(_ObjectCache, cls).__call__(ptr, *args, **kwargs) - _ObjectCache.__instances[key] = obj - return obj - - @staticmethod - def forget(obj): - objid = _core.PyCObjectVoidPtrToPyLong(obj.ptr) - key = "%s:%d" % (type(obj).__name__, objid) - if key in _ObjectCache.__instances: - del _ObjectCache.__instances[key] - - -#===----------------------------------------------------------------------=== -# Cacheables -#===----------------------------------------------------------------------=== - -# version 2/3 compatibility help -# version 2 metaclass -# class Cacheable(object): -# __metaclass__ = _ObjectCache # Doing nothing for version 3 -# -# version 3 metaclass -# class Cacheable(metaclass=_ObjectCache): -# -# Reference: http://mikewatkins.ca/2008/11/29/python-2-and-3-metaclasses/#using-the-metaclass-in-python-3-x -ObjectCache = _ObjectCache('ObjectCache', (object, ), {}) - -class Cacheable(ObjectCache): - """Objects that can be cached. - - Objects that wrap a PyCObject are cached to avoid "aliasing", i.e., - two Python objects each containing a PyCObject which internally points - to the same C pointer.""" - - def forget(self): - ObjectCache.forget(self) - - -def test(verbosity=1): - """test(verbosity=1) -> TextTestResult - - Run self-test, and return unittest.runner.TextTestResult object. - """ - from llvm.test_llvmpy import run - - return run(verbosity=verbosity) diff --git a/llvm/_core.cpp b/llvm/_core.cpp deleted file mode 100644 index db5287e..0000000 --- a/llvm/_core.cpp +++ /dev/null @@ -1,2212 +0,0 @@ -/* - * Copyright (c) 2008-10, Mahadevan R All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of this software, nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* our includes */ -#include "wrap.h" -#include "extra.h" - - - -// Python include -#include "Python.h" - -/* LLVM includes */ -#include "llvm-c/Analysis.h" -#include "llvm-c/Transforms/Scalar.h" -#include "llvm-c/ExecutionEngine.h" -#include "llvm-c/Target.h" -#include "llvm-c/Transforms/IPO.h" - -#include "llvm/Support/CommandLine.h" -#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 2 - #include "llvm-c/Linker.h" -#else - typedef unsigned int LLVMLinkerMode; -#endif - -/* Compatibility with Python 2.4: Py_ssize_t is not available. */ -#ifndef PY_SSIZE_T_MAX -typedef int Py_ssize_t; -#endif - - -// explicit specializations -template <> PyObject* pycap_new(int i) -{ - return PyLong_FromLong(static_cast(i)); -} - -template <> PyObject* pycap_new(unsigned long i) -{ - return PyLong_FromLong(static_cast(i)); -} - -template <> PyObject* pycap_new(LLVMTypeKind i) -{ - return PyLong_FromLong(static_cast(i)); -} - -template <> PyObject* pycap_new(LLVMLinkage i) -{ - return PyLong_FromLong(static_cast(i)); -} - -template <> PyObject* pycap_new(LLVMVisibility i) -{ - return PyLong_FromLong(static_cast(i)); -} - -template <> PyObject* pycap_new(LLVMByteOrdering i) -{ - return PyLong_FromLong(static_cast(i)); -} - -template <> PyObject* pycap_new(unsigned PY_LONG_LONG ull) -{ - return PyLong_FromUnsignedLongLong(ull); -} - -template <> PyObject* pycap_new(PY_LONG_LONG ll) -{ - return PyLong_FromLongLong(ll); -} - -/*===----------------------------------------------------------------------===*/ -/* Modules */ -/*===----------------------------------------------------------------------===*/ - -static PyObject * -_wLLVMModuleCreateWithName(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const char *s; - - if (!PyArg_ParseTuple(args, "s:LLVMModuleCreateWithName", &s)) { - return NULL; - } - - const LLVMModuleRef module = LLVMModuleCreateWithName(s); - return pycap_new(module); - LLVMPY_CATCH_ALL -} - -_wrap_obj2str(LLVMGetDataLayout, LLVMModuleRef) -_wrap_objstr2none(LLVMSetDataLayout, LLVMModuleRef) -_wrap_obj2str(LLVMGetModuleIdentifier, LLVMModuleRef) -_wrap_objstr2none(LLVMSetModuleIdentifier, LLVMModuleRef) -_wrap_obj2str(LLVMGetTarget, LLVMModuleRef) -_wrap_objstr2none(LLVMSetTarget, LLVMModuleRef) -_wrap_objstr2none(LLVMModuleAddLibrary, LLVMModuleRef) -_wrap_objstr2obj(LLVMGetTypeByName, LLVMModuleRef, LLVMTypeRef) -_wrap_obj2none(LLVMDumpModule, LLVMModuleRef) -_wrap_obj2none(LLVMDisposeModule, LLVMModuleRef) -_wrap_dumper(LLVMDumpModuleToString, LLVMModuleRef) - _wrap_obj2obj( LLVMModuleGetPointerSize, LLVMModuleRef, int) -_wrap_objstrobj2obj(LLVMModuleGetOrInsertFunction, LLVMModuleRef, - LLVMTypeRef, LLVMValueRef) - -static PyObject * -_wLLVMVerifyModule(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const LLVMModuleRef m = get_object_arg(args) ; - if (!m) return NULL; - - char *outmsg = 0; - (void) LLVMVerifyModule(m, LLVMReturnStatusAction, &outmsg); - - PyObject *ret; - if (outmsg) { - ret = PyUnicode_FromString(outmsg); - LLVMDisposeMessage(outmsg); - } else { - ret = PyUnicode_FromString(""); - } - - return ret; - LLVMPY_CATCH_ALL -} - -///// unused -// typedef LLVMModuleRef (*asm_or_bc_fn_t)(const char *A, unsigned Len, char **OutMessage); - - -static PyObject* -_wLLVMGetModuleFromAssembly(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const char * str; -#if (PY_MAJOR_VERSION >= 3) - if ( !PyArg_ParseTuple(args, "y", &str) ){ -#else - if ( !PyArg_ParseTuple(args, "s", &str) ){ -#endif - return NULL; - } - - char * outmsg = 0; - const LLVMModuleRef mod = LLVMGetModuleFromAssembly(str, &outmsg); - - if ( !mod ){ - if ( outmsg ){ - PyObject * ret = PyUnicode_FromString(outmsg); - LLVMDisposeMessage(outmsg); - return ret; - } else { - Py_RETURN_NONE; - } - } - - return pycap_new(mod); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMGetModuleFromBitcode(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj ; - - if (!PyArg_ParseTuple(args, "S", &obj)) - return NULL; - - const char *start = PyBytes_AsString(obj); - const Py_ssize_t len = PyBytes_Size(obj); - - char *outmsg = 0; - LLVMModuleRef m = LLVMGetModuleFromBitcode(start, len, &outmsg); - - PyObject *ret; - if (!m) { - if (outmsg) { - ret = PyUnicode_FromString(outmsg); - LLVMDisposeMessage(outmsg); - return ret; - } else { - Py_RETURN_NONE; - } - } - - return pycap_new(m); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMGetBitcodeFromModule(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const LLVMModuleRef m = get_object_arg(args) ; - if (!m ) return NULL; - - size_t len; - const unsigned char *ubytes = LLVMGetBitcodeFromModule(m, &len) ; - if ( !ubytes ) Py_RETURN_NONE; - - const char *chars = reinterpret_cast(ubytes) ; - PyObject *ret = PyBytes_FromStringAndSize(chars, len); - delete [] ubytes; - return ret; - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMGetNativeCodeFromModule(PyObject * self, PyObject * args) -{ - LLVMPY_TRY - PyObject * arg_m; - int arg_use_asm; - - if (!PyArg_ParseTuple(args, "Oi", &arg_m, &arg_use_asm)) - return NULL; - - const LLVMModuleRef m = pycap_get( arg_m ) ; - - std::string error; - size_t len; - unsigned const char * ubytes - = LLVMGetNativeCodeFromModule(m, arg_use_asm, &len, error); - if ( !error.empty() ){ - PyErr_SetString(PyExc_RuntimeError, error.c_str()); - } - - const char *chars = reinterpret_cast(ubytes) ; - PyObject * ret = PyBytes_FromStringAndSize(chars, len); - - delete [] ubytes; - - return ret; - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMLinkModules(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - size_t mode = 0; - - PyObject *dest_obj, *src_obj ; - if (!PyArg_ParseTuple(args, "OO|I", &dest_obj, &src_obj, &mode)) - return NULL; - - const LLVMModuleRef dest = pycap_get(dest_obj ) ; - const LLVMModuleRef src = pycap_get(src_obj) ; - - PyObject *ret = NULL; - char *errmsg = NULL; - if (LLVMLinkModules(dest, src, (LLVMLinkerMode)mode, &errmsg)) { - if (errmsg) { - ret = PyUnicode_FromString(errmsg); - LLVMDisposeMessage(errmsg); - } else { - ret = PyUnicode_FromString("Link error"); - } - return ret; - } - - /* note: success => None, failure => string with error message */ - Py_RETURN_NONE; - LLVMPY_CATCH_ALL -} - -_wrap_objstr2obj(LLVMModuleGetOrInsertNamedMetaData, LLVMModuleRef, LLVMNamedMDRef) -_wrap_objstr2obj(LLVMModuleGetNamedMetaData, LLVMModuleRef, LLVMNamedMDRef) -_wrap_obj2obj(LLVMCloneModule, LLVMModuleRef, LLVMModuleRef) - -/*===----------------------------------------------------------------------===*/ -/* Types */ -/*===----------------------------------------------------------------------===*/ - -/*===-- General ----------------------------------------------------------===*/ - -_wrap_obj2obj(LLVMGetTypeKind, LLVMTypeRef, int) -_wrap_dumper(LLVMDumpTypeToString, LLVMTypeRef) - -/*===-- Integer types ----------------------------------------------------===*/ - -_wrap_none2obj(LLVMInt1Type, LLVMTypeRef) -_wrap_none2obj(LLVMInt8Type, LLVMTypeRef) -_wrap_none2obj(LLVMInt16Type, LLVMTypeRef) -_wrap_none2obj(LLVMInt32Type, LLVMTypeRef) -_wrap_none2obj(LLVMInt64Type, LLVMTypeRef) -_wrap_int2obj(LLVMIntType, LLVMTypeRef) -_wrap_obj2obj(LLVMGetIntTypeWidth, LLVMTypeRef, int) - -/*===-- Floating-point types ---------------------------------------------===*/ - -_wrap_none2obj(LLVMFloatType, LLVMTypeRef) -_wrap_none2obj(LLVMDoubleType, LLVMTypeRef) -_wrap_none2obj(LLVMX86FP80Type, LLVMTypeRef) -_wrap_none2obj(LLVMFP128Type, LLVMTypeRef) -_wrap_none2obj(LLVMPPCFP128Type, LLVMTypeRef) - -/*===-- Function types ---------------------------------------------------===*/ - -_wrap_objlistint2obj(LLVMFunctionType, LLVMTypeRef, LLVMTypeRef, LLVMTypeRef) -_wrap_obj2obj(LLVMIsFunctionVarArg, LLVMTypeRef, int) -_wrap_obj2obj(LLVMGetReturnType, LLVMTypeRef, LLVMTypeRef) -_wrap_obj2obj(LLVMCountParamTypes, LLVMTypeRef, int) - -/* The LLVMGetParamTypes and LLVMGetStructElementTypes functions both - * have the same signatures. The following implementation takes advantage - * of this. - */ - -typedef void (*obj2arr_fn_t)(LLVMTypeRef ty, LLVMTypeRef *outv); -typedef unsigned (*arrcnt_fn_t)(LLVMTypeRef ty); - -static PyObject * -obj2arr(PyObject *self, PyObject *args, arrcnt_fn_t cntfunc, obj2arr_fn_t arrfunc) -{ - size_t param_count; - - /* get the function object ptr */ - const LLVMTypeRef type = get_object_arg(args) ; - - /* get param count */ - param_count = cntfunc(type); - - /* alloc enough space for all of them */ - LLVMTypeRef* param_types = new LLVMTypeRef[param_count] ; - - /* call LLVM func */ - arrfunc(type, param_types); - - /* create a list from the array */ - PyObject *list = make_list(param_types, param_count); - - /* free temp storage */ - delete [] param_types ; - - return list; -} - -static PyObject * -_wLLVMGetFunctionTypeParams(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - return obj2arr(self, args, LLVMCountParamTypes, LLVMGetParamTypes); - LLVMPY_CATCH_ALL -} - -/*===-- Struct types -----------------------------------------------------===*/ - -_wrap_listint2obj(LLVMStructType, LLVMTypeRef, LLVMTypeRef) -_wrap_str2obj(LLVMStructTypeIdentified, LLVMTypeRef) -_wrap_objlistint2none(LLVMSetStructBody, LLVMTypeRef, LLVMTypeRef) -_wrap_obj2obj(LLVMCountStructElementTypes, LLVMTypeRef, int) -_wrap_obj2str(LLVMGetStructName, LLVMTypeRef) -_wrap_objstr2none(LLVMSetStructName, LLVMTypeRef) - - -static PyObject * -_wLLVMGetStructElementTypes(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - return obj2arr(self, args, LLVMCountStructElementTypes, - LLVMGetStructElementTypes); - LLVMPY_CATCH_ALL -} - - -_wrap_obj2obj(LLVMIsPackedStruct, LLVMTypeRef, int) -_wrap_obj2obj(LLVMIsOpaqueStruct, LLVMTypeRef, int) -_wrap_obj2obj(LLVMIsLiteralStruct, LLVMTypeRef, int) - -/*===-- Array types ------------------------------------------------------===*/ - -_wrap_objint2obj(LLVMArrayType, LLVMTypeRef, LLVMTypeRef) -_wrap_obj2obj(LLVMGetElementType, LLVMTypeRef, LLVMTypeRef) -_wrap_obj2obj(LLVMGetArrayLength, LLVMTypeRef, int) - -/*===-- Pointer types ----------------------------------------------------===*/ - -_wrap_objint2obj(LLVMPointerType, LLVMTypeRef, LLVMTypeRef) -_wrap_obj2obj(LLVMGetPointerAddressSpace, LLVMTypeRef, int) - -/*===-- Vector type ------------------------------------------------------===*/ - -_wrap_objint2obj(LLVMVectorType, LLVMTypeRef, LLVMTypeRef) -_wrap_obj2obj(LLVMGetVectorSize, LLVMTypeRef, int) - -/*===-- Other types ------------------------------------------------------===*/ - -_wrap_none2obj(LLVMVoidType, LLVMTypeRef) -_wrap_none2obj(LLVMLabelType, LLVMTypeRef) - -/*===-- Type handles -----------------------------------------------------===*/ - -/* -_wrap_obj2obj(LLVMCreateTypeHandle, LLVMTypeRef, LLVMTypeHandleRef) -_wrap_obj2obj(LLVMResolveTypeHandle, LLVMTypeHandleRef, LLVMTypeRef) -_wrap_obj2none(LLVMDisposeTypeHandle, LLVMTypeHandleRef) -*/ - - -/*===----------------------------------------------------------------------===*/ -/* Values */ -/*===----------------------------------------------------------------------===*/ - -/* Operations on all values */ - -_wrap_obj2obj(LLVMTypeOf, LLVMValueRef, LLVMTypeRef) -_wrap_obj2str(LLVMGetValueName, LLVMValueRef) -_wrap_objstr2none(LLVMSetValueName, LLVMValueRef) -_wrap_obj2none(LLVMDumpValue, LLVMValueRef) -_wrap_dumper(LLVMDumpValueToString, LLVMValueRef) -_wrap_obj2obj(LLVMValueGetID, LLVMValueRef, int) -_wrap_obj2obj(LLVMValueGetNumUses, LLVMValueRef, int) - -static PyObject * -_wLLVMValueGetUses(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const LLVMValueRef value = get_object_arg(args) ; - - LLVMValueRef *uses = 0; - size_t n = LLVMValueGetUses(value, &uses); - - PyObject *list = make_list(uses, n); - if (n > 0) - LLVMDisposeValueRefArray(uses); - - return list; - LLVMPY_CATCH_ALL -} - -/*===-- Users ------------------------------------------------------------===*/ - -_wrap_obj2obj(LLVMUserGetNumOperands, LLVMValueRef, int) -_wrap_objint2obj(LLVMUserGetOperand, LLVMValueRef, LLVMValueRef) - -/*===-- Constant Values --------------------------------------------------===*/ - -/* Operations on constants of any type */ - -_wrap_obj2obj(LLVMConstNull, LLVMTypeRef, LLVMValueRef) -_wrap_obj2obj(LLVMConstAllOnes, LLVMTypeRef, LLVMValueRef) -_wrap_obj2obj(LLVMGetUndef, LLVMTypeRef, LLVMValueRef) -_wrap_obj2obj(LLVMIsConstant, LLVMValueRef, int) -_wrap_obj2obj(LLVMIsNull, LLVMValueRef, int) -_wrap_obj2obj(LLVMIsUndef, LLVMValueRef, int) - -/* Operations on scalar constants */ - -static PyObject * -_wLLVMConstInt(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj; - unsigned PY_LONG_LONG n; - int sign_extend; - - if (!PyArg_ParseTuple(args, "OKi", &obj, &n, &sign_extend)) - return NULL; - - const LLVMTypeRef ty = pycap_get( obj ) ; - - const LLVMValueRef val = LLVMConstInt(ty, n, sign_extend); - - return pycap_new(val); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMConstReal(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj; - double d; - - if (!PyArg_ParseTuple(args, "Od", &obj, &d)) - return NULL; - - const LLVMTypeRef ty = pycap_get( obj ) ; - - const LLVMValueRef val = LLVMConstReal(ty, d); - return pycap_new(val); - LLVMPY_CATCH_ALL -} - -_wrap_objstr2obj(LLVMConstRealOfString, LLVMTypeRef, LLVMValueRef) -_wrap_obj2obj(LLVMConstIntGetZExtValue, LLVMValueRef, llvmwrap_ull) -_wrap_obj2obj(LLVMConstIntGetSExtValue, LLVMValueRef, llvmwrap_ll) - -/* Operations on composite constants */ - -static PyObject * -_wLLVMConstString(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const char *s; - int dont_null_terminate; - - if (!PyArg_ParseTuple(args, "si:LLVMConstString", &s, &dont_null_terminate)) { - return NULL; - } - - LLVMValueRef val = LLVMConstString(s, strlen(s), dont_null_terminate); - return pycap_new(val); - LLVMPY_CATCH_ALL -} - -_wrap_objlist2obj(LLVMConstArray, LLVMTypeRef, LLVMValueRef, LLVMValueRef) -_wrap_listint2obj(LLVMConstStruct, LLVMValueRef, LLVMValueRef) -_wrap_list2obj(LLVMConstVector, LLVMValueRef, LLVMValueRef) - -/* Constant expressions */ - -_wrap_obj2obj(LLVMGetConstExprOpcode, LLVMValueRef, int) -_wrap_obj2str(LLVMGetConstExprOpcodeName, LLVMValueRef) -_wrap_obj2obj(LLVMSizeOf, LLVMTypeRef, LLVMValueRef) -_wrap_obj2obj(LLVMConstNeg, LLVMValueRef, LLVMValueRef) -_wrap_obj2obj(LLVMConstNot, LLVMValueRef, LLVMValueRef) - -_wrap_objobj2obj(LLVMConstAdd, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstFAdd, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstSub, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstFSub, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstMul, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstFMul, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstUDiv, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstSDiv, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstFDiv, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstURem, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstSRem, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstFRem, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstAnd, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstOr, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstXor, LLVMValueRef, LLVMValueRef, LLVMValueRef) - -_wrap_enumobjobj2obj(LLVMConstICmp, LLVMIntPredicate, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_enumobjobj2obj(LLVMConstFCmp, LLVMRealPredicate, LLVMValueRef, LLVMValueRef, LLVMValueRef) - -_wrap_objobj2obj(LLVMConstShl, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstLShr, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstAShr, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objlist2obj(LLVMConstGEP, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstTrunc, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstSExt, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstZExt, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstFPTrunc, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstFPExt, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstUIToFP, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstSIToFP, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstFPToUI, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstFPToSI, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstPtrToInt, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstIntToPtr, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstBitCast, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobj2obj(LLVMConstSelect, LLVMValueRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMConstExtractElement, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobj2obj(LLVMConstInsertElement, LLVMValueRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobj2obj(LLVMConstShuffleVector, LLVMValueRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) - - -/*===----------------------------------------------------------------------===*/ -/* Globals */ -/*===----------------------------------------------------------------------===*/ - -/*===-- Globals ----------------------------------------------------------===*/ - -_wrap_obj2obj(LLVMGetGlobalParent, LLVMValueRef, LLVMModuleRef) -_wrap_obj2obj(LLVMIsDeclaration, LLVMValueRef, int) -_wrap_obj2obj(LLVMGetLinkage, LLVMValueRef, int) -_wrap_objenum2none(LLVMSetLinkage, LLVMValueRef, LLVMLinkage) -_wrap_obj2str(LLVMGetSection, LLVMValueRef) -_wrap_objstr2none(LLVMSetSection, LLVMValueRef) -_wrap_obj2obj(LLVMGetVisibility, LLVMValueRef, int) -_wrap_objenum2none(LLVMSetVisibility, LLVMValueRef, LLVMVisibility) -_wrap_obj2obj(LLVMGetAlignment, LLVMValueRef, int) -_wrap_objint2none(LLVMSetAlignment, LLVMValueRef) - -/*===-- Global Variables -------------------------------------------------===*/ - -_wrap_objobjstr2obj(LLVMAddGlobal, LLVMModuleRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjstrint2obj(LLVMAddGlobalInAddressSpace, LLVMModuleRef, LLVMTypeRef, LLVMValueRef) -_wrap_objstr2obj(LLVMGetNamedGlobal, LLVMModuleRef, LLVMValueRef) -_wrap_obj2obj(LLVMGetFirstGlobal, LLVMModuleRef, LLVMValueRef) -_wrap_obj2obj(LLVMGetNextGlobal, LLVMValueRef, LLVMValueRef) -_wrap_obj2none(LLVMDeleteGlobal, LLVMValueRef) -_wrap_obj2obj(LLVMHasInitializer, LLVMValueRef, int) -_wrap_obj2obj(LLVMGetInitializer, LLVMValueRef, LLVMValueRef) -_wrap_objobj2none(LLVMSetInitializer, LLVMValueRef, LLVMValueRef) -_wrap_objint2none(LLVMSetGlobalConstant, LLVMValueRef) -_wrap_obj2obj(LLVMIsGlobalConstant, LLVMValueRef, int) -_wrap_objint2none(LLVMSetThreadLocal, LLVMValueRef) -_wrap_obj2obj(LLVMIsThreadLocal, LLVMValueRef, int) - - -/*===-- Functions --------------------------------------------------------===*/ - -_wrap_objstrobj2obj(LLVMAddFunction, LLVMModuleRef, LLVMTypeRef, LLVMValueRef) -_wrap_objstr2obj(LLVMGetNamedFunction, LLVMModuleRef, LLVMValueRef) -_wrap_obj2obj(LLVMGetFirstFunction, LLVMModuleRef, LLVMValueRef) -_wrap_obj2obj(LLVMGetNextFunction, LLVMValueRef, LLVMValueRef) -_wrap_obj2none(LLVMDeleteFunction, LLVMValueRef) -_wrap_obj2obj(LLVMGetIntrinsicID, LLVMValueRef, int) -_wrap_obj2obj(LLVMGetFunctionCallConv, LLVMValueRef, int) -_wrap_objint2none(LLVMSetFunctionCallConv, LLVMValueRef) -_wrap_obj2str(LLVMGetGC, LLVMValueRef) -_wrap_objstr2none(LLVMSetGC, LLVMValueRef) -_wrap_obj2obj(LLVMGetDoesNotThrow, LLVMValueRef, int) -_wrap_objint2none(LLVMSetDoesNotThrow, LLVMValueRef) -_wrap_obj2none(LLVMViewFunctionCFG, LLVMValueRef) -_wrap_obj2none(LLVMViewFunctionCFGOnly, LLVMValueRef) -_wrap_objenum2none(LLVMAddFunctionAttr, LLVMValueRef, LLVMAttribute) -_wrap_objenum2none(LLVMRemoveFunctionAttr, LLVMValueRef, LLVMAttribute) - -static PyObject * -_wLLVMVerifyFunction(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const LLVMValueRef fn = get_object_arg(args); - if (!fn) return NULL; - - return pycap_new(LLVMVerifyFunction(fn, LLVMReturnStatusAction)); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMGetFunctionFromInlineAsm(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *pycapFuncType; - const char *inlineAsm = NULL; - const char *constrains = NULL; - int hasSideEffect; - int isAlignStack; - int asmDialect; - - if (!PyArg_ParseTuple(args, "Ossiii", &pycapFuncType, &inlineAsm, - &constrains, &hasSideEffect, - &isAlignStack, &asmDialect)) - return NULL; - - - LLVMTypeRef funcType = pycap_get(pycapFuncType); - LLVMValueRef inlineAsmRef; - inlineAsmRef = LLVMGetFunctionFromInlineAsm(funcType, inlineAsm, constrains, - hasSideEffect, isAlignStack, - asmDialect); - - return pycap_new(inlineAsmRef); - LLVMPY_CATCH_ALL -} - - -/*===-- Arguments --------------------------------------------------------===*/ - -_wrap_obj2obj(LLVMCountParams, LLVMValueRef, int) -_wrap_obj2obj(LLVMGetFirstParam, LLVMValueRef, LLVMValueRef) -_wrap_obj2obj(LLVMGetNextParam, LLVMValueRef, LLVMValueRef) -_wrap_obj2obj(LLVMGetParamParent, LLVMValueRef, LLVMValueRef) -_wrap_objenum2none(LLVMAddAttribute, LLVMValueRef, LLVMAttribute) -_wrap_objenum2none(LLVMRemoveAttribute, LLVMValueRef, LLVMAttribute) -_wrap_objenum2none(LLVMSetParamAlignment, LLVMValueRef, LLVMAttribute) -_wrap_obj2obj(LLVMGetParamAlignment, LLVMValueRef, int) - -/*===-- Basic Blocks -----------------------------------------------------===*/ - -_wrap_obj2obj(LLVMGetBasicBlockParent, LLVMBasicBlockRef, LLVMValueRef) -_wrap_obj2obj(LLVMCountBasicBlocks, LLVMValueRef, int) -_wrap_obj2obj(LLVMGetFirstBasicBlock, LLVMValueRef, LLVMBasicBlockRef) -_wrap_obj2obj(LLVMGetNextBasicBlock, LLVMBasicBlockRef, LLVMBasicBlockRef) -_wrap_obj2obj(LLVMGetEntryBasicBlock, LLVMValueRef, LLVMBasicBlockRef) -_wrap_objstr2obj(LLVMAppendBasicBlock, LLVMValueRef, LLVMBasicBlockRef) -_wrap_objstr2obj(LLVMInsertBasicBlock, LLVMBasicBlockRef, LLVMBasicBlockRef) -_wrap_obj2none(LLVMDeleteBasicBlock, LLVMBasicBlockRef) - - -/*===-- MetaData -----------------------------------------------------===*/ - -_wrap_objlist2obj(LLVMMetaDataGet, LLVMModuleRef, LLVMValueRef, LLVMValueRef) -_wrap_objstrobj2none(LLVMAddNamedMetadataOperand, LLVMModuleRef, LLVMValueRef) -_wrap_objint2obj(LLVMMetaDataGetOperand, LLVMValueRef, LLVMValueRef) -_wrap_obj2obj(LLVMMetaDataGetNumOperands, LLVMValueRef, int) -_wrap_objstr2obj(LLVMMetaDataStringGet, LLVMModuleRef, LLVMValueRef) - -static PyObject * -_wLLVMGetNamedMetadataOperands(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj_module; - const char *name; - - if (!PyArg_ParseTuple(args, "Os", &obj_module, &name)) - return NULL; - - LLVMModuleRef module = pycap_get(obj_module); - unsigned num_operands = LLVMGetNamedMetadataNumOperands(module, name); - LLVMValueRef *operands = new LLVMValueRef[num_operands]; - LLVMGetNamedMetadataOperands(module, name, operands); - - PyObject *list = make_list(operands, num_operands); - delete [] operands; - - return list; - LLVMPY_CATCH_ALL -} - - -/*===-- NamedMetaData -----------------------------------------------------===*/ - -_wrap_obj2str( LLVMNamedMetaDataGetName, LLVMNamedMDRef ) -_wrap_objobj2none( LLVMNamedMetaDataAddOperand, LLVMNamedMDRef, LLVMValueRef ) -_wrap_obj2none( LLVMEraseNamedMetaData, LLVMNamedMDRef ) -_wrap_dumper(LLVMDumpNamedMDToString, LLVMNamedMDRef) - -/*===-- Instructions -----------------------------------------------------===*/ - -_wrap_obj2obj(LLVMGetInstructionParent, LLVMValueRef, LLVMBasicBlockRef) -_wrap_obj2obj(LLVMGetFirstInstruction, LLVMBasicBlockRef, LLVMValueRef) -_wrap_obj2obj(LLVMGetNextInstruction, LLVMValueRef, LLVMValueRef) -_wrap_obj2obj(LLVMInstIsTerminator, LLVMValueRef, int) -_wrap_obj2obj(LLVMInstIsBinaryOp, LLVMValueRef, int) -_wrap_obj2obj(LLVMInstIsShift, LLVMValueRef, int) -_wrap_obj2obj(LLVMInstIsCast, LLVMValueRef, int) -_wrap_obj2obj(LLVMInstIsLogicalShift, LLVMValueRef, int) -_wrap_obj2obj(LLVMInstIsArithmeticShift, LLVMValueRef, int) -_wrap_obj2obj(LLVMInstIsAssociative, LLVMValueRef, int) -_wrap_obj2obj(LLVMInstIsCommutative, LLVMValueRef, int) -_wrap_obj2obj(LLVMInstIsVolatile, LLVMValueRef, int) -_wrap_objint2none(LLVMSetVolatile, LLVMValueRef) -_wrap_obj2obj(LLVMInstGetOpcode, LLVMValueRef, int) -_wrap_obj2str(LLVMInstGetOpcodeName, LLVMValueRef) - -_wrap_objstrobj2none(LLVMInstSetMetaData, LLVMValueRef, LLVMValueRef) -_wrap_obj2none(LLVMInstructionEraseFromParent, LLVMValueRef) - -/*===-- Call Sites (Call or Invoke) --------------------------------------===*/ - -_wrap_objint2none(LLVMSetInstructionCallConv, LLVMValueRef) -_wrap_obj2obj(LLVMGetInstructionCallConv, LLVMValueRef, int) -_wrap_objintenum2none(LLVMAddInstrAttribute, LLVMValueRef, LLVMAttribute) -_wrap_objintenum2none(LLVMRemoveInstrAttribute, LLVMValueRef, LLVMAttribute) -_wrap_objintint2none(LLVMSetInstrParamAlignment, LLVMValueRef) -_wrap_obj2obj(LLVMIsTailCall, LLVMValueRef, int) -_wrap_objint2none(LLVMSetTailCall, LLVMValueRef) -_wrap_obj2obj(LLVMInstGetCalledFunction, LLVMValueRef, LLVMValueRef) -_wrap_objobj2none(LLVMInstSetCalledFunction, LLVMValueRef, LLVMValueRef) - -/*===-- PHI Nodes --------------------------------------------------------===*/ - -static void LLVMAddIncoming1(LLVMValueRef PhiNode, LLVMValueRef IncomingValue, LLVMBasicBlockRef IncomingBlock) -{ - LLVMAddIncoming(PhiNode, &IncomingValue, &IncomingBlock, 1); -} - -_wrap_objobjobj2none(LLVMAddIncoming1, LLVMValueRef, LLVMValueRef, LLVMBasicBlockRef) -_wrap_obj2obj(LLVMCountIncoming, LLVMValueRef, int) -_wrap_objint2obj(LLVMGetIncomingValue, LLVMValueRef, LLVMValueRef) -_wrap_objint2obj(LLVMGetIncomingBlock, LLVMValueRef, LLVMBasicBlockRef) - -/*===-- Compare Instructions ---------------------------------------------===*/ - -_wrap_obj2obj(LLVMCmpInstGetPredicate, LLVMValueRef, int) - -/*===-- Instruction builders ----------------------------------------------===*/ - -_wrap_none2obj(LLVMCreateBuilder, LLVMBuilderRef) -_wrap_objobj2none(LLVMPositionBuilderBefore, LLVMBuilderRef, LLVMValueRef) -_wrap_objobj2none(LLVMPositionBuilderAtEnd, LLVMBuilderRef, LLVMBasicBlockRef) -_wrap_obj2obj(LLVMGetInsertBlock, LLVMBuilderRef, LLVMBasicBlockRef) -_wrap_obj2none(LLVMDisposeBuilder, LLVMBuilderRef) - -/* Terminators */ - -_wrap_obj2obj(LLVMBuildRetVoid, LLVMBuilderRef, LLVMValueRef) -_wrap_objobj2obj(LLVMBuildRet, LLVMBuilderRef, LLVMValueRef, LLVMValueRef) -_wrap_objlist2obj(LLVMBuildRetMultiple, LLVMBuilderRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMBuildBr, LLVMBuilderRef, LLVMBasicBlockRef, LLVMValueRef) -_wrap_objobjobjobj2obj(LLVMBuildCondBr, LLVMBuilderRef, LLVMValueRef, LLVMBasicBlockRef, LLVMBasicBlockRef, LLVMValueRef) -_wrap_objobjobjint2obj(LLVMBuildSwitch, LLVMBuilderRef, LLVMValueRef, LLVMBasicBlockRef, LLVMValueRef) - -static PyObject * -_wLLVMBuildInvoke(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj1, *obj2, *obj3, *obj4, *obj5; - const char *name; - - if (!PyArg_ParseTuple(args, "OOOOOs:LLVMBuildInvoke", &obj1, &obj2, &obj3, &obj4, &obj5, &name)) { - return NULL; - } - - const LLVMBuilderRef builder = pycap_get( obj1); - const LLVMValueRef func = pycap_get( obj2 ) ; - - size_t fnarg_count = PyList_Size(obj3); - LLVMValueRef *fnargs - = make_array_from_list(obj3, fnarg_count); - - const LLVMBasicBlockRef then_blk = pycap_get ( obj4 ) ; - const LLVMBasicBlockRef catch_blk = pycap_get ( obj5 ) ; - - const LLVMValueRef inst - = LLVMBuildInvoke(builder, func, fnargs, fnarg_count, then_blk, - catch_blk, name); - - delete [] fnargs; - - return pycap_new(inst); - LLVMPY_CATCH_ALL -} - -_wrap_obj2obj(LLVMBuildUnreachable, LLVMBuilderRef, LLVMValueRef) - -/* Add a case to the switch instruction */ - -_wrap_objobjobj2none(LLVMAddCase, LLVMValueRef, LLVMValueRef, LLVMBasicBlockRef) - -/* Arithmetic */ - -_wrap_objobjobjstr2obj(LLVMBuildAdd, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildFAdd, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildSub, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildFSub, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildMul, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildFMul, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildUDiv, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildSDiv, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildFDiv, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildURem, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildSRem, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildFRem, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildShl, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildLShr, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildAShr, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildAnd, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildOr, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildXor, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjstr2obj(LLVMBuildNeg, LLVMBuilderRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjstr2obj(LLVMBuildNot, LLVMBuilderRef, LLVMValueRef, LLVMValueRef) - -/* Memory */ - -_wrap_objobjstr2obj(LLVMBuildMalloc, LLVMBuilderRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildArrayMalloc, LLVMBuilderRef, LLVMTypeRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjstr2obj(LLVMBuildAlloca, LLVMBuilderRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildArrayAlloca, LLVMBuilderRef, LLVMTypeRef, LLVMValueRef, LLVMValueRef) -_wrap_objobj2obj(LLVMBuildFree, LLVMBuilderRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjstr2obj(LLVMBuildLoad, LLVMBuilderRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobj2obj(LLVMBuildStore, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjliststr2obj(LLVMBuildGEP, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjliststr2obj(LLVMBuildInBoundsGEP, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) - - - -_wrap_objint2none(LLVMLdSetAlignment, LLVMValueRef) -_wrap_objint2none(LLVMStSetAlignment, LLVMValueRef) - -/* Casts */ - -_wrap_objobjobjstr2obj(LLVMBuildTrunc, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildZExt, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildSExt, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildFPToUI, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildFPToSI, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildUIToFP, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildSIToFP, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildFPTrunc, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildFPExt, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildPtrToInt, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildIntToPtr, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildBitCast, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) - -/* Comparisons */ - -_wrap_objenumobjobjstr2obj(LLVMBuildICmp, LLVMBuilderRef, LLVMIntPredicate, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objenumobjobjstr2obj(LLVMBuildFCmp, LLVMBuilderRef, LLVMRealPredicate, LLVMValueRef, LLVMValueRef, LLVMValueRef) - - -/* Atomics */ -_wrap_objobjobjobjstrint2obj(LLVMBuildAtomicCmpXchg, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objstrobjobjstrint2obj(LLVMBuildAtomicRMW, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjintstrint2obj(LLVMBuildAtomicLoad, LLVMBuilderRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjintstrint2obj(LLVMBuildAtomicStore, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objstrint2obj(LLVMBuildFence, LLVMBuilderRef, LLVMValueRef) - -/* Miscellaneous instructions */ - -_wrap_objobjintstr2obj(LLVMBuildGetResult, LLVMBuilderRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjintstr2obj(LLVMBuildInsertValue, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjstr2obj(LLVMBuildPhi, LLVMBuilderRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjliststr2obj(LLVMBuildCall, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjobjstr2obj(LLVMBuildSelect, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildVAArg, LLVMBuilderRef, LLVMValueRef, LLVMTypeRef, LLVMValueRef) -_wrap_objobjobjstr2obj(LLVMBuildExtractElement, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjobjstr2obj(LLVMBuildInsertElement, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) -_wrap_objobjobjobjstr2obj(LLVMBuildShuffleVector, LLVMBuilderRef, LLVMValueRef, LLVMValueRef, LLVMValueRef, LLVMValueRef) - - -/*===----------------------------------------------------------------------===*/ -/* Memory Buffer */ -/*===----------------------------------------------------------------------===*/ - -static PyObject * -_wLLVMCreateMemoryBufferWithContentsOfFile(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const char *path; - LLVMMemoryBufferRef ref; - PyObject *ret; - - if (!PyArg_ParseTuple(args, "s:LLVMCreateMemoryBufferWithContentsOfFile", &path)) { - return NULL; - } - - char *outmsg; - if (!LLVMCreateMemoryBufferWithContentsOfFile(path, &ref, &outmsg)) { - ret = pycap_new(ref); - } else { - ret = PyUnicode_FromString(outmsg); - LLVMDisposeMessage(outmsg); - } - - return ret; - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMCreateMemoryBufferWithSTDIN(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *ret; - LLVMMemoryBufferRef ref; - char *outmsg; - if (!LLVMCreateMemoryBufferWithSTDIN(&ref, &outmsg)) { - ret = pycap_new(ref); - } else { - ret = PyUnicode_FromString(outmsg); - LLVMDisposeMessage(outmsg); - } - - return ret; - LLVMPY_CATCH_ALL -} - -_wrap_obj2none(LLVMDisposeMemoryBuffer, LLVMMemoryBufferRef) - - -/*===----------------------------------------------------------------------===*/ -/* Pass Manager Builder */ -/*===----------------------------------------------------------------------===*/ - -_wrap_none2obj(LLVMPassManagerBuilderCreate, LLVMPassManagerBuilderRef) -_wrap_obj2none(LLVMPassManagerBuilderDispose, LLVMPassManagerBuilderRef) - -_wrap_objint2none(LLVMPassManagerBuilderSetOptLevel, LLVMPassManagerBuilderRef) -_wrap_obj2obj(LLVMPassManagerBuilderGetOptLevel, LLVMPassManagerBuilderRef, int) - -_wrap_objint2none(LLVMPassManagerBuilderSetSizeLevel, LLVMPassManagerBuilderRef) -_wrap_obj2obj(LLVMPassManagerBuilderGetSizeLevel, LLVMPassManagerBuilderRef, int) - -_wrap_objint2none(LLVMPassManagerBuilderSetVectorize, LLVMPassManagerBuilderRef) -_wrap_obj2obj(LLVMPassManagerBuilderGetVectorize, LLVMPassManagerBuilderRef, int) - -#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 2 -_wrap_objint2none(LLVMPassManagerBuilderSetLoopVectorize, LLVMPassManagerBuilderRef) -_wrap_obj2obj(LLVMPassManagerBuilderGetLoopVectorize, LLVMPassManagerBuilderRef, int) -#endif //llvm-3.2 - -_wrap_objint2none(LLVMPassManagerBuilderSetDisableUnitAtATime, - LLVMPassManagerBuilderRef) -_wrap_obj2obj(LLVMPassManagerBuilderGetDisableUnitAtATime, - LLVMPassManagerBuilderRef, int) - -_wrap_objint2none(LLVMPassManagerBuilderSetDisableUnrollLoops, - LLVMPassManagerBuilderRef) -_wrap_obj2obj(LLVMPassManagerBuilderGetDisableUnrollLoops, - LLVMPassManagerBuilderRef, int) - -_wrap_objint2none(LLVMPassManagerBuilderSetDisableSimplifyLibCalls, - LLVMPassManagerBuilderRef) -_wrap_obj2obj(LLVMPassManagerBuilderGetDisableSimplifyLibCalls, - LLVMPassManagerBuilderRef, int) - -_wrap_objint2none(LLVMPassManagerBuilderUseInlinerWithThreshold, - LLVMPassManagerBuilderRef) - - -_wrap_objobj2none(LLVMPassManagerBuilderPopulateFunctionPassManager, - LLVMPassManagerBuilderRef, - LLVMPassManagerRef) - -_wrap_objobj2none(LLVMPassManagerBuilderPopulateModulePassManager, - LLVMPassManagerBuilderRef, - LLVMPassManagerRef) - - -/*===----------------------------------------------------------------------===*/ -/* Pass Manager */ -/*===----------------------------------------------------------------------===*/ - -_wrap_none2obj(LLVMCreatePassManager, LLVMPassManagerRef) -_wrap_obj2obj(LLVMCreateFunctionPassManagerForModule, LLVMModuleRef, LLVMPassManagerRef) -_wrap_objobj2obj(LLVMRunPassManager, LLVMPassManagerRef, LLVMModuleRef, int) -_wrap_obj2obj(LLVMInitializeFunctionPassManager, LLVMPassManagerRef, int) -_wrap_objobj2obj(LLVMRunFunctionPassManager, LLVMPassManagerRef, LLVMValueRef, int) -_wrap_obj2obj(LLVMFinalizeFunctionPassManager, LLVMPassManagerRef, int) -_wrap_obj2none(LLVMDisposePassManager, LLVMPassManagerRef) -_wrap_none2str(LLVMDumpPasses) -_wrap_objstr2obj(LLVMAddPassByName, LLVMPassManagerRef, int) - - -_wrap_objobj2none(LLVMAddPass, LLVMPassManagerRef, LLVMPassRef) -_wrap_none2none(LLVMInitializePasses) - -_wrap_none2obj(LLVMInitializeNativeTarget, int) -_wrap_none2obj(LLVMInitializeNativeTargetAsmPrinter, int) -#if !defined(LLVM_DISABLE_PTX) -# if LLVM_HAS_NVPTX -_wrap_none2none(LLVMInitializeNVPTXTarget) -_wrap_none2none(LLVMInitializeNVPTXTargetInfo) -_wrap_none2none( LLVMInitializeNVPTXTargetMC ) -_wrap_none2none(LLVMInitializeNVPTXAsmPrinter) -# else -_wrap_none2none(LLVMInitializePTXTarget) -_wrap_none2none(LLVMInitializePTXTargetInfo) -_wrap_none2none( LLVMInitializePTXTargetMC ) -_wrap_none2none(LLVMInitializePTXAsmPrinter) -# endif -#endif - -/*===----------------------------------------------------------------------===*/ -/* Passes */ -/*===----------------------------------------------------------------------===*/ - -_wrap_str2obj(LLVMCreatePassByName, LLVMPassRef) -_wrap_obj2none(LLVMDisposePass, LLVMPassRef) -_wrap_obj2str(LLVMGetPassName, LLVMPassRef) -_wrap_obj2none(LLVMPassDump, LLVMPassRef) - -_wrap_str2obj(LLVMCreateTargetLibraryInfo, LLVMPassRef) - -#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 2 -_wrap_obj2obj(LLVMCreateTargetTransformInfo, LLVMTargetMachineRef, LLVMPassRef) -#endif - - -/*===----------------------------------------------------------------------===*/ -/* Target Machine */ -/*===----------------------------------------------------------------------===*/ - -_wrap_none2str(LLVMGetHostCPUName); - -_wrap_obj2obj(LLVMTargetMachineFromEngineBuilder, LLVMEngineBuilderRef, - LLVMTargetMachineRef) -_wrap_obj2none(LLVMDisposeTargetMachine, LLVMTargetMachineRef) - -static PyObject * -_wLLVMTargetMachineLookup(PyObject * self, PyObject * args) -{ - LLVMPY_TRY - const char *triple; - const char *cpu; - const char *features; - int opt, codemodel; - - if (!PyArg_ParseTuple(args, "sssii", &triple, &cpu, &features, - &opt, &codemodel)) - return NULL; - - std::string error; - LLVMTargetMachineRef tm = LLVMTargetMachineLookup(triple, cpu, features, - opt, codemodel, error); - if(!error.empty()){ - PyErr_SetString(PyExc_RuntimeError, error.c_str()); - return NULL; - } - return pycap_new(tm); - LLVMPY_CATCH_ALL -} - - -static PyObject * -_wLLVMCreateTargetMachine(PyObject * self, PyObject * args) -{ - LLVMPY_TRY - const char *triple; - const char *cpu; - const char *features; - int opt, codemodel; - - if (!PyArg_ParseTuple(args, "sssii", &triple, &cpu, &features, - &opt, &codemodel)) - return NULL; - - std::string error; - LLVMTargetMachineRef tm = LLVMCreateTargetMachine(triple, cpu, features, - opt, codemodel, error); - if(!error.empty()){ - PyErr_SetString(PyExc_RuntimeError, error.c_str()); - return NULL; - } - return pycap_new(tm); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMTargetMachineEmitFile(PyObject * self, PyObject * args) -{ - LLVMPY_TRY - PyObject *arg_tm, *arg_m; - int arg_use_asm; - - if (!PyArg_ParseTuple(args, "OOi", &arg_tm, &arg_m, &arg_use_asm)) - return NULL; - - const LLVMTargetMachineRef tm - = pycap_get( arg_tm ) ; - const LLVMModuleRef m = pycap_get( arg_m ) ; - - std::string error; - size_t len; - unsigned const char * ubytes - = LLVMTargetMachineEmitFile(tm, m, arg_use_asm, &len, error); - if ( !error.empty() ){ - PyErr_SetString(PyExc_RuntimeError, error.c_str()); - return NULL; - } - - const char *chars = reinterpret_cast(ubytes) ; - PyObject * ret = PyBytes_FromStringAndSize(chars, len); - delete [] ubytes; - return ret; - LLVMPY_CATCH_ALL -} - -_wrap_obj2obj(LLVMTargetMachineGetTargetData, LLVMTargetMachineRef, - LLVMTargetDataRef) -_wrap_obj2str(LLVMTargetMachineGetTargetName, LLVMTargetMachineRef) -_wrap_obj2str(LLVMTargetMachineGetTargetShortDescription, LLVMTargetMachineRef) -_wrap_obj2str(LLVMTargetMachineGetTriple, LLVMTargetMachineRef) -_wrap_obj2str(LLVMTargetMachineGetCPU, LLVMTargetMachineRef) -_wrap_obj2str(LLVMTargetMachineGetFS, LLVMTargetMachineRef) -_wrap_none2none(LLVMPrintRegisteredTargetsForVersion) - - -/*===----------------------------------------------------------------------===*/ -/* Target Data */ -/*===----------------------------------------------------------------------===*/ - -_wrap_str2obj(LLVMCreateTargetData, LLVMTargetDataRef) -_wrap_obj2none(LLVMDisposeTargetData, LLVMTargetDataRef) - -static PyObject * -_wLLVMTargetDataAsString(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const LLVMTargetDataRef td = get_object_arg(args); - - char *tdrep = LLVMCopyStringRepOfTargetData(td); - PyObject *ret = PyUnicode_FromString(tdrep); - LLVMDisposeMessage(tdrep); - return ret; - LLVMPY_CATCH_ALL -} - -_wrap_objobj2none(LLVMAddTargetData, LLVMTargetDataRef, LLVMPassManagerRef) -_wrap_obj2obj(LLVMByteOrder, LLVMTargetDataRef, int) -_wrap_obj2obj(LLVMPointerSize, LLVMTargetDataRef, int) -_wrap_obj2obj(LLVMIntPtrType, LLVMTargetDataRef, LLVMTypeRef) -_wrap_objobj2obj(LLVMSizeOfTypeInBits, LLVMTargetDataRef, LLVMTypeRef, - llvmwrap_ull) -_wrap_objobj2obj(LLVMStoreSizeOfType, LLVMTargetDataRef, LLVMTypeRef, - llvmwrap_ull) -_wrap_objobj2obj(LLVMABISizeOfType, LLVMTargetDataRef, LLVMTypeRef, - llvmwrap_ull) -_wrap_objobj2obj(LLVMABIAlignmentOfType, LLVMTargetDataRef, LLVMTypeRef, - int) -_wrap_objobj2obj(LLVMCallFrameAlignmentOfType, LLVMTargetDataRef, LLVMTypeRef, - int) -_wrap_objobj2obj(LLVMPreferredAlignmentOfType, LLVMTargetDataRef, LLVMTypeRef, - int) -_wrap_objobj2obj(LLVMPreferredAlignmentOfGlobal, LLVMTargetDataRef, - LLVMValueRef, int) -_wrap_objobjull2obj(LLVMElementAtOffset, LLVMTargetDataRef, LLVMTypeRef, int) -_wrap_objobjint2obj(LLVMOffsetOfElement, LLVMTargetDataRef, LLVMTypeRef, - llvmwrap_ull) - - -/*===----------------------------------------------------------------------===*/ -/* Engine Builder */ -/*===----------------------------------------------------------------------===*/ - -_wrap_obj2obj(LLVMCreateEngineBuilder, LLVMModuleRef, LLVMEngineBuilderRef) -_wrap_obj2none(LLVMDisposeEngineBuilder, LLVMEngineBuilderRef) -_wrap_obj2none(LLVMEngineBuilderForceJIT, LLVMEngineBuilderRef) -_wrap_obj2none(LLVMEngineBuilderForceInterpreter, LLVMEngineBuilderRef) -_wrap_objint2none(LLVMEngineBuilderSetOptLevel, LLVMEngineBuilderRef) -_wrap_objstr2none(LLVMEngineBuilderSetMCPU, LLVMEngineBuilderRef) -_wrap_objstr2none(LLVMEngineBuilderSetMAttrs, LLVMEngineBuilderRef) - -static PyObject * -_wLLVMEngineBuilderCreate(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const LLVMEngineBuilderRef obj - = get_object_arg(args) ; - - std::string outmsg; - const LLVMExecutionEngineRef ee = LLVMEngineBuilderCreate(obj, outmsg); - - PyObject * ret; - if( !ee ){ // check if error message is set. - ret = PyUnicode_FromString(outmsg.c_str()); - }else{ - ret = pycap_new(ee); - } - - return ret; - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMEngineBuilderCreateTM(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj, *tm; - if (!PyArg_ParseTuple(args, "OO", &obj, &tm)) - return NULL; - - const LLVMEngineBuilderRef objref = pycap_get( obj ); - const LLVMTargetMachineRef tmref = pycap_get( tm ); - std::string outmsg; - - const LLVMExecutionEngineRef ee = LLVMEngineBuilderCreateTM(objref, tmref, - outmsg); - - PyObject * ret; - if( !ee ){ // check if error message is set. - ret = PyUnicode_FromString(outmsg.c_str()); - }else{ - ret = pycap_new(ee); - } - - return ret; - LLVMPY_CATCH_ALL -} - -/*===----------------------------------------------------------------------===*/ -/* Execution Engine */ -/*===----------------------------------------------------------------------===*/ - -// Use EngineBuilder -//static PyObject * -//_wLLVMCreateExecutionEngine(PyObject *self, PyObject *args) -//{ -// LLVMPY_TRY -// PyObject *obj; -// int force_interpreter; -// char *outmsg = 0; -// int error; -// -// if (!PyArg_ParseTuple(args, "Oi", &obj, &force_interpreter)) -// return NULL; -// -// const LLVMModuleRef mod = pycap_get( obj ) ; -// -// LLVMExecutionEngineRef ee; -// if (force_interpreter) -// error = LLVMCreateInterpreterForModule(&ee, mod, &outmsg); -// else -// error = LLVMCreateJITCompilerForModule(&ee, mod, 1 /*fast*/, &outmsg); -// -// PyObject *ret; -// if (error) { -// ret = PyUnicode_FromString(outmsg); -// LLVMDisposeMessage(outmsg); -// } else { -// ret = pycap_new(ee); -// } -// -// return ret; -// LLVMPY_CATCH_ALL -//} - -static PyObject * -_wLLVMGetPointerToFunction(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj_ee; - PyObject *obj_fn; - - if (!PyArg_ParseTuple(args, "OO", &obj_ee, &obj_fn)) - return NULL; - - const LLVMExecutionEngineRef ee = pycap_get(obj_ee ) ; - const LLVMValueRef fn = pycap_get( obj_fn ) ; - - return PyLong_FromVoidPtr(LLVMGetPointerToFunction(ee,fn)); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMGetPointerToGlobal(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj_ee; - PyObject *obj_val; - - if (!PyArg_ParseTuple(args, "OO", &obj_ee, &obj_val)) - return NULL; - - const LLVMExecutionEngineRef ee = pycap_get( obj_ee ) ; - const LLVMValueRef val = pycap_get( obj_val ) ; - - return PyLong_FromVoidPtr(LLVMGetPointerToGlobal(ee, val)); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMAddGlobalMapping(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj_ee; - PyObject *obj_val; - PyObject *obj_long; - void* address; - - if (!PyArg_ParseTuple(args, "OOO", &obj_ee, &obj_val, &obj_long)) - return NULL; - - address = PyLong_AsVoidPtr(obj_long); - if (PyErr_Occurred()) return NULL; - - const LLVMExecutionEngineRef ee = pycap_get( obj_ee ); - const LLVMValueRef val = pycap_get( obj_val ); - - LLVMAddGlobalMapping(ee, val, address); - - Py_RETURN_NONE; - - LLVMPY_CATCH_ALL -} - -/* the args should have been ptr, num */ -LLVMGenericValueRef LLVMRunFunction2(LLVMExecutionEngineRef EE, - LLVMValueRef F, LLVMGenericValueRef *Args, unsigned NumArgs) -{ - return LLVMRunFunction(EE, F, NumArgs, Args); -} - -static PyObject * -_wLLVMRemoveModule2(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj_ee; - PyObject *obj_mod; - if (!PyArg_ParseTuple(args, "OO", &obj_ee, &obj_mod)) - return NULL; - - const LLVMExecutionEngineRef ee = pycap_get( obj_ee ) ; - const LLVMModuleRef mod = pycap_get(obj_mod) ; - - char *outmsg = 0; - LLVMModuleRef mod_new = 0; - LLVMRemoveModule(ee, mod, &mod_new, &outmsg); - PyObject *ret; - if (mod_new) { - ret = pycap_new(mod_new); - } else { - if (outmsg) { - ret = PyUnicode_FromString(outmsg); - LLVMDisposeMessage(outmsg); - } else { - ret = PyUnicode_FromString("error"); - } - } - - return ret; - LLVMPY_CATCH_ALL -} - -_wrap_obj2none(LLVMDisposeExecutionEngine, LLVMExecutionEngineRef) -_wrap_objint2none(LLVMExecutionEngineDisableLazyCompilation, - LLVMExecutionEngineRef) -_wrap_objobjlist2obj(LLVMRunFunction2, LLVMExecutionEngineRef, - LLVMValueRef, LLVMGenericValueRef, LLVMGenericValueRef) -_wrap_obj2obj(LLVMGetExecutionEngineTargetData, LLVMExecutionEngineRef, - LLVMTargetDataRef) -_wrap_obj2none(LLVMRunStaticConstructors, LLVMExecutionEngineRef) -_wrap_obj2none(LLVMRunStaticDestructors, LLVMExecutionEngineRef) -_wrap_objobj2none(LLVMFreeMachineCodeForFunction, LLVMExecutionEngineRef, - LLVMValueRef) -_wrap_objobj2none(LLVMAddModule, LLVMExecutionEngineRef, - LLVMModuleRef) - - -/*===----------------------------------------------------------------------===*/ -/* Generic Value */ -/*===----------------------------------------------------------------------===*/ - -static PyObject * -_wLLVMCreateGenericValueOfInt(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj1; - unsigned PY_LONG_LONG n; - int is_signed; - LLVMGenericValueRef gv; - - if (!PyArg_ParseTuple(args, "OKi", &obj1, &n, &is_signed)) - return NULL; - - const LLVMTypeRef ty = pycap_get( obj1 ) ; - - gv = LLVMCreateGenericValueOfInt(ty, n, is_signed); - return pycap_new(gv); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMCreateGenericValueOfFloat(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj1; - double d; - LLVMGenericValueRef gv; - - if (!PyArg_ParseTuple(args, "Od", &obj1, &d)) - return NULL; - - const LLVMTypeRef ty = pycap_get( obj1 ) ; - - gv = LLVMCreateGenericValueOfFloat(ty, d); - return pycap_new(gv); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMCreateGenericValueOfPointer(PyObject *self, PyObject *args) -{ - LLVMPY_TRY -// PyObject *obj1; -// LLVMTypeRef ty; //unused? - unsigned PY_LONG_LONG n_; - size_t n; - - if (!PyArg_ParseTuple(args, "K", &n_)) - return NULL; - - n=n_; - - const LLVMGenericValueRef gv = LLVMCreateGenericValueOfPointer((void*)n); - return pycap_new(gv); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMGenericValueToInt(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj1; - int is_signed; - unsigned PY_LONG_LONG val; - - if (!PyArg_ParseTuple(args, "Oi", &obj1, &is_signed)) - return NULL; - - LLVMGenericValueRef gv = pycap_get(obj1); - - val = LLVMGenericValueToInt(gv, is_signed); - return is_signed ? - PyLong_FromLongLong((PY_LONG_LONG)val) : - PyLong_FromUnsignedLongLong(val); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMGenericValueToFloat(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj1, *obj2; - - if (!PyArg_ParseTuple(args, "OO", &obj1, &obj2)) - return NULL; - - const LLVMTypeRef ty = pycap_get( obj1 ) ; - const LLVMGenericValueRef gv = pycap_get( obj2 ) ; - - double val = LLVMGenericValueToFloat(ty, gv); - return PyFloat_FromDouble(val); - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMGenericValueToPointer(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - PyObject *obj1; - - if (!PyArg_ParseTuple(args, "O", &obj1)) - return NULL; - - const LLVMGenericValueRef gv = pycap_get( obj1 ) ; - - void * val = LLVMGenericValueToPointer(gv); - return PyLong_FromVoidPtr(val); - LLVMPY_CATCH_ALL -} - -_wrap_obj2none(LLVMDisposeGenericValue, LLVMGenericValueRef) - - -/*===----------------------------------------------------------------------===*/ -/* Misc */ -/*===----------------------------------------------------------------------===*/ - -static PyObject * -_wLLVMGetVersion(PyObject *self, PyObject *args) -{ - int major = LLVM_VERSION_MAJOR; - int minor = LLVM_VERSION_MINOR; - return Py_BuildValue("(i,i)", major, minor); -} - -_wrap_objintlist2obj(LLVMGetIntrinsic, LLVMModuleRef, LLVMTypeRef, - LLVMValueRef) - -static PyObject * -_wLLVMLoadLibraryPermanently(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const char *filename; - PyObject *ret; - - if (!PyArg_ParseTuple(args, "s:LLVMLoadLibraryPermanently", &filename)) { - return NULL; - } - - char *outmsg = 0; - if (!LLVMLoadLibraryPermanently(filename, &outmsg)) { - if (outmsg) { - ret = PyUnicode_FromString(outmsg); - LLVMDisposeMessage(outmsg); - return ret; - } - } - - /* note: success => None, failure => string with error message */ - Py_RETURN_NONE; - LLVMPY_CATCH_ALL -} - -static PyObject * -_wLLVMParseEnvOpts(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - const char * progname; - const char * envname; - if(!PyArg_ParseTuple(args, "ss", &progname, &envname)) { - return NULL; - } - - llvm::cl::ParseEnvironmentOptions(progname, envname); - - Py_RETURN_NONE; - LLVMPY_CATCH_ALL -} - -_wrap_obj2obj(LLVMInlineFunction, LLVMValueRef, int) - -_wrap_none2str(LLVMDefaultTargetTriple) - - -/* Expose the void* inside a PyCObject as a PyLong. This allows us to - * use it as a unique ID. */ -static PyObject * -_wPyCObjectVoidPtrToPyLong(PyObject *self, PyObject *args) -{ - LLVMPY_TRY - void *p = get_object_arg(args); - return PyLong_FromVoidPtr(p); - LLVMPY_CATCH_ALL -} - - -/*===----------------------------------------------------------------------===*/ -/* Python member method table */ -/*===----------------------------------------------------------------------===*/ - -#define _method( func ) { # func , ( PyCFunction )_w ## func , METH_VARARGS , NULL }, -#define _pass( P ) _method( LLVMAdd ## P ## Pass ) - -static PyMethodDef core_methods[] = { - - /* Modules */ - _method( LLVMModuleCreateWithName ) - _method( LLVMGetDataLayout ) - _method( LLVMSetDataLayout ) - _method( LLVMGetModuleIdentifier ) - _method( LLVMSetModuleIdentifier ) - _method( LLVMGetTarget ) - _method( LLVMSetTarget ) - _method( LLVMModuleAddLibrary ) - _method( LLVMGetTypeByName ) - _method( LLVMDumpModule ) - _method( LLVMDisposeModule ) - _method( LLVMDumpModuleToString ) - _method( LLVMVerifyModule ) - _method( LLVMGetModuleFromAssembly ) - _method( LLVMGetModuleFromBitcode ) - _method( LLVMGetBitcodeFromModule ) - _method( LLVMGetNativeCodeFromModule ) - _method( LLVMModuleGetPointerSize ) - _method( LLVMModuleGetOrInsertFunction ) - _method( LLVMLinkModules ) - _method( LLVMModuleGetOrInsertNamedMetaData ) - _method( LLVMModuleGetNamedMetaData ) - _method( LLVMCloneModule ) - - /* Types */ - - /* General */ - _method( LLVMGetTypeKind ) - _method( LLVMDumpTypeToString ) - - /* Integer types */ - _method( LLVMInt1Type ) - _method( LLVMInt8Type ) - _method( LLVMInt16Type ) - _method( LLVMInt32Type ) - _method( LLVMInt64Type ) - _method( LLVMIntType ) - _method( LLVMGetIntTypeWidth ) - - /* Floating-point types */ - _method( LLVMFloatType ) - _method( LLVMDoubleType ) - _method( LLVMX86FP80Type ) - _method( LLVMFP128Type ) - _method( LLVMPPCFP128Type ) - - /* Function types */ - _method( LLVMFunctionType ) - _method( LLVMIsFunctionVarArg ) - _method( LLVMGetReturnType ) - _method( LLVMCountParamTypes ) - _method( LLVMGetFunctionTypeParams ) - - /* Struct types */ - _method( LLVMStructType ) - _method( LLVMStructTypeIdentified ) - _method( LLVMSetStructBody ) - _method( LLVMCountStructElementTypes ) - _method( LLVMGetStructElementTypes ) - _method( LLVMIsPackedStruct ) - _method( LLVMIsOpaqueStruct ) - _method( LLVMIsLiteralStruct ) - _method( LLVMGetStructName ) - _method( LLVMSetStructName ) - - /* Array types */ - _method( LLVMArrayType ) - _method( LLVMGetElementType ) - _method( LLVMGetArrayLength ) - - /* Pointer types */ - _method( LLVMPointerType ) - _method( LLVMGetPointerAddressSpace ) - - /* Vector type */ - _method( LLVMVectorType ) - _method( LLVMGetVectorSize ) - - /* Other types */ - _method( LLVMVoidType ) - _method( LLVMLabelType ) - - /* Type handles */ - /* - _method( LLVMResolveTypeHandle ) - _method( LLVMDisposeTypeHandle ) - */ - - /* Values */ - - /* Operations on all values */ - _method( LLVMTypeOf ) - _method( LLVMGetValueName ) - _method( LLVMSetValueName ) - _method( LLVMDumpValue ) - _method( LLVMDumpValueToString ) - _method( LLVMValueGetID ) - _method( LLVMValueGetNumUses ) - _method( LLVMValueGetUses ) - - /* Users */ - - _method( LLVMUserGetNumOperands ) - _method( LLVMUserGetOperand ) - - /* Constant Values */ - - /* Operations on constants of any type */ - _method( LLVMConstNull ) - _method( LLVMConstAllOnes ) - _method( LLVMGetUndef ) - _method( LLVMIsConstant ) - _method( LLVMIsNull ) - _method( LLVMIsUndef ) - - /* Operations on scalar constants */ - _method( LLVMConstInt ) - _method( LLVMConstReal ) - _method( LLVMConstRealOfString ) - _method( LLVMConstIntGetZExtValue ) - _method( LLVMConstIntGetSExtValue ) - - /* Operations on composite constants */ - _method( LLVMConstString ) - _method( LLVMConstArray ) - _method( LLVMConstStruct ) - _method( LLVMConstVector ) - - /* Constant expressions */ - _method( LLVMGetConstExprOpcode ) - _method( LLVMGetConstExprOpcodeName ) - _method( LLVMSizeOf ) - _method( LLVMConstNeg ) - _method( LLVMConstNot ) - _method( LLVMConstAdd ) - _method( LLVMConstFAdd ) - _method( LLVMConstSub ) - _method( LLVMConstFSub ) - _method( LLVMConstMul ) - _method( LLVMConstFMul ) - _method( LLVMConstUDiv ) - _method( LLVMConstSDiv ) - _method( LLVMConstFDiv ) - _method( LLVMConstURem ) - _method( LLVMConstSRem ) - _method( LLVMConstFRem ) - _method( LLVMConstAnd ) - _method( LLVMConstOr ) - _method( LLVMConstXor ) - _method( LLVMConstICmp ) - _method( LLVMConstFCmp ) - _method( LLVMConstShl ) - _method( LLVMConstLShr ) - _method( LLVMConstAShr ) - _method( LLVMConstGEP ) - _method( LLVMConstTrunc ) - _method( LLVMConstSExt ) - _method( LLVMConstZExt ) - _method( LLVMConstFPTrunc ) - _method( LLVMConstFPExt ) - _method( LLVMConstUIToFP ) - _method( LLVMConstSIToFP ) - _method( LLVMConstFPToUI ) - _method( LLVMConstFPToSI ) - _method( LLVMConstPtrToInt ) - _method( LLVMConstIntToPtr ) - _method( LLVMConstBitCast ) - _method( LLVMConstSelect ) - _method( LLVMConstExtractElement ) - _method( LLVMConstInsertElement ) - _method( LLVMConstShuffleVector ) - - /* Globals */ - - /* Globals (general) */ - _method( LLVMGetGlobalParent ) - _method( LLVMIsDeclaration ) - _method( LLVMGetLinkage ) - _method( LLVMSetLinkage ) - _method( LLVMGetSection ) - _method( LLVMSetSection ) - _method( LLVMGetVisibility ) - _method( LLVMSetVisibility ) - _method( LLVMGetAlignment ) - _method( LLVMSetAlignment ) - - /* Global Variables */ - _method( LLVMAddGlobal ) - _method( LLVMAddGlobalInAddressSpace ) - _method( LLVMGetNamedGlobal ) - _method( LLVMGetFirstGlobal ) - _method( LLVMGetNextGlobal ) - _method( LLVMDeleteGlobal ) - _method( LLVMHasInitializer ) - _method( LLVMGetInitializer ) - _method( LLVMSetInitializer ) - _method( LLVMSetThreadLocal ) - _method( LLVMIsThreadLocal ) - _method( LLVMSetGlobalConstant ) - _method( LLVMIsGlobalConstant ) - - /* Functions */ - _method( LLVMAddFunction ) - _method( LLVMGetNamedFunction ) - _method( LLVMGetFirstFunction ) - _method( LLVMGetNextFunction ) - _method( LLVMDeleteFunction ) - _method( LLVMGetIntrinsicID ) - _method( LLVMGetFunctionCallConv ) - _method( LLVMSetFunctionCallConv ) - _method( LLVMGetGC ) - _method( LLVMSetGC ) - _method( LLVMGetDoesNotThrow ) - _method( LLVMSetDoesNotThrow ) - _method( LLVMVerifyFunction ) - _method( LLVMViewFunctionCFG ) - _method( LLVMViewFunctionCFGOnly ) - _method( LLVMAddFunctionAttr ) - _method( LLVMRemoveFunctionAttr ) - _method( LLVMGetFunctionFromInlineAsm ) - - /* Arguments */ - _method( LLVMCountParams ) - _method( LLVMGetFirstParam ) - _method( LLVMGetNextParam ) - _method( LLVMGetParamParent ) - _method( LLVMAddAttribute ) - _method( LLVMRemoveAttribute ) - _method( LLVMSetParamAlignment ) - _method( LLVMGetParamAlignment ) - - /* Basic Blocks */ - _method( LLVMGetBasicBlockParent ) - _method( LLVMCountBasicBlocks ) - _method( LLVMGetFirstBasicBlock ) - _method( LLVMGetNextBasicBlock ) - _method( LLVMGetEntryBasicBlock ) - _method( LLVMAppendBasicBlock ) - _method( LLVMInsertBasicBlock ) - _method( LLVMDeleteBasicBlock ) - - /* MetaData */ - _method( LLVMMetaDataGet ) - _method( LLVMGetNamedMetadataOperands ) - _method( LLVMAddNamedMetadataOperand ) - _method( LLVMMetaDataGetOperand ) - _method( LLVMMetaDataGetNumOperands ) - _method( LLVMMetaDataStringGet ) - - /* NamedMetaData */ - _method( LLVMNamedMetaDataGetName ) - _method( LLVMNamedMetaDataAddOperand ) - _method( LLVMEraseNamedMetaData ) - _method( LLVMDumpNamedMDToString ) - - /* Instructions */ - _method( LLVMGetInstructionParent ) - _method( LLVMGetFirstInstruction ) - _method( LLVMGetNextInstruction ) - _method( LLVMInstIsTerminator ) - _method( LLVMInstIsBinaryOp ) - _method( LLVMInstIsShift ) - _method( LLVMInstIsCast ) - _method( LLVMInstIsLogicalShift ) - _method( LLVMInstIsArithmeticShift ) - _method( LLVMInstIsAssociative ) - _method( LLVMInstIsCommutative ) - _method( LLVMInstIsVolatile ) - _method( LLVMSetVolatile ) - _method( LLVMInstGetOpcode ) - _method( LLVMInstGetOpcodeName ) - - _method( LLVMInstSetMetaData ) - _method( LLVMInstructionEraseFromParent ) - - /* Call Sites (Call or Invoke) */ - _method( LLVMSetInstructionCallConv ) - _method( LLVMGetInstructionCallConv ) - _method( LLVMIsTailCall ) - _method( LLVMSetTailCall ) - _method( LLVMAddInstrAttribute ) - _method( LLVMRemoveInstrAttribute ) - _method( LLVMSetInstrParamAlignment ) - _method( LLVMInstGetCalledFunction ) - _method( LLVMInstSetCalledFunction ) - - /* PHI Nodes */ - _method( LLVMAddIncoming1 ) - _method( LLVMCountIncoming ) - _method( LLVMGetIncomingValue ) - _method( LLVMGetIncomingBlock ) - - /* Comparison Instructions */ - _method( LLVMCmpInstGetPredicate ) - - /* Instruction builders */ - _method( LLVMCreateBuilder ) - _method( LLVMPositionBuilderBefore ) - _method( LLVMPositionBuilderAtEnd ) - _method( LLVMGetInsertBlock ) - _method( LLVMDisposeBuilder ) - - /* Terminators */ - _method( LLVMBuildRetVoid ) - _method( LLVMBuildRet ) - _method( LLVMBuildRetMultiple ) - _method( LLVMBuildBr ) - _method( LLVMBuildCondBr ) - _method( LLVMBuildSwitch ) - _method( LLVMBuildInvoke ) - _method( LLVMBuildUnreachable ) - - /* Add a case to the switch instruction */ - _method( LLVMAddCase ) - - /* Arithmetic */ - _method( LLVMBuildAdd ) - _method( LLVMBuildFAdd) - _method( LLVMBuildSub ) - _method( LLVMBuildFSub) - _method( LLVMBuildMul ) - _method( LLVMBuildFMul) - _method( LLVMBuildUDiv ) - _method( LLVMBuildSDiv ) - _method( LLVMBuildFDiv ) - _method( LLVMBuildURem ) - _method( LLVMBuildSRem ) - _method( LLVMBuildFRem ) - _method( LLVMBuildShl ) - _method( LLVMBuildLShr ) - _method( LLVMBuildAShr ) - _method( LLVMBuildAnd ) - _method( LLVMBuildOr ) - _method( LLVMBuildXor ) - _method( LLVMBuildNeg ) - _method( LLVMBuildNot ) - - /* Memory */ - _method( LLVMBuildMalloc ) - _method( LLVMBuildArrayMalloc ) - _method( LLVMBuildAlloca ) - _method( LLVMBuildArrayAlloca ) - _method( LLVMBuildFree ) - _method( LLVMBuildLoad ) - _method( LLVMBuildStore ) - _method( LLVMBuildGEP ) - _method( LLVMBuildInBoundsGEP ) - - _method( LLVMLdSetAlignment ) - _method( LLVMStSetAlignment ) - - /* Casts */ - _method( LLVMBuildTrunc ) - _method( LLVMBuildZExt ) - _method( LLVMBuildSExt ) - _method( LLVMBuildFPToUI ) - _method( LLVMBuildFPToSI ) - _method( LLVMBuildUIToFP ) - _method( LLVMBuildSIToFP ) - _method( LLVMBuildFPTrunc ) - _method( LLVMBuildFPExt ) - _method( LLVMBuildPtrToInt ) - _method( LLVMBuildIntToPtr ) - _method( LLVMBuildBitCast ) - - /* Comparisons */ - _method( LLVMBuildICmp ) - _method( LLVMBuildFCmp ) - - /* Atomics */ - _method( LLVMBuildAtomicCmpXchg ) - _method( LLVMBuildAtomicRMW ) - _method( LLVMBuildAtomicLoad ) - _method( LLVMBuildAtomicStore ) - _method( LLVMBuildFence ) - - /* Miscellaneous instructions */ - _method( LLVMBuildGetResult ) - _method( LLVMBuildInsertValue ) - _method( LLVMBuildPhi ) - _method( LLVMBuildCall ) - _method( LLVMBuildSelect ) - _method( LLVMBuildVAArg ) - _method( LLVMBuildExtractElement ) - _method( LLVMBuildInsertElement ) - _method( LLVMBuildShuffleVector ) - - /* Memory Buffer */ - _method( LLVMCreateMemoryBufferWithContentsOfFile ) - _method( LLVMCreateMemoryBufferWithSTDIN ) - _method( LLVMDisposeMemoryBuffer ) - - /* Pass Manager Builder */ - - _method( LLVMPassManagerBuilderCreate ) - _method( LLVMPassManagerBuilderDispose ) - - _method( LLVMPassManagerBuilderSetOptLevel ) - _method( LLVMPassManagerBuilderGetOptLevel ) - - _method( LLVMPassManagerBuilderSetSizeLevel ) - _method( LLVMPassManagerBuilderGetSizeLevel ) - - _method( LLVMPassManagerBuilderSetVectorize ) - _method( LLVMPassManagerBuilderGetVectorize ) -#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 2 - _method( LLVMPassManagerBuilderSetLoopVectorize ) - _method( LLVMPassManagerBuilderGetLoopVectorize ) -#endif // llvm-3.2 - - _method( LLVMPassManagerBuilderSetDisableUnitAtATime ) - _method( LLVMPassManagerBuilderGetDisableUnitAtATime ) - - _method( LLVMPassManagerBuilderSetDisableUnrollLoops ) - _method( LLVMPassManagerBuilderGetDisableUnrollLoops ) - - _method( LLVMPassManagerBuilderSetDisableSimplifyLibCalls ) - _method( LLVMPassManagerBuilderGetDisableSimplifyLibCalls ) - - _method( LLVMPassManagerBuilderUseInlinerWithThreshold ) - - _method( LLVMPassManagerBuilderPopulateFunctionPassManager ) - _method( LLVMPassManagerBuilderPopulateModulePassManager ) - - /* Pass Manager */ - _method( LLVMCreatePassManager ) - _method( LLVMCreateFunctionPassManagerForModule ) - _method( LLVMRunPassManager ) - _method( LLVMInitializeFunctionPassManager ) - _method( LLVMRunFunctionPassManager ) - _method( LLVMFinalizeFunctionPassManager ) - _method( LLVMDisposePassManager ) - _method( LLVMDumpPasses ) - _method( LLVMAddPassByName ) - _method( LLVMAddPass ) - _method( LLVMInitializePasses ) - - _method( LLVMInitializeNativeTarget ) - _method( LLVMInitializeNativeTargetAsmPrinter ) -#if !defined(LLVM_DISABLE_PTX) -# if LLVM_HAS_NVPTX - _method( LLVMInitializeNVPTXTarget ) - _method( LLVMInitializeNVPTXTargetInfo ) - _method( LLVMInitializeNVPTXTargetMC ) - _method( LLVMInitializeNVPTXAsmPrinter ) -# else - _method( LLVMInitializePTXTarget ) - _method( LLVMInitializePTXTargetInfo ) - _method( LLVMInitializePTXTargetMC ) - _method( LLVMInitializePTXAsmPrinter ) -# endif -#endif - - /* Target Machine */ - _method( LLVMTargetMachineFromEngineBuilder ) - _method( LLVMDisposeTargetMachine ) - _method( LLVMCreateTargetMachine ) - _method( LLVMTargetMachineLookup ) - _method( LLVMTargetMachineEmitFile ) - _method( LLVMTargetMachineGetTargetData ) - _method( LLVMTargetMachineGetTargetName ) - _method( LLVMTargetMachineGetTargetShortDescription ) - _method( LLVMTargetMachineGetTriple ) - _method( LLVMTargetMachineGetCPU ) - _method( LLVMTargetMachineGetFS ) - - _method( LLVMPrintRegisteredTargetsForVersion ) - _method( LLVMGetHostCPUName ) - - /* Target Data */ - _method( LLVMCreateTargetData ) - _method( LLVMDisposeTargetData ) - _method( LLVMTargetDataAsString ) - _method( LLVMAddTargetData ) - _method( LLVMByteOrder ) - _method( LLVMPointerSize ) - _method( LLVMIntPtrType ) - _method( LLVMSizeOfTypeInBits ) - _method( LLVMStoreSizeOfType ) - _method( LLVMABISizeOfType ) - _method( LLVMABIAlignmentOfType ) - _method( LLVMCallFrameAlignmentOfType ) - _method( LLVMPreferredAlignmentOfType ) - _method( LLVMPreferredAlignmentOfGlobal ) - _method( LLVMElementAtOffset ) - _method( LLVMOffsetOfElement ) - - /* Engine Builder */ - - _method( LLVMCreateEngineBuilder ) - _method( LLVMDisposeEngineBuilder ) - _method( LLVMEngineBuilderForceJIT ) - _method( LLVMEngineBuilderForceInterpreter ) - _method( LLVMEngineBuilderSetOptLevel ) - _method( LLVMEngineBuilderSetMCPU ) - _method( LLVMEngineBuilderSetMAttrs ) - _method( LLVMEngineBuilderCreate ) - _method( LLVMEngineBuilderCreateTM ) - - /* Execution Engine */ -// Use EngineBuilder instead -// _method( LLVMCreateExecutionEngine ) - _method( LLVMDisposeExecutionEngine ) - _method( LLVMExecutionEngineDisableLazyCompilation ) - _method( LLVMRunFunction2 ) - _method( LLVMGetPointerToFunction ) - _method( LLVMGetPointerToGlobal ) - _method( LLVMAddGlobalMapping ) - _method( LLVMGetExecutionEngineTargetData ) - _method( LLVMRunStaticConstructors ) - _method( LLVMRunStaticDestructors ) - _method( LLVMFreeMachineCodeForFunction ) - _method( LLVMAddModule ) - _method( LLVMRemoveModule2 ) - - /* Generic Value */ - _method( LLVMCreateGenericValueOfInt ) - _method( LLVMCreateGenericValueOfFloat ) - _method( LLVMCreateGenericValueOfPointer ) - _method( LLVMGenericValueToInt ) - _method( LLVMGenericValueToFloat ) - _method( LLVMGenericValueToPointer ) - _method( LLVMDisposeGenericValue ) - - /* Passes */ - _method( LLVMCreatePassByName ) - _method( LLVMDisposePass ) - _method( LLVMGetPassName ) - _method( LLVMPassDump ) - - _method( LLVMCreateTargetLibraryInfo ) - -#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 2 - _method( LLVMCreateTargetTransformInfo ) -#endif - - /* Misc */ - _method( LLVMGetVersion ) - _method( LLVMGetIntrinsic ) - _method( LLVMLoadLibraryPermanently ) - _method( LLVMParseEnvOpts ) - _method( LLVMDefaultTargetTriple ) - _method( LLVMInlineFunction ) - _method( PyCObjectVoidPtrToPyLong ) - { NULL } -}; - - - -// Module main function, hairy because of py3k port -extern "C" { - -#if (PY_MAJOR_VERSION >= 3) -struct PyModuleDef module_def = { - PyModuleDef_HEAD_INIT, - "_core", - NULL, - -1, - core_methods, - NULL, NULL, NULL, NULL -}; -#define INITERROR return NULL -PyObject * -PyInit__core(void) -#else -#define INITERROR return -PyMODINIT_FUNC -init_core(void) -#endif -{ - LLVMLinkInJIT(); - LLVMLinkInInterpreter(); - LLVMInitializeNativeTarget(); -#if PY_MAJOR_VERSION >= 3 - PyObject *module = PyModule_Create( &module_def ); -#else - PyObject *module = Py_InitModule("_core", core_methods); -#endif - if (module == NULL) - INITERROR; -#if PY_MAJOR_VERSION >= 3 - - return module; -#endif -} - -} // end extern C diff --git a/llvm/_dwarf.cpp b/llvm/_dwarf.cpp deleted file mode 100644 index 43f75aa..0000000 --- a/llvm/_dwarf.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include - -namespace llvmpy { -namespace dwarf { - -using namespace llvm::dwarf; - -const char *constant_names[] = { - "LLVMDebugVersion", - - #define define(x) #x, - #include "_dwarf.h" - #undef define -}; - -int constant_values[] = { - llvm::LLVMDebugVersion, - - #define define(x) x, - #include "_dwarf.h" - #undef define -}; - -enum enum_values { - __llvmpy_LLVMDebugVersion, - - #define define(x) __llvmpy_##x, - #include "_dwarf.h" - #undef define - - NVALUES /* Get the number of constants */ -}; - -} // End namespace dwarf - -int -set_dwarf_constants(PyObject *module) -{ - int i; - for (i = 0; i < dwarf::NVALUES; i++) { - if (PyModule_AddIntConstant(module, dwarf::constant_names[i], - dwarf::constant_values[i]) > 0) - return -1; - } - - return 0; -} - -} // End namespace llvmpy - -#if (PY_MAJOR_VERSION >= 3) - struct PyModuleDef module_def = { - PyModuleDef_HEAD_INIT, - "_dwarf", - NULL, - -1, - NULL, /* m_methods */ - NULL, /* m_reload */ - NULL, /* m_traverse */ - NULL, /* m_clear */ - NULL, /* m_free */ - }; - - #define INITERROR return NULL - PyObject *PyInit__dwarf(void) -#else - #define INITERROR return - PyMODINIT_FUNC init_dwarf(void) -#endif -{ -#if PY_MAJOR_VERSION >= 3 - PyObject *module = PyModule_Create( &module_def ); -#else - PyObject *module = Py_InitModule("_dwarf", NULL); -#endif - if (module == NULL) - INITERROR; - - if (llvmpy::set_dwarf_constants(module) < 0) - INITERROR; - -#if PY_MAJOR_VERSION >= 3 - return module; -#endif -} diff --git a/llvm/_dwarf.h b/llvm/_dwarf.h deleted file mode 100644 index 78eada0..0000000 --- a/llvm/_dwarf.h +++ /dev/null @@ -1,101 +0,0 @@ -/* Dwarf constant wrapping. See include/llvm/Support/Dwarf.h */ - -define(DWARF_VERSION) - -/* Dwarf tags */ -define(DW_TAG_array_type) -define(DW_TAG_class_type) -define(DW_TAG_entry_point) -define(DW_TAG_enumeration_type) -define(DW_TAG_formal_parameter) -define(DW_TAG_imported_declaration) -define(DW_TAG_label) -define(DW_TAG_lexical_block) -define(DW_TAG_member) -define(DW_TAG_pointer_type) -define(DW_TAG_reference_type) -define(DW_TAG_compile_unit) -define(DW_TAG_string_type) -define(DW_TAG_structure_type) -define(DW_TAG_subroutine_type) -define(DW_TAG_typedef) -define(DW_TAG_union_type) -define(DW_TAG_unspecified_parameters) -define(DW_TAG_variant) -define(DW_TAG_common_block) -define(DW_TAG_common_inclusion) -define(DW_TAG_inheritance) -define(DW_TAG_inlined_subroutine) -define(DW_TAG_module) -define(DW_TAG_ptr_to_member_type) -define(DW_TAG_set_type) -define(DW_TAG_subrange_type) -define(DW_TAG_with_stmt) -define(DW_TAG_access_declaration) -define(DW_TAG_base_type) -define(DW_TAG_catch_block) -define(DW_TAG_const_type) -define(DW_TAG_constant) -define(DW_TAG_enumerator) -define(DW_TAG_file_type) -define(DW_TAG_friend) -define(DW_TAG_namelist) -define(DW_TAG_namelist_item) -define(DW_TAG_packed_type) -define(DW_TAG_subprogram) -define(DW_TAG_template_type_parameter) -define(DW_TAG_template_value_parameter) -define(DW_TAG_thrown_type) -define(DW_TAG_try_block) -define(DW_TAG_variant_part) -define(DW_TAG_variable) -define(DW_TAG_volatile_type) -define(DW_TAG_dwarf_procedure) -define(DW_TAG_restrict_type) -define(DW_TAG_interface_type) -define(DW_TAG_namespace) -define(DW_TAG_imported_module) -define(DW_TAG_unspecified_type) -define(DW_TAG_partial_unit) -define(DW_TAG_imported_unit) -define(DW_TAG_condition) -define(DW_TAG_shared_type) -define(DW_TAG_type_unit) -define(DW_TAG_rvalue_reference_type) -define(DW_TAG_template_alias) -define(DW_TAG_MIPS_loop) -define(DW_TAG_format_label) -define(DW_TAG_function_template) -define(DW_TAG_class_template) -define(DW_TAG_GNU_template_template_param) -define(DW_TAG_GNU_template_parameter_pack) -define(DW_TAG_GNU_formal_parameter_pack) -define(DW_TAG_lo_user) -define(DW_TAG_APPLE_property) -define(DW_TAG_hi_user) - -/* Dwarf language constants */ -define(DW_LANG_C89) -define(DW_LANG_C) -define(DW_LANG_Ada83) -define(DW_LANG_C_plus_plus) -define(DW_LANG_Cobol74) -define(DW_LANG_Cobol85) -define(DW_LANG_Fortran77) -define(DW_LANG_Fortran90) -define(DW_LANG_Pascal83) -define(DW_LANG_Modula2) -define(DW_LANG_Java) -define(DW_LANG_C99) -define(DW_LANG_Ada95) -define(DW_LANG_Fortran95) -define(DW_LANG_PLI) -define(DW_LANG_ObjC) -define(DW_LANG_ObjC_plus_plus) -define(DW_LANG_UPC) -define(DW_LANG_D) -define(DW_LANG_Python) -define(DW_LANG_lo_user) -define(DW_LANG_Mips_Assembler) -define(DW_LANG_hi_user) - diff --git a/llvm/_util.py b/llvm/_util.py deleted file mode 100644 index da003b0..0000000 --- a/llvm/_util.py +++ /dev/null @@ -1,108 +0,0 @@ -# -# Copyright (c) 2008-10, Mahadevan R All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# -# * Neither the name of this software, nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - -"""Utility functions and classes. - -Used only in other modules, not for public use.""" - -import llvm -import llvm._core as _core # for PyCObjectVoidPtrToPyLong - - -#===----------------------------------------------------------------------=== -# A set of helpers to check various things. Raises exceptions on -# failures. -#===----------------------------------------------------------------------=== - -def check_gen(obj, typ): - if not isinstance(obj, typ): - typ_str = typ.__name__ - msg = "argument not an instance of llvm.core.%s" % typ_str - raise TypeError(msg) - -def check_is_unowned(ownable): - if ownable.owner: - raise llvm.LLVMException("object is already owned") - - -#===----------------------------------------------------------------------=== -# A set of helpers to unpack a list of Python wrapper objects -# into a list of PyCObject wrapped objects, checking types along -# the way. -#===----------------------------------------------------------------------=== - -def unpack_gen(objlist, check_fn): - for obj in objlist: check_fn(obj) - return [ obj.ptr for obj in objlist ] - -def unpack_gen_allow_none(objlist, check_fn): - for obj in objlist: - if obj is not None: - check_fn(obj) - return [ (obj.ptr if obj is not None else None) for obj in objlist ] - -#===----------------------------------------------------------------------=== -# Helper to wrap over iterables (LLVMFirstXXX, LLVMNextXXX). This used -# to be a generator, but that loses subscriptability of the result, so -# we now return a list. -#===----------------------------------------------------------------------=== - -def wrapiter(first, next, container, wrapper): - ret = [] - ptr = first(container) - while ptr: - ret.append(wrapper(ptr)) - ptr = next(ptr) - return ret - - -#===----------------------------------------------------------------------=== -# Py2/3 compatibility string check -#===----------------------------------------------------------------------=== -def _isstring_py2(x): - return isinstance(x, basestring) - -def _isstring_py3(x): - return isinstance(x, str) - -def _isstring_choose(): - try: - basestring - return _isstring_py2 - except: - return _isstring_py3 - -isstring = _isstring_choose() - -try: - unicode_type = unicode -except NameError: # Py3 - unicode_type = str - diff --git a/llvm/_version.py b/llvm/_version.py deleted file mode 100644 index a90c5b8..0000000 --- a/llvm/_version.py +++ /dev/null @@ -1,193 +0,0 @@ - -IN_LONG_VERSION_PY = True -# This file helps to compute a version number in source trees obtained from -# git-archive tarball (such as those provided by github's download-from-tag -# feature). Distribution tarballs (build by setup.py sdist) and build -# directories (produced by setup.py build) will contain a much shorter file -# that just contains the computed version number. - -# This file is released into the public domain. Generated by -# versioneer-0.7+ (https://github.com/warner/python-versioneer) - -# these strings will be replaced by git during git-archive -git_refnames = "$Format:%d$" -git_full = "$Format:%H$" -GIT = "git" - -import subprocess -import sys - -def run_command(args, cwd=None, verbose=False): - try: - # remember shell=False, so use git.cmd on windows, not just git - p = subprocess.Popen(args, stdout=subprocess.PIPE, cwd=cwd) - except EnvironmentError: - e = sys.exc_info()[1] - if verbose: - print("unable to run %s" % args[0]) - print(e) - return None - stdout = p.communicate()[0].strip() - if sys.version >= '3': - stdout = stdout.decode() - if p.returncode != 0: - if verbose: - print("unable to run %s (error)" % args[0]) - return None - return stdout - - -import sys -import re -import os.path - -def get_expanded_variables(versionfile_source): - # the code embedded in _version.py can just fetch the value of these - # variables. When used from setup.py, we don't want to import - # _version.py, so we do it with a regexp instead. This function is not - # used from _version.py. - variables = {} - try: - for line in open(versionfile_source,"r").readlines(): - if line.strip().startswith("git_refnames ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - variables["refnames"] = mo.group(1) - if line.strip().startswith("git_full ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - variables["full"] = mo.group(1) - except EnvironmentError: - pass - return variables - -def versions_from_expanded_variables(variables, tag_prefix, verbose=False): - refnames = variables["refnames"].strip() - if refnames.startswith("$Format"): - if verbose: - print("variables are unexpanded, not using") - return {} # unexpanded, so not in an unpacked git-archive tarball - refs = set([r.strip() for r in refnames.strip("()").split(",")]) - for ref in list(refs): - if not re.search(r'\d', ref): - if verbose: - print("discarding '%s', no digits" % ref) - refs.discard(ref) - # Assume all version tags have a digit. git's %d expansion - # behaves like git log --decorate=short and strips out the - # refs/heads/ and refs/tags/ prefixes that would let us - # distinguish between branches and tags. By ignoring refnames - # without digits, we filter out many common branch names like - # "release" and "stabilization", as well as "HEAD" and "master". - if verbose: - print("remaining refs: %s" % ",".join(sorted(refs))) - for ref in sorted(refs): - # sorting will prefer e.g. "2.0" over "2.0rc1" - if ref.startswith(tag_prefix): - r = ref[len(tag_prefix):] - if verbose: - print("picking %s" % r) - return { "version": r, - "full": variables["full"].strip() } - # no suitable tags, so we use the full revision id - if verbose: - print("no suitable tags, using full revision id") - return { "version": variables["full"].strip(), - "full": variables["full"].strip() } - -def versions_from_vcs(tag_prefix, versionfile_source, verbose=False): - # this runs 'git' from the root of the source tree. That either means - # someone ran a setup.py command (and this code is in versioneer.py, so - # IN_LONG_VERSION_PY=False, thus the containing directory is the root of - # the source tree), or someone ran a project-specific entry point (and - # this code is in _version.py, so IN_LONG_VERSION_PY=True, thus the - # containing directory is somewhere deeper in the source tree). This only - # gets called if the git-archive 'subst' variables were *not* expanded, - # and _version.py hasn't already been rewritten with a short version - # string, meaning we're inside a checked out source tree. - - try: - here = os.path.abspath(__file__) - except NameError: - # some py2exe/bbfreeze/non-CPython implementations don't do __file__ - return {} # not always correct - - # versionfile_source is the relative path from the top of the source tree - # (where the .git directory might live) to this file. Invert this to find - # the root from __file__. - root = here - if IN_LONG_VERSION_PY: - for i in range(len(versionfile_source.split("/"))): - root = os.path.dirname(root) - else: - root = os.path.dirname(here) - if not os.path.exists(os.path.join(root, ".git")): - if verbose: - print("no .git in %s" % root) - return {} - - stdout = run_command([GIT, "describe", "--tags", "--dirty", "--always"], - cwd=root) - if stdout is None: - return {} - if not stdout.startswith(tag_prefix): - if verbose: - print("tag '%s' doesn't start with prefix '%s'" % (stdout, tag_prefix)) - return {} - tag = stdout[len(tag_prefix):] - stdout = run_command([GIT, "rev-parse", "HEAD"], cwd=root) - if stdout is None: - return {} - full = stdout.strip() - if tag.endswith("-dirty"): - full += "-dirty" - return {"version": tag, "full": full} - - -def versions_from_parentdir(parentdir_prefix, versionfile_source, verbose=False): - if IN_LONG_VERSION_PY: - # We're running from _version.py. If it's from a source tree - # (execute-in-place), we can work upwards to find the root of the - # tree, and then check the parent directory for a version string. If - # it's in an installed application, there's no hope. - try: - here = os.path.abspath(__file__) - except NameError: - # py2exe/bbfreeze/non-CPython don't have __file__ - return {} # without __file__, we have no hope - # versionfile_source is the relative path from the top of the source - # tree to _version.py. Invert this to find the root from __file__. - root = here - for i in range(len(versionfile_source.split("/"))): - root = os.path.dirname(root) - else: - # we're running from versioneer.py, which means we're running from - # the setup.py in a source tree. sys.argv[0] is setup.py in the root. - here = os.path.abspath(sys.argv[0]) - root = os.path.dirname(here) - - # Source tarballs conventionally unpack into a directory that includes - # both the project name and a version string. - dirname = os.path.basename(root) - if not dirname.startswith(parentdir_prefix): - if verbose: - print("guessing rootdir is '%s', but '%s' doesn't start with prefix '%s'" % - (root, dirname, parentdir_prefix)) - return None - return {"version": dirname[len(parentdir_prefix):], "full": ""} - -tag_prefix = "" -parentdir_prefix = "llvmpy-" -versionfile_source = "llvm/_version.py" - -def get_versions(default={"version": "unknown", "full": ""}, verbose=False): - variables = { "refnames": git_refnames, "full": git_full } - ver = versions_from_expanded_variables(variables, tag_prefix, verbose) - if not ver: - ver = versions_from_vcs(tag_prefix, versionfile_source, verbose) - if not ver: - ver = versions_from_parentdir(parentdir_prefix, versionfile_source, - verbose) - if not ver: - ver = default - return ver diff --git a/llvm/capsulethunk.h b/llvm/capsulethunk.h deleted file mode 100644 index 6b20564..0000000 --- a/llvm/capsulethunk.h +++ /dev/null @@ -1,134 +0,0 @@ -#ifndef __CAPSULETHUNK_H -#define __CAPSULETHUNK_H - -#if ( (PY_VERSION_HEX < 0x02070000) \ - || ((PY_VERSION_HEX >= 0x03000000) \ - && (PY_VERSION_HEX < 0x03010000)) ) - -#define __PyCapsule_GetField(capsule, field, default_value) \ - ( PyCapsule_CheckExact(capsule) \ - ? (((PyCObject *)capsule)->field) \ - : (default_value) \ - ) \ - -#define __PyCapsule_SetField(capsule, field, value) \ - ( PyCapsule_CheckExact(capsule) \ - ? (((PyCObject *)capsule)->field = value), 1 \ - : 0 \ - ) \ - - -#define PyCapsule_Type PyCObject_Type - -#define PyCapsule_CheckExact(capsule) (PyCObject_Check(capsule)) -#define PyCapsule_IsValid(capsule, name) (PyCObject_Check(capsule)) - - -#define PyCapsule_New(pointer, name, destructor) \ - (PyCObject_FromVoidPtr(pointer, destructor)) - - -#define PyCapsule_GetPointer(capsule, name) \ - (PyCObject_AsVoidPtr(capsule)) - -/* Don't call PyCObject_SetPointer here, it fails if there's a destructor */ -#define PyCapsule_SetPointer(capsule, pointer) \ - __PyCapsule_SetField(capsule, cobject, pointer) - - -#define PyCapsule_GetDestructor(capsule) \ - __PyCapsule_GetField(capsule, destructor) - -#define PyCapsule_SetDestructor(capsule, dtor) \ - __PyCapsule_SetField(capsule, destructor, dtor) - - -/* - * Sorry, there's simply no place - * to store a Capsule "name" in a CObject. - */ -#define PyCapsule_GetName(capsule) NULL - -static int -PyCapsule_SetName(PyObject *capsule, const char *unused) -{ - unused = unused; - PyErr_SetString(PyExc_NotImplementedError, - "can't use PyCapsule_SetName with CObjects"); - return 1; -} - - - -#define PyCapsule_GetContext(capsule) \ - __PyCapsule_GetField(capsule, descr) - -#define PyCapsule_SetContext(capsule, context) \ - __PyCapsule_SetField(capsule, descr, context) - - -static void * -PyCapsule_Import(const char *name, int no_block) -{ - PyObject *object = NULL; - void *return_value = NULL; - char *trace; - size_t name_length = (strlen(name) + 1) * sizeof(char); - char *name_dup = (char *)PyMem_MALLOC(name_length); - - if (!name_dup) { - return NULL; - } - - memcpy(name_dup, name, name_length); - - trace = name_dup; - while (trace) { - char *dot = strchr(trace, '.'); - if (dot) { - *dot++ = '\0'; - } - - if (object == NULL) { - if (no_block) { - object = PyImport_ImportModuleNoBlock(trace); - } else { - object = PyImport_ImportModule(trace); - if (!object) { - PyErr_Format(PyExc_ImportError, - "PyCapsule_Import could not " - "import module \"%s\"", trace); - } - } - } else { - PyObject *object2 = PyObject_GetAttrString(object, trace); - Py_DECREF(object); - object = object2; - } - if (!object) { - goto EXIT; - } - - trace = dot; - } - - if (PyCObject_Check(object)) { - PyCObject *cobject = (PyCObject *)object; - return_value = cobject->cobject; - } else { - PyErr_Format(PyExc_AttributeError, - "PyCapsule_Import \"%s\" is not valid", - name); - } - -EXIT: - Py_XDECREF(object); - if (name_dup) { - PyMem_FREE(name_dup); - } - return return_value; -} - -#endif /* #if PY_VERSION_HEX < 0x02070000 */ - -#endif /* __CAPSULETHUNK_H */ diff --git a/llvm/core.py b/llvm/core.py index fa9dc77..0bf99fd 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -1,43 +1,9 @@ -# -# Copyright (c) 2008-10, Mahadevan R All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# -# * Neither the name of this software, nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - -"""Core classes of LLVM. - -The llvm.core module contains classes and constants required to build the -in-memory intermediate representation (IR) data structures.""" - - -import llvm # top-level, for common stuff -import llvm._core as _core # C wrappers -import llvm._util as _util # utility functions +try: + from cStringIO import StringIO +except ImportError: + from StringIO import StringIO +import api #===----------------------------------------------------------------------=== # Enumerations @@ -276,72 +242,16 @@ ATTR_INLINE_HINT = 1<<25 ATTR_STACK_ALIGNMENT = 7<<26 ATTR_HOTPATCH = 1<<29 -# intrinsic IDs -from llvm._intrinsic_ids import * - - -#===----------------------------------------------------------------------=== -# Helpers (for internal use) -#===----------------------------------------------------------------------=== - -def check_is_type(obj): _util.check_gen(obj, Type) -def check_is_type_struct(obj): _util.check_gen(obj, StructType) -def check_is_value(obj): _util.check_gen(obj, Value) -def check_is_constant(obj): _util.check_gen(obj, Constant) -def check_is_function(obj): _util.check_gen(obj, Function) -def check_is_global_value(obj): _util.check_gen(obj, GlobalValue) -def check_is_basic_block(obj): _util.check_gen(obj, BasicBlock) -def check_is_module(obj): _util.check_gen(obj, Module) - -def unpack_types(objlst): return _util.unpack_gen(objlst, check_is_type) -def unpack_values(objlst): return _util.unpack_gen(objlst, check_is_value) -def unpack_constants(objlst): return _util.unpack_gen(objlst, check_is_constant) - -def unpack_values_or_none(objlst): - return _util.unpack_gen_allow_none(objlst, check_is_value) - -def check_is_callable(obj): - if isinstance(obj, Function): - return - typ = obj.type - if isinstance(typ, PointerType) and \ - isinstance(typ.pointee, FunctionType): - return - raise TypeError("argument is neither a function nor a function pointer") - -def _to_int(v): - if v: - return 1 - else: - return 0 - - -#===----------------------------------------------------------------------=== -# Module -#===----------------------------------------------------------------------=== - -class Module(llvm.Ownable, llvm.Cacheable): - """A Module instance stores all the information related to an LLVM module. - - Modules are the top level container of all other LLVM Intermediate - Representation (IR) objects. Each module directly contains a list of - globals variables, a list of functions, a list of libraries (or - other modules) this module depends on, a symbol table, and various - data about the target's characteristics. - - Construct a Module only using the static methods defined below, *NOT* - using the constructor. A correct usage is: - - module_obj = Module.new('my_module') - """ - +class Module(object): @staticmethod def new(id): """Create a new Module instance. Creates an instance of Module, having the id `id'. """ - return Module(_core.LLVMModuleCreateWithName(id)) + context = api.getGlobalContext() + m = api.Module.new(id, context) + return Module(m) @staticmethod def from_bitcode(fileobj_or_str): @@ -349,2049 +259,21 @@ class Module(llvm.Ownable, llvm.Cacheable): file. fileobj_or_str -- takes a file-like object or string that contains - a module represented in bitcode. + a module represented in bitcode. """ - - if isinstance(fileobj_or_str, _util.unicode_type): - data = fileobj_or_str.encode('utf-8') - elif isinstance(fileobj_or_str, bytes): - data = fileobj_or_str + if isinstance(fileobj_or_str, str): + bc = fileobj_or_str else: - data = fileobj_or_str.read() - ret = _core.LLVMGetModuleFromBitcode(data) - if not ret: - raise llvm.LLVMException("Unable to create module from bitcode") - elif _util.isstring(ret): - raise llvm.LLVMException(ret) - else: - return Module(ret) - - @staticmethod - def from_assembly(fileobj_or_str): - """Create a Module instance from the contents of an LLVM - assembly (.ll) file. - - - fileobj_or_str -- takes a file-like object or string that contains - a module represented in llvm-ir assembly. - """ - - if isinstance(fileobj_or_str, _util.unicode_type): - data = fileobj_or_str.encode('utf-8') - elif isinstance(fileobj_or_str, bytes): - data = fileobj_or_str - else: - data = fileobj_or_str.read() - if isinstance(data, _util.unicode_type): - data = data.encode() - 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. - - Use the static method `Module.new' instead. - """ - llvm.Ownable.__init__(self, ptr, _core.LLVMDisposeModule) - - def __str__(self): - """Text representation of a module. - - Returns the textual representation (`llvm assembly') of the - module. Use it like this: - - ll = str(module_obj) - print module_obj # same as `print ll' - """ - return _core.LLVMDumpModuleToString(self.ptr) - - def __eq__(self, rhs): - if isinstance(rhs, Module): - return str(self) == str(rhs) - else: - return False - - def __ne__(self, rhs): - return not self == rhs - - def _get_target(self): - return _core.LLVMGetTarget(self.ptr) - - def _set_target(self, value): - return _core.LLVMSetTarget(self.ptr, value) - - target = property(_get_target, _set_target, - """The target triple string describing the target host.""" - ) - - def _get_data_layout(self): - return _core.LLVMGetDataLayout(self.ptr) - - def _set_data_layout(self, value): - _core.LLVMSetDataLayout(self.ptr, value) - - data_layout = property(_get_data_layout, _set_data_layout, - """The data layout string for the module's target platform. - - The data layout strings is an encoded representation of - the type sizes and alignments expected by this module. - """ - ) - - @property - def pointer_size(self): - """Pointer size of target platform. - - Can be 0, 32 or 64. Zero represents - llvm::Module::AnyPointerSize.""" - return _core.LLVMModuleGetPointerSize(self.ptr) - - def link_in(self, other, preserve=False): - """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, all refs to it should be dropped. - - In the future, this API might be replaced with a full-fledged - Linker class. - """ - check_is_module(other) - if not preserve: - other.forget() # remove it from object cache - result = _core.LLVMLinkModules(self.ptr, other.ptr, int(bool(preserve))) - if result is not None: - raise llvm.LLVMException(result) - if not preserve: - # Prevent user from using the other module - other.ptr = None - # Use a dummy owner to prevent other.ptr to be deleted - other._own(llvm.DummyOwner()) - - def get_type_named(self, name): - """Return a Type object with the given name.""" - ptr = _core.LLVMGetTypeByName(self.ptr, name) - if ptr: - kind = _core.LLVMGetTypeKind(ptr) - return _make_type(ptr, kind) - return None - - def add_global_variable(self, ty, name, addrspace=0): - """Add a global variable of given type with given name.""" - return GlobalVariable.new(self, ty, name, addrspace) - - def get_global_variable_named(self, name): - """Return a GlobalVariable object for the given name.""" - return GlobalVariable.get(self, name) - - @property - def global_variables(self): - """All global variables in this module.""" - return _util.wrapiter(_core.LLVMGetFirstGlobal, - _core.LLVMGetNextGlobal, self.ptr, _make_value) - - def add_function(self, ty, name): - """Add a function of given type with given name.""" - return Function.new(self, ty, name) - - def get_function_named(self, name): - """Return a Function object representing function with given name.""" - return Function.get(self, name) - - def get_or_insert_function(self, ty, name): - """Like get_function_named(), but does add_function() first, if - function is not present.""" - return Function.get_or_insert(self, ty, name) - - @property - def functions(self): - """All functions in this module.""" - return _util.wrapiter(_core.LLVMGetFirstFunction, - _core.LLVMGetNextFunction, self.ptr, _make_value) - - def verify(self): - """Verify module. - - Checks module for errors. Raises `llvm.LLVMException' on any - error.""" - ret = _core.LLVMVerifyModule(self.ptr) - # Note: LLVM has a bug in preverifier that will always abort - # the process upon failure. - if ret != "": - raise llvm.LLVMException(ret) - - def to_bitcode(self, fileobj=None): - """Write bitcode representation of module to given file-like - object. - - fileobj -- A file-like object to where the bitcode is written. - If it is None, the bitcode is returned. - - Return value -- Returns None if fileobj is not None. - Otherwise, return the bitcode as a bytestring. - """ - - data = _core.LLVMGetBitcodeFromModule(self.ptr) - if not data: - raise llvm.LLVMException("Unable to create bitcode") - if fileobj is not None: - fileobj.write(data) - else: - return data - - def add_library(self, name): - return _core.LLVMModuleAddLibrary(self.ptr, name) - - def _get_id(self): - return _core.LLVMGetModuleIdentifier(self.ptr) - - def _set_id(self, string): - _core.LLVMSetModuleIdentifier(self.ptr, string) - - id = property(_get_id, _set_id) - - def to_native_object(self, fileobj=None): - '''Outputs the byte string of the module as native object code - - If a fileobj is given, the output is written to it; - Otherwise, the output is returned - ''' - data = _core.LLVMGetNativeCodeFromModule(self.ptr, 0) - if fileobj is not None: - fileobj.write(data) - else: - return data - - def to_native_assembly(self, fileobj=None): - '''Outputs the byte string of the module as native assembly code - - If a fileobj is given, the output is written to it; - Otherwise, the output is returned - ''' - data = _core.LLVMGetNativeCodeFromModule(self.ptr, 1) - if fileobj is not None: - fileobj.write(data) - else: - return data - - def get_or_insert_named_metadata(self, name): - ptr = _core.LLVMModuleGetOrInsertNamedMetaData(self.ptr, name) - return NamedMetaData(ptr) - - def get_named_metadata(self, name): - ptr = _core.LLVMModuleGetNamedMetaData(self.ptr, name) - return NamedMetaData(ptr) - - def clone(self): - return Module(_core.LLVMCloneModule(self.ptr)) - -#===----------------------------------------------------------------------=== -# Types -#===----------------------------------------------------------------------=== - -class Type(object): - """Represents a type, like a 32-bit integer or an 80-bit x86 float. - - Use one of the static methods to create an instance. Example: - ty = Type.double() - """ - - @staticmethod - def int(bits=32): - """Create an integer type having the given bit width.""" - if bits == 1: - return _make_type(_core.LLVMInt1Type(), TYPE_INTEGER) - elif bits == 8: - return _make_type(_core.LLVMInt8Type(), TYPE_INTEGER) - elif bits == 16: - return _make_type(_core.LLVMInt16Type(), TYPE_INTEGER) - elif bits == 32: - return _make_type(_core.LLVMInt32Type(), TYPE_INTEGER) - elif bits == 64: - return _make_type(_core.LLVMInt64Type(), TYPE_INTEGER) - else: - bits = int(bits) # bits must be an int - return _make_type(_core.LLVMIntType(bits), TYPE_INTEGER) - - @staticmethod - def float(): - """Create a 32-bit floating point type.""" - return _make_type(_core.LLVMFloatType(), TYPE_FLOAT) - - @staticmethod - def double(): - """Create a 64-bit floating point type.""" - return _make_type(_core.LLVMDoubleType(), TYPE_DOUBLE) - - @staticmethod - def x86_fp80(): - """Create a 80-bit x86 floating point type.""" - return _make_type(_core.LLVMX86FP80Type(), TYPE_X86_FP80) - - @staticmethod - def fp128(): - """Create a 128-bit floating point type (with 112-bit - mantissa).""" - return _make_type(_core.LLVMFP128Type(), TYPE_FP128) - - @staticmethod - def ppc_fp128(): - """Create a 128-bit floating point type (two 64-bits).""" - return _make_type(_core.LLVMPPCFP128Type(), TYPE_PPC_FP128) - - @staticmethod - def function(return_ty, param_tys, var_arg=False): - """Create a function type. - - Creates a function type that returns a value of type - `return_ty', takes arguments of types as given in the iterable - `param_tys'. Set `var_arg' to True (default is False) for a - variadic function.""" - check_is_type(return_ty) - var_arg = _to_int(var_arg) # ensure int - params = unpack_types(param_tys) - return _make_type(_core.LLVMFunctionType(return_ty.ptr, params, - var_arg), TYPE_FUNCTION) - - @staticmethod - def opaque(name): - """Create a opaque StructType""" - if not name: - raise llvm.LLVMException("Must specify a name") - - objptr = _core.LLVMStructTypeIdentified(name) - return _make_type(objptr, TYPE_STRUCT) - - @staticmethod - def struct(element_tys, name=''): # not packed - """Create a (unpacked) structure type. - - Creates a structure type with elements of types as given in the - iterable `element_tys'. This method creates a unpacked - structure. For a packed one, use the packed_struct() method. - - If name is not '', creates a identified type; - otherwise, creates a literal type.""" - return Type.__struct(element_tys, packed=False, name=name) - - @staticmethod - def packed_struct(element_tys, name=''): - """Create a (packed) structure type. - - Creates a structure type with elements of types as given in the - iterable `element_tys'. This method creates a packed - structure. For an unpacked one, use the struct() method. - - If name is not '', creates a identified type; - otherwise, creates a literal type.""" - return Type.__struct(element_tys, packed=True, name=name) - - @staticmethod - def __struct(element_tys, packed, name): - elems = unpack_types(element_tys) - packed = int(bool(packed)) - - if name: # create Identified StructType - objptr = _core.LLVMStructTypeIdentified(name) - _core.LLVMSetStructBody(objptr, elems, packed) - else: # create Literal StructType - objptr = _core.LLVMStructType(elems, packed) - - return _make_type(objptr, TYPE_STRUCT) - - - @staticmethod - def array(element_ty, count): - """Create an array type. - - Creates a type for an array of elements of type `element_ty', - having 'count' elements.""" - check_is_type(element_ty) - count = int(count) # must be an int - return _make_type(_core.LLVMArrayType(element_ty.ptr, count), - TYPE_ARRAY) - - @staticmethod - def pointer(pointee_ty, addr_space=0): - """Create a pointer type. - - Creates a pointer type, which can point to values of type - `pointee_ty', in the address space `addr_space'.""" - check_is_type(pointee_ty) - addr_space = int(addr_space) # must be an int - return _make_type(_core.LLVMPointerType(pointee_ty.ptr, - addr_space), TYPE_POINTER) - - @staticmethod - def vector(element_ty, count): - """Create a vector type. - - Creates a type for a vector of elements of type `element_ty', - having `count' elements.""" - check_is_type(element_ty) - count = int(count) # must be an int - return _make_type(_core.LLVMVectorType(element_ty.ptr, count), - TYPE_VECTOR) - - @staticmethod - def void(): - """Create a void type. - - Represents the `void' type.""" - return _make_type(_core.LLVMVoidType(), TYPE_VOID) - - @staticmethod - def label(): - """Create a label type.""" - return _make_type(_core.LLVMLabelType(), TYPE_LABEL) - - def __init__(self, ptr, kind): - """DO NOT CALL DIRECTLY. - - Use one of the static methods instead.""" - self.ptr = ptr - self.kind = kind - """An enum (int) value denoting which type this is. - - Use the symbolic constants TYPE_* defined in llvm.core - module.""" - - def __str__(self): - """Text representation of a type. - - Returns the textual representation (`llvm assembly') of the type.""" - return _core.LLVMDumpTypeToString(self.ptr) - - def __eq__(self, rhs): - if isinstance(rhs, Type): - return str(self) == str(rhs) - else: - return False - - def __ne__(self, rhs): - return not self == rhs - - -class IntegerType(Type): - """Represents an integer type.""" - - @property - def width(self): - """The width of the integer type, in bits.""" - return _core.LLVMGetIntTypeWidth(self.ptr) - - -class FunctionType(Type): - """Represents a function type.""" - - @property - def return_type(self): - """The type of the value returned by this function.""" - ptr = _core.LLVMGetReturnType(self.ptr) - kind = _core.LLVMGetTypeKind(ptr) - return _make_type(ptr, kind) - - @property - def vararg(self): - """True if this function is variadic.""" - return _core.LLVMIsFunctionVarArg(self.ptr) != 0 - - @property - def args(self): - """An iterable that yields Type objects, representing the types of the - arguments accepted by this function, in order.""" - pp = _core.LLVMGetFunctionTypeParams(self.ptr) - return [ _make_type(p, _core.LLVMGetTypeKind(p)) for p in pp ] - - @property - def arg_count(self): - """Number of arguments accepted by this function. - - Same as len(obj.args), but faster.""" - return _core.LLVMCountParamTypes(self.ptr) - - -class StructType(Type): - """Represents a structure type.""" - - @property - def element_count(self): - """Number of elements (members) in the structure. - - Same as len(obj.elements), but faster.""" - return _core.LLVMCountStructElementTypes(self.ptr) - - @property - def elements(self): - """An iterable that yieldsd Type objects, representing the types of the - elements (members) of the structure, in order.""" - pp = _core.LLVMGetStructElementTypes(self.ptr) - return [ _make_type(p, _core.LLVMGetTypeKind(p)) for p in pp ] - - def set_body(self, elems, packed=False): - """Filled the body of a opaque type. - """ - # check - if not self.is_opaque: - raise llvm.LLVMException("Body is already defined.") - - # prepare arguments - elems = unpack_types(elems) - if packed: - packed = 1 - else: - packed = 0 - - # call c API - _core.LLVMSetStructBody(self.ptr, elems, packed) - - @property - def packed(self): - """True if the structure is packed, False otherwise.""" - return _core.LLVMIsPackedStruct(self.ptr) != 0 - - def _set_name(self, name): - _core.LLVMSetStructName(self.ptr, name) - - def _get_name(self): - return _core.LLVMGetStructName(self.ptr) - - name = property(_get_name, _set_name) - - @property - def is_literal(self): - return bool(_core.LLVMIsLiteralStruct(self.ptr)) - - @property - def is_identified(self): - return not _core.LLVMIsLiteralStruct(self.ptr) - - @property - def is_opaque(self): - return bool(_core.LLVMIsOpaqueStruct(self.ptr)) - -class ArrayType(Type): - """Represents an array type.""" - - @property - def element(self): - ptr = _core.LLVMGetElementType(self.ptr) - kind = _core.LLVMGetTypeKind(ptr) - return _make_type(ptr, kind) - - @property - def count(self): - return _core.LLVMGetArrayLength(self.ptr) - - -class PointerType(Type): - - @property - def pointee(self): - ptr = _core.LLVMGetElementType(self.ptr) - kind = _core.LLVMGetTypeKind(ptr) - return _make_type(ptr, kind) - - @property - def address_space(self): - return _core.LLVMGetPointerAddressSpace(self.ptr) - - -class VectorType(Type): - - @property - def element(self): - ptr = _core.LLVMGetElementType(self.ptr) - kind = _core.LLVMGetTypeKind(ptr) - return _make_type(ptr, kind) - - @property - def count(self): - return _core.LLVMGetVectorSize(self.ptr) - - -#===----------------------------------------------------------------------=== -# Type factory method -#===----------------------------------------------------------------------=== - -# type ID -> class map -__class_for_typeid = { - TYPE_INTEGER : IntegerType, - TYPE_FUNCTION : FunctionType, - TYPE_STRUCT : StructType, - TYPE_ARRAY : ArrayType, - TYPE_POINTER : PointerType, - TYPE_VECTOR : VectorType, -} - -def _make_type(ptr, kind): - class_obj = __class_for_typeid.get(kind) - if class_obj: - return class_obj(ptr, kind) - else: - # "generic" type - return Type(ptr, kind) - - -#===----------------------------------------------------------------------=== -# Values -#===----------------------------------------------------------------------=== - -class Value(llvm.Cacheable): + bc = fileobj_or_str.read() + errbuf = StringIO() + m = api.ParseBitCodeFile(bc, context, errbuf) + if not m: + raise Exception(errbuf.getvalue()) + errbuf.close() + return Module(m) def __init__(self, ptr): self.ptr = ptr - def __str__(self): - return _core.LLVMDumpValueToString(self.ptr) - - def __eq__(self, rhs): - if isinstance(rhs, Value): - return str(self) == str(rhs) - else: - return False - - def __ne__(self, rhs): - return not self == rhs - - def _get_name(self): - return _core.LLVMGetValueName(self.ptr) - - def _set_name(self, value): - return _core.LLVMSetValueName(self.ptr, value) - - name = property(_get_name, _set_name) - - @property - def value_id(self): - return _core.LLVMValueGetID(self.ptr) - - @property - def type(self): - ptr = _core.LLVMTypeOf(self.ptr) - kind = _core.LLVMGetTypeKind(ptr) - return _make_type(ptr, kind) - - @property - def use_count(self): - return _core.LLVMValueGetNumUses(self.ptr) - - @property - def uses(self): - return [ _make_value(v) for v in _core.LLVMValueGetUses(self.ptr) ] - - -class User(Value): - - @property - def operand_count(self): - return _core.LLVMUserGetNumOperands(self.ptr) - - @property - def operands(self): - """Yields operands of this instruction.""" - return [self._get_operand(i) for i in range(self.operand_count)] - - def _get_operand(self, i): - return _make_value(_core.LLVMUserGetOperand(self.ptr, i)) - - -class Constant(User): - - @staticmethod - def null(ty): - check_is_type(ty) - return _make_value(_core.LLVMConstNull(ty.ptr)) - - @staticmethod - def all_ones(ty): - check_is_type(ty) - return _make_value(_core.LLVMConstAllOnes(ty.ptr)) - - @staticmethod - def undef(ty): - check_is_type(ty) - return _make_value(_core.LLVMGetUndef(ty.ptr)) - - @staticmethod - def int(ty, value): - check_is_type(ty) - return _make_value(_core.LLVMConstInt(ty.ptr, value, 0)) - - @staticmethod - def int_signextend(ty, value): - check_is_type(ty) - return _make_value(_core.LLVMConstInt(ty.ptr, value, 1)) - - @staticmethod - def real(ty, value): - check_is_type(ty) - if isinstance(value, str): - return _make_value(_core.LLVMConstRealOfString(ty.ptr, value)) - else: - return _make_value(_core.LLVMConstReal(ty.ptr, value)) - - @staticmethod - def string(strval): # dont_null_terminate=True - return _make_value(_core.LLVMConstString(strval, 1)) - - @staticmethod - def stringz(strval): # dont_null_terminate=False - return _make_value(_core.LLVMConstString(strval, 0)) - - @staticmethod - def array(ty, consts): - check_is_type(ty) - const_ptrs = unpack_constants(consts) - return _make_value(_core.LLVMConstArray(ty.ptr, const_ptrs)) - - @staticmethod - def struct(consts): # not packed - const_ptrs = unpack_constants(consts) - return _make_value(_core.LLVMConstStruct(const_ptrs, 0)) - - @staticmethod - def packed_struct(consts): - const_ptrs = unpack_constants(consts) - return _make_value(_core.LLVMConstStruct(const_ptrs, 1)) - - @staticmethod - def vector(consts): - const_ptrs = unpack_constants(consts) - return _make_value(_core.LLVMConstVector(const_ptrs)) - - @staticmethod - def sizeof(ty): - check_is_type(ty) - return _make_value(_core.LLVMSizeOf(ty.ptr)) - - def neg(self): - return _make_value(_core.LLVMConstNeg(self.ptr)) - - def not_(self): - return _make_value(_core.LLVMConstNot(self.ptr)) - - def add(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstAdd(self.ptr, rhs.ptr)) - - def fadd(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstFAdd(self.ptr, rhs.ptr)) - - def sub(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstSub(self.ptr, rhs.ptr)) - - def fsub(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstFSub(self.ptr, rhs.ptr)) - - def mul(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstMul(self.ptr, rhs.ptr)) - - def fmul(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstFMul(self.ptr, rhs.ptr)) - - def udiv(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstUDiv(self.ptr, rhs.ptr)) - - def sdiv(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstSDiv(self.ptr, rhs.ptr)) - - def fdiv(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstFDiv(self.ptr, rhs.ptr)) - - def urem(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstURem(self.ptr, rhs.ptr)) - - def srem(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstSRem(self.ptr, rhs.ptr)) - - def frem(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstFRem(self.ptr, rhs.ptr)) - - def and_(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstAnd(self.ptr, rhs.ptr)) - - def or_(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstOr(self.ptr, rhs.ptr)) - - def xor(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstXor(self.ptr, rhs.ptr)) - - def icmp(self, int_pred, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstICmp(int_pred, self.ptr, rhs.ptr)) - - def fcmp(self, real_pred, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstFCmp(real_pred, self.ptr, rhs.ptr)) - - def shl(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstShl(self.ptr, rhs.ptr)) - - def lshr(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstLShr(self.ptr, rhs.ptr)) - - def ashr(self, rhs): - check_is_constant(rhs) - return _make_value(_core.LLVMConstAShr(self.ptr, rhs.ptr)) - - def gep(self, indices): - index_ptrs = unpack_constants(indices) - return _make_value(_core.LLVMConstGEP(self.ptr, index_ptrs)) - - def trunc(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstTrunc(self.ptr, ty.ptr)) - - def sext(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstSExt(self.ptr, ty.ptr)) - - def zext(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstZExt(self.ptr, ty.ptr)) - - def fptrunc(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstFPTrunc(self.ptr, ty.ptr)) - - def fpext(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstFPExt(self.ptr, ty.ptr)) - - def uitofp(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstUIToFP(self.ptr, ty.ptr)) - - def sitofp(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstSIToFP(self.ptr, ty.ptr)) - - def fptoui(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstFPToUI(self.ptr, ty.ptr)) - - def fptosi(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstFPToSI(self.ptr, ty.ptr)) - - def ptrtoint(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstPtrToInt(self.ptr, ty.ptr)) - - def inttoptr(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstIntToPtr(self.ptr, ty.ptr)) - - def bitcast(self, ty): - check_is_type(ty) - return _make_value(_core.LLVMConstBitCast(self.ptr, ty.ptr)) - - def select(self, true_const, false_const): - check_is_constant(true_const) - check_is_constant(false_const) - return _make_value( - _core.LLVMConstSelect(self.ptr, true_const.ptr, false_const.ptr)) - - def extract_element(self, index): # note: self must be a _vector_ constant - check_is_constant(index) - return _make_value( - _core.LLVMConstExtractElement(self.ptr, index.ptr)) - - def insert_element(self, value, index): - # note: self must be a _vector_ constant - check_is_constant(value) - check_is_constant(index) - return _make_value( - _core.LLVMConstInsertElement(self.ptr, value.ptr, index.ptr)) - - def shuffle_vector(self, vector_b, mask): - # note: self must be a _vector_ constant - check_is_constant(vector_b) - # note: vector_b must be a _vector_ constant - check_is_constant(mask) - return _make_value( - _core.LLVMConstShuffleVector(self.ptr, vector_b.ptr, mask.ptr)) - - -class ConstantExpr(Constant): - @property - def opcode(self): - return _core.LLVMGetConstExprOpcode(self.ptr) - - @property - def opcode_name(self): - return _core.LLVMGetConstExprOpcodeName(self.ptr) - - -class ConstantAggregateZero(Constant): - pass - - -class ConstantDataArray(Constant): - pass - - -class ConstantDataVector(Constant): - pass - -class ConstantInt(Constant): - @property - def z_ext_value(self): - '''Obtain the zero extended value for an integer constant value.''' - # Warning: assertion failure when value does not fit in 64 bits - return _core.LLVMConstIntGetZExtValue(self.ptr) - - @property - def s_ext_value(self): - '''Obtain the sign extended value for an integer constant value.''' - # Warning: assertion failure when value does not fit in 64 bits - return _core.LLVMConstIntGetSExtValue(self.ptr) - - -class ConstantFP(Constant): - pass - - -class ConstantArray(Constant): - pass - - -class ConstantStruct(Constant): - pass - - -class ConstantVector(Constant): - pass - - -class ConstantPointerNull(Constant): - pass - - -class UndefValue(Constant): - pass - - -class GlobalValue(Constant): - - def __init__(self, ptr): - Constant.__init__(self, ptr) - # Hang on to the module, don't let it die before we do. - # It is nice to have just a map of functions without - # retaining a ref to the owning module. - self._module_obj = self.module - - def _delete(self): - # Called in subclass delete() methods. - self._module_obj = None - - def _get_linkage(self): - return _core.LLVMGetLinkage(self.ptr) - def _set_linkage(self, value): - _core.LLVMSetLinkage(self.ptr, value) - linkage = property(_get_linkage, _set_linkage) - - def _get_section(self): - return _core.LLVMGetSection(self.ptr) - def _set_section(self, value): - return _core.LLVMSetSection(self.ptr, value) - section = property(_get_section, _set_section) - - def _get_visibility(self): - return _core.LLVMGetVisibility(self.ptr) - def _set_visibility(self, value): - return _core.LLVMSetVisibility(self.ptr, value) - visibility = property(_get_visibility, _set_visibility) - - def _get_alignment(self): - return _core.LLVMGetAlignment(self.ptr) - def _set_alignment(self, value): - return _core.LLVMSetAlignment(self.ptr, value) - alignment = property(_get_alignment, _set_alignment) - - @property - def is_declaration(self): - return _core.LLVMIsDeclaration(self.ptr) != 0 - - @property - def module(self): - return Module(_core.LLVMGetGlobalParent(self.ptr)) - -class GlobalVariable(GlobalValue): - - @staticmethod - def new(module, ty, name, addrspace=0): - check_is_module(module) - check_is_type(ty) - return _make_value(_core.LLVMAddGlobalInAddressSpace(module.ptr, ty.ptr, name, addrspace)) - - @staticmethod - def get(module, name): - check_is_module(module) - ptr = _core.LLVMGetNamedGlobal(module.ptr, name) - if not ptr: - raise llvm.LLVMException("no global named `%s`" % name) - return _make_value(ptr) - - def delete(self): - self._delete() - _core.LLVMDeleteGlobal(self.ptr) - self.forget() - self.ptr = None - - def _get_initializer(self): - if _core.LLVMHasInitializer(self.ptr): - return _make_value(_core.LLVMGetInitializer(self.ptr)) - else: - return None - - def _set_initializer(self, const): - check_is_constant(const) - _core.LLVMSetInitializer(self.ptr, const.ptr) - - def _del_initializer(self): - check_is_constant(const) - - initializer = property(_get_initializer, _set_initializer) - - def _get_is_global_constant(self): - return _core.LLVMIsGlobalConstant(self.ptr) - - def _set_is_global_constant(self, value): - value = _to_int(value) - _core.LLVMSetGlobalConstant(self.ptr, value) - - global_constant = \ - property(_get_is_global_constant, _set_is_global_constant) - - def _get_thread_local(self): - return bool(_core.LLVMIsThreadLocal(self.ptr)) - def _set_thread_local(self, value): - value = _to_int(value) - _core.LLVMSetThreadLocal(self.ptr, value) - - thread_local = property(_get_thread_local, _set_thread_local) - -class Argument(Value): - - def add_attribute(self, attr): - _core.LLVMAddAttribute(self.ptr, attr) - - def remove_attribute(self, attr): - _core.LLVMRemoveAttribute(self.ptr, attr) - - def _set_alignment(self, align): - _core.LLVMSetParamAlignment(self.ptr, align) - - def _get_alignment(self): - return _core.LLVMGetParamAlignment(self.ptr) - - alignment = \ - property(_get_alignment, _set_alignment) - - -class Function(GlobalValue): - - @staticmethod - def new(module, func_ty, name): - check_is_module(module) - check_is_type(func_ty) - return _make_value(_core.LLVMAddFunction(module.ptr, name, - func_ty.ptr)) - - @staticmethod - def get_or_insert(module, func_ty, name): - check_is_module(module) - check_is_type(func_ty) - return _make_value(_core.LLVMModuleGetOrInsertFunction(module.ptr, - name, func_ty.ptr)) - - @staticmethod - def get(module, name): - check_is_module(module) - ptr = _core.LLVMGetNamedFunction(module.ptr, name) - if not ptr: - raise llvm.LLVMException("no function named `%s`" % name) - return _make_value(ptr) - - @staticmethod - def intrinsic(module, intrinsic_id, types): - check_is_module(module) - ptrs = unpack_types(types) - return _make_value( - _core.LLVMGetIntrinsic(module.ptr, intrinsic_id, ptrs)) - - def delete(self): - self._delete() - _core.LLVMDeleteFunction(self.ptr) - self.forget() - self.ptr = None - - @property - def intrinsic_id(self): - return _core.LLVMGetIntrinsicID(self.ptr) - - def _get_cc(self): return _core.LLVMGetFunctionCallConv(self.ptr) - def _set_cc(self, value): _core.LLVMSetFunctionCallConv(self.ptr, value) - calling_convention = property(_get_cc, _set_cc) - - def _get_coll(self): return _core.LLVMGetGC(self.ptr) - def _set_coll(self, value): _core.LLVMSetGC(self.ptr, value) - collector = property(_get_coll, _set_coll) - - # the nounwind attribute: - def _get_does_not_throw(self): return _core.LLVMGetDoesNotThrow(self.ptr) - def _set_does_not_throw(self,value): _core.LLVMSetDoesNotThrow(self.ptr, value) - does_not_throw = property(_get_does_not_throw, _set_does_not_throw) - - @property - def args(self): - return _util.wrapiter(_core.LLVMGetFirstParam, - _core.LLVMGetNextParam, self.ptr, _make_value) - - @property - def basic_block_count(self): - return _core.LLVMCountBasicBlocks(self.ptr) - - @property - def entry_basic_block(self): - if self.basic_block_count == 0: - return None - return _make_value(_core.LLVMGetEntryBasicBlock(self.ptr)) - - def get_entry_basic_block(self): - """Deprecated, use entry_basic_block property.""" - return self.entry_basic_block - - def append_basic_block(self, name): - return _make_value(_core.LLVMAppendBasicBlock(self.ptr, name)) - - @property - def basic_blocks(self): - return _util.wrapiter(_core.LLVMGetFirstBasicBlock, - _core.LLVMGetNextBasicBlock, self.ptr, _make_value) - - def viewCFG(self): - return _core.LLVMViewFunctionCFG(self.ptr) - - def add_attribute(self, attr): - _core.LLVMAddFunctionAttr(self.ptr, attr) - - def remove_attribute(self, attr): - _core.LLVMRemoveFunctionAttr(self.ptr, attr) - - def viewCFGOnly(self): - return _core.LLVMViewFunctionCFGOnly(self.ptr) - - def verify(self): - # Although we're just asking LLVM to return the success or - # failure, it appears to print result to stderr and abort. - - # Note: LLVM has a bug in preverifier that will always abort - # the process upon failure. - return _core.LLVMVerifyFunction(self.ptr) != 0 - -#===----------------------------------------------------------------------=== -# InlineAsm -#===----------------------------------------------------------------------=== - -class InlineAsm(Value): - @staticmethod - def get(functype, asm, constrains, side_effect=False, - align_stack=False, dialect=0): - assert dialect == 0, "LLVM 3.1 does not implement dialect selection" - check_is_type(functype) - pycap = _core.LLVMGetFunctionFromInlineAsm(functype.ptr, asm, - constrains, int(side_effect), - int(align_stack), dialect) - return _make_value(pycap) - -#===----------------------------------------------------------------------=== -# MetaData -#===----------------------------------------------------------------------=== - -class MetaData(Value): - @staticmethod - def get(module, values): - ''' - values -- must be an iterable of Constant or None. None is treated as "null". - ''' - vs = unpack_values_or_none(values) - ptr = _core.LLVMMetaDataGet(module.ptr, vs) - return MetaData(ptr) - - @staticmethod - def get_named_operands(module, name): - lst = _core.LLVMGetNamedMetadataOperands(module.ptr, name) - return [MetaData(ptr) for ptr in lst] - - @staticmethod - def add_named_operand(module, name, operand): - _core.LLVMAddNamedMetadataOperand(module.ptr, name, operand.ptr) - - @property - def operand_count(self): - return _core.LLVMMetaDataGetNumOperands(self.ptr) - - @property - def operands(self): - """Yields operands of this metadata.""" - return [self._get_operand(i) for i in range(self.operand_count)] - - def _get_operand(self, i): - val = _core.LLVMMetaDataGetOperand(self.ptr, i) - if val: # metadata operands can be None - return _make_value(val) - -class MetaDataString(Value): - @staticmethod - def get(module, s): - ptr = _core.LLVMMetaDataStringGet(module.ptr, s) - return MetaDataString(ptr) - - @property - def string(self): - '''Same as MDString::getString''' - return self.name - -class NamedMetaData(llvm.Cacheable): - @staticmethod - def get_or_insert(mod, name): - return mod.get_or_insert_named_metadata(name) - - @staticmethod - def get(mod, name): - return mod.get_named_metadata(name) - - def __init__(self, ptr): - self.ptr = ptr - - def delete(self): - _core.LLVMEraseNamedMetaData(self.ptr) - - @property - def name(self): - return _core.LLVMNamedMetaDataGetName(self.ptr) - - def __str__(self): - return _core.LLVMDumpNamedMDToString(self.ptr) - - def add(self, operand): - _core.LLVMNamedMetaDataAddOperand(self.ptr, operand.ptr) - -#===----------------------------------------------------------------------=== -# Instruction -#===----------------------------------------------------------------------=== - -class Instruction(User): - - @property - def basic_block(self): - return _make_value(_core.LLVMGetInstructionParent(self.ptr)) - - @property - def is_terminator(self): - return _core.LLVMInstIsTerminator(self.ptr) != 0 - - @property - def is_binary_op(self): - return _core.LLVMInstIsBinaryOp(self.ptr) != 0 - - @property - def is_shift(self): - return _core.LLVMInstIsShift(self.ptr) != 0 - - @property - def is_cast(self): - return _core.LLVMInstIsCast(self.ptr) != 0 - - @property - def is_logical_shift(self): - return _core.LLVMInstIsLogicalShift(self.ptr) != 0 - - @property - def is_arithmetic_shift(self): - return _core.LLVMInstIsArithmeticShift(self.ptr) != 0 - - @property - def is_associative(self): - return _core.LLVMInstIsAssociative(self.ptr) != 0 - - @property - def is_commutative(self): - return _core.LLVMInstIsCommutative(self.ptr) != 0 - - @property - def is_volatile(self): - """True if this is a volatile load or store.""" - return _core.LLVMInstIsVolatile(self.ptr) != 0 - - def set_volatile(self, flag): - return _core.LLVMSetVolatile(self.ptr, int(bool(flag))) - - def set_metadata(self, kind, metadata): - return _core.LLVMInstSetMetaData(self.ptr, kind, metadata.ptr) - - @property - def opcode(self): - return _core.LLVMInstGetOpcode(self.ptr) - - @property - def opcode_name(self): - return _core.LLVMInstGetOpcodeName(self.ptr) - - def erase_from_parent(self): - return _core.LLVMInstructionEraseFromParent(self.ptr) - -class CallOrInvokeInstruction(Instruction): - - def _get_cc(self): return _core.LLVMGetInstructionCallConv(self.ptr) - def _set_cc(self, value): _core.LLVMSetInstructionCallConv(self.ptr, value) - calling_convention = property(_get_cc, _set_cc) - - def add_parameter_attribute(self, idx, attr): - _core.LLVMAddInstrAttribute(self.ptr, idx, attr) - - def remove_parameter_attribute(self, idx, attr): - _core.LLVMRemoveInstrAttribute(self.ptr, idx, attr) - - def set_parameter_alignment(self, idx, align): - _core.LLVMSetInstrParamAlignment(self.ptr, idx, align) - - def _get_called_function(self): - function = _core.LLVMInstGetCalledFunction(self.ptr) - if function: # Return value can be None on indirect call/invoke - return _make_value(function) - - def _set_called_function(self, function): - _core.LLVMInstSetCalledFunction(self.ptr, function.ptr) - - called_function = property(_get_called_function, _set_called_function) - - # tail call is valid only for 'call', not 'invoke' - # disabled for now - #def _get_tc(self): return _core.LLVMIsTailCall(self.ptr) - #def _set_tc(self, value): _core.LLVMSetTailCall(self.ptr, value) - #tail_call = property(_get_tc, _set_tc) - - -class PHINode(Instruction): - - @property - def incoming_count(self): - return _core.LLVMCountIncoming(self.ptr) - - def add_incoming(self, value, block): - check_is_value(value) - check_is_basic_block(block) - _core.LLVMAddIncoming1(self.ptr, value.ptr, block.ptr) - - def get_incoming_value(self, idx): - return _make_value(_core.LLVMGetIncomingValue(self.ptr, idx)) - - def get_incoming_block(self, idx): - return _make_value(_core.LLVMGetIncomingBlock(self.ptr, idx)) - - -class SwitchInstruction(Instruction): - - def add_case(self, const, bblk): - check_is_constant(const) # and has to be an int too - check_is_basic_block(bblk) - _core.LLVMAddCase(self.ptr, const.ptr, bblk.ptr) - - -class CompareInstruction(Instruction): - - @property - def predicate(self): - return _core.LLVMCmpInstGetPredicate(self.ptr) - - -#===----------------------------------------------------------------------=== -# Basic block -#===----------------------------------------------------------------------=== - -class BasicBlock(Value): - - def insert_before(self, name): - return _make_value(_core.LLVMInsertBasicBlock(self.ptr, name)) - - def delete(self): - _core.LLVMDeleteBasicBlock(self.ptr) - self.forget() - self.ptr = None - - @property - def function(self): - func_ptr = _core.LLVMGetBasicBlockParent(self.ptr) - return _make_value(func_ptr) - - @property - def instructions(self): - return _util.wrapiter(_core.LLVMGetFirstInstruction, - _core.LLVMGetNextInstruction, self.ptr, _make_value) - - -#===----------------------------------------------------------------------=== -# Value factory method -#===----------------------------------------------------------------------=== - -# value ID -> class map -__class_for_valueid = { - VALUE_ARGUMENT : Argument, - VALUE_BASIC_BLOCK : BasicBlock, - VALUE_FUNCTION : Function, - VALUE_GLOBAL_ALIAS : GlobalValue, - VALUE_GLOBAL_VARIABLE : GlobalVariable, - VALUE_UNDEF_VALUE : UndefValue, - VALUE_CONSTANT_EXPR : ConstantExpr, - VALUE_CONSTANT_AGGREGATE_ZERO : ConstantAggregateZero, - VALUE_CONSTANT_DATA_ARRAY : ConstantDataArray, - VALUE_CONSTANT_DATA_VECTOR : ConstantDataVector, - VALUE_CONSTANT_INT : ConstantInt, - VALUE_CONSTANT_FP : ConstantFP, - VALUE_CONSTANT_ARRAY : ConstantArray, - VALUE_CONSTANT_STRUCT : ConstantStruct, - VALUE_CONSTANT_VECTOR : ConstantVector, - VALUE_CONSTANT_POINTER_NULL : ConstantPointerNull, - VALUE_MD_NODE : MetaData, - VALUE_MD_STRING : MetaDataString, - VALUE_INLINE_ASM : InlineAsm, - VALUE_INSTRUCTION + OPCODE_PHI : PHINode, - VALUE_INSTRUCTION + OPCODE_CALL : CallOrInvokeInstruction, - VALUE_INSTRUCTION + OPCODE_INVOKE : CallOrInvokeInstruction, - VALUE_INSTRUCTION + OPCODE_SWITCH : SwitchInstruction, - VALUE_INSTRUCTION + OPCODE_ICMP : CompareInstruction, - VALUE_INSTRUCTION + OPCODE_FCMP : CompareInstruction -} - -def _make_value(ptr): - kind = _core.LLVMValueGetID(ptr) - # based on kind, create one of the Value subclasses - class_obj = __class_for_valueid.get(kind) - if class_obj: - return class_obj(ptr) - elif kind > VALUE_INSTRUCTION: - # "generic" instruction - return Instruction(ptr) - else: - # "generic" value - return Value(ptr) - - -#===----------------------------------------------------------------------=== -# Builder -#===----------------------------------------------------------------------=== - -class Builder(object): - - @staticmethod - def new(basic_block): - check_is_basic_block(basic_block) - b = Builder(_core.LLVMCreateBuilder()) - b.position_at_end(basic_block) - return b - - def __init__(self, ptr): - self.ptr = ptr - - def __del__(self): - _core.LLVMDisposeBuilder(self.ptr) - - def position_at_beginning(self, bblk): - """Position the builder at the beginning of the given block. - - Next instruction inserted will be first one in the block.""" - check_is_basic_block(bblk) - # Avoids using "blk.instructions", which will fetch all the - # instructions into a list. Don't try this at home, though. - inst_ptr = _core.LLVMGetFirstInstruction(bblk.ptr) - if inst_ptr: - # Issue #10: inst_ptr can be None if b/b has no insts. - inst = _make_value(inst_ptr) - self.position_before(inst) - - def position_at_end(self, bblk): - """Position the builder at the end of the given block. - - Next instruction inserted will be last one in the block.""" - _core.LLVMPositionBuilderAtEnd(self.ptr, bblk.ptr) - - def position_before(self, instr): - """Position the builder before the given instruction. - - The instruction can belong to a basic block other than the - current one.""" - _core.LLVMPositionBuilderBefore(self.ptr, instr.ptr) - - @property - def block(self): - """Deprecated, use basic_block property instead.""" - return _make_value(_core.LLVMGetInsertBlock(self.ptr)) - - @property - def basic_block(self): - """The basic block where the builder is positioned.""" - return _make_value(_core.LLVMGetInsertBlock(self.ptr)) - - # terminator instructions - - def ret_void(self): - return _make_value(_core.LLVMBuildRetVoid(self.ptr)) - - def ret(self, value): - check_is_value(value) - return _make_value(_core.LLVMBuildRet(self.ptr, value.ptr)) - - def ret_many(self, values): - vs = unpack_values(values) - return _make_value(_core.LLVMBuildRetMultiple(self.ptr, vs)) - - def branch(self, bblk): - check_is_basic_block(bblk) - if __debug__: - for instr in self.basic_block.instructions: - assert not instr.is_terminator, "BasicBlock can only have one terminator" - return _make_value(_core.LLVMBuildBr(self.ptr, bblk.ptr)) - - def cbranch(self, if_value, then_blk, else_blk): - check_is_value(if_value) - check_is_basic_block(then_blk) - check_is_basic_block(else_blk) - return _make_value( - _core.LLVMBuildCondBr(self.ptr, - if_value.ptr, then_blk.ptr, else_blk.ptr)) - - def switch(self, value, else_blk, n=10): - check_is_value(value) # value has to be of any 'int' type - check_is_basic_block(else_blk) - return _make_value( - _core.LLVMBuildSwitch(self.ptr, value.ptr, else_blk.ptr, n)) - - def invoke(self, func, args, then_blk, catch_blk, name=""): - check_is_callable(func) - check_is_basic_block(then_blk) - check_is_basic_block(catch_blk) - args2 = unpack_values(args) - return _make_value( - _core.LLVMBuildInvoke(self.ptr, func.ptr, args2, - then_blk.ptr, catch_blk.ptr, name)) - - def unreachable(self): - return _make_value(_core.LLVMBuildUnreachable(self.ptr)) - - # arithmethic, bitwise and logical - - def add(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value(_core.LLVMBuildAdd(self.ptr, lhs.ptr, rhs.ptr, name)) - - def fadd(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value(_core.LLVMBuildFAdd(self.ptr, lhs.ptr, rhs.ptr, name)) - - def sub(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value(_core.LLVMBuildSub(self.ptr, lhs.ptr, rhs.ptr, name)) - - def fsub(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value(_core.LLVMBuildFSub(self.ptr, lhs.ptr, rhs.ptr, name)) - - def mul(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value(_core.LLVMBuildMul(self.ptr, lhs.ptr, rhs.ptr, name)) - - def fmul(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value(_core.LLVMBuildFMul(self.ptr, lhs.ptr, rhs.ptr, name)) - - def udiv(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildUDiv(self.ptr, lhs.ptr, rhs.ptr, name)) - - def sdiv(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildSDiv(self.ptr, lhs.ptr, rhs.ptr, name)) - - def fdiv(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildFDiv(self.ptr, lhs.ptr, rhs.ptr, name)) - - def urem(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildURem(self.ptr, lhs.ptr, rhs.ptr, name)) - - def srem(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildSRem(self.ptr, lhs.ptr, rhs.ptr, name)) - - def frem(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildFRem(self.ptr, lhs.ptr, rhs.ptr, name)) - - def shl(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildShl(self.ptr, lhs.ptr, rhs.ptr, name)) - - def lshr(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildLShr(self.ptr, lhs.ptr, rhs.ptr, name)) - - def ashr(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildAShr(self.ptr, lhs.ptr, rhs.ptr, name)) - - def and_(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildAnd(self.ptr, lhs.ptr, rhs.ptr, name)) - - def or_(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildOr(self.ptr, lhs.ptr, rhs.ptr, name)) - - def xor(self, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildXor(self.ptr, lhs.ptr, rhs.ptr, name)) - - def neg(self, val, name=""): - check_is_value(val) - return _make_value(_core.LLVMBuildNeg(self.ptr, val.ptr, name)) - - def not_(self, val, name=""): - check_is_value(val) - return _make_value(_core.LLVMBuildNot(self.ptr, val.ptr, name)) - - # memory - - def malloc(self, ty, name=""): - check_is_type(ty) - return _make_value(_core.LLVMBuildMalloc(self.ptr, ty.ptr, name)) - - def malloc_array(self, ty, size, name=""): - check_is_type(ty) - check_is_value(size) - return _make_value( - _core.LLVMBuildArrayMalloc(self.ptr, ty.ptr, size.ptr, name)) - - def alloca(self, ty, name=""): - check_is_type(ty) - return _make_value(_core.LLVMBuildAlloca(self.ptr, ty.ptr, name)) - - def alloca_array(self, ty, size, name=""): - check_is_type(ty) - check_is_value(size) - return _make_value( - _core.LLVMBuildArrayAlloca(self.ptr, ty.ptr, size.ptr, name)) - - def free(self, ptr): - check_is_value(ptr) - return _make_value(_core.LLVMBuildFree(self.ptr, ptr.ptr)) - - def load(self, ptr, name="", align=0, volatile=False, invariant=False): - check_is_value(ptr) - inst = _make_value(_core.LLVMBuildLoad(self.ptr, ptr.ptr, name)) - if align: - _core.LLVMLdSetAlignment(inst.ptr, align) - if volatile: - inst.set_volatile(volatile) - if invariant: - mod = self.basic_block.function.module - md = MetaData.get(mod, []) # empty metadata node - inst.set_metadata('invariant.load', md) - return inst - - def store(self, value, ptr, align=0, volatile=False): - check_is_value(value) - check_is_value(ptr) - inst = _make_value(_core.LLVMBuildStore(self.ptr, value.ptr, ptr.ptr)) - if align: - _core.LLVMStSetAlignment(inst.ptr, align) - if volatile: - inst.set_volatile(volatile) - return inst - - def gep(self, ptr, indices, name="", inbounds=False): - check_is_value(ptr) - index_ptrs = unpack_values(indices) - if inbounds: - ret = _core.LLVMBuildInBoundsGEP(self.ptr, ptr.ptr, index_ptrs, name) - else: - ret = _core.LLVMBuildGEP(self.ptr, ptr.ptr, index_ptrs, name) - return _make_value(ret) - - # casts and extensions - - def trunc(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildTrunc(self.ptr, value.ptr, dest_ty.ptr, name)) - - def zext(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildZExt(self.ptr, value.ptr, dest_ty.ptr, name)) - - def sext(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildSExt(self.ptr, value.ptr, dest_ty.ptr, name)) - - def fptoui(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildFPToUI(self.ptr, value.ptr, dest_ty.ptr, name)) - - def fptosi(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildFPToSI(self.ptr, value.ptr, dest_ty.ptr, name)) - - def uitofp(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildUIToFP(self.ptr, value.ptr, dest_ty.ptr, name)) - - def sitofp(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildSIToFP(self.ptr, value.ptr, dest_ty.ptr, name)) - - def fptrunc(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildFPTrunc(self.ptr, value.ptr, dest_ty.ptr, name)) - - def fpext(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildFPExt(self.ptr, value.ptr, dest_ty.ptr, name)) - - def ptrtoint(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildPtrToInt(self.ptr, value.ptr, dest_ty.ptr, name)) - - def inttoptr(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildIntToPtr(self.ptr, value.ptr, dest_ty.ptr, name)) - - def bitcast(self, value, dest_ty, name=""): - check_is_value(value) - check_is_type(dest_ty) - return _make_value( - _core.LLVMBuildBitCast(self.ptr, value.ptr, dest_ty.ptr, name)) - - # comparisons - - def icmp(self, ipred, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildICmp(self.ptr, ipred, lhs.ptr, rhs.ptr, name)) - - def fcmp(self, rpred, lhs, rhs, name=""): - check_is_value(lhs) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildFCmp(self.ptr, rpred, lhs.ptr, rhs.ptr, name)) - - # misc - - def extract_value(self, retval, idx, name=""): - check_is_value(retval) - return _make_value( - _core.LLVMBuildGetResult(self.ptr, retval.ptr, idx, name)) - - # obsolete synonym for extract_value - getresult = extract_value - - def insert_value(self, retval, rhs, idx, name=""): - check_is_value(retval) - check_is_value(rhs) - return _make_value( - _core.LLVMBuildInsertValue(self.ptr, retval.ptr, rhs.ptr, idx, - name)) - - def phi(self, ty, name=""): - check_is_type(ty) - return _make_value(_core.LLVMBuildPhi(self.ptr, ty.ptr, name)) - - def call(self, fn, args, name=""): - check_is_callable(fn) - - err_template = 'Argument type mismatch: expected %s but got %s' - for i, (t, v) in enumerate(zip(fn.type.pointee.args, args)): - if t != v.type: - raise TypeError(err_template % (t, v.type)) - arg_ptrs = unpack_values(args) - return _make_value( - _core.LLVMBuildCall(self.ptr, fn.ptr, arg_ptrs, name)) - - def select(self, cond, then_value, else_value, name=""): - check_is_value(cond) - check_is_value(then_value) - check_is_value(else_value) - return _make_value( - _core.LLVMBuildSelect(self.ptr, cond.ptr, - then_value.ptr, else_value.ptr, name)) - - def vaarg(self, list_val, ty, name=""): - check_is_value(list_val) - check_is_type(ty) - return _make_value( - _core.LLVMBuildVAArg(self.ptr, list_val.ptr, ty.ptr, name)) - - def extract_element(self, vec_val, idx_val, name=""): - check_is_value(vec_val) - check_is_value(idx_val) - return _make_value( - _core.LLVMBuildExtractElement(self.ptr, vec_val.ptr, - idx_val.ptr, name)) - - def insert_element(self, vec_val, elt_val, idx_val, name=""): - check_is_value(vec_val) - check_is_value(elt_val) - check_is_value(idx_val) - return _make_value( - _core.LLVMBuildInsertElement(self.ptr, vec_val.ptr, - elt_val.ptr, idx_val.ptr, name)) - - def shuffle_vector(self, vecA, vecB, mask, name=""): - check_is_value(vecA) - check_is_value(vecB) - check_is_value(mask) - return _make_value( - _core.LLVMBuildShuffleVector(self.ptr, - vecA.ptr, vecB.ptr, mask.ptr, name)) - - # atomics - - def atomic_cmpxchg(self, ptr, old, new, ordering, crossthread=True): - check_is_value(ptr) - check_is_value(old) - check_is_value(new) - inst = _core.LLVMBuildAtomicCmpXchg(self.ptr, ptr.ptr, old.ptr, new.ptr, - ordering.lower(), - int(bool(crossthread))) - return _make_value(inst) - - def atomic_rmw(self, op, ptr, val, ordering, crossthread=True): - check_is_value(ptr) - check_is_value(val) - inst = _core.LLVMBuildAtomicRMW(self.ptr, op.lower(), ptr.ptr, val.ptr, - ordering.lower(), int(bool(crossthread))) - return _make_value(inst) - - def atomic_xchg(self, *args, **kwargs): - return self.atomic_rmw('xchg', *args, **kwargs) - - def atomic_add(self, *args, **kwargs): - return self.atomic_rmw('add', *args, **kwargs) - - def atomic_sub(self, *args, **kwargs): - return self.atomic_rmw('sub', *args, **kwargs) - - def atomic_and(self, *args, **kwargs): - return self.atomic_rmw('and', *args, **kwargs) - - def atomic_nand(self, *args, **kwargs): - return self.atomic_rmw('nand', *args, **kwargs) - - def atomic_or(self, *args, **kwargs): - return self.atomic_rmw('or', *args, **kwargs) - - def atomic_xor(self, *args, **kwargs): - return self.atomic_rmw('xor', *args, **kwargs) - - def atomic_max(self, *args, **kwargs): - return self.atomic_rmw('max', *args, **kwargs) - - def atomic_min(self, *args, **kwargs): - return self.atomic_rmw('min', *args, **kwargs) - - def atomic_umax(self, *args, **kwargs): - return self.atomic_rmw('umax', *args, **kwargs) - - def atomic_umin(self, *args, **kwargs): - return self.atomic_rmw('umin', *args, **kwargs) - - - def atomic_load(self, ptr, ordering, align=1, crossthread=True, - volatile=False, name=""): - check_is_value(ptr) - inst = _make_value(_core.LLVMBuildAtomicLoad( - self.ptr, ptr.ptr, int(align), - ordering.lower(), int(bool(crossthread)))) - if volatile: - inst.set_volatile(volatile) - if inst: - inst.name = name - return inst - - def atomic_store(self, value, ptr, ordering, align=1, crossthread=True, - volatile=False): - check_is_value(value) - check_is_value(ptr) - inst = _make_value(_core.LLVMBuildAtomicStore( - self.ptr, ptr.ptr, value.ptr, int(align), - ordering.lower(), int(bool(crossthread)))) - if volatile: - inst.set_volatile(volatile) - return inst - - def fence(self, ordering, crossthread=True): - inst = _make_value(_core.LLVMBuildFence(self.ptr, ordering.lower(), - int(bool(crossthread)))) - return inst - -#===----------------------------------------------------------------------=== -# Memory buffer -#===----------------------------------------------------------------------=== - -class MemoryBuffer(object): - - @staticmethod - def from_file(fname): - ret = _core.LLVMCreateMemoryBufferWithContentsOfFile(fname) - if isinstance(ret, str): - return (None, ret) - else: - obj = MemoryBuffer(ret) - return (obj, "") - - @staticmethod - def from_stdin(): - ret = _core.LLVMCreateMemoryBufferWithSTDIN() - if isinstance(ret, str): - return (None, ret) - else: - obj = MemoryBuffer(ret) - return (obj, "") - - def __init__(self, ptr): - self.ptr = ptr - - def __del__(self): - _core.LLVMDisposeMemoryBuffer(self.ptr) - - -#===----------------------------------------------------------------------=== -# Misc -#===----------------------------------------------------------------------=== - -def load_library_permanently(filename): - """Load a shared library. - - Load the given shared library (filename argument specifies the full - path of the .so file) using LLVM. Symbols from these are available - from the execution engine thereafter.""" - - ret = _core.LLVMLoadLibraryPermanently(filename) - if isinstance(ret, str): - raise llvm.LLVMException(ret) - -def inline_function(call): - check_is_value(call) - return bool(_core.LLVMInlineFunction(call.ptr)) - -def parse_environment_options(progname, envname): - _core.LLVMParseEnvOpts(progname, envname) - -#===----------------------------------------------------------------------=== -# Initialization -#===----------------------------------------------------------------------=== -if _core.LLVMInitializeNativeTarget(): - raise llvm.LLVMException("No native target!?") -if _core.LLVMInitializeNativeTargetAsmPrinter(): - # should this be an optional feature? - # should user trigger the initialization? - raise llvm.LLVMException("No native asm printer!?") - - -HAS_PTX = HAS_NVPTX = False -if True: # use PTX? - try: - _core.LLVMInitializePTXTarget() - _core.LLVMInitializePTXTargetInfo() - _core.LLVMInitializePTXTargetMC() - _core.LLVMInitializePTXAsmPrinter() - HAS_PTX = True - except AttributeError: - try: - _core.LLVMInitializeNVPTXTarget() - _core.LLVMInitializeNVPTXTargetInfo() - _core.LLVMInitializeNVPTXTargetMC() - _core.LLVMInitializeNVPTXAsmPrinter() - HAS_NVPTX = True - except AttributeError: - pass - + \ No newline at end of file diff --git a/llvm/debuginfo.py b/llvm/debuginfo.py deleted file mode 100644 index 0f18b33..0000000 --- a/llvm/debuginfo.py +++ /dev/null @@ -1,398 +0,0 @@ -""" -Support for debug info metadata. -""" - -import functools - -import llvm.core -from llvm import _dwarf - -#---------------------------------------------------------------------------- -# Some types and type checking functions -#---------------------------------------------------------------------------- - -int32_t = llvm.core.Type.int(32) -bool_t = llvm.core.Type.int(1) -p_int32_t = llvm.core.Type.pointer(int32_t) -null = llvm.core.Constant.null(p_int32_t) - -i32 = functools.partial(llvm.core.Constant.int, int32_t) -i1 = functools.partial(llvm.core.Constant.int, bool_t) - -def is_md(value): - return isinstance(value, (llvm.core.MetaData, llvm.core.NamedMetaData, - llvm.core.Value)) - -def is_mdstr(value): - return isinstance(value, (llvm.core.MetaDataString, llvm.core.Value)) - -#---------------------------------------------------------------------------- -# Callbacks for debug type descriptors -#---------------------------------------------------------------------------- - -def get_i32(llvm_module, value): - return i32(value) - -def get_i1(llvm_module, value): - return i1(value) - -def get_md(llvm_module, value): - if is_md(value): - return value - return value.get_metadata(llvm_module) - -def get_mdstr(llvm_module, value): - if is_mdstr(value): - return value - return llvm.core.MetaDataString.get(llvm_module, value) - -def get_mdlist(llvm_module, value): - if isinstance(value, list): - value = MDList([value]) - return get_md(llvm_module, value) - -def get_lfunc(llvm_module, lfunc): - assert lfunc.module is llvm_module - return lfunc - -#---------------------------------------------------------------------------- -# Debug descriptors that generate LLVM Metadata -#---------------------------------------------------------------------------- - -class desc(object): - """ - Descriptor of a debug field. - - field_name: - name of the field (keyword argument name) - build_metadata: - metadata callback :: (llvm_module, Python value) -> LLVM Value - default: - default value for this field - """ - - def __init__(self, field_name, build_metadata, default=None): - self.field_name = field_name - self.build_metadata = build_metadata - self.default = default - - -def build_operand_list(type_descriptors, idx2name, operands, kwargs): - """ - Build the list of operands from the positional and keyword arguments - to a DebugInfoDescriptor. - - E.g. FileDescriptor("foo.c", "/path/to/file", compile_unit=compile_unit) - - idx2name: {0 : 'source_filename', - 1 : 'source_filedir', - 2 : 'compile_unit' } - operands: ["foo.c", "/path/to/file"] - kwargs: { 'compile_unit' : compile_unit } - """ - for i in range(len(operands), len(type_descriptors)): - name = idx2name[i] - if name in kwargs: - op = kwargs[name] - else: - typedesc = type_descriptors[i] - assert typedesc.default is not None, ( - "No value found for field %s" % typedesc.field_name) - op = typedesc.default - - operands.append(op) - - return operands - - -class DebugInfoDescriptor(object): - """ - Base class to describe a debug info descriptor. - - See http://llvm.org/docs/SourceLevelDebugging.html - """ - - type_descriptors = None # [desc(...)] - idx2name = None # { "field_idx" : field_name } - name2idx = None # { "field_name" : field_idx } - - # Whether the debug descriptor is allowed to be incomplete - # The policy seems unclear ? - accept_optional_data = False - - def __init__(self, *args, **kwargs): - self.class_init() - self.metadata_cache = {} - - operands = list(args) - if kwargs or not self.accept_optional_data: - operands = build_operand_list(self.type_descriptors, - self.idx2name, operands, kwargs) - - self.operands = operands - self.operands_dict = dict( - (typedesc.field_name, operand) - for typedesc, operand in zip(self.type_descriptors, operands)) - - @classmethod - def class_init(cls): - if cls.idx2name is None and cls.type_descriptors is not None: - cls.name2idx = {} - cls.idx2name = {} - - for i, typedesc in enumerate(cls.type_descriptors): - cls.name2idx[typedesc.field_name] = i - cls.idx2name[i] = typedesc.field_name - - def add_metadata(self, metadata_name, metadata): - """ - Replace a metadata value in the operand list. - """ - idx = self.name2idx[metadata_name] - self.operands[idx] = metadata - - #------------------------------------------------------------------------ - # Define metadata in a module - #------------------------------------------------------------------------ - - def get_metadata(self, llvm_module): - """ - Get an existing metadata node for the given LLVM module, or build - one from this instance. - """ - if llvm_module in self.metadata_cache: - node = self.metadata_cache[llvm_module] - else: - node = self.build_metadata(llvm_module) - self.metadata_cache[llvm_module] = node - - return node - - def build_metadata(self, llvm_module): - "Build a metadata node for the given LLVM module" - mdops = [] - for type_desc, operand in zip(self.type_descriptors, self.operands): - try: - field_value = type_desc.build_metadata(llvm_module, operand) - except Exception, e: - if type_desc.build_metadata is get_md: - raise - - raise ValueError("Invalid value for field %r: %s" % ( - type_desc.field_name, e)) - - mdops.append(field_value) - - return llvm.core.MetaData.get(llvm_module, mdops) - - def define(self, llvm_module): - """ - Define this debug descriptor as named debug metadata for the module. - """ - md = self.get_metadata(llvm_module) - llvm.core.MetaData.add_named_operand(llvm_module, "dbg", md) - -#---------------------------------------------------------------------------- -# Convenience descriptors -#---------------------------------------------------------------------------- - -class MDList(DebugInfoDescriptor): - """ - [MetaData] - """ - - def __init__(self, operands): - self.type_descriptors = [desc("op", get_md)] * len(operands) - super(MDList, self).__init__(*operands) - -empty = MDList([]) - -#---------------------------------------------------------------------------- -# Dwarf Debug descriptors -#---------------------------------------------------------------------------- - -class CompileUnitDescriptor(DebugInfoDescriptor): - """ - !0 = metadata !{ - i32, ;; Tag = 17 + LLVMDebugVersion (DW_TAG_compile_unit) - i32, ;; Unused field. - i32, ;; DWARF language identifier (ex. DW_LANG_C89) - metadata, ;; Source file name - metadata, ;; Source file directory (includes trailing slash) - metadata ;; Producer (ex. "4.0.1 LLVM (LLVM research group)") - i1, ;; True if this is a main compile unit. - i1, ;; True if this is optimized. - metadata, ;; Flags - i32 ;; Runtime version - metadata ;; List of enums types - metadata ;; List of retained types - metadata ;; List of subprograms - metadata ;; List of global variables - } - """ - - accept_optional_data = True - - type_descriptors = [ - desc("tag", get_i32), - desc("unused", get_i32), - - # Positional argument list starts here: - desc("langid", get_i32), - desc("source_filename", get_mdstr), - desc("source_filedir", get_mdstr), - desc("producer", get_mdstr), - desc("is_main", get_i1, default=False), - desc("is_optimized", get_i1, default=False), - desc("compile_flags", get_mdstr, default=""), - desc("runtime_version", get_i32, default=0), - desc("enum_types", get_mdlist, default=empty), - desc("retained_types", get_mdlist, default=empty), - desc("subprograms", get_mdlist, default=empty), - desc("global_vars", get_mdlist, default=empty), - ] - - def __init__(self, *args, **kwargs): - super(CompileUnitDescriptor, self).__init__( - _dwarf.DW_TAG_compile_unit + _dwarf.LLVMDebugVersion, # tag - 0, # unused - *args, **kwargs) - - def define(self, llvm_module): - """ - Define this debug descriptor as named debug metadata for the module. - """ - md = self.get_metadata(llvm_module) - llvm.core.MetaData.add_named_operand(llvm_module, "llvm.dbg.cu", md) - - -class FileDescriptor(DebugInfoDescriptor): - """ - !0 = metadata !{ - i32, ;; Tag = 41 + LLVMDebugVersion (DW_TAG_file_type) - metadata, ;; Source file name - metadata, ;; Source file directory (includes trailing slash) - metadata ;; Unused - } - """ - - type_descriptors = [ - desc("tag", get_i32), - - # Positional argument list starts here: - desc("source_filename", get_mdstr), - desc("source_filedir", get_mdstr), - desc("compile_unit", get_md, default=null), - ] - - def __init__(self, *args, **kwargs): - super(FileDescriptor, self).__init__( - _dwarf.DW_TAG_file_type + _dwarf.LLVMDebugVersion, # Tag - *args, **kwargs) - - @classmethod - def from_compileunit(cls, compile_unit_descriptor): - return cls(compile_unit_descriptor.operands_dict["source_filename"], - compile_unit_descriptor.operands_dict["source_filedir"], - compile_unit_descriptor) - - -class SubprogramDescriptor(DebugInfoDescriptor): - """ - !2 = metadata !{ - i32, ;; Tag = 46 + LLVMDebugVersion (DW_TAG_subprogram) - i32, ;; Unused field. - metadata, ;; Reference to context descriptor - metadata, ;; Name - metadata, ;; Display name (fully qualified C++ name) - metadata, ;; MIPS linkage name (for C++) - metadata, ;; Reference to file where defined - i32, ;; Line number where defined - metadata, ;; Reference to type descriptor - i1, ;; True if the global is local to compile unit (static) - i1, ;; True if the global is defined in the compile unit (not extern) - i32, ;; Line number where the scope of the subprogram begins - i32, ;; Virtuality, e.g. dwarf::DW_VIRTUALITY__virtual - i32, ;; Index into a virtual function - metadata, ;; indicates which base type contains the vtable pointer for the - ;; derived class - i32, ;; Flags - Artifical, Private, Protected, Explicit, Prototyped. - i1, ;; isOptimized - Function * , ;; Pointer to LLVM function - metadata, ;; Lists function template parameters - metadata, ;; Function declaration descriptor - metadata ;; List of function variables - } - """ - - accept_optional_data = True - - type_descriptors = [ - desc("tag", get_i32), - desc("unused", get_i32), - - # Positional argument list starts here: - desc("file_desc", get_md), - desc("name", get_mdstr), - desc("display_name", get_mdstr), - desc("mips_linkage_name", get_mdstr), - desc("source_file_ref", get_md), - desc("line_number", get_i32), - desc("signature", get_md), - desc("is_local", get_i1, default=False), - desc("is_definition", get_i1, default=True), - desc("virtual_attribute", get_i32, default=0), - desc("virtual_index", get_i32, default=0), - desc("virttab", get_i32, default=0), - desc("flags", get_i32, default=0), - desc("is_optimized", get_i1, default=False), - desc("llvm_func", get_lfunc), - # Template params - # Func decl - # Func vars - ] - - def __init__(self, *args, **kwargs): - super(SubprogramDescriptor, self).__init__( - _dwarf.DW_TAG_subprogram + _dwarf.LLVMDebugVersion, # Tag - 0, # Unused - *args, **kwargs) - -class BlockDescriptor(DebugInfoDescriptor): - """ - !3 = metadata !{ - i32, ;; Tag = 11 + LLVMDebugVersion (DW_TAG_lexical_block) - metadata,;; Reference to context descriptor - i32, ;; Line number - i32 ;; Column number - } - """ - - type_descriptors = [ - desc("tag", get_i32), - - # Positional argument list starts here: - desc("context_descr", get_md), # FileDescr | BlockDescr | - # SubprogDescr | ComputeUnit - desc("line_number", get_i32), - desc("col_number", get_i32), - ] - - def __init__(self, *args, **kwargs): - super(BlockDescriptor, self).__init__( - _dwarf.DW_TAG_lexical_block + _dwarf.LLVMDebugVersion, - *args, **kwargs) - -class PositionInfoDescriptor(DebugInfoDescriptor): - """ - line number, column number, scope, and original scope - """ - - type_descriptors = [ - desc("line_number", get_i32), - desc("col_number", get_i32), - desc("context_descr", get_md), # Scope of instruction - # (FileDescr etc) - desc("original_context_descr", get_md, # The original scope if inlined - default=null), - ] diff --git a/llvm/ee.py b/llvm/ee.py index e5d6ef1..e69de29 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -1,392 +0,0 @@ -# -# Copyright (c) 2008-10, Mahadevan R All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# -# * Neither the name of this software, nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - -"""Execution Engine and related classes. - -""" - -import llvm # top-level, for common stuff -import llvm.core as core # module, function etc. -import llvm._core as _core # C wrappers -import llvm._util as _util # utility functions -import logging -import os - -logger = logging.getLogger(__name__) - - -# re-export TargetData for backward compatibility. -from llvm.passes import TargetData - -def _detect_avx_support(): - '''FIXME: This is a workaround for AVX support. - ''' - disable_avx_detect = int(os.environ.get('LLVMPY_DISABLE_AVX_DETECT', 0)) - if disable_avx_detect: - return False # enable AVX if user disable AVX detect - force_disable_avx = int(os.environ.get('LLVMPY_FORCE_DISABLE_AVX', 0)) - if force_disable_avx: - return True # force disable AVX - # auto-detect avx - try: - for line in open('/proc/cpuinfo'): - if line.lstrip().startswith('flags') and 'avx' in line.split(): - # enable AVX if flags contain AVX - return False - except IOError: - pass # disable AVX if no /proc/cpuinfo is found - return True # disable AVX if flags does not have AVX - -FORCE_DISABLE_AVX = _detect_avx_support() - -#===----------------------------------------------------------------------=== -# Enumerations -#===----------------------------------------------------------------------=== - -BO_BIG_ENDIAN = 0 -BO_LITTLE_ENDIAN = 1 - -# CodeModel -CM_DEFAULT = 0 -CM_JITDEFAULT = 1 -CM_SMALL = 2 -CM_KERNEL = 3 -CM_MEDIUM = 4 -CM_LARGE = 5 - -#===----------------------------------------------------------------------=== -# Generic value -#===----------------------------------------------------------------------=== - -class GenericValue(object): - - @staticmethod - def int(ty, intval): - core.check_is_type(ty) - ptr = _core.LLVMCreateGenericValueOfInt(ty.ptr, intval, 0) - return GenericValue(ptr) - - @staticmethod - def int_signed(ty, intval): - core.check_is_type(ty) - ptr = _core.LLVMCreateGenericValueOfInt(ty.ptr, intval, 1) - return GenericValue(ptr) - - @staticmethod - def real(ty, floatval): - core.check_is_type(ty) # only float or double - ptr = _core.LLVMCreateGenericValueOfFloat(ty.ptr, floatval) - return GenericValue(ptr) - - @staticmethod - def pointer(*args): - ''' - One argument version takes (addr). - Two argument version takes (ty, addr). [Deprecated] - - `ty` is unused. - `addr` is an integer representing an address. - - TODO: remove two argument version. - ''' - if len(args)==2: - logger.warning("Deprecated: Two argument version of " - "GenericValue.pointer() is deprecated.") - addr = args[1] - elif len(args)!=1: - raise TypeError("pointer() takes 1 or 2 arguments.") - else: - addr = args[0] - ptr = _core.LLVMCreateGenericValueOfPointer(addr) - return GenericValue(ptr) - - def __init__(self, ptr): - self.ptr = ptr - - def __del__(self): - _core.LLVMDisposeGenericValue(self.ptr) - - def as_int(self): - return _core.LLVMGenericValueToInt(self.ptr, 0) - - def as_int_signed(self): - return _core.LLVMGenericValueToInt(self.ptr, 1) - - def as_real(self, ty): - core.check_is_type(ty) # only float or double - return _core.LLVMGenericValueToFloat(ty.ptr, self.ptr) - - def as_pointer(self): - return _core.LLVMGenericValueToPointer(self.ptr) - - -# helper functions for generic value objects -def check_is_generic_value(obj): _util.check_gen(obj, GenericValue) -def _unpack_generic_values(objlist): - return _util.unpack_gen(objlist, check_is_generic_value) - - -#===----------------------------------------------------------------------=== -# Engine builder -#===----------------------------------------------------------------------=== - -class EngineBuilder(object): - @staticmethod - def new(module): - core.check_is_module(module) - _util.check_is_unowned(module) - obj = _core.LLVMCreateEngineBuilder(module.ptr) - return EngineBuilder(obj, module) - - def __init__(self, ptr, module): - self.ptr = ptr - self._module = module - self.__has_mattrs = False - - def __del__(self): - _core.LLVMDisposeEngineBuilder(self.ptr) - - def force_jit(self): - _core.LLVMEngineBuilderForceJIT(self.ptr) - return self - - def force_interpreter(self): - _core.LLVMEngineBuilderForceInterpreter(self.ptr) - return self - - def opt(self, level): - ''' - level valid [0, 1, 2, 3] -- [None, Less, Default, Aggressive] - ''' - assert level in range(4) - _core.LLVMEngineBuilderSetOptLevel(self.ptr, level) - return self - - def mattrs(self, string): - '''set machine attributes as a comma/space separated string - - e.g: +sse,-3dnow - ''' - self.__has_mattrs = True - if FORCE_DISABLE_AVX: - if 'avx' not in map(lambda x: x.strip(), string.split(',')): - # User did not override - string += ',-avx' - _core.LLVMEngineBuilderSetMAttrs(self.ptr, string.replace(',', ' ')) - return self - - def create(self, tm=None): - ''' - tm --- Optional. Provide a TargetMachine. Ownership is transfered - to the returned execution engine. - ''' - if not self.__has_mattrs and FORCE_DISABLE_AVX: - self.mattrs('-avx') - - if tm: - _util.check_is_unowned(tm) - ret = _core.LLVMEngineBuilderCreateTM(self.ptr, tm.ptr) - else: - ret = _core.LLVMEngineBuilderCreate(self.ptr) - if isinstance(ret, str): - raise llvm.LLVMException(ret) - engine = ExecutionEngine(ret, self._module) - if tm: - tm._own(owner=llvm.DummyOwner) - return engine - - def select_target(self): - '''get the corresponding target machine - ''' - ptr = _core.LLVMTargetMachineFromEngineBuilder(self.ptr) - return TargetMachine(ptr) - -#===----------------------------------------------------------------------=== -# Execution engine -#===----------------------------------------------------------------------=== - -class ExecutionEngine(object): - - @staticmethod - def new(module, force_interpreter=False): - eb = EngineBuilder.new(module) - if force_interpreter: - eb.force_interpreter() - return eb.create() - - def __init__(self, ptr, module): - self.ptr = ptr - module._own(self) - - def __del__(self): - _core.LLVMDisposeExecutionEngine(self.ptr) - - def disable_lazy_compilation(self, disabled=True): - _core.LLVMExecutionEngineDisableLazyCompilation(self.ptr, - int(bool(disabled))) - - def run_function(self, fn, args): - core.check_is_function(fn) - ptrs = _unpack_generic_values(args) - gvptr = _core.LLVMRunFunction2(self.ptr, fn.ptr, ptrs) - return GenericValue(gvptr) - - def get_pointer_to_function(self, fn): - core.check_is_function(fn) - return _core.LLVMGetPointerToFunction(self.ptr,fn.ptr) - - def get_pointer_to_global(self, val): - core.check_is_global_value(val) - return _core.LLVMGetPointerToGlobal(self.ptr, val.ptr) - - def add_global_mapping(self, gvar, addr): - assert addr >= 0, "Address cannot not be negative" - _core.LLVMAddGlobalMapping(self.ptr, gvar.ptr, addr) - - def run_static_ctors(self): - _core.LLVMRunStaticConstructors(self.ptr) - - def run_static_dtors(self): - _core.LLVMRunStaticDestructors(self.ptr) - - def free_machine_code_for(self, fn): - core.check_is_function(fn) - _core.LLVMFreeMachineCodeForFunction(self.ptr, fn.ptr) - - def add_module(self, module): - core.check_is_module(module) - _core.LLVMAddModule(self.ptr, module.ptr) - module._own(self) - - def remove_module(self, module): - core.check_is_module(module) - if module.owner != self: - raise llvm.LLVMException("module is not owned by self") - ret = _core.LLVMRemoveModule2(self.ptr, module.ptr) - if isinstance(ret, str): - raise llvm.LLVMException(ret) - return core.Module(ret) - - @property - def target_data(self): - td = TargetData(_core.LLVMGetExecutionEngineTargetData(self.ptr)) - td._own(self) - return td - - -#===----------------------------------------------------------------------=== -# Target machine -#===----------------------------------------------------------------------=== - -def print_registered_targets(): - ''' - Note: print directly to stdout - ''' - _core.LLVMPrintRegisteredTargetsForVersion() - -def get_host_cpu_name(): - '''return the string name of the host CPU - ''' - return _core.LLVMGetHostCPUName() - -def get_default_triple(): - '''return the target triple of the host in str-rep - ''' - return _core.LLVMDefaultTargetTriple() - - -class TargetMachine(llvm.Ownable): - - @staticmethod - def new(triple='', cpu='', features='', opt=2, cm=CM_DEFAULT): - if not triple and not cpu: - triple = get_default_triple() - cpu = get_host_cpu_name() - ptr = _core.LLVMCreateTargetMachine(triple, cpu, features, opt, cm) - return TargetMachine(ptr) - - @staticmethod - def lookup(arch, cpu='', features='', opt=2, cm=CM_DEFAULT): - '''create a targetmachine given an architecture name - - For a list of architectures, - use: `llc -help` - - For a list of available CPUs, - use: `llvm-as < /dev/null | llc -march=xyz -mcpu=help` - - For a list of available attributes (features), - use: `llvm-as < /dev/null | llc -march=xyz -mattr=help` - ''' - ptr = _core.LLVMTargetMachineLookup(arch, cpu, features, opt, cm) - return TargetMachine(ptr) - - def __init__(self, ptr): - llvm.Ownable.__init__(self, ptr, _core.LLVMDisposeTargetMachine) - - def emit_assembly(self, module): - '''returns byte string of the module as assembly code of the target machine - ''' - return _core.LLVMTargetMachineEmitFile(self.ptr, module.ptr, True) - - def emit_object(self, module): - '''returns byte string of the module as native code of the target machine - ''' - return _core.LLVMTargetMachineEmitFile(self.ptr, module.ptr, False) - - @property - def target_data(self): - '''get target data of this machine - ''' - ptr = _core.LLVMTargetMachineGetTargetData(self.ptr) - td = TargetData(ptr) - td._own(self) - return td - - @property - def target_name(self): - return _core.LLVMTargetMachineGetTargetName(self.ptr) - - @property - def target_short_description(self): - return _core.LLVMTargetMachineGetTargetShortDescription(self.ptr) - - @property - def triple(self): - return _core.LLVMTargetMachineGetTriple(self.ptr) - - @property - def cpu(self): - return _core.LLVMTargetMachineGetCPU(self.ptr) - - @property - def feature_string(self): - return _core.LLVMTargetMachineGetFS(self.ptr) - diff --git a/llvm/extra.cpp b/llvm/extra.cpp deleted file mode 100644 index 7b6c064..0000000 --- a/llvm/extra.cpp +++ /dev/null @@ -1,1361 +0,0 @@ -/* - * Copyright (c) 2008-10, Mahadevan R All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of this software, nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * These are some "extra" functions not available in the standard LLVM-C - * bindings, but are required / good-to-have inorder to implement the - * Python bindings. - */ - -// standard includes -#include -#include -#include -#include -#include - -// LLVM includes -#include "llvm/LLVMContext.h" -#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" -//#include "llvm/TypeSymbolTable.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/CallSite.h" -#include "llvm/Support/FormattedStream.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/TargetSelect.h" -#include "llvm/Support/Host.h" - -#include "llvm/IntrinsicInst.h" -#include "llvm/Analysis/Verifier.h" -#include "llvm/Assembly/Parser.h" -#include "llvm/Support/DynamicLibrary.h" -#include "llvm/PassManager.h" -#include "llvm/ExecutionEngine/ExecutionEngine.h" -#include "llvm/Analysis/LoopPass.h" -#include "llvm/Analysis/Passes.h" -#include "llvm/Analysis/DomPrinter.h" -#include "llvm/Transforms/Scalar.h" -#include "llvm/Transforms/IPO.h" -#include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" -#include "llvm/Transforms/Instrumentation.h" -#include "llvm/Transforms/Utils/Cloning.h" -#include "llvm/Linker.h" -#include "llvm/Support/SourceMgr.h" -#include -#include -#include - - -#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 2 - #include "llvm/DataLayout.h" -#else - #include "llvm/Target/TargetData.h" -#endif - -// LLVM-C includes -#include "llvm-c/Core.h" -#include "llvm-c/ExecutionEngine.h" - -// our includes -#include "extra.h" -#include "llvm_c_extra.h" - -namespace llvm{ -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(EngineBuilder, LLVMEngineBuilderRef) -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef) -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(NamedMDNode, LLVMNamedMDRef) -DEFINE_SIMPLE_CONVERSION_FUNCTIONS(Pass, LLVMPassRef) - -template -inline T **unwrap(LLVMTypeRef *Tys, unsigned Length) { - (void)Length; - return reinterpret_cast(Tys); -} - -} - -/* - * For use in LLVMDumpPasses to dump passes. - */ -class PassRegistryPrinter : public llvm::PassRegistrationListener{ -public: - std::ostringstream stringstream; - - inline virtual void passEnumerate(const llvm::PassInfo * pass_info){ - stringstream << pass_info->getPassArgument() - << "\t" - << pass_info->getPassName() - << "\n"; - } -}; - - -/* Helper method for LLVMDumpXXXToString() methods. */ -template -char *do_print(W obj) -{ - std::string s; - llvm::raw_string_ostream buf(s); - UW *p = llvm::unwrap(obj); - assert(p); - p->print(buf); - return strdup(buf.str().c_str()); -} - -namespace { -using namespace llvm; -const CodeGenOpt::Level OptLevelMap[] = { - CodeGenOpt::None, - CodeGenOpt::Less, - CodeGenOpt::Default, - CodeGenOpt::Aggressive, -}; - -const CodeModel::Model CodeModelMap[] = { - CodeModel::Default, - CodeModel::JITDefault, - CodeModel::Small, - CodeModel::Kernel, - CodeModel::Medium, - CodeModel::Large, -}; - - -} // end anony namespace - -#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 2 -LLVMPassRef LLVMCreateTargetTransformInfo(LLVMTargetMachineRef tmref){ - using namespace llvm; - TargetMachine * tm = unwrap(tmref); - Pass * tti = new TargetTransformInfo(tm->getScalarTargetTransformInfo(), - tm->getVectorTargetTransformInfo()); - return wrap(tti); -} -#endif - -LLVMPassRef LLVMCreateTargetLibraryInfo(const char * triple){ - using namespace llvm; - Pass * tli = new TargetLibraryInfo(Triple(triple)); - return wrap(tli); -} - -const char * LLVMDefaultTargetTriple(){ - return strdup(llvm::sys::getDefaultTargetTriple().c_str()); -} - -LLVMPassRef LLVMCreatePassByName(const char *name){ - using namespace llvm; - const PassInfo * pi = Pass::lookupPassInfo(StringRef(name)); - if (pi) { - return wrap(pi->createPass()); - } else { // cannot find pass - return NULL; - } -} - -void LLVMDisposePass(LLVMPassRef passref){ - using namespace llvm; - delete unwrap(passref); -} - -const char * LLVMGetPassName(LLVMPassRef passref){ - using namespace llvm; - return unwrap(passref)->getPassName(); -} - -void LLVMPassDump(LLVMPassRef passref){ - using namespace llvm; - return unwrap(passref)->dump(); -} - -void LLVMAddPass(LLVMPassManagerRef pmref, LLVMPassRef passref){ - using namespace llvm; - unwrap(pmref)->add(unwrap(passref)); -} - -LLVMValueRef LLVMGetFunctionFromInlineAsm(LLVMTypeRef funcType, - const char inlineAsm[], - const char constrains[], - bool hasSideEffect, - bool isAlignStack, - int asmDialect) -{ - using namespace llvm; - FunctionType *fnty = unwrap(funcType); - // asmDialect does not exist for LLVM 3.1 - InlineAsm *inlineasmobj = InlineAsm::get(fnty, inlineAsm, constrains, - hasSideEffect, isAlignStack); - return wrap(inlineasmobj); -} - -LLVMModuleRef LLVMCloneModule(LLVMModuleRef mod) -{ - using namespace llvm; - return wrap(CloneModule(unwrap(mod))); -} - -const char * LLVMDumpNamedMDToString(LLVMNamedMDRef nmd) -{ - using namespace llvm; - std::string s; - llvm::raw_string_ostream buf(s); - unwrap(nmd)->print(buf, NULL); - return strdup(buf.str().c_str()); -} - -const char * LLVMNamedMetaDataGetName(LLVMNamedMDRef nmd) -{ - using namespace llvm; - return unwrap(nmd)->getName().data(); -} - -void LLVMNamedMetaDataAddOperand(LLVMNamedMDRef nmd, LLVMValueRef md) -{ - using namespace llvm; - unwrap(nmd)->addOperand(unwrap(md)); -} - -void LLVMEraseNamedMetaData(LLVMNamedMDRef nmd) -{ - using namespace llvm; - unwrap(nmd)->eraseFromParent(); -} - -LLVMNamedMDRef LLVMModuleGetOrInsertNamedMetaData(LLVMModuleRef mod, const char *name) -{ - using namespace llvm; - return wrap(unwrap(mod)->getOrInsertNamedMetadata(name)); -} - -LLVMNamedMDRef LLVMModuleGetNamedMetaData(LLVMModuleRef mod, const char *name) -{ - using namespace llvm; - return wrap(unwrap(mod)->getNamedMetadata(name)); -} - -void LLVMInstSetMetaData(LLVMValueRef instref, const char* mdkind, - LLVMValueRef metaref) -{ - using namespace llvm; - unwrap(instref)->setMetadata(mdkind, unwrap(metaref)); -} - -LLVMValueRef LLVMMetaDataGet(LLVMModuleRef modref, LLVMValueRef * valrefs, - unsigned valct) -{ - using namespace llvm; - LLVMContext & context = unwrap(modref)->getContext(); - MDNode * const node = MDNode::get( - context, - makeArrayRef(unwrap(valrefs, valct), valct)); - return wrap(node); -} - -LLVMValueRef LLVMMetaDataGetOperand(LLVMValueRef mdref, unsigned index) -{ - return wrap(llvm::unwrap(mdref)->getOperand(index)); -} - -unsigned LLVMMetaDataGetNumOperands(LLVMValueRef mdref) -{ - return llvm::unwrap(mdref)->getNumOperands(); -} - -LLVMValueRef LLVMMetaDataStringGet(LLVMModuleRef modref, const char *s) -{ - LLVMContext & context = unwrap(modref)->getContext(); - MDString * const mdstring = MDString::get(context, s); - return wrap(mdstring); -} - -const char *LLVMGetConstExprOpcodeName(LLVMValueRef inst) -{ - return llvm::unwrap(inst)->getOpcodeName(); -} - -unsigned LLVMGetConstExprOpcode(LLVMValueRef inst) -{ - return llvm::unwrap(inst)->getOpcode(); -} - -void LLVMLdSetAlignment(LLVMValueRef inst, unsigned align) -{ - return llvm::unwrap(inst)->setAlignment(align); -} - -void LLVMStSetAlignment(LLVMValueRef inst, unsigned align) -{ - return llvm::unwrap(inst)->setAlignment(align); -} - -const char * LLVMGetHostCPUName() -{ - return strdup(llvm::sys::getHostCPUName().c_str()); -} - -const char * LLVMGetHostCPUFeatures() -{ - // placeholder - // TODO not implemented even in LLVM3.2svn - // llvm::sys::getHostCPUFeatures - return NULL; -} - -int LLVMInitializeNativeTargetAsmPrinter() -{ - return llvm::InitializeNativeTargetAsmPrinter(); -} - - -LLVMTargetMachineRef LLVMTargetMachineLookup(const char *arch, const char *cpu, - const char *features, int opt, - int codemodel, - std::string &error) -{ - using namespace llvm; - Triple TheTriple; - - // begin borrow from LLVM 3.2 code - // because we don't have 3 argument version of lookup() in 3.1 - const Target * TheTarget = NULL; - - const std::string ArchName(arch); - for (TargetRegistry::iterator it = TargetRegistry::begin(), - ie = TargetRegistry::end(); it != ie; ++it) { - if (ArchName == it->getName()) { - TheTarget = &*it; - break; - } - } - - if (!TheTarget) { - error = "Unknown arch"; - return NULL; - } - - Triple::ArchType Type = Triple::getArchTypeForLLVMName(ArchName); - - if (Type != Triple::UnknownArch){ - TheTriple.setArch(Type); - } - // end borrow from LLVM 3.2 code - - if (!TheTarget->hasTargetMachine()){ - error = "No target machine for the arch"; - return NULL; - } - - TargetOptions no_target_options; - TargetMachine * tm = TheTarget->createTargetMachine(TheTriple.str(), cpu, - features, - no_target_options, - Reloc::Default, - CodeModelMap[codemodel], - OptLevelMap[opt]); - - if (!tm){ - error = "Cannot create target machine"; - return NULL; - } - return wrap(tm); -} - -LLVMTargetMachineRef LLVMCreateTargetMachine(const char *triple, - const char *cpu, - const char *features, - int opt, - int codemodel, - std::string &error) -{ - using namespace llvm; - - std::string TheTriple = triple; - const Target * TheTarget = TargetRegistry::lookupTarget(TheTriple, error); - if (!TheTarget) return NULL; - - TargetOptions no_target_options; - TargetMachine * tm = TheTarget->createTargetMachine(TheTriple, cpu, features, - no_target_options, - Reloc::Default, - CodeModelMap[codemodel], - OptLevelMap[opt]); - if (!tm) { - error = "Cannot create target machine"; - return NULL; - } - return wrap(tm); -} - -LLVMTargetMachineRef LLVMTargetMachineFromEngineBuilder(LLVMEngineBuilderRef eb) -{ - using namespace llvm; - TargetMachine * tm = unwrap(eb)->selectTarget(); - return wrap(tm); -} - -void LLVMDisposeTargetMachine(LLVMTargetMachineRef tm){ - delete llvm::unwrap(tm); -} - - -unsigned char* LLVMTargetMachineEmitFile(LLVMTargetMachineRef tmref, - LLVMModuleRef modref, - int assembly, size_t * lenp, - std::string &error) -{ - using namespace llvm; - assert(lenp); - - Module *modulep = unwrap(modref); - assert(modulep); - - // get objectcode into a string - std::string s; - raw_string_ostream buf(s); - - formatted_raw_ostream fso(buf); - - TargetMachine * tm = unwrap(tmref); - - PassManager pm; -#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 2 - if (!tm->getDataLayout()){ - error = "No target data in target machine"; - return NULL; - } - pm.add(new DataLayout(*tm->getDataLayout())); -#else - if (!tm->getTargetData()){ - error = "No target data in target machine"; - return NULL; - } - pm.add(new TargetData(*tm->getTargetData())); -#endif - - - - bool failed; - if( assembly ) { - failed = tm->addPassesToEmitFile(pm, fso, TargetMachine::CGFT_AssemblyFile); - } else { - failed = tm->addPassesToEmitFile(pm, fso, TargetMachine::CGFT_ObjectFile); - } - - if ( failed ) { - error = "No support for emit file"; - return NULL; - } - - pm.run(*modulep); - - // flush all streams - fso.flush(); - buf.flush(); - - const std::string& bc = buf.str(); - - // and then into a new buffer - size_t bclen = bc.size(); - unsigned char *bytes = new unsigned char[bclen]; - memcpy(bytes, bc.data(), bclen); - - /* return */ - *lenp = bclen; - return bytes; -} - -const char* LLVMTargetMachineGetTargetName(LLVMTargetMachineRef tm) -{ - return strdup(llvm::unwrap(tm)->getTarget().getName()); -} - -const char* LLVMTargetMachineGetTargetShortDescription(LLVMTargetMachineRef tm) -{ - return strdup(llvm::unwrap(tm)->getTarget().getShortDescription()); -} - -const char* LLVMTargetMachineGetTriple(LLVMTargetMachineRef tm) -{ - return strdup(llvm::unwrap(tm)->getTargetTriple().str().c_str()); -} - -const char* LLVMTargetMachineGetCPU(LLVMTargetMachineRef tm) -{ - return strdup(llvm::unwrap(tm)->getTargetCPU().str().c_str()); -} - -const char* LLVMTargetMachineGetFS(LLVMTargetMachineRef tm) -{ - return strdup(llvm::unwrap(tm)->getTargetFeatureString().str().c_str()); -} - -void LLVMPrintRegisteredTargetsForVersion(){ - llvm::TargetRegistry::printRegisteredTargetsForVersion(); -} - - - -LLVMTargetDataRef LLVMTargetMachineGetTargetData(LLVMTargetMachineRef tm) -{ - using namespace llvm; -#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 2 - return wrap(new DataLayout(*unwrap(tm)->getDataLayout())); -#else - return wrap(new TargetData(*unwrap(tm)->getTargetData())); -#endif -} - -unsigned char* LLVMGetNativeCodeFromModule(LLVMModuleRef module, int assembly, - size_t * lenp, std::string &error) -{ - using namespace llvm; - assert(lenp); - - Module *modulep = unwrap(module); - assert(modulep); - - // select native default machine - TargetMachine * tm = EngineBuilder(modulep).selectTarget(); - - return LLVMTargetMachineEmitFile(wrap(tm), module, assembly, lenp, error); -} - -static -llvm::AtomicOrdering atomic_ordering_from_string(const char * ordering) -{ - using namespace llvm; - - if ( strcmp(ordering, "unordered") == 0 ) - return Unordered; - else if ( strcmp(ordering, "monotonic") == 0 ) - return Monotonic; - else if ( strcmp(ordering, "acquire") == 0 ) - return Acquire; - else if ( strcmp(ordering, "release") == 0 ) - return Release; - else if ( strcmp(ordering, "acq_rel") == 0 ) - return AcquireRelease; - else if ( strcmp(ordering, "seq_cst") == 0 ) - return SequentiallyConsistent; - else - return NotAtomic; -} - -static -llvm::SynchronizationScope sync_scope_from_int(int crossthread) -{ - if( crossthread ) - return llvm::CrossThread; - else - return llvm::SingleThread; -} - -LLVMValueRef LLVMBuildFence(LLVMBuilderRef builder, const char* ordering, - int crossthread) -{ - using namespace llvm; - AtomicOrdering atomic_order = atomic_ordering_from_string(ordering); - SynchronizationScope sync_scope = sync_scope_from_int(crossthread); - - Value * inst = unwrap(builder)->CreateFence(atomic_order, sync_scope); - return wrap(inst); -} - -LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef builder, const char * opname, - LLVMValueRef ptr, LLVMValueRef val, - const char* ordering, int crossthread) -{ - using namespace llvm; - - AtomicRMWInst::BinOp op; - - if( strcmp(opname, "xchg") == 0 ) - op = AtomicRMWInst::Xchg; - else if( strcmp(opname, "add") == 0 ) - op = AtomicRMWInst::Add; - else if( strcmp(opname, "sub") == 0 ) - op = AtomicRMWInst::Sub; - else if( strcmp(opname, "and") == 0 ) - op = AtomicRMWInst::And; - else if( strcmp(opname, "nand") == 0 ) - op = AtomicRMWInst::Nand; - else if( strcmp(opname, "or") == 0 ) - op = AtomicRMWInst::Or; - else if( strcmp(opname, "xor") == 0 ) - op = AtomicRMWInst::Xor; - else if( strcmp(opname, "max") == 0 ) - op = AtomicRMWInst::Max; - else if( strcmp(opname, "min") == 0 ) - op = AtomicRMWInst::Min; - else if( strcmp(opname, "umax") == 0 ) - op = AtomicRMWInst::UMax; - else if( strcmp(opname, "umin") == 0 ) - op = AtomicRMWInst::UMin; - else - op = AtomicRMWInst::BAD_BINOP; - - AtomicOrdering atomic_order = atomic_ordering_from_string(ordering); - SynchronizationScope sync_scope = sync_scope_from_int(crossthread); - - Value * inst = unwrap(builder)->CreateAtomicRMW(op, unwrap(ptr), unwrap(val), - atomic_order, sync_scope); - return wrap(inst); -} - -LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef builder, LLVMValueRef ptr, - unsigned align, const char* ordering, - int crossthread) -{ - using namespace llvm; - AtomicOrdering atomic_order = atomic_ordering_from_string(ordering); - SynchronizationScope sync_scope = sync_scope_from_int(crossthread); - - LoadInst * inst = unwrap(builder)->CreateLoad(unwrap(ptr)); - - inst->setAtomic(atomic_order, sync_scope); - inst->setAlignment(align); - - return wrap(inst); -} - -LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef builder, - LLVMValueRef ptr, LLVMValueRef val, - unsigned align, const char* ordering, - int crossthread) -{ - using namespace llvm; - AtomicOrdering atomic_order = atomic_ordering_from_string(ordering); - SynchronizationScope sync_scope = sync_scope_from_int(crossthread); - - StoreInst * inst = unwrap(builder)->CreateStore(unwrap(val), unwrap(ptr)); - - inst->setAtomic(atomic_order, sync_scope); - inst->setAlignment(align); - - return wrap(inst); -} - -LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef builder, LLVMValueRef ptr, - LLVMValueRef cmp, LLVMValueRef val, - const char* ordering, int crossthread) -{ - using namespace llvm; - - AtomicOrdering atomic_order = atomic_ordering_from_string(ordering); - SynchronizationScope sync_scope = sync_scope_from_int(crossthread); - - Value * inst = unwrap(builder)->CreateAtomicCmpXchg( - unwrap(ptr), unwrap(cmp), unwrap(val), - atomic_order, sync_scope); - return wrap(inst); -} - -LLVMEngineBuilderRef LLVMCreateEngineBuilder(LLVMModuleRef mod) -{ - return llvm::wrap(new EngineBuilder(unwrap(mod))); -} - -void LLVMDisposeEngineBuilder(LLVMEngineBuilderRef eb) -{ - delete llvm::unwrap(eb); -} - -void LLVMEngineBuilderForceJIT(LLVMEngineBuilderRef eb) -{ - using namespace llvm; - unwrap(eb)->setEngineKind(EngineKind::JIT); -} - -void LLVMEngineBuilderForceInterpreter(LLVMEngineBuilderRef eb) -{ - using namespace llvm; - unwrap(eb)->setEngineKind(EngineKind::Interpreter); -} - -void LLVMEngineBuilderSetOptLevel(LLVMEngineBuilderRef eb, int level) -{ - unwrap(eb)->setOptLevel(OptLevelMap[level]); -} - -void LLVMEngineBuilderSetMCPU(LLVMEngineBuilderRef eb, const char * mcpu) -{ // TODO add test when llvm3.2 releases - unwrap(eb)->setMCPU(mcpu); // does not work in llvm3.1 -} - -void LLVMEngineBuilderSetMAttrs(LLVMEngineBuilderRef eb, const char * mattrs) -{ // TODO add test when llvm3.2 releases - std::vector tokenized; - std::istringstream iss(mattrs); - std::string buf; - while ( iss >> buf ){ - tokenized.push_back(buf); - } - unwrap(eb)->setMAttrs(tokenized); // does not work in llvm3.1 -} - -LLVMExecutionEngineRef LLVMEngineBuilderCreate(LLVMEngineBuilderRef eb, std::string & error) -{ - using namespace llvm; - LLVMExecutionEngineRef ret; - - ret = wrap(unwrap(eb)->setErrorStr(&error).create()); - - if ( !error.empty() ) { // error string is set - return NULL; - } else { - return ret; - } -} - -LLVMExecutionEngineRef LLVMEngineBuilderCreateTM(LLVMEngineBuilderRef eb, - LLVMTargetMachineRef tm, - std::string & error) -{ - using namespace llvm; - LLVMExecutionEngineRef ret; - - ret = wrap(unwrap(eb)->setErrorStr(&error).create(unwrap(tm))); - - if ( !error.empty() ) { // error string is set - return NULL; - } else { - return ret; - } -} - -int LLVMPassManagerBuilderGetOptLevel(LLVMPassManagerBuilderRef pmb) -{ - return llvm::unwrap(pmb)->OptLevel; -} - -int LLVMPassManagerBuilderGetSizeLevel(LLVMPassManagerBuilderRef pmb) -{ - return llvm::unwrap(pmb)->SizeLevel; -} - -void LLVMPassManagerBuilderSetVectorize(LLVMPassManagerBuilderRef pmb, int flag) -{ - llvm::unwrap(pmb)->Vectorize = flag; -} - -int LLVMPassManagerBuilderGetVectorize(LLVMPassManagerBuilderRef pmb){ - return llvm::unwrap(pmb)->Vectorize; -} - -#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 2 -void LLVMPassManagerBuilderSetLoopVectorize(LLVMPassManagerBuilderRef pmb, - int flag) -{ - llvm::unwrap(pmb)->LoopVectorize = flag; -} - -int LLVMPassManagerBuilderGetLoopVectorize(LLVMPassManagerBuilderRef pmb){ - return llvm::unwrap(pmb)->LoopVectorize; -} -#endif // llvm-3.2 - - -int LLVMPassManagerBuilderGetDisableUnitAtATime(LLVMPassManagerBuilderRef pmb) -{ - return llvm::unwrap(pmb)->DisableUnitAtATime; -} - -int LLVMPassManagerBuilderGetDisableUnrollLoops(LLVMPassManagerBuilderRef pmb) -{ - return llvm::unwrap(pmb)->DisableUnrollLoops; -} - -int LLVMPassManagerBuilderGetDisableSimplifyLibCalls(LLVMPassManagerBuilderRef pmb) -{ - return llvm::unwrap(pmb)->DisableSimplifyLibCalls; -} - - -int LLVMAddPassByName(LLVMPassManagerRef pm, const char * name) -{ - using namespace llvm; - const PassInfo * pi = Pass::lookupPassInfo(StringRef(name)); - if (pi){ - unwrap(pm)->add(pi->createPass()); - return 1; // success - } else { - return 0; // fail -- cannot find pass - } -} - -void LLVMInitializePasses(){ - using namespace llvm; - PassRegistry ®istry = *PassRegistry::getPassRegistry(); - initializeCore(registry); - initializeScalarOpts(registry); - initializeVectorization(registry); - initializeIPO(registry); - initializeAnalysis(registry); - initializeIPA(registry); - initializeTransformUtils(registry); - initializeInstCombine(registry); - initializeInstrumentation(registry); - initializeTarget(registry); -} - -const char * LLVMDumpPasses() -{ - using namespace llvm; - PassRegistry ®istry = *PassRegistry::getPassRegistry(); - PassRegistryPrinter prp; - registry.enumerateWith(&prp); - return strdup(prp.stringstream.str().c_str()); -} - - -int LLVMIsLiteralStruct(LLVMTypeRef type) -{ - return llvm::unwrap(type)->isLiteral(); -} - -LLVMTypeRef LLVMStructTypeIdentified(const char * name) -{ - using namespace llvm; - return wrap(StructType::create(getGlobalContext(), name)); -} - -void LLVMSetStructBody(LLVMTypeRef type, LLVMTypeRef* elemtys, - unsigned elemct, int is_packed) -{ - using namespace llvm; - ArrayRef elemtys_aryref(unwrap(elemtys), elemct); - unwrap(type)->setBody(elemtys_aryref, is_packed); -} - -void LLVMSetStructName(LLVMTypeRef type, const char * name) -{ - llvm::StructType *st = llvm::unwrap(type); - st->setName(name); -} - -char *LLVMGetModuleIdentifier(LLVMModuleRef module) -{ - return strdup(llvm::unwrap(module)->getModuleIdentifier().c_str()); -} - -void LLVMSetModuleIdentifier(LLVMModuleRef module, const char * name) -{ - llvm::unwrap(module)->setModuleIdentifier(name); -} - -char *LLVMDumpModuleToString(LLVMModuleRef module) -{ - std::string s; - llvm::raw_string_ostream buf(s); - llvm::Module *p = llvm::unwrap(module); - assert(p); - p->print(buf, NULL); - return strdup(buf.str().c_str()); -} - -void LLVMModuleAddLibrary(LLVMModuleRef module, const char *name) -{ - llvm::Module *M = llvm::unwrap(module); - llvm::StringRef namestr = llvm::StringRef(name); - M->addLibrary(namestr); - return; -} - -char *LLVMDumpTypeToString(LLVMTypeRef type) -{ - return do_print(type); -} - -char *LLVMDumpValueToString(LLVMValueRef value) -{ - return do_print(value); -} - -unsigned LLVMModuleGetPointerSize(LLVMModuleRef module) -{ - llvm::Module *modulep = llvm::unwrap(module); - assert(modulep); - - llvm::Module::PointerSize p = modulep->getPointerSize(); - if (p == llvm::Module::Pointer32) - return 32; - else if (p == llvm::Module::Pointer64) - return 64; - return 0; -} - -LLVMValueRef LLVMModuleGetOrInsertFunction(LLVMModuleRef module, - const char *name, LLVMTypeRef function_type) -{ - assert(name); - - llvm::Module *modulep = llvm::unwrap(module); - assert(modulep); - - llvm::FunctionType *ftp = llvm::unwrap(function_type); - assert(ftp); - - llvm::Constant *f = modulep->getOrInsertFunction(name, ftp); - return wrap(f); -} - -int LLVMHasInitializer(LLVMValueRef global_var) -{ - llvm::GlobalVariable *gvp = llvm::unwrap(global_var); - assert(gvp); - - return gvp->hasInitializer(); -} - -#define inst_checkfn(ourfn, llvmfn) \ -unsigned ourfn (LLVMValueRef v) { \ - llvm::Instruction *ip = llvm::unwrap(v); \ - assert(ip); \ - return ip-> llvmfn () ? 1 : 0; \ -} - -inst_checkfn(LLVMInstIsTerminator, isTerminator) -inst_checkfn(LLVMInstIsBinaryOp, isBinaryOp) -inst_checkfn(LLVMInstIsShift, isShift) -inst_checkfn(LLVMInstIsCast, isCast) -inst_checkfn(LLVMInstIsLogicalShift, isLogicalShift) -inst_checkfn(LLVMInstIsArithmeticShift, isArithmeticShift) -inst_checkfn(LLVMInstIsAssociative, isAssociative) -inst_checkfn(LLVMInstIsCommutative, isCommutative) - -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); - assert(instp); - return instp->getOpcodeName(); -} - -unsigned LLVMInstGetOpcode(LLVMValueRef inst) -{ - llvm::Instruction *instp = llvm::unwrap(inst); - assert(instp); - return instp->getOpcode(); -} - -unsigned LLVMCmpInstGetPredicate(LLVMValueRef cmpinst) -{ - llvm::CmpInst *instp = llvm::unwrap(cmpinst); - assert(instp); - return instp->getPredicate(); -} - -LLVMValueRef LLVMInstGetCalledFunction(LLVMValueRef inst) -{ - llvm::Instruction *instp = llvm::unwrap(inst); - return llvm::wrap(CallSite(instp).getCalledFunction()); -} - -void LLVMInstSetCalledFunction(LLVMValueRef inst, LLVMValueRef fn) -{ - using namespace llvm; - Instruction *instp = unwrap(inst); - CallSite(instp).setCalledFunction(unwrap(fn)); -} - -///* llvm::unwrap a set of `n' wrapped objects starting at `values', -// * into a vector of pointers to llvm::unwrapped objects `out'. */ -//template -//void unwrap_vec(W *values, unsigned n, std::vector& out) -//{ -// out.clear(); -// out.reserve(n); -// while (n--) { -// UW *p = llvm::unwrap(*values); -// assert(p); -// out.push_back(p); -// ++values; -// } -//} - -///* Same as llvm::unwrap_vec, but use a vector of const pointers. */ -//template -//void unwrap_cvec(W *values, unsigned n, std::vector& out) -//{ -// out.clear(); - -// while (n--) { -// UW *p = llvm::unwrap(*values); -// assert(p); -// out.push_back(p); -// ++values; -// } -//} - - -LLVMValueRef LLVMBuildRetMultiple(LLVMBuilderRef builder, - LLVMValueRef *values, unsigned n_values) -{ - using namespace llvm; - assert(values); - - IRBuilder<> *builderp = unwrap(builder); - assert(builderp); - - return wrap(builderp->CreateAggregateRet(unwrap(values, n_values), n_values)); -} - -LLVMValueRef LLVMBuildGetResult(LLVMBuilderRef builder, - LLVMValueRef value, unsigned index, const char *name) -{ - assert(name); - - llvm::IRBuilder<> *builderp = llvm::unwrap(builder); - assert(builderp); - - return llvm::wrap(builderp->CreateExtractValue(llvm::unwrap(value), index, name)); -} - -unsigned LLVMValueGetID(LLVMValueRef value) -{ - llvm::Value *valuep = llvm::unwrap(value); - assert(valuep); - - return valuep->getValueID(); -} - - -unsigned LLVMValueGetNumUses(LLVMValueRef value) -{ - llvm::Value *valuep = llvm::unwrap(value); - assert(valuep); - - return valuep->getNumUses(); -} - - -unsigned LLVMValueGetUses(LLVMValueRef value, LLVMValueRef **refs) -{ - llvm::Value *valuep = llvm::unwrap(value); - assert(valuep); - - unsigned n = valuep->getNumUses(); - if (n == 0) - return 0; - - assert(refs); - LLVMValueRef *out = new LLVMValueRef[n]; - if (!out) - return 0; - *refs = out; - - memset(out, 0, sizeof(LLVMValueRef) * n); - llvm::Value::use_iterator it = valuep->use_begin(); - while (it != valuep->use_end()) { - *out++ = llvm::wrap(*it); - ++it; - } - - return n; -} - -void LLVMDisposeValueRefArray(LLVMValueRef *refs) -{ - assert(refs); - delete [] refs; -} - -unsigned LLVMUserGetNumOperands(LLVMValueRef user) -{ - llvm::User *userp = llvm::unwrap(user); - assert(userp); - return userp->getNumOperands(); -} - -LLVMValueRef LLVMUserGetOperand(LLVMValueRef user, unsigned idx) -{ - llvm::User *userp = llvm::unwrap(user); - assert(userp); - llvm::Value *operand = userp->getOperand(idx); - return llvm::wrap(operand); -} - -unsigned LLVMGetDoesNotThrow(LLVMValueRef fn) -{ - llvm::Function *fnp = llvm::unwrap(fn); - assert(fnp); - - return fnp->doesNotThrow(); -} - -void LLVMSetDoesNotThrow(LLVMValueRef fn, int DoesNotThrow) -{ - llvm::Function *fnp = llvm::unwrap(fn); - assert(fnp); - - if ((bool)DoesNotThrow) - fnp->setDoesNotThrow(); -} - - -LLVMValueRef LLVMGetIntrinsic(LLVMModuleRef module, int id, - LLVMTypeRef *types, unsigned n_types) -{ - using namespace llvm; - assert(types); - - Module *modulep = unwrap(module); - assert(modulep); - - Function *intfunc = Intrinsic::getDeclaration(modulep, Intrinsic::ID(id), - makeArrayRef(unwrap(types, n_types), - n_types)); - - return wrap(intfunc); -} - -LLVMModuleRef LLVMGetModuleFromAssembly(const char *asmtext, char **out) -{ - assert(asmtext); - assert(out); - - llvm::Module *modulep; - llvm::SMDiagnostic error; - if (!(modulep = llvm::ParseAssemblyString(asmtext, NULL, error, - llvm::getGlobalContext()))) { - std::string s; - llvm::raw_string_ostream buf(s); - error.print("llvm-py", buf); - *out = strdup(buf.str().c_str()); - return NULL; - } - - return wrap(modulep); -} - -LLVMModuleRef LLVMGetModuleFromBitcode(const char *bitcode, unsigned bclen, - char **out) -{ - assert(bitcode); - assert(out); - - llvm::StringRef as_str(bitcode, bclen); - - llvm::MemoryBuffer *mbp; - if (!(mbp = llvm::MemoryBuffer::getMemBufferCopy(as_str))) - return NULL; - - std::string msg; - llvm::Module *modulep; - if (!(modulep = llvm::ParseBitcodeFile(mbp, llvm::getGlobalContext(), - &msg))) - *out = strdup(msg.c_str()); - - delete mbp; - return wrap(modulep); -} - -#if LLVM_VERSION_MAJOR <= 3 && LLVM_VERSION_MINOR < 2 -// Shamelessly copy from LLVM-3.2 -unsigned LLVMLinkModules(LLVMModuleRef Dest, LLVMModuleRef Src, - int Mode, char **OutMessages) { - std::string Messages; - unsigned Result = Linker::LinkModules(unwrap(Dest), unwrap(Src), Mode, - OutMessages? &Messages : 0); - if (OutMessages) - *OutMessages = strdup(Messages.c_str()); - return Result; -} -#endif - -unsigned char *LLVMGetBitcodeFromModule(LLVMModuleRef module, size_t *lenp) -{ - assert(lenp); - - llvm::Module *modulep = llvm::unwrap(module); - assert(modulep); - - /* get bc into a string */ - std::string s; - llvm::raw_string_ostream buf(s); - llvm::WriteBitcodeToFile(modulep, buf); - const std::string& bc = buf.str(); - - /* and then into a new()-ed block */ - size_t bclen = bc.size(); - unsigned char *bytes = new unsigned char[bclen]; - memcpy(bytes, bc.data(), bclen); - - /* return */ - *lenp = bclen; - return bytes; -} - -/* Return 0 on failure (with errmsg filled in), 1 on success. */ -unsigned LLVMLoadLibraryPermanently(const char* filename, char **errmsg) -{ - printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@1"); - assert(filename); - printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@2"); - assert(errmsg); - printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@3"); - - /* Note: the LLVM API returns true on failure. Don't ask why. */ - std::string msg; - printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@4"); - if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(filename, &msg)) { - printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@5"); - *errmsg = strdup(msg.c_str()); - printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@6"); - return 0; - } - printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@7"); - return 1; -} - -void LLVMExecutionEngineDisableLazyCompilation(LLVMExecutionEngineRef ee, int flag) -{ - llvm::unwrap(ee)->DisableLazyCompilation(flag); -} - -void *LLVMGetPointerToFunction(LLVMExecutionEngineRef ee, LLVMValueRef fn) -{ - llvm::ExecutionEngine *eep = llvm::unwrap(ee); - assert(eep); - - llvm::Function *fnp = llvm::unwrap(fn); - assert(fnp); - - return eep->getPointerToFunction(fnp); -} - - -int LLVMInlineFunction(LLVMValueRef call) -{ - llvm::Value *callp = llvm::unwrap(call); - assert(callp); - - llvm::InlineFunctionInfo unused; - - llvm::Instruction *II = llvm::dyn_cast(callp); - if (II->getOpcode() == llvm::Instruction::Call) - return llvm::InlineFunction(static_cast(II), unused); - else if (II->getOpcode() == llvm::Instruction::Invoke) - return llvm::InlineFunction(static_cast(II), unused); - else - return 0; -} - -unsigned LLVMGetParamAlignment(LLVMValueRef arg) -{ - llvm::Argument *argp = llvm::unwrap(arg); - assert(argp); - - unsigned argno = argp->getArgNo(); - - return argp->getParent()->getParamAlignment(argno + 1); -} - - -/* Passes. A few passes (listed below) are used directly from LLVM-C, - * rest are defined here. - */ -/* -#define define_pass(P) \ -void LLVMAdd ## P ## Pass (LLVMPassManagerRef passmgr) { \ - using namespace llvm; \ - llvm::PassManagerBase *pmp = llvm::unwrap(passmgr); \ - assert(pmp); \ - pmp->add( create ## P ## Pass ()); \ -} - -define_pass( AAEval ) -define_pass( AliasAnalysisCounter ) -//define_pass( AlwaysInliner ) -//define_pass( BasicAliasAnalysis ) -define_pass( BlockPlacement ) -define_pass( BreakCriticalEdges ) -define_pass( CodeGenPrepare ) -define_pass( DbgInfoPrinter ) -define_pass( DeadCodeElimination ) -define_pass( DeadInstElimination ) -define_pass( DemoteRegisterToMemory ) -define_pass( DomOnlyPrinter ) -define_pass( DomOnlyViewer ) -define_pass( DomPrinter ) -define_pass( DomViewer ) -define_pass( EdgeProfiler ) -//define_pass( GEPSplitter ) -define_pass( GlobalsModRef ) -define_pass( InstCount ) -define_pass( InstructionNamer ) -define_pass( LazyValueInfo ) -define_pass( LCSSA ) -//define_pass( LiveValues ) -define_pass( LoopDependenceAnalysis ) -define_pass( LoopExtractor ) -define_pass( LoopSimplify ) -define_pass( LoopStrengthReduce ) -define_pass( LowerInvoke ) -define_pass( LowerSwitch ) -define_pass( MergeFunctions ) -define_pass( NoAA ) -define_pass( NoProfileInfo ) -define_pass( OptimalEdgeProfiler ) -define_pass( PartialInlining ) -//define_pass( PartialSpecialization ) -define_pass( PostDomOnlyPrinter ) -define_pass( PostDomOnlyViewer ) -define_pass( PostDomPrinter ) -define_pass( PostDomViewer ) -define_pass( ProfileEstimator ) -define_pass( ProfileLoader ) -define_pass( ProfileVerifier ) -define_pass( ScalarEvolutionAliasAnalysis ) -//define_pass( SimplifyHalfPowrLibCalls ) -define_pass( SingleLoopExtractor ) -define_pass( StripNonDebugSymbols ) -//define_pass( StructRetPromotion ) -//define_pass( TailDuplication ) -define_pass( UnifyFunctionExitNodes ) -*/ -/* we support only internalize(true) */ -/* -llvm::ModulePass *createInternalize2Pass() { return llvm::createInternalizePass(true); } -define_pass( Internalize2 ) -*/ diff --git a/llvm/extra.h b/llvm/extra.h deleted file mode 100644 index b734f1b..0000000 --- a/llvm/extra.h +++ /dev/null @@ -1,676 +0,0 @@ -/* - * Copyright (c) 2008-10, Mahadevan R All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of this software, nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * These are some "extra" functions not available in the standard LLVM-C - * bindings, but are required / good-to-have inorder to implement the - * Python bindings. - */ - -#ifndef LLVM_PY_EXTRA_H -#define LLVM_PY_EXTRA_H - -// select PTX or NVPTX - -#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 2 - #define LLVM_HAS_NVPTX 1 -#else - #define LLVM_HAS_NVPTX 0 -#endif - -#include "llvm-c/Transforms/PassManagerBuilder.h" -#include "llvm_c_extra.h" - - -#ifdef __cplusplus -extern "C" { -#endif - - -#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 2 -/* - * Wraps new TargetTransformInfo( - * TargetMachine::getScalarTargetTransformInfo, - * TargetMachine::getVectorTargetTransformInfo) - */ -LLVMPassRef LLVMCreateTargetTransformInfo(LLVMTargetMachineRef tmref); -#endif - -/* - * Wraps new TargetLibraryInfo - */ -LLVMPassRef LLVMCreateTargetLibraryInfo(const char * triple); - -/* - * Wraps llvm::getDefaultTargetTriple - */ -const char * LLVMDefaultTargetTriple(); - -/* - * Wraps Pass::lookupPassInfo and PassInfo::createPass - */ -LLVMPassRef LLVMCreatePassByName(const char *name); - -/* - * Wraps operator delete (Pass*) - */ -void LLVMDisposePass(LLVMPassRef passref); - -/* - * Wraps Pass::getPassName - */ -const char * LLVMGetPassName(LLVMPassRef passref); - -/* - * Wraps PassManager::add - */ -void LLVMAddPass(LLVMPassManagerRef pmref, LLVMPassRef passref); - -/* - * Wraps Pass::dump - */ -void LLVMPassDump(LLVMPassRef passref); - -/* - * Wraps llvm:InlineAsm::get - */ -LLVMValueRef LLVMGetFunctionFromInlineAsm(LLVMTypeRef funcType, - const char inlineAsm[], - const char constrains[], - bool hasSideEffect, - bool isAlignStack, - int asmDialect); - -/* - * Wraps llvm::CloneModule - */ -LLVMModuleRef LLVMCloneModule(LLVMModuleRef mod); - - -/* - * Wraps NamedMDNode::print() - */ -const char * LLVMDumpNamedMDToString(LLVMNamedMDRef nmd); - -/* - * Wraps NamedMDNode::getName() - */ -const char * LLVMNamedMetaDataGetName(LLVMNamedMDRef nmd); - -/* - * Wraps NamedMDNode::addOperand() - */ -void LLVMNamedMetaDataAddOperand(LLVMNamedMDRef nmd, LLVMValueRef md); - -/* - * Wraps NamedMDNode::eraseFromParent() - */ -void LLVMEraseNamedMetaData(LLVMNamedMDRef nmd); - -/* - * Wraps Module::getOrInsertNamedMetadata - */ -LLVMNamedMDRef LLVMModuleGetOrInsertNamedMetaData(LLVMModuleRef mod, const char *name); - -/* - * Wraps Module::getNamedMetadata - */ -LLVMNamedMDRef LLVMModuleGetNamedMetaData(LLVMModuleRef mod, const char *name); - -/* - * Wraps Instruction::setMetadata() - */ -void LLVMInstSetMetaData(LLVMValueRef instref, const char* mdkind, - LLVMValueRef metaref); - -/* - * Wraps MDNode::get() - */ -LLVMValueRef LLVMMetaDataGet(LLVMModuleRef modref, LLVMValueRef * valrefs, - unsigned valct); - -/* - * Wraps MDNode::getOperand() - */ -LLVMValueRef LLVMMetaDataGetOperand(LLVMValueRef mdref, unsigned index); - -/* - * Wraps MDNode::getNumOperands() - */ -unsigned LLVMMetaDataGetNumOperands(LLVMValueRef mdref); - -/* - * Wraps MDString::get() - */ -LLVMValueRef LLVMMetaDataStringGet(LLVMModuleRef modref, const char *s); - -/* - * Wraps ConstantExpr::getOpcodeName() - */ -const char *LLVMGetConstExprOpcodeName(LLVMValueRef inst); - -/* - * Wraps ConstantExpr::getOpcode() - */ -unsigned LLVMGetConstExprOpcode(LLVMValueRef inst); - -/* - * Wraps LoadInst::SetAlignment - */ -void LLVMLdSetAlignment(LLVMValueRef inst, unsigned align); - -/* - * Wraps StoreInst::SetAlignment - */ -void LLVMStSetAlignment(LLVMValueRef inst, unsigned align); - -const char * LLVMGetHostCPUName(); - -int LLVMInitializeNativeTargetAsmPrinter(); - - -LLVMTargetMachineRef LLVMTargetMachineLookup(const char *arch, const char *cpu, - const char *features, int opt, - int codemodel, std::string &error); - -LLVMTargetMachineRef LLVMCreateTargetMachine(const char *arch, const char *cpu, - const char *features, int opt, - int codemodel, - std::string &error); - -/* - * Wraps EngineBuilder::selectTarget - */ -LLVMTargetMachineRef LLVMTargetMachineFromEngineBuilder(LLVMEngineBuilderRef eb); - -/* - * Wraps operator delete - */ -void LLVMDisposeTargetMachine(LLVMTargetMachineRef tm); - -/* - * Wraps TargetMachine::addPassesToEmitFile - */ -unsigned char* LLVMTargetMachineEmitFile(LLVMTargetMachineRef tmref, - LLVMModuleRef modref, - int assembly, size_t * lenp, - std::string &error); - -/* - * Wraps TargetMachine::getTargetData - */ -LLVMTargetDataRef LLVMTargetMachineGetTargetData(LLVMTargetMachineRef tm); - -/* - * Wraps TargetMachine::getTarget().getName() - */ -const char* LLVMTargetMachineGetTargetName(LLVMTargetMachineRef tm); - -/* - * Wraps TargetMachine::getTarget().getShortDescription() - */ -const char* LLVMTargetMachineGetTargetShortDescription(LLVMTargetMachineRef tm); - -/* - * Wraps TargetMachine::getTargetTriple - */ -const char * LLVMTargetMachineGetTriple(LLVMTargetMachineRef tm); - -/* - * Wraps TargetMachine::getTargetCPU - */ -const char * LLVMTargetMachineGetCPU(LLVMTargetMachineRef tm); - -/* - * Wraps TargetMachine::getTargetFeatureString - */ -const char * LLVMTargetMachineGetFS(LLVMTargetMachineRef tm); - -/* - * Wraps TargetRegister::printRegisteredTargetsForVersion - */ -void LLVMPrintRegisteredTargetsForVersion(); - -/* - * Wraps TargetMachine::addPassesToEmitFile - */ -unsigned char* LLVMGetNativeCodeFromModule(LLVMModuleRef module, int assembly, - size_t * lenp, std::string &error); - -/* - * Wraps IRBuilder::CreateFence - */ -LLVMValueRef LLVMBuildFence(LLVMBuilderRef builder, const char* ordering, - int crossthread); - -/* - * Wraps IRBuilder::CreateLoad, LoadInst::setAtomic - */ -LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef builder, LLVMValueRef ptr, - unsigned align, const char* ordering, - int crossthread); -/* - * Wraps IRBuilder::CreateStore, StoreInst::setAtomic - */ -LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef builder, - LLVMValueRef ptr, LLVMValueRef val, - unsigned align, const char* ordering, - int crossthread); - -/* - * Wraps IRBuilder::CreateAtomicRMW - */ -LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef builder, const char * op, - LLVMValueRef ptr, LLVMValueRef val, - const char* ordering, int crossthread); - -/* - * Wraps IRBuilder::CreateAtomicCmpXchg - */ -LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef builder, LLVMValueRef ptr, - LLVMValueRef cmp, LLVMValueRef val, - const char* ordering, int crossthread); - -/* - * Wraps new EngineBuilder - */ -LLVMEngineBuilderRef LLVMCreateEngineBuilder(LLVMModuleRef mod); - -/* - * Wraps delete EngineBuilder - */ -void LLVMDisposeEngineBuilder(LLVMEngineBuilderRef eb); - - -/* - * Wraps EngineBuilder::setEngineKind(EngineKind::JIT) - */ -void LLVMEngineBuilderForceJIT(LLVMEngineBuilderRef eb); - -/* - * Wraps EngineBuilder::setEngineKind(EngineKind::Interpreter) - */ -void LLVMEngineBuilderForceInterpreter(LLVMEngineBuilderRef eb); - - -/* - * Wraps EngineBuilder::setOptLevel - */ -void LLVMEngineBuilderSetOptLevel(LLVMEngineBuilderRef eb, int level); - -/* - * Wraps EngineBuilder::setMCPU - */ -void LLVMEngineBuilderSetMCPU(LLVMEngineBuilderRef eb, const char * mcpu); - -/* - * Wraps EngineBuilder::setMAttrs - */ -void LLVMEngineBuilderSetMAttrs(LLVMEngineBuilderRef eb, const char * mattrs); - -/* - * Wraps EngineBuilder::setErrorStr and EngineBuilder::create - */ -LLVMExecutionEngineRef LLVMEngineBuilderCreate(LLVMEngineBuilderRef eb, - std::string &error); - -/* - * Wraps EngineBuilder::create(TargetMachine*) - */ -LLVMExecutionEngineRef LLVMEngineBuilderCreateTM(LLVMEngineBuilderRef ebref, - LLVMTargetMachineRef tmref, - std::string & error); - - -/* - * Wraps PassManagerBuilder::OptLevel - */ -int LLVMPassManagerBuilderGetOptLevel(LLVMPassManagerBuilderRef pmb); - -/* - * Wraps PassManagerBuilder::SizeLevel - */ -int LLVMPassManagerBuilderGetSizeLevel(LLVMPassManagerBuilderRef pmb); - -/* - * Wraps PassManagerBuilder::Vectorize - */ -void LLVMPassManagerBuilderSetVectorize(LLVMPassManagerBuilderRef pmb, int flag); - -/* - * Wraps PassManagerBuilder::Vectorize - */ -int LLVMPassManagerBuilderGetVectorize(LLVMPassManagerBuilderRef pmb); - -#if LLVM_VERSION_MAJOR >= 3 && LLVM_VERSION_MINOR >= 2 -/* - * Wraps PassManagerBuilder::LoopVectorize - */ -void LLVMPassManagerBuilderSetLoopVectorize(LLVMPassManagerBuilderRef pmb, - int flag); - -/* - * Wraps PassManagerBuilder::LoopVectorize - */ -int LLVMPassManagerBuilderGetLoopVectorize(LLVMPassManagerBuilderRef pmb); -#endif // llvm-3.2 - -/* - * Wraps PassManagerBuilder::DisableUnitAtATime - */ -int LLVMPassManagerBuilderGetDisableUnitAtATime(LLVMPassManagerBuilderRef pmb); - -/* - * Wraps PassManagerBuilder::DisableUnrollLoops - */ -int LLVMPassManagerBuilderGetDisableUnrollLoops(LLVMPassManagerBuilderRef pmb); - -/* - * Wraps PassManagerBuilder::DisableSimplifyLibCalls - */ -int LLVMPassManagerBuilderGetDisableSimplifyLibCalls(LLVMPassManagerBuilderRef pmb); - -/* - * Wraps PassManager::add - */ -int LLVMAddPassByName(LLVMPassManagerRef pm, const char * name); - -/* - * Wraps initialize* - */ -void LLVMInitializePasses(void); - -/* - * Wraps PassRegistry::enumerateWith() - * Returns a '\n' separated string of all passes available to `opt`. - */ -const char * LLVMDumpPasses(void); - -/* - * Wraps StructType::isLiteral() - */ -int LLVMIsLiteralStruct(LLVMTypeRef type); - -/* - * Wraps StructType::create() - */ -LLVMTypeRef LLVMStructTypeIdentified(const char * name); - -/* - * StructType::setBody() - */ -void LLVMSetStructBody(LLVMTypeRef type, LLVMTypeRef* elemtys, unsigned elemct, int is_packed); - -/* - * Wraps llvm::StructType::setName() - */ -void LLVMSetStructName(LLVMTypeRef type, const char * name); - - -/* - * Wraps llvm::Module::getModuleIdentifier() - */ -char *LLVMGetModuleIdentifier(LLVMModuleRef module); - -/* - * Wraps llvm::Module::setModuleIdentifier() - */ -void LLVMSetModuleIdentifier(LLVMModuleRef module, const char * name); - -/* Notes: - * - Some returned strings must be disposed of by LLVMDisposeMessage. These are - * indicated in the comments. Where it is not indicated, DO NOT call dispose. - */ - -/* Wraps llvm::Module::print(). Dispose the returned string after use, via - * LLVMDisposeMessage(). */ -char *LLVMDumpModuleToString(LLVMModuleRef module); - -/* Wraps llvm::Module::addLibrary(name). */ -void LLVMModuleAddLibrary(LLVMModuleRef module, const char *name); - -/* Wraps llvm::Type::print(). Dispose the returned string after use, via - * LLVMDisposeMessage(). */ -char *LLVMDumpTypeToString(LLVMTypeRef type); - -/* Wraps llvm::Value::print(). Dispose the returned string after use, via - * LLVMDisposeMessage(). */ -char *LLVMDumpValueToString(LLVMValueRef Val); - -/* Wraps llvm::IRBuilder::CreateRet(). */ -LLVMValueRef LLVMBuildRetMultiple(LLVMBuilderRef bulder, LLVMValueRef *values, - unsigned n_values); - -/* Wraps llvm::IRBuilder::CreateGetResult(). */ -LLVMValueRef LLVMBuildGetResult(LLVMBuilderRef builder, LLVMValueRef value, - unsigned index, const char *name); - -/* Wraps llvm::Value::getValueID(). */ -unsigned LLVMValueGetID(LLVMValueRef value); - -/* Wraps llvm::Value::getNumUses(). */ -unsigned LLVMValueGetNumUses(LLVMValueRef value); - -/* Wraps llvm::Value::use_{begin,end}. Allocates LLVMValueRef's as - * required. Number of objects are returned as return value. If that is - * greater than zero, the pointer given out must be freed by a - * subsequent call to LLVMDisposeValueRefArray(). */ -unsigned LLVMValueGetUses(LLVMValueRef value, LLVMValueRef **refs); - -/* See above. */ -void LLVMDisposeValueRefArray(LLVMValueRef *refs); - -/* Wraps llvm:User::getNumOperands(). */ -unsigned LLVMUserGetNumOperands(LLVMValueRef user); - -/* Wraps llvm:User::getOperand(). */ -LLVMValueRef LLVMUserGetOperand(LLVMValueRef user, unsigned idx); - -/* Wraps llvm::ConstantExpr::getVICmp(). */ -LLVMValueRef LLVMConstVICmp(LLVMIntPredicate predicate, LLVMValueRef lhs, - LLVMValueRef rhs); - -/* Wraps llvm::ConstantExpr::getVFCmp(). */ -LLVMValueRef LLVMConstVFCmp(LLVMRealPredicate predicate, LLVMValueRef lhs, - LLVMValueRef rhs); - -/* Wraps llvm::IRBuilder::CreateVICmp(). */ -LLVMValueRef LLVMBuildVICmp(LLVMBuilderRef builder, LLVMIntPredicate predicate, - LLVMValueRef lhs, LLVMValueRef rhs, const char *name); - -/* Wraps llvm::IRBuilder::CreateVFCmp(). */ -LLVMValueRef LLVMBuildVFCmp(LLVMBuilderRef builder, LLVMRealPredicate predicate, - LLVMValueRef lhs, LLVMValueRef rhs, const char *name); - -/* Wraps llvm::Intrinsic::getDeclaration(). */ -LLVMValueRef LLVMGetIntrinsic(LLVMModuleRef builder, int id, - LLVMTypeRef *types, unsigned n_types); - -/* Wraps llvm::Function::doesNotThrow(). */ -unsigned LLVMGetDoesNotThrow(LLVMValueRef fn); - -/* Wraps llvm::Function::setDoesNotThrow(). */ -void LLVMSetDoesNotThrow(LLVMValueRef fn, int DoesNotThrow); - -/* Wraps llvm::Module::getPointerSize(). */ -unsigned LLVMModuleGetPointerSize(LLVMModuleRef module); - -/* Wraps llvm::Module::getOrInsertFunction(). */ -LLVMValueRef LLVMModuleGetOrInsertFunction(LLVMModuleRef module, - const char *name, LLVMTypeRef function_type); - -/* Wraps llvm::GlobalVariable::hasInitializer(). */ -int LLVMHasInitializer(LLVMValueRef global_var); - -/* The following functions wrap various llvm::Instruction::isXXX() functions. - * All of them take an instruction and return 0 (isXXX returned false) or 1 - * (isXXX returned false). */ -unsigned LLVMInstIsTerminator (LLVMValueRef inst); -unsigned LLVMInstIsBinaryOp (LLVMValueRef inst); -unsigned LLVMInstIsShift (LLVMValueRef inst); -unsigned LLVMInstIsCast (LLVMValueRef inst); -unsigned LLVMInstIsLogicalShift (LLVMValueRef inst); -unsigned LLVMInstIsArithmeticShift (LLVMValueRef inst); -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); - -/* Wraps llvm::Instruction::getOpcode(). */ -unsigned LLVMInstGetOpcode(LLVMValueRef inst); - -/* Wraps llvm::CmpInst::getPredicate(). */ -unsigned LLVMCmpInstGetPredicate(LLVMValueRef cmpinst); - -/* Wraps llvm::CallSite::getCalledFunction. - */ -LLVMValueRef LLVMInstGetCalledFunction(LLVMValueRef inst); - -/* Wraps llvm::CallSite::setCalledFunction. - */ -void LLVMInstSetCalledFunction(LLVMValueRef inst, LLVMValueRef fn); - -/* Wraps llvm::ParseAssemblyString(). Returns a module reference or NULL (with - * `out' pointing to an error message). Dispose error message after use, via - * LLVMDisposeMessage(). */ -LLVMModuleRef LLVMGetModuleFromAssembly(const char *asmtxt, char **out); - -/* Wraps llvm::ParseBitcodeFile(). Returns a module reference or NULL (with - * `out' pointing to an error message). Dispose error message after use, via - * LLVMDisposeMessage(). */ -LLVMModuleRef LLVMGetModuleFromBitcode(const char *bc, unsigned bclen, - char **out); - -#if LLVM_VERSION_MAJOR <= 3 && LLVM_VERSION_MINOR < 2 -/* 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, int mode, - char **errmsg); -#endif -/* 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, size_t *len); - -/* Wraps llvm::sys::DynamicLibrary::LoadLibraryPermanently(). Returns 0 on - * failure (with errmsg filled in) and 1 on success. Dispose error message after - * use, via LLVMDisposeMessage(). */ -unsigned LLVMLoadLibraryPermanently(const char* filename, char **errmsg); - -/* Wraps llvm::ExecutionEngine::DisableLazyCompilation(bool) - */ -void LLVMExecutionEngineDisableLazyCompilation(LLVMExecutionEngineRef ee, - int flag); - -/* Wraps llvm::ExecutionEngine::getPointerToFunction(). Returns a pointer - * to the JITted function. */ -void *LLVMGetPointerToFunction(LLVMExecutionEngineRef ee, LLVMValueRef fn); - -/* Wraps llvm::InlineFunction(). Inlines a function. C is the call - * instruction, created by LLVMBuildCall. Even if it fails, the Function - * containing the call is still in a proper state (not changed). - */ -int LLVMInlineFunction(LLVMValueRef call); - -/* Wraps llvm::getAlignmentFromAttrs from Attributes.h. Compliments the - * already available LLVMSetParamAlignment(). */ -unsigned LLVMGetParamAlignment(LLVMValueRef arg); - -/* Passes. Some passes are used directly from LLVM-C, rest are declared - * here. */ - -/* -#define declare_pass(P) \ - void LLVMAdd ## P ## Pass (LLVMPassManagerRef PM); - -declare_pass( AAEval ) -declare_pass( AliasAnalysisCounter ) -declare_pass( AlwaysInliner ) -declare_pass( BasicAliasAnalysis ) -declare_pass( BlockPlacement ) -declare_pass( BreakCriticalEdges ) -declare_pass( CodeGenPrepare ) -declare_pass( DbgInfoPrinter ) -declare_pass( DeadCodeElimination ) -declare_pass( DeadInstElimination ) -declare_pass( DemoteRegisterToMemory ) -declare_pass( DomOnlyPrinter ) -declare_pass( DomOnlyViewer ) -declare_pass( DomPrinter ) -declare_pass( DomViewer ) -declare_pass( EdgeProfiler ) -//declare_pass( GEPSplitter ) -declare_pass( GlobalsModRef ) -declare_pass( InstCount ) -declare_pass( InstructionNamer ) -declare_pass( LazyValueInfo ) -declare_pass( LCSSA ) -//declare_pass( LiveValues ) -declare_pass( LoopDependenceAnalysis ) -declare_pass( LoopExtractor ) -declare_pass( LoopSimplify ) -declare_pass( LoopStrengthReduce ) -declare_pass( LowerInvoke ) -declare_pass( LowerSwitch ) -declare_pass( MergeFunctions ) -declare_pass( NoAA ) -declare_pass( NoProfileInfo ) -declare_pass( OptimalEdgeProfiler ) -declare_pass( PartialInlining ) -//declare_pass( PartialSpecialization ) -declare_pass( PostDomOnlyPrinter ) -declare_pass( PostDomOnlyViewer ) -declare_pass( PostDomPrinter ) -declare_pass( PostDomViewer ) -declare_pass( ProfileEstimator ) -declare_pass( ProfileLoader ) -declare_pass( ProfileVerifier ) -declare_pass( ScalarEvolutionAliasAnalysis ) -declare_pass( SimplifyHalfPowrLibCalls ) -declare_pass( SingleLoopExtractor ) -declare_pass( StripNonDebugSymbols ) -declare_pass( StructRetPromotion ) -declare_pass( TailDuplication ) -declare_pass( UnifyFunctionExitNodes ) - -declare_pass( Internalize2 ) -*/ - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* LLVM_PY_EXTRA_H */ - diff --git a/llvm/llvm_c_extra.h b/llvm/llvm_c_extra.h deleted file mode 100644 index 5728875..0000000 --- a/llvm/llvm_c_extra.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef LLVM_C_EXTRA_H_ -#define LLVM_C_EXTRA_H_ - -#include - - -#ifdef __cplusplus - extern "C" { -#endif - -// Resurrect from llvm-c/Core.h -#define DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ty, ref) \ -inline ty *unwrap(ref P) { \ - return reinterpret_cast(P); \ -} \ - \ -inline ref wrap(const ty *P) { \ - return reinterpret_cast(const_cast(P)); \ -} - -typedef struct LLVMOpaqueEngineBuilder *LLVMEngineBuilderRef; -typedef struct LLVMOpaqueTargetMachine *LLVMTargetMachineRef; -typedef struct LLVMOpaqueNamedMD *LLVMNamedMDRef; -typedef struct LLVMOpaquePass *LLVMPassRef; - -#ifdef __cplusplus - } -#endif - -#endif //LLVM_C_EXTRA_H_ - diff --git a/llvm/passes.py b/llvm/passes.py index 4d7efb4..e69de29 100644 --- a/llvm/passes.py +++ b/llvm/passes.py @@ -1,417 +0,0 @@ -# -# Copyright (c) 2008-10, Mahadevan R All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# -# * Neither the name of this software, nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - -"""Pass managers and passes. - -This module provides the LLVM pass managers and the passes themselves. -All transformation passes listed at http://www.llvm.org/docs/Passes.html -are available. -""" - -import llvm # top-level, for common stuff -import llvm.core as core # module, function etc. -import llvm._core as _core # C wrappers -import llvm._util as _util # Utility functions - -import warnings -#===----------------------------------------------------------------------=== -# Pass manager builder -#===----------------------------------------------------------------------=== - -class PassManagerBuilder(object): - @staticmethod - def new(): - return PassManagerBuilder(_core.LLVMPassManagerBuilderCreate()) - - def __init__(self, ptr): - self.ptr = ptr - - def __del__(self): - _core.LLVMPassManagerBuilderDispose(self.ptr) - - def populate(self, pm): - if isinstance(pm, FunctionPassManager): - return _core.LLVMPassManagerBuilderPopulateFunctionPassManager( - self.ptr, pm.ptr) - else: - return _core.LLVMPassManagerBuilderPopulateModulePassManager( - self.ptr, pm.ptr) - - - def _set_opt_level(self, optlevel): - _core.LLVMPassManagerBuilderSetOptLevel(self.ptr, optlevel) - - def _get_opt_level(self): - return _core.LLVMPassManagerBuilderGetOptLevel(self.ptr) - - opt_level = property(_get_opt_level, _set_opt_level) - - def _set_size_level(self, sizelevel): - _core.LLVMPassManagerBuilderSetSizeLevel(self.ptr, sizelevel) - - def _get_size_level(self): - return _core.LLVMPassManagerBuilderGetSizeLevel(self.ptr) - - size_level = property(_get_size_level, _set_size_level) - - def _set_vectorize(self, enable): - _core.LLVMPassManagerBuilderSetVectorize(self.ptr, int(bool(enable))) - - def _get_vectorize(self): - return bool(_core.LLVMPassManagerBuilderGetVectorize(self.ptr)) - - vectorize = property(_get_vectorize, _set_vectorize) - - def _set_loop_vectorize(self, enable): - if llvm.version >= (3, 2): - _core.LLVMPassManagerBuilderSetLoopVectorize(self.ptr, - int(bool(enable))) - elif enable: - warnings.warn("Ignored. LLVM-3.1 & prior do not support loop vectorizer.") - - def _get_loop_vectorize(self): - try: - return bool(_core.LLVMPassManagerBuilderGetLoopVectorize(self.ptr)) - except AttributeError: - return False - - loop_vectorize = property(_get_loop_vectorize, _set_loop_vectorize) - - def _set_disable_unit_at_a_time(self, disable): - return _core.LLVMPassManagerBuilderSetDisableUnitAtATime( - self.ptr, disable) - - def _get_disable_unit_at_a_time(self): - return _core.LLVMPassManagerBuilderGetDisableUnitAtATime( - self.ptr) - - disable_unit_at_a_time = property(_get_disable_unit_at_a_time, - _set_disable_unit_at_a_time) - - def _set_disable_unroll_loops(self, disable): - return _core.LLVMPassManagerBuilderGetDisableUnrollLoops( - self.ptr, disable) - - def _get_disable_unroll_loops(self): - return _core.LLVMPassManagerBuilderGetDisableUnrollLoops(self.ptr) - - disable_unroll_loops = property(_get_disable_unroll_loops, - _set_disable_unroll_loops) - - def _set_disable_simplify_lib_calls(self, disable): - return _core.LLVMPassManagerBuilderGetDisableSimplifyLibCalls( - self.ptr, disable) - - def _get_disable_simplify_lib_calls(self): - return _core.LLVMPassManagerBuilderGetDisableSimplifyLibCalls(self.ptr) - - disable_simplify_lib_calls = property(_get_disable_simplify_lib_calls, - _set_disable_simplify_lib_calls) - - def use_inliner_with_threshold(self, threshold): - _core.LLVMPassManagerBuilderUseInlinerWithThreshold(self.ptr, threshold) - -#===----------------------------------------------------------------------=== -# Pass manager -#===----------------------------------------------------------------------=== - -class PassManager(object): - - @staticmethod - def new(): - return PassManager(_core.LLVMCreatePassManager()) - - def __init__(self, ptr): - self.ptr = ptr - - def __del__(self): - _core.LLVMDisposePassManager(self.ptr) - - def add(self, pass_obj): - '''Add a pass to the pass manager. - - pass_obj --- Either a Pass instance, a string name of a pass - ''' - if isinstance(pass_obj, Pass): - _util.check_is_unowned(pass_obj) - _core.LLVMAddPass(self.ptr, pass_obj.ptr) - pass_obj._own(self) # PassManager owns the pass - elif _util.isstring(pass_obj): - self._add_pass(pass_obj) - else: - raise llvm.LLVMException("invalid pass_id (%s)" % pass_obj) - - def _add_pass(self, pass_name): - status = _core.LLVMAddPassByName(self.ptr, pass_name) - if not status: - assert pass_name not in PASSES, "Registered but not found?" - raise llvm.LLVMException('Invalid pass name "%s"' % pass_name) - - def run(self, module): - core.check_is_module(module) - return _core.LLVMRunPassManager(self.ptr, module.ptr) - -class FunctionPassManager(PassManager): - - @staticmethod - def new(module): - core.check_is_module(module) - ptr = _core.LLVMCreateFunctionPassManagerForModule(module.ptr) - return FunctionPassManager(ptr) - - def __init__(self, ptr): - PassManager.__init__(self, ptr) - - def initialize(self): - _core.LLVMInitializeFunctionPassManager(self.ptr) - - def run(self, fn): - core.check_is_function(fn) - return _core.LLVMRunFunctionPassManager(self.ptr, fn.ptr) - - def finalize(self): - _core.LLVMFinalizeFunctionPassManager(self.ptr) - - - -#===----------------------------------------------------------------------=== -# Passes -#===----------------------------------------------------------------------=== - -class Pass(llvm.Ownable): - '''Pass Inferface - ''' - def __init__(self, ptr): - llvm.Ownable.__init__(self, ptr, _core.LLVMDisposePass) - self.__name = '' - - @staticmethod - def new(name): - '''Create a new pass by name. - - Note: Not all pass has a default constructor. LLVM will kill - the process if an the pass requires arguments to construct. - The error cannot be caught. - ''' - ptr = _core.LLVMCreatePassByName(name) - p = Pass(ptr) - p.__name = name - return p - - @property - def name(self): - '''The name used in PassRegistry. - ''' - return self.__name - - @property - def description(self): - return _core.LLVMGetPassName(self.ptr) - - def dump(self): - return _core.LLVMPassDump(self.ptr) - - -#===----------------------------------------------------------------------=== -# Target data -#===----------------------------------------------------------------------=== - -class TargetData(Pass): - - @staticmethod - def new(strrep): - return TargetData(_core.LLVMCreateTargetData(strrep)) - - def clone(self): - return TargetData.new(str(self)) - - def __str__(self): - return _core.LLVMTargetDataAsString(self.ptr) - - @property - def byte_order(self): - return _core.LLVMByteOrder(self.ptr) - - @property - def pointer_size(self): - return _core.LLVMPointerSize(self.ptr) - - @property - def target_integer_type(self): - ptr = _core.LLVMIntPtrType(self.ptr); - return core.IntegerType(ptr, core.TYPE_INTEGER) - - def size(self, ty): - core.check_is_type(ty) - return _core.LLVMSizeOfTypeInBits(self.ptr, ty.ptr) - - def store_size(self, ty): - core.check_is_type(ty) - return _core.LLVMStoreSizeOfType(self.ptr, ty.ptr) - - def abi_size(self, ty): - core.check_is_type(ty) - return _core.LLVMABISizeOfType(self.ptr, ty.ptr) - - def abi_alignment(self, ty): - core.check_is_type(ty) - return _core.LLVMABIAlignmentOfType(self.ptr, ty.ptr) - - def callframe_alignment(self, ty): - core.check_is_type(ty) - return _core.LLVMCallFrameAlignmentOfType(self.ptr, ty.ptr) - - def preferred_alignment(self, ty_or_gv): - if isinstance(ty_or_gv, core.Type): - return _core.LLVMPreferredAlignmentOfType(self.ptr, - ty_or_gv.ptr) - elif isinstance(ty_or_gv, core.GlobalVariable): - return _core.LLVMPreferredAlignmentOfGlobal(self.ptr, - ty_or_gv.ptr) - else: - raise core.LLVMException("argument is neither a type nor a global variable") - - def element_at_offset(self, ty, ofs): - core.check_is_type_struct(ty) - ofs = int(ofs) # ofs is unsigned long long - return _core.LLVMElementAtOffset(self.ptr, ty.ptr, ofs) - - def offset_of_element(self, ty, el): - core.check_is_type_struct(ty) - el = int(el) # el should be an int - return _core.LLVMOffsetOfElement(self.ptr, ty.ptr, el) - - -#===----------------------------------------------------------------------=== -# Target Library Info -#===----------------------------------------------------------------------=== - -class TargetLibraryInfo(Pass): - @staticmethod - def new(triple): - ptr = _core.LLVMCreateTargetLibraryInfo(triple) - return TargetLibraryInfo(ptr) - - -#===----------------------------------------------------------------------=== -# Target Transform Info -#===----------------------------------------------------------------------=== - -class TargetTransformInfo(Pass): - @staticmethod - def new(targetmachine): - llvm.require_version_at_least(3, 2) - ptr = _core.LLVMCreateTargetTransformInfo(targetmachine.ptr) - return TargetTransformInfo(ptr) - - -#===----------------------------------------------------------------------=== -# Helpers -#===----------------------------------------------------------------------=== - -def build_pass_managers(tm, opt=2, loop_vectorize=False, vectorize=False, - inline_threshold=2000, pm=True, fpm=True, mod=None): - ''' - tm --- The TargetMachine for which the passes are optimizing for. - The TargetMachine must stay alive until the pass managers - are removed. - opt --- [0-3] Optimization level. Default to 2. - loop_vectorize --- [boolean] Whether to use loop-vectorizer. - vectorize --- [boolean] Whether to use basic-block vectorizer. - inline_threshold --- [int] Threshold for the inliner. - features --- [str] CPU feature string. - pm --- [boolean] Whether to build a module-level pass-manager. - fpm --- [boolean] Whether to build a function-level pass-manager. - mod --- [Module] The module object for the FunctionPassManager. - ''' - if pm: - pm = PassManager.new() - if fpm: - if not mod: - raise TypeError("Keyword 'mod' must be defined") - fpm = FunctionPassManager.new(mod) - - # Populate PassManagers with target specific passes - pmb = PassManagerBuilder.new() - pmb.opt_level = opt - pmb.vectorize = vectorize - pmb.loop_vectorize = loop_vectorize - if inline_threshold: - pmb.use_inliner_with_threshold(inline_threshold) - if pm: - pm.add(tm.target_data.clone()) - pm.add(TargetLibraryInfo.new(tm.triple)) - if llvm.version >= (3, 2): - pm.add(TargetTransformInfo.new(tm)) - pmb.populate(pm) - - if fpm: - fpm.add(tm.target_data) - fpm.add(TargetLibraryInfo.new(tm.triple)) - if llvm.version >= (3, 2): - fpm.add(TargetTransformInfo.new(tm)) - pmb.populate(fpm) - fpm.initialize() - - from collections import namedtuple - return namedtuple('passmanagers', ['pm', 'fpm'])(pm=pm, fpm=fpm) - - -#===----------------------------------------------------------------------=== -# Misc. -#===----------------------------------------------------------------------=== - -# Intialize passes -PASSES = None - -def _dump_all_passes(): - passes_sep_by_line = _core.LLVMDumpPasses() - strip = lambda S : S.strip() - for line in passes_sep_by_line.splitlines(): - passarg, passname = map(strip, line.split('\t', 1)) - if passarg: - yield passarg, passname - -def _initialize_passes(): - global PASSES - _core.LLVMInitializePasses() - PASSES = dict(_dump_all_passes()) - - # build globals - def transform(name): - return "PASS_%s" % (name.upper().replace('-', '_')) - - global_symbols = globals() - for i in PASSES: - assert i not in global_symbols - global_symbols[transform(i)] = i - -_initialize_passes() - diff --git a/llvm/py3k_update.diff b/llvm/py3k_update.diff deleted file mode 100644 index 2bb11a9..0000000 --- a/llvm/py3k_update.diff +++ /dev/null @@ -1,973 +0,0 @@ ---- .\setup-win32.py (original) -+++ .\setup-win32.py (refactored) -@@ -145,10 +145,10 @@ - - # get llvm config - llvm_dir, llvm_build_dir, is_good = get_llvm_config() -- print "Using llvm-dir=" + llvm_dir + " and llvm-build-dir=" + llvm_build_dir -+ print("Using llvm-dir=" + llvm_dir + " and llvm-build-dir=" + llvm_build_dir) - if not is_good: -- print "Cannot find llvm-dir or llvm-build-dir" -- print "Try again with --llvm-dir=/path/to/llvm-top-dir --llvm-build-dir=/path/to/llvm/cmake/dir." -+ print("Cannot find llvm-dir or llvm-build-dir") -+ print("Try again with --llvm-dir=/path/to/llvm-top-dir --llvm-build-dir=/path/to/llvm/cmake/dir.") - return 1 - - # setup ---- .\setup.py (original) -+++ .\setup.py (refactored) -@@ -120,10 +120,10 @@ - # get llvm config - llvm_config, is_good = get_llvm_config() - if is_good: -- print "Using llvm-config=" + llvm_config -+ print("Using llvm-config=" + llvm_config) - else: -- print "Cannot invoke llvm-config (tried '%s')." % llvm_config -- print "Try again with --llvm-config=/path/to/llvm-config." -+ print("Cannot invoke llvm-config (tried '%s')." % llvm_config) -+ print("Try again with --llvm-config=/path/to/llvm-config.") - return 1 - - # setup ---- .\llvm\__init__.py (original) -+++ .\llvm\__init__.py (refactored) -@@ -68,12 +68,12 @@ - - def _own(self, owner): - if self.owner: -- raise LLVMException, "object already owned" -+ raise LLVMException("object already owned") - self.owner = owner - - def _disown(self): - if not self.owner: -- raise LLVMException, "not owned" -+ raise LLVMException("not owned") - self.owner = None - - def __del__(self): -@@ -135,15 +135,13 @@ - # Cacheables - #===----------------------------------------------------------------------=== - --class Cacheable(object): -+class Cacheable(object, metaclass=_ObjectCache): - """Objects that can be cached. - - Objects that wrap a PyCObject are cached to avoid "aliasing", i.e., - two Python objects each containing a PyCObject which internally points - to the same C pointer.""" - -- __metaclass__ = _ObjectCache -- - def forget(self): - _ObjectCache.forget(self) - ---- .\llvm\_util.py (original) -+++ .\llvm\_util.py (refactored) -@@ -45,11 +45,11 @@ - if not isinstance(obj, typ): - typ_str = typ.__name__ - msg = "argument not an instance of llvm.core.%s" % typ_str -- raise TypeError, msg -+ raise TypeError(msg) - - def check_is_unowned(ownable): - if ownable.owner: -- raise llvm.LLVMException, "object is already owned" -+ raise llvm.LLVMException("object is already owned") - - - #===----------------------------------------------------------------------=== ---- .\llvm\core.py (original) -+++ .\llvm\core.py (refactored) -@@ -297,7 +297,7 @@ - if isinstance(typ, PointerType) and \ - isinstance(typ.pointee, FunctionType): - return -- raise TypeError, "argument is neither a function nor a function pointer" -+ raise TypeError("argument is neither a function nor a function pointer") - - def _to_int(v): - if v: -@@ -341,9 +341,9 @@ - data = fileobj.read() - ret = _core.LLVMGetModuleFromBitcode(data) - if not ret: -- raise llvm.LLVMException, "Unable to create module from bitcode" -+ raise llvm.LLVMException("Unable to create module from bitcode") - elif isinstance(ret, str): -- raise llvm.LLVMException, ret -+ raise llvm.LLVMException(ret) - else: - return Module(ret) - -@@ -355,10 +355,9 @@ - data = fileobj.read() - ret = _core.LLVMGetModuleFromAssembly(data) - if not ret: -- raise llvm.LLVMException, \ -- "Unable to create module from assembly" -+ raise llvm.LLVMException("Unable to create module from assembly") - elif isinstance(ret, str): -- raise llvm.LLVMException, ret -+ raise llvm.LLVMException(ret) - else: - return Module(ret) - -@@ -437,7 +436,7 @@ - other.forget() # remove it from object cache - ret = _core.LLVMLinkModules(self.ptr, other.ptr) - if isinstance(ret, str): -- raise llvm.LLVMException, ret -+ raise llvm.LLVMException(ret) - # Do not try to destroy the other module's llvm::Module*. - other._own(llvm.DummyOwner()) - -@@ -506,7 +505,7 @@ - error.""" - ret = _core.LLVMVerifyModule(self.ptr) - if ret != "": -- raise llvm.LLVMException, ret -+ raise llvm.LLVMException(ret) - - def to_bitcode(self, fileobj): - """Write bitcode representation of module to given file-like -@@ -514,7 +513,7 @@ - - data = _core.LLVMGetBitcodeFromModule(self.ptr) - if not data: -- raise llvm.LLVMException, "Unable to create bitcode" -+ raise llvm.LLVMException("Unable to create bitcode") - fileobj.write(data) - - -@@ -1236,7 +1235,7 @@ - check_is_module(module) - ptr = _core.LLVMGetNamedGlobal(module.ptr, name) - if not ptr: -- raise llvm.LLVMException, ("no global named `%s`" % name) -+ raise llvm.LLVMException("no global named `%s`" % name) - return _make_value(ptr) - - def delete(self): -@@ -1307,7 +1306,7 @@ - check_is_module(module) - ptr = _core.LLVMGetNamedFunction(module.ptr, name) - if not ptr: -- raise llvm.LLVMException, ("no function named `%s`" % name) -+ raise llvm.LLVMException("no function named `%s`" % name) - return _make_value(ptr) - - @staticmethod -@@ -2006,7 +2005,7 @@ - - ret = _core.LLVMLoadLibraryPermanently(filename) - if isinstance(ret, str): -- raise llvm.LLVMException, ret -+ raise llvm.LLVMException(ret) - - def inline_function(call): - check_is_value(call) ---- .\llvm\ee.py (original) -+++ .\llvm\ee.py (refactored) -@@ -103,12 +103,11 @@ - return _core.LLVMPreferredAlignmentOfGlobal(self.ptr, - ty_or_gv.ptr) - else: -- raise core.LLVMException, \ -- "argument is neither a type nor a global variable" -+ raise core.LLVMException("argument is neither a type nor a global variable") - - def element_at_offset(self, ty, ofs): - core.check_is_type_struct(ty) -- ofs = long(ofs) # ofs is unsigned long long -+ ofs = int(ofs) # ofs is unsigned long long - return _core.LLVMElementAtOffset(self.ptr, ty.ptr, ofs) - - def offset_of_element(self, ty, el): -@@ -185,7 +184,7 @@ - _util.check_is_unowned(module) - ret = _core.LLVMCreateExecutionEngine(module.ptr, int(force_interpreter)) - if isinstance(ret, str): -- raise llvm.LLVMException, ret -+ raise llvm.LLVMException(ret) - return ExecutionEngine(ret, module) - - def __init__(self, ptr, module): -@@ -223,10 +222,10 @@ - def remove_module(self, module): - core.check_is_module(module) - if module.owner != self: -- raise llvm.LLVMException, "module is not owned by self" -+ raise llvm.LLVMException("module is not owned by self") - ret = _core.LLVMRemoveModule2(self.ptr, module.ptr) - if isinstance(ret, str): -- raise llvm.LLVMException, ret -+ raise llvm.LLVMException(ret) - return core.Module(ret) - - @property ---- .\llvm\passes.py (original) -+++ .\llvm\passes.py (refactored) -@@ -245,8 +245,7 @@ - elif tgt_data_or_pass_id in _pass_creator: - self._add_pass(tgt_data_or_pass_id) - else: -- raise llvm.LLVMException, \ -- ("invalid pass_id (%s)" % str(tgt_data_or_pass_id)) -+ raise llvm.LLVMException("invalid pass_id (%s)" % str(tgt_data_or_pass_id)) - - def _add_target_data(self, tgt): - _core.LLVMAddTargetData(tgt.ptr, self.ptr) ---- .\test\JITTutorial1.py (original) -+++ .\test\JITTutorial1.py (refactored) -@@ -28,4 +28,4 @@ - - bldr.ret (tmp_2) - --print module -+print(module) ---- .\test\JITTutorial2.py (original) -+++ .\test\JITTutorial2.py (refactored) -@@ -47,4 +47,4 @@ - recur_2 = bldr.call (gcd, (x_sub_y, y,), "tmp") - bldr.ret (recur_2) - --print module -+print(module) ---- .\test\asm.py (original) -+++ .\test\asm.py (refactored) -@@ -9,9 +9,9 @@ - - # write it's assembly representation to a file - asm = str(m) --print >> file("/tmp/testasm.ll", "w"), asm -+print(asm, file=file("/tmp/testasm.ll", "w")) - - # read it back into a module - m2 = Module.from_assembly(file("/tmp/testasm.ll")) --print m2 -+print(m2) - ---- .\test\call-jit-ctypes.py (original) -+++ .\test\call-jit-ctypes.py (refactored) -@@ -42,7 +42,7 @@ - - if 0: - # print the created module -- print my_module -+ print(my_module) - - # compile the function - ee = ExecutionEngine.new(my_module) ---- .\test\example-jit.py (original) -+++ .\test\example-jit.py (refactored) -@@ -29,5 +29,5 @@ - retval = ee.run_function(f_sum, [arg1, arg2]) - - # The return value is also GenericValue. Let's print it. --print "returned", retval.as_int() -+print("returned", retval.as_int()) - ---- .\test\example.py (original) -+++ .\test\example.py (refactored) -@@ -41,5 +41,5 @@ - - # We've completed the definition now! Let's see the LLVM assembly - # language representation of what we've created: --print my_module -+print(my_module) - ---- .\test\intrinsic.py (original) -+++ .\test\intrinsic.py (refactored) -@@ -16,7 +16,7 @@ - val = Constant.int(Type.int(), 42) - bswap = Function.intrinsic(mod, INTR_BSWAP, [Type.int()]) - b.call(bswap, [val]) --print mod -+print(mod) - - # the output is: - # -@@ -50,7 +50,7 @@ - onemc2 = b.sub(one, cos2, "onemc2") - sin = b.call(sqrt, [onemc2], "sin") - b.ret(sin) --print mod -+print(mod) - - # - # ; ModuleID = 'test' ---- .\test\objcache.py (original) -+++ .\test\objcache.py (refactored) -@@ -4,17 +4,17 @@ - - def check(a, b): - if a is b: -- print "OK" -+ print("OK") - else: -- print "FAIL" -+ print("FAIL") - - def check_isnot(a, b): - if not (a is b): -- print "OK" -+ print("OK") - else: -- print "FAIL" -+ print("FAIL") - --print "Testing module aliasing ..", -+print("Testing module aliasing ..", end=' ') - m1 = Module.new('a') - t = Type.int() - ft = Type.function(t, [t]) -@@ -22,75 +22,75 @@ - m2 = f1.module - check(m1, m2) - --print "Testing global vairable aliasing 1 .. ", -+print("Testing global vairable aliasing 1 .. ", end=' ') - gv1 = GlobalVariable.new(m1, t, "gv") - gv2 = GlobalVariable.get(m1, "gv") - check(gv1, gv2) - --print "Testing global vairable aliasing 2 .. ", -+print("Testing global vairable aliasing 2 .. ", end=' ') - gv3 = m1.global_variables[0] - check(gv1, gv3) - --print "Testing global vairable aliasing 3 .. ", -+print("Testing global vairable aliasing 3 .. ", end=' ') - gv2 = None - gv3 = None - gv1.delete() - gv4 = GlobalVariable.new(m1, t, "gv") - check_isnot(gv1, gv4) - --print "Testing function aliasing 1 ..", -+print("Testing function aliasing 1 ..", end=' ') - b1 = f1.append_basic_block('entry') - f2 = b1.function - check(f1, f2) - --print "Testing function aliasing 2 ..", -+print("Testing function aliasing 2 ..", end=' ') - f3 = m1.get_function_named("func") - check(f1, f3) - --print "Testing function aliasing 3 ..", -+print("Testing function aliasing 3 ..", end=' ') - f4 = Function.get_or_insert(m1, ft, "func") - check(f1, f4) - --print "Testing function aliasing 4 ..", -+print("Testing function aliasing 4 ..", end=' ') - f5 = Function.get(m1, "func") - check(f1, f5) - --print "Testing function aliasing 5 ..", -+print("Testing function aliasing 5 ..", end=' ') - f6 = m1.get_or_insert_function(ft, "func") - check(f1, f6) - --print "Testing function aliasing 6 ..", -+print("Testing function aliasing 6 ..", end=' ') - f7 = m1.functions[0] - check(f1, f7) - --print "Testing argument aliasing .. ", -+print("Testing argument aliasing .. ", end=' ') - a1 = f1.args[0] - a2 = f1.args[0] - check(a1, a2) - --print "Testing basic block aliasing 1 .. ", -+print("Testing basic block aliasing 1 .. ", end=' ') - b2 = f1.basic_blocks[0] - check(b1, b2) - --print "Testing basic block aliasing 2 .. ", -+print("Testing basic block aliasing 2 .. ", end=' ') - b3 = f1.get_entry_basic_block() - check(b1, b3) - --print "Testing basic block aliasing 3 .. ", -+print("Testing basic block aliasing 3 .. ", end=' ') - b31 = f1.entry_basic_block - check(b1, b31) - --print "Testing basic block aliasing 4 .. ", -+print("Testing basic block aliasing 4 .. ", end=' ') - bldr = Builder.new(b1) - b4 = bldr.basic_block - check(b1, b4) - --print "Testing basic block aliasing 5 .. ", -+print("Testing basic block aliasing 5 .. ", end=' ') - i1 = bldr.ret_void() - b5 = i1.basic_block - check(b1, b5) - --print "Testing instruction aliasing 1 .. ", -+print("Testing instruction aliasing 1 .. ", end=' ') - i2 = b5.instructions[0] - check(i1, i2) - -@@ -100,9 +100,9 @@ - v2 = phi.get_incoming_value(0) - b6 = phi.get_incoming_block(0) - --print "Testing PHI / basic block aliasing 5 .. ", -+print("Testing PHI / basic block aliasing 5 .. ", end=' ') - check(b1, b6) - --print "Testing PHI / value aliasing .. ", -+print("Testing PHI / value aliasing .. ", end=' ') - check(f1.args[0], v2) - ---- .\test\operands.py (original) -+++ .\test\operands.py (refactored) -@@ -28,9 +28,9 @@ - def __init__(self): pass - def read(self): return test_module - m = Module.from_assembly(strstream()) --print "-"*60 --print m --print "-"*60 -+print("-"*60) -+print(m) -+print("-"*60) - - test_func = m.get_function_named("test_func") - prod = m.get_function_named("prod") -@@ -38,16 +38,16 @@ - #===----------------------------------------------------------------------=== - # test operands - --print -+print() - i1 = test_func.basic_blocks[0].instructions[0] - i2 = test_func.basic_blocks[0].instructions[1] --print "Testing User.operand_count ..", -+print("Testing User.operand_count ..", end=' ') - if i1.operand_count == 3 and i2.operand_count == 2: -- print "OK" -+ print("OK") - else: -- print "FAIL" -+ print("FAIL") - --print "Testing User.operands ..", -+print("Testing User.operands ..", end=' ') - c1 = i1.operands[0] is prod - c2 = i1.operands[1] is test_func.args[0] - c3 = i1.operands[2] is test_func.args[1] -@@ -56,22 +56,22 @@ - c6 = len(i1.operands) == 3 - c7 = len(i2.operands) == 2 - if c1 and c2 and c3 and c5 and c6 and c7: -- print "OK" -+ print("OK") - else: -- print "FAIL" --print -+ print("FAIL") -+print() - - #===----------------------------------------------------------------------=== - # show test_function - --print "Examining test_function `test_test_func':" -+print("Examining test_function `test_test_func':") - idx = 1 - for inst in test_func.basic_blocks[0].instructions: -- print "Instruction #%d:" % (idx,) -- print " operand_count =", inst.operand_count -- print " operands:" -+ print("Instruction #%d:" % (idx,)) -+ print(" operand_count =", inst.operand_count) -+ print(" operands:") - oidx = 1 - for op in inst.operands: -- print " %d: %s" % (oidx, repr(op)) -+ print(" %d: %s" % (oidx, repr(op))) - oidx += 1 - idx += 1 ---- .\test\passes.py (original) -+++ .\test\passes.py (refactored) -@@ -36,8 +36,8 @@ - } - """ - m = Module.from_assembly(strstream(asm)) --print "-"*72 --print m -+print("-"*72) -+print(m) - - # Let's run a module-level inlining pass. First, create a pass manager. - pm = PassManager.new() -@@ -55,8 +55,8 @@ - del pm - - # Print the result. Note the change in @test2. --print "-"*72 --print m -+print("-"*72) -+print(m) - - - # Let's run a DCE pass on the the function 'test1' now. First create a -@@ -73,5 +73,5 @@ - fpm.run( m.get_function_named('test1') ) - - # Print the result. Note the change in @test1. --print "-"*72 --print m -+print("-"*72) -+print(m) ---- .\test\test.py (original) -+++ .\test\test.py (refactored) -@@ -69,7 +69,7 @@ - - # done - if gc.garbage: -- print "garbage = ", gc.garbage -+ print("garbage = ", gc.garbage) - - - main() ---- .\test\testall.py (original) -+++ .\test\testall.py (refactored) -@@ -15,12 +15,12 @@ - - - def do_llvmexception(): -- print " Testing class LLVMException" -+ print(" Testing class LLVMException") - e = LLVMException() - - - def do_ownable(): -- print " Testing class Ownable" -+ print(" Testing class Ownable") - o = Ownable(None, lambda x: None) - try: - o._own(None) -@@ -30,7 +30,7 @@ - - - def do_misc(): -- print " Testing miscellaneous functions" -+ print(" Testing miscellaneous functions") - try: - load_library_permanently("/usr/lib/libm.so") - except LLVMException: -@@ -42,14 +42,14 @@ - - - def do_llvm(): -- print " Testing module llvm" -+ print(" Testing module llvm") - do_llvmexception() - do_ownable() - do_misc() - - - def do_module(): -- print " Testing class Module" -+ print(" Testing class Module") - m = Module.new('test') - m.target = 'a' - a = m.target -@@ -101,7 +101,7 @@ - - - def do_type(): -- print " Testing class Type" -+ print(" Testing class Type") - for i in range(1,100): - Type.int(i) - Type.float() -@@ -151,14 +151,14 @@ - - - def do_typehandle(): -- print " Testing class TypeHandle" -+ print(" Testing class TypeHandle") - th = TypeHandle.new(Type.opaque()) - ts = Type.struct([ Type.int(), Type.pointer(th.type) ]) - th.type.refine(ts) - - - def do_value(): -- print " Testing class Value" -+ print(" Testing class Value") - k = Constant.int(ti, 42) - k.name = 'a' - s = k.name -@@ -186,7 +186,7 @@ - - - def do_constant(): -- print " Testing class Constant" -+ print(" Testing class Constant") - Constant.null(ti) - Constant.all_ones(ti) - Constant.undef(ti) -@@ -231,7 +231,7 @@ - - - def do_global_value(): -- print " Testing class GlobalValue" -+ print(" Testing class GlobalValue") - m = Module.new('a') - gv = GlobalVariable.new(m, Type.int(), 'b') - s = gv.is_declaration -@@ -247,7 +247,7 @@ - - - def do_global_variable(): -- print " Testing class GlobalVariable" -+ print(" Testing class GlobalVariable") - m = Module.new('a') - gv = GlobalVariable.new(m, Type.int(), 'b') - gv = GlobalVariable.get(m, 'b') -@@ -260,7 +260,7 @@ - - - def do_argument(): -- print " Testing class Argument" -+ print(" Testing class Argument") - m = Module.new('a') - ft = Type.function(ti, [ti]) - f = Function.new(m, ft, 'func') -@@ -272,7 +272,7 @@ - - - def do_function(): -- print " Testing class Function" -+ print(" Testing class Function") - ft = Type.function(ti, [ti]*20) - zz = Function.new(Module.new('z'), ft, 'foobar') - del zz -@@ -307,7 +307,7 @@ - - - def do_instruction(): -- print " Testing class Instruction" -+ print(" Testing class Instruction") - m = Module.new('a') - ft = Type.function(ti, [ti]*20) - f = Function.new(m, ft, 'func') -@@ -320,7 +320,7 @@ - - - def do_callorinvokeinstruction(): -- print " Testing class CallOrInvokeInstruction" -+ print(" Testing class CallOrInvokeInstruction") - m = Module.new('a') - ft = Type.function(ti, [ti]) - f = Function.new(m, ft, 'func') -@@ -337,7 +337,7 @@ - - - def do_phinode(): -- print " Testing class PhiNode" -+ print(" Testing class PhiNode") - m = Module.new('a') - ft = Type.function(ti, [ti]) - f = Function.new(m, ft, 'func') -@@ -354,7 +354,7 @@ - - - def do_switchinstruction(): -- print " Testing class SwitchInstruction" -+ print(" Testing class SwitchInstruction") - m = Module.new('a') - ft = Type.function(ti, [ti]) - f = Function.new(m, ft, 'func') -@@ -365,7 +365,7 @@ - - - def do_basicblock(): -- print " Testing class BasicBlock" -+ print(" Testing class BasicBlock") - m = Module.new('a') - ft = Type.function(ti, [ti]) - f = Function.new(m, ft, 'func') -@@ -395,7 +395,7 @@ - - - def do_builder(): -- print " Testing class Builder" -+ print(" Testing class Builder") - m = Module.new('a') - ft = Type.function(ti, [ti]) - f = Function.new(m, ft, 'func') -@@ -488,7 +488,7 @@ - - - def do_llvm_core(): -- print " Testing module llvm.core" -+ print(" Testing module llvm.core") - do_module() - do_type() - do_typehandle() -@@ -508,7 +508,7 @@ - - - def do_targetdata(): -- print " Testing class TargetData" -+ print(" Testing class TargetData") - t = TargetData.new('') - v = str(t) - v = t.byte_order -@@ -530,7 +530,7 @@ - - - def do_genericvalue(): -- print " Testing class GenericValue" -+ print(" Testing class GenericValue") - v = GenericValue.int(ti, 1) - v = GenericValue.int_signed(ti, 1) - v = GenericValue.real(Type.float(), 3.14) -@@ -540,7 +540,7 @@ - - - def do_executionengine(): -- print " Testing class ExecutionEngine" -+ print(" Testing class ExecutionEngine") - m = Module.new('a') - ee = ExecutionEngine.new(m, True) - ft = Type.function(ti, []) -@@ -567,14 +567,14 @@ - - - def do_llvm_ee(): -- print " Testing module llvm.ee" -+ print(" Testing module llvm.ee") - do_targetdata() - do_genericvalue() - do_executionengine() - - - def do_passmanager(): -- print " Testing class PassManager" -+ print(" Testing class PassManager") - pm = PassManager.new() - pm.add(TargetData.new('')) - for i in [getattr(llvm.passes, x) for x in \ -@@ -586,7 +586,7 @@ - - - def do_functionpassmanager(): -- print " Testing class FunctionPassManager" -+ print(" Testing class FunctionPassManager") - m = Module.new('a') - ft = Type.function(ti, []) - f = m.add_function(ft, 'func') -@@ -602,13 +602,13 @@ - - - def do_llvm_passes(): -- print " Testing module llvm.passes" -+ print(" Testing module llvm.passes") - do_passmanager() - do_functionpassmanager() - - - def main(): -- print "Testing package llvm" -+ print("Testing package llvm") - do_llvm() - do_llvm_core() - do_llvm_ee() ---- .\test\testattrs.py (original) -+++ .\test\testattrs.py (refactored) -@@ -1,7 +1,7 @@ - #!/usr/bin/env python - - from llvm.core import * --from cStringIO import StringIO -+from io import StringIO - - - def make_module(): ---- .\test\typehandle.py (original) -+++ .\test\typehandle.py (refactored) -@@ -16,4 +16,4 @@ - m.add_type_name("struct.node", th.type) - - # show what we created --print m -+print(m) ---- .\test\uses.py (original) -+++ .\test\uses.py (refactored) -@@ -13,11 +13,11 @@ - tmp3 = bld.add(tmp1, f.args[2], "tmp3") - bld.ret(tmp3) - --print "-"*60 --print m --print "-"*60 -+print("-"*60) -+print(m) -+print("-"*60) - --print "Testing use count ..", -+print("Testing use count ..", end=' ') - c1 = f.args[0].use_count == 1 - c2 = f.args[1].use_count == 1 - c3 = f.args[2].use_count == 1 -@@ -25,11 +25,11 @@ - c5 = tmp2.use_count == 0 - c6 = tmp3.use_count == 1 - if c1 and c2 and c3 and c4 and c5 and c6: -- print "OK" -+ print("OK") - else: -- print "FAIL" -+ print("FAIL") - --print "Testing uses ..", -+print("Testing uses ..", end=' ') - c1 = f.args[0].uses[0] is tmp1 - c2 = len(f.args[0].uses) == 1 - c3 = f.args[1].uses[0] is tmp2 -@@ -40,6 +40,6 @@ - c8 = len(tmp2.uses) == 0 - c9 = len(tmp3.uses) == 1 - if c1 and c2 and c3 and c4 and c5 and c6 and c7 and c8 and c9: -- print "OK" -+ print("OK") - else: -- print "FAIL" -+ print("FAIL") ---- .\tools\intrgen.py (original) -+++ .\tools\intrgen.py (refactored) -@@ -26,7 +26,7 @@ - idx = 1 - for i in intr: - s = 'INTR_' + i.upper() -- print '%s = %d' % (s.ljust(maxw), idx) -+ print('%s = %d' % (s.ljust(maxw), idx)) - idx += 1 - - gen(sys.argv[1]) ---- .\tools\intrs_for_doc.py (original) -+++ .\tools\intrs_for_doc.py (refactored) -@@ -21,5 +21,5 @@ - outf = open(OUTF, 'wt') - i = 0 - while i < len(intrs): -- print >>outf, "`" + "`,`".join(intrs[i:min(i+NCOLS,len(intrs)+1)]) + "`" -+ print("`" + "`,`".join(intrs[i:min(i+NCOLS,len(intrs)+1)]) + "`", file=outf) - i += NCOLS ---- .\www\makeweb.py (original) -+++ .\www\makeweb.py (refactored) -@@ -52,7 +52,7 @@ - - - def _rmtree_warn(fn, path, excinfo): -- print "** WARNING **: error while doing %s on %s" % (fn, path) -+ print("** WARNING **: error while doing %s on %s" % (fn, path)) - - - def _can_skip(opts, infile, outfile): -@@ -67,14 +67,14 @@ - cmd = cmdfn(opts, infile, outfile_actual) - if _can_skip(opts, infile, outfile_actual): - if opts.verbose >= 2: -- print "up to date %s -> %s" % (infile, outfile_actual) -+ print("up to date %s -> %s" % (infile, outfile_actual)) - return - if cmd: - # do cmd - if opts.verbose: -- print "process %s -> %s" % (infile, outfile_actual) -+ print("process %s -> %s" % (infile, outfile_actual)) - if opts.verbose >= 3: -- print "command is [%s]" % cmd -+ print("command is [%s]" % cmd) - if not opts.dryrun: - os.system(cmd) - # else if cmd is None, do nothing -@@ -83,7 +83,7 @@ - # nothing matched, default action is to copy - if not _can_skip(opts, infile, outfile): - if opts.verbose: -- print "copying %s -> %s" % (infile, outfile) -+ print("copying %s -> %s" % (infile, outfile)) - if not opts.dryrun: - shutil.copy(infile, outfile) - -@@ -95,14 +95,14 @@ - - # if it exists, it must be a dir! - if odexists and not os.path.isdir(outdir): -- print "** WARNING **: output dir '%s' exists but is " \ -- "not a dir, skipping" % outdir -+ print("** WARNING **: output dir '%s' exists but is " \ -+ "not a dir, skipping" % outdir) - return - - # make outdir if not existing - if not odexists: - if opts.verbose: -- print "creating %s" % outdir -+ print("creating %s" % outdir) - if not opts.dryrun: - os.mkdir(outdir) - -@@ -114,8 +114,8 @@ - # process files - if os.path.isfile(inp): - if os.path.exists(outp) and not os.path.isfile(outp): -- print "** WARNING **: output '%s' corresponding to " \ -- "input '%s' is not a file, skipping" % (outp, inp) -+ print("** WARNING **: output '%s' corresponding to " \ -+ "input '%s' is not a file, skipping" % (outp, inp)) - else: - process_file(opts, inp, outp) - -@@ -124,15 +124,15 @@ - # if dir is in skip list, silently ignore - if elem in DIR_SKIP_TBL: - if opts.verbose >= 3: -- print "skipping %s" % inp -+ print("skipping %s" % inp) - continue - # just recurse - make(opts, inp, outp) - - # neither a file nor a dir - else: -- print "** WARNING **: input '%s' is neither file nor " \ -- "dir, skipping" % inp -+ print("** WARNING **: input '%s' is neither file nor " \ -+ "dir, skipping" % inp) - - - def get_opts(): -@@ -173,14 +173,14 @@ - def main(): - opts, src, dest = get_opts() - if opts.verbose >= 3: -- print ("running with options:\nsrc = [%s]\ndest = [%s]\nverbose = [%d]\n" +\ -+ print(("running with options:\nsrc = [%s]\ndest = [%s]\nverbose = [%d]\n" +\ - "dry-run = [%d]\nclean-first = [%d]\nforce = [%d]") %\ -- (src, dest, opts.verbose, opts.dryrun, opts.clean, opts.force) -+ (src, dest, opts.verbose, opts.dryrun, opts.clean, opts.force)) - if opts.dryrun and opts.verbose == 0: - opts.verbose = 1 - if opts.clean: - if opts.dryrun or opts.verbose: -- print "removing tree %s" % dest -+ print("removing tree %s" % dest) - if not opts.dryrun: - os.rmtree(dest, True, _rmtree_warn) - make(opts, src, dest) diff --git a/llvm/py3k_update.output b/llvm/py3k_update.output deleted file mode 100644 index 4ea51a4..0000000 --- a/llvm/py3k_update.output +++ /dev/null @@ -1,62 +0,0 @@ -C:\Users\AndrewBC\src\llvm-py>python "C:\Program Files\Python27\Tools\Scripts\2to3.py" -w -f all -f idioms . > llvm/py3k_update.diff -RefactoringTool: Skipping implicit fixer: buffer -RefactoringTool: Skipping implicit fixer: set_literal -RefactoringTool: Skipping implicit fixer: ws_comma -RefactoringTool: Refactored .\setup-win32.py -RefactoringTool: Refactored .\setup.py -RefactoringTool: Refactored .\llvm\__init__.py -RefactoringTool: Refactored .\llvm\_util.py -RefactoringTool: Refactored .\llvm\core.py -RefactoringTool: Refactored .\llvm\ee.py -RefactoringTool: Refactored .\llvm\passes.py -RefactoringTool: Refactored .\test\JITTutorial1.py -RefactoringTool: Refactored .\test\JITTutorial2.py -RefactoringTool: Refactored .\test\asm.py -RefactoringTool: Refactored .\test\call-jit-ctypes.py -RefactoringTool: Refactored .\test\example-jit.py -RefactoringTool: Refactored .\test\example.py -RefactoringTool: Refactored .\test\intrinsic.py -RefactoringTool: Refactored .\test\objcache.py -RefactoringTool: Refactored .\test\operands.py -RefactoringTool: Refactored .\test\passes.py -RefactoringTool: Refactored .\test\test.py -RefactoringTool: Refactored .\test\testall.py -RefactoringTool: Refactored .\test\testattrs.py -RefactoringTool: Refactored .\test\typehandle.py -RefactoringTool: Refactored .\test\uses.py -RefactoringTool: Refactored .\tools\intrgen.py -RefactoringTool: Refactored .\tools\intrs_for_doc.py -RefactoringTool: Refactored .\www\makeweb.py -RefactoringTool: Can't parse .\www\src\examples\JITTutorial1.py: ParseError: bad input: type=17, value=u'/', context=('', (1, 2)) -RefactoringTool: Can't parse .\www\src\examples\JITTutorial2.py: ParseError: bad input: type=17, value=u'/', context=('', (1, 2)) -RefactoringTool: Files that need to be modified: -RefactoringTool: .\setup-win32.py -RefactoringTool: .\setup.py -RefactoringTool: .\llvm\__init__.py -RefactoringTool: .\llvm\_util.py -RefactoringTool: .\llvm\core.py -RefactoringTool: .\llvm\ee.py -RefactoringTool: .\llvm\passes.py -RefactoringTool: .\test\JITTutorial1.py -RefactoringTool: .\test\JITTutorial2.py -RefactoringTool: .\test\asm.py -RefactoringTool: .\test\call-jit-ctypes.py -RefactoringTool: .\test\example-jit.py -RefactoringTool: .\test\example.py -RefactoringTool: .\test\intrinsic.py -RefactoringTool: .\test\objcache.py -RefactoringTool: .\test\operands.py -RefactoringTool: .\test\passes.py -RefactoringTool: .\test\test.py -RefactoringTool: .\test\testall.py -RefactoringTool: .\test\testattrs.py -RefactoringTool: .\test\typehandle.py -RefactoringTool: .\test\uses.py -RefactoringTool: .\tools\intrgen.py -RefactoringTool: .\tools\intrs_for_doc.py -RefactoringTool: .\www\makeweb.py -RefactoringTool: There were 2 errors: -RefactoringTool: Can't parse .\www\src\examples\JITTutorial1.py: ParseError: bad input: type=17, value=u'/', context=('', (1, 2)) -RefactoringTool: Can't parse .\www\src\examples\JITTutorial2.py: ParseError: bad input: type=17, value=u'/', context=('', (1, 2)) - -C:\Users\AndrewBC\src\llvm-py> \ No newline at end of file diff --git a/llvm/tbaa.py b/llvm/tbaa.py deleted file mode 100644 index b510ce2..0000000 --- a/llvm/tbaa.py +++ /dev/null @@ -1,51 +0,0 @@ -from llvm.core import * - -class TBAABuilder(object): - '''Simplify creation of TBAA metadata. - - Each TBAABuidler object operates on a module. - User can create multiple TBAABuilder on a module - ''' - - def __init__(self, module, rootid): - ''' - module --- the module to use. - root --- string name to identify the TBAA root. - ''' - self.__module = module - self.__rootid = rootid - self.__rootmd = self.__new_md(rootid) - - @classmethod - def new(cls, module, rootid): - return cls(module, rootid) - - def get_node(self, name, parent=None, const=False): - '''Returns a MetaData object representing a TBAA node. - - Use loadstore_instruction.set_metadata('tbaa', node) to - bind a type to a memory. - ''' - parent = parent or self.root - const = Constant.int(Type.int(), int(bool(const))) - return self.__new_md(name, parent, const) - - @property - def module(self): - return self.__module - - @property - def root(self): - return self.__rootmd - - @property - def root_name(self): - return self.__rootid - - def __new_md(self, *args): - contents = list(args) - for i, v in enumerate(contents): - if isinstance(v, str): - contents[i] = MetaDataString.get(self.module, v) - return MetaData.get(self.module, contents) - diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py deleted file mode 100644 index 05b7d72..0000000 --- a/llvm/test_llvmpy.py +++ /dev/null @@ -1,1249 +0,0 @@ -""" -LLVM tests -""" -import os -import sys -import math -import shutil -import unittest -import subprocess -import tempfile -import contextlib - -is_py3k = bool(sys.version_info[0] == 3) -BITS = tuple.__itemsize__ * 8 - -if is_py3k: - from io import StringIO -else: - from cStringIO import StringIO - - -import llvm -from llvm.core import (Module, Type, GlobalVariable, Function, Builder, - Constant, MetaData, MetaDataString, inline_function) -from llvm.ee import EngineBuilder -import llvm.core as lc -import llvm.passes as lp -import llvm.ee as le - - -tests = [] - - -# --------------------------------------------------------------------------- - -if sys.version_info[:2] <= (2, 6): - # create custom TestCase - class TestCase(unittest.TestCase): - def assertIn(self, item, container): - self.assertTrue(item in container) - - def assertNotIn(self, item, container): - self.assertFalse(item in container) - - def assertLess(self, a, b): - self.assertTrue(a < b) - - def assertIs(self, a, b): - self.assertTrue(a is b) - - @contextlib.contextmanager - def assertRaises(self, exc): - try: - yield - except exc: - pass - else: - raise self.failureException("Did not raise %s" % exc) - -else: - TestCase = unittest.TestCase - - -# --------------------------------------------------------------------------- - -class TestAsm(TestCase): - def setUp(self): - self.tmpdir = tempfile.mkdtemp() - - def tearDown(self): - shutil.rmtree(self.tmpdir) - - def test_asm(self): - # 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) - - testasm_ll = os.path.join(self.tmpdir, 'testasm.ll') - with open(testasm_ll, "w") as fout: - fout.write(asm) - - # read it back into a module - with open(testasm_ll) as fin: - m2 = Module.from_assembly(fin) - # The default `m.id` is ''. - m2.id = m.id # Copy the name from `m` - - self.assertEqual(str(m2).strip(), asm.strip()) - - def test_bitcode(self): - # 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) - - testasm_bc = os.path.join(self.tmpdir, 'testasm.bc') - with open(testasm_bc, "wb") as fout: - m.to_bitcode(fout) - - # read it back into a module - with open(testasm_bc, "rb") as fin: - m2 = Module.from_bitcode(fin) - # The default `m.id` is ''. - m2.id = m.id # Copy the name from `m` - - self.assertEqual(str(m2).strip(), asm.strip()) - -tests.append(TestAsm) - -# --------------------------------------------------------------------------- - -class TestAttr(TestCase): - def make_module(self): - test_module = """ - define i32 @sum(i32, i32) { - entry: - %2 = add i32 %0, %1 - ret i32 %2 - } - """ - return Module.from_assembly(StringIO(test_module)) - - def test_align(self): - m = self.make_module() - f = m.get_function_named('sum') - f.args[0].alignment = 16 - self.assert_("align 16" in str(f)) - self.assertEqual(f.args[0].alignment, 16) - -tests.append(TestAttr) - -# --------------------------------------------------------------------------- - -class TestAtomic(TestCase): - orderings = ['unordered', 'monotonic', 'acquire', - 'release', 'acq_rel', 'seq_cst'] - - atomic_op = ['xchg', 'add', 'sub', 'and', 'nand', 'or', 'xor', - 'max', 'min', 'umax', 'umin'] - - def test_atomic_cmpxchg(self): - mod = Module.new('mod') - functype = Type.function(Type.void(), []) - func = mod.add_function(functype, name='foo') - bb = func.append_basic_block('entry') - bldr = Builder.new(bb) - ptr = bldr.alloca(Type.int()) - - old = bldr.load(ptr) - new = Constant.int(Type.int(), 1234) - - for ordering in self.orderings: - inst = bldr.atomic_cmpxchg(ptr, old, new, ordering) - self.assertEqual(ordering, str(inst).strip().split(' ')[-1]) - - inst = bldr.atomic_cmpxchg(ptr, old, new, ordering, crossthread=False) - self.assertEqual('singlethread', str(inst).strip().split(' ')[-2]) - - def test_atomic_rmw(self): - mod = Module.new('mod') - functype = Type.function(Type.void(), []) - func = mod.add_function(functype, name='foo') - bb = func.append_basic_block('entry') - bldr = Builder.new(bb) - ptr = bldr.alloca(Type.int()) - - old = bldr.load(ptr) - val = Constant.int(Type.int(), 1234) - - for ordering in self.orderings: - inst = bldr.atomic_rmw('xchg', ptr, val, ordering) - self.assertEqual(ordering, str(inst).split(' ')[-1]) - - for op in self.atomic_op: - inst = bldr.atomic_rmw(op, ptr, val, ordering) - self.assertEqual(op, str(inst).strip().split(' ')[3]) - - inst = bldr.atomic_rmw('xchg', ptr, val, ordering, crossthread=False) - self.assertEqual('singlethread', str(inst).strip().split(' ')[-2]) - - for op in self.atomic_op: - atomic_op = getattr(bldr, 'atomic_%s' % op) - inst = atomic_op(ptr, val, ordering) - self.assertEqual(op, str(inst).strip().split(' ')[3]) - - def test_atomic_ldst(self): - mod = Module.new('mod') - functype = Type.function(Type.void(), []) - func = mod.add_function(functype, name='foo') - bb = func.append_basic_block('entry') - bldr = Builder.new(bb) - ptr = bldr.alloca(Type.int()) - - val = Constant.int(Type.int(), 1234) - - for ordering in self.orderings: - loaded = bldr.atomic_load(ptr, ordering) - self.assert_('load atomic' in str(loaded)) - self.assertEqual(ordering, - str(loaded).strip().split(' ')[-3].rstrip(',')) - self.assert_('align 1' in str(loaded)) - - stored = bldr.atomic_store(loaded, ptr, ordering) - self.assert_('store atomic' in str(stored)) - self.assertEqual(ordering, - str(stored).strip().split(' ')[-3].rstrip(',')) - self.assert_('align 1' in str(stored)) - - fenced = bldr.fence(ordering) - self.assertEqual(['fence', ordering], - str(fenced).strip().split(' ')) - -tests.append(TestAtomic) - -# --------------------------------------------------------------------------- - -class TestConstExpr(TestCase): - - def test_constexpr_opcode(self): - mod = Module.new('test_constexpr_opcode') - func = mod.add_function(Type.function(Type.void(), []), name="foo") - builder = Builder.new(func.append_basic_block('entry')) - a = builder.inttoptr(Constant.int(Type.int(), 123), - Type.pointer(Type.int())) - self.assertTrue(isinstance(a, lc.ConstantExpr)) - self.assertEqual(a.opcode, lc.OPCODE_INTTOPTR) - self.assertEqual(a.opcode_name, "inttoptr") - -tests.append(TestConstExpr) - -# --------------------------------------------------------------------------- - -class TestOperands(TestCase): - # implement a test function - test_module = """ -define i32 @prod(i32, i32) { -entry: - %2 = mul i32 %0, %1 - ret i32 %2 -} - -define i32 @test_func(i32, i32, i32) { -entry: - %tmp1 = call i32 @prod(i32 %0, i32 %1) - %tmp2 = add i32 %tmp1, %2 - %tmp3 = add i32 %tmp2, 1 - %tmp4 = add i32 %tmp3, -1 - %tmp5 = add i64 -81985529216486895, 12297829382473034410 - ret i32 %tmp4 -} -""" - def test_operands(self): - m = Module.from_assembly(StringIO(self.test_module)) - - test_func = m.get_function_named("test_func") - prod = m.get_function_named("prod") - - # test operands - i1 = test_func.basic_blocks[0].instructions[0] - i2 = test_func.basic_blocks[0].instructions[1] - i3 = test_func.basic_blocks[0].instructions[2] - i4 = test_func.basic_blocks[0].instructions[3] - i5 = test_func.basic_blocks[0].instructions[4] - - self.assertEqual(i1.operand_count, 3) - self.assertEqual(i2.operand_count, 2) - - self.assertEqual(i3.operands[1].z_ext_value, 1) - self.assertEqual(i3.operands[1].s_ext_value, 1) - self.assertEqual(i4.operands[1].z_ext_value, 0xffffffff) - self.assertEqual(i4.operands[1].s_ext_value, -1) - self.assertEqual(i5.operands[0].s_ext_value, -81985529216486895) - self.assertEqual(i5.operands[1].z_ext_value, 12297829382473034410) - - self.assert_(i1.operands[-1] is prod) - self.assert_(i1.operands[0] is test_func.args[0]) - self.assert_(i1.operands[1] is test_func.args[1]) - self.assert_(i2.operands[0] is i1) - self.assert_(i2.operands[1] is test_func.args[2]) - self.assertEqual(len(i1.operands), 3) - self.assertEqual(len(i2.operands), 2) - - self.assert_(i1.called_function is prod) - -tests.append(TestOperands) - -# --------------------------------------------------------------------------- - -class TestPasses(TestCase): - # Create a module. - asm = """ - -define i32 @test() nounwind { - ret i32 42 -} - -define i32 @test1() nounwind { -entry: - %tmp = alloca i32 - store i32 42, i32* %tmp, align 4 - %tmp1 = load i32* %tmp, align 4 - %tmp2 = call i32 @test() - %tmp3 = load i32* %tmp, align 4 - %tmp4 = load i32* %tmp, align 4 - ret i32 %tmp1 -} - -define i32 @test2() nounwind { -entry: - %tmp = call i32 @test() - ret i32 %tmp -} -""" - def test_passes(self): - m = Module.from_assembly(StringIO(self.asm)) - - fn_test1 = m.get_function_named('test1') - fn_test2 = m.get_function_named('test2') - - original_test1 = str(fn_test1) - original_test2 = str(fn_test2) - - # Let's run a module-level inlining pass. First, create a pass manager. - pm = lp.PassManager.new() - - # Add the target data as the first "pass". This is mandatory. - pm.add(le.TargetData.new('')) - - # Add the inlining pass. - pm.add(lp.PASS_INLINE) - - # Run it! - pm.run(m) - - # Done with the pass manager. - del pm - - # Make sure test2 is inlined - self.assertNotEqual(str(fn_test2).strip(), original_test2.strip()) - - bb_entry = fn_test2.basic_blocks[0] - - self.assertEqual(len(bb_entry.instructions), 1) - self.assertEqual(bb_entry.instructions[0].opcode_name, 'ret') - - # Let's run a DCE pass on the the function 'test1' now. First create a - # function pass manager. - fpm = lp.FunctionPassManager.new(m) - - # Add the target data as first "pass". This is mandatory. - fpm.add(le.TargetData.new('')) - - # Add a DCE pass - fpm.add(lp.PASS_ADCE) - - # Run the pass on the function 'test1' - fpm.run(m.get_function_named('test1')) - - # Make sure test1 is modified - self.assertNotEqual(str(fn_test1).strip(), original_test1.strip()) - - def test_passes_with_pmb(self): - m = Module.from_assembly(StringIO(self.asm)) - - fn_test1 = m.get_function_named('test1') - fn_test2 = m.get_function_named('test2') - - original_test1 = str(fn_test1) - original_test2 = str(fn_test2) - - # Try out the PassManagerBuilder - - pmb = lp.PassManagerBuilder.new() - - self.assertEqual(pmb.opt_level, 2) # ensure default is level 2 - pmb.opt_level = 3 - self.assertEqual(pmb.opt_level, 3) # make sure it works - - self.assertEqual(pmb.size_level, 0) # ensure default is level 0 - pmb.size_level = 2 - self.assertEqual(pmb.size_level, 2) # make sure it works - - self.assertFalse(pmb.vectorize) # ensure default is False - pmb.vectorize = True - self.assertTrue(pmb.vectorize) # make sure it works - - # make sure the default is False - self.assertFalse(pmb.disable_unit_at_a_time) - self.assertFalse(pmb.disable_unroll_loops) - self.assertFalse(pmb.disable_simplify_lib_calls) - - # Do function pass - fpm = lp.FunctionPassManager.new(m) - pmb.populate(fpm) - fpm.run(fn_test1) - - # Make sure test1 has changed - self.assertNotEqual(str(fn_test1).strip(), original_test1.strip()) - - # Do module pass - pm = lp.PassManager.new() - pmb.populate(pm) - pm.run(m) - - # Make sure test2 has changed - self.assertNotEqual(str(fn_test2).strip(), original_test2.strip()) - - def test_dump_passes(self): - self.assertTrue(len(lp.PASSES)>0, msg="Cannot have no passes") - -tests.append(TestPasses) - -# --------------------------------------------------------------------------- - -class TestEngineBuilder(TestCase): - - def make_test_module(self): - module = Module.new("testmodule") - fnty = Type.function(Type.int(), []) - function = module.add_function(fnty, 'foo') - bb_entry = function.append_basic_block('entry') - builder = Builder.new(bb_entry) - builder.ret(Constant.int(Type.int(), 0xcafe)) - module.verify() - return module - - def run_foo(self, ee, module): - function = module.get_function_named('foo') - retval = ee.run_function(function, []) - self.assertEqual(retval.as_int(), 0xcafe) - - - def test_enginebuilder_basic(self): - module = self.make_test_module() - ee = EngineBuilder.new(module).create() - - with self.assertRaises(llvm.LLVMException): - # Ensure the module is owned. - llvm._util.check_is_unowned(module) - - self.run_foo(ee, module) - - - def test_enginebuilder_with_tm(self): - tm = le.TargetMachine.new() - module = self.make_test_module() - ee = EngineBuilder.new(module).create(tm) - - with self.assertRaises(llvm.LLVMException): - # Ensure the targetmachine is owned. - llvm._util.check_is_unowned(tm) - - - with self.assertRaises(llvm.LLVMException): - # Ensure the module is owned. - llvm._util.check_is_unowned(module) - - self.run_foo(ee, module) - - def test_enginebuilder_force_jit(self): - module = self.make_test_module() - ee = EngineBuilder.new(module).force_jit().create() - - self.run_foo(ee, module) - - def test_enginebuilder_force_interpreter(self): - module = self.make_test_module() - ee = EngineBuilder.new(module).force_interpreter().create() - - self.run_foo(ee, module) - - def test_enginebuilder_opt(self): - module = self.make_test_module() - ee = EngineBuilder.new(module).opt(3).create() - - self.run_foo(ee, module) - -tests.append(TestEngineBuilder) - -# --------------------------------------------------------------------------- - -class TestExecutionEngine(TestCase): - def test_get_pointer_to_global(self): - module = lc.Module.new(str(self)) - gvar = module.add_global_variable(Type.int(), 'hello') - X = 1234 - gvar.initializer = lc.Constant.int(Type.int(), X) - - ee = le.ExecutionEngine.new(module) - ptr = ee.get_pointer_to_global(gvar) - from ctypes import c_void_p, cast, c_int, POINTER - casted = cast(c_void_p(ptr), POINTER(c_int)) - self.assertEqual(X, casted[0]) - - def test_add_global_mapping(self): - module = lc.Module.new(str(self)) - gvar = module.add_global_variable(Type.int(), 'hello') - - fnty = lc.Type.function(Type.int(), []) - foo = module.add_function(fnty, name='foo') - bldr = lc.Builder.new(foo.append_basic_block('entry')) - bldr.ret(bldr.load(gvar)) - - ee = le.ExecutionEngine.new(module) - from ctypes import c_int, addressof, CFUNCTYPE - value = 0xABCD - value_ctype = c_int(value) - value_pointer = addressof(value_ctype) - - ee.add_global_mapping(gvar, value_pointer) - - foo_addr = ee.get_pointer_to_function(foo) - prototype = CFUNCTYPE(c_int) - foo_callable = prototype(foo_addr) - self.assertEqual(foo_callable(), value) - - - -tests.append(TestExecutionEngine) -# --------------------------------------------------------------------------- - -class TestObjCache(TestCase): - - def test_objcache(self): - # Testing module aliasing - m1 = Module.new('a') - t = Type.int() - ft = Type.function(t, [t]) - f1 = m1.add_function(ft, "func") - m2 = f1.module - self.assert_(m1 is m2) - - # Testing global vairable aliasing 1 - gv1 = GlobalVariable.new(m1, t, "gv") - gv2 = GlobalVariable.get(m1, "gv") - self.assert_(gv1 is gv2) - - # Testing global vairable aliasing 2 - gv3 = m1.global_variables[0] - self.assert_(gv1 is gv3) - - # Testing global vairable aliasing 3 - gv2 = None - gv3 = None - - gv1.delete() - gv4 = GlobalVariable.new(m1, t, "gv") - - self.assert_(gv1 is not gv4) - - # Testing function aliasing 1 - b1 = f1.append_basic_block('entry') - f2 = b1.function - self.assert_(f1 is f2) - - # Testing function aliasing 2 - f3 = m1.get_function_named("func") - self.assert_(f1 is f3) - - # Testing function aliasing 3 - f4 = Function.get_or_insert(m1, ft, "func") - self.assert_(f1 is f4) - - # Testing function aliasing 4 - f5 = Function.get(m1, "func") - self.assert_(f1 is f5) - - # Testing function aliasing 5 - f6 = m1.get_or_insert_function(ft, "func") - self.assert_(f1 is f6) - - # Testing function aliasing 6 - f7 = m1.functions[0] - self.assert_(f1 is f7) - - # Testing argument aliasing - a1 = f1.args[0] - a2 = f1.args[0] - self.assert_(a1 is a2) - - # Testing basic block aliasing 1 - b2 = f1.basic_blocks[0] - self.assert_(b1 is b2) - - # Testing basic block aliasing 2 - b3 = f1.get_entry_basic_block() - self.assert_(b1 is b3) - - # Testing basic block aliasing 3 - b31 = f1.entry_basic_block - self.assert_(b1 is b31) - - # Testing basic block aliasing 4 - bldr = Builder.new(b1) - b4 = bldr.basic_block - self.assert_(b1 is b4) - - # Testing basic block aliasing 5 - i1 = bldr.ret_void() - b5 = i1.basic_block - self.assert_(b1 is b5) - - # Testing instruction aliasing 1 - i2 = b5.instructions[0] - self.assert_(i1 is i2) - - # phi node - phi = bldr.phi(t) - phi.add_incoming(f1.args[0], b1) - v2 = phi.get_incoming_value(0) - b6 = phi.get_incoming_block(0) - - # Testing PHI / basic block aliasing 5 - self.assert_(b1 is b6) - - # Testing PHI / value aliasing - self.assert_(f1.args[0] is v2) - -tests.append(TestObjCache) - -# --------------------------------------------------------------------------- - -class TestTargetMachines(TestCase): - '''Exercise target machines - - Require PTX backend - ''' - def test_native(self): - m, _ = self._build_module() - tm = le.EngineBuilder.new(m).select_target() - - self.assertTrue(tm.target_name) - self.assertTrue(tm.target_data) - self.assertTrue(tm.target_short_description) - self.assertTrue(tm.triple) - self.assertIn('foo', tm.emit_assembly(m).decode('utf-8')) - self.assertTrue(le.get_host_cpu_name()) - - def test_ptx(self): - if lc.HAS_PTX: - arch = 'ptx64' - elif lc.HAS_NVPTX: - arch = 'nvptx64' - else: - return # skip this test - m, func = self._build_module() - func.calling_convention = lc.CC_PTX_KERNEL # set calling conv - ptxtm = le.TargetMachine.lookup(arch=arch, cpu='compute_20') - self.assertTrue(ptxtm.triple) - self.assertTrue(ptxtm.cpu) - ptxasm = ptxtm.emit_assembly(m).decode('utf-8') - self.assertIn('foo', ptxasm) - if lc.HAS_NVPTX: - self.assertIn('.address_size 64', ptxasm) - self.assertIn('compute_20', ptxasm) - - def _build_module(self): - m = Module.new('TestTargetMachines') - - fnty = Type.function(Type.void(), []) - func = m.add_function(fnty, name='foo') - - bldr = Builder.new(func.append_basic_block('entry')) - bldr.ret_void() - m.verify() - return m, func - - def _build_bad_archname(self): - with self.assertRaises(RuntimeError): - tm = TargetMachine.lookup("ain't no arch name") - -tests.append(TestTargetMachines) - -# --------------------------------------------------------------------------- - -class TestNative(TestCase): - def setUp(self): - self.tmpdir = tempfile.mkdtemp() - - def tearDown(self): - shutil.rmtree(self.tmpdir) - - - def _make_module(self): - m = Module.new('module1') - m.add_global_variable(Type.int(), 'i') - - fty = Type.function(Type.int(), []) - f = m.add_function(fty, name='main') - - bldr = Builder.new(f.append_basic_block('entry')) - bldr.ret(Constant.int(Type.int(), 0xab)) - - return m - - def _compile(self, src): - dst = os.path.join(self.tmpdir, 'llvmobj.out') - s = subprocess.call(['cc', '-o', dst, src]) - if s != 0: - raise Exception("Cannot compile") - - s = subprocess.call([dst]) - self.assertEqual(s, 0xab) - - def test_assembly(self): - if sys.platform == 'darwin': - # skip this test on MacOSX for now - return - - m = self._make_module() - output = m.to_native_assembly() - - src = os.path.join(self.tmpdir, 'llvmasm.s') - with open(src, 'wb') as fout: - fout.write(output) - - self._compile(src) - - def test_object(self): - if sys.platform == 'darwin': - # skip this test on MacOSX for now - return - - m = self._make_module() - output = m.to_native_object() - - src = os.path.join(self.tmpdir, 'llvmobj.o') - with open(src, 'wb') as fout: - fout.write(output) - - self._compile(src) - -if sys.platform != 'win32': - tests.append(TestNative) - -# --------------------------------------------------------------------------- - -class TestNativeAsm(TestCase): - - def test_asm(self): - m = Module.new('module1') - - foo = m.add_function(Type.function(Type.int(), - [Type.int(), Type.int()]), - name="foo") - bldr = Builder.new(foo.append_basic_block('entry')) - x = bldr.add(foo.args[0], foo.args[1]) - bldr.ret(x) - - att_syntax = m.to_native_assembly() - os.environ["LLVMPY_OPTIONS"] = "-x86-asm-syntax=intel" - lc.parse_environment_options(sys.argv[0], "LLVMPY_OPTIONS") - intel_syntax = m.to_native_assembly() - - self.assertNotEqual(att_syntax, intel_syntax) - -tests.append(TestNativeAsm) - -# --------------------------------------------------------------------------- - -class TestUses(TestCase): - - def test_uses(self): - m = Module.new('a') - t = Type.int() - ft = Type.function(t, [t, t, t]) - f = m.add_function(ft, "func") - b = f.append_basic_block('entry') - bld = Builder.new(b) - tmp1 = bld.add(Constant.int(t, 100), f.args[0], "tmp1") - tmp2 = bld.add(tmp1, f.args[1], "tmp2") - tmp3 = bld.add(tmp1, f.args[2], "tmp3") - bld.ret(tmp3) - - # Testing use count - self.assertEqual(f.args[0].use_count, 1) - self.assertEqual(f.args[1].use_count, 1) - self.assertEqual(f.args[2].use_count, 1) - self.assertEqual(tmp1.use_count, 2) - self.assertEqual(tmp2.use_count, 0) - self.assertEqual(tmp3.use_count, 1) - - # Testing uses - self.assert_(f.args[0].uses[0] is tmp1) - self.assertEqual(len(f.args[0].uses), 1) - self.assert_(f.args[1].uses[0] is tmp2) - self.assertEqual(len(f.args[1].uses), 1) - self.assert_(f.args[2].uses[0] is tmp3) - self.assertEqual(len(f.args[2].uses), 1) - self.assertEqual(len(tmp1.uses), 2) - self.assertEqual(len(tmp2.uses), 0) - self.assertEqual(len(tmp3.uses), 1) - -tests.append(TestUses) - -# --------------------------------------------------------------------------- - -class TestMetaData(TestCase): - # test module metadata - def test_metadata(self): - m = Module.new('a') - t = Type.int() - metadata = MetaData.get(m, [Constant.int(t, 100), - MetaDataString.get(m, 'abcdef'), - None]) - MetaData.add_named_operand(m, 'foo', metadata) - self.assertEqual(MetaData.get_named_operands(m, 'foo'), [metadata]) - self.assertEqual(MetaData.get_named_operands(m, 'bar'), []) - self.assertEqual(len(metadata.operands), 3) - self.assertEqual(metadata.operands[0].z_ext_value, 100) - self.assertEqual(metadata.operands[1].string, 'abcdef') - self.assertTrue(metadata.operands[2] is None) - -tests.append(TestMetaData) - -# --------------------------------------------------------------------------- - -class TestInlining(TestCase): - def test_inline_call(self): - mod = Module.new(__name__) - callee = mod.add_function(Type.function(Type.int(), [Type.int()]), - name='bar') - - builder = Builder.new(callee.append_basic_block('entry')) - builder.ret(builder.add(callee.args[0], callee.args[0])) - - caller = mod.add_function(Type.function(Type.int(), []), - name='foo') - - builder = Builder.new(caller.append_basic_block('entry')) - callinst = builder.call(callee, [Constant.int(Type.int(), 1234)]) - builder.ret(callinst) - - pre_inlining = str(caller) - self.assertIn('call', pre_inlining) - - self.assertTrue(inline_function(callinst)) - - post_inlining = str(caller) - self.assertNotIn('call', post_inlining) - self.assertIn('2468', post_inlining) - -tests.append(TestInlining) - -# --------------------------------------------------------------------------- - -class TestIssue10(TestCase): - def test_issue10(self): - m = Module.new('a') - ti = Type.int() - tf = Type.function(ti, [ti, ti]) - - f = m.add_function(tf, "func1") - - bb = f.append_basic_block('entry') - - b = Builder.new(bb) - - # There are no instructions in bb. Positioning of the - # builder at beginning (or end) should succeed (trivially). - b.position_at_end(bb) - b.position_at_beginning(bb) - -tests.append(TestIssue10) - -# --------------------------------------------------------------------------- - -class TestOpaque(TestCase): - - def test_opaque(self): - # Create an opaque type - ts = Type.opaque('mystruct') - self.assertTrue('type opaque' in str(ts)) - self.assertTrue(ts.is_opaque) - self.assertTrue(ts.is_identified) - self.assertFalse(ts.is_literal) - #print(ts) - - # Create a recursive type - ts.set_body([Type.int(), Type.pointer(ts)]) - - self.assertEqual(ts.elements[0], Type.int()) - self.assertEqual(ts.elements[1], Type.pointer(ts)) - self.assertEqual(ts.elements[1].pointee, ts) - self.assertFalse(ts.is_opaque) # is not longer a opaque type - #print(ts) - - with self.assertRaises(llvm.LLVMException): - # Cannot redefine - ts.set_body([]) - - def test_opaque_with_no_name(self): - with self.assertRaises(llvm.LLVMException): - Type.opaque('') - -tests.append(TestOpaque) - -# --------------------------------------------------------------------------- -class TestCPUSupport(TestCase): - - def _build_test_module(self): - mod = Module.new('test') - - float = Type.double() - mysinty = Type.function( float, [float] ) - mysin = mod.add_function(mysinty, "mysin") - block = mysin.append_basic_block("entry") - b = Builder.new(block) - - sqrt = Function.intrinsic(mod, lc.INTR_SQRT, [float]) - pow = Function.intrinsic(mod, lc.INTR_POWI, [float]) - cos = Function.intrinsic(mod, lc.INTR_COS, [float]) - - mysin.args[0].name = "x" - x = mysin.args[0] - one = Constant.real(float, "1") - cosx = b.call(cos, [x], "cosx") - cos2 = b.call(pow, [cosx, Constant.int(Type.int(), 2)], "cos2") - onemc2 = b.fsub(one, cos2, "onemc2") # Should use fsub - sin = b.call(sqrt, [onemc2], "sin") - b.ret(sin) - return mod, mysin - - def _template(self, mattrs): - mod, func = self._build_test_module() - ee = self._build_engine(mod, mattrs=mattrs) - - arg = le.GenericValue.real(Type.double(), 1.234) - retval = ee.run_function(func, [arg]) - - golden = math.sin(1.234) - answer = retval.as_real(Type.double()) - self.assertTrue(abs(answer-golden)/golden < 1e-5) - - - def _build_engine(self, mod, mattrs): - if mattrs: - return EngineBuilder.new(mod).mattrs(mattrs).create() - else: - return EngineBuilder.new(mod).create() - - def test_cpu_support2(self): - features = 'sse3', 'sse41', 'sse42', 'avx' - mattrs = ','.join(map(lambda s: '-%s' % s, features)) - print 'disable mattrs', mattrs - self._template(mattrs) - - def test_cpu_support3(self): - features = 'sse41', 'sse42', 'avx' - mattrs = ','.join(map(lambda s: '-%s' % s, features)) - print 'disable mattrs', mattrs - self._template(mattrs) - - def test_cpu_support4(self): - features = 'sse42', 'avx' - mattrs = ','.join(map(lambda s: '-%s' % s, features)) - print 'disable mattrs', mattrs - self._template(mattrs) - - def test_cpu_support5(self): - features = 'avx', - mattrs = ','.join(map(lambda s: '-%s' % s, features)) - print 'disable mattrs', mattrs - self._template(mattrs) - - def test_cpu_support6(self): - features = [] - mattrs = ','.join(map(lambda s: '-%s' % s, features)) - print 'disable mattrs', mattrs - self._template(mattrs) - -tests.append(TestCPUSupport) - -# --------------------------------------------------------------------------- -class TestIntrinsicBasic(TestCase): - - def _build_module(self, float): - mod = Module.new('test') - functy = Type.function(float, [float]) - func = mod.add_function(functy, "mytest%s" % float) - block = func.append_basic_block("entry") - b = Builder.new(block) - return mod, func, b - - def _template(self, mod, func, pyfunc): - float = func.type.pointee.return_type - ee = le.ExecutionEngine.new(mod) - arg = le.GenericValue.real(float, 1.234) - retval = ee.run_function(func, [arg]) - golden = pyfunc(1.234) - answer = retval.as_real(float) - self.assertTrue(abs(answer - golden) / golden < 1e-7) - - def test_sqrt_f32(self): - float = Type.float() - mod, func, b = self._build_module(float) - intr = Function.intrinsic(mod, lc.INTR_SQRT, [float]) - b.ret(b.call(intr, func.args)) - self._template(mod, func, math.sqrt) - - def test_sqrt_f64(self): - float = Type.double() - mod, func, b = self._build_module(float) - intr = Function.intrinsic(mod, lc.INTR_SQRT, [float]) - b.ret(b.call(intr, func.args)) - self._template(mod, func, math.sqrt) - - def test_cos_f32(self): - if sys.platform == 'win32' and BITS == 32: - # float32 support is known to fail on 32-bit Windows - return - float = Type.float() - mod, func, b = self._build_module(float) - intr = Function.intrinsic(mod, lc.INTR_COS, [float]) - b.ret(b.call(intr, func.args)) - self._template(mod, func, math.cos) - - def test_cos_f64(self): - float = Type.double() - mod, func, b = self._build_module(float) - intr = Function.intrinsic(mod, lc.INTR_COS, [float]) - b.ret(b.call(intr, func.args)) - self._template(mod, func, math.cos) - - def test_sin_f32(self): - if sys.platform == 'win32' and BITS == 32: - # float32 support is known to fail on 32-bit Windows - return - float = Type.float() - mod, func, b = self._build_module(float) - intr = Function.intrinsic(mod, lc.INTR_SIN, [float]) - b.ret(b.call(intr, func.args)) - self._template(mod, func, math.sin) - - def test_sin_f64(self): - float = Type.double() - mod, func, b = self._build_module(float) - intr = Function.intrinsic(mod, lc.INTR_SIN, [float]) - b.ret(b.call(intr, func.args)) - self._template(mod, func, math.sin) - - def test_powi_f32(self): - float = Type.float() - mod, func, b = self._build_module(float) - intr = Function.intrinsic(mod, lc.INTR_POWI, [float]) - b.ret(b.call(intr, [func.args[0], lc.Constant.int(Type.int(), 2)])) - self._template(mod, func, lambda x: x**2) - - def test_powi_f64(self): - float = Type.double() - mod, func, b = self._build_module(float) - intr = Function.intrinsic(mod, lc.INTR_POWI, [float]) - b.ret(b.call(intr, [func.args[0], lc.Constant.int(Type.int(), 2)])) - self._template(mod, func, lambda x: x**2) - - - -tests.append(TestIntrinsicBasic) - -# --------------------------------------------------------------------------- - -class TestIntrinsic(TestCase): - def test_bswap(self): - # setup a function and a builder - mod = Module.new('test') - functy = Type.function(Type.int(), []) - func = mod.add_function(functy, "showme") - block = func.append_basic_block("entry") - b = Builder.new(block) - - # let's do bswap on a 32-bit integer using llvm.bswap - val = Constant.int(Type.int(), 0x42) - bswap = Function.intrinsic(mod, lc.INTR_BSWAP, [Type.int()]) - - bswap_res = b.call(bswap, [val]) - b.ret(bswap_res) - - # logging.debug(mod) - - # the output is: - # - # ; ModuleID = 'test' - # - # define void @showme() { - # entry: - # %0 = call i32 @llvm.bswap.i32(i32 42) - # ret i32 %0 - # } - - # let's run the function - ee = le.ExecutionEngine.new(mod) - retval = ee.run_function(func, []) - self.assertEqual(retval.as_int(), 0x42000000) - - def test_mysin(self): - if sys.platform == 'win32' and BITS == 32: - # float32 support is known to fail on 32-bit Windows - return - - # mysin(x) = sqrt(1.0 - pow(cos(x), 2)) - mod = Module.new('test') - - float = Type.float() - mysinty = Type.function( float, [float] ) - mysin = mod.add_function(mysinty, "mysin") - block = mysin.append_basic_block("entry") - b = Builder.new(block) - - sqrt = Function.intrinsic(mod, lc.INTR_SQRT, [float]) - pow = Function.intrinsic(mod, lc.INTR_POWI, [float]) - cos = Function.intrinsic(mod, lc.INTR_COS, [float]) - - mysin.args[0].name = "x" - x = mysin.args[0] - one = Constant.real(float, "1") - cosx = b.call(cos, [x], "cosx") - cos2 = b.call(pow, [cosx, Constant.int(Type.int(), 2)], "cos2") - onemc2 = b.fsub(one, cos2, "onemc2") # Should use fsub - sin = b.call(sqrt, [onemc2], "sin") - b.ret(sin) - #logging.debug(mod) - -# ; ModuleID = 'test' -# -# define void @showme() { -# entry: -# call i32 @llvm.bswap.i32( i32 42 ) ; :0 [#uses -# } -# -# declare i32 @llvm.bswap.i32(i32) nounwind readnone -# -# define float @mysin(float %x) { -# entry: -# %cosx = call float @llvm.cos.f32( float %x ) ; [#uses -# %sin = call float @llvm.sqrt.f32( float %onemc2 ) -# ret float %sin -# } -# -# declare float @llvm.sqrt.f32(float) nounwind readnone -# -# declare float @llvm.powi.f32(float, i32) nounwind readnone -# -# declare float @llvm.cos.f32(float) nounwind readnone - - # let's run the function - ee = le.ExecutionEngine.new(mod) - arg = le.GenericValue.real(Type.float(), 1.234) - retval = ee.run_function(mysin, [arg]) - - golden = math.sin(1.234) - answer = retval.as_real(Type.float()) - self.assertTrue(abs(answer-golden)/golden < 1e-5) - -tests.append(TestIntrinsic) - -# --------------------------------------------------------------------------- - -class TestVolatile(TestCase): - - def test_volatile(self): - mod = Module.new('mod') - functype = Type.function(Type.void(), []) - func = mod.add_function(functype, name='foo') - bb = func.append_basic_block('entry') - bldr = Builder.new(bb) - ptr = bldr.alloca(Type.int()) - - # test load inst - val = bldr.load(ptr) - self.assertFalse(val.is_volatile, "default must be non-volatile") - val.set_volatile(True) - self.assertTrue(val.is_volatile, "fail to set volatile") - val.set_volatile(False) - self.assertFalse(val.is_volatile, "fail to unset volatile") - - # test store inst - store_inst = bldr.store(val, ptr) - self.assertFalse(store_inst.is_volatile, "default must be non-volatile") - store_inst.set_volatile(True) - self.assertTrue(store_inst.is_volatile, "fail to set volatile") - store_inst.set_volatile(False) - self.assertFalse(store_inst.is_volatile, "fail to unset volatile") - - def test_volatile_another(self): - mod = Module.new('mod') - functype = Type.function(Type.void(), []) - func = mod.add_function(functype, name='foo') - bb = func.append_basic_block('entry') - bldr = Builder.new(bb) - ptr = bldr.alloca(Type.int()) - - # test load inst - val = bldr.load(ptr, volatile=True) - self.assertTrue(val.is_volatile, "volatile kwarg does not work") - val.set_volatile(False) - self.assertFalse(val.is_volatile, "fail to unset volatile") - val.set_volatile(True) - self.assertTrue(val.is_volatile, "fail to set volatile") - - # test store inst - store_inst = bldr.store(val, ptr, volatile=True) - self.assertTrue(store_inst.is_volatile, "volatile kwarg does not work") - store_inst.set_volatile(False) - self.assertFalse(store_inst.is_volatile, "fail to unset volatile") - store_inst.set_volatile(True) - self.assertTrue(store_inst.is_volatile, "fail to set volatile") - -tests.append(TestVolatile) - -# --------------------------------------------------------------------------- - -class TestNamedMetaData(TestCase): - def test_named_md(self): - m = Module.new('test_named_md') - nmd = m.get_or_insert_named_metadata('something') - md = MetaData.get(m, [Constant.int(Type.int(), 0xbeef)]) - nmd.add(md) - self.assertTrue(str(nmd).startswith('!something')) - ir = str(m) - self.assertTrue('!something' in ir) - -tests.append(TestNamedMetaData) - -# --------------------------------------------------------------------------- - -def run(verbosity=1): - print('llvmpy is installed in: ' + os.path.dirname(__file__)) - print('llvmpy version: ' + llvm.__version__) - print(sys.version) - - suite = unittest.TestSuite() - for cls in tests: - suite.addTest(unittest.makeSuite(cls)) - - # The default stream fails in IPython qtconsole on Windows, - # so just using sys.stdout - runner = unittest.TextTestRunner(verbosity=verbosity, stream=sys.stdout) - return runner.run(suite) - - -if __name__ == '__main__': - run() diff --git a/llvm/wrap.cpp b/llvm/wrap.cpp deleted file mode 100644 index 6702ade..0000000 --- a/llvm/wrap.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2008-10, Mahadevan R All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of this software, nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "wrap.h" - -const char PYCAP_OBJECT_NAME[] = "llvm.wrap.h"; - -/*===----------------------------------------------------------------------===*/ -/* Type ctor/dtor */ -/*===----------------------------------------------------------------------===*/ - - -/*===----------------------------------------------------------------------===*/ -/* Helper functions */ -/*===----------------------------------------------------------------------===*/ - -void *get_object_arg(PyObject *args) -{ - PyObject *o; - - if (!PyArg_ParseTuple(args, "O", &o)) - throw py_exception(); - - return pycap_get(o); -} - -// must delete [] returned array -void **make_array_from_list(PyObject *list, int n) -{ - void **arr = new void*[n] ; - - int i; - for (i=0; i(e); - } - } - - return arr; -} diff --git a/llvm/wrap.h b/llvm/wrap.h deleted file mode 100644 index ce2dd88..0000000 --- a/llvm/wrap.h +++ /dev/null @@ -1,1277 +0,0 @@ -/* - * Copyright (c) 2008-10, Mahadevan R All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * * Neither the name of this software, nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * Functions and macros to aid in wrapping. - */ - -#ifndef LLVM_PY_WRAP_H -#define LLVM_PY_WRAP_H - - -/* python includes */ -#include -// #include //unused? - -//// For pre-2.7 compatbility, use the following include, which provides -//// alias for PyCapsule. -//// See http://docs.python.org/py3k/howto/cporting.html -#include "capsulethunk.h" // pre-2.7 compatibility for PyCapsule - - -/* llvm includes */ -#include "llvm-c/Core.h" -#include "llvm-c/Analysis.h" -#include "llvm-c/ExecutionEngine.h" -#include "llvm-c/Target.h" - -// workaround missing bool type -#define bool int -#include "llvm-c/Transforms/PassManagerBuilder.h" -#undef bool - -#include "llvm_c_extra.h" - -#include -#include - -class py_exception: public std::exception{}; - -#define LLVMPY_TRY \ - try { - -#define LLVMPY_CATCH_ALL \ - } catch (const std::bad_alloc&) { \ - return PyErr_NoMemory(); \ - } catch (const py_exception &) { \ - return NULL; \ - } catch (const std::exception& e) { \ - PyErr_SetString(PyExc_RuntimeError, e.what()); \ - return NULL; \ - } catch (...) { \ - std::ostringstream oss; \ - oss << "Unknown exception " << __FILE__ << ":" << __LINE__; \ - PyErr_SetString(PyExc_RuntimeError, oss.str().c_str()); \ - return NULL; \ - } - -/*===----------------------------------------------------------------------===*/ -/* Typedefs */ -/*===----------------------------------------------------------------------===*/ - -typedef unsigned long long llvmwrap_ull; -typedef long long llvmwrap_ll; - -/*===----------------------------------------------------------------------===*/ -/* Type ctor/dtor */ -/*===----------------------------------------------------------------------===*/ - -extern const char PYCAP_OBJECT_NAME[] ; - -// Cast python object to aTYPE -template -aTYPE pycap_get( PyObject* obj ) -{ - void *p = PyCapsule_GetPointer(obj, PYCAP_OBJECT_NAME); - if (!p){ - throw py_exception(); - } - return static_cast (p); -} - -// Contruct python object to hold aTYPE pointer -template -PyObject* pycap_new( aTYPE p ) -{ - if (p){ - return PyCapsule_New(p, PYCAP_OBJECT_NAME, NULL); - } - Py_RETURN_NONE; -} - -/*===----------------------------------------------------------------------===*/ -/* Helper methods */ -/*===----------------------------------------------------------------------===*/ - -/** - * Accept a single object argument of type PyCObject and return the - * opaque pointer contained in it. - */ -void *get_object_arg(PyObject *args); - -template -aTYPE get_object_arg( PyObject* obj ) -{ - return static_cast ( get_object_arg(obj) ); -} - -/** - * Given a PyList object (list) having n (= PyList_Size(list)) elements, - * each list object being a PyCObject, return a new()-ed array of - * opaque pointers from the PyCObjects. The 'n' is passed explicitly - * since the caller will have to query it once anyway, and we can avoid - * a second call internally. - */ -void **make_array_from_list(PyObject *list, int n); - -template -LLTYPE make_array_from_list(PyObject *list, int n) -{ - LLTYPE p = reinterpret_cast(make_array_from_list(list, n)) ; - if ( !p ) throw py_exception(); - return p; -} - -template -PyObject* make_list( aTYPE p[], size_t n ) -{ - PyObject *list = PyList_New(n); - - if (!list) - return NULL; - - size_t i; - for (i=0; i( p[i] ); - PyList_SetItem(list, i, elem); - } - - return list; -} - -/*===----------------------------------------------------------------------===*/ -/* Wrapper macros */ -/*===----------------------------------------------------------------------===*/ - -/* The following wrapper macros define functions that wrap over LLVM-C APIs - * of various signatures. Though they look hairy, they all follow some - * conventions. - */ - - -/****************************************************************************** - ****************************************************************************** - *** PyCapsule Calls - ****************************************************************************** - *****************************************************************************/ - -#define _wrap_none2none(func) \ -static PyObject * \ -_w ## func(PyObject * self, PyObject * args) \ -{ \ - LLVMPY_TRY \ - if (!PyArg_ParseTuple(args, "")) \ - return NULL; \ - func(); \ - Py_RETURN_NONE; \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1) - */ -#define _wrap_obj2obj(func, intype1, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - intype1 arg1 = get_object_arg(args); \ - \ - return pycap_new( func( arg1 ) ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(int arg1) - */ -#define _wrap_int2obj(func, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - int arg1; \ - \ - if (!PyArg_ParseTuple(args, "i", &arg1)) \ - return NULL; \ - \ - return pycap_new( func( arg1 ) ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2) - */ -#define _wrap_objobj2obj(func, intype1, intype2, outtype)\ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2; \ - \ - if (!PyArg_ParseTuple(args, "OO", &obj1, &obj2)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - \ - return pycap_new( func( arg1, arg2 ) ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * void func(intype1 arg1, intype2 arg2) - */ -#define _wrap_objobj2none(func, intype1, intype2) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2; \ - \ - if (!PyArg_ParseTuple(args, "OO", &obj1, &obj2)) \ - return NULL; \ - \ - intype1 arg1 = pycap_get< intype1 > (obj1); \ - intype2 arg2 = pycap_get< intype2 > (obj2); \ - \ - func (arg1, arg2); \ - Py_RETURN_NONE; \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, arg2) - */ -#define _wrap_objint2obj(func, intype1, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1; \ - size_t arg2; \ - \ - if (!PyArg_ParseTuple(args, "OI", &obj1, &arg2)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - \ - return pycap_new( func( arg1, arg2 ) ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, intype3 arg3) - */ -#define _wrap_objobjobj2obj(func, intype1, intype2, intype3, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2, *obj3; \ - \ - if (!PyArg_ParseTuple(args, "OOO", &obj1, &obj2, &obj3)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - \ - return pycap_new( func( arg1, arg2, arg3 ) ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * void func(intype1 arg1, intype2 arg2, intype3 arg3) - */ -#define _wrap_objobjobj2none(func, intype1, intype2, intype3) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2, *obj3; \ - \ - if (!PyArg_ParseTuple(args, "OOO", &obj1, &obj2, &obj3)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - \ - func (arg1, arg2, arg3); \ - Py_RETURN_NONE; \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func( arg1, intype2 arg2, intype3 arg3) - */ -#define _wrap_intobjobj2obj(func, intype2, intype3, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - size_t arg1; \ - PyObject *obj2, *obj3; \ - \ - if (!PyArg_ParseTuple(args, "IOO", &arg1, &obj2, &obj3)) \ - return NULL; \ - \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - \ - return pycap_new( func( arg1, arg2, arg3 ) ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(enum_intype1 arg1, intype2 arg2, intype3 arg3) - */ -#define _wrap_enumobjobj2obj(func, intype1, intype2, intype3, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - intype1 arg1; \ - PyObject *obj2, *obj3; \ - \ - if (!PyArg_ParseTuple(args, "IOO", &arg1, &obj2, &obj3)) \ - return NULL; \ - \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - \ - return pycap_new( func( arg1, arg2, arg3 ) ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(const char *s) - */ -#define _wrap_str2obj(func, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - const char *arg1; \ - \ - if (!PyArg_ParseTuple(args, "s", &arg1)) \ - return NULL; \ - \ - return pycap_new( func( arg1 ) ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func() - */ -#define _wrap_none2obj(func, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - if (!PyArg_ParseTuple(args, "")) \ - return NULL; \ - \ - return pycap_new( func() ); \ - LLVMPY_CATCH_ALL \ -} - - -/** - * Wrap LLVM functions of the type - * const char * func() - */ - #define _wrap_none2str(func) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - if (!PyArg_ParseTuple(args, "")) \ - return NULL; \ - return PyUnicode_FromString(func()); \ - LLVMPY_CATCH_ALL \ -} - - -/** - * Wrap LLVM functions of the type - * const char *func(intype1 arg1) - */ -#define _wrap_obj2str(func, intype1) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - const intype1 arg1 = get_object_arg(args) ; \ - return PyUnicode_FromString( func (arg1)); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * void func(intype1 arg1) - */ -#define _wrap_obj2none(func, intype1) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - const intype1 arg1 = get_object_arg(args) ; \ - func (arg1); \ - Py_RETURN_NONE; \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * void func(intype1 arg1, const char *arg2) - */ -#define _wrap_objstr2none(func, intype1) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1; \ - const char *arg2; \ - \ - if (!PyArg_ParseTuple(args, "Os", &obj1, &arg2)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 >( obj1 ); \ - \ - func (arg1, arg2); \ - Py_RETURN_NONE; \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, const char *arg2) - */ -#define _wrap_objstr2obj(func, intype1, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1; \ - const char *arg2; \ - \ - if (!PyArg_ParseTuple(args, "Os", &obj1, &arg2)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - \ - return pycap_new( func( arg1, arg2 ) ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * void func(intype1 arg1, arg2) - */ -#define _wrap_objint2none(func, intype1) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1; \ - int arg2; \ - \ - if (!PyArg_ParseTuple(args, "Oi", &obj1, &arg2)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - \ - func (arg1, arg2); \ - Py_RETURN_NONE; \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * void func(intype1 arg1, enum_intype2 arg2) - */ -#define _wrap_objenum2none(func, intype1, intype2) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - intype2 arg2; \ - PyObject *obj1; \ - \ - if (!PyArg_ParseTuple(args, "Oi", &obj1, &arg2)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 >( obj1 ); \ - \ - func (arg1, arg2); \ - Py_RETURN_NONE; \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, const char *arg3) - */ -#define _wrap_objobjstr2obj(func, intype1, intype2, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2; \ - const char *arg3; \ - \ - if (!PyArg_ParseTuple(args, "OOs", &obj1, &obj2, &arg3)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - \ - return pycap_new ( func (arg1, arg2, arg3)); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, int arg3) - */ -#define _wrap_objobjint2obj(func, intype1, intype2, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2; \ - int arg3; \ - \ - if (!PyArg_ParseTuple(args, "OOi", &obj1, &obj2, &arg3)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - \ - return pycap_new( func( arg1, arg2, arg3 ) ) ; \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, unsigned long long arg3) - */ -#define _wrap_objobjull2obj(func, intype1, intype2, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2; \ - unsigned long long arg3; \ - \ - if (!PyArg_ParseTuple(args, "OOK", &obj1, &obj2, &arg3)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - \ - return pycap_new( func( arg1, arg2, arg3 ) ) ; \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * void func(intype1 arg1, arg2, arg3) - */ -#define _wrap_objintint2none(func, intype1) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1; \ - int arg2, arg3; \ - \ - if (!PyArg_ParseTuple(args, "Oii", &obj1, &arg2, &arg3)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - \ - func (arg1, arg2, arg3); \ - Py_RETURN_NONE; \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * void func(intype1 arg1, arg2, enum_intype3 arg3) - */ -#define _wrap_objintenum2none(func, intype1, intype3) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1; \ - int arg2; \ - intype3 arg3; \ - \ - if (!PyArg_ParseTuple(args, "Oii", &obj1, &arg2, &arg3)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 >( obj1 ); \ - \ - func (arg1, arg2, arg3); \ - Py_RETURN_NONE; \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, const char *arg2, intype3 arg3) - */ -#define _wrap_objstrobj2obj(func, intype1, intype3, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj3; \ - const char *arg2; \ - \ - if (!PyArg_ParseTuple(args, "OsO", &obj1, &arg2, &obj3)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - \ - return pycap_new( func( arg1, arg2, arg3 ) ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * void func(intype1 arg1, const char *arg2, intype3 arg3) - */ -#define _wrap_objstrobj2none(func, intype1, intype3) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj3; \ - const char *arg2; \ - \ - if (!PyArg_ParseTuple(args, "OsO", &obj1, &arg2, &obj3)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - \ - func(arg1, arg2, arg3); \ - \ - Py_RETURN_NONE; \ - LLVMPY_CATCH_ALL \ -} - - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, int arg3, const char *arg4) - */ -#define _wrap_objobjintstr2obj(func, intype1, intype2, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2; \ - int arg3; \ - const char *arg4; \ - \ - if (!PyArg_ParseTuple(args, "OOis", &obj1, &obj2, &arg3, &arg4)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - \ - return pycap_new( func( arg1, arg2, arg3, arg4 ) ) ; \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, intype3, int arg3, const char *arg4) - */ -#define _wrap_objobjobjintstr2obj(func, intype1, intype2, intype3, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2, *obj3; \ - int arg4; \ - const char *arg5; \ - \ - if (!PyArg_ParseTuple(args, "OOOis", &obj1, &obj2, &obj3, &arg4, \ - &arg5)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - \ - return pycap_new( func( arg1, arg2, arg3, arg4, arg5 ) ) ; \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, intype3 arg3, const char *arg4) - */ -#define _wrap_objobjobjstr2obj(func, intype1, intype2, intype3, outtype)\ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2, *obj3; \ - const char *arg4; \ - \ - if (!PyArg_ParseTuple(args, "OOOs", &obj1, &obj2, &obj3, &arg4)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - \ - return pycap_new( func( arg1, arg2, arg3, arg4 ) ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, const char *arg3, arg4) - */ -#define _wrap_objobjstrint2obj(func, intype1, intype2, outtype)\ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2; \ - const char *arg3; \ - int arg4; \ - \ - if (!PyArg_ParseTuple(args, "OOsi", &obj1, &obj2, &arg3, &arg4)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - \ - return pycap_new( func( arg1, arg2, arg3, arg4 ) ); \ - LLVMPY_CATCH_ALL \ -} - - - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, arg3, const char *arg4, arg5) - */ -#define _wrap_objobjintstrint2obj(func, intype1, intype2, outtype)\ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2; \ - int arg3; \ - const char *arg4; \ - int arg5; \ - \ - if (!PyArg_ParseTuple(args, "OOisi", &obj1, &obj2, &arg3, &arg4, &arg5)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - \ - return pycap_new( func( arg1, arg2, arg3, arg4, arg5 ) ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, const char *arg2, arg3) - */ -#define _wrap_objstrint2obj(func, intype1, outtype)\ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1; \ - const char *arg2; \ - int arg3; \ - \ - if (!PyArg_ParseTuple(args, "Osi", &obj1, &arg2, &arg3)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - \ - return pycap_new( func( arg1, arg2, arg3 ) ); \ - LLVMPY_CATCH_ALL \ -} - - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, intype3, const char *arg4, arg5) - */ -#define _wrap_objobjobjstrint2obj(func, intype1, intype2, intype3, outtype)\ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2, *obj3; \ - const char *arg4; \ - int arg5; \ - \ - if (!PyArg_ParseTuple(args, "OOOsi", &obj1, &obj2, &obj3, &arg4, &arg5)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - \ - return pycap_new( func( arg1, arg2, arg3, arg4, arg5 ) ); \ - LLVMPY_CATCH_ALL \ -} - - - - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, intype3, arg4, const char *arg5, arg6) - */ -#define _wrap_objobjobjintstrint2obj(func, intype1, intype2, intype3, outtype)\ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2, *obj3; \ - int arg4; \ - const char *arg5; \ - int arg6; \ - \ - if (!PyArg_ParseTuple(args, "OOOisi", &obj1, &obj2, &obj3, &arg4, &arg5, &arg6)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - \ - return pycap_new( func( arg1, arg2, arg3, arg4, arg5, arg6 ) );\ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, intype3 arg3, intype4, const char *arg5, arg6) - */ -#define _wrap_objobjobjobjstrint2obj(func, intype1, intype2, intype3, intype4, outtype)\ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2, *obj3, *obj4; \ - const char *arg5; \ - int arg6; \ - \ - if (!PyArg_ParseTuple(args, "OOOOsi", &obj1, &obj2, &obj3, &obj4, &arg5, &arg6)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - const intype4 arg4 = pycap_get< intype4 > (obj4); \ - \ - return pycap_new( func( arg1, arg2, arg3, arg4, arg5, arg6 ) ); \ - LLVMPY_CATCH_ALL \ -} - - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, const char* arg2, intype3 arg3, intype4, const char *arg5, arg6) - */ -#define _wrap_objstrobjobjstrint2obj(func, intype1, intype3, intype4, outtype)\ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj3, *obj4; \ - const char *arg2; \ - const char *arg5; \ - int arg6; \ - \ - if (!PyArg_ParseTuple(args, "OsOOsi", &obj1, &arg2, &obj3, &obj4, &arg5, &arg6)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - const intype4 arg4 = pycap_get< intype4 > (obj4); \ - \ - return pycap_new( func( arg1, arg2, arg3, arg4, arg5, arg6 ) ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, intype3 arg3, arg4) - */ -#define _wrap_objobjobjint2obj(func, intype1, intype2, intype3, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2, *obj3; \ - int arg4; \ - \ - if (!PyArg_ParseTuple(args, "OOOi", &obj1, &obj2, &obj3, &arg4)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - \ - return pycap_new( func( arg1, arg2, arg3, arg4 ) ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, intype3 arg3, intype arg4) - */ -#define _wrap_objobjobjobj2obj(func, intype1, intype2, intype3, \ - intype4, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2, *obj3, *obj4; \ - \ - if (!PyArg_ParseTuple(args, "OOOO", &obj1, &obj2, &obj3, &obj4)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - const intype4 arg4 = pycap_get< intype4 > (obj4); \ - return pycap_new( func( arg1, arg2, arg3, arg4 ) );\ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, intype3 arg3, intype arg4, const char *arg5) - */ -#define _wrap_objobjobjobjstr2obj(func, intype1, intype2, intype3, \ - intype4, outtype)\ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2, *obj3, *obj4; \ - const char *arg5; \ - \ - if (!PyArg_ParseTuple(args, "OOOOs", &obj1, &obj2, &obj3, &obj4, &arg5)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - const intype4 arg4 = pycap_get< intype4 > (obj4); \ - \ - return pycap_new( func( arg1, arg2, arg3, arg4, arg5 ) );\ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, enum_intype2 arg2, intype3 arg3, intype4 arg4, const char *arg5) - */ -#define _wrap_objenumobjobjstr2obj(func, intype1, intype2, intype3, \ - intype4, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj3, *obj4; \ - intype2 arg2 ; \ - const char *arg5; \ - \ - if (!PyArg_ParseTuple(args, "OiOOs", &obj1, &arg2, &obj3, &obj4, &arg5)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype3 arg3 = pycap_get< intype3 > (obj3); \ - const intype4 arg4 = pycap_get< intype4 > (obj4); \ - \ - return pycap_new( func( arg1, arg2, arg3, arg4, arg5 ) ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 *arg2v, unsigned arg2n) - * where arg2v is an array of intype2 elements, arg2n in length. - */ -#define _wrap_objlist2obj(func, intype1, intype2, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2; \ - \ - if (!PyArg_ParseTuple(args, "OO", &obj1, &obj2)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 >( obj1 ); \ - const size_t arg2n = PyList_Size(obj2); \ - intype2 *arg2v = make_array_from_list< intype2 *>(obj2, arg2n); \ - \ - outtype ret = func (arg1, arg2v, arg2n); \ - delete [] arg2v ; \ - return pycap_new( ret ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 *arg1v, unsigned arg1n, int arg2) - * where arg1v is an array of intype1 elements, arg1n in length. - */ -#define _wrap_listint2obj(func, intype1, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1; \ - int arg2; \ - \ - if (!PyArg_ParseTuple(args, "Oi", &obj1, &arg2)) \ - return NULL; \ - \ - const size_t arg1n = PyList_Size(obj1); \ - intype1 *arg1v = make_array_from_list< intype1 *>(obj1, arg1n); \ - \ - outtype ret = func (arg1v, arg1n, arg2); \ - delete [] arg1v; \ - return pycap_new( ret ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 *arg1v, unsigned arg1n) - * where arg1v is an array of intype1 elements, arg1n in length. - */ -#define _wrap_list2obj(func, intype1, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1; \ - \ - if (!PyArg_ParseTuple(args, "O", &obj1)) \ - return NULL; \ - \ - const size_t arg1n = PyList_Size(obj1); \ - intype1 *arg1v = make_array_from_list< intype1 *>(obj1, arg1n); \ - \ - outtype ret = func (arg1v, arg1n); \ - delete [] arg1v; \ - return pycap_new( ret ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 *arg2v, unsigned arg2n, int arg3) - * where arg2v is an array of intype2 elements, arg2n in length. - */ -#define _wrap_objlistint2obj(func, intype1, intype2, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2; \ - int arg3; \ - \ - if (!PyArg_ParseTuple(args, "OOi", &obj1, &obj2, &arg3)) \ - return NULL; \ - \ - intype1 arg1 = pycap_get< intype1 >( obj1 ); \ - const size_t arg2n = PyList_Size(obj2); \ - intype2 *arg2v = make_array_from_list< intype2 *>(obj2, arg2n); \ - \ - outtype ret = func (arg1, arg2v, arg2n, arg3); \ - delete [] arg2v ; \ - return pycap_new( ret ); \ - LLVMPY_CATCH_ALL \ -} - - -/** - * Wrap LLVM functions of the type - * void func(intype1 arg1, intype2 *arg2v, unsigned arg2n, int arg3) - * where arg2v is an array of intype2 elements, arg2n in length. - */ -#define _wrap_objlistint2none(func, intype1, intype2) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2; \ - int arg3; \ - \ - if (!PyArg_ParseTuple(args, "OOi", &obj1, &obj2, &arg3)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 >( obj1 ); \ - const size_t arg2n = PyList_Size(obj2); \ - intype2 *arg2v = make_array_from_list< intype2 *>(obj2, arg2n); \ - \ - func (arg1, arg2v, arg2n, arg3); \ - delete [] arg2v ; \ - Py_RETURN_NONE; \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, int arg2, intype3 *arg3v, unsigned arg3n) - * where arg3v is an array of intype3 elements, arg3n in length. - */ -#define _wrap_objintlist2obj(func, intype1, intype3, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj3; \ - int arg2; \ - \ - if (!PyArg_ParseTuple(args, "OiO", &obj1, &arg2, &obj3)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 >( obj1 ); \ - const size_t arg3n = PyList_Size(obj3); \ - intype3 *arg3v = make_array_from_list< intype3 *>(obj3, arg3n); \ - \ - outtype ret = func (arg1, arg2, arg3v, arg3n); \ - delete [] arg3v ; \ - return pycap_new( ret ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, intype3 *arg3v, unsigned arg3n) - * where arg3v is an array of intype3 elements, arg3n in length. - */ -#define _wrap_objobjlist2obj(func, intype1, intype2, intype3, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2, *obj3; \ - \ - if (!PyArg_ParseTuple(args, "OOO", &obj1, &obj2, &obj3)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - const size_t arg3n = PyList_Size(obj3); \ - intype3 *arg3v = make_array_from_list< intype3 *>(obj3, arg3n); \ - \ - outtype ret = func (arg1, arg2, arg3v, arg3n); \ - delete [] arg3v ; \ - return pycap_new( ret ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM functions of the type - * outtype func(intype1 arg1, intype2 arg2, intype3 *arg3v, unsigned arg3n, const char *arg4) - * where arg3v is an array of intype3 elements, arg3n in length. - */ -#define _wrap_objobjliststr2obj(func, intype1, intype2, intype3, outtype) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - PyObject *obj1, *obj2, *obj3; \ - const char *arg4; \ - \ - if (!PyArg_ParseTuple(args, "OOOs", &obj1, &obj2, &obj3, &arg4)) \ - return NULL; \ - \ - const intype1 arg1 = pycap_get< intype1 > (obj1); \ - const intype2 arg2 = pycap_get< intype2 > (obj2); \ - const size_t arg3n = PyList_Size(obj3); \ - intype3 *arg3v = make_array_from_list< intype3 *>(obj3, arg3n); \ - \ - outtype ret = func (arg1, arg2, arg3v, arg3n, arg4); \ - delete [] arg3v ; \ - return pycap_new( ret ); \ - LLVMPY_CATCH_ALL \ -} - -/** - * Wrap LLVM dump-to-string functions of the type - * char *func(intype1) - * where the return value has to be disposed after use by calling - * LLVMDisposeMessage. - */ -#define _wrap_dumper(func, intype1) \ -static PyObject * \ -_w ## func (PyObject *self, PyObject *args) \ -{ \ - LLVMPY_TRY \ - intype1 arg1 = get_object_arg(args); \ - \ - const char *val = func (arg1); \ - PyObject *ret = PyUnicode_FromString(val); \ - LLVMDisposeMessage(const_cast(val)); \ - return ret; \ - LLVMPY_CATCH_ALL \ -} - - -#endif /* LLVM_PY_WRAP_H */ From c98a1274d9cd80fc4bc3da38cc00230d5839e91b Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 5 Feb 2013 18:48:09 -0600 Subject: [PATCH 47/85] Add Linker and Assembly (IR) Parser --- newbinding/src/Assembly/Parser.py | 14 ++++++++ newbinding/src/Linker.py | 51 +++++++++++++++++++++++++++++ newbinding/src/Support/SourceMgr.py | 10 ++++++ 3 files changed, 75 insertions(+) create mode 100644 newbinding/src/Assembly/Parser.py create mode 100644 newbinding/src/Linker.py create mode 100644 newbinding/src/Support/SourceMgr.py diff --git a/newbinding/src/Assembly/Parser.py b/newbinding/src/Assembly/Parser.py new file mode 100644 index 0000000..1858bcd --- /dev/null +++ b/newbinding/src/Assembly/Parser.py @@ -0,0 +1,14 @@ +from binding import * +from ..namespace import llvm +from ..Module import Module +from ..LLVMContext import LLVMContext +from ..Support.SourceMgr import SMDiagnostic + +llvm.includes.add('llvm/Assembly/Parser.h') + +ParseAssemblyString = llvm.Function('ParseAssemblyString', + ptr(Module), + cast(str, ConstCharPtr), + ptr(Module), # can be None + ref(SMDiagnostic), + ref(LLVMContext)) diff --git a/newbinding/src/Linker.py b/newbinding/src/Linker.py new file mode 100644 index 0000000..0b846d6 --- /dev/null +++ b/newbinding/src/Linker.py @@ -0,0 +1,51 @@ +from binding import * +from namespace import llvm +from ADT.StringRef import StringRef +from Module import Module +from LLVMContext import LLVMContext + +llvm.includes.add('llvm/Linker.h') + +Linker = llvm.Class() + +@Linker +class Linker: + ControlFlags = Enum('Verbose, QuietWarnings, QuietErrors') + LinkerMode = Enum('DestroySource, PreserveSource') + + _new_w_empty = Constructor(cast(str, StringRef), + cast(str, StringRef), + ref(LLVMContext), + cast(int, Unsigned)).require_only(3) + + _new_w_existing = Constructor(cast(str, StringRef), + ptr(Module), + cast(int, Unsigned)).require_only(2) + + @CustomPythonStaticMethod + def new(progname, module_or_name, *args): + if isinstance(module_or_name, Module): + return _new_w_existing(progname, module_or_name, *args) + else: + return _new_w_empty(progname, module_or_name, *args) + + delete = Destructor() + + getModule = Method(ptr(Module)) + releaseModule = Method(ptr(Module)) + getLastError = Method(cast(ConstStdString, str)) + + LinkInModule = CustomMethod('Linker_LinkInModule', + PyObjectPtr, # boolean + ptr(Module), + PyObjectPtr, # errmsg + ) + + LinkModules = CustomStaticMethod('Linker_LinkModules', + PyObjectPtr, # boolean + ptr(Module), + ptr(Module), + LinkerMode, + PyObjectPtr, # errsg + ) + diff --git a/newbinding/src/Support/SourceMgr.py b/newbinding/src/Support/SourceMgr.py new file mode 100644 index 0000000..7dc75be --- /dev/null +++ b/newbinding/src/Support/SourceMgr.py @@ -0,0 +1,10 @@ +from binding import * +from ..namespace import llvm + +llvm.includes.add('llvm/Support/SourceMgr.h') + +@llvm.Class() +class SMDiagnostic: + new = Constructor() + delete = Destructor() + From 9c81fa1f63ba56c76b9a10009216e23667763c53 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 5 Feb 2013 18:48:46 -0600 Subject: [PATCH 48/85] Add more functions to GlobalValue GlobalVariable, StructType and Module --- newbinding/include/llvm_binding/extra.h | 82 +++++++++++++++++++++++++ newbinding/src/GlobalValue.py | 18 ++++++ newbinding/src/GlobalVariable.py | 44 ++++++++++++- newbinding/src/Module.py | 26 +++++++- newbinding/src/Type.py | 27 +++++++- newbinding/src/Value.py | 14 +++-- 6 files changed, 201 insertions(+), 10 deletions(-) diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index 77b399d..fd4eb4e 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -8,6 +9,10 @@ #include #include #include +#include +#include + +#include "auto_pyobject.h" namespace extra{ using namespace llvm; @@ -496,3 +501,80 @@ PyObject* TargetMachine_addPassesToEmitFile( } } +static +PyObject* Linker_LinkInModule(llvm::Linker* Linker, + llvm::Module* Mod, + PyObject* ErrMsg) +{ + std::string errmsg; + bool failed = Linker->LinkInModule(Mod, &errmsg); + if (not failed) { + Py_RETURN_FALSE; + } else { + if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { + return NULL; + } + Py_RETURN_TRUE; + } +} + +static +PyObject* Linker_LinkModules(llvm::Module* Dest, + llvm::Module* Src, + unsigned Mode, + PyObject* ErrMsg) +{ + std::string errmsg; + bool failed = llvm::Linker::LinkModules(Dest, Src, Mode, &errmsg); + if (not failed) { + Py_RETURN_FALSE; + } else { + if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { + return NULL; + } + Py_RETURN_TRUE; + } +} + +static +PyObject* StructType_setBody(llvm::StructType* Self, + PyObject* Elems, + bool isPacked=false) +{ + using namespace llvm; + std::vector elements; + Py_ssize_t N = PySequence_Size(Elems); + elements.reserve(N); + for (Py_ssize_t i=0; i < N; ++i) { + auto_pyobject obj = PySequence_GetItem(Elems, i); + auto_pyobject capsule = PyObject_GetAttrString(*obj, "_ptr"); + if (!capsule) { + return NULL; + } + void * ptr = PyCapsule_GetPointer(*capsule, "llvm::Type"); + if (!ptr) { + return NULL; + } + Type* type = static_cast(ptr); + elements.push_back(type); + } + + Self->setBody(elements, isPacked); + + Py_RETURN_NONE; +} + +static +PyObject* Module_list_globals(llvm::Module* Mod) +{ + return iplist_to_pylist(Mod->getGlobalList(), + "llvm::Value", "llvm::GlobalVariable"); +} + +static +PyObject* Module_list_functions(llvm::Module* Mod) +{ + return iplist_to_pylist(Mod->getFunctionList(), + "llvm::Value", "llvm::Function"); +} + diff --git a/newbinding/src/GlobalValue.py b/newbinding/src/GlobalValue.py index 40825a8..d14d48a 100644 --- a/newbinding/src/GlobalValue.py +++ b/newbinding/src/GlobalValue.py @@ -6,3 +6,21 @@ from Value import GlobalValue class GlobalValue: _include_ = 'llvm/GlobalValue.h' + LinkageTypes = Enum(''' + ExternalLinkage, AvailableExternallyLinkage, LinkOnceAnyLinkage, + LinkOnceODRLinkage, LinkOnceODRAutoHideLinkage, WeakAnyLinkage, + WeakODRLinkage, AppendingLinkage, InternalLinkage, PrivateLinkage, + LinkerPrivateLinkage, LinkerPrivateWeakLinkage, DLLImportLinkage, + DLLExportLinkage, ExternalWeakLinkage, CommonLinkage + ''') + + VisibilityTypes = Enum('''DefaultVisibility, + HiddenVisibility, + ProtectedVisibility''') + + setLinkage = Method(Void, LinkageTypes) + getLinkage = Method(LinkageTypes) + + setVisibility = Method(Void, VisibilityTypes) + getVisibility = Method(VisibilityTypes) + diff --git a/newbinding/src/GlobalVariable.py b/newbinding/src/GlobalVariable.py index 548a8d1..70203d5 100644 --- a/newbinding/src/GlobalVariable.py +++ b/newbinding/src/GlobalVariable.py @@ -1,8 +1,48 @@ from binding import * from namespace import llvm + from GlobalValue import GlobalValue +GlobalVariable = llvm.Class(GlobalValue) -@llvm.Class(GlobalValue) +from Constant import Constant +from Module import Module +from Type import Type +from ADT.StringRef import StringRef + +@GlobalVariable class GlobalVariable: - pass + ThreadLocalMode = Enum('''NotThreadLocal, GeneralDynamicTLSModel, + LocalDynamicTLSModel, InitialExecTLSModel, + LocalExecTLSModel + ''') + new = Constructor(ref(Module), + ptr(Type), + cast(bool, Bool), # is constant + GlobalValue.LinkageTypes, + ptr(Constant), # initializer -- can be None + cast(str, StringRef), # name + ptr(GlobalVariable), # insert before + ThreadLocalMode, + cast(int, Unsigned), # address-space + # cast(bool, Bool), # externally initialized + ).require_only(5) + + setThreadLocal = Method(Void, cast(bool, Bool)) + setThreadLocalMode = Method(Void, ThreadLocalMode) + isThreadLocal = Method(cast(Bool, bool)) + + isConstant = Method(cast(Bool, bool)) + setConstant = Method(Void, ptr(Constant)) + + setInitializer = Method(Void, ptr(Constant)) + getInitializer = Method(ptr(Constant)) + hasInitializer = Method(cast(Bool, bool)) + + hasUniqueInitializer = Method(cast(Bool, bool)) + hasDefinitiveInitializer = Method(cast(Bool, bool)) + +# isExternallyInitialized = Method(cast(Bool, bool)) +# setExternallyinitialized = Method(Void, cast(bool, Bool)) + + \ No newline at end of file diff --git a/newbinding/src/Module.py b/newbinding/src/Module.py index 539c486..706fe48 100644 --- a/newbinding/src/Module.py +++ b/newbinding/src/Module.py @@ -1,14 +1,19 @@ from binding import * from namespace import llvm + +Module = llvm.Class() + from LLVMContext import LLVMContext from ADT.StringRef import StringRef from Constant import Constant +from GlobalVariable import GlobalVariable from Function import Function from DerivedTypes import FunctionType from Support.raw_ostream import raw_ostream from Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter +from Type import Type, StructType -@llvm.Class() +@Module class Module: _include_ = "llvm/Module.h" # Enumerators @@ -38,6 +43,21 @@ class Module: # Function Accessors getOrInsertFunction = Method(ptr(Constant), cast(str, StringRef), ptr(FunctionType)) + getFunction = Method(ptr(Function), cast(str, StringRef)) + + # Function Iteration + list_functions = CustomMethod('Module_list_functions', PyObjectPtr) + + # GlobalVariabe Accessors + getGlobalVariable = Method(ptr(GlobalVariable), + cast(str, StringRef), + cast(bool, Bool), + ).require_only(1) + getNamedGlobal = Method(ptr(GlobalVariable), cast(str, StringRef)) + getOrInsertGlobal = Method(ptr(Constant), cast(str, StringRef), ptr(Type)) + + # GlobalVariable Iteration + list_globals = CustomMethod('Module_list_globals', PyObjectPtr) # Utilities dump = Method(Void) @@ -52,3 +72,7 @@ class Module: return os.str() dropAllReferences = Method() + + getTypeByName = Method(ptr(StructType), cast(str, StringRef)) + + \ No newline at end of file diff --git a/newbinding/src/Type.py b/newbinding/src/Type.py index 8e6b381..09b8ba9 100644 --- a/newbinding/src/Type.py +++ b/newbinding/src/Type.py @@ -110,6 +110,12 @@ class Type: getIntNPtrTy = StaticMethod(ptr(PointerType), ref(LLVMContext), cast(int, Unsigned)) + @CustomPythonMethod + def __str__(self): + import extra + os = extra.make_raw_ostream_for_printing() + self.print_(os) + return os.str() @IntegerType class IntegerType: @@ -130,4 +136,23 @@ class PointerType: @StructType class StructType: - pass + isPacked = Method(cast(Bool, bool)) + isLiteral = Method(cast(Bool, bool)) + isOpaque = Method(cast(Bool, bool)) + hasName = Method(cast(Bool, bool)) + getName = Method(cast(StringRef, str)) + setName = Method(Void, cast(str, StringRef)) + setBody = CustomMethod('StructType_setBody', + PyObjectPtr, # None + PyObjectPtr, # ArrayRef + cast(bool, Bool), + ).require_only(1) + getNumElements = Method(cast(Unsigned, int)) + getElementType = Method(ptr(Type), cast(int, Unsigned)) + + create = StaticMethod(ptr(StructType), + ref(LLVMContext), + cast(str, StringRef), + ).require_only(1) + isValidElementType = StaticMethod(cast(Bool, bool), ptr(Type)) + diff --git a/newbinding/src/Value.py b/newbinding/src/Value.py index 5841746..5675fa5 100644 --- a/newbinding/src/Value.py +++ b/newbinding/src/Value.py @@ -1,13 +1,8 @@ from binding import * from namespace import llvm -from Support.raw_ostream import raw_ostream -from Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter -from Type import Type -from LLVMContext import LLVMContext -from ADT.StringRef import StringRef -Value = llvm.Class() # forward declarations +Value = llvm.Class() Argument = llvm.Class(Value) MDNode = llvm.Class(Value) User = llvm.Class(Value) @@ -16,6 +11,13 @@ Constant = llvm.Class(User) GlobalValue = llvm.Class(Constant) Function = llvm.Class(GlobalValue) +from Support.raw_ostream import raw_ostream +from Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter +from Type import Type +from LLVMContext import LLVMContext +from ADT.StringRef import StringRef + + @Value class Value: From 39de8c400332ffac9bfbdbaba4fd8ca48f08bdc4 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 5 Feb 2013 18:49:33 -0600 Subject: [PATCH 49/85] Expand test --- newbinding/test_binding.py | 59 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/newbinding/test_binding.py b/newbinding/test_binding.py index 1321eb6..578c532 100644 --- a/newbinding/test_binding.py +++ b/newbinding/test_binding.py @@ -151,6 +151,10 @@ def test_basic_jit_use(): m2.setModuleIdentifier(m.getModuleIdentifier()) assert str(m2) == str(m) + # parse llvm ir + m3 = api.ParseAssemblyString(str(m), None, api.SMDiagnostic.new(), context) + m3.setModuleIdentifier(m.getModuleIdentifier()) + assert str(m3) == str(m) def test_engine_builder(): api.InitializeNativeTarget() @@ -223,10 +227,64 @@ def test_engine_builder(): assert 'foo' in asm +def test_linker(): + context = api.getGlobalContext() + mA = api.Module.new("modA", context) + mB = api.Module.new("modB", context) + def create_function(m, name): + int32ty = api.Type.getIntNTy(context, 32) + fnty = api.FunctionType.get(int32ty, [int32ty], False) + fn = m.getOrInsertFunction(name, fnty)._downcast(api.Function) + bb = api.BasicBlock.Create(context, "entry", fn, None) + builder = api.IRBuilder.new(context) + builder.SetInsertPoint(bb) + builder.CreateRet(fn.getArgumentList()[0]) + create_function(mA, 'foo') + create_function(mB, 'bar') + errmsg = StringIO() + linkermode = api.Linker.LinkerMode.PreserveSource + failed = api.Linker.LinkModules(mA, mB, linkermode, errmsg) + assert not failed, errmsg.getvalue() + assert mA.getFunction('foo') + assert mA.getFunction('bar') + + assert set(mA.list_functions()) == set([mA.getFunction('foo'), + mA.getFunction('bar')]) + +def test_structtype(): + context = api.getGlobalContext() + m = api.Module.new("modname", context) + + assert m.getTypeByName("truck") is None + + truck = api.StructType.create(context, "truck") + assert 'type opaque' in str(truck) + elemtys = [api.Type.getInt32Ty(context), api.Type.getDoubleTy(context)] + truck.setBody(elemtys) + + assert 'i32' in str(truck) + assert 'double' in str(truck) + + assert m.getTypeByName("truck") is truck + +def test_globalvariable(): + context = api.getGlobalContext() + m = api.Module.new("modname", context) + + ty = api.Type.getInt32Ty(context) + LinkageTypes = api.GlobalVariable.LinkageTypes + linkage = LinkageTypes.ExternalLinkage + gvar = api.GlobalVariable.new(m, ty, False, linkage, None, "apple") + assert '@apple = external global i32' in str(m) + + gvar2 = m.getNamedGlobal('apple') + assert gvar2 is gvar + + print m.list_globals() def main(): for name, value in globals().items(): @@ -234,6 +292,7 @@ def main(): print name.center(80, '-') value() + if __name__ == '__main__': main() From cd1fa4c4d825efab4cc8b3ac1375f72dd2725dbe Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 6 Feb 2013 21:30:36 -0600 Subject: [PATCH 50/85] Add binding for Attributes, Argument, Constants, CallingConv, GlobalValue, GlobalVariable, etc. --- newbinding/gen/binding.py | 1 + newbinding/include/llvm_binding/conversion.h | 22 ++ newbinding/include/llvm_binding/extra.h | 152 +++++++++-- newbinding/src/Analysis/Verifier.py | 25 ++ newbinding/src/Analysis/__init__.py | 10 + newbinding/src/Argument.py | 4 + newbinding/src/Attributes.py | 39 +++ newbinding/src/CallingConv.py | 11 + newbinding/src/Constant.py | 260 ++++++++++++++++++- newbinding/src/DerivedTypes.py | 1 - newbinding/src/Function.py | 5 + newbinding/src/GlobalValue.py | 21 ++ newbinding/src/GlobalVariable.py | 3 +- newbinding/src/IRBuilder.py | 29 ++- newbinding/src/Metadata.py | 17 ++ newbinding/src/Module.py | 13 +- newbinding/src/Transforms/Utils/Cloning.py | 8 + newbinding/src/Transforms/Utils/__init__.py | 15 ++ newbinding/src/Transforms/__init__.py | 11 +- newbinding/src/Type.py | 59 ++++- newbinding/src/User.py | 8 +- newbinding/src/Value.py | 13 + 22 files changed, 692 insertions(+), 35 deletions(-) create mode 100644 newbinding/src/Analysis/Verifier.py create mode 100644 newbinding/src/Analysis/__init__.py create mode 100644 newbinding/src/Attributes.py create mode 100644 newbinding/src/CallingConv.py create mode 100644 newbinding/src/Transforms/Utils/Cloning.py create mode 100644 newbinding/src/Transforms/Utils/__init__.py diff --git a/newbinding/gen/binding.py b/newbinding/gen/binding.py index d9b44af..09cd9bf 100644 --- a/newbinding/gen/binding.py +++ b/newbinding/gen/binding.py @@ -69,6 +69,7 @@ LongLong = BuiltinTypes('long long') Float = BuiltinTypes('float') Double = BuiltinTypes('double') Uint64 = BuiltinTypes('uint64_t') +Int64 = BuiltinTypes('int64_t') Size_t = BuiltinTypes('size_t') VoidPtr = BuiltinTypes('void*') Bool = BuiltinTypes('bool') diff --git a/newbinding/include/llvm_binding/conversion.h b/newbinding/include/llvm_binding/conversion.h index a1fc87c..cf4e639 100644 --- a/newbinding/include/llvm_binding/conversion.h +++ b/newbinding/include/llvm_binding/conversion.h @@ -64,6 +64,28 @@ int py_str_to(PyObject *strobj, const char* &strref){ return 1; } + +static +int py_int_to(PyObject *intobj, int64_t & val){ + if (!PyInt_Check(intobj)) { + // raise TypeError + PyErr_SetString(PyExc_TypeError, "Expecting an int"); + return 0; + } + if (PyLong_Check(intobj)) { + val = PyLong_AsLongLong(intobj); + } else { + val = PyInt_AsLong(intobj); + } + if (PyErr_Occurred()){ + return NULL; + } + // success + return 1; +} + + + static int py_int_to(PyObject *intobj, unsigned & val){ if (!PyInt_Check(intobj)) { diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index fd4eb4e..85e1ea5 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include "auto_pyobject.h" @@ -171,6 +173,33 @@ PyObject* iplist_to_pylist(iplist &IPL, const char * capsuleName, className); } +template +struct extract { + + template + static + bool from_py_sequence(VecTy& vec, PyObject* seq, const char *capsuleName) + { + Py_ssize_t N = PySequence_Size(seq); + for (Py_ssize_t i = 0; i < N; ++i) { + auto_pyobject item = PySequence_GetItem(seq, i); + if (!item) { + return false; + } + auto_pyobject capsule = PyObject_GetAttrString(*item, "_ptr"); + if (!capsule) { + return false; + } + void* ptr = PyCapsule_GetPointer(*capsule, capsuleName); + if (!ptr) { + return false; + } + vec.push_back(static_cast(ptr)); + } + return true; + } + +}; //static //bool string_equal(const char *A, const char *B){ // for (; *A and *B; ++A, ++B) { @@ -492,7 +521,7 @@ PyObject* TargetMachine_addPassesToEmitFile( if (!buf) { return NULL; } - if ( -1 == PyFile_WriteObject(buf, Out, Py_PRINT_RAW) ){ + if (-1 == PyFile_WriteObject(buf, Out, Py_PRINT_RAW)){ return NULL; } Py_RETURN_TRUE; @@ -501,6 +530,30 @@ PyObject* TargetMachine_addPassesToEmitFile( } } +static +PyObject* Constant_getIntegerValue(llvm::Type* Ty, PyObject* pyint) +{ + using namespace llvm; + if (!Ty->isIntegerTy()) { + PyErr_SetString(PyExc_ValueError, "Type should be of integer type."); + return NULL; + } + unsigned width = Ty->getIntegerBitWidth(); + if (width > sizeof(unsigned long long)*8) { + PyErr_SetString(PyExc_ValueError, "Integer value is too large."); + } + Constant* K; + if (PyLong_Check(pyint)){ + APInt apint(width, PyLong_AsLongLong(pyint), true); + K = Constant::getIntegerValue(Ty, apint); + } else { + APInt apint(width, PyInt_AsLong(pyint), true); + K = Constant::getIntegerValue(Ty, apint); + } + return pycapsule_new(K, "llvm::Value", "llvm::Constant"); +} + + static PyObject* Linker_LinkInModule(llvm::Linker* Linker, llvm::Module* Mod, @@ -543,24 +596,8 @@ PyObject* StructType_setBody(llvm::StructType* Self, { using namespace llvm; std::vector elements; - Py_ssize_t N = PySequence_Size(Elems); - elements.reserve(N); - for (Py_ssize_t i=0; i < N; ++i) { - auto_pyobject obj = PySequence_GetItem(Elems, i); - auto_pyobject capsule = PyObject_GetAttrString(*obj, "_ptr"); - if (!capsule) { - return NULL; - } - void * ptr = PyCapsule_GetPointer(*capsule, "llvm::Type"); - if (!ptr) { - return NULL; - } - Type* type = static_cast(ptr); - elements.push_back(type); - } - + extract::from_py_sequence(elements, Elems, "llvm::Type"); Self->setBody(elements, isPacked); - Py_RETURN_NONE; } @@ -578,3 +615,82 @@ PyObject* Module_list_functions(llvm::Module* Mod) "llvm::Value", "llvm::Function"); } +static +PyObject* Module_list_named_metadata(llvm::Module* Mod) +{ + return iplist_to_pylist(Mod->getFunctionList(), + "llvm::NamedMDNode", "llvm::NamedMDNode"); + +} + +static +PyObject* llvm_verifyModule(const llvm::Module& Fn, + llvm::VerifierFailureAction Action, + PyObject* ErrMsg) +{ + std::string errmsg; + bool failed = llvm::verifyModule(Fn, Action, &errmsg); + + if (failed) { + if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { + return NULL; + } + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } +} + +static +PyObject* ConstantArray_get(llvm::ArrayType* Ty, PyObject* Consts) +{ + using namespace llvm; + + std::vector vec_consts; + bool ok = extract::from_py_sequence(vec_consts, Consts, + "llvm::Value"); + if (not ok) return NULL; + Constant* ary = ConstantArray::get(Ty, vec_consts); + return pycapsule_new(ary, "llvm::Value", "llvm::Constant"); +} + +static +PyObject* ConstantStruct_get(llvm::StructType* Ty, PyObject* Elems) +{ + using namespace llvm; + + std::vector vec_consts; + bool ok = extract::from_py_sequence(vec_consts, Elems, + "llvm::Value"); + if (not ok) return NULL; + Constant* ary = ConstantStruct::get(Ty, vec_consts); + return pycapsule_new(ary, "llvm::Value", "llvm::Constant"); +} + +static +PyObject* ConstantStruct_getAnon(PyObject* Elems, + bool isPacked=false) +{ + using namespace llvm; + + std::vector vec_consts; + bool ok = extract::from_py_sequence(vec_consts, Elems, + "llvm::Value"); + if (not ok) return NULL; + Constant* ary = ConstantStruct::getAnon(vec_consts, isPacked); + return pycapsule_new(ary, "llvm::Value", "llvm::Constant"); +} + +static +PyObject* ConstantVector_get(PyObject* Elems) +{ + using namespace llvm; + + std::vector vec_consts; + bool ok = extract::from_py_sequence(vec_consts, Elems, + "llvm::Value"); + if (not ok) return NULL; + Constant* ary = ConstantVector::get(vec_consts); + return pycapsule_new(ary, "llvm::Value", "llvm::Constant"); +} + diff --git a/newbinding/src/Analysis/Verifier.py b/newbinding/src/Analysis/Verifier.py new file mode 100644 index 0000000..5b47740 --- /dev/null +++ b/newbinding/src/Analysis/Verifier.py @@ -0,0 +1,25 @@ +from binding import * +from ..namespace import llvm +from ..Module import Module +from ..Function import Function + +llvm.includes.add('llvm/Analysis/Verifier.h') + +VerifierFailureAction = llvm.Enum('VerifierFailureAction', + '''AbortProcessAction + PrintMessageAction + ReturnStatusAction''') + +verifyModule = llvm.CustomFunction('verifyModule', + 'llvm_verifyModule', + PyObjectPtr, # boolean -- failed? + ref(Module), + VerifierFailureAction, + PyObjectPtr, # errmsg + ) + +verifyFunction = llvm.Function('verifyFunction', + cast(Bool, bool), # failed? + ref(Function), + VerifierFailureAction) + diff --git a/newbinding/src/Analysis/__init__.py b/newbinding/src/Analysis/__init__.py new file mode 100644 index 0000000..da0beed --- /dev/null +++ b/newbinding/src/Analysis/__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/Argument.py b/newbinding/src/Argument.py index 08b35be..eac4b07 100644 --- a/newbinding/src/Argument.py +++ b/newbinding/src/Argument.py @@ -1,9 +1,13 @@ from binding import * from namespace import llvm from Value import Argument +from Attributes import Attributes @Argument class Argument: _include_ = 'llvm/Argument.h' + addAttr = Method(Void, ref(Attributes)) + removeAttr = Method(Void, ref(Attributes)) + getParamAlignment = Method(cast(Unsigned, int)) diff --git a/newbinding/src/Attributes.py b/newbinding/src/Attributes.py new file mode 100644 index 0000000..235d2c8 --- /dev/null +++ b/newbinding/src/Attributes.py @@ -0,0 +1,39 @@ +from binding import * +from namespace import llvm +from LLVMContext import LLVMContext + +llvm.includes.add('llvm/Attributes.h') + +Attributes = llvm.Class() +AttrBuilder = llvm.Class() + + +@Attributes +class Attributes: + AttrVal = Enum('''None, AddressSafety, Alignment, AlwaysInline, + ByVal, InlineHint, InReg, MinSize, + Naked, Nest, NoAlias, NoCapture, + NoImplicitFloat, NoInline, NonLazyBind, NoRedZone, + NoReturn, NoUnwind, OptimizeForSize, ReadNone, + ReadOnly, ReturnsTwice, SExt, StackAlignment, + StackProtect, StackProtectReq, StructRet, UWTable, ZExt''') + + delete = Destructor() + + get = Method(Attributes, ref(LLVMContext), ref(AttrBuilder)) + + +@AttrBuilder +class AttrBuilder: + + new = Constructor() + delete = Destructor() + + clear = Method() + + addAttribute = Method(ref(AttrBuilder), Attributes.AttrVal) + removeAttribute = Method(ref(AttrBuilder), Attributes.AttrVal) + + addAlignmentAttr = Method(ref(AttrBuilder), cast(int, Unsigned)) + + diff --git a/newbinding/src/CallingConv.py b/newbinding/src/CallingConv.py new file mode 100644 index 0000000..6d0baea --- /dev/null +++ b/newbinding/src/CallingConv.py @@ -0,0 +1,11 @@ +from binding import * +from namespace import llvm + +@llvm.Class() # actually a namespace +class CallingConv: + ID = Enum(''' + C, Fast, Cold, GHC, FirstTargetCC, X86_StdCall, X86_FastCall, + ARM_APCS, ARM_AAPCS, ARM_AAPCS_VFP, MSP430_INTR, X86_ThisCall, + PTX_Kernel, PTX_Device, MBLAZE_INTR, MBLAZE_SVOL, SPIR_FUNC, + SPIR_KERNEL, Intel_OCL_BI + ''') # HiPE diff --git a/newbinding/src/Constant.py b/newbinding/src/Constant.py index c59fef4..9027e3f 100644 --- a/newbinding/src/Constant.py +++ b/newbinding/src/Constant.py @@ -1,8 +1,266 @@ from binding import * from namespace import llvm -from Value import Constant +from LLVMContext import LLVMContext +from ADT.StringRef import StringRef +from ADT.SmallVector import SmallVector_Value, SmallVector_Unsigned +from Type import Type, IntegerType, ArrayType, StructType +from Value import Constant, Value +from Instruction import CmpInst @Constant class Constant: + _downcast_ = Value + + isNullValue = Method(cast(bool, Bool)) + isAllOnesValue = Method(cast(bool, Bool)) + isNegativeZeroValue = Method(cast(bool, Bool)) + #isZeroValue = Method(cast(bool, Bool)) + canTrap = Method(cast(bool, Bool)) + isThreadDependent = Method(cast(bool, Bool)) + isConstantUsed = Method(cast(bool, Bool)) + + _getAggregateElement_by_int = Method(ptr(Constant), cast(int, Unsigned)) + _getAggregateElement_by_int.realname = 'getAggregateElement' + _getAggregateElement_by_const = Method(ptr(Constant), ptr(Constant)) + _getAggregateElement_by_const.realname = 'getAggregateElement' + + @CustomPythonMethod + def getAggregateElement(self, elt): + if isinstance(elt, Constant): + return self._getAggregateElement_by_const(elt) + else: + return self._getAggregateElement_by_int(elt) + + + removeDeadConstantUsers = Method() + + getNullValue = StaticMethod(ptr(Constant), ptr(Type)) + getAllOnesValue = StaticMethod(ptr(Constant), ptr(Type)) + getIntegerValue = CustomStaticMethod('Constant_getIntegerValue', + PyObjectPtr, # ptr(Constant), + ptr(Type), + PyObjectPtr) + + +UndefValue = llvm.Class(Constant) + +@UndefValue +class UndefValue: + getSequentialElement = Method(ptr(UndefValue)) + getStructElement = Method(ptr(UndefValue), cast(int, Unsigned)) + + _getElementValue_by_const = Method(ptr(UndefValue), ptr(Constant)) + _getElementValue_by_const.realname = 'getElementValue' + + _getElementValue_by_int = Method(ptr(UndefValue), cast(int, Unsigned)) + _getElementValue_by_int.realname = 'getElementValue' + + @CustomPythonMethod + def getElementValue(self, idx): + if isinstance(idx, Constant): + return self._getElementValue_by_const(idx) + else: + return self._getElementValue_by_int(idx) + + destroyConstant = Method() + + get = StaticMethod(ptr(UndefValue), ptr(Type)) + + +ConstantInt = llvm.Class(Constant) + +@ConstantInt +class ConstantInt: + get = StaticMethod(ptr(ConstantInt), + ptr(IntegerType), + cast(int, Unsigned), + cast(bool, Bool), + ).require_only(2) + isValueValidForType = StaticMethod(cast(Bool, bool), + ptr(Type), + cast(int, Int64)) + getZExtValue = Method(cast(Uint64, int)) + getSExtValue = Method(cast(Int64, int)) + +ConstantFP = llvm.Class(Constant) + +@ConstantFP +class ConstantFP: + get = StaticMethod(ptr(Constant), ptr(Type), cast(float, Double)) + getNegativeZero = StaticMethod(ptr(ConstantFP), ptr(Type)) + getInfinity = StaticMethod(ptr(ConstantFP), ptr(Type), cast(bool, Bool)) + + isZero = Method(cast(Bool, bool)) + isNegative = Method(cast(Bool, bool)) + isNaN = Method(cast(Bool, bool)) + + +ConstantArray = llvm.Class(Constant) + +@ConstantArray +class ConstantArray: + get = CustomStaticMethod('ConstantArray_get', + PyObjectPtr, # ptr(Constant), + ptr(ArrayType), + PyObjectPtr, # Constants + ) + +ConstantStruct = llvm.Class(Constant) + +@ConstantStruct +class ConstantStruct: + get = CustomStaticMethod('ConstantStruct_get', + PyObjectPtr, # ptr(Constant) + ptr(StructType), + PyObjectPtr, # Constants + ) + getAnon = CustomStaticMethod('ConstantStruct_getAnon', + PyObjectPtr, # ptr(Constant) + PyObjectPtr, # constants + cast(bool, Bool), # packed + ).require_only(1) + +ConstantVector = llvm.Class(Constant) + +@ConstantVector +class ConstantVector: + get = CustomStaticMethod('ConstantVector_get', + PyObjectPtr, # ptr(Constant) + PyObjectPtr, # constants + ) + +ConstantDataSequential = llvm.Class(Constant) + +@ConstantDataSequential +class ConstantDataSequential: pass +ConstantDataArray = llvm.Class(ConstantDataSequential) + +@ConstantDataArray +class ConstantDataArray: + getString = StaticMethod(ptr(Constant), + ref(LLVMContext), + cast(str, StringRef), + cast(bool, Bool) + ).require_only(2) + + +ConstantExpr = llvm.Class(Constant) + +def _factory(*args): + return StaticMethod(ptr(Constant), *args) + +def _factory_const(*args): + return _factory(ptr(Constant), *args) + +def _factory_const2(*args): + return _factory(ptr(Constant), ptr(Constant), *args) + +def _factory_const_nuw_nsw(): + return _factory_const(cast(bool, Bool), cast(bool, Bool)).require_only(1) + +def _factory_const2_nuw_nsw(): + return _factory_const2(cast(bool, Bool), cast(bool, Bool)).require_only(2) + +def _factory_const2_exact(): + return _factory_const2(cast(bool, Bool)).require_only(2) + +def _factory_const_type(): + return _factory_const(ptr(Type)) + +@ConstantExpr +class ConstantExpr: + getAlignOf = _factory(ptr(Type)) + getSizeOf = _factory(ptr(Type)) + getOffsetOf = _factory(ptr(Type), ptr(Constant)) + getNeg = _factory_const_nuw_nsw() + getFNeg = _factory_const() + getNot = _factory_const() + getAdd = _factory_const2_nuw_nsw() + getFAdd = _factory_const2() + getSub = _factory_const2_nuw_nsw() + getFSub = _factory_const2() + getMul = _factory_const2_nuw_nsw() + getFMul = _factory_const2() + getUDiv = _factory_const2_exact() + getSDiv = _factory_const2_exact() + getFDiv = _factory_const2() + getURem = _factory_const2() + getSRem = _factory_const2() + getFRem = _factory_const2() + getAnd = _factory_const2() + getOr = _factory_const2() + getXor = _factory_const2() + getShl = _factory_const2_nuw_nsw() + getLShr = _factory_const2_exact() + getAShr = _factory_const2_exact() + getTrunc = _factory_const_type() + getSExt = _factory_const_type() + getZExt = _factory_const_type() + getFPTrunc = _factory_const_type() + getFPExtend = _factory_const_type() + getUIToFP = _factory_const_type() + getSIToFP = _factory_const_type() + getFPToUI = _factory_const_type() + getFPToSI = _factory_const_type() + getPtrToInt = _factory_const_type() + getIntToPtr = _factory_const_type() + getBitCast = _factory_const_type() + + getCompare = _factory(CmpInst.Predicate, ptr(Constant), ptr(Constant)) + getICmp = _factory(CmpInst.Predicate, ptr(Constant), ptr(Constant)) + getFCmp = _factory(CmpInst.Predicate, ptr(Constant), ptr(Constant)) + + getPointerCast = _factory_const_type() + getIntegerCast = _factory_const(ptr(Type), cast(bool, Bool)) + getFPCast = _factory_const_type() + getSelect = _factory(ptr(Constant), ptr(Constant), ptr(Constant)) + + + _getGEP = _factory(ptr(Constant), ref(SmallVector_Value), cast(bool, Bool)) + _getGEP.require_only(2) + _getGEP.realname = 'getGetElementPtr' + + @CustomPythonStaticMethod + def getGetElementPtr(*args): + import extra + args = list(args) + valuelist = args[1] + args[1] = extra.make_small_vector_from_values(*valuelist) + return ConstantExpr._getGEP(*args) + + getExtractElement = _factory_const2() + getInsertElement = _factory_const2(ptr(Constant)) + getShuffleVector = _factory_const2(ptr(Constant)) + + _getExtractValue = _factory(ptr(Constant), ref(SmallVector_Unsigned)) + _getExtractValue.realname = 'getExtractValue' + + @CustomPythonStaticMethod + def getExtractValue(*args): + import extra + args = list(args) + valuelist = args[1] + args[1] = extra.make_small_vector_from_unsigned(*valuelist) + return ConstantExpr._getExtractValue(*args) + + _getInsertValue = _factory(ptr(Constant), ptr(Constant), + ref(SmallVector_Unsigned)) + _getInsertValue.realname = 'getInsertValue' + + @CustomPythonStaticMethod + def getInsertValue(*args): + import extra + args = list(args) + valuelist = args[2] + args[1] = extra.make_small_vector_from_unsigned(*valuelist) + return ConstantExpr._getInsertValue(*args) + + getOpcode = Method(cast(Unsigned, int)) + getOpcodeName = Method(cast(ConstCharPtr, str)) + isCast = Method(cast(Bool, bool)) + isCompare = Method(cast(Bool, bool)) + hasIndices = Method(cast(Bool, bool)) + isGEPWithNoNotionalOverIndexing = Method(cast(Bool, bool)) + diff --git a/newbinding/src/DerivedTypes.py b/newbinding/src/DerivedTypes.py index af9e757..e71f1a8 100644 --- a/newbinding/src/DerivedTypes.py +++ b/newbinding/src/DerivedTypes.py @@ -25,7 +25,6 @@ class FunctionType: else: return FunctionType._get(*args) - isVarArg = Method(cast(Bool, bool)) getReturnType = Method(ptr(Type)) getParamType = Method(ptr(Type), cast(int, Unsigned)) diff --git a/newbinding/src/Function.py b/newbinding/src/Function.py index 5cebf84..ee59990 100644 --- a/newbinding/src/Function.py +++ b/newbinding/src/Function.py @@ -4,6 +4,7 @@ from Value import GlobalValue, Constant, Function, Argument from Type import Type from DerivedTypes import FunctionType from LLVMContext import LLVMContext +from CallingConv import CallingConv @Function class Function: @@ -17,5 +18,9 @@ class Function: getIntrinsicID = Method(cast(Unsigned, int)) isIntrinsic = Method(cast(Bool, bool)) + getCallingConv = Method(CallingConv.ID) + setCallingConv = Method(Void, CallingConv.ID) + + getArgumentList = CustomMethod('Function_getArgumentList', PyObjectPtr) getBasicBlockList = CustomMethod('Function_getBasicBlockList', PyObjectPtr) diff --git a/newbinding/src/GlobalValue.py b/newbinding/src/GlobalValue.py index d14d48a..02ba4ea 100644 --- a/newbinding/src/GlobalValue.py +++ b/newbinding/src/GlobalValue.py @@ -1,6 +1,8 @@ from binding import * from namespace import llvm from Value import GlobalValue +from Module import Module +from ADT.StringRef import StringRef @GlobalValue class GlobalValue: @@ -24,3 +26,22 @@ class GlobalValue: setVisibility = Method(Void, VisibilityTypes) getVisibility = Method(VisibilityTypes) + setLinkage = Method(Void, LinkageTypes) + getLinkage = Method(LinkageTypes) + + getAlignment = Method(cast(Unsigned, int)) + setAlignment = Method(Void, cast(int, Unsigned)) + + hasSection = Method(cast(Bool, bool)) + getSection = Method(cast(ConstStdString, str)) + setSection = Method(Void, cast(str, StringRef)) + + isDiscardableIfUnused = Method(cast(Bool, bool)) + mayBeOverridden = Method(cast(Bool, bool)) + isWeakForLinker = Method(cast(Bool, bool)) + copyAttributesFrom = Method(Void, ptr(GlobalValue)) + destroyConstant = Method() + isDeclaration = Method(cast(Bool, bool)) + removeFromParent = Method() + eraseFromParent = Method() + getParent = Method(ptr(Module)) diff --git a/newbinding/src/GlobalVariable.py b/newbinding/src/GlobalVariable.py index 70203d5..a11f259 100644 --- a/newbinding/src/GlobalVariable.py +++ b/newbinding/src/GlobalVariable.py @@ -33,7 +33,7 @@ class GlobalVariable: isThreadLocal = Method(cast(Bool, bool)) isConstant = Method(cast(Bool, bool)) - setConstant = Method(Void, ptr(Constant)) + setConstant = Method(Void, cast(bool, Bool)) setInitializer = Method(Void, ptr(Constant)) getInitializer = Method(ptr(Constant)) @@ -45,4 +45,5 @@ class GlobalVariable: # isExternallyInitialized = Method(cast(Bool, bool)) # setExternallyinitialized = Method(Void, cast(bool, Bool)) + eraseFromParent = Method() \ No newline at end of file diff --git a/newbinding/src/IRBuilder.py b/newbinding/src/IRBuilder.py index 61dd99b..e0cac79 100644 --- a/newbinding/src/IRBuilder.py +++ b/newbinding/src/IRBuilder.py @@ -242,13 +242,32 @@ class IRBuilder: ptr(Value), cast(str, StringRef)) CreateShuffleVector.require_only(3) - CreateExtractValue = Method(ptr(Value), ptr(Value), ref(SmallVector_Unsigned), - cast(str, StringRef)) - CreateExtractValue.require_only(2) + _CreateExtractValue = Method(ptr(Value), ptr(Value), + ref(SmallVector_Unsigned), + cast(str, StringRef)) + _CreateExtractValue.require_only(2) + _CreateExtractValue.realname = 'CreateExtractValue' - CreateInsertValue = Method(ptr(Value), ptr(Value), ptr(Value), + @CustomPythonMethod + def CreateExtractValue(self, args): + import extra + args = list(args) + valuelist = args[1] + args[1] = extra.make_small_vector_from_unsigned(*valuelist) + return self._CreateExtractValue(*args) + + _CreateInsertValue = Method(ptr(Value), ptr(Value), ptr(Value), ref(SmallVector_Unsigned), cast(str, StringRef)) - CreateInsertValue.require_only(3) + _CreateInsertValue.require_only(3) + _CreateInsertValue.realname = 'CreateInsertValue' + + @CustomPythonMethod + def CreateInsertValue(self, args): + import extra + args = list(args) + valuelist = args[2] + args[1] = extra.make_small_vector_from_unsigned(*valuelist) + return self._CreateInsertValue(*args) CreateLandingPad = Method(ptr(LandingPadInst), ptr(Type), ptr(Value), cast(int, Unsigned), cast(str, StringRef)) diff --git a/newbinding/src/Metadata.py b/newbinding/src/Metadata.py index 78dbe15..96dbc01 100644 --- a/newbinding/src/Metadata.py +++ b/newbinding/src/Metadata.py @@ -1,7 +1,24 @@ from binding import * from namespace import llvm from Value import MDNode +from ADT.StringRef import StringRef +from Module import Module +from Support.raw_ostream import raw_ostream +from Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter @MDNode class MDNode: pass + +@llvm.Class() +class NamedMDNode: + eraseFromParent = Method() + dropAllReferences = Method() + getParent = Method(ptr(Module)) + getOperand = Method(ptr(MDNode), cast(int, Unsigned)) + getNumOperands = Method(cast(Unsigned, int)) + getName = Method(cast(StringRef, str)) + print_ = Method(Void, ref(raw_ostream), ptr(AssemblyAnnotationWriter)) + print_.realname = "print" + dump = Method() + diff --git a/newbinding/src/Module.py b/newbinding/src/Module.py index 706fe48..7718cd6 100644 --- a/newbinding/src/Module.py +++ b/newbinding/src/Module.py @@ -12,6 +12,7 @@ from DerivedTypes import FunctionType from Support.raw_ostream import raw_ostream from Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter from Type import Type, StructType +from Metadata import NamedMDNode @Module class Module: @@ -59,6 +60,16 @@ class Module: # GlobalVariable Iteration list_globals = CustomMethod('Module_list_globals', PyObjectPtr) + # Named MetaData Accessors + getNamedMetadata = Method(ptr(NamedMDNode), cast(str, StringRef)) + getOrInsertNamedMetadata = Method(ptr(NamedMDNode), cast(str, StringRef)) + eraseNamedMetadata = Method(Void, ptr(NamedMDNode)) + + # Named MetaData Iteration + list_named_metadata = CustomMethod('Module_list_named_metadata', + PyObjectPtr) + + # Utilities dump = Method(Void) print_ = Method(Void, ref(raw_ostream), ptr(AssemblyAnnotationWriter)) @@ -74,5 +85,3 @@ class Module: dropAllReferences = Method() getTypeByName = Method(ptr(StructType), cast(str, StringRef)) - - \ No newline at end of file diff --git a/newbinding/src/Transforms/Utils/Cloning.py b/newbinding/src/Transforms/Utils/Cloning.py new file mode 100644 index 0000000..c7f7a86 --- /dev/null +++ b/newbinding/src/Transforms/Utils/Cloning.py @@ -0,0 +1,8 @@ +from binding import * +from src.namespace import llvm +from src.Module import Module + +llvm.includes.add('llvm/Transforms/Utils/Cloning.h') +CloneModule = llvm.Function('CloneModule', ptr(Module), ptr(Module)) + + diff --git a/newbinding/src/Transforms/Utils/__init__.py b/newbinding/src/Transforms/Utils/__init__.py new file mode 100644 index 0000000..98c06fc --- /dev/null +++ b/newbinding/src/Transforms/Utils/__init__.py @@ -0,0 +1,15 @@ +import os.path, importlib + +def _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() + diff --git a/newbinding/src/Transforms/__init__.py b/newbinding/src/Transforms/__init__.py index da0beed..98c06fc 100644 --- a/newbinding/src/Transforms/__init__.py +++ b/newbinding/src/Transforms/__init__.py @@ -1,10 +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() + diff --git a/newbinding/src/Type.py b/newbinding/src/Type.py index 09b8ba9..4078a9d 100644 --- a/newbinding/src/Type.py +++ b/newbinding/src/Type.py @@ -9,17 +9,29 @@ IntegerType = llvm.Class(Type) CompositeType = llvm.Class(Type) StructType = llvm.Class(CompositeType) SequentialType = llvm.Class(CompositeType) +ArrayType = llvm.Class(SequentialType) PointerType = llvm.Class(SequentialType) +VectorType = llvm.Class(SequentialType) @Type class Type: _include_ = 'llvm/Type.h' + TypeID = Enum(''' + VoidTyID, HalfTyID, FloatTyID, DoubleTyID, + X86_FP80TyID, FP128TyID, PPC_FP128TyID, LabelTyID, + MetadataTyID, X86_MMXTyID, IntegerTyID, FunctionTyID, + StructTyID, ArrayTyID, PointerTyID, VectorTyID, + NumTypeIDs, LastPrimitiveTyID, FirstDerivedTyID + ''') + getContext = Method(ref(LLVMContext)) dump = Method() print_ = Method(Void, ref(raw_ostream)) print_.realname = 'print' + getTypeID = Method(TypeID) + def type_checker(): return Method(cast(Bool, bool)) @@ -81,7 +93,8 @@ class Type: getPPC_FP128Ty = type_factory() getX86_MMXTy = type_factory() - getIntNTy = StaticMethod(ptr(IntegerType), ref(LLVMContext), cast(Unsigned, int)) + getIntNTy = StaticMethod(ptr(IntegerType), + ref(LLVMContext), cast(Unsigned, int)) def integer_factory(): return StaticMethod(ptr(IntegerType), ref(LLVMContext)) @@ -117,6 +130,20 @@ class Type: self.print_(os) return os.str() + getContainedType = Method(ptr(Type), cast(int, Unsigned)) + getNumContainedTypes = Method(cast(int, Unsigned)) + + getArrayNumElements = Method(cast(Uint64, int)) + getArrayElementType = Method(ptr(Type)) + + getVectorNumElements = Method(cast(Unsigned, int)) + getVectorElementType = Method(ptr(Type)) + + getPointerElementType = Method(ptr(Type)) + getPointerAddressSpace = Method(cast(Unsigned, int)) + getPointerTo = Method(ptr(PointerType), cast(int, Unsigned)) + + @IntegerType class IntegerType: pass @@ -130,9 +157,30 @@ class CompositeType: class SequentialType: pass +@ArrayType +class ArrayType: + getNumElements = Method(cast(Uint64, int)) + get = StaticMethod(ptr(ArrayType), ptr(Type), cast(int, Uint64)) + isValidElementType = StaticMethod(cast(Bool, bool), ptr(Type)) + @PointerType class PointerType: - pass + getAddressSpace = Method(cast(Unsigned, int)) + get = StaticMethod(ptr(PointerType), ptr(Type), cast(int, Unsigned)) + getUnqual = StaticMethod(ptr(PointerType), ptr(Type)) + isValidElementType = StaticMethod(cast(Bool, bool), ptr(Type)) + +@VectorType +class VectorType: + getNumElements = Method(cast(Unsigned, int)) + getBitWidth = Method(cast(Unsigned, int)) + get = StaticMethod(ptr(VectorType), ptr(Type), cast(int, Unsigned)) + getInteger = StaticMethod(ptr(VectorType), ptr(VectorType)) + getExtendedElementVectorType = StaticMethod(ptr(VectorType), + ptr(VectorType)) + getTruncatedElementVectorType = StaticMethod(ptr(VectorType), + ptr(VectorType)) + isValidElementType = StaticMethod(cast(Bool, bool), ptr(Type)) @StructType class StructType: @@ -154,5 +202,12 @@ class StructType: ref(LLVMContext), cast(str, StringRef), ).require_only(1) + + get = StaticMethod(ptr(StructType), + ref(LLVMContext), + cast(bool, Bool), # is packed + ).require_only(1) + + isValidElementType = StaticMethod(cast(Bool, bool), ptr(Type)) diff --git a/newbinding/src/User.py b/newbinding/src/User.py index 57d58bc..9a077c1 100644 --- a/newbinding/src/User.py +++ b/newbinding/src/User.py @@ -1,7 +1,11 @@ from binding import * from namespace import llvm -from Value import User +from Value import Value, User @User class User: - pass + _downcast_ = Value + getOperand = Method(ptr(Value), cast(int, Unsigned)) + setOperand = Method(Void, cast(int, Unsigned), ptr(Value)) + getNumOperands = Method(cast(Unsigned, int)) + diff --git a/newbinding/src/Value.py b/newbinding/src/Value.py index 5675fa5..5d8c0a9 100644 --- a/newbinding/src/Value.py +++ b/newbinding/src/Value.py @@ -21,6 +21,16 @@ from ADT.StringRef import StringRef @Value class Value: + ValueTy = Enum(''' + ArgumentVal, BasicBlockVal, FunctionVal, GlobalAliasVal, + GlobalVariableVal, UndefValueVal, BlockAddressVal, ConstantExprVal, + ConstantAggregateZeroVal, ConstantDataArrayVal, ConstantDataVectorVal, + ConstantIntVal, ConstantFPVal, ConstantArrayVal, ConstantStructVal, + ConstantVectorVal, ConstantPointerNullVal, MDNodeVal, MDStringVal, + InlineAsmVal, PseudoSourceValueVal, FixedStackPseudoSourceValueVal, + InstructionVal, ConstantFirstVal, ConstantLastVal + ''') + dump = Method() print_ = Method(Void, ref(raw_ostream), ptr(AssemblyAnnotationWriter)) @@ -41,6 +51,7 @@ class Value: hasOneUse = Method(cast(Bool, bool)) hasNUses = Method(cast(Bool, bool), cast(int, Unsigned)) isUsedInBasicBlock = Method(cast(Bool, bool), BasicBlock) + getNumUses = Method(cast(Unsigned, int)) @CustomPythonMethod def __str__(self): @@ -48,3 +59,5 @@ class Value: os = extra.make_raw_ostream_for_printing() self.print_(os, None) return os.str() + + getValueID = Method(cast(Unsigned, int)) From aa5b969961b4390a2e68dab0d6c14b23c7e92933 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 6 Feb 2013 21:31:24 -0600 Subject: [PATCH 51/85] Expand test --- newbinding/test_binding.py | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/newbinding/test_binding.py b/newbinding/test_binding.py index 578c532..5b51ecb 100644 --- a/newbinding/test_binding.py +++ b/newbinding/test_binding.py @@ -82,8 +82,16 @@ def test_basic_jit_use(): errio = StringIO() print m - # build pass manager + # verifier + action = api.VerifierFailureAction.ReturnStatusAction + corrupted = api.verifyFunction(fn, action) + assert not corrupted + corrupted = api.verifyModule(m, action, errio) + print corrupted + assert not corrupted, errio.getvalue() + + # build pass manager pmb = api.PassManagerBuilder.new() pmb.OptLevel = 3 assert pmb.OptLevel == 3 @@ -156,6 +164,11 @@ def test_basic_jit_use(): m3.setModuleIdentifier(m.getModuleIdentifier()) assert str(m3) == str(m) + # test clone + m4 = api.CloneModule(m) + assert m4 is not m + assert str(m4) == str(m) + def test_engine_builder(): api.InitializeNativeTarget() context = api.getGlobalContext() @@ -286,6 +299,26 @@ def test_globalvariable(): print m.list_globals() + +def test_sequentialtypes(): + context = api.getGlobalContext() + int32ty = api.Type.getInt32Ty(context) + ary_int32x4 = api.ArrayType.get(int32ty, 4) + assert '[4 x i32]' == str(ary_int32x4) + ptr_int32 = api.PointerType.get(int32ty, 1) + assert 'i32 addrspace(1)*' == str(ptr_int32) + vec_int32x4 = api.VectorType.get(int32ty, 4) + assert '<4 x i32>' == str(vec_int32x4) + + +def test_constants(): + context = api.getGlobalContext() + int32ty = api.Type.getInt32Ty(context) + ary_int32x4 = api.ArrayType.get(int32ty, 4) + intconst = api.ConstantInt.get(int32ty, 123) + aryconst = api.ConstantArray.get(ary_int32x4, [intconst] * 4) + assert str(aryconst.getAggregateElement(0)) == str(intconst) + def main(): for name, value in globals().items(): if name.startswith('test_') and callable(value): From 11cc78d780772ec90bab2581fc86e6a5046cf170 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 7 Feb 2013 13:27:03 -0600 Subject: [PATCH 52/85] Add binding for Intrinsics. Add support for functions that free the resource but is not a destructor. --- newbinding/capsule.py | 14 +++++++++--- newbinding/gen/binding.py | 3 +++ newbinding/include/llvm_binding/extra.h | 19 ++++++++++++++++ newbinding/src/Function.py | 29 +++++++++++++++++++++++++ newbinding/src/GlobalValue.py | 2 ++ newbinding/src/GlobalVariable.py | 2 +- newbinding/src/Intrinsics.py | 17 +++++++++++++++ newbinding/test_binding.py | 10 +++++++++ 8 files changed, 92 insertions(+), 4 deletions(-) create mode 100644 newbinding/src/Intrinsics.py diff --git a/newbinding/capsule.py b/newbinding/capsule.py index 8c2f10e..e29948d 100644 --- a/newbinding/capsule.py +++ b/newbinding/capsule.py @@ -92,8 +92,12 @@ _cache = defaultdict(WeakValueDictionary) def release_ownership(old): logger.debug('Release %s', old) addr = Capsule.getPointer(old) - if _addr2dtor[addr] is None: - # Guard deduplicated release + + if _addr2dtor.get(addr) is None: + clsname = Capsule.getClassName(old) + if not _pyclasses[clsname]._has_dtor(): + return + # Guard duplicated release raise Exception("Already released") _addr2dtor[addr] = None @@ -117,7 +121,7 @@ def wrap(cap, owned=False): try: # lookup cached object return _cache[cls][addr] except KeyError: - if not owned and hasattr(cls, '_delete_'): + if not owned and cls._has_dtor(): _addr2dtor[addr] = cls._delete_ obj = cap.instantiate() _cache[cls][addr] = obj # cache it @@ -164,6 +168,10 @@ class Wrapper(object): def _downcast(self, newcls): return downcast(self, newcls) + @classmethod + def _has_dtor(cls): + return hasattr(cls, '_delete_') + def downcast(obj, cls): import _api if type(obj) is cls: diff --git a/newbinding/gen/binding.py b/newbinding/gen/binding.py index 09cd9bf..1c7c7ca 100644 --- a/newbinding/gen/binding.py +++ b/newbinding/gen/binding.py @@ -283,6 +283,7 @@ class Method(object): self.signatures = [] self.includes = set() self._add_signature(return_type, *args) + self.disowning = False def _add_signature(self, return_type, *args): prev_lens = set(map(len, self.signatures)) @@ -350,6 +351,8 @@ class Method(object): decl = writer.function(self.name, args=('self',), varargs='args') with decl as (this, varargs): unwrap_this = writer.unwrap(this) + if self.disowning: + writer.release_ownership(unwrap_this) unwrapped = writer.unwrap_many(varargs) self.process_ownedptr_args(writer, unwrapped) diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index 85e1ea5..0d9ba16 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -13,6 +13,7 @@ #include #include #include +#include #include "auto_pyobject.h" @@ -694,3 +695,21 @@ PyObject* ConstantVector_get(PyObject* Elems) return pycapsule_new(ary, "llvm::Value", "llvm::Constant"); } +static +PyObject* Intrinsic_getDeclaration(llvm::Module* Mod, + unsigned ID, + PyObject* Types=NULL) +{ + using namespace llvm; + Function* Fn = NULL; + if (Types) { + std::vector types; + bool ok = extract::from_py_sequence(types, Types, "llvm::Type"); + if (!ok) return NULL; + Fn = Intrinsic::getDeclaration(Mod, (Intrinsic::ID)ID, types); + } else { + Fn = Intrinsic::getDeclaration(Mod, (Intrinsic::ID)ID); + } + return pycapsule_new(Fn, "llvm::Value", "llvm::Function"); +} + diff --git a/newbinding/src/Function.py b/newbinding/src/Function.py index ee59990..d82b5d3 100644 --- a/newbinding/src/Function.py +++ b/newbinding/src/Function.py @@ -1,6 +1,8 @@ from binding import * from namespace import llvm from Value import GlobalValue, Constant, Function, Argument +from BasicBlock import BasicBlock +from Attributes import Attributes from Type import Type from DerivedTypes import FunctionType from LLVMContext import LLVMContext @@ -21,6 +23,33 @@ class Function: getCallingConv = Method(CallingConv.ID) setCallingConv = Method(Void, CallingConv.ID) + hasGC = Method(cast(bool, Bool)) + getGC = Method(cast(ConstCharPtr, str)) + setGC = Method(Void, cast(str, ConstCharPtr)) + getArgumentList = CustomMethod('Function_getArgumentList', PyObjectPtr) getBasicBlockList = CustomMethod('Function_getBasicBlockList', PyObjectPtr) + getEntryBlock = Method(ref(BasicBlock)) + + copyAttributesFrom = Method(Void, ptr(GlobalValue)) + + setDoesNotThrow = Method() + doesNotThrow = Method(cast(Bool, bool)) + setDoesNotReturn = Method() + doesNotReturn = Method(cast(Bool, bool)) + setOnlyReadsMemory = Method() + onlyReadsMemory = Method(cast(Bool, bool)) + setDoesNotAccessMemory = Method() + doesNotAccessMemory = Method(cast(Bool, bool)) + + deleteBody = Method() + viewCFG = Method() + viewCFGOnly = Method() + + addFnAttr = Method(Void, Attributes.AttrVal) + removeFnAttr = Method(Void, ref(Attributes)) + + eraseFromParent = Method() + eraseFromParent.disowning = True + diff --git a/newbinding/src/GlobalValue.py b/newbinding/src/GlobalValue.py index 02ba4ea..f21d5af 100644 --- a/newbinding/src/GlobalValue.py +++ b/newbinding/src/GlobalValue.py @@ -44,4 +44,6 @@ class GlobalValue: isDeclaration = Method(cast(Bool, bool)) removeFromParent = Method() eraseFromParent = Method() + eraseFromParent.disowning = True + getParent = Method(ptr(Module)) diff --git a/newbinding/src/GlobalVariable.py b/newbinding/src/GlobalVariable.py index a11f259..4ee91fb 100644 --- a/newbinding/src/GlobalVariable.py +++ b/newbinding/src/GlobalVariable.py @@ -45,5 +45,5 @@ class GlobalVariable: # isExternallyInitialized = Method(cast(Bool, bool)) # setExternallyinitialized = Method(Void, cast(bool, Bool)) - eraseFromParent = Method() + \ No newline at end of file diff --git a/newbinding/src/Intrinsics.py b/newbinding/src/Intrinsics.py new file mode 100644 index 0000000..0f1bcb4 --- /dev/null +++ b/newbinding/src/Intrinsics.py @@ -0,0 +1,17 @@ +from binding import * +from namespace import llvm + +from Module import Module +from Function import Function + + +Intrinsic = llvm.Class() # fake class (actually a namespace) + +@Intrinsic +class Intrinsic: + getDeclaration = CustomStaticMethod('Intrinsic_getDeclaration', + PyObjectPtr, # Function* + ptr(Module), + cast(int, Unsigned), # intrinsic id + PyObjectPtr, # list of Type + ).require_only(2) diff --git a/newbinding/test_binding.py b/newbinding/test_binding.py index 5b51ecb..9003f7d 100644 --- a/newbinding/test_binding.py +++ b/newbinding/test_binding.py @@ -319,6 +319,16 @@ def test_constants(): aryconst = api.ConstantArray.get(ary_int32x4, [intconst] * 4) assert str(aryconst.getAggregateElement(0)) == str(intconst) +def test_intrinsic(): + context = api.getGlobalContext() + m = api.Module.new("modname", context) + INTR_SIN = 1652 + floatty = api.Type.getFloatTy(context) + fn = api.Intrinsic.getDeclaration(m, INTR_SIN, [floatty]) + assert 'llvm.sin.f32' in str(fn) + fn.eraseFromParent() + assert 'llvm.sin.f32' not in str(m) + def main(): for name, value in globals().items(): if name.startswith('test_') and callable(value): From 541c119fc38ef87e7ade743ceb4402db7f213b68 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 7 Feb 2013 13:50:16 -0600 Subject: [PATCH 53/85] Add binding for MDNode, MDString, InlineAsm --- newbinding/include/llvm_binding/extra.h | 17 +++++++++++++++-- newbinding/src/InlineAsm.py | 24 ++++++++++++++++++++++++ newbinding/src/Metadata.py | 23 +++++++++++++++++++++-- newbinding/src/Value.py | 1 + 4 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 newbinding/src/InlineAsm.py diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index 0d9ba16..df0cecd 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -697,8 +697,8 @@ PyObject* ConstantVector_get(PyObject* Elems) static PyObject* Intrinsic_getDeclaration(llvm::Module* Mod, - unsigned ID, - PyObject* Types=NULL) + unsigned ID, + PyObject* Types=NULL) { using namespace llvm; Function* Fn = NULL; @@ -713,3 +713,16 @@ PyObject* Intrinsic_getDeclaration(llvm::Module* Mod, return pycapsule_new(Fn, "llvm::Value", "llvm::Function"); } +static +PyObject* MDNode_get(llvm::LLVMContext &Cxt, PyObject* Vals) +{ + std::vector vals; + bool ok = extract::from_py_sequence(vals, Vals, "llvm::Value"); + if (not ok) return NULL; + llvm::MDNode* md = llvm::MDNode::get(Cxt, vals); + return pycapsule_new(md, "llvm::Value", "llvm::MDNode"); +} + + + + diff --git a/newbinding/src/InlineAsm.py b/newbinding/src/InlineAsm.py new file mode 100644 index 0000000..a4ce16b --- /dev/null +++ b/newbinding/src/InlineAsm.py @@ -0,0 +1,24 @@ +from binding import * +from namespace import llvm +from Value import Value +from DerivedTypes import FunctionType +from ADT.StringRef import StringRef + +llvm.includes.add('llvm/InlineAsm.h') + +InlineAsm = llvm.Class(Value) + +@InlineAsm +class InlineAsm: + AsmDialect = Enum('AD_ATT', 'AD_Intel') + ConstraintPrefix = Enum('''isInput, isOutput, isClobber''') + + get = StaticMethod(ptr(InlineAsm), + ptr(FunctionType), + cast(str, StringRef), # AsmString + cast(str, StringRef), # Constrains + cast(bool, Bool), # hasSideEffects + cast(bool, Bool), # isAlignStack + AsmDialect, # default = AD_ATT + ).require_only(4) + diff --git a/newbinding/src/Metadata.py b/newbinding/src/Metadata.py index 96dbc01..bda09e1 100644 --- a/newbinding/src/Metadata.py +++ b/newbinding/src/Metadata.py @@ -1,14 +1,32 @@ from binding import * from namespace import llvm -from Value import MDNode +from Value import Value, MDNode, MDString +from LLVMContext import LLVMContext from ADT.StringRef import StringRef from Module import Module +from Function import Function from Support.raw_ostream import raw_ostream from Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter @MDNode class MDNode: - pass + replaceOperandWith = Method(Void, cast(int, Unsigned), ptr(Value)) + getOperand = Method(ptr(Value), cast(int, Unsigned)) + getNumOperands = Method(cast(Unsigned, int)) + isFunctionLocal = Method(cast(Bool, bool)) + getFunction = Method(const(ptr(Function))) + + get = CustomStaticMethod('MDNode_get', + PyObjectPtr, # MDNode* + ref(LLVMContext), + PyObjectPtr, # ArrayRef + ) + +@MDString +class MDString: + get = StaticMethod(ptr(MDString), ref(LLVMContext), cast(str, StringRef)) + getString = Method(cast(StringRef, str)) + getLength = Method(cast(int, Unsigned)) @llvm.Class() class NamedMDNode: @@ -18,6 +36,7 @@ class NamedMDNode: getOperand = Method(ptr(MDNode), cast(int, Unsigned)) getNumOperands = Method(cast(Unsigned, int)) getName = Method(cast(StringRef, str)) + addOperand = Method(Void, ptr(MDNode)) print_ = Method(Void, ref(raw_ostream), ptr(AssemblyAnnotationWriter)) print_.realname = "print" dump = Method() diff --git a/newbinding/src/Value.py b/newbinding/src/Value.py index 5d8c0a9..27bcda0 100644 --- a/newbinding/src/Value.py +++ b/newbinding/src/Value.py @@ -5,6 +5,7 @@ from namespace import llvm Value = llvm.Class() Argument = llvm.Class(Value) MDNode = llvm.Class(Value) +MDString = llvm.Class(Value) User = llvm.Class(Value) BasicBlock = llvm.Class(Value) Constant = llvm.Class(User) From 113f30ffab758fc1bf7b0c9d7889ed5297379bf5 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 7 Feb 2013 15:23:31 -0600 Subject: [PATCH 54/85] Add more to Instruction --- newbinding/gen/binding.py | 1 + newbinding/src/Constant.py | 23 ++++--- newbinding/src/Instruction.py | 121 +++++++++++++++++++++++++++++++--- newbinding/src/Metadata.py | 9 +++ 4 files changed, 135 insertions(+), 19 deletions(-) diff --git a/newbinding/gen/binding.py b/newbinding/gen/binding.py index 1c7c7ca..c1e1d1e 100644 --- a/newbinding/gen/binding.py +++ b/newbinding/gen/binding.py @@ -70,6 +70,7 @@ Float = BuiltinTypes('float') Double = BuiltinTypes('double') Uint64 = BuiltinTypes('uint64_t') Int64 = BuiltinTypes('int64_t') +Int = BuiltinTypes('int') Size_t = BuiltinTypes('size_t') VoidPtr = BuiltinTypes('void*') Bool = BuiltinTypes('bool') diff --git a/newbinding/src/Constant.py b/newbinding/src/Constant.py index 9027e3f..42541c4 100644 --- a/newbinding/src/Constant.py +++ b/newbinding/src/Constant.py @@ -1,10 +1,22 @@ from binding import * from namespace import llvm + +from Value import Constant, Value + +UndefValue = llvm.Class(Constant) +ConstantInt = llvm.Class(Constant) +ConstantFP = llvm.Class(Constant) +ConstantArray = llvm.Class(Constant) +ConstantStruct = llvm.Class(Constant) +ConstantVector = llvm.Class(Constant) +ConstantDataSequential = llvm.Class(Constant) +ConstantDataArray = llvm.Class(ConstantDataSequential) +ConstantExpr = llvm.Class(Constant) + from LLVMContext import LLVMContext from ADT.StringRef import StringRef from ADT.SmallVector import SmallVector_Value, SmallVector_Unsigned from Type import Type, IntegerType, ArrayType, StructType -from Value import Constant, Value from Instruction import CmpInst @Constant @@ -42,7 +54,6 @@ class Constant: PyObjectPtr) -UndefValue = llvm.Class(Constant) @UndefValue class UndefValue: @@ -67,7 +78,6 @@ class UndefValue: get = StaticMethod(ptr(UndefValue), ptr(Type)) -ConstantInt = llvm.Class(Constant) @ConstantInt class ConstantInt: @@ -82,7 +92,6 @@ class ConstantInt: getZExtValue = Method(cast(Uint64, int)) getSExtValue = Method(cast(Int64, int)) -ConstantFP = llvm.Class(Constant) @ConstantFP class ConstantFP: @@ -95,7 +104,6 @@ class ConstantFP: isNaN = Method(cast(Bool, bool)) -ConstantArray = llvm.Class(Constant) @ConstantArray class ConstantArray: @@ -105,7 +113,6 @@ class ConstantArray: PyObjectPtr, # Constants ) -ConstantStruct = llvm.Class(Constant) @ConstantStruct class ConstantStruct: @@ -120,7 +127,6 @@ class ConstantStruct: cast(bool, Bool), # packed ).require_only(1) -ConstantVector = llvm.Class(Constant) @ConstantVector class ConstantVector: @@ -129,13 +135,11 @@ class ConstantVector: PyObjectPtr, # constants ) -ConstantDataSequential = llvm.Class(Constant) @ConstantDataSequential class ConstantDataSequential: pass -ConstantDataArray = llvm.Class(ConstantDataSequential) @ConstantDataArray class ConstantDataArray: @@ -146,7 +150,6 @@ class ConstantDataArray: ).require_only(2) -ConstantExpr = llvm.Class(Constant) def _factory(*args): return StaticMethod(ptr(Constant), *args) diff --git a/newbinding/src/Instruction.py b/newbinding/src/Instruction.py index dda6b48..79cf4a3 100644 --- a/newbinding/src/Instruction.py +++ b/newbinding/src/Instruction.py @@ -1,6 +1,11 @@ from binding import * from namespace import llvm -from Value import User +from Value import Value, MDNode, User, BasicBlock, Function +from ADT.StringRef import StringRef +from CallingConv import CallingConv +from Attributes import Attributes +from Constant import ConstantInt + Instruction = llvm.Class(User) AtomicCmpXchgInst = llvm.Class(Instruction) @@ -54,7 +59,49 @@ FPTruncInst = llvm.Class(CastInst) @Instruction class Instruction: - pass + removeFromParent = Method() + eraseFromParent = Method() + eraseFromParent.disowning = True + + getParent = Method(ptr(BasicBlock)) + getOpcode = Method(cast(Unsigned, int)) + getOpcodeName = Method(cast(ConstCharPtr, str)) + + insertBefore = Method(Void, ptr(Instruction)) + insertAfter = Method(Void, ptr(Instruction)) + moveBefore = Method(Void, ptr(Instruction)) + + isTerminator = Method(cast(Bool, bool)) + isBinaryOp = Method(cast(Bool, bool)) + isShift = Method(cast(Bool, bool)) + isCast = Method(cast(Bool, bool)) + isLogicalShift = Method(cast(Bool, bool)) + isArithmeticShift = Method(cast(Bool, bool)) + hasMetadata = Method(cast(Bool, bool)) + hasMetadataOtherThanDebugLoc = Method(cast(Bool, bool)) + isAssociative = Method(cast(Bool, bool)) + isCommutative = Method(cast(Bool, bool)) + isIdempotent = Method(cast(Bool, bool)) + isNilpotent = Method(cast(Bool, bool)) + mayWriteToMemory = Method(cast(Bool, bool)) + mayReadFromMemory = Method(cast(Bool, bool)) + mayReadOrWriteMemory = Method(cast(Bool, bool)) + mayThrow = Method(cast(Bool, bool)) + mayHaveSideEffects = Method(cast(Bool, bool)) + + hasMetadata = Method(cast(Bool, bool)) + getMetadata = Method(ptr(MDNode), cast(str, StringRef)) + setMetadata = Method(Void, cast(str, StringRef), ptr(MDNode)) + + clone = Method(ptr(Instruction)) + +# LLVM 3.3 +# hasUnsafeAlgebra = Method(cast(Bool, bool)) +# hasNoNans = Method(cast(Bool, bool)) +# hasNoInfs = Method(cast(Bool, bool)) +# hasNoSignedZeros = Method(cast(Bool, bool)) +# hasAllowReciprocal = Method(cast(Bool, bool)) + @AtomicCmpXchgInst class AtomicCmpXchgInst: @@ -71,7 +118,16 @@ class BinaryOperator: @CallInst class CallInst: - pass + _downcast_ = Value, Instruction + getCallingConv = Method(CallingConv.ID) + setCallingConv = Method(Void, CallingConv.ID) + getParamAlignment = Method(cast(Unsigned, int), cast(int, Unsigned)) + addAttribute = Method(Void, cast(int, Unsigned), ref(Attributes)) + removeAttribute = Method(Void, cast(int, Unsigned), ref(Attributes)) + getCalledFunction = Method(ptr(Function)) + getCalledValue = Method(ptr(Value)) + setCalledFunction = Method(Void, ptr(Function)) + isInlineAsm = Method(cast(Bool, bool)) @CmpInst class CmpInst: @@ -87,6 +143,8 @@ class CmpInst: 'LAST_ICMP_PREDICATE', 'BAD_ICMP_PREDICATE',) + getPredicate = Method(Predicate) + @ExtractElementInst class ExtractElementInst: pass @@ -113,7 +171,14 @@ class LandingPadInst: @PHINode class PHINode: - pass + getNumIncomingValues = Method(cast(Unsigned, int)) + getIncomingValue = Method(ptr(Value), cast(int, Unsigned)) + setIncomingValue = Method(Void, cast(int, Unsigned), ptr(Value)) + getIncomingBlock = Method(ptr(BasicBlock), cast(int, Unsigned)) + setIncomingBlock = Method(Void, cast(int, Unsigned), ptr(BasicBlock)) + addIncoming = Method(Void, ptr(Value), ptr(BasicBlock)) + hasConstantValue = Method(ptr(Value)) + getBasicBlockIndex = Method(cast(Int, int), ptr(BasicBlock)) @SelectInst class SelectInst: @@ -125,11 +190,24 @@ class ShuffleVectorInst: @StoreInst class StoreInst: - pass + _downcast_ = Instruction + isVolatile = Method(cast(Bool, bool)) + isSimple = Method(cast(Bool, bool)) + isUnordered = Method(cast(Bool, bool)) + isAtomic = Method(cast(Bool, bool)) + + setVolatile = Method(Void, cast(Bool, bool)) + + getAlignment = Method(cast(Unsigned, int)) + setAlignment = Method(Void, cast(int, Unsigned)) + + classof = StaticMethod(cast(Bool, bool), ptr(Value)) @TerminatorInst class TerminatorInst: - pass + getNumSuccessors = Method(cast(Unsigned, int)) + getSuccessor = Method(ptr(BasicBlock), cast(int, Unsigned)) + setSuccessor = Method(Void, cast(int, Unsigned), ptr(BasicBlock)) @UnaryInstruction class UnaryInstruction: @@ -162,7 +240,15 @@ class IndirectBrInst: @InvokeInst class InvokeInst: - pass + _downcast_ = Value, Instruction + getCallingConv = Method(CallingConv.ID) + setCallingConv = Method(Void, CallingConv.ID) + getParamAlignment = Method(cast(Unsigned, int), cast(int, Unsigned)) + addAttribute = Method(Void, cast(int, Unsigned), ref(Attributes)) + removeAttribute = Method(Void, cast(int, Unsigned), ref(Attributes)) + getCalledFunction = Method(ptr(Function)) + getCalledValue = Method(ptr(Value)) + setCalledFunction = Method(Void, ptr(Function)) @ResumeInst class ResumeInst: @@ -174,7 +260,13 @@ class ReturnInst: @SwitchInst class SwitchInst: - pass + getCondition = Method(ptr(Value)) + setCondition = Method(Void, ptr(Value)) + getDefaultDest = Method(ptr(BasicBlock)) + setDefaultDest = Method(Void, ptr(BasicBlock)) + getNumCases = Method(cast(int, Unsigned)) + addCase = Method(Void, ptr(ConstantInt), ptr(BasicBlock)) + @UnreachableInst class UnreachableInst: @@ -195,7 +287,18 @@ class ExtractValueInst: @LoadInst class LoadInst: - pass + _downcast_ = Value, Instruction + isVolatile = Method(cast(Bool, bool)) + isSimple = Method(cast(Bool, bool)) + isUnordered = Method(cast(Bool, bool)) + isAtomic = Method(cast(Bool, bool)) + + setVolatile = Method(Void, cast(Bool, bool)) + + getAlignment = Method(cast(Unsigned, int)) + setAlignment = Method(Void, cast(int, Unsigned)) + + classof = StaticMethod(cast(Bool, bool), ptr(Value)) @VAArgInst class VAArgInst: diff --git a/newbinding/src/Metadata.py b/newbinding/src/Metadata.py index bda09e1..338cbbd 100644 --- a/newbinding/src/Metadata.py +++ b/newbinding/src/Metadata.py @@ -31,6 +31,8 @@ class MDString: @llvm.Class() class NamedMDNode: eraseFromParent = Method() + eraseFromParent.disowning = True + dropAllReferences = Method() getParent = Method(ptr(Module)) getOperand = Method(ptr(MDNode), cast(int, Unsigned)) @@ -41,3 +43,10 @@ class NamedMDNode: print_.realname = "print" dump = Method() + + @CustomPythonMethod + def __str__(self): + import extra + os = extra.make_raw_ostream_for_printing() + self.print_(os, None) + return os.str() \ No newline at end of file From b9ac22d13688cb7ae2c99e14fbed92d96312e566 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 7 Feb 2013 15:31:54 -0600 Subject: [PATCH 55/85] More to BasicBlock --- newbinding/include/llvm_binding/extra.h | 8 +++++++- newbinding/src/BasicBlock.py | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index df0cecd..bde92a7 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -724,5 +724,11 @@ PyObject* MDNode_get(llvm::LLVMContext &Cxt, PyObject* Vals) } - +static +PyObject* BasicBlock_getInstList(llvm::BasicBlock* BB) +{ + return iplist_to_pylist(BB->getInstList(), + "llvm::Value", + "llvm::Instruction"); +} diff --git a/newbinding/src/BasicBlock.py b/newbinding/src/BasicBlock.py index 61a09d7..81edf37 100644 --- a/newbinding/src/BasicBlock.py +++ b/newbinding/src/BasicBlock.py @@ -20,3 +20,5 @@ class BasicBlock: isLandingPad = Method(cast(Bool, bool)) removePredecessor = Method(Void, ptr(BasicBlock), cast(bool, Bool)) removePredecessor |= Method(Void, ptr(BasicBlock)) + + getInstList = CustomMethod('BasicBlock_getInstList', PyObjectPtr) \ No newline at end of file From fe383ca326342472b325f60e79fca563873f10cd Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Thu, 7 Feb 2013 17:40:00 -0600 Subject: [PATCH 56/85] More to IRBuilder and Instruction --- newbinding/include/llvm_binding/extra.h | 15 +++++++ newbinding/src/IRBuilder.py | 54 ++++++++++++++++++++----- newbinding/src/Instruction.py | 40 ++++++++++++++---- 3 files changed, 90 insertions(+), 19 deletions(-) diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index bde92a7..75739de 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -14,6 +14,7 @@ #include #include #include +#include #include "auto_pyobject.h" @@ -732,3 +733,17 @@ PyObject* BasicBlock_getInstList(llvm::BasicBlock* BB) "llvm::Instruction"); } +static +PyObject* IRBuilder_CreateAggregateRet(llvm::IRBuilder<>* builder, + PyObject* Vals, + unsigned N) +{ + using namespace llvm; + std::vector vec_values; + bool ok = extract::from_py_sequence(vec_values, Vals, "llvm::Value"); + if (not ok) return NULL; + Value** ptr_values = &vec_values[0]; + ReturnInst* inst = builder->CreateAggregateRet(ptr_values, N); + return pycapsule_new(inst, "llvm::Value", "llvm:ReturnInst"); +} + diff --git a/newbinding/src/IRBuilder.py b/newbinding/src/IRBuilder.py index e0cac79..2965367 100644 --- a/newbinding/src/IRBuilder.py +++ b/newbinding/src/IRBuilder.py @@ -2,6 +2,7 @@ from binding import * from namespace import llvm from LLVMContext import LLVMContext from BasicBlock import BasicBlock +from Instruction import Instruction from Instruction import ReturnInst, CallInst, BranchInst, SwitchInst from Instruction import IndirectBrInst, InvokeInst, ResumeInst, PHINode from Instruction import UnreachableInst, AllocaInst, LoadInst, StoreInst @@ -23,12 +24,30 @@ class IRBuilder: new = Constructor(ref(LLVMContext)) delete = Destructor() - SetInsertPoint = Method(Void, ptr(BasicBlock)) + GetInsertBlock = Method(ptr(BasicBlock)) + + _SetInsertPoint_end_of_bb = Method(Void, ptr(BasicBlock)) + _SetInsertPoint_end_of_bb.realname = 'SetInsertPoint' + _SetInsertPoint_before_instr = Method(Void, ptr(Instruction)) + _SetInsertPoint_before_instr.realname = 'SetInsertPoint' + + @CustomPythonMethod + def SetInsertPoint(self, pt): + if isinstance(pt, Instruction): + return self._SetInsertPoint_before_instr(pt) + elif isinstance(pt, BasicBlock): + return self._SetInsertPoint_end_of_bb(pt) + else: + raise ValueError("Expected either an Instruction or a BasicBlock") isNamePreserving = Method(cast(Bool, bool)) CreateRetVoid = Method(ptr(ReturnInst)) CreateRet = Method(ptr(ReturnInst), ptr(Value)) + CreateAggregateRet = CustomMethod('IRBuilder_CreateAggregateRet', + PyObjectPtr, # ptr(ReturnInst), + PyObjectPtr, # list of Value + cast(int, Unsigned)) CreateBr = Method(ptr(BranchInst), ptr(BasicBlock)) @@ -42,9 +61,18 @@ class IRBuilder: CreateIndirectBr = Method(ptr(IndirectBrInst), ptr(Value), cast(int, Unsigned)).require_only(1) - CreateInvoke = Method(ptr(InvokeInst), ptr(Value), ptr(BasicBlock), + _CreateInvoke = Method(ptr(InvokeInst), ptr(Value), ptr(BasicBlock), ptr(BasicBlock), ref(SmallVector_Value), cast(str, StringRef)).require_only(4) + _CreateInvoke.realname = 'CreateInvoke' + + @CustomPythonMethod + def CreateInvoke(self, *args): + import extra + args = list(args) + valuelist = args[3] + args[3] = extra.make_small_vector_from_values(*valuelist) + return self._CreateInvoke(*args) CreateResume = Method(ptr(ResumeInst), ptr(Value)) @@ -114,8 +142,11 @@ class IRBuilder: ptr(Value), cast(str, StringRef)).require_only(1) - CreateAlloca = Method(ptr(AllocaInst), ptr(Type), ptr(Value), - cast(str, StringRef)).require_only(2) + CreateAlloca = Method(ptr(AllocaInst), + ptr(Type), # ty + ptr(Value), # arysize = 0 + cast(str, StringRef), # name = '' + ).require_only(1) CreateLoad = Method(ptr(LoadInst), ptr(Value), cast(str, StringRef)).require_only(1) @@ -208,6 +239,14 @@ class IRBuilder: cast(str, StringRef)).require_only(2) _CreateCall.realname = 'CreateCall' + @CustomPythonMethod + def CreateCall(self, *args): + import extra + args = list(args) + valuelist = args[1] + args[1] = extra.make_small_vector_from_values(*valuelist) + return self._CreateCall(*args) + # Skip specialized CreateICmp* and CreateFCmp* CreateICmp = Method(ptr(Value), CmpInst.Predicate, ptr(Value), ptr(Value), @@ -219,13 +258,6 @@ class IRBuilder: CreatePHI = Method(ptr(PHINode), ptr(Type), cast(int, Unsigned), cast(str, StringRef)).require_only(2) - @CustomPythonMethod - def CreateCall(self, *args): - import extra - args = list(args) - valuelist = args[1] - args[1] = extra.make_small_vector_from_values(*valuelist) - return self._CreateCall(*args) CreateSelect = Method(ptr(Value), ptr(Value), ptr(Value), ptr(Value), cast(str, StringRef)).require_only(3) diff --git a/newbinding/src/Instruction.py b/newbinding/src/Instruction.py index 79cf4a3..ca64072 100644 --- a/newbinding/src/Instruction.py +++ b/newbinding/src/Instruction.py @@ -5,6 +5,7 @@ from ADT.StringRef import StringRef from CallingConv import CallingConv from Attributes import Attributes from Constant import ConstantInt +from Type import Type Instruction = llvm.Class(User) @@ -57,6 +58,17 @@ FPToSIInst = llvm.Class(CastInst) FPToUIInst = llvm.Class(CastInst) FPTruncInst = llvm.Class(CastInst) +AtomicOrdering = llvm.Enum('AtomicOrdering', + 'NotAtomic', 'Unordered', 'Monotonic', 'Acquire', + 'Release', 'AcquireRelease', + 'SequentiallyConsistent') + +SynchronizationScope = llvm.Enum('SynchronizationScope', + 'SingleThread', 'CrossThread') + + + + @Instruction class Instruction: removeFromParent = Method() @@ -129,6 +141,18 @@ class CallInst: setCalledFunction = Method(Void, ptr(Function)) isInlineAsm = Method(cast(Bool, bool)) + CreateMalloc = StaticMethod(ptr(Instruction), + ptr(BasicBlock), # insertAtEnd + ptr(Type), # intptrty + ptr(Type), # allocty + ptr(Value), # allocsz + ptr(Value), # array size = 0 + ptr(Function), # malloc fn = 0 + cast(str, StringRef), # name + ).require_only(4) + + CreateFree = StaticMethod(ptr(Instruction), ptr(Value), ptr(BasicBlock)) + @CmpInst class CmpInst: Predicate = Enum('FCMP_FALSE', 'FCMP_OEQ', 'FCMP_OGT', 'FCMP_OGE', @@ -201,6 +225,10 @@ class StoreInst: getAlignment = Method(cast(Unsigned, int)) setAlignment = Method(Void, cast(int, Unsigned)) + setAtomic = Method(Void, + AtomicOrdering, + SynchronizationScope).require_only(1) + classof = StaticMethod(cast(Bool, bool), ptr(Value)) @TerminatorInst @@ -298,6 +326,10 @@ class LoadInst: getAlignment = Method(cast(Unsigned, int)) setAlignment = Method(Void, cast(int, Unsigned)) + setAtomic = Method(Void, + AtomicOrdering, + SynchronizationScope).require_only(1) + classof = StaticMethod(cast(Bool, bool), ptr(Value)) @VAArgInst @@ -345,11 +377,3 @@ class FPToUIInst: class FPTruncInst: pass -AtomicOrdering = llvm.Enum('AtomicOrdering', - 'NotAtomic', 'Unordered', 'Monotonic', 'Acquire', - 'Release', 'AcquireRelease', - 'SequentiallyConsistent') - -SynchronizationScope = llvm.Enum('SynchronizationScope', - 'SingleThread', 'CrossThread') - From 7c39bd1f5beb2182a6863ad48bd6d874041a53c1 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 8 Feb 2013 16:03:29 -0600 Subject: [PATCH 57/85] Refactor to allow sub-namespace declaration --- newbinding/Makefile | 10 +- newbinding/capsule.py | 2 +- newbinding/gen/binding.py | 225 ++++++++++++++++----- newbinding/gen/codegen.py | 6 + newbinding/gen/gen.py | 135 +++---------- newbinding/include/llvm_binding/binding.h | 12 +- newbinding/src/CallingConv.py | 5 +- newbinding/src/EngineBuilder.py | 7 +- newbinding/src/Intrinsics.py | 17 +- newbinding/src/Support/CodeGen.py | 26 +-- newbinding/src/Support/DynamicLibrary.py | 6 + newbinding/src/Target/TargetLibraryInfo.py | 5 +- newbinding/src/namespace.py | 5 +- 13 files changed, 264 insertions(+), 197 deletions(-) create mode 100644 newbinding/src/Support/DynamicLibrary.py diff --git a/newbinding/Makefile b/newbinding/Makefile index 0e7924f..9de1fb0 100644 --- a/newbinding/Makefile +++ b/newbinding/Makefile @@ -5,18 +5,18 @@ all: _api.so _capsule.so _api.so _capsule.so: api.cpp capsule.cpp $(PYTHON) setup.py build_ext --inplace -api.cpp api.py: src/*.py include/llvm_binding/*.h gen/gen.py gen/binding.py +api.cpp api/__init__.py: src/*.py include/llvm_binding/*.h gen/gen.py gen/binding.py $(PYTHON) gen/gen.py api src clean: cleantemp rm -f _api.so _capsule.so + rm -rf api + py_clean cleantemp: - rm -f api.cpp api.py - rm -f src/*.pyc src/Transforms/*.pyc src/ADT/*.pyc src/Assembly/*.pyc src/CodeGen/*.pyc src/ExecutionEngine/*.pyc src/Target/*.pyc src/Transforms/*.pyc + rm -f api.cpp - -check: _api.so api.py +check: _api.so api/__init__.py $(PYTHON) test_binding.py @PHONY: all clean check diff --git a/newbinding/capsule.py b/newbinding/capsule.py index e29948d..d98a23d 100644 --- a/newbinding/capsule.py +++ b/newbinding/capsule.py @@ -182,7 +182,7 @@ def downcast(obj, cls): fname = 'downcast_%s_to_%s' % (fromty, toty) fname = fname.replace('::', '_') try: - caster = getattr(_api, fname) + caster = getattr(_api.downcast, fname) except AttributeError: fmt = "Downcast from %s to %s is not supported" raise TypeError(fmt % (fromty, toty)) diff --git a/newbinding/gen/binding.py b/newbinding/gen/binding.py index c1e1d1e..601ac6e 100644 --- a/newbinding/gen/binding.py +++ b/newbinding/gen/binding.py @@ -1,19 +1,157 @@ import inspect, textwrap import functools import codegen as cg +import os _rank = 0 namespaces = {} RESERVED = frozenset(['None']) -class Namespace(object): - def __init__(self, name): - self.name = name +def makedir(directory): + if not os.path.exists(directory): + os.makedirs(directory) + +class SubModule(object): + def __init__(self): + self.methods = [] self.enums = [] self.classes = [] - self.functions = [] + self.namespaces = [] + self.attrs = [] self.includes = set() + + def aggregate_includes(self): + includes = set(self.includes) + for unit in self.iter_all(): + if isinstance(unit, SubModule): + includes |= unit.aggregate_includes() + else: + includes |= unit.includes + return includes + + def aggregate_downcast(self): + dclist = [] + for cls in self.classes: + for bcls in cls.downcastables: + from_to = bcls.fullname, cls.fullname + name = 'downcast_%s_to_%s' % tuple(map(cg.mangle, from_to)) + fn = Function(namespaces[''], name, ptr(cls), ptr(bcls)) + dclist.append((from_to, fn)) + for ns in self.namespaces: + dclist.extend(ns.aggregate_downcast()) + return dclist + + def iter_all(self): + for fn in self.methods: + yield fn + for cls in self.classes: + yield cls + for enum in self.enums: + yield enum + for attr in self.attrs: + yield attr + for ns in self.namespaces: + yield ns + + + def generate_method_table(self, println): + writer = cg.CppCodeWriter(println) + writer.println('static') + writer.println('PyMethodDef meth_%s[] = {' % cg.mangle(self.fullname)) + with writer.indent(): + fmt = '{ "%(name)s", (PyCFunction)%(func)s, METH_VARARGS, NULL },' + for meth in self.methods: + name = meth.name + func = meth.c_name + writer.println(fmt % locals()) + for enumkind in self.enums: + for enum in enumkind.value_names: + name = enum + func = enumkind.c_name(enum) + writer.println(fmt % locals()) + for attr in self.attrs: + # getter + name = attr.getter_name + func = attr.getter_c_name + writer.println(fmt % locals()) + # setter + name = attr.setter_name + func = attr.setter_c_name + writer.println(fmt % locals()) + writer.println('{ NULL },') + writer.println('};') + writer.println() + + def generate_downcasts(self, println): + for ((fromty, toty), fn) in self.downcastlist: + name = fn.name + fmt = ''' +static +%(toty)s* %(name)s(%(fromty)s* arg) +{ + return typecast<%(toty)s>::from(arg); +} + ''' + println(fmt % locals()) + + fn.generate_cpp(println) + + def generate_cpp(self, println, extras=()): + for unit in self.iter_all(): + unit.generate_cpp(println) + self.generate_method_table(println) + self.generate_submodule_table(println, extras=extras) + + def generate_submodule_table(self, println, extras=()): + writer = cg.CppCodeWriter(println) + writer.println('static') + name = cg.mangle(self.fullname) + writer.println('SubModuleEntry submodule_%(name)s[] = {' % locals()) + with writer.indent(): + for cls in self.classes: + name = cls.name + table = cg.mangle(cls.fullname) + writer.println('{ "%(name)s", meth_%(table)s, NULL },' % + locals()) + for ns in self.namespaces: + name = ns.localname + table = cg.mangle(ns.fullname) + fmt = '{ "%(name)s", meth_%(table)s, submodule_%(table)s },' + writer.println(fmt % locals()) + for name, table in extras: + writer.println('{ "%(name)s", %(table)s, NULL },' % locals()) + writer.println('{ NULL }') + writer.println('};') + writer.println('') + + def generate_py(self, rootdir='.', name=''): + name = name or self.localname + if self.namespaces: # should make new directory + path = os.path.join(rootdir, name) + makedir(path) + filepath = os.path.join(path, '__init__.py') + else: + filepath = os.path.join(rootdir, '%s.py' % name) + with open(filepath, 'w') as pyfile: + println = cg.wrap_println_from_file(pyfile) + println('import _api, capsule') + for ns in self.namespaces: + println('from . import %s' % ns.localname) + println() + for unit in self.iter_all(): + if not isinstance(unit, Namespace): + writer = cg.PyCodeWriter(println) + unit.compile_py(writer) + + for ns in self.namespaces: + ns.generate_py(rootdir=path) + + +class Namespace(SubModule): + def __init__(self, name): + SubModule.__init__(self) + self.name = name namespaces[name] = self def Class(self, *bases): @@ -23,12 +161,12 @@ class Namespace(object): def Function(self, *args): fn = Function(self, *args) - self.functions.append(fn) + self.methods.append(fn) return fn def CustomFunction(self, *args): fn = CustomFunction(self, *args) - self.functions.append(fn) + self.methods.append(fn) return fn def Enum(self, name, *value_names): @@ -36,12 +174,23 @@ class Namespace(object): enum.parent = self enum.name = name self.enums.append(enum) + assert name not in vars(self), 'Duplicated' + setattr(self, name, enum) return enum + def Namespace(self, name): + ns = Namespace('::'.join([self.name, name])) + self.namespaces.append(ns) + return ns + @property def fullname(self): return self.name + @property + def localname(self): + return self.name.rsplit('::', 1)[-1] + def __str__(self): return self.name @@ -80,18 +229,15 @@ ConstCharPtr = BuiltinTypes('const char*') PyObjectPtr = BuiltinTypes('PyObject*') PyObjectPtr.format='O' -class Class(_Type): +class Class(SubModule, _Type): format = 'O' def __init__(self, ns, *bases): + SubModule.__init__(self) self.ns = ns self.bases = bases self._is_defined = False - self.methods = [] self.pymethods = [] - self.enums = [] - self.attrs = [] - self.includes = set() self.downcastables = set() def __call__(self, defn): @@ -110,6 +256,7 @@ class Class(_Type): self.enums.append(v) v.name = k v.parent = self + assert k not in vars(self), "Duplicated: %s" % k setattr(self, k, v) elif isinstance(v, Attr): self.attrs.append(v) @@ -133,43 +280,6 @@ class Class(_Type): self.downcastables.add(i) return self - def compile_cpp(self, writer): - # generate methods - for meth in self.methods: - meth.compile_cpp(writer) - for enum in self.enums: - enum.compile_cpp(writer) - for attr in self.attrs: - attr.compile_cpp(writer) - - # generate method table - writer.println('static') - writer.println('PyMethodDef %s[] = {' % cg.mangle(self.fullname)) - with writer.indent(): - fmt = '{ "%(name)s", (PyCFunction)%(func)s, METH_VARARGS, NULL },' - for meth in self.methods: - name = meth.name - func = meth.c_name - writer.println(fmt % locals()) - for enumkind in self.enums: - for enum in enumkind.value_names: - name = enum - func = enumkind.c_name(enum) - writer.println(fmt % locals()) - for attr in self.attrs: - # getter - name = attr.getter_name - func = attr.getter_c_name - writer.println(fmt % locals()) - # setter - name = attr.setter_name - func = attr.setter_c_name - writer.println(fmt % locals()) - - writer.println('{ NULL },') - writer.println('};') - writer.println() - def compile_py(self, writer): clsname = self.name bases = 'capsule.Wrapper' @@ -256,6 +366,9 @@ class Enum(object): def c_name(self, enum): return cg.mangle("%s_%s_%s" % (self.parent, self.name, enum)) + def generate_cpp(self, println): + self.compile_cpp(cg.CppCodeWriter(println)) + def compile_cpp(self, writer): for enum in self.value_names: with writer.py_function(self.c_name(enum)): @@ -322,6 +435,9 @@ class Method(object): def __str__(self): return self.fullname + def generate_cpp(self, println): + self.compile_cpp(cg.CppCodeWriter(println)) + def compile_cpp(self, writer): with writer.py_function(self.c_name): if len(self.signatures) == 1: @@ -454,9 +570,12 @@ 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.name - ret = writer.call('_api.%s' % func, - varargs=unwrapped) + if '::' in self.parent.name: + ns = self.parent.name.split('::', 1)[-1].replace('::', '.') + func = '.'.join([ns, self.name]) + else: + 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() @@ -630,6 +749,7 @@ class Attr(object): def __init__(self, getter, setter): self.getter = getter self.setter = setter + self.includes = set() @property def fullname(self): @@ -658,6 +778,9 @@ class Attr(object): def setter_c_name(self): return cg.mangle('%s_set' % self.fullname) + def generate_cpp(self, println): + self.compile_cpp(cg.CppCodeWriter(println)) + def compile_cpp(self, writer): # getter with writer.py_function(self.getter_c_name): diff --git a/newbinding/gen/codegen.py b/newbinding/gen/codegen.py index 5a31e38..dd499d6 100644 --- a/newbinding/gen/codegen.py +++ b/newbinding/gen/codegen.py @@ -4,6 +4,12 @@ NULL = 'NULL' _symbols = set() +def wrap_println_from_file(file): + def println(s=''): + file.write(s) + file.write('\n') + return println + def indent(println): def _println(s=''): println("%s%s" % (' '* 4, s)) diff --git a/newbinding/gen/gen.py b/newbinding/gen/gen.py index 89399f3..bb7eab3 100644 --- a/newbinding/gen/gen.py +++ b/newbinding/gen/gen.py @@ -14,7 +14,7 @@ PyInit_%(module)s(void) { PyObject *module = create_python_module("%(module)s", %(methtable)s); if (module) { -if (populate_submodules(module, submodules)) +if (populate_submodules(module, submodule_llvm)) return module; } return NULL; @@ -27,7 +27,7 @@ init%(module)s(void) { PyObject *module = create_python_module("%(module)s", %(methtable)s); if (module) { -populate_submodules(module, submodules); +populate_submodules(module, submodule_llvm); } } #endif @@ -49,65 +49,25 @@ def populate_headers(println): println('#include "%s"' % inc) println() - -def wrap_println_from_file(file): - def println(s=''): - file.write(s) - file.write('\n') - return println - def main(): outputfilename = sys.argv[1] entry_modname = sys.argv[2] sys.path += [os.path.dirname(os.curdir)] entry_module = __import__(entry_modname) - units = [] - for ns in namespaces.values(): - print 'namespace', ns - for fn in ns.functions: - print fn - units.append(fn) - for cls in ns.classes: - print cls - units.append(cls) - for enum in ns.enums: - print enum - units.append(enum) - - # add extra stuffs - downcastlist = [] - ## add downcast - for cls in units: - if isinstance(cls, Class): - for bcls in cls.downcastables: - from_to = bcls.fullname, cls.fullname - name = 'downcast_%s_to_%s' % tuple(map(codegen.mangle, from_to)) - fn = Function(namespaces[''], name, ptr(cls), ptr(bcls)) - downcastlist.append((from_to, fn)) - units.append(fn) - + rootns = namespaces['llvm'] # Generate C++ source with open('%s.cpp' % outputfilename, 'w') as cppfile: - println = wrap_println_from_file(cppfile) - - # extra headers - populate_headers(println) - - # required headers - includes = set() - for ns in namespaces.values(): - includes |= ns.includes - for u in units: - includes |= u.includes - - for inc in includes: + println = codegen.wrap_println_from_file(cppfile) + populate_headers(println) # extra headers + # print all includes + for inc in rootns.aggregate_includes(): println('#include "%s"' % inc) println() - - # generate downcast - for ((fromty, toty), fn) in downcastlist: + # print all downcast + downcast_fns = rootns.aggregate_downcast() + for ((fromty, toty), fn) in downcast_fns: name = fn.name fmt = ''' static @@ -117,65 +77,28 @@ static } ''' println(fmt % locals()) + + fn.generate_cpp(println) - # write methods and method tables - for u in units: - writer = codegen.CppCodeWriter(println) - u.compile_cpp(writer) - else: - del writer - - # write function table - writer = codegen.CppCodeWriter(println) - writer.println('static') - writer.println('PyMethodDef methtable[] = {') - with writer.indent(): - fmt = '{ "%(name)s", (PyCFunction)%(func)s, METH_VARARGS, NULL },' - for u in units: - if isinstance(u, Function): - name = u.name - func = u.c_name - writer.println(fmt % locals()) - for u in units: - if isinstance(u, Enum): - for enum in u.value_names: - name = enum - func = u.c_name(enum) - writer.println(fmt % locals()) - - writer.println('{ NULL },') - writer.println('};') - writer.println() - del writer - - - # write submodule table - writer = codegen.CppCodeWriter(println) - writer.println('static') - writer.println('SubModuleEntry submodules[] = {') - with writer.indent(): - for cls in units: - if isinstance(cls, Class): - name = cls.name - table = codegen.mangle(cls.fullname) - writer.println('{ "%(name)s", %(table)s },' % locals()) - writer.println('{ "extra", extra_methodtable },') - writer.println('{ NULL }') - writer.println('};') - writer.println('') - del writer - - println(extension_entry % {'module': '_api', 'methtable': 'methtable'}) + println('static') + println('PyMethodDef downcast_methodtable[] = {') + fmt = '{ "%(name)s", (PyCFunction)%(func)s, METH_VARARGS, NULL },' + for _, fn in downcast_fns: + name = fn.name + func = fn.c_name + println(fmt % locals()) + println('{ NULL }') + println('};') + println() + # generate submodule + rootns.generate_cpp(println, extras=[('extra', 'extra_methodtable'), + ('downcast', 'downcast_methodtable')]) + println(extension_entry % {'module' : '_api', + 'methtable': 'meth_llvm'}) # Generate Python source - with open('%s.py' % outputfilename, 'w') as pyfile: - println = wrap_println_from_file(pyfile) - println('import _api, capsule') - println() - for u in units: - writer = codegen.PyCodeWriter(println) - u.compile_py(writer) - + rootns.generate_py(rootdir='.', name='api') + if __name__ == '__main__': main() diff --git a/newbinding/include/llvm_binding/binding.h b/newbinding/include/llvm_binding/binding.h index 58a8ad0..68af615 100644 --- a/newbinding/include/llvm_binding/binding.h +++ b/newbinding/include/llvm_binding/binding.h @@ -63,13 +63,23 @@ create_python_submodule(PyObject* parent, const char* name, struct SubModuleEntry{ const char* name; PyMethodDef* methtable; + SubModuleEntry* submodule; }; static int populate_submodules(PyObject* parent, SubModuleEntry* entries){ for(SubModuleEntry* iter = entries; iter->name; ++iter){ - if (!create_python_submodule(parent, iter->name, iter->methtable)) + PyObject* submodule = create_python_submodule(parent, + iter->name, + iter->methtable); + if (!submodule){ return 0; + } else if (iter->submodule){ + // Recursively populate submodules + if (!populate_submodules(submodule, iter->submodule)) { + return 0; + } + } } return 1; } diff --git a/newbinding/src/CallingConv.py b/newbinding/src/CallingConv.py index 6d0baea..71b4ad3 100644 --- a/newbinding/src/CallingConv.py +++ b/newbinding/src/CallingConv.py @@ -1,9 +1,8 @@ from binding import * from namespace import llvm -@llvm.Class() # actually a namespace -class CallingConv: - ID = Enum(''' +CallingConv = llvm.Namespace('CallingConv') +ID = CallingConv.Enum('ID', ''' C, Fast, Cold, GHC, FirstTargetCC, X86_StdCall, X86_FastCall, ARM_APCS, ARM_AAPCS, ARM_AAPCS_VFP, MSP430_INTR, X86_ThisCall, PTX_Kernel, PTX_Device, MBLAZE_INTR, MBLAZE_SVOL, SPIR_FUNC, diff --git a/newbinding/src/EngineBuilder.py b/newbinding/src/EngineBuilder.py index 4b68a25..c3feafe 100644 --- a/newbinding/src/EngineBuilder.py +++ b/newbinding/src/EngineBuilder.py @@ -10,9 +10,8 @@ from ADT.Triple import Triple EngineBuilder = llvm.Class() -@llvm.Class() # a fake class (actually a namespace) -class EngineKind: - Kind = Enum('JIT', 'Interpreter') +EngineKind = llvm.Namespace('EngineKind') +Kind = EngineKind.Enum('Kind', 'JIT', 'Interpreter') @EngineBuilder class EngineBuilder: @@ -22,7 +21,7 @@ class EngineBuilder: def _setter(*args): return Method(ref(EngineBuilder), *args) - setEngineKind = _setter(EngineKind.Kind) + setEngineKind = _setter(Kind) setJITMemoryManager = _setter(ptr(JITMemoryManager)) setErrorStr = CustomMethod('EngineBuilder_setErrorStr', diff --git a/newbinding/src/Intrinsics.py b/newbinding/src/Intrinsics.py index 0f1bcb4..5314112 100644 --- a/newbinding/src/Intrinsics.py +++ b/newbinding/src/Intrinsics.py @@ -5,13 +5,12 @@ from Module import Module from Function import Function -Intrinsic = llvm.Class() # fake class (actually a namespace) +Intrinsic = llvm.Namespace('Intrinsic') -@Intrinsic -class Intrinsic: - getDeclaration = CustomStaticMethod('Intrinsic_getDeclaration', - PyObjectPtr, # Function* - ptr(Module), - cast(int, Unsigned), # intrinsic id - PyObjectPtr, # list of Type - ).require_only(2) +getDeclaration = Intrinsic.CustomFunction('getDeclaration', + 'Intrinsic_getDeclaration', + PyObjectPtr, # Function* + ptr(Module), + cast(int, Unsigned), # intrinsic id + PyObjectPtr, # list of Type + ).require_only(2) diff --git a/newbinding/src/Support/CodeGen.py b/newbinding/src/Support/CodeGen.py index 013caa1..3bc6f9d 100644 --- a/newbinding/src/Support/CodeGen.py +++ b/newbinding/src/Support/CodeGen.py @@ -1,20 +1,20 @@ from binding import * from ..namespace import llvm -@llvm.Class() -class Reloc: - Model = Enum('Default', 'Static', 'PIC_', 'DynamicNoPIC') -@llvm.Class() -class CodeModel: - Model = Enum('Default', 'JITDefault', 'Small', 'Kernel', 'Medium', 'Large') +Reloc = llvm.Namespace('Reloc') +Reloc.Enum('Model', + 'Default', 'Static', 'PIC_', 'DynamicNoPIC') -@llvm.Class() -class TLSModel: - Model = Enum('GeneralDynamic', 'LocalDynamic', 'InitialExec', 'LocalExec') +CodeModel = llvm.Namespace('CodeModel') +CodeModel.Enum('Model', + 'Default', 'JITDefault', 'Small', 'Kernel', 'Medium', 'Large') -@llvm.Class() -class CodeGenOpt: - 'Actually a namespace' - Level = Enum('None', 'Less', 'Default', 'Aggressive') +TLSModel = llvm.Namespace('TLSModel') +TLSModel.Enum('Model', + 'GeneralDynamic', 'LocalDynamic', 'InitialExec', 'LocalExec') + +CodeGenOpt = llvm.Namespace('CodeGenOpt') +CodeGenOpt.Enum('Level', + 'None', 'Less', 'Default', 'Aggressive') diff --git a/newbinding/src/Support/DynamicLibrary.py b/newbinding/src/Support/DynamicLibrary.py new file mode 100644 index 0000000..7f661d3 --- /dev/null +++ b/newbinding/src/Support/DynamicLibrary.py @@ -0,0 +1,6 @@ +from binding import * +from ..namespace import sys + +DynamicLibrary = sys.Namespace('DynamicLibrary') +#LoadLibraryPermanently + diff --git a/newbinding/src/Target/TargetLibraryInfo.py b/newbinding/src/Target/TargetLibraryInfo.py index b90c619..d98b00b 100644 --- a/newbinding/src/Target/TargetLibraryInfo.py +++ b/newbinding/src/Target/TargetLibraryInfo.py @@ -6,9 +6,8 @@ from ..ADT.StringRef import StringRef TargetLibraryInfo = llvm.Class(ImmutablePass) -@llvm.Class() -class LibFunc: - Func = Enum(''' +LibFunc = llvm.Namespace('LibFunc') +LibFunc.Enum('Func', ''' ZdaPv, ZdlPv, Znaj, ZnajRKSt9nothrow_t, Znam, ZnamRKSt9nothrow_t, Znwj, ZnwjRKSt9nothrow_t, Znwm, ZnwmRKSt9nothrow_t, cxa_atexit, cxa_guard_abort, diff --git a/newbinding/src/namespace.py b/newbinding/src/namespace.py index 3a081af..f833af8 100644 --- a/newbinding/src/namespace.py +++ b/newbinding/src/namespace.py @@ -1,4 +1,7 @@ from binding import * -llvm = Namespace('llvm') default = Namespace('') + +llvm = Namespace('llvm') +sys = llvm.Namespace('sys') + From 6eae24bcf3966471dc8404805af5c609a331642c Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 8 Feb 2013 18:10:52 -0600 Subject: [PATCH 58/85] Set default namespace to top-level C++ namespace. --- newbinding/gen/binding.py | 58 +++++++------ newbinding/gen/gen.py | 16 ++-- newbinding/test_binding.py | 170 ++++++++++++++++++------------------- 3 files changed, 124 insertions(+), 120 deletions(-) diff --git a/newbinding/gen/binding.py b/newbinding/gen/binding.py index 601ac6e..51620a8 100644 --- a/newbinding/gen/binding.py +++ b/newbinding/gen/binding.py @@ -83,19 +83,19 @@ class SubModule(object): writer.println('};') writer.println() - def generate_downcasts(self, println): - for ((fromty, toty), fn) in self.downcastlist: - name = fn.name - fmt = ''' -static -%(toty)s* %(name)s(%(fromty)s* arg) -{ - return typecast<%(toty)s>::from(arg); -} - ''' - println(fmt % locals()) - - fn.generate_cpp(println) +# def generate_downcasts(self, println): +# for ((fromty, toty), fn) in self.downcastlist: +# name = fn.name +# fmt = ''' +#static +#%(toty)s* %(name)s(%(fromty)s* arg) +#{ +# return typecast< %(toty)s >::from(arg); +#} +# ''' +# println(fmt % locals()) +# +# fn.generate_cpp(println) def generate_cpp(self, println, extras=()): for unit in self.iter_all(): @@ -151,7 +151,7 @@ static class Namespace(SubModule): def __init__(self, name): SubModule.__init__(self) - self.name = name + self.name = name = name.lstrip(':') namespaces[name] = self def Class(self, *bases): @@ -187,6 +187,10 @@ class Namespace(SubModule): def fullname(self): return self.name + @property + def py_name(self): + return self.name.replace('::', '.') + @property def localname(self): return self.name.rsplit('::', 1)[-1] @@ -313,6 +317,11 @@ class Class(SubModule, _Type): name = self.name return '::'.join([self.ns.fullname, name]) + @property + def py_name(self): + ns = self.ns.name.split('::') + return '.'.join(ns + [self.name]) + def __str__(self): return self.fullname @@ -323,7 +332,7 @@ class Class(SubModule, _Type): writer.die_if_false(raw) ptrty = ptr(self).fullname ty = self.fullname - fmt = 'typecast<%(ty)s >::from(%(raw)s)' + fmt = 'typecast< %(ty)s >::from(%(raw)s)' casted = writer.declare(ptrty, fmt % locals()) writer.die_if_false(casted) return casted @@ -385,7 +394,7 @@ class Enum(object): else: k = v fmt = '%(k)s = %(p)s.%(v)s()' - p = '.'.join(['_api'] + self.parent.fullname.split('::')[1:]) + p = '.'.join(['_api'] + self.parent.fullname.split('::')) writer.println(fmt % locals()) writer.println() @@ -415,7 +424,7 @@ class Method(object): @property def fullname(self): - return '::'.join([self.parent.fullname, self.realname]) + return '::'.join([self.parent.fullname, self.realname]).lstrip(':') @property def realname(self): @@ -472,8 +481,7 @@ class Method(object): writer.release_ownership(unwrap_this) unwrapped = writer.unwrap_many(varargs) self.process_ownedptr_args(writer, unwrapped) - - func = '.'.join([self.parent.name, self.name]) + func = '.'.join([self.parent.py_name, self.name]) ret = writer.call('_api.%s' % func, args=(unwrap_this,), varargs=unwrapped) @@ -537,7 +545,7 @@ class StaticMethod(Method): unwrapped = writer.unwrap_many(varargs) self.process_ownedptr_args(writer, unwrapped) - func = '.'.join([self.parent.name, self.name]) + func = '.'.join([self.parent.py_name, self.name]) ret = writer.call('_api.%s' % func, varargs=unwrapped) wrapped = writer.wrap(ret, self.is_return_ownedptr()) writer.return_value(wrapped) @@ -570,11 +578,7 @@ class Function(Method): with writer.function(self.name, varargs='args') as varargs: unwrapped = writer.unwrap_many(varargs) self.process_ownedptr_args(writer, unwrapped) - if '::' in self.parent.name: - ns = self.parent.name.split('::', 1)[-1].replace('::', '.') - func = '.'.join([ns, self.name]) - else: - func = self.name + func = '.'.join([self.parent.py_name, self.name]) ret = writer.call('_api.%s' % func, varargs=unwrapped) wrapped = writer.wrap(ret, self.is_return_ownedptr()) writer.return_value(wrapped) @@ -603,7 +607,7 @@ class Destructor(Method): writer.return_value(None) def compile_py(self, writer): - func = '.'.join([self.parent.name, self.name]) + func = '.'.join([self.parent.py_name, self.name]) writer.println('_delete_ = _api.%s' % func) @@ -799,7 +803,7 @@ class Attr(object): def compile_py(self, writer): name = self.name - parent = '.'.join(self.parent.fullname.split('::')[1:]) + parent = '.'.join(self.parent.fullname.split('::')) getter = '.'.join([parent, self.getter_name]) setter = '.'.join([parent, self.setter_name]) writer.println('@property') diff --git a/newbinding/gen/gen.py b/newbinding/gen/gen.py index bb7eab3..c5d30de 100644 --- a/newbinding/gen/gen.py +++ b/newbinding/gen/gen.py @@ -12,9 +12,9 @@ extern "C" { PyObject * PyInit_%(module)s(void) { -PyObject *module = create_python_module("%(module)s", %(methtable)s); +PyObject *module = create_python_module("%(module)s", meth_%(ns)s); if (module) { -if (populate_submodules(module, submodule_llvm)) +if (populate_submodules(module, submodule_%(ns)s)) return module; } return NULL; @@ -25,9 +25,9 @@ return NULL; PyMODINIT_FUNC init%(module)s(void) { -PyObject *module = create_python_module("%(module)s", %(methtable)s); +PyObject *module = create_python_module("%(module)s", meth_%(ns)s); if (module) { -populate_submodules(module, submodule_llvm); +populate_submodules(module, submodule_%(ns)s); } } #endif @@ -55,7 +55,7 @@ def main(): sys.path += [os.path.dirname(os.curdir)] entry_module = __import__(entry_modname) - rootns = namespaces['llvm'] + rootns = namespaces[''] # Generate C++ source with open('%s.cpp' % outputfilename, 'w') as cppfile: @@ -73,7 +73,7 @@ def main(): static %(toty)s* %(name)s(%(fromty)s* arg) { - return typecast<%(toty)s>::from(arg); + return typecast< %(toty)s >::from(arg); } ''' println(fmt % locals()) @@ -93,8 +93,8 @@ static # generate submodule rootns.generate_cpp(println, extras=[('extra', 'extra_methodtable'), ('downcast', 'downcast_methodtable')]) - println(extension_entry % {'module' : '_api', - 'methtable': 'meth_llvm'}) + println(extension_entry % {'module' : '_api', + 'ns' : ''}) # Generate Python source rootns.generate_py(rootdir='.', name='api') diff --git a/newbinding/test_binding.py b/newbinding/test_binding.py index 9003f7d..7fa5e2c 100644 --- a/newbinding/test_binding.py +++ b/newbinding/test_binding.py @@ -1,22 +1,22 @@ -import api +from api import llvm import extra import _capsule from StringIO import StringIO -api.capsule.set_debug(True) +llvm.capsule.set_debug(True) def test_basic_jit_use(): - api.InitializeNativeTarget() - api.InitializeNativeTargetAsmPrinter() - context = api.getGlobalContext() + llvm.InitializeNativeTarget() + llvm.InitializeNativeTargetAsmPrinter() + context = llvm.getGlobalContext() - m = api.Module.new("modname", context) + m = llvm.Module.new("modname", context) print m.getModuleIdentifier() m.setModuleIdentifier('modname2') print m.getModuleIdentifier() print 'endianness', m.getEndianness() - assert m.getEndianness() == api.Module.Endianness.AnyEndianness + assert m.getEndianness() == llvm.Module.Endianness.AnyEndianness print 'pointer-size', m.getPointerSize() - assert m.getPointerSize() == api.Module.PointerSize.AnyPointerSize + assert m.getPointerSize() == llvm.Module.PointerSize.AnyPointerSize m.dump() @@ -25,21 +25,21 @@ def test_basic_jit_use(): print os.str() - int1ty = api.Type.getInt1Ty(context) + int1ty = llvm.Type.getInt1Ty(context) int1ty.dump() assert int1ty.isIntegerTy(1) - fnty = api.FunctionType.get(int1ty, False) + fnty = llvm.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 = [llvm.Type.getIntNTy(context, 8), llvm.Type.getIntNTy(context, 32)] + fnty = llvm.FunctionType.get(llvm.Type.getIntNTy(context, 8), types, False) print fnty const = m.getOrInsertFunction("foo", fnty) - fn = const._downcast(api.Function) + fn = const._downcast(llvm.Function) print fn assert fn.hasName() assert 'foo' == fn.getName() @@ -58,10 +58,10 @@ def test_basic_jit_use(): assert isinstance(fn_uselist, list) assert len(fn_uselist) == 0 - builder = api.IRBuilder.new(context) + builder = llvm.IRBuilder.new(context) print builder - bb = api.BasicBlock.Create(context, "entry", fn, None) + bb = llvm.BasicBlock.Create(context, "entry", fn, None) assert bb.empty() builder.SetInsertPoint(bb) @@ -83,23 +83,23 @@ def test_basic_jit_use(): print m # verifier - action = api.VerifierFailureAction.ReturnStatusAction + action = llvm.VerifierFailureAction.ReturnStatusAction - corrupted = api.verifyFunction(fn, action) + corrupted = llvm.verifyFunction(fn, action) assert not corrupted - corrupted = api.verifyModule(m, action, errio) + corrupted = llvm.verifyModule(m, action, errio) print corrupted assert not corrupted, errio.getvalue() # build pass manager - pmb = api.PassManagerBuilder.new() + pmb = llvm.PassManagerBuilder.new() pmb.OptLevel = 3 assert pmb.OptLevel == 3 - pmb.LibraryInfo = api.TargetLibraryInfo.new() - pmb.Inliner = api.createFunctionInliningPass() + pmb.LibraryInfo = llvm.TargetLibraryInfo.new() + pmb.Inliner = llvm.createFunctionInliningPass() - fpm = api.FunctionPassManager.new(m) - pm = api.PassManager.new() + fpm = llvm.FunctionPassManager.new(m) + pm = llvm.PassManager.new() pmb.populateFunctionPassManager(fpm) pmb.populateModulePassManager(pm) @@ -114,14 +114,14 @@ def test_basic_jit_use(): # build engine - ee = api.ExecutionEngine.createJIT(m, errio) + ee = llvm.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' - 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(llvm.DataLayout.new(datalayout_str)) + assert datalayout_str == str(llvm.DataLayout.new(str(llvm.DataLayout.new(datalayout_str)))) fn2 = ee.FindFunctionNamed(fn.getName()) assert fn2 is fn @@ -129,8 +129,8 @@ def test_basic_jit_use(): 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 = llvm.GenericValue.CreateInt(arg0.getType(), 12, False) + gv1 = llvm.GenericValue.CreateInt(arg1.getType(), -32, True) assert gv0.valueIntWidth() == arg0.getType().getIntegerBitWidth() assert gv1.valueIntWidth() == arg1.getType().getIntegerBitWidth() @@ -138,7 +138,7 @@ def test_basic_jit_use(): assert gv0.toUnsignedInt() == 12 assert gv1.toSignedInt() == -32 - gv1 = api.GenericValue.CreateInt(arg1.getType(), 32, False) + gv1 = llvm.GenericValue.CreateInt(arg1.getType(), 32, False) gvR = ee.runFunction(fn, (gv0, gv1)) @@ -146,13 +146,13 @@ def test_basic_jit_use(): # write bitcode bc_buffer = StringIO() - api.WriteBitcodeToFile(m, bc_buffer) + llvm.WriteBitcodeToFile(m, bc_buffer) bc = bc_buffer.getvalue() bc_buffer.close() # read bitcode errbuf = StringIO() - m2 = api.ParseBitCodeFile(bc, context, errbuf) + m2 = llvm.ParseBitCodeFile(bc, context, errbuf) if not m2: raise Exception(errbuf.getvalue()) else: @@ -160,35 +160,35 @@ def test_basic_jit_use(): assert str(m2) == str(m) # parse llvm ir - m3 = api.ParseAssemblyString(str(m), None, api.SMDiagnostic.new(), context) + m3 = llvm.ParseAssemblyString(str(m), None, llvm.SMDiagnostic.new(), context) m3.setModuleIdentifier(m.getModuleIdentifier()) assert str(m3) == str(m) # test clone - m4 = api.CloneModule(m) + m4 = llvm.CloneModule(m) assert m4 is not m assert str(m4) == str(m) def test_engine_builder(): - api.InitializeNativeTarget() - context = api.getGlobalContext() + llvm.InitializeNativeTarget() + context = llvm.getGlobalContext() - m = api.Module.new("modname", context) + m = llvm.Module.new("modname", context) - int32ty = api.Type.getIntNTy(context, 32) - fnty = api.FunctionType.get(int32ty, [int32ty], False) - fn = m.getOrInsertFunction("foo", fnty)._downcast(api.Function) - bb = api.BasicBlock.Create(context, "entry", fn, None) - builder = api.IRBuilder.new(context) + int32ty = llvm.Type.getIntNTy(context, 32) + fnty = llvm.FunctionType.get(int32ty, [int32ty], False) + fn = m.getOrInsertFunction("foo", fnty)._downcast(llvm.Function) + bb = llvm.BasicBlock.Create(context, "entry", fn, None) + builder = llvm.IRBuilder.new(context) builder.SetInsertPoint(bb) builder.CreateRet(fn.getArgumentList()[0]) print fn - eb = api.EngineBuilder.new(m) - eb2 = eb.setEngineKind(api.EngineKind.Kind.JIT) + eb = llvm.EngineBuilder.new(m) + eb2 = eb.setEngineKind(llvm.EngineKind.Kind.JIT) assert eb is eb2 - eb.setOptLevel(api.CodeGenOpt.Level.Aggressive).setUseMCJIT(False) + eb.setOptLevel(llvm.CodeGenOpt.Level.Aggressive).setUseMCJIT(False) tm = eb.selectTarget() @@ -205,7 +205,7 @@ def test_engine_builder(): ee = eb.create(tm) - triple = api.Triple.new('x86_64-unknown-linux') + triple = llvm.Triple.new('x86_64-unknown-linux') assert triple.getArchName() == 'x86_64' assert triple.getVendorName() == 'unknown' assert triple.getOSName() == 'linux' @@ -216,18 +216,18 @@ def test_engine_builder(): print tm.getDataLayout() - pm = api.PassManager.new() - pm.add(api.DataLayout.new(str(tm.getDataLayout()))) - pm.add(api.TargetLibraryInfo.new()) + pm = llvm.PassManager.new() + pm.add(llvm.DataLayout.new(str(tm.getDataLayout()))) + pm.add(llvm.TargetLibraryInfo.new()) # write assembly - pm = api.PassManager.new() - pm.add(api.DataLayout.new(str(tm.getDataLayout()))) + pm = llvm.PassManager.new() + pm.add(llvm.DataLayout.new(str(tm.getDataLayout()))) raw = extra.make_raw_ostream_for_printing() - formatted = api.formatted_raw_ostream.new(raw, False) + formatted = llvm.formatted_raw_ostream.new(raw, False) - cgft = api.TargetMachine.CodeGenFileType.CGFT_AssemblyFile + cgft = llvm.TargetMachine.CodeGenFileType.CGFT_AssemblyFile failed = tm.addPassesToEmitFile(pm, formatted, cgft, False) assert not failed @@ -241,17 +241,17 @@ def test_engine_builder(): def test_linker(): - context = api.getGlobalContext() + context = llvm.getGlobalContext() - mA = api.Module.new("modA", context) - mB = api.Module.new("modB", context) + mA = llvm.Module.new("modA", context) + mB = llvm.Module.new("modB", context) def create_function(m, name): - int32ty = api.Type.getIntNTy(context, 32) - fnty = api.FunctionType.get(int32ty, [int32ty], False) - fn = m.getOrInsertFunction(name, fnty)._downcast(api.Function) - bb = api.BasicBlock.Create(context, "entry", fn, None) - builder = api.IRBuilder.new(context) + int32ty = llvm.Type.getIntNTy(context, 32) + fnty = llvm.FunctionType.get(int32ty, [int32ty], False) + fn = m.getOrInsertFunction(name, fnty)._downcast(llvm.Function) + bb = llvm.BasicBlock.Create(context, "entry", fn, None) + builder = llvm.IRBuilder.new(context) builder.SetInsertPoint(bb) builder.CreateRet(fn.getArgumentList()[0]) @@ -259,8 +259,8 @@ def test_linker(): create_function(mB, 'bar') errmsg = StringIO() - linkermode = api.Linker.LinkerMode.PreserveSource - failed = api.Linker.LinkModules(mA, mB, linkermode, errmsg) + linkermode = llvm.Linker.LinkerMode.PreserveSource + failed = llvm.Linker.LinkModules(mA, mB, linkermode, errmsg) assert not failed, errmsg.getvalue() assert mA.getFunction('foo') assert mA.getFunction('bar') @@ -269,14 +269,14 @@ def test_linker(): mA.getFunction('bar')]) def test_structtype(): - context = api.getGlobalContext() - m = api.Module.new("modname", context) + context = llvm.getGlobalContext() + m = llvm.Module.new("modname", context) assert m.getTypeByName("truck") is None - truck = api.StructType.create(context, "truck") + truck = llvm.StructType.create(context, "truck") assert 'type opaque' in str(truck) - elemtys = [api.Type.getInt32Ty(context), api.Type.getDoubleTy(context)] + elemtys = [llvm.Type.getInt32Ty(context), llvm.Type.getDoubleTy(context)] truck.setBody(elemtys) assert 'i32' in str(truck) @@ -285,13 +285,13 @@ def test_structtype(): assert m.getTypeByName("truck") is truck def test_globalvariable(): - context = api.getGlobalContext() - m = api.Module.new("modname", context) + context = llvm.getGlobalContext() + m = llvm.Module.new("modname", context) - ty = api.Type.getInt32Ty(context) - LinkageTypes = api.GlobalVariable.LinkageTypes + ty = llvm.Type.getInt32Ty(context) + LinkageTypes = llvm.GlobalVariable.LinkageTypes linkage = LinkageTypes.ExternalLinkage - gvar = api.GlobalVariable.new(m, ty, False, linkage, None, "apple") + gvar = llvm.GlobalVariable.new(m, ty, False, linkage, None, "apple") assert '@apple = external global i32' in str(m) gvar2 = m.getNamedGlobal('apple') @@ -301,30 +301,30 @@ def test_globalvariable(): def test_sequentialtypes(): - context = api.getGlobalContext() - int32ty = api.Type.getInt32Ty(context) - ary_int32x4 = api.ArrayType.get(int32ty, 4) + context = llvm.getGlobalContext() + int32ty = llvm.Type.getInt32Ty(context) + ary_int32x4 = llvm.ArrayType.get(int32ty, 4) assert '[4 x i32]' == str(ary_int32x4) - ptr_int32 = api.PointerType.get(int32ty, 1) + ptr_int32 = llvm.PointerType.get(int32ty, 1) assert 'i32 addrspace(1)*' == str(ptr_int32) - vec_int32x4 = api.VectorType.get(int32ty, 4) + vec_int32x4 = llvm.VectorType.get(int32ty, 4) assert '<4 x i32>' == str(vec_int32x4) def test_constants(): - context = api.getGlobalContext() - int32ty = api.Type.getInt32Ty(context) - ary_int32x4 = api.ArrayType.get(int32ty, 4) - intconst = api.ConstantInt.get(int32ty, 123) - aryconst = api.ConstantArray.get(ary_int32x4, [intconst] * 4) + context = llvm.getGlobalContext() + int32ty = llvm.Type.getInt32Ty(context) + ary_int32x4 = llvm.ArrayType.get(int32ty, 4) + intconst = llvm.ConstantInt.get(int32ty, 123) + aryconst = llvm.ConstantArray.get(ary_int32x4, [intconst] * 4) assert str(aryconst.getAggregateElement(0)) == str(intconst) def test_intrinsic(): - context = api.getGlobalContext() - m = api.Module.new("modname", context) + context = llvm.getGlobalContext() + m = llvm.Module.new("modname", context) INTR_SIN = 1652 - floatty = api.Type.getFloatTy(context) - fn = api.Intrinsic.getDeclaration(m, INTR_SIN, [floatty]) + floatty = llvm.Type.getFloatTy(context) + fn = llvm.Intrinsic.getDeclaration(m, INTR_SIN, [floatty]) assert 'llvm.sin.f32' in str(fn) fn.eraseFromParent() assert 'llvm.sin.f32' not in str(m) From 355332d6d848ec162ffcdaed9e70d52ef5915efb Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 8 Feb 2013 18:12:07 -0600 Subject: [PATCH 59/85] Add NVPTX components --- newbinding/setup.py | 22 ++++++++++++++++------ newbinding/src/Support/TargetSelect.py | 21 ++++++++++++++++----- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/newbinding/setup.py b/newbinding/setup.py index 6e2ceb5..bb23c32 100644 --- a/newbinding/setup.py +++ b/newbinding/setup.py @@ -26,12 +26,22 @@ macros = [('__STDC_CONSTANT_MACROS', None), extra_link_args = ldflags.split() -libs_core, objs_core = get_libs_and_objs(['core', 'analysis', 'scalaropts', - 'executionengine', 'jit', 'native', - 'interpreter', 'bitreader', - 'bitwriter', 'instrumentation', 'ipa', - 'ipo', 'transformutils', 'asmparser', - 'linker', 'support', 'vectorize']) +components = ['core', 'analysis', 'scalaropts', + 'executionengine', 'jit', 'native', + 'interpreter', 'bitreader', + 'bitwriter', 'instrumentation', 'ipa', + 'ipo', 'transformutils', 'asmparser', + 'linker', 'support', 'vectorize', + ] + +nvptx = ['nvptx', + 'nvptxasmprinter', + 'nvptxcodegen', + 'nvptxdesc', + 'nvptxinfo'] + +libs_core, objs_core = get_libs_and_objs(components + nvptx) + ext_modules = [Extension(name='_api', sources=['api.cpp'], diff --git a/newbinding/src/Support/TargetSelect.py b/newbinding/src/Support/TargetSelect.py index 208ef4b..ca97c24 100644 --- a/newbinding/src/Support/TargetSelect.py +++ b/newbinding/src/Support/TargetSelect.py @@ -1,17 +1,28 @@ from binding import * -from ..namespace import llvm +from ..namespace import llvm, default llvm.includes.add('llvm/Support/TargetSelect.h') InitializeNativeTarget = llvm.Function('InitializeNativeTarget') -#llvm.Function('InitializeAllTargets') - InitializeNativeTargetAsmPrinter = llvm.Function( 'InitializeNativeTargetAsmPrinter', cast(Bool, bool)) - InitializeNativeTargetAsmParser = llvm.Function( 'InitializeNativeTargetAsmParser', cast(Bool, bool)) - InitializeNativeTargetDisassembler = llvm.Function( 'InitializeNativeTargetDisassembler', cast(Bool, bool)) + +#InitializeAllTargets = llvm.Function('InitializeAllTargets') +#InitializeAllTargetInfos = llvm.Function('InitializeAllTargetInfos') +#InitializeAllTargetMCs = llvm.Function('InitializeAllTargetMCs') +#InitializeAllAsmPrinters = llvm.Function('InitializeAllAsmPrinters') + +#LLVMInitializePTXTarget = default.Function('LLVMInitializePTXTarget') +#LLVMInitializePTXTargetInfo = default.Function('LLVMInitializePTXTargetInfo') +#LLVMInitializePTXTargetMC = default.Function('LLVMInitializePTXTargetMC') +#LLVMInitializePTXAsmPrinter = default.Function('LLVMInitializePTXAsmPrinter') + +LLVMInitializeNVPTXTarget = default.Function('LLVMInitializeNVPTXTarget') +LLVMInitializeNVPTXTargetInfo = default.Function('LLVMInitializeNVPTXTargetInfo') +LLVMInitializeNVPTXTargetMC = default.Function('LLVMInitializeNVPTXTargetMC') +LLVMInitializeNVPTXAsmPrinter = default.Function('LLVMInitializeNVPTXAsmPrinter') From c66dad7ecede9cf6c5224711dc1485605633320d Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 8 Feb 2013 18:12:36 -0600 Subject: [PATCH 60/85] Implement commandline namespace --- newbinding/src/Support/CommandLine.py | 12 ++++++++++++ newbinding/src/namespace.py | 5 ++--- 2 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 newbinding/src/Support/CommandLine.py diff --git a/newbinding/src/Support/CommandLine.py b/newbinding/src/Support/CommandLine.py new file mode 100644 index 0000000..2a114f7 --- /dev/null +++ b/newbinding/src/Support/CommandLine.py @@ -0,0 +1,12 @@ +from binding import * +from src.namespace import cl + +cl.includes.add('llvm/Support/CommandLine.h') + +ParseEnvironmentOptions = cl.Function('ParseEnvironmentOptions', + Void, + cast(str, ConstCharPtr), # progName + cast(str, ConstCharPtr), # envvar + cast(str, ConstCharPtr), # overiew = 0 + ).require_only(2) + diff --git a/newbinding/src/namespace.py b/newbinding/src/namespace.py index f833af8..8ad62a3 100644 --- a/newbinding/src/namespace.py +++ b/newbinding/src/namespace.py @@ -1,7 +1,6 @@ from binding import * default = Namespace('') - -llvm = Namespace('llvm') +llvm = default.Namespace('llvm') sys = llvm.Namespace('sys') - +cl = llvm.Namespace('cl') From 60336d1c5fe9fc897e1c5899131e663f7a3f1a6d Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 8 Feb 2013 18:12:51 -0600 Subject: [PATCH 61/85] Add DynamicLibrary and InlineFunction --- newbinding/include/llvm_binding/extra.h | 26 ++++++++++++++++++++++ newbinding/src/Support/DynamicLibrary.py | 26 ++++++++++++++++++++-- newbinding/src/Transforms/Utils/Cloning.py | 15 ++++++++++++- 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/newbinding/include/llvm_binding/extra.h b/newbinding/include/llvm_binding/extra.h index 75739de..d045d5c 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/newbinding/include/llvm_binding/extra.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -747,3 +748,28 @@ PyObject* IRBuilder_CreateAggregateRet(llvm::IRBuilder<>* builder, return pycapsule_new(inst, "llvm::Value", "llvm:ReturnInst"); } +static +PyObject* DynamicLibrary_LoadLibraryPermanently(const char * Filename, + PyObject* ErrMsg = 0) +{ + using namespace llvm::sys; + bool failed; + if (ErrMsg) { + std::string errmsg; + failed = DynamicLibrary::LoadLibraryPermanently(Filename, &errmsg); + if (failed) { + if (-1 == PyFile_WriteString(errmsg.c_str(), ErrMsg)) { + return NULL; + } + } + } else { + failed = DynamicLibrary::LoadLibraryPermanently(Filename); + } + + if (failed) { + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } +} + diff --git a/newbinding/src/Support/DynamicLibrary.py b/newbinding/src/Support/DynamicLibrary.py index 7f661d3..7dce97a 100644 --- a/newbinding/src/Support/DynamicLibrary.py +++ b/newbinding/src/Support/DynamicLibrary.py @@ -1,6 +1,28 @@ from binding import * from ..namespace import sys +from ..ADT.StringRef import StringRef -DynamicLibrary = sys.Namespace('DynamicLibrary') -#LoadLibraryPermanently +DynamicLibrary = sys.Class() + +@DynamicLibrary +class DynamicLibrary: + _include_ = 'llvm/Support/DynamicLibrary.h' + isValid = Method(cast(Bool, bool)) + getAddressOfSymbol = Method(cast(VoidPtr, int), cast(str, ConstCharPtr)) + + LoadPermanentLibrary = CustomStaticMethod( + 'DynamicLibrary_LoadLibraryPermanently', + PyObjectPtr, # bool --- failed? + cast(str, ConstCharPtr), # filename + PyObjectPtr, # std::string * errmsg = 0 + ).require_only(1) + + SearchForAddressOfSymbol = StaticMethod(cast(VoidPtr, int), # address + cast(str, ConstCharPtr), # symName + ) + + AddSymbol = StaticMethod(Void, + cast(str, StringRef), # symbolName + cast(int, VoidPtr), # address + ) diff --git a/newbinding/src/Transforms/Utils/Cloning.py b/newbinding/src/Transforms/Utils/Cloning.py index c7f7a86..1971177 100644 --- a/newbinding/src/Transforms/Utils/Cloning.py +++ b/newbinding/src/Transforms/Utils/Cloning.py @@ -1,8 +1,21 @@ from binding import * from src.namespace import llvm from src.Module import Module +from src.Instruction import CallInst llvm.includes.add('llvm/Transforms/Utils/Cloning.h') + +@llvm.Class() +class InlineFunctionInfo: + new = Constructor() + delete = Destructor() + + CloneModule = llvm.Function('CloneModule', ptr(Module), ptr(Module)) - +InlineFunction = llvm.Function('InlineFunction', + cast(Bool, bool), # bool --- failed + ptr(CallInst), + ref(InlineFunctionInfo), + cast(bool, Bool), # insert lifetime = true + ).require_only(2) From 8700bbc4f16192f84d77989ecc5ef0ab640d3bdf Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 8 Feb 2013 18:13:16 -0600 Subject: [PATCH 62/85] Fix segfault on exit --- newbinding/include/llvm_binding/binding.h | 1 + 1 file changed, 1 insertion(+) diff --git a/newbinding/include/llvm_binding/binding.h b/newbinding/include/llvm_binding/binding.h index 68af615..b5c5b48 100644 --- a/newbinding/include/llvm_binding/binding.h +++ b/newbinding/include/llvm_binding/binding.h @@ -57,6 +57,7 @@ create_python_submodule(PyObject* parent, const char* name, if (-1 == PyModule_AddObject(parent, name, submod)) { return NULL; } + Py_INCREF(submod); // otherwise, it would segfault on exit return submod; } From 1fb6b05715f4eba36583e2210d1a58e555b5a121 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 8 Feb 2013 18:13:45 -0600 Subject: [PATCH 63/85] Finished wrapper in llvm.core --- .gitignore | 3 + llvm/__init__.py | 11 + llvm/core.py | 2196 +++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 1980 insertions(+), 230 deletions(-) diff --git a/.gitignore b/.gitignore index 6d0cc2b..6d6296f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,7 @@ build _build *.pyc +*.so /llvm/_intrinsic_ids.py +llvm_ +newbinding/api/* \ No newline at end of file diff --git a/llvm/__init__.py b/llvm/__init__.py index e69de29..23f3f4d 100644 --- a/llvm/__init__.py +++ b/llvm/__init__.py @@ -0,0 +1,11 @@ +class Wrapper(object): + def __init__(self, ptr): + self.__ptr = ptr + + @property + def _ptr(self): + return self.__ptr + + +def _extract_ptrs(objs): + return [x._ptr for x in objs] diff --git a/llvm/core.py b/llvm/core.py index 0bf99fd..6d5f0d1 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -2,6 +2,9 @@ try: from cStringIO import StringIO except ImportError: from StringIO import StringIO +import contextlib + +import llvm import api @@ -9,248 +12,263 @@ import api # Enumerations #===----------------------------------------------------------------------=== -# type kinds (LLVMTypeKind enum) -TYPE_VOID = 0 -TYPE_HALF = 1 -TYPE_FLOAT = 2 -TYPE_DOUBLE = 3 -TYPE_X86_FP80 = 4 -TYPE_FP128 = 5 -TYPE_PPC_FP128 = 6 -TYPE_LABEL = 7 -TYPE_INTEGER = 8 -TYPE_FUNCTION = 9 -TYPE_STRUCT = 10 -TYPE_ARRAY = 11 -TYPE_POINTER = 12 -TYPE_VECTOR = 13 -TYPE_METADATA = 14 -TYPE_X86_MMX = 15 +# type id (llvm::Type::TypeID) +TYPE_VOID = api.llvm.Type.TypeID.VoidTyID +TYPE_HALF = api.llvm.Type.TypeID.HalfTyID +TYPE_FLOAT = api.llvm.Type.TypeID.FloatTyID +TYPE_DOUBLE = api.llvm.Type.TypeID.DoubleTyID +TYPE_X86_FP80 = api.llvm.Type.TypeID.X86_FP80TyID +TYPE_FP128 = api.llvm.Type.TypeID.FP128TyID +TYPE_PPC_FP128 = api.llvm.Type.TypeID.PPC_FP128TyID +TYPE_LABEL = api.llvm.Type.TypeID.LabelTyID +TYPE_INTEGER = api.llvm.Type.TypeID.IntegerTyID +TYPE_FUNCTION = api.llvm.Type.TypeID.FunctionTyID +TYPE_STRUCT = api.llvm.Type.TypeID.StructTyID +TYPE_ARRAY = api.llvm.Type.TypeID.ArrayTyID +TYPE_POINTER = api.llvm.Type.TypeID.PointerTyID +TYPE_VECTOR = api.llvm.Type.TypeID.VectorTyID +TYPE_METADATA = api.llvm.Type.TypeID.MetadataTyID +TYPE_X86_MMX = api.llvm.Type.TypeID.X86_MMXTyID # value IDs (llvm::Value::ValueTy enum) -VALUE_ARGUMENT = 0 -VALUE_BASIC_BLOCK = 1 -VALUE_FUNCTION = 2 -VALUE_GLOBAL_ALIAS = 3 -VALUE_GLOBAL_VARIABLE = 4 -VALUE_UNDEF_VALUE = 5 -VALUE_BLOCK_ADDRESS = 6 -VALUE_CONSTANT_EXPR = 7 -VALUE_CONSTANT_AGGREGATE_ZERO = 8 -VALUE_CONSTANT_DATA_ARRAY = 9 -VALUE_CONSTANT_DATA_VECTOR = 10 -VALUE_CONSTANT_INT = 11 -VALUE_CONSTANT_FP = 12 -VALUE_CONSTANT_ARRAY = 13 -VALUE_CONSTANT_STRUCT = 14 -VALUE_CONSTANT_VECTOR = 15 -VALUE_CONSTANT_POINTER_NULL = 16 -VALUE_MD_NODE = 17 -VALUE_MD_STRING = 18 -VALUE_INLINE_ASM = 19 -VALUE_PSEUDO_SOURCE_VALUE = 20 -VALUE_FIXED_STACK_PSEUDO_SOURCE_VALUE = 21 -VALUE_INSTRUCTION = 22 +# According to the doxygen docs, it is not a good idea to use these enums. +# There are more values than those declared. +VALUE_ARGUMENT = api.llvm.Value.ValueTy.ArgumentVal +VALUE_BASIC_BLOCK = api.llvm.Value.ValueTy.BasicBlockVal +VALUE_FUNCTION = api.llvm.Value.ValueTy.FunctionVal +VALUE_GLOBAL_ALIAS = api.llvm.Value.ValueTy.GlobalAliasVal +VALUE_GLOBAL_VARIABLE = api.llvm.Value.ValueTy.GlobalVariableVal +VALUE_UNDEF_VALUE = api.llvm.Value.ValueTy.UndefValueVal +VALUE_BLOCK_ADDRESS = api.llvm.Value.ValueTy.BlockAddressVal +VALUE_CONSTANT_EXPR = api.llvm.Value.ValueTy.ConstantExprVal +VALUE_CONSTANT_AGGREGATE_ZERO = api.llvm.Value.ValueTy.ConstantAggregateZeroVal +VALUE_CONSTANT_DATA_ARRAY = api.llvm.Value.ValueTy.ConstantDataArrayVal +VALUE_CONSTANT_DATA_VECTOR = api.llvm.Value.ValueTy.ConstantDataVectorVal +VALUE_CONSTANT_INT = api.llvm.Value.ValueTy.ConstantIntVal +VALUE_CONSTANT_FP = api.llvm.Value.ValueTy.ConstantFPVal +VALUE_CONSTANT_ARRAY = api.llvm.Value.ValueTy.ConstantArrayVal +VALUE_CONSTANT_STRUCT = api.llvm.Value.ValueTy.ConstantStructVal +VALUE_CONSTANT_VECTOR = api.llvm.Value.ValueTy.ConstantVectorVal +VALUE_CONSTANT_POINTER_NULL = api.llvm.Value.ValueTy.ConstantPointerNullVal +VALUE_MD_NODE = api.llvm.Value.ValueTy.MDNodeVal +VALUE_MD_STRING = api.llvm.Value.ValueTy.MDStringVal +VALUE_INLINE_ASM = api.llvm.Value.ValueTy.InlineAsmVal +VALUE_PSEUDO_SOURCE_VALUE = api.llvm.Value.ValueTy.PseudoSourceValueVal +VALUE_FIXED_STACK_PSEUDO_SOURCE_VALUE = api.llvm.Value.ValueTy.FixedStackPseudoSourceValueVal +VALUE_INSTRUCTION = api.llvm.Value.ValueTy.InstructionVal -# instruction opcodes (from include/llvm/Instruction.def) -OPCODE_RET = 1 -OPCODE_BR = 2 -OPCODE_SWITCH = 3 -OPCODE_INDIRECT_BR = 4 -OPCODE_INVOKE = 5 -OPCODE_RESUME = 6 -OPCODE_UNREACHABLE = 7 -OPCODE_ADD = 8 -OPCODE_FADD = 9 -OPCODE_SUB = 10 -OPCODE_FSUB = 11 -OPCODE_MUL = 12 -OPCODE_FMUL = 13 -OPCODE_UDIV = 14 -OPCODE_SDIV = 15 -OPCODE_FDIV = 16 -OPCODE_UREM = 17 -OPCODE_SREM = 18 -OPCODE_FREM = 19 -OPCODE_SHL = 20 -OPCODE_LSHR = 21 -OPCODE_ASHR = 22 -OPCODE_AND = 23 -OPCODE_OR = 24 -OPCODE_XOR = 25 -OPCODE_ALLOCA = 26 -OPCODE_LOAD = 27 -OPCODE_STORE = 28 -OPCODE_GETELEMENTPTR = 29 -OPCODE_FENCE = 30 -OPCODE_ATOMICCMPXCHG = 31 -OPCODE_ATOMICRMW = 32 -OPCODE_TRUNC = 33 -OPCODE_ZEXT = 34 -OPCODE_SEXT = 35 -OPCODE_FPTOUI = 36 -OPCODE_FPTOSI = 37 -OPCODE_UITOFP = 38 -OPCODE_SITOFP = 39 -OPCODE_FPTRUNC = 40 -OPCODE_FPEXT = 41 -OPCODE_PTRTOINT = 42 -OPCODE_INTTOPTR = 43 -OPCODE_BITCAST = 44 -OPCODE_ICMP = 45 -OPCODE_FCMP = 46 -OPCODE_PHI = 47 -OPCODE_CALL = 48 -OPCODE_SELECT = 49 -OPCODE_USEROP1 = 50 -OPCODE_USEROP2 = 51 -OPCODE_VAARG = 52 -OPCODE_EXTRACTELEMENT = 53 -OPCODE_INSERTELEMENT = 54 -OPCODE_SHUFFLEVECTOR = 55 -OPCODE_EXTRACTVALUE = 56 -OPCODE_INSERTVALUE = 57 -OPCODE_LANDINGPAD = 58 +## instruction opcodes (from include/llvm/Instruction.def) +#OPCODE_RET = 1 +#OPCODE_BR = 2 +#OPCODE_SWITCH = 3 +#OPCODE_INDIRECT_BR = 4 +#OPCODE_INVOKE = 5 +#OPCODE_RESUME = 6 +#OPCODE_UNREACHABLE = 7 +#OPCODE_ADD = 8 +#OPCODE_FADD = 9 +#OPCODE_SUB = 10 +#OPCODE_FSUB = 11 +#OPCODE_MUL = 12 +#OPCODE_FMUL = 13 +#OPCODE_UDIV = 14 +#OPCODE_SDIV = 15 +#OPCODE_FDIV = 16 +#OPCODE_UREM = 17 +#OPCODE_SREM = 18 +#OPCODE_FREM = 19 +#OPCODE_SHL = 20 +#OPCODE_LSHR = 21 +#OPCODE_ASHR = 22 +#OPCODE_AND = 23 +#OPCODE_OR = 24 +#OPCODE_XOR = 25 +#OPCODE_ALLOCA = 26 +#OPCODE_LOAD = 27 +#OPCODE_STORE = 28 +#OPCODE_GETELEMENTPTR = 29 +#OPCODE_FENCE = 30 +#OPCODE_ATOMICCMPXCHG = 31 +#OPCODE_ATOMICRMW = 32 +#OPCODE_TRUNC = 33 +#OPCODE_ZEXT = 34 +#OPCODE_SEXT = 35 +#OPCODE_FPTOUI = 36 +#OPCODE_FPTOSI = 37 +#OPCODE_UITOFP = 38 +#OPCODE_SITOFP = 39 +#OPCODE_FPTRUNC = 40 +#OPCODE_FPEXT = 41 +#OPCODE_PTRTOINT = 42 +#OPCODE_INTTOPTR = 43 +#OPCODE_BITCAST = 44 +#OPCODE_ICMP = 45 +#OPCODE_FCMP = 46 +#OPCODE_PHI = 47 +#OPCODE_CALL = 48 +#OPCODE_SELECT = 49 +#OPCODE_USEROP1 = 50 +#OPCODE_USEROP2 = 51 +#OPCODE_VAARG = 52 +#OPCODE_EXTRACTELEMENT = 53 +#OPCODE_INSERTELEMENT = 54 +#OPCODE_SHUFFLEVECTOR = 55 +#OPCODE_EXTRACTVALUE = 56 +#OPCODE_INSERTVALUE = 57 +#OPCODE_LANDINGPAD = 58 +# +## calling conventions +#CC_C = 0 +#CC_FASTCALL = 8 +#CC_COLDCALL = 9 +#CC_GHC = 10 +#CC_X86_STDCALL = 64 +#CC_X86_FASTCALL = 65 +#CC_ARM_APCS = 66 +#CC_ARM_AAPCS = 67 +#CC_ARM_AAPCS_VFP = 68 +#CC_MSP430_INTR = 69 +#CC_X86_THISCALL = 70 +#CC_PTX_KERNEL = 71 +#CC_PTX_DEVICE = 72 +#CC_MBLAZE_INTR = 73 +#CC_MBLAZE_SVOL = 74 +# +# +## int predicates +#ICMP_EQ = 32 +#ICMP_NE = 33 +#ICMP_UGT = 34 +#ICMP_UGE = 35 +#ICMP_ULT = 36 +#ICMP_ULE = 37 +#ICMP_SGT = 38 +#ICMP_SGE = 39 +#ICMP_SLT = 40 +#ICMP_SLE = 41 +# +## same as ICMP_xx, for backward compatibility +#IPRED_EQ = ICMP_EQ +#IPRED_NE = ICMP_NE +#IPRED_UGT = ICMP_UGT +#IPRED_UGE = ICMP_UGE +#IPRED_ULT = ICMP_ULT +#IPRED_ULE = ICMP_ULE +#IPRED_SGT = ICMP_SGT +#IPRED_SGE = ICMP_SGE +#IPRED_SLT = ICMP_SLT +#IPRED_SLE = ICMP_SLE +# +## real predicates +#FCMP_FALSE = 0 +#FCMP_OEQ = 1 +#FCMP_OGT = 2 +#FCMP_OGE = 3 +#FCMP_OLT = 4 +#FCMP_OLE = 5 +#FCMP_ONE = 6 +#FCMP_ORD = 7 +#FCMP_UNO = 8 +#FCMP_UEQ = 9 +#FCMP_UGT = 10 +#FCMP_UGE = 11 +#FCMP_ULT = 12 +#FCMP_ULE = 13 +#FCMP_UNE = 14 +#FCMP_TRUE = 15 +# +## real predicates +#RPRED_FALSE = FCMP_FALSE +#RPRED_OEQ = FCMP_OEQ +#RPRED_OGT = FCMP_OGT +#RPRED_OGE = FCMP_OGE +#RPRED_OLT = FCMP_OLT +#RPRED_OLE = FCMP_OLE +#RPRED_ONE = FCMP_ONE +#RPRED_ORD = FCMP_ORD +#RPRED_UNO = FCMP_UNO +#RPRED_UEQ = FCMP_UEQ +#RPRED_UGT = FCMP_UGT +#RPRED_UGE = FCMP_UGE +#RPRED_ULT = FCMP_ULT +#RPRED_ULE = FCMP_ULE +#RPRED_UNE = FCMP_UNE +#RPRED_TRUE = FCMP_TRUE +# +## linkages (see llvm-c/Core.h) +#LINKAGE_EXTERNAL = 0 +#LINKAGE_AVAILABLE_EXTERNALLY = 1 +#LINKAGE_LINKONCE_ANY = 2 +#LINKAGE_LINKONCE_ODR = 3 +#LINKAGE_WEAK_ANY = 4 +#LINKAGE_WEAK_ODR = 5 +#LINKAGE_APPENDING = 6 +#LINKAGE_INTERNAL = 7 +#LINKAGE_PRIVATE = 8 +#LINKAGE_DLLIMPORT = 9 +#LINKAGE_DLLEXPORT = 10 +#LINKAGE_EXTERNAL_WEAK = 11 +#LINKAGE_GHOST = 12 +#LINKAGE_COMMON = 13 +#LINKAGE_LINKER_PRIVATE = 14 +#LINKAGE_LINKER_PRIVATE_WEAK = 15 +#LINKAGE_LINKER_PRIVATE_WEAK_DEF_AUTO = 16 +# +## visibility (see llvm/GlobalValue.h) +#VISIBILITY_DEFAULT = 0 +#VISIBILITY_HIDDEN = 1 +#VISIBILITY_PROTECTED = 2 -# calling conventions -CC_C = 0 -CC_FASTCALL = 8 -CC_COLDCALL = 9 -CC_GHC = 10 -CC_X86_STDCALL = 64 -CC_X86_FASTCALL = 65 -CC_ARM_APCS = 66 -CC_ARM_AAPCS = 67 -CC_ARM_AAPCS_VFP = 68 -CC_MSP430_INTR = 69 -CC_X86_THISCALL = 70 -CC_PTX_KERNEL = 71 -CC_PTX_DEVICE = 72 -CC_MBLAZE_INTR = 73 -CC_MBLAZE_SVOL = 74 +# parameter attributes llvm::Attributes::AttrVal (see llvm/Attributes.h) +ATTR_NONE = api.llvm.Attributes.AttrVal.None_ +ATTR_ZEXT = api.llvm.Attributes.AttrVal.ZExt +ATTR_SEXT = api.llvm.Attributes.AttrVal.SExt +ATTR_NO_RETURN = api.llvm.Attributes.AttrVal.NoReturn +ATTR_IN_REG = api.llvm.Attributes.AttrVal.InReg +ATTR_STRUCT_RET = api.llvm.Attributes.AttrVal.StructRet +ATTR_NO_UNWIND = api.llvm.Attributes.AttrVal.NoUnwind +ATTR_NO_ALIAS = api.llvm.Attributes.AttrVal.NoAlias +ATTR_BY_VAL = api.llvm.Attributes.AttrVal.ByVal +ATTR_NEST = api.llvm.Attributes.AttrVal.Nest +ATTR_READ_NONE = api.llvm.Attributes.AttrVal.ReadNone +ATTR_READONLY = api.llvm.Attributes.AttrVal.ReadOnly +ATTR_NO_INLINE = api.llvm.Attributes.AttrVal.NoInline +ATTR_ALWAYS_INLINE = api.llvm.Attributes.AttrVal.AlwaysInline +ATTR_OPTIMIZE_FOR_SIZE = api.llvm.Attributes.AttrVal.OptimizeForSize +ATTR_STACK_PROTECT = api.llvm.Attributes.AttrVal.StackProtect +ATTR_STACK_PROTECT_REQ = api.llvm.Attributes.AttrVal.StackProtectReq +ATTR_ALIGNMENT = api.llvm.Attributes.AttrVal.Alignment +ATTR_NO_CAPTURE = api.llvm.Attributes.AttrVal.NoCapture +ATTR_NO_REDZONE = api.llvm.Attributes.AttrVal.NoRedZone +ATTR_NO_IMPLICIT_FLOAT = api.llvm.Attributes.AttrVal.NoImplicitFloat +ATTR_NAKED = api.llvm.Attributes.AttrVal.Naked +ATTR_INLINE_HINT = api.llvm.Attributes.AttrVal.InlineHint +ATTR_STACK_ALIGNMENT = api.llvm.Attributes.AttrVal.StackAlignment -# int predicates -ICMP_EQ = 32 -ICMP_NE = 33 -ICMP_UGT = 34 -ICMP_UGE = 35 -ICMP_ULT = 36 -ICMP_ULE = 37 -ICMP_SGT = 38 -ICMP_SGE = 39 -ICMP_SLT = 40 -ICMP_SLE = 41 +class Module(llvm.Wrapper): + """A Module instance stores all the information related to an LLVM module. -# same as ICMP_xx, for backward compatibility -IPRED_EQ = ICMP_EQ -IPRED_NE = ICMP_NE -IPRED_UGT = ICMP_UGT -IPRED_UGE = ICMP_UGE -IPRED_ULT = ICMP_ULT -IPRED_ULE = ICMP_ULE -IPRED_SGT = ICMP_SGT -IPRED_SGE = ICMP_SGE -IPRED_SLT = ICMP_SLT -IPRED_SLE = ICMP_SLE + Modules are the top level container of all other LLVM Intermediate + Representation (IR) objects. Each module directly contains a list of + globals variables, a list of functions, a list of libraries (or + other modules) this module depends on, a symbol table, and various + data about the target's characteristics. -# real predicates -FCMP_FALSE = 0 -FCMP_OEQ = 1 -FCMP_OGT = 2 -FCMP_OGE = 3 -FCMP_OLT = 4 -FCMP_OLE = 5 -FCMP_ONE = 6 -FCMP_ORD = 7 -FCMP_UNO = 8 -FCMP_UEQ = 9 -FCMP_UGT = 10 -FCMP_UGE = 11 -FCMP_ULT = 12 -FCMP_ULE = 13 -FCMP_UNE = 14 -FCMP_TRUE = 15 + Construct a Module only using the static methods defined below, *NOT* + using the constructor. A correct usage is: -# real predicates -RPRED_FALSE = FCMP_FALSE -RPRED_OEQ = FCMP_OEQ -RPRED_OGT = FCMP_OGT -RPRED_OGE = FCMP_OGE -RPRED_OLT = FCMP_OLT -RPRED_OLE = FCMP_OLE -RPRED_ONE = FCMP_ONE -RPRED_ORD = FCMP_ORD -RPRED_UNO = FCMP_UNO -RPRED_UEQ = FCMP_UEQ -RPRED_UGT = FCMP_UGT -RPRED_UGE = FCMP_UGE -RPRED_ULT = FCMP_ULT -RPRED_ULE = FCMP_ULE -RPRED_UNE = FCMP_UNE -RPRED_TRUE = FCMP_TRUE - -# linkages (see llvm-c/Core.h) -LINKAGE_EXTERNAL = 0 -LINKAGE_AVAILABLE_EXTERNALLY = 1 -LINKAGE_LINKONCE_ANY = 2 -LINKAGE_LINKONCE_ODR = 3 -LINKAGE_WEAK_ANY = 4 -LINKAGE_WEAK_ODR = 5 -LINKAGE_APPENDING = 6 -LINKAGE_INTERNAL = 7 -LINKAGE_PRIVATE = 8 -LINKAGE_DLLIMPORT = 9 -LINKAGE_DLLEXPORT = 10 -LINKAGE_EXTERNAL_WEAK = 11 -LINKAGE_GHOST = 12 -LINKAGE_COMMON = 13 -LINKAGE_LINKER_PRIVATE = 14 -LINKAGE_LINKER_PRIVATE_WEAK = 15 -LINKAGE_LINKER_PRIVATE_WEAK_DEF_AUTO = 16 - -# visibility (see llvm/GlobalValue.h) -VISIBILITY_DEFAULT = 0 -VISIBILITY_HIDDEN = 1 -VISIBILITY_PROTECTED = 2 - -# parameter attributes (see llvm/Attributes.h) -ATTR_NONE = 0 -ATTR_ZEXT = 1 -ATTR_SEXT = 2 -ATTR_NO_RETURN = 4 -ATTR_IN_REG = 8 -ATTR_STRUCT_RET = 16 -ATTR_NO_UNWIND = 32 -ATTR_NO_ALIAS = 64 -ATTR_BY_VAL = 128 -ATTR_NEST = 256 -ATTR_READ_NONE = 512 -ATTR_READONLY = 1024 -ATTR_NO_INLINE = 1<<11 -ATTR_ALWAYS_INLINE = 1<<12 -ATTR_OPTIMIZE_FOR_SIZE = 1<<13 -ATTR_STACK_PROTECT = 1<<14 -ATTR_STACK_PROTECT_REQ = 1<<15 -ATTR_ALIGNMENT = 1<<16 -ATTR_NO_CAPTURE = 1<<21 -ATTR_NO_REDZONE = 1<<22 -ATTR_NO_IMPLICIT_FLOAT = 1<<23 -ATTR_NAKED = 1<<24 -ATTR_INLINE_HINT = 1<<25 -ATTR_STACK_ALIGNMENT = 7<<26 -ATTR_HOTPATCH = 1<<29 - -class Module(object): + module_obj = Module.new('my_module') + """ @staticmethod def new(id): """Create a new Module instance. Creates an instance of Module, having the id `id'. """ - context = api.getGlobalContext() - m = api.Module.new(id, context) + context = api.llvm.getGlobalContext() + m = api.llvm.Module.new(id, context) return Module(m) @staticmethod @@ -266,14 +284,1732 @@ class Module(object): else: bc = fileobj_or_str.read() errbuf = StringIO() - m = api.ParseBitCodeFile(bc, context, errbuf) + m = api.llvm.ParseBitCodeFile(bc, context, errbuf) if not m: raise Exception(errbuf.getvalue()) errbuf.close() return Module(m) - def __init__(self, ptr): - self.ptr = ptr + + @staticmethod + def from_assembly(fileobj_or_str): + """Create a Module instance from the contents of an LLVM + assembly (.ll) file. + + + fileobj_or_str -- takes a file-like object or string that contains + a module represented in llvm-ir assembly. + """ + if isinstance(fileobj_or_str, str): + ir = fileobj_or_str + else: + ir = fileobj_or_str.read() + errbuf = StringIO() + m = api.llvm.ParseAssemblyString(ir, None, api.llvm.SMDIagnostic.new(), context) + errbuf.close() + return Module(m) + + def __str__(self): + """Text representation of a module. + + Returns the textual representation (`llvm assembly') of the + module. Use it like this: + + ll = str(module_obj) + print module_obj # same as `print ll' + """ + return str(self.ptr) + + def __eq__(self, rhs): + if isinstance(rhs, Module): + return str(self) == str(rhs) + else: + return False + + def __ne__(self, rhs): + return not (self == rhs) + + + def _get_target(self): + return self.ptr.getTargetTriple() + + def _set_target(self, value): + return self.ptr.setTargetTriple(value) + + target = property(_get_target, _set_target, + doc="The target triple string describing the target host.") + + + def _get_data_layout(self): + return self.ptr.getDataLayout() + + def _set_data_layout(self, value): + return self.ptr.setDataLayout(value) + + data_layout = property(_get_data_layout, _set_data_layout, + doc = """The data layout string for the module's target platform. + + The data layout strings is an encoded representation of + the type sizes and alignments expected by this module. + """ + ) + + @property + def pointer_size(self): + return self.getPointerSize() + + def link_in(self, other, preserve=False): + """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, all refs to it should be dropped. + + In the future, this API might be replaced with a full-fledged + Linker class. + """ + assert isinstance(other, Module) + enum_mode = api.llvm.Linker.LinkMode + mode = enum_mode.PreserveSource if preserve else enum_mode.DestroySource + + with contextlib.closing(StringIO()) as errmsg: + failed = api.llvm.Linker.LinkModule(self._ptr, + other._ptr, + mode, + errmsg) + if failed: + raise llvm.LLVMException(errmsg) + + def get_type_named(self, name): + typ = self.ptr.getTypeByName(name) + return StructType(typ) + + def add_global_variable(self, ty, name, addrspace=0): + """Add a global variable of given type with given name.""" + external = api.llvm.GlobalVariable.LinkageTypes.ExternalLinkage + notthreadlocal = api.llvm.GlobalVariable.ThreadLocalMode.NotThreadLocal + init = None + insertbefore = None + ptr = api.llvm.GlobalVariable.new(self, + ty._ptr, + False, + external, + init, + name, + insertbefore, + notthreadlocal, + addrspace) + return GlobalVariable(ptr) + + def get_global_variable_named(self, name): + """Return a GlobalVariable object for the given name.""" + ptr = self.ptr.getNamedGlobal(name) + return GlobalVariable(ptr) + + @property + def global_variables(self): + return self.ptr.list_globals() + + def add_function(self, ty, name): + """Add a function of given type with given name.""" + fn = self.get_function_named(name) + if fn is not None: + raise llvm.LLVMException("Duplicated function %s" % name) + return self.get_or_insert_function(ty, name) + + def get_function_named(self, name): + """Return a Function object representing function with given name.""" + fn = self.ptr.getFunction(name) + if fn is None: + return None + return Function(fn) + + def get_or_insert_function(self, ty, name): + """Like get_function_named(), but does add_function() first, if + function is not present.""" + constant = self.ptr.getOrInsertFunction(name, ty._ptr) + fn = constant._downcast(api.llvm.Function) + return Function(fn) + + @property + def functions(self): + """All functions in this module.""" + return map(Function, self.ptr.list_functions()) + + def verify(self): + """Verify module. + + Checks module for errors. Raises `llvm.LLVMException' on any + error.""" + action = api.llvm.VerifierFailureAction.ReturnStatusAction + errio = StringIO() + broken = api.llvm.verifyModule(self.ptr, action, errio) + if broken: + raise llvm.LLVMException(errio.getvalue()) + + def to_bitcode(self, fileobj=None): + """Write bitcode representation of module to given file-like + object. + + fileobj -- A file-like object to where the bitcode is written. + If it is None, the bitcode is returned. + + Return value -- Returns None if fileobj is not None. + Otherwise, return the bitcode as a bytestring. + """ + ret = False + if fileobj is None: + ret = True + fileobj = StringIO + api.llvm.WriteBitcodeToFile(self.ptr, fileobj) + if ret: + return fileobj.getvalue() + + def _get_id(self): + return self.ptr.getModuleIdentifier(self.ptr) + + def _set_id(self, string): + self.ptr.setModuleIdentifier(string) + + id = property(_get_id, _set_id) + + def _to_native_something(self, fileobj, cgft): + ret = False + if fileobj is None: + ret = True + fileobj = StringIO() + cgft = api.llvm.TargetMachine.CodeGenFileType.CGFT_AssemblyFile + cgft = api.llvm.TargetMachine.CodeGenFileType.CGFT_ObjectFile + failed = tm.addPassesToEmitFile(pm, formatted, cgft, False) + if failed: + raise llvm.LLVMException("Failed to write native object file") + if ret: + return fileobj.getvalue() + + + def to_native_object(self, fileobj=None): + '''Outputs the byte string of the module as native object code + + If a fileobj is given, the output is written to it; + Otherwise, the output is returned + ''' + CGFT = api.llvm.TargetMachine.CodeGenFileType + return self._to_native_something(fileobj, CGFT.CGFT_ObjectFile) + + def to_native_assembly(self, fileobj=None): + '''Outputs the byte string of the module as native assembly code + + If a fileobj is given, the output is written to it; + Otherwise, the output is returned + ''' + CGFT = api.llvm.TargetMachine.CodeGenFileType + return self._to_native_something(fileobj, CGFT.CGFT_AssemblyFile) + + def get_or_insert_named_metadata(self, name): + return NamedMetadata(self.ptr.getOrInsertNamedMetadata(name)) + + def get_named_metadata(self, name): + return NamedMetadata(self.ptr.get_named_metadata(name)) + + def clone(self): + return NamedMetadata(api.llvm.CloneModule(self.ptr)) + +class Type(llvm.Wrapper): + """Represents a type, like a 32-bit integer or an 80-bit x86 float. + + Use one of the static methods to create an instance. Example: + ty = Type.double() + """ + + @staticmethod + def int(bits=32): + """Create an integer type having the given bit width.""" + context = api.llvm.getGlobalContext() + ptr = api.llvm.Type.getIntNTy(context, bits) + return Type(ptr) + + @staticmethod + def float(): + """Create a 32-bit floating point type.""" + context = api.llvm.getGlobalContext() + ptr = api.llvm.Type.getFloatTy(context) + return Type(ptr) + + @staticmethod + def double(): + """Create a 64-bit floating point type.""" + context = api.llvm.getGlobalContext() + ptr = api.llvm.Type.getDoubleTy(context) + return Type(ptr) + + @staticmethod + def x86_fp80(): + """Create a 80-bit x86 floating point type.""" + context = api.llvm.getGlobalContext() + ptr = api.llvm.Type.getX86_FP80Ty(context) + return Type(ptr) + + @staticmethod + def fp128(): + """Create a 128-bit floating point type (with 112-bit + mantissa).""" + context = api.llvm.getGlobalContext() + ptr = api.llvm.Type.getFP128Ty(context) + return Type(ptr) + + @staticmethod + def ppc_fp128(): + """Create a 128-bit floating point type (two 64-bits).""" + context = api.llvm.getGlobalContext() + ptr = api.llvm.Type.getPPC_FP128Ty(context) + return Type(ptr) + + + @staticmethod + def function(return_ty, param_tys, var_arg=False): + """Create a function type. + + Creates a function type that returns a value of type + `return_ty', takes arguments of types as given in the iterable + `param_tys'. Set `var_arg' to True (default is False) for a + variadic function.""" + ptr = api.llvm.FunctionType.get(return_ty._ptr, + llvm._extract_ptrs(param_tys), + var_arg) + return FunctionType(ptr) + + @staticmethod + def opaque(name): + """Create a opaque StructType""" + context = api.llvm.getGlobalContext() + ptr = api.llvm.StructType.create(context, name) + return StructType(ptr) + + @staticmethod + def struct(element_tys, name=''): # not packed + """Create a (unpacked) structure type. + + Creates a structure type with elements of types as given in the + iterable `element_tys'. This method creates a unpacked + structure. For a packed one, use the packed_struct() method. + + If name is not '', creates a identified type; + otherwise, creates a literal type.""" + context = api.llvm.getGlobalContext() + is_packed = False + ptr = api.llvm.StructType.create(context) + ptr.setBody(_extract_ptrs(element_tys), is_packed) + return StructType(ptr) + + @staticmethod + def packed_struct(element_tys, name=''): + """Create a (packed) structure type. + + Creates a structure type with elements of types as given in the + iterable `element_tys'. This method creates a packed + structure. For an unpacked one, use the struct() method. + + If name is not '', creates a identified type; + otherwise, creates a literal type.""" + context = api.llvm.getGlobalContext() + is_packed = True + ptr = api.llvm.StructType.create(context) + ptr.setBody(_extract_ptrs(element_tys), is_packed) + return StructType(ptr) + + @staticmethod + def array(element_ty, count): + """Create an array type. + + Creates a type for an array of elements of type `element_ty', + having 'count' elements.""" + ptr = api.llvm.ArrayType.get(element_ty._ptr, count) + return ArrayType(ptr) + + @staticmethod + def pointer(pointee_ty, addr_space=0): + """Create a pointer type. + + Creates a pointer type, which can point to values of type + `pointee_ty', in the address space `addr_space'.""" + ptr = api.llvm.PointerType.get(pointee_ty._ptr, addr_space) + return PointerType(ptr) + + @staticmethod + def vector(element_ty, count): + """Create a vector type. + + Creates a type for a vector of elements of type `element_ty', + having `count' elements.""" + ptr = api.llvm.VectorType.get(element_ty._ptr, count) + return VectorType(ptr) + + @staticmethod + def void(): + """Create a void type. + + Represents the `void' type.""" + context = api.llvm.getGlobalContext() + ptr = api.llvm.Type.getVoidTy(context) + return Type(ptr) + + @staticmethod + def label(): + """Create a label type.""" + context = api.llvm.getGlobalContext() + ptr = api.llvm.Type.getLabelTy(context) + return Type(ptr) + + def __new__(cls, ptr): + tyid = ptr.getTypeID() + + idmap = { + TYPE_HALF: IntegerType, + TYPE_INTEGER: IntegerType, + TYPE_FUNCTION: FunctionType, + TYPE_STRUCT: StructType, + TYPE_ARRAY: ArrayType, + TYPE_POINTER: PointerType, + TYPE_VECTOR: VectorType, + } + + try: + newcls = idmap[tyid] + except KeyError: + newcls = Type + obj = llvm.Wrapper.__new__(newcls) + return obj + + def __str__(self): + return str(self._ptr) + + def __eq__(self, rhs): + return self._ptr is rhs._ptr + + def __ne__(self, rhs): + return not (self == rhs) + +class IntegerType(Type): + """Represents an integer type.""" + + @property + def width(self): + """The width of the integer type, in bits.""" + return self._ptr.getIntegerBitWidth() + +class FunctionType(Type): + """Represents a function type.""" + + @property + def return_type(self): + """The type of the value returned by this function.""" + return Type(self._ptr.getReturnType()) + + @property + def vararg(self): + """True if this function is variadic.""" + return self._ptr.isVarArg() + + @property + def args(self): + """An iterable that yields Type objects, representing the types of the + arguments accepted by this function, in order.""" + tys = [Type(self._ptr.getParamType(i)) for i in range(self.arg_count)] + + @property + def arg_count(self): + """Number of arguments accepted by this function. + + Same as len(obj.args), but faster.""" + return self._ptr.getNumParams() + + + +class StructType(Type): + """Represents a structure type.""" + + @property + def element_count(self): + """Number of elements (members) in the structure. + + Same as len(obj.elements), but faster.""" + return self._ptr.getNumElements() + + @property + def elements(self): + """An iterable that yields Type objects, representing the types of the + elements (members) of the structure, in order.""" + return [Type(self._ptr.getElementType(i)) + for i in range(self._ptr.getNumElements())] + + def set_body(self, elems, packed=False): + """Filled the body of a opaque type. + """ + # check + if not self.is_opaque: + raise llvm.LLVMException("Body is already defined.") + + self._ptr.setBody(llvm._extract_ptrs(elems), packed) + + @property + def packed(self): + """True if the structure is packed, False otherwise.""" + return self._ptr.isPacked() + + def _set_name(self, name): + self._ptr.setName(name) + + def _get_name(self): + return self._ptr.getName() + + name = property(_get_name, _set_name) + + @property + def is_literal(self): + return self.isLiteral() + + @property + def is_identified(self): + return not self.is_literal() + + @property + def is_opaque(self): + return self.isOpaque() + +class ArrayType(Type): + """Represents an array type.""" + + @property + def element(self): + return Type(self._ptr.getArrayElementType()) + + @property + def count(self): + return self._ptr.getNumElements() + +class PointerType(Type): + + @property + def pointee(self): + return Type(self._ptr.getPointerElementType()) + + @property + def address_space(self): + return self._ptr.getAddressSpace() + +class VectorType(Type): + + @property + def element(self): + return self._ptr.getVectorElementType() + + @property + def count(self): + return self._ptr.getNumElements() + +class Value(llvm.Wrapper): + + def __str__(self): + return str(self._ptr) + + def __eq__(self, rhs): + if isinstance(rhs, Value): + return str(self) == str(rhs) + else: + return False + + def __ne__(self, rhs): + return not self == rhs + + def _get_name(self): + return self._ptr.getName() + + def _set_name(self, value): + return self._ptr.setName(value) + + name = property(_get_name, _set_name) + + @property + def value_id(self): + return self._ptr.getValueID() + + @property + def type(self): + return Type(self._ptr.getType()) + + @property + def use_count(self): + return self._ptr.getNumUses() + + @property + def uses(self): + return map(User, self._ptr.list_use()) + +class User(Value): + + @property + def operand_count(self): + return self._ptr.getNumOperands() + + @property + def operands(self): + """Yields operands of this instruction.""" + return [Value(self._ptr.getOperand(i)) + for i in range(self.operand_count)] + + def _get_operand(self, i): + return _make_value(_core.LLVMUserGetOperand(self.ptr, i)) + +class Constant(User): + + @staticmethod + def null(ty): + return Value(api.llvm.Constant.getNullValue(ty._ptr)) + + @staticmethod + def all_ones(ty): + return Value(api.llvm.Constant.getAllOnesValue(ty._ptr)) + + @staticmethod + def undef(ty): + return Value(api.llvm.UndefValue.get(ty._ptr)) + + @staticmethod + def int(ty, value): + return Value(api.llvm.ConstantInt.get(ty._ptr, value, False)) + + @staticmethod + def int_signextend(ty, value): + return Value(api.llvm.ConstantInt.get(ty._ptr, value, True)) + + @staticmethod + def real(ty, value): + return Value(api.llvm.ConstantFP.get(ty._ptr, value)) + + @staticmethod + def string(strval): # dont_null_terminate=True + return Value(api.llvm.ConstantDataArray.getString(strval, False)) + + @staticmethod + def stringz(strval): # dont_null_terminate=False + return Value(api.llvm.ConstantDataArray.getString(strval, True)) + + @staticmethod + def array(ty, consts): + return Value(api.llvm.ConstantArray.get(ty._ptr, consts)) + + @staticmethod + def struct(consts): # not packed + return Value(api.llvm.ConstantStruct.getAnon(llvm._extract_ptrs(consts), + False)) + + @staticmethod + def packed_struct(consts): + return Value(api.llvm.ConstantStruct.getAnon(llvm._extract_ptrs(consts), + False)) + + @staticmethod + def vector(consts): + return Value(api.llvm.ConstantVector.get(llvm._extract_ptrs(consts))) + + @staticmethod + def sizeof(ty): + return Value(api.llvm.ConstantExpr.getSizeOf(ty._ptr)) + + def neg(self): + return Value(api.llvm.ConstantExpr.getNeg(self._ptr)) + + def not_(self): + return Value(api.llvm.ConstantExpr.getNot(self._ptr)) + + def add(self, rhs): + return Value(api.llvm.ConstantExpr.getAdd(self._ptr, rhs._ptr)) + + def fadd(self, rhs): + return Value(api.llvm.ConstantExpr.getFAdd(self._ptr, rhs._ptr)) + + def sub(self, rhs): + return Value(api.llvm.ConstantExpr.getSub(self._ptr, rhs._ptr)) + + def fsub(self, rhs): + return Value(api.llvm.ConstantExpr.getFSub(self._ptr, rhs._ptr)) + + def mul(self, rhs): + return Value(api.llvm.ConstantExpr.getMul(self._ptr, rhs._ptr)) + + def fmul(self, rhs): + return Value(api.llvm.ConstantExpr.getFMul(self._ptr, rhs._ptr)) + + def udiv(self, rhs): + return Value(api.llvm.ConstantExpr.getUDiv(self._ptr, rhs._ptr)) + + def sdiv(self, rhs): + return Value(api.llvm.ConstantExpr.getSDiv(self._ptr, rhs._ptr)) + + def fdiv(self, rhs): + return Value(api.llvm.ConstantExpr.getFDiv(self._ptr, rhs._ptr)) + + def urem(self, rhs): + return Value(api.llvm.ConstantExpr.getURem(self._ptr, rhs._ptr)) + + def srem(self, rhs): + return Value(api.llvm.ConstantExpr.getSRem(self._ptr, rhs._ptr)) + + def frem(self, rhs): + return Value(api.llvm.ConstantExpr.getFRem(self._ptr, rhs._ptr)) + + def and_(self, rhs): + return Value(api.llvm.ConstantExpr.getAnd(self._ptr, rhs._ptr)) + + def or_(self, rhs): + return Value(api.llvm.ConstantExpr.getOr(self._ptr, rhs._ptr)) + + def xor(self, rhs): + return Value(api.llvm.ConstantExpr.getXor(self._ptr, rhs._ptr)) + + def icmp(self, int_pred, rhs): + return Value(api.llvm.ConstantExpr.getICmp(int_pred, self._ptr, rhs._ptr)) + + def fcmp(self, real_pred, rhs): + return Value(api.llvm.ConstantExpr.getFCmp(real_pred, self._ptr, rhs._ptr)) + + def shl(self, rhs): + return Value(api.llvm.ConstantExpr.getShl(self._ptr, rhs._ptr)) + + def lshr(self, rhs): + return Value(api.llvm.ConstantExpr.getLShr(self._ptr, rhs._ptr)) + + def ashr(self, rhs): + return Value(api.llvm.ConstantExpr.getAShr(self._ptr, rhs._ptr)) + + def gep(self, indices): + indices = llvm._extract_ptrs(indices) + return Value(api.llvm.ConstantExpr.getGetElementPtr(self._ptr, indices)) + + def trunc(self, ty): + return Value(api.llvm.ConstantExpr.getTrunc(self._ptr, ty)) + + def sext(self, ty): + return Value(api.llvm.ConstantExpr.getSExt(self._ptr, ty)) + + def zext(self, ty): + return Value(api.llvm.ConstantExpr.getZExt(self._ptr, ty)) + + def fptrunc(self, ty): + return Value(api.llvm.ConstantExpr.getFPTrunc(self._ptr, ty)) + + def fpext(self, ty): + return Value(api.llvm.ConstantExpr.getFPExtend(self._ptr, ty)) + + def uitofp(self, ty): + return Value(api.llvm.ConstantExpr.getUIToFP(self._ptr, ty)) + + def sitofp(self, ty): + return Value(api.llvm.ConstantExpr.getSIToFP(self._ptr, ty)) + + def fptoui(self, ty): + return Value(api.llvm.ConstantExpr.getFPToUI(self._ptr, ty)) + + def fptosi(self, ty): + return Value(api.llvm.ConstantExpr.getFPToSI(self._ptr, ty)) + + def ptrtoint(self, ty): + return Value(api.llvm.ConstantExpr.getPtrToInt(self._ptr, ty)) + + def inttoptr(self, ty): + return Value(api.llvm.ConstantExpr.getIntToPtr(self._ptr, ty)) + + def bitcast(self, ty): + return Value(api.llvm.ConstantExpr.getBitCast(self._ptr, ty)) + + def select(self, true_const, false_const): + return Value(api.llvm.ConstantExpr.getSelect(self._ptr, + true_const._ptr, + false_const._ptr)) + + def extract_element(self, index): # note: self must be a _vector_ constant + return Value(api.llvm.ConstantExpr.getExtractElement(self._ptr, index._ptr)) + + def insert_element(self, value, index): + return Value(api.llvm.ConstantExpr.getExtractElement(self._ptr, + value._ptr, + index._ptr)) + + def shuffle_vector(self, vector_b, mask): + return Value(api.llvm.ConstantExpr.getShuffleVector(self._ptr, + vector_b._ptr, + mask._ptr)) + +class ConstantExpr(Constant): + @property + def opcode(self): + return self._ptr.getOpcode() + + @property + def opcode_name(self): + return self._ptr.getOpcodeName() + +class ConstantAggregateZero(Constant): + pass + + +class ConstantDataArray(Constant): + pass + + +class ConstantDataVector(Constant): + pass + + +class ConstantInt(Constant): + @property + def z_ext_value(self): + '''Obtain the zero extended value for an integer constant value.''' + # Warning: assertion failure when value does not fit in 64 bits + return self._ptr.getZExtValue() + + @property + def s_ext_value(self): + '''Obtain the sign extended value for an integer constant value.''' + # Warning: assertion failure when value does not fit in 64 bits + return self._ptr.getSExtValue() + + +class ConstantFP(Constant): + pass + + +class ConstantArray(Constant): + pass + + +class ConstantStruct(Constant): + pass + + +class ConstantVector(Constant): + pass + + +class ConstantPointerNull(Constant): + pass + + +class UndefValue(Constant): + pass + + +class GlobalValue(Constant): + + def _get_linkage(self): + return self._ptr.getLinkage() + + def _set_linkage(self, value): + self._ptr.setLinkage(value) + + linkage = property(_get_linkage, _set_linkage) + + def _get_section(self): + return self._ptr.getSection() + + def _set_section(self, value): + return self._ptr.setSection(value) + + section = property(_get_section, _set_section) + + def _get_visibility(self): + return self._ptr.getVisibility() + + def _set_visibility(self, value): + return self._ptr.setVisibility(value) + + visibility = property(_get_visibility, _set_visibility) + + def _get_alignment(self): + return self._ptr.getAlignment() + + def _set_alignment(self, value): + return self._ptr.setAlignment(value) + + alignment = property(_get_alignment, _set_alignment) + + @property + def is_declaration(self): + return self._ptr.isDeclaration() + + @property + def module(self): + return Module(self._ptr.getParent()) + + + +class GlobalVariable(GlobalValue): + + @staticmethod + def new(module, ty, name, addrspace=0): + linkage = api.llvm.GlobalValue.LinkageTypes + external_linkage = linkage.ExternalLinkage + tlmode = api.llvm.GlobalVariable.ThreadLocalMode + not_threadlocal = tlmode.NotThreadLocal + gv = api.llvm.GlobalVariablel.new(module._ptr, + ty._ptr, + False, # is constant + external_linkage, + None, # initializer + name, + None, # insert before + not_threadlocal, + addrspace) + return GlobalVariable(gv) + + @staticmethod + def get(module, name): + gv = GlobalVariable(module._ptr.getNamedGlobal(name)) + if not gv: + llvm.LLVMException("no global named `%s`" % name) + return gv + + def delete(self): + self._ptr.eraseFromParent() + + def _get_initializer(self): + if not self._ptr.hasInitializer(): + return None + return Constant(self._ptr.getInitializer()) + + def _set_initializer(self, const): + self._ptr.setInitializer(const._ptr) + + def _del_initializer(self): + self._ptr.setInitializer(None) + + initializer = property(_get_initializer, _set_initializer) + + def _get_is_global_constant(self): + return self._ptr.isConstant() + + def _set_is_global_constant(self, value): + self._ptr.setConstant(value) + + global_constant = property(_get_is_global_constant, + _set_is_global_constant) + + def _get_thread_local(self): + return self._ptr.isThreadLocal() + + def _set_thread_local(self, value): + return self._ptr.setThreadLocal(value) + + thread_local = property(_get_thread_local, _set_thread_local) + +class Argument(Value): + + def add_attribute(self, attr): + attrbldr = api.llvm.AttrBuilder() + attrbldr.addAttribute(attr) + attrs = api.llvm.Attributes.get(context, attrbldr) + self._ptr.addAttr(attrs) + + def remove_attribute(self, attr): + attrbldr = api.llvm.AttrBuilder() + attrbldr.addAttribute(attr) + attrs = api.llvm.Attributes.get(context, attrbldr) + self._ptr.removeAttr(attrs) + + def _set_alignment(self, align): + attrbldr = api.llvm.AttrBuilder() + attrbldr.addAlignmentAttr(align) + attrs = api.llvm.Attributes.get(context, attrbldr) + self._ptr.addAttr(attrs) + + def _get_alignment(self): + return self._ptr.getParamAlignment() + + alignment = property(_get_alignment, + _set_alignment) + +class Function(GlobalValue): + + @staticmethod + def new(module, func_ty, name): + return module.add_function(func_ty, name) + + @staticmethod + def get_or_insert(module, func_ty, name): + return module.get_or_insert_function(func_ty, name) + + @staticmethod + def get(module, name): + return module.get_function_named(name) + + @staticmethod + def intrinsic(module, intrinsic_id, types): + fn = api.llvm.Intrinsic.getDeclaration(module._ptr, + intrinsic_id, + types) + return Function(fn) + + def delete(self): + self._ptr.eraseFromParent() + + @property + def intrinsic_id(self): + self._ptr.getIntrinsicID() + + def _get_cc(self): + return self._ptr.getCallingConv() + + def _set_cc(self, value): + self._ptr.setCallingConv(value) + + calling_convention = property(_get_cc, _set_cc) + + def _get_coll(self): + return self._ptr.getGC() + + def _set_coll(self, value): + return self._ptr.setGC(value) + + collector = property(_get_coll, _set_coll) + + # the nounwind attribute: + def _get_does_not_throw(self): + return self._ptr.doesNotThrow() + + def _set_does_not_throw(self,value): + assert value + self._ptr.setDoesNotThow() + + does_not_throw = property(_get_does_not_throw, _set_does_not_throw) + + @property + def args(self): + return self._ptr.getArgumentList() + + @property + def basic_block_count(self): + return len(self.basic_blocks) + + @property + def entry_basic_block(self): + return self._ptr.getEntryBlock() + + def append_basic_block(self, name): + context = api.llvm.getGlobalContext() + bb = api.llvm.BasicBlock.Create(context, name, self._ptr, None) + return BasicBlock(bb) + + @property + def basic_blocks(self): + return self._ptr.getBasicBlockList() + + def viewCFG(self): + return self._ptr.viewCFG() + + def add_attribute(self, attr): + _core.LLVMAddFunctionAttr(self.ptr, attr) + + def remove_attribute(self, attr): + attrbldr = api.llvm.AttrBuilder() + attrbldr.addAttribute(attr) + attrs = api.llvm.Attributes.get(context, attrbldr) + self._ptr.removeFnAttr(attrs) + + def viewCFGOnly(self): + return self._ptr.viewCFGOnly() + + def verify(self): + # Although we're just asking LLVM to return the success or + # failure, it appears to print result to stderr and abort. + + # Note: LLVM has a bug in preverifier that will always abort + # the process upon failure. + return api.llvm.verifyFunction() + +#===----------------------------------------------------------------------=== +# InlineAsm +#===----------------------------------------------------------------------=== + +class InlineAsm(Value): + @staticmethod + def get(functype, asm, constrains, side_effect=False, + align_stack=False, dialect=api.llvm.InlineAsm.AsmDialect.AD_ATT): + ilasm = api.llvm.InlineAsm.get(functype._ptr, asm, contrains, side_effect, + align_stack, dialect) + return InlineAsm(ilasm) + +#===----------------------------------------------------------------------=== +# MetaData +#===----------------------------------------------------------------------=== + +class MetaData(Value): + @staticmethod + def get(module, values): + ''' + values -- must be an iterable of Constant or None. None is treated as "null". + ''' + context = api.llvm.getGlobalContext() + ptr = api.llvm.MDNode.get(context, llvm._extract_ptrs(values)) + return MetaData(ptr) + + @staticmethod + def get_named_operands(module, name): + namedmd = module.get_named_metadata(name)._ptr + return [MetaData(namedmd.getOperand(i)) + for i in namedmd.getNumOperands()] + + @staticmethod + def add_named_operand(module, name, operand): + namedmd = module.get_or_insert_named_metadata(name)._ptr + namedmd.addOperand(operand._ptr) + + @property + def operand_count(self): + return self._ptr.getOperand() + + @property + def operands(self): + """Yields operands of this metadata.""" + return [Value(self._ptr.getOperand(i)) for i in self.operand_count] + + +class MetaDataString(Value): + @staticmethod + def get(module, s): + context = api.llvm.getGlobalContext() + ptr = api.llvm.MDString.get(context, s) + return MetaDataString(ptr) + + @property + def string(self): + '''Same as MDString::getString''' + return self._ptr.getString() + + +class NamedMetaData(llvm.Wrapper): + @staticmethod + def get_or_insert(mod, name): + return mod.get_or_insert_named_metadata(name) + + @staticmethod + def get(mod, name): + return mod.get_named_metadata(name) + + def delete(self): + self._ptr.eraseFromParent() + + @property + def name(self): + return self._ptr.getName() + + def __str__(self): + return str(self._ptr) + + def add(self, operand): + self._ptr.addOperand(operand._ptr) + + +#===----------------------------------------------------------------------=== +# Instruction +#===----------------------------------------------------------------------=== + +class Instruction(User): + + @property + def basic_block(self): + return BasicBlock(self._ptr.getParent()) + + @property + def is_terminator(self): + return self._ptr.isTerminator() + + @property + def is_binary_op(self): + return self._ptr.isBinaryOp() + + @property + def is_shift(self): + return self._ptr.isShift() + + @property + def is_cast(self): + return self._ptr.isCast() + + @property + def is_logical_shift(self): + return self._ptr.isLogicalShift() + + @property + def is_arithmetic_shift(self): + return self._ptr.isArithmeticShift() + + @property + def is_associative(self): + return self._ptr.isAssociative() + + @property + def is_commutative(self): + return self._ptr.isCommutative() + + @property + def is_volatile(self): + """True if this is a volatile load or store.""" + if api.llvm.LoadInst.classof(self._ptr): + return self._ptr._downcast(api.llvm.LoadInst).isVolatile() + elif api.llvm.StoreInst.classof(self._ptr): + return self._ptr._downcast(api.llvm.StoreInst).isVolatile() + else: + return False + + def set_volatile(self, flag): + if api.llvm.LoadInst.classof(self._ptr): + return self._ptr._downcast(api.llvm.LoadInst).setVolatile(flag) + elif api.llvm.StoreInst.classof(self._ptr): + return self._ptr._downcast(api.llvm.StoreInst).setVolatile(flag) + else: + return False + + def set_metadata(self, kind, metadata): + self._ptr.setMetadata(kind, metadata._ptr) + + @property + def opcode(self): + return self._ptr.getOpcode() + + @property + def opcode_name(self): + return self._ptr.getOpcodeName() + + def erase_from_parent(self): + return self._ptr.eraseFromParent() + + +class CallOrInvokeInstruction(Instruction): + + def _get_cc(self): + return self._ptr.getCallingConv() + + def _set_cc(self, value): + return self._ptr.setCallingConv(value) + + calling_convention = property(_get_cc, _set_cc) + + def add_parameter_attribute(self, idx, attr): + attrbldr = api.llvm.AttrBuilder() + attrbldr.addAttribute(attr) + attrs = api.llvm.Attributes.get(context, attrbldr) + self._ptr.addAttribute(idx, attrs) + + def remove_parameter_attribute(self, idx, attr): + attrbldr = api.llvm.AttrBuilder() + attrbldr.addAttribute(attr) + attrs = api.llvm.Attributes.get(context, attrbldr) + self._ptr.removeAttribute(idx, attrs) + + def set_parameter_alignment(self, idx, align): + attrbldr = api.llvm.AttrBuilder() + attrbldr.addAlignmentAttr(align) + attrs = api.llvm.Attributes.get(context, attrbldr) + self._ptr.addAttribute(idx, attrs) + + def _get_called_function(self): + function = self._ptr.getCalledFunction() + if function: # Return value can be None on indirect call/invoke + return Value(function) + + def _set_called_function(self, function): + self._ptr.setCalledFunction(function) + + called_function = property(_get_called_function, _set_called_function) + + +class PHINode(Instruction): + + @property + def incoming_count(self): + return self._ptr.getNumIncomingValues() + + def add_incoming(self, value, block): + self._ptr.addIncoming(value._ptr, block._ptr) + + def get_incoming_value(self, idx): + return self._ptr.getIncomingValue(idx) + + def get_incoming_block(self, idx): + return self._ptr.getIncomingBlock(idx) + + +class SwitchInstruction(Instruction): + + def add_case(self, const, bblk): + self._ptr.addCase(const._ptr, bblk._ptr) + + +class CompareInstruction(Instruction): + + @property + def predicate(self): + return self._ptr.getPredicate() + + +#===----------------------------------------------------------------------=== +# Basic block +#===----------------------------------------------------------------------=== + +class BasicBlock(Value): + + def insert_before(self, name): + context = api.llvm.getGlobalContext() + ptr = api.llvm.BasicBlock.Create(context, name, self.function._ptr, + self._ptr) + return BasicBlock(ptr) + + def delete(self): + self._ptr.eraseFromParent() + + @property + def function(self): + return Function(self._ptr.getParent()) + + @property + def instructions(self): + return map(Value, self._ptr.getInstList()) + + +#===----------------------------------------------------------------------=== +# Builder +#===----------------------------------------------------------------------=== + +class Builder(llvm.Wrapper): + + @staticmethod + def new(basic_block): + context = api.llvm.getGlobalContext() + ptr = api.llvm.IRBuilder.new(context) + ptr.SetInsertPoint(basic_block._ptr) + return BasicBlock(ptr) + + def position_at_beginning(self, bblk): + """Position the builder at the beginning of the given block. + + Next instruction inserted will be first one in the block.""" + + # Instruction list won't be long anyway, + # Does not matter much to build a list of all instructions + instrs = bblk._ptr.getInstList() + if instrs: + self.position_before(instrs[0]) + else: + self.position_at_end(bblk) + + def position_at_end(self, bblk): + """Position the builder at the end of the given block. + + Next instruction inserted will be last one in the block.""" + self._ptr.SetInsertPoint(bblk._ptr) + + def position_before(self, instr): + """Position the builder before the given instruction. + + The instruction can belong to a basic block other than the + current one.""" + self._ptr.SetInsertPoint(instr._ptr) + + @property + def basic_block(self): + """The basic block where the builder is positioned.""" + return BasicBlock(self._ptr.GetInsertBlock()) + + # terminator instructions + + def ret_void(self): + return Value(self._ptr.CreateRetVoid()) + + def ret(self, value): + return Value(self._ptr.CreateRet(value._ptr)) + + def ret_many(self, values): + values = llvm._extract_ptrs(values) + return Value(self._ptr.CreateAggregateRet(values, len(values))) + + def branch(self, bblk): + if __debug__: + for instr in self.basic_block.instructions: + assert not instr.is_terminator, "BasicBlock can only have one terminator" + return Value(self._ptr.CreateBr(bblk._ptr)) + + def cbranch(self, if_value, then_blk, else_blk): + return Value(self._ptr.CreateCondBr(if_value._ptr, + then_blk._ptr, + else_blk._ptr)) + + def switch(self, value, else_blk, n=10): + return Value(self._ptr.CreateSwitch(self.value._ptr, + self.else_blk._ptr, + n)) + + def invoke(self, func, args, then_blk, catch_blk, name=""): + return Value(self._ptr.CreateInvoke(self.func._ptr, + self.then_blk._ptr, + self.catch_blk._ptr, + args)) + + def unreachable(self): + return Value(self._ptr.CreateUnreachable()) + + # arithmethic, bitwise and logical + + def add(self, lhs, rhs, name=""): + return Value(self._ptr.CreateAdd(lhs._ptr, rhs._ptr, name)) + + def fadd(self, lhs, rhs, name=""): + return Value(self._ptr.CreateFAdd(lhs._ptr, rhs._ptr, name)) + + def sub(self, lhs, rhs, name=""): + return Value(self._ptr.CreateSub(lhs._ptr, rhs._ptr, name)) + + def fsub(self, lhs, rhs, name=""): + return Value(self._ptr.CreateFSub(lhs._ptr, rhs._ptr, name)) + + def mul(self, lhs, rhs, name=""): + return Value(self._ptr.CreateMul(lhs._ptr, rhs._ptr, name)) + + def fmul(self, lhs, rhs, name=""): + return Value(self._ptr.CreateFMul(lhs._ptr, rhs._ptr, name)) + + def udiv(self, lhs, rhs, name=""): + return Value(self._ptr.CreateUDiv(lhs._ptr, rhs._ptr, name)) + + def sdiv(self, lhs, rhs, name=""): + return Value(self._ptr.CreateSDiv(lhs._ptr, rhs._ptr, name)) + + def fdiv(self, lhs, rhs, name=""): + return Value(self._ptr.CreateFDiv(lhs._ptr, rhs._ptr, name)) + + def urem(self, lhs, rhs, name=""): + return Value(self._ptr.CreateURem(lhs._ptr, rhs._ptr, name)) + + def srem(self, lhs, rhs, name=""): + return Value(self._ptr.CreateSRem(lhs._ptr, rhs._ptr, name)) + + def frem(self, lhs, rhs, name=""): + return Value(self._ptr.CreateFRem(lhs._ptr, rhs._ptr, name)) + + def shl(self, lhs, rhs, name=""): + return Value(self._ptr.CreateShl(lhs._ptr, rhs._ptr, name)) + + def lshr(self, lhs, rhs, name=""): + return Value(self._ptr.CreateLShr(lhs._ptr, rhs._ptr, name)) + + def ashr(self, lhs, rhs, name=""): + return Value(self._ptr.CreateAShr(lhs._ptr, rhs._ptr, name)) + + def and_(self, lhs, rhs, name=""): + return Value(self._ptr.CreateAnd(lhs._ptr, rhs._ptr, name)) + + def or_(self, lhs, rhs, name=""): + return Value(self._ptr.CreateOr(lhs._ptr, rhs._ptr, name)) + + def xor(self, lhs, rhs, name=""): + return Value(self._ptr.CreateXor(lhs._ptr, rhs._ptr, name)) + + def neg(self, val, name=""): + return Value(self._ptr.CreateNeg(val._ptr, name)) + + def not_(self, val, name=""): + return Value(self._ptr.CreateNot(val._ptr, name)) + + # memory + + def malloc(self, ty, name=""): + context = api.llvm.getGlobalContext() + intty = api.llvm.Type.getInt32Ty(context) + sizeof = api.llvm.ConstantExpr.getSizeOf(ty) + zero = api.llvm.ConstantInt.get(intty, 0) + # XXX: how do I know when to insert? + # assume to end of block for now + inst = api.llvm.CallInst.CreateMalloc(self.basic_block._ptr, + intty, + ty._ptr, + sizeof, + zero, + None, + name) + return Value(inst) + + def malloc_array(self, ty, size, name=""): + sizeof = api.llvm.ConstantExpr.getSizeOf(ty) + # XXX: how do I know when to insert? + # assume to end of block for now + inst = api.llvm.CallInst.CreateMalloc(self.basic_block._ptr, + size.type._ptr, + ty._ptr, + sizeof, + size._ptr, + None, + name) + return Value(inst) + + def alloca(self, ty, name=""): + zero = api.llvm.ConstantInt.get(intty, 0) + return Value(self._ptr.CreateAlloca(ty._ptr, zero, name)) + + def alloca_array(self, ty, size, name=""): + return Value(self._ptr.CreateAlloca(ty._ptr, size._ptr, name)) + + def free(self, ptr): + return Value(api.llvm.CallInst.CreateFree(ptr._ptr, self.basic_block._ptr)) + + def load(self, ptr, name="", align=0, volatile=False, invariant=False): + inst = Value(self._ptr.CreateLoad(ptr._ptr, name)) + if align: + inst._ptr.setAlignment(align) + if volatile: + inst.set_volatile(volatile) + if invariant: + mod = self.basic_block.function.module + md = MetaData.get(mod, []) # empty metadata node + inst.set_metadata('invariant.load', md) + return inst + + def store(self, value, ptr, align=0, volatile=False): + inst = Value(self._ptr.CreateStore(value._ptr, ptr._ptr)) + if align: + inst._ptr.setAlignment(align) + if volatile: + inst.set_volatile(volatile) + return inst + + def gep(self, ptr, indices, name="", inbounds=False): + if inbounds: + ret = self._ptr.CreateInBoundsGEP(ptr._ptr, + llvm._extract_ptrs(indices), + name) + else: + ret = self._ptr.CreateGEP(ptr._ptr, + llvm._extract_ptrs(indices), + name) + return Value(ret) + + # casts and extensions + + def trunc(self, value, dest_ty, name=""): + return Value(self._ptr.CreateTrunc(value._ptr, dest_ty._ptr, name)) + + def zext(self, value, dest_ty, name=""): + return Value(self._ptr.CreateZext(value._ptr, dest_ty._ptr, name)) + + def sext(self, value, dest_ty, name=""): + return Value(self._ptr.CreateSext(value._ptr, dest_ty._ptr, name)) + + def fptoui(self, value, dest_ty, name=""): + return Value(self._ptr.CreateFPToUI(value._ptr, dest_ty._ptr, name)) + + def fptosi(self, value, dest_ty, name=""): + return Value(self._ptr.CreateFPToSI(value._ptr, dest_ty._ptr, name)) + + def uitofp(self, value, dest_ty, name=""): + return Value(self._ptr.CreateUIToFP(value._ptr, dest_ty._ptr, name)) + + def sitofp(self, value, dest_ty, name=""): + return Value(self._ptr.CreateSIToFP(value._ptr, dest_ty._ptr, name)) + + def fptrunc(self, value, dest_ty, name=""): + return Value(self._ptr.CreateFPTrunc(value._ptr, dest_ty._ptr, name)) + + def fpext(self, value, dest_ty, name=""): + return Value(self._ptr.CreateFPExt(value._ptr, dest_ty._ptr, name)) + + def ptrtoint(self, value, dest_ty, name=""): + return Value(self._ptr.CreatePtrToInt(value._ptr, dest_ty._ptr, name)) + + def inttoptr(self, value, dest_ty, name=""): + return Value(self._ptr.CreateIntToPtr(value._ptr, dest_ty._ptr, name)) + + def bitcast(self, value, dest_ty, name=""): + return Value(self._ptr.CreateBitCast(value._ptr, dest_ty._ptr, name)) + + # comparisons + + def icmp(self, ipred, lhs, rhs, name=""): + return Value(self._ptr.CreateICmp(ipred, lhs._ptr, rhs._ptr, name)) + + def fcmp(self, rpred, lhs, rhs, name=""): + return Value(self._ptr.CreateFCmp(rpred, lhs._ptr, rhs._ptr, name)) + + # misc + + def extract_value(self, retval, idx, name=""): + return Value(self._ptr.CreateExtractValue(retval._ptr, [idx], name)) + + # obsolete synonym for extract_value + getresult = extract_value + + def insert_value(self, retval, rhs, idx, name=""): + return Value(self._ptr.CreateInsertValue(retval._ptr, + rhs._ptr, + [idx], + name)) + + def phi(self, ty, name=""): + return Value(self._ptr.CreatePHI(ty._ptr, 2, name)) + + def call(self, fn, args, name=""): + err_template = 'Argument type mismatch: expected %s but got %s' + for i, (t, v) in enumerate(zip(fn.type.pointee.args, args)): + if t != v.type: + raise TypeError(err_template % (t, v.type)) + arg_ptrs = llvm._extract_ptrs(args) + return Value(self._ptr.CreateCall(fn._ptr, arg_ptrs, name)) + + def select(self, cond, then_value, else_value, name=""): + return Value(self._ptr.CreateSelect(cond._ptr, then_value._ptr, + else_value._ptr, name)) + + def vaarg(self, list_val, ty, name=""): + return Value(self._ptr.CreateVAArg(list_val._ptr, ty._ptr, name)) + + def extract_element(self, vec_val, idx_val, name=""): + return Value(self._ptr.CreateExtractElement(vec_val._ptr, + idx_val_.ptr, + name)) + + + def insert_element(self, vec_val, elt_val, idx_val, name=""): + return Value(self._ptr.CreateExtractElement(vec_val._ptr, + elt_val._ptr, + idx_val_.ptr, + name)) + + def shuffle_vector(self, vecA, vecB, mask, name=""): + return Value(self._ptr.CreateShuffleVector(vecA._ptr, + vecB._ptr, + mask._ptr, + name)) + # atomics + + def atomic_cmpxchg(self, ptr, old, new, ordering, crossthread=True): + return Value(self._ptr.CreateAtomicCmpXchg(ptr._ptr, + old._ptr, + new._ptr, + ordering, + _sync_scope(crossthread))) + + def atomic_rmw(self, op, ptr, val, ordering, crossthread=True): + op_dict = dict((k.lower(), v) + for k, v in vars(api.llvm.AtomicRMWInst.BinOp)) + op = op_dict[op] + return Value(self._ptr.CreateAtomicRMW(op, ptr._ptr, val._ptr, + ordering, + _sync_scope(crossthread))) + + def atomic_xchg(self, *args, **kwargs): + return self.atomic_rmw('xchg', *args, **kwargs) + + def atomic_add(self, *args, **kwargs): + return self.atomic_rmw('add', *args, **kwargs) + + def atomic_sub(self, *args, **kwargs): + return self.atomic_rmw('sub', *args, **kwargs) + + def atomic_and(self, *args, **kwargs): + return self.atomic_rmw('and', *args, **kwargs) + + def atomic_nand(self, *args, **kwargs): + return self.atomic_rmw('nand', *args, **kwargs) + + def atomic_or(self, *args, **kwargs): + return self.atomic_rmw('or', *args, **kwargs) + + def atomic_xor(self, *args, **kwargs): + return self.atomic_rmw('xor', *args, **kwargs) + + def atomic_max(self, *args, **kwargs): + return self.atomic_rmw('max', *args, **kwargs) + + def atomic_min(self, *args, **kwargs): + return self.atomic_rmw('min', *args, **kwargs) + + def atomic_umax(self, *args, **kwargs): + return self.atomic_rmw('umax', *args, **kwargs) + + def atomic_umin(self, *args, **kwargs): + return self.atomic_rmw('umin', *args, **kwargs) + + def atomic_load(self, ptr, ordering, align=1, crossthread=True, + volatile=False, name=""): + inst = self._ptr.load(ptr, align=align, volatile=volatile, name=name) + inst._ptr.setAtomic(ordering, _sync_scope(crossthread)) + return inst + + def atomic_store(self, value, ptr, ordering, align=1, crossthread=True, + volatile=False): + inst = self._ptr.store(ptr, value, align=align, volatile=volatile, + name=name) + inst._ptr.setAtomic(ordering, _sync_scope(crossthread)) + return inst + + + def fence(self, ordering, crossthread=True): + return Value(self._ptr.CreateFence(ordering, + _sync_scope(crossthread))) + +def _sync_scope(crossthread): + if crossthread: + scope = api.llvm.SynchronizationScope.CrossThread + else: + scope = api.llvm.SynchronizationScope.SingleThread + return scope + +def load_library_permanently(filename): + """Load a shared library. + + Load the given shared library (filename argument specifies the full + path of the .so file) using LLVM. Symbols from these are available + from the execution engine thereafter.""" + with contextlib.closing(StringIO()) as errmsg: + failed = _api.llvm.sys.LoadLibraryPermanently(filename, errmsg) + if failed: + raise llvm.LLVMException(errmsg.getvalue()) + +def inline_function(call): + info = _api.llvm.InlineFunctionInfo() + return _api.llvm.InlineFunction(call._ptr, info) + +def parse_environment_options(progname, envname): + _api.llvm.cl.ParseEnvironmentOptions(progname, envname) + +if _api.llvm.InitializeNativeTarget(): + raise llvm.LLVMException("No native target!?") +if _api.llvm.InitializeNativeTargetAsmPrinter(): + # should this be an optional feature? + # should user trigger the initialization? + raise llvm.LLVMException("No native asm printer!?") + +#===----------------------------------------------------------------------=== +# Initialization +#===----------------------------------------------------------------------=== + +HAS_PTX = HAS_NVPTX = False + +if True: # use PTX? + try: + _api.LLVMInitializePTXTarget() + _api.LLVMInitializePTXTargetInfo() + _api.LLVMInitializePTXTargetMC() + _api.LLVMInitializePTXAsmPrinter() + HAS_PTX = True + except AttributeError: + try: + _api.LLVMInitializeNVPTXTarget() + _api.LLVMInitializeNVPTXTargetInfo() + _api.LLVMInitializeNVPTXTargetMC() + _api.LLVMInitializeNVPTXAsmPrinter() + HAS_NVPTX = True + except AttributeError: + pass + - \ No newline at end of file From 230583f42ddec81bcea0f153c29f8e1930c7f900 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 8 Feb 2013 18:16:26 -0600 Subject: [PATCH 64/85] Fix bug with empty namespace --- newbinding/gen/binding.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/newbinding/gen/binding.py b/newbinding/gen/binding.py index 51620a8..cfe4394 100644 --- a/newbinding/gen/binding.py +++ b/newbinding/gen/binding.py @@ -578,7 +578,7 @@ class Function(Method): with writer.function(self.name, varargs='args') as varargs: unwrapped = writer.unwrap_many(varargs) self.process_ownedptr_args(writer, unwrapped) - func = '.'.join([self.parent.py_name, self.name]) + func = '.'.join([self.parent.py_name, self.name]).lstrip('.') ret = writer.call('_api.%s' % func, varargs=unwrapped) wrapped = writer.wrap(ret, self.is_return_ownedptr()) writer.return_value(wrapped) From 0681d2f37eb4a67aa2e8b78403241bd2f7a7e03e Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 8 Feb 2013 18:22:53 -0600 Subject: [PATCH 65/85] Fixes various problem in llvm.core --- llvm/core.py | 70 ++++++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/llvm/core.py b/llvm/core.py index 6d5f0d1..2f7adb5 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -318,7 +318,7 @@ class Module(llvm.Wrapper): ll = str(module_obj) print module_obj # same as `print ll' """ - return str(self.ptr) + return str(self._ptr) def __eq__(self, rhs): if isinstance(rhs, Module): @@ -331,20 +331,20 @@ class Module(llvm.Wrapper): def _get_target(self): - return self.ptr.getTargetTriple() + return self._ptr.getTargetTriple() def _set_target(self, value): - return self.ptr.setTargetTriple(value) + return self._ptr.setTargetTriple(value) target = property(_get_target, _set_target, doc="The target triple string describing the target host.") def _get_data_layout(self): - return self.ptr.getDataLayout() + return self._ptr.getDataLayout() def _set_data_layout(self, value): - return self.ptr.setDataLayout(value) + return self._ptr.setDataLayout(value) data_layout = property(_get_data_layout, _set_data_layout, doc = """The data layout string for the module's target platform. @@ -383,7 +383,7 @@ class Module(llvm.Wrapper): raise llvm.LLVMException(errmsg) def get_type_named(self, name): - typ = self.ptr.getTypeByName(name) + typ = self._ptr.getTypeByName(name) return StructType(typ) def add_global_variable(self, ty, name, addrspace=0): @@ -405,12 +405,12 @@ class Module(llvm.Wrapper): def get_global_variable_named(self, name): """Return a GlobalVariable object for the given name.""" - ptr = self.ptr.getNamedGlobal(name) + ptr = self._ptr.getNamedGlobal(name) return GlobalVariable(ptr) @property def global_variables(self): - return self.ptr.list_globals() + return self._ptr.list_globals() def add_function(self, ty, name): """Add a function of given type with given name.""" @@ -421,7 +421,7 @@ class Module(llvm.Wrapper): def get_function_named(self, name): """Return a Function object representing function with given name.""" - fn = self.ptr.getFunction(name) + fn = self._ptr.getFunction(name) if fn is None: return None return Function(fn) @@ -429,14 +429,14 @@ class Module(llvm.Wrapper): def get_or_insert_function(self, ty, name): """Like get_function_named(), but does add_function() first, if function is not present.""" - constant = self.ptr.getOrInsertFunction(name, ty._ptr) + constant = self._ptr.getOrInsertFunction(name, ty._ptr) fn = constant._downcast(api.llvm.Function) return Function(fn) @property def functions(self): """All functions in this module.""" - return map(Function, self.ptr.list_functions()) + return map(Function, self._ptr.list_functions()) def verify(self): """Verify module. @@ -445,7 +445,7 @@ class Module(llvm.Wrapper): error.""" action = api.llvm.VerifierFailureAction.ReturnStatusAction errio = StringIO() - broken = api.llvm.verifyModule(self.ptr, action, errio) + broken = api.llvm.verifyModule(self._ptr, action, errio) if broken: raise llvm.LLVMException(errio.getvalue()) @@ -463,15 +463,15 @@ class Module(llvm.Wrapper): if fileobj is None: ret = True fileobj = StringIO - api.llvm.WriteBitcodeToFile(self.ptr, fileobj) + api.llvm.WriteBitcodeToFile(self._ptr, fileobj) if ret: return fileobj.getvalue() def _get_id(self): - return self.ptr.getModuleIdentifier(self.ptr) + return self._ptr.getModuleIdentifier(self._ptr) def _set_id(self, string): - self.ptr.setModuleIdentifier(string) + self._ptr.setModuleIdentifier(string) id = property(_get_id, _set_id) @@ -508,13 +508,13 @@ class Module(llvm.Wrapper): return self._to_native_something(fileobj, CGFT.CGFT_AssemblyFile) def get_or_insert_named_metadata(self, name): - return NamedMetadata(self.ptr.getOrInsertNamedMetadata(name)) + return NamedMetadata(self._ptr.getOrInsertNamedMetadata(name)) def get_named_metadata(self, name): - return NamedMetadata(self.ptr.get_named_metadata(name)) + return NamedMetadata(self._ptr.get_named_metadata(name)) def clone(self): - return NamedMetadata(api.llvm.CloneModule(self.ptr)) + return NamedMetadata(api.llvm.CloneModule(self._ptr)) class Type(llvm.Wrapper): """Represents a type, like a 32-bit integer or an 80-bit x86 float. @@ -860,7 +860,7 @@ class User(Value): for i in range(self.operand_count)] def _get_operand(self, i): - return _make_value(_core.LLVMUserGetOperand(self.ptr, i)) + return _make_value(_core.LLVMUserGetOperand(self._ptr, i)) class Constant(User): @@ -1309,7 +1309,7 @@ class Function(GlobalValue): return self._ptr.viewCFG() def add_attribute(self, attr): - _core.LLVMAddFunctionAttr(self.ptr, attr) + _core.LLVMAddFunctionAttr(self._ptr, attr) def remove_attribute(self, attr): attrbldr = api.llvm.AttrBuilder() @@ -1589,7 +1589,7 @@ class Builder(llvm.Wrapper): context = api.llvm.getGlobalContext() ptr = api.llvm.IRBuilder.new(context) ptr.SetInsertPoint(basic_block._ptr) - return BasicBlock(ptr) + return Builder(ptr) def position_at_beginning(self, bblk): """Position the builder at the beginning of the given block. @@ -1970,20 +1970,20 @@ def load_library_permanently(filename): path of the .so file) using LLVM. Symbols from these are available from the execution engine thereafter.""" with contextlib.closing(StringIO()) as errmsg: - failed = _api.llvm.sys.LoadLibraryPermanently(filename, errmsg) + failed = api.llvm.sys.LoadLibraryPermanently(filename, errmsg) if failed: raise llvm.LLVMException(errmsg.getvalue()) def inline_function(call): - info = _api.llvm.InlineFunctionInfo() - return _api.llvm.InlineFunction(call._ptr, info) + info = api.llvm.InlineFunctionInfo() + return api.llvm.InlineFunction(call._ptr, info) def parse_environment_options(progname, envname): - _api.llvm.cl.ParseEnvironmentOptions(progname, envname) + api.llvm.cl.ParseEnvironmentOptions(progname, envname) -if _api.llvm.InitializeNativeTarget(): +if api.llvm.InitializeNativeTarget(): raise llvm.LLVMException("No native target!?") -if _api.llvm.InitializeNativeTargetAsmPrinter(): +if api.llvm.InitializeNativeTargetAsmPrinter(): # should this be an optional feature? # should user trigger the initialization? raise llvm.LLVMException("No native asm printer!?") @@ -1996,17 +1996,17 @@ HAS_PTX = HAS_NVPTX = False if True: # use PTX? try: - _api.LLVMInitializePTXTarget() - _api.LLVMInitializePTXTargetInfo() - _api.LLVMInitializePTXTargetMC() - _api.LLVMInitializePTXAsmPrinter() + api.LLVMInitializePTXTarget() + api.LLVMInitializePTXTargetInfo() + api.LLVMInitializePTXTargetMC() + api.LLVMInitializePTXAsmPrinter() HAS_PTX = True except AttributeError: try: - _api.LLVMInitializeNVPTXTarget() - _api.LLVMInitializeNVPTXTargetInfo() - _api.LLVMInitializeNVPTXTargetMC() - _api.LLVMInitializeNVPTXAsmPrinter() + api.LLVMInitializeNVPTXTarget() + api.LLVMInitializeNVPTXTargetInfo() + api.LLVMInitializeNVPTXTargetMC() + api.LLVMInitializeNVPTXAsmPrinter() HAS_NVPTX = True except AttributeError: pass From 3189be4d58a24d6a16bb02d38a89472806a89eaa Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 11 Feb 2013 09:59:15 -0600 Subject: [PATCH 66/85] Rename newbinding directory to llvmpy. --- {newbinding => llvmpy}/Makefile | 0 {newbinding => llvmpy}/README | 0 llvmpy/__init__.py | 0 {newbinding => llvmpy}/capsule.cpp | 0 {newbinding => llvmpy}/capsule.py | 0 {newbinding => llvmpy}/extra.py | 4 ++-- {newbinding => llvmpy}/gen/binding.py | 2 +- {newbinding => llvmpy}/gen/codegen.py | 0 {newbinding => llvmpy}/gen/gen.py | 0 .../include/llvm_binding/auto_pyobject.h | 0 .../include/llvm_binding/binding.h | 0 .../include/llvm_binding/capsule_context.h | 0 .../include/llvm_binding/conversion.h | 0 {newbinding => llvmpy}/include/llvm_binding/extra.h | 1 + {newbinding => llvmpy}/setup.py | 0 {newbinding => llvmpy}/src/ADT/SmallVector.py | 0 {newbinding => llvmpy}/src/ADT/StringRef.py | 0 {newbinding => llvmpy}/src/ADT/Triple.py | 0 {newbinding => llvmpy}/src/ADT/__init__.py | 0 {newbinding => llvmpy}/src/Analysis/Verifier.py | 0 {newbinding => llvmpy}/src/Analysis/__init__.py | 0 {newbinding => llvmpy}/src/Argument.py | 0 .../src/Assembly/AssemblyAnnotationWriter.py | 0 {newbinding => llvmpy}/src/Assembly/Parser.py | 0 {newbinding => llvmpy}/src/Assembly/__init__.py | 0 {newbinding => llvmpy}/src/Attributes.py | 0 {newbinding => llvmpy}/src/BasicBlock.py | 0 {newbinding => llvmpy}/src/Bitcode/ReaderWriter.py | 0 {newbinding => llvmpy}/src/Bitcode/__init__.py | 0 {newbinding => llvmpy}/src/CallingConv.py | 0 .../src/CodeGen/MachineCodeInfo.py | 0 {newbinding => llvmpy}/src/CodeGen/__init__.py | 0 {newbinding => llvmpy}/src/Constant.py | 6 +++--- {newbinding => llvmpy}/src/DataLayout.py | 2 +- {newbinding => llvmpy}/src/DerivedTypes.py | 2 +- {newbinding => llvmpy}/src/EngineBuilder.py | 0 .../src/ExecutionEngine/ExecutionEngine.py | 2 +- .../src/ExecutionEngine/__init__.py | 0 {newbinding => llvmpy}/src/Function.py | 0 {newbinding => llvmpy}/src/GenericValue.py | 0 {newbinding => llvmpy}/src/GlobalValue.py | 0 {newbinding => llvmpy}/src/GlobalVariable.py | 0 {newbinding => llvmpy}/src/IRBuilder.py | 12 ++++++------ {newbinding => llvmpy}/src/InlineAsm.py | 0 {newbinding => llvmpy}/src/Instruction.py | 0 {newbinding => llvmpy}/src/Intrinsics.py | 0 {newbinding => llvmpy}/src/JITMemoryManager.py | 0 {newbinding => llvmpy}/src/LLVMContext.py | 0 {newbinding => llvmpy}/src/Linker.py | 0 {newbinding => llvmpy}/src/Metadata.py | 2 +- {newbinding => llvmpy}/src/Module.py | 2 +- {newbinding => llvmpy}/src/Pass.py | 0 {newbinding => llvmpy}/src/PassManager.py | 0 {newbinding => llvmpy}/src/Support/CodeGen.py | 0 {newbinding => llvmpy}/src/Support/CommandLine.py | 0 {newbinding => llvmpy}/src/Support/DynamicLibrary.py | 0 .../src/Support/FormattedStream.py | 0 {newbinding => llvmpy}/src/Support/SourceMgr.py | 0 {newbinding => llvmpy}/src/Support/Target.py | 0 {newbinding => llvmpy}/src/Support/TargetSelect.py | 0 {newbinding => llvmpy}/src/Support/__init__.py | 0 {newbinding => llvmpy}/src/Support/raw_ostream.py | 0 .../src/Target/TargetLibraryInfo.py | 0 {newbinding => llvmpy}/src/Target/TargetMachine.py | 0 {newbinding => llvmpy}/src/Target/__init__.py | 0 {newbinding => llvmpy}/src/TargetTransformInfo.py | 0 {newbinding => llvmpy}/src/Transforms/IPO.py | 0 .../src/Transforms/PassManagerBuilder.py | 0 .../src/Transforms/Utils/Cloning.py | 0 .../src/Transforms/Utils/__init__.py | 0 {newbinding => llvmpy}/src/Transforms/__init__.py | 0 {newbinding => llvmpy}/src/Type.py | 2 +- {newbinding => llvmpy}/src/User.py | 0 {newbinding => llvmpy}/src/Value.py | 2 +- {newbinding => llvmpy}/src/__init__.py | 0 {newbinding => llvmpy}/src/namespace.py | 0 {newbinding => llvmpy}/test_binding.py | 11 +++++++---- 77 files changed, 27 insertions(+), 23 deletions(-) rename {newbinding => llvmpy}/Makefile (100%) rename {newbinding => llvmpy}/README (100%) create mode 100644 llvmpy/__init__.py rename {newbinding => llvmpy}/capsule.cpp (100%) rename {newbinding => llvmpy}/capsule.py (100%) rename {newbinding => llvmpy}/extra.py (89%) rename {newbinding => llvmpy}/gen/binding.py (99%) rename {newbinding => llvmpy}/gen/codegen.py (100%) rename {newbinding => llvmpy}/gen/gen.py (100%) rename {newbinding => llvmpy}/include/llvm_binding/auto_pyobject.h (100%) rename {newbinding => llvmpy}/include/llvm_binding/binding.h (100%) rename {newbinding => llvmpy}/include/llvm_binding/capsule_context.h (100%) rename {newbinding => llvmpy}/include/llvm_binding/conversion.h (100%) rename {newbinding => llvmpy}/include/llvm_binding/extra.h (99%) rename {newbinding => llvmpy}/setup.py (100%) rename {newbinding => llvmpy}/src/ADT/SmallVector.py (100%) rename {newbinding => llvmpy}/src/ADT/StringRef.py (100%) rename {newbinding => llvmpy}/src/ADT/Triple.py (100%) rename {newbinding => llvmpy}/src/ADT/__init__.py (100%) rename {newbinding => llvmpy}/src/Analysis/Verifier.py (100%) rename {newbinding => llvmpy}/src/Analysis/__init__.py (100%) rename {newbinding => llvmpy}/src/Argument.py (100%) rename {newbinding => llvmpy}/src/Assembly/AssemblyAnnotationWriter.py (100%) rename {newbinding => llvmpy}/src/Assembly/Parser.py (100%) rename {newbinding => llvmpy}/src/Assembly/__init__.py (100%) rename {newbinding => llvmpy}/src/Attributes.py (100%) rename {newbinding => llvmpy}/src/BasicBlock.py (100%) rename {newbinding => llvmpy}/src/Bitcode/ReaderWriter.py (100%) rename {newbinding => llvmpy}/src/Bitcode/__init__.py (100%) rename {newbinding => llvmpy}/src/CallingConv.py (100%) rename {newbinding => llvmpy}/src/CodeGen/MachineCodeInfo.py (100%) rename {newbinding => llvmpy}/src/CodeGen/__init__.py (100%) rename {newbinding => llvmpy}/src/Constant.py (98%) rename {newbinding => llvmpy}/src/DataLayout.py (99%) rename {newbinding => llvmpy}/src/DerivedTypes.py (96%) rename {newbinding => llvmpy}/src/EngineBuilder.py (100%) rename {newbinding => llvmpy}/src/ExecutionEngine/ExecutionEngine.py (99%) rename {newbinding => llvmpy}/src/ExecutionEngine/__init__.py (100%) rename {newbinding => llvmpy}/src/Function.py (100%) rename {newbinding => llvmpy}/src/GenericValue.py (100%) rename {newbinding => llvmpy}/src/GlobalValue.py (100%) rename {newbinding => llvmpy}/src/GlobalVariable.py (100%) rename {newbinding => llvmpy}/src/IRBuilder.py (98%) rename {newbinding => llvmpy}/src/InlineAsm.py (100%) rename {newbinding => llvmpy}/src/Instruction.py (100%) rename {newbinding => llvmpy}/src/Intrinsics.py (100%) rename {newbinding => llvmpy}/src/JITMemoryManager.py (100%) rename {newbinding => llvmpy}/src/LLVMContext.py (100%) rename {newbinding => llvmpy}/src/Linker.py (100%) rename {newbinding => llvmpy}/src/Metadata.py (98%) rename {newbinding => llvmpy}/src/Module.py (98%) rename {newbinding => llvmpy}/src/Pass.py (100%) rename {newbinding => llvmpy}/src/PassManager.py (100%) rename {newbinding => llvmpy}/src/Support/CodeGen.py (100%) rename {newbinding => llvmpy}/src/Support/CommandLine.py (100%) rename {newbinding => llvmpy}/src/Support/DynamicLibrary.py (100%) rename {newbinding => llvmpy}/src/Support/FormattedStream.py (100%) rename {newbinding => llvmpy}/src/Support/SourceMgr.py (100%) rename {newbinding => llvmpy}/src/Support/Target.py (100%) rename {newbinding => llvmpy}/src/Support/TargetSelect.py (100%) rename {newbinding => llvmpy}/src/Support/__init__.py (100%) rename {newbinding => llvmpy}/src/Support/raw_ostream.py (100%) rename {newbinding => llvmpy}/src/Target/TargetLibraryInfo.py (100%) rename {newbinding => llvmpy}/src/Target/TargetMachine.py (100%) rename {newbinding => llvmpy}/src/Target/__init__.py (100%) rename {newbinding => llvmpy}/src/TargetTransformInfo.py (100%) rename {newbinding => llvmpy}/src/Transforms/IPO.py (100%) rename {newbinding => llvmpy}/src/Transforms/PassManagerBuilder.py (100%) rename {newbinding => llvmpy}/src/Transforms/Utils/Cloning.py (100%) rename {newbinding => llvmpy}/src/Transforms/Utils/__init__.py (100%) rename {newbinding => llvmpy}/src/Transforms/__init__.py (100%) rename {newbinding => llvmpy}/src/Type.py (99%) rename {newbinding => llvmpy}/src/User.py (100%) rename {newbinding => llvmpy}/src/Value.py (98%) rename {newbinding => llvmpy}/src/__init__.py (100%) rename {newbinding => llvmpy}/src/namespace.py (100%) rename {newbinding => llvmpy}/test_binding.py (98%) diff --git a/newbinding/Makefile b/llvmpy/Makefile similarity index 100% rename from newbinding/Makefile rename to llvmpy/Makefile diff --git a/newbinding/README b/llvmpy/README similarity index 100% rename from newbinding/README rename to llvmpy/README diff --git a/llvmpy/__init__.py b/llvmpy/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/newbinding/capsule.cpp b/llvmpy/capsule.cpp similarity index 100% rename from newbinding/capsule.cpp rename to llvmpy/capsule.cpp diff --git a/newbinding/capsule.py b/llvmpy/capsule.py similarity index 100% rename from newbinding/capsule.py rename to llvmpy/capsule.py diff --git a/newbinding/extra.py b/llvmpy/extra.py similarity index 89% rename from newbinding/extra.py rename to llvmpy/extra.py index d65f84c..a2e744f 100644 --- a/newbinding/extra.py +++ b/llvmpy/extra.py @@ -2,8 +2,8 @@ Wrapped the extra functions in _api.so ''' -import capsule -import _api +from llvmpy import capsule +from llvmpy import _api # # Re-export the native API from the _api.extra and wrap the functions # diff --git a/newbinding/gen/binding.py b/llvmpy/gen/binding.py similarity index 99% rename from newbinding/gen/binding.py rename to llvmpy/gen/binding.py index cfe4394..6d73cd3 100644 --- a/newbinding/gen/binding.py +++ b/llvmpy/gen/binding.py @@ -135,7 +135,7 @@ class SubModule(object): filepath = os.path.join(rootdir, '%s.py' % name) with open(filepath, 'w') as pyfile: println = cg.wrap_println_from_file(pyfile) - println('import _api, capsule') + println('from llvmpy import _api, capsule') for ns in self.namespaces: println('from . import %s' % ns.localname) println() diff --git a/newbinding/gen/codegen.py b/llvmpy/gen/codegen.py similarity index 100% rename from newbinding/gen/codegen.py rename to llvmpy/gen/codegen.py diff --git a/newbinding/gen/gen.py b/llvmpy/gen/gen.py similarity index 100% rename from newbinding/gen/gen.py rename to llvmpy/gen/gen.py diff --git a/newbinding/include/llvm_binding/auto_pyobject.h b/llvmpy/include/llvm_binding/auto_pyobject.h similarity index 100% rename from newbinding/include/llvm_binding/auto_pyobject.h rename to llvmpy/include/llvm_binding/auto_pyobject.h diff --git a/newbinding/include/llvm_binding/binding.h b/llvmpy/include/llvm_binding/binding.h similarity index 100% rename from newbinding/include/llvm_binding/binding.h rename to llvmpy/include/llvm_binding/binding.h diff --git a/newbinding/include/llvm_binding/capsule_context.h b/llvmpy/include/llvm_binding/capsule_context.h similarity index 100% rename from newbinding/include/llvm_binding/capsule_context.h rename to llvmpy/include/llvm_binding/capsule_context.h diff --git a/newbinding/include/llvm_binding/conversion.h b/llvmpy/include/llvm_binding/conversion.h similarity index 100% rename from newbinding/include/llvm_binding/conversion.h rename to llvmpy/include/llvm_binding/conversion.h diff --git a/newbinding/include/llvm_binding/extra.h b/llvmpy/include/llvm_binding/extra.h similarity index 99% rename from newbinding/include/llvm_binding/extra.h rename to llvmpy/include/llvm_binding/extra.h index d045d5c..438f52c 100644 --- a/newbinding/include/llvm_binding/extra.h +++ b/llvmpy/include/llvm_binding/extra.h @@ -358,6 +358,7 @@ PyObject* ExecutionEngine_RunFunction(llvm::ExecutionEngine* EE, return NULL; } std::vector vec_args; + Py_ssize_t nargs = PyTuple_Size(Args); vec_args.reserve(nargs); for (Py_ssize_t i = 0; i < nargs; ++i) { diff --git a/newbinding/setup.py b/llvmpy/setup.py similarity index 100% rename from newbinding/setup.py rename to llvmpy/setup.py diff --git a/newbinding/src/ADT/SmallVector.py b/llvmpy/src/ADT/SmallVector.py similarity index 100% rename from newbinding/src/ADT/SmallVector.py rename to llvmpy/src/ADT/SmallVector.py diff --git a/newbinding/src/ADT/StringRef.py b/llvmpy/src/ADT/StringRef.py similarity index 100% rename from newbinding/src/ADT/StringRef.py rename to llvmpy/src/ADT/StringRef.py diff --git a/newbinding/src/ADT/Triple.py b/llvmpy/src/ADT/Triple.py similarity index 100% rename from newbinding/src/ADT/Triple.py rename to llvmpy/src/ADT/Triple.py diff --git a/newbinding/src/ADT/__init__.py b/llvmpy/src/ADT/__init__.py similarity index 100% rename from newbinding/src/ADT/__init__.py rename to llvmpy/src/ADT/__init__.py diff --git a/newbinding/src/Analysis/Verifier.py b/llvmpy/src/Analysis/Verifier.py similarity index 100% rename from newbinding/src/Analysis/Verifier.py rename to llvmpy/src/Analysis/Verifier.py diff --git a/newbinding/src/Analysis/__init__.py b/llvmpy/src/Analysis/__init__.py similarity index 100% rename from newbinding/src/Analysis/__init__.py rename to llvmpy/src/Analysis/__init__.py diff --git a/newbinding/src/Argument.py b/llvmpy/src/Argument.py similarity index 100% rename from newbinding/src/Argument.py rename to llvmpy/src/Argument.py diff --git a/newbinding/src/Assembly/AssemblyAnnotationWriter.py b/llvmpy/src/Assembly/AssemblyAnnotationWriter.py similarity index 100% rename from newbinding/src/Assembly/AssemblyAnnotationWriter.py rename to llvmpy/src/Assembly/AssemblyAnnotationWriter.py diff --git a/newbinding/src/Assembly/Parser.py b/llvmpy/src/Assembly/Parser.py similarity index 100% rename from newbinding/src/Assembly/Parser.py rename to llvmpy/src/Assembly/Parser.py diff --git a/newbinding/src/Assembly/__init__.py b/llvmpy/src/Assembly/__init__.py similarity index 100% rename from newbinding/src/Assembly/__init__.py rename to llvmpy/src/Assembly/__init__.py diff --git a/newbinding/src/Attributes.py b/llvmpy/src/Attributes.py similarity index 100% rename from newbinding/src/Attributes.py rename to llvmpy/src/Attributes.py diff --git a/newbinding/src/BasicBlock.py b/llvmpy/src/BasicBlock.py similarity index 100% rename from newbinding/src/BasicBlock.py rename to llvmpy/src/BasicBlock.py diff --git a/newbinding/src/Bitcode/ReaderWriter.py b/llvmpy/src/Bitcode/ReaderWriter.py similarity index 100% rename from newbinding/src/Bitcode/ReaderWriter.py rename to llvmpy/src/Bitcode/ReaderWriter.py diff --git a/newbinding/src/Bitcode/__init__.py b/llvmpy/src/Bitcode/__init__.py similarity index 100% rename from newbinding/src/Bitcode/__init__.py rename to llvmpy/src/Bitcode/__init__.py diff --git a/newbinding/src/CallingConv.py b/llvmpy/src/CallingConv.py similarity index 100% rename from newbinding/src/CallingConv.py rename to llvmpy/src/CallingConv.py diff --git a/newbinding/src/CodeGen/MachineCodeInfo.py b/llvmpy/src/CodeGen/MachineCodeInfo.py similarity index 100% rename from newbinding/src/CodeGen/MachineCodeInfo.py rename to llvmpy/src/CodeGen/MachineCodeInfo.py diff --git a/newbinding/src/CodeGen/__init__.py b/llvmpy/src/CodeGen/__init__.py similarity index 100% rename from newbinding/src/CodeGen/__init__.py rename to llvmpy/src/CodeGen/__init__.py diff --git a/newbinding/src/Constant.py b/llvmpy/src/Constant.py similarity index 98% rename from newbinding/src/Constant.py rename to llvmpy/src/Constant.py index 42541c4..5407d71 100644 --- a/newbinding/src/Constant.py +++ b/llvmpy/src/Constant.py @@ -227,7 +227,7 @@ class ConstantExpr: @CustomPythonStaticMethod def getGetElementPtr(*args): - import extra + from llvmpy import extra args = list(args) valuelist = args[1] args[1] = extra.make_small_vector_from_values(*valuelist) @@ -242,7 +242,7 @@ class ConstantExpr: @CustomPythonStaticMethod def getExtractValue(*args): - import extra + from llvmpy import extra args = list(args) valuelist = args[1] args[1] = extra.make_small_vector_from_unsigned(*valuelist) @@ -254,7 +254,7 @@ class ConstantExpr: @CustomPythonStaticMethod def getInsertValue(*args): - import extra + from llvmpy import extra args = list(args) valuelist = args[2] args[1] = extra.make_small_vector_from_unsigned(*valuelist) diff --git a/newbinding/src/DataLayout.py b/llvmpy/src/DataLayout.py similarity index 99% rename from newbinding/src/DataLayout.py rename to llvmpy/src/DataLayout.py index 704c4b1..d704723 100644 --- a/newbinding/src/DataLayout.py +++ b/llvmpy/src/DataLayout.py @@ -81,7 +81,7 @@ class DataLayout: @CustomPythonMethod def getIndexedOffset(self, *args): - import extra + from llvmpy import extra args = list(args) args[1] = extra.make_small_vector_from_values(args[1]) return self.getIndexedOffset(*args) diff --git a/newbinding/src/DerivedTypes.py b/llvmpy/src/DerivedTypes.py similarity index 96% rename from newbinding/src/DerivedTypes.py rename to llvmpy/src/DerivedTypes.py index e71f1a8..a34c2f1 100644 --- a/newbinding/src/DerivedTypes.py +++ b/llvmpy/src/DerivedTypes.py @@ -17,7 +17,7 @@ class FunctionType: @CustomPythonStaticMethod def get(*args): - import extra + from llvmpy import extra if len(args) == 3: typelist = args[1] sv = extra.make_small_vector_from_types(*typelist) diff --git a/newbinding/src/EngineBuilder.py b/llvmpy/src/EngineBuilder.py similarity index 100% rename from newbinding/src/EngineBuilder.py rename to llvmpy/src/EngineBuilder.py diff --git a/newbinding/src/ExecutionEngine/ExecutionEngine.py b/llvmpy/src/ExecutionEngine/ExecutionEngine.py similarity index 99% rename from newbinding/src/ExecutionEngine/ExecutionEngine.py rename to llvmpy/src/ExecutionEngine/ExecutionEngine.py index f4bdb14..1188de3 100644 --- a/newbinding/src/ExecutionEngine/ExecutionEngine.py +++ b/llvmpy/src/ExecutionEngine/ExecutionEngine.py @@ -88,7 +88,7 @@ class ExecutionEngine: @CustomPythonMethod def runFunction(self, fn, args): - import capsule + from llvmpy import capsule unwrapped = map(capsule.unwrap, args) return self._runFunction(fn, tuple(unwrapped)) diff --git a/newbinding/src/ExecutionEngine/__init__.py b/llvmpy/src/ExecutionEngine/__init__.py similarity index 100% rename from newbinding/src/ExecutionEngine/__init__.py rename to llvmpy/src/ExecutionEngine/__init__.py diff --git a/newbinding/src/Function.py b/llvmpy/src/Function.py similarity index 100% rename from newbinding/src/Function.py rename to llvmpy/src/Function.py diff --git a/newbinding/src/GenericValue.py b/llvmpy/src/GenericValue.py similarity index 100% rename from newbinding/src/GenericValue.py rename to llvmpy/src/GenericValue.py diff --git a/newbinding/src/GlobalValue.py b/llvmpy/src/GlobalValue.py similarity index 100% rename from newbinding/src/GlobalValue.py rename to llvmpy/src/GlobalValue.py diff --git a/newbinding/src/GlobalVariable.py b/llvmpy/src/GlobalVariable.py similarity index 100% rename from newbinding/src/GlobalVariable.py rename to llvmpy/src/GlobalVariable.py diff --git a/newbinding/src/IRBuilder.py b/llvmpy/src/IRBuilder.py similarity index 98% rename from newbinding/src/IRBuilder.py rename to llvmpy/src/IRBuilder.py index 2965367..095122f 100644 --- a/newbinding/src/IRBuilder.py +++ b/llvmpy/src/IRBuilder.py @@ -68,7 +68,7 @@ class IRBuilder: @CustomPythonMethod def CreateInvoke(self, *args): - import extra + from llvmpy import extra args = list(args) valuelist = args[3] args[3] = extra.make_small_vector_from_values(*valuelist) @@ -181,7 +181,7 @@ class IRBuilder: @CustomPythonMethod def CreateGEP(self, *args): - import extra + from llvmpy import extra args = list(args) valuelist = args[1] args[1] = extra.make_small_vector_from_values(*valuelist) @@ -194,7 +194,7 @@ class IRBuilder: @CustomPythonMethod def CreateInBoundsGEP(self, *args): - import extra + from llvmpy import extra args = list(args) valuelist = args[1] args[1] = extra.make_small_vector_from_values(*valuelist) @@ -241,7 +241,7 @@ class IRBuilder: @CustomPythonMethod def CreateCall(self, *args): - import extra + from llvmpy import extra args = list(args) valuelist = args[1] args[1] = extra.make_small_vector_from_values(*valuelist) @@ -282,7 +282,7 @@ class IRBuilder: @CustomPythonMethod def CreateExtractValue(self, args): - import extra + from llvmpy import extra args = list(args) valuelist = args[1] args[1] = extra.make_small_vector_from_unsigned(*valuelist) @@ -295,7 +295,7 @@ class IRBuilder: @CustomPythonMethod def CreateInsertValue(self, args): - import extra + from llvmpy import extra args = list(args) valuelist = args[2] args[1] = extra.make_small_vector_from_unsigned(*valuelist) diff --git a/newbinding/src/InlineAsm.py b/llvmpy/src/InlineAsm.py similarity index 100% rename from newbinding/src/InlineAsm.py rename to llvmpy/src/InlineAsm.py diff --git a/newbinding/src/Instruction.py b/llvmpy/src/Instruction.py similarity index 100% rename from newbinding/src/Instruction.py rename to llvmpy/src/Instruction.py diff --git a/newbinding/src/Intrinsics.py b/llvmpy/src/Intrinsics.py similarity index 100% rename from newbinding/src/Intrinsics.py rename to llvmpy/src/Intrinsics.py diff --git a/newbinding/src/JITMemoryManager.py b/llvmpy/src/JITMemoryManager.py similarity index 100% rename from newbinding/src/JITMemoryManager.py rename to llvmpy/src/JITMemoryManager.py diff --git a/newbinding/src/LLVMContext.py b/llvmpy/src/LLVMContext.py similarity index 100% rename from newbinding/src/LLVMContext.py rename to llvmpy/src/LLVMContext.py diff --git a/newbinding/src/Linker.py b/llvmpy/src/Linker.py similarity index 100% rename from newbinding/src/Linker.py rename to llvmpy/src/Linker.py diff --git a/newbinding/src/Metadata.py b/llvmpy/src/Metadata.py similarity index 98% rename from newbinding/src/Metadata.py rename to llvmpy/src/Metadata.py index 338cbbd..94088ca 100644 --- a/newbinding/src/Metadata.py +++ b/llvmpy/src/Metadata.py @@ -46,7 +46,7 @@ class NamedMDNode: @CustomPythonMethod def __str__(self): - import extra + from llvmpy import extra os = extra.make_raw_ostream_for_printing() self.print_(os, None) return os.str() \ No newline at end of file diff --git a/newbinding/src/Module.py b/llvmpy/src/Module.py similarity index 98% rename from newbinding/src/Module.py rename to llvmpy/src/Module.py index 7718cd6..d68be36 100644 --- a/newbinding/src/Module.py +++ b/llvmpy/src/Module.py @@ -77,7 +77,7 @@ class Module: @CustomPythonMethod def __str__(self): - import extra + from llvmpy import extra os = extra.make_raw_ostream_for_printing() self.print_(os, None) return os.str() diff --git a/newbinding/src/Pass.py b/llvmpy/src/Pass.py similarity index 100% rename from newbinding/src/Pass.py rename to llvmpy/src/Pass.py diff --git a/newbinding/src/PassManager.py b/llvmpy/src/PassManager.py similarity index 100% rename from newbinding/src/PassManager.py rename to llvmpy/src/PassManager.py diff --git a/newbinding/src/Support/CodeGen.py b/llvmpy/src/Support/CodeGen.py similarity index 100% rename from newbinding/src/Support/CodeGen.py rename to llvmpy/src/Support/CodeGen.py diff --git a/newbinding/src/Support/CommandLine.py b/llvmpy/src/Support/CommandLine.py similarity index 100% rename from newbinding/src/Support/CommandLine.py rename to llvmpy/src/Support/CommandLine.py diff --git a/newbinding/src/Support/DynamicLibrary.py b/llvmpy/src/Support/DynamicLibrary.py similarity index 100% rename from newbinding/src/Support/DynamicLibrary.py rename to llvmpy/src/Support/DynamicLibrary.py diff --git a/newbinding/src/Support/FormattedStream.py b/llvmpy/src/Support/FormattedStream.py similarity index 100% rename from newbinding/src/Support/FormattedStream.py rename to llvmpy/src/Support/FormattedStream.py diff --git a/newbinding/src/Support/SourceMgr.py b/llvmpy/src/Support/SourceMgr.py similarity index 100% rename from newbinding/src/Support/SourceMgr.py rename to llvmpy/src/Support/SourceMgr.py diff --git a/newbinding/src/Support/Target.py b/llvmpy/src/Support/Target.py similarity index 100% rename from newbinding/src/Support/Target.py rename to llvmpy/src/Support/Target.py diff --git a/newbinding/src/Support/TargetSelect.py b/llvmpy/src/Support/TargetSelect.py similarity index 100% rename from newbinding/src/Support/TargetSelect.py rename to llvmpy/src/Support/TargetSelect.py diff --git a/newbinding/src/Support/__init__.py b/llvmpy/src/Support/__init__.py similarity index 100% rename from newbinding/src/Support/__init__.py rename to llvmpy/src/Support/__init__.py diff --git a/newbinding/src/Support/raw_ostream.py b/llvmpy/src/Support/raw_ostream.py similarity index 100% rename from newbinding/src/Support/raw_ostream.py rename to llvmpy/src/Support/raw_ostream.py diff --git a/newbinding/src/Target/TargetLibraryInfo.py b/llvmpy/src/Target/TargetLibraryInfo.py similarity index 100% rename from newbinding/src/Target/TargetLibraryInfo.py rename to llvmpy/src/Target/TargetLibraryInfo.py diff --git a/newbinding/src/Target/TargetMachine.py b/llvmpy/src/Target/TargetMachine.py similarity index 100% rename from newbinding/src/Target/TargetMachine.py rename to llvmpy/src/Target/TargetMachine.py diff --git a/newbinding/src/Target/__init__.py b/llvmpy/src/Target/__init__.py similarity index 100% rename from newbinding/src/Target/__init__.py rename to llvmpy/src/Target/__init__.py diff --git a/newbinding/src/TargetTransformInfo.py b/llvmpy/src/TargetTransformInfo.py similarity index 100% rename from newbinding/src/TargetTransformInfo.py rename to llvmpy/src/TargetTransformInfo.py diff --git a/newbinding/src/Transforms/IPO.py b/llvmpy/src/Transforms/IPO.py similarity index 100% rename from newbinding/src/Transforms/IPO.py rename to llvmpy/src/Transforms/IPO.py diff --git a/newbinding/src/Transforms/PassManagerBuilder.py b/llvmpy/src/Transforms/PassManagerBuilder.py similarity index 100% rename from newbinding/src/Transforms/PassManagerBuilder.py rename to llvmpy/src/Transforms/PassManagerBuilder.py diff --git a/newbinding/src/Transforms/Utils/Cloning.py b/llvmpy/src/Transforms/Utils/Cloning.py similarity index 100% rename from newbinding/src/Transforms/Utils/Cloning.py rename to llvmpy/src/Transforms/Utils/Cloning.py diff --git a/newbinding/src/Transforms/Utils/__init__.py b/llvmpy/src/Transforms/Utils/__init__.py similarity index 100% rename from newbinding/src/Transforms/Utils/__init__.py rename to llvmpy/src/Transforms/Utils/__init__.py diff --git a/newbinding/src/Transforms/__init__.py b/llvmpy/src/Transforms/__init__.py similarity index 100% rename from newbinding/src/Transforms/__init__.py rename to llvmpy/src/Transforms/__init__.py diff --git a/newbinding/src/Type.py b/llvmpy/src/Type.py similarity index 99% rename from newbinding/src/Type.py rename to llvmpy/src/Type.py index 4078a9d..ec0bf88 100644 --- a/newbinding/src/Type.py +++ b/llvmpy/src/Type.py @@ -125,7 +125,7 @@ class Type: @CustomPythonMethod def __str__(self): - import extra + from llvmpy import extra os = extra.make_raw_ostream_for_printing() self.print_(os) return os.str() diff --git a/newbinding/src/User.py b/llvmpy/src/User.py similarity index 100% rename from newbinding/src/User.py rename to llvmpy/src/User.py diff --git a/newbinding/src/Value.py b/llvmpy/src/Value.py similarity index 98% rename from newbinding/src/Value.py rename to llvmpy/src/Value.py index 27bcda0..88f221c 100644 --- a/newbinding/src/Value.py +++ b/llvmpy/src/Value.py @@ -56,7 +56,7 @@ class Value: @CustomPythonMethod def __str__(self): - import extra + from llvmpy import extra os = extra.make_raw_ostream_for_printing() self.print_(os, None) return os.str() diff --git a/newbinding/src/__init__.py b/llvmpy/src/__init__.py similarity index 100% rename from newbinding/src/__init__.py rename to llvmpy/src/__init__.py diff --git a/newbinding/src/namespace.py b/llvmpy/src/namespace.py similarity index 100% rename from newbinding/src/namespace.py rename to llvmpy/src/namespace.py diff --git a/newbinding/test_binding.py b/llvmpy/test_binding.py similarity index 98% rename from newbinding/test_binding.py rename to llvmpy/test_binding.py index 7fa5e2c..e1e12e5 100644 --- a/newbinding/test_binding.py +++ b/llvmpy/test_binding.py @@ -1,8 +1,11 @@ -from api import llvm -import extra -import _capsule from StringIO import StringIO -llvm.capsule.set_debug(True) + +from llvmpy.api import llvm +from llvmpy import extra +from llvmpy import _capsule +import llvmpy.capsule +llvmpy.capsule.set_debug(True) + def test_basic_jit_use(): llvm.InitializeNativeTarget() From 2d8c6f0a410469ee0276c120e63414f0b3eb3e7f Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 11 Feb 2013 18:13:38 -0600 Subject: [PATCH 67/85] Add PassRegistry, PassSupport, TargetRegistry, TargetOptions, and functions in Host.h And a few other fixes --- llvmpy/.gitignore | 4 + llvmpy/capsule.py | 7 ++ llvmpy/include/llvm_binding/auto_pyobject.h | 3 +- llvmpy/include/llvm_binding/extra.h | 97 +++++++++++++++++++ llvmpy/src/Analysis/Verifier.py | 2 +- llvmpy/src/DataLayout.py | 15 ++- llvmpy/src/ExecutionEngine/ExecutionEngine.py | 15 ++- llvmpy/src/GlobalVariable.py | 2 +- llvmpy/src/Instruction.py | 12 ++- llvmpy/src/Pass.py | 8 +- llvmpy/src/PassManager.py | 2 +- llvmpy/src/PassRegistry.py | 21 ++++ llvmpy/src/PassSupport.py | 24 +++++ llvmpy/src/Support/Host.py | 25 +++++ llvmpy/src/Support/Target.py | 27 ------ llvmpy/src/Support/TargetRegistry.py | 68 +++++++++++++ llvmpy/src/Target/TargetLibraryInfo.py | 9 +- llvmpy/src/Target/TargetMachine.py | 21 ++-- llvmpy/src/Target/TargetOptions.py | 12 +++ llvmpy/test_binding.py | 41 +++++++- 20 files changed, 352 insertions(+), 63 deletions(-) create mode 100644 llvmpy/.gitignore create mode 100644 llvmpy/src/PassRegistry.py create mode 100644 llvmpy/src/PassSupport.py create mode 100644 llvmpy/src/Support/Host.py delete mode 100644 llvmpy/src/Support/Target.py create mode 100644 llvmpy/src/Support/TargetRegistry.py create mode 100644 llvmpy/src/Target/TargetOptions.py diff --git a/llvmpy/.gitignore b/llvmpy/.gitignore new file mode 100644 index 0000000..ab608aa --- /dev/null +++ b/llvmpy/.gitignore @@ -0,0 +1,4 @@ +api.cpp +api/*.py +api/*/*.py + diff --git a/llvmpy/capsule.py b/llvmpy/capsule.py index d98a23d..7a7ceaf 100644 --- a/llvmpy/capsule.py +++ b/llvmpy/capsule.py @@ -102,6 +102,13 @@ def release_ownership(old): _addr2dtor[addr] = None +def obtain_ownership(cap): + cls = cap.get_class() + if cls._has_dtor(): + addr = cap.pointer + assert _addr2dtor[addr] is None + _addr2dtor[addr] = cls._delete_ + def has_ownership(cap): addr = Capsule.getPointer(cap) return _addr2dtor.get(addr) is not None diff --git a/llvmpy/include/llvm_binding/auto_pyobject.h b/llvmpy/include/llvm_binding/auto_pyobject.h index 451f2d9..368e64f 100644 --- a/llvmpy/include/llvm_binding/auto_pyobject.h +++ b/llvmpy/include/llvm_binding/auto_pyobject.h @@ -34,5 +34,4 @@ private: void operator = (const auto_pyobject&); }; -#endif AUTO_PYOBJECT_H_ - +#endif // AUTO_PYOBJECT_H_ diff --git a/llvmpy/include/llvm_binding/extra.h b/llvmpy/include/llvm_binding/extra.h index 438f52c..2bbad42 100644 --- a/llvmpy/include/llvm_binding/extra.h +++ b/llvmpy/include/llvm_binding/extra.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -16,6 +17,9 @@ #include #include #include +#include +#include + #include "auto_pyobject.h" @@ -774,3 +778,96 @@ PyObject* DynamicLibrary_LoadLibraryPermanently(const char * Filename, } } +class PassRegistryEnumerator : public llvm::PassRegistrationListener{ +public: + PyObject* List; +public: + PassRegistryEnumerator(PyObject* list) : List(list) { } + + inline virtual void passEnumerate(const llvm::PassInfo * pass_info){ + PyObject* passArg = PyString_FromString(pass_info->getPassArgument()); + PyObject* passName = PyString_FromString(pass_info->getPassName()); + PyList_Append(List, Py_BuildValue("(OO)", passArg, passName)); + } +}; + +static +PyObject* PassRegistry_enumerate(llvm::PassRegistry* PR) +{ + using namespace llvm; + PassRegistryEnumerator PRE(PyList_New(0)); + PR->enumerateWith(&PRE); + return PRE.List; +} + +static +PyObject* TargetRegistry_lookupTarget(const std::string &Triple, + PyObject* Error) +{ + using namespace llvm; + std::string error; + const Target* target = TargetRegistry::lookupTarget(Triple, error); + if (!target) { + PyFile_WriteString(error.c_str(), Error); + Py_RETURN_NONE; + } else { + return pycapsule_new(const_cast(target), "llvm::Target"); + } +} + + +static +PyObject* TargetRegistry_lookupTarget(const std::string &Arch, + llvm::Triple &Triple, + PyObject* Error) +{ + using namespace llvm; + std::string error; + const Target* target = TargetRegistry::lookupTarget(Arch, Triple, error); + if (!target) { + PyFile_WriteString(error.c_str(), Error); + Py_RETURN_NONE; + } else { + return pycapsule_new(const_cast(target), "llvm::Target"); + } +} + + +static +PyObject* TargetRegistry_getClosestTargetForJIT(PyObject* Error) +{ + using namespace llvm; + std::string error; + const Target* target = TargetRegistry::getClosestTargetForJIT(error); + if (!target) { + PyFile_WriteString(error.c_str(), Error); + Py_RETURN_NONE; + } else { + return pycapsule_new(const_cast(target), "llvm::Target"); + } + +} + +static +PyObject* llvm_sys_getHostCPUFeatures(PyObject* Features) +{ + using namespace llvm::sys; + using namespace llvm; + typedef StringMap::iterator iterator; + StringMap features; + bool ok = getHostCPUFeatures(features); + if (ok) { + for (iterator it = features.begin(); it != features.end(); ++it) { + const char *key = it->getKey().data(); + PyObject *val = it->getValue() ? Py_True : Py_False; + Py_INCREF(val); + if (-1 == PyDict_SetItemString(Features, key, val)) { + return NULL; + } + } + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } +} + diff --git a/llvmpy/src/Analysis/Verifier.py b/llvmpy/src/Analysis/Verifier.py index 5b47740..3afa075 100644 --- a/llvmpy/src/Analysis/Verifier.py +++ b/llvmpy/src/Analysis/Verifier.py @@ -1,7 +1,7 @@ from binding import * from ..namespace import llvm from ..Module import Module -from ..Function import Function +from ..Value import Function llvm.includes.add('llvm/Analysis/Verifier.h') diff --git a/llvmpy/src/DataLayout.py b/llvmpy/src/DataLayout.py index d704723..9582d53 100644 --- a/llvmpy/src/DataLayout.py +++ b/llvmpy/src/DataLayout.py @@ -1,15 +1,17 @@ from binding import * from namespace import llvm +from Pass import ImmutablePass + +DataLayout = llvm.Class(ImmutablePass) +StructLayout = llvm.Class() + from LLVMContext import LLVMContext from ADT.StringRef import StringRef from Module import Module from Type import Type, IntegerType, StructType from ADT.SmallVector import SmallVector_Value from GlobalVariable import GlobalVariable -from Pass import ImmutablePass -DataLayout = llvm.Class(ImmutablePass) -StructLayout = llvm.Class() @DataLayout class DataLayout: @@ -93,4 +95,9 @@ class DataLayout: @StructLayout class StructLayout: - pass + getSizeInBytes = Method(cast(Uint64, int)) + getSizeInBits = Method(cast(Uint64, int)) + getAlignment = Method(cast(Unsigned, int)) + getElementContainingOffset = Method(cast(Unsigned, int), cast(int, Uint64)) + getElementOffset = Method(cast(Uint64, int), cast(int, Unsigned)) + getElementOffsetInBits = Method(cast(Uint64, int), cast(int, Unsigned)) diff --git a/llvmpy/src/ExecutionEngine/ExecutionEngine.py b/llvmpy/src/ExecutionEngine/ExecutionEngine.py index 1188de3..0bd4714 100644 --- a/llvmpy/src/ExecutionEngine/ExecutionEngine.py +++ b/llvmpy/src/ExecutionEngine/ExecutionEngine.py @@ -34,16 +34,25 @@ class ExecutionEngine: Reloc.Model, CodeModel.Model).require_only(1) - addModule = Method(Void, ptr(Module)) + addModule = Method(Void, ownedptr(Module)) getDataLayout = Method(const(ownedptr(DataLayout))) - removeModule = Method(cast(Bool, bool), ptr(Module)) + _removeModule = Method(cast(Bool, bool), ptr(Module)) + _removeModule.realname = 'removeModule' + @CustomPythonMethod + def removeModule(self, module): + if self._removeModule(module): + capsule.obtain_ownership(module._ptr) + return True + return False FindFunctionNamed = Method(ptr(Function), cast(str, ConstCharPtr)) getPointerToNamedFunction = Method(cast(VoidPtr, int), cast(str, StdString), cast(bool, Bool)).require_only(1) - runStaticConstructorsDestructors = Method(Void, cast(Bool, bool)) + runStaticConstructorsDestructors = Method(Void, + cast(Bool, bool), # is dtor + ) runStaticConstructorsDestructors |= Method(Void, ptr(Module), cast(Bool, bool)) diff --git a/llvmpy/src/GlobalVariable.py b/llvmpy/src/GlobalVariable.py index 4ee91fb..2280e24 100644 --- a/llvmpy/src/GlobalVariable.py +++ b/llvmpy/src/GlobalVariable.py @@ -4,10 +4,10 @@ from namespace import llvm from GlobalValue import GlobalValue GlobalVariable = llvm.Class(GlobalValue) -from Constant import Constant from Module import Module from Type import Type from ADT.StringRef import StringRef +from Value import Constant @GlobalVariable class GlobalVariable: diff --git a/llvmpy/src/Instruction.py b/llvmpy/src/Instruction.py index ca64072..b3fa701 100644 --- a/llvmpy/src/Instruction.py +++ b/llvmpy/src/Instruction.py @@ -1,11 +1,6 @@ from binding import * from namespace import llvm from Value import Value, MDNode, User, BasicBlock, Function -from ADT.StringRef import StringRef -from CallingConv import CallingConv -from Attributes import Attributes -from Constant import ConstantInt -from Type import Type Instruction = llvm.Class(User) @@ -68,6 +63,13 @@ SynchronizationScope = llvm.Enum('SynchronizationScope', +from ADT.StringRef import StringRef +from CallingConv import CallingConv +from Attributes import Attributes +from Constant import ConstantInt +from Type import Type + + @Instruction class Instruction: diff --git a/llvmpy/src/Pass.py b/llvmpy/src/Pass.py index 39e894b..f36856c 100644 --- a/llvmpy/src/Pass.py +++ b/llvmpy/src/Pass.py @@ -1,14 +1,14 @@ from binding import * from namespace import llvm -from ADT.StringRef import StringRef -from Module import Module -from Function import Function Pass = llvm.Class() ModulePass = llvm.Class(Pass) FunctionPass = llvm.Class(Pass) ImmutablePass = llvm.Class(ModulePass) +from ADT.StringRef import StringRef +from Module import Module +from Value import Function @Pass class Pass: @@ -16,7 +16,7 @@ class Pass: delete = Destructor() getPassName = Method(cast(StringRef, str)) - + dump = Method() @ModulePass class ModulePass: diff --git a/llvmpy/src/PassManager.py b/llvmpy/src/PassManager.py index f969192..91a98f4 100644 --- a/llvmpy/src/PassManager.py +++ b/llvmpy/src/PassManager.py @@ -2,7 +2,7 @@ from binding import * from namespace import llvm from Pass import Pass from Module import Module -from Function import Function +from Value import Function PassManagerBase = llvm.Class() PassManager = llvm.Class(PassManagerBase) diff --git a/llvmpy/src/PassRegistry.py b/llvmpy/src/PassRegistry.py new file mode 100644 index 0000000..495de51 --- /dev/null +++ b/llvmpy/src/PassRegistry.py @@ -0,0 +1,21 @@ +from binding import * +from namespace import llvm +from src.ADT.StringRef import StringRef + +PassRegistry = llvm.Class() + +from src.PassSupport import PassInfo + +@PassRegistry +class PassRegistry: + _include_ = 'llvm/PassRegistry.h' + + delete = Destructor() + + getPassRegistry = StaticMethod(ownedptr(PassRegistry)) + + getPassInfo = Method(const(ptr(PassInfo)), cast(str, StringRef)) + + # This is a custom method that wraps enumerateWith + # Returns list of tuples of (pass-arg, pass-name) + enumerate = CustomMethod('PassRegistry_enumerate', PyObjectPtr) \ No newline at end of file diff --git a/llvmpy/src/PassSupport.py b/llvmpy/src/PassSupport.py new file mode 100644 index 0000000..8dba872 --- /dev/null +++ b/llvmpy/src/PassSupport.py @@ -0,0 +1,24 @@ +from binding import * +from namespace import llvm + +PassInfo = llvm.Class() + +from src.Pass import Pass +from src.PassRegistry import PassRegistry + +@PassInfo +class PassInfo: + _include_ = 'llvm/PassSupport.h' + + createPass = Method(ptr(Pass)) + +llvm.Function('initializeCore', Void, ref(PassRegistry)) +llvm.Function('initializeScalarOpts', Void, ref(PassRegistry)) +llvm.Function('initializeVectorization', Void, ref(PassRegistry)) +llvm.Function('initializeIPO', Void, ref(PassRegistry)) +llvm.Function('initializeAnalysis', Void, ref(PassRegistry)) +llvm.Function('initializeIPA', Void, ref(PassRegistry)) +llvm.Function('initializeTransformUtils', Void, ref(PassRegistry)) +llvm.Function('initializeInstCombine', Void, ref(PassRegistry)) +llvm.Function('initializeInstrumentation', Void, ref(PassRegistry)) +llvm.Function('initializeTarget', Void, ref(PassRegistry)) diff --git a/llvmpy/src/Support/Host.py b/llvmpy/src/Support/Host.py new file mode 100644 index 0000000..8163ebe --- /dev/null +++ b/llvmpy/src/Support/Host.py @@ -0,0 +1,25 @@ +from binding import * +from src.namespace import sys + +isLittleEndianHost = sys.Function('isLittleEndianHost', + cast(Bool, bool)) + +isBigEndianHost = sys.Function('isBigEndianHost', + cast(Bool, bool)) + +getDefaultTargetTriple = sys.Function('getDefaultTargetTriple', + cast(ConstStdString, str)) + +# llvm 3.3 +#getProcessTriple = sys.Function('getProcessTriple', +# cast(ConstStdString, str)) + +getHostCPUName = sys.Function('getHostCPUName', + cast(ConstStdString, str)) + +getHostCPUFeatures = sys.CustomFunction('getHostCPUFeatures', + 'llvm_sys_getHostCPUFeatures', + PyObjectPtr, # bool: success? + PyObjectPtr, # dict: store feature map + ) + diff --git a/llvmpy/src/Support/Target.py b/llvmpy/src/Support/Target.py deleted file mode 100644 index bdaeff5..0000000 --- a/llvmpy/src/Support/Target.py +++ /dev/null @@ -1,27 +0,0 @@ -from binding import * -from ..namespace import llvm -from ..ADT.StringRef import StringRef -Target = llvm.Class() - -@Target -class Target: - _include_ = 'llvm/Support/TargetRegistry.h' - - getNext = Method(const(ptr(Target))) - - getName = Method(cast(StringRef, str)) - getShortDescription = Method(cast(StringRef, str)) - - def _has(): - return Method(cast(Bool, bool)) - - hasJIT = _has() - hasTargetMachine = _has() - hasMCAsmBackend = _has() - hasMCAsmParser = _has() - hasAsmPrinter = _has() - hasMCDisassembler = _has() - hasMCInstPrinter = _has() - hasMCCodeEmitter = _has() - hasMCObjectStreamer = _has() - hasAsmStreamer = _has() diff --git a/llvmpy/src/Support/TargetRegistry.py b/llvmpy/src/Support/TargetRegistry.py new file mode 100644 index 0000000..640364b --- /dev/null +++ b/llvmpy/src/Support/TargetRegistry.py @@ -0,0 +1,68 @@ +from binding import * +from src.namespace import llvm + +llvm.includes.add('llvm/Support/TargetRegistry.h') + +Target = llvm.Class() +TargetRegistry = llvm.Class() + +from src.ADT.Triple import Triple +from src.ADT.StringRef import StringRef +from src.Target.TargetMachine import TargetMachine +from src.Target.TargetOptions import TargetOptions +from src.Support.CodeGen import Reloc, CodeModel, CodeGenOpt + +@Target +class Target: + getNext = Method(const(ptr(Target))) + + getName = Method(cast(StringRef, str)) + getShortDescription = Method(cast(StringRef, str)) + + def _has(): + return Method(cast(Bool, bool)) + + hasJIT = _has() + hasTargetMachine = _has() + hasMCAsmBackend = _has() + hasMCAsmParser = _has() + hasAsmPrinter = _has() + hasMCDisassembler = _has() + hasMCInstPrinter = _has() + hasMCCodeEmitter = _has() + hasMCObjectStreamer = _has() + hasAsmStreamer = _has() + + createTargetMachine = Method(ptr(TargetMachine), + cast(str, StringRef), # triple + cast(str, StringRef), # cpu + cast(str, StringRef), # features + ref(TargetOptions), + Reloc.Model, # = Reloc::Default + CodeModel.Model, # = CodeModel.Default + CodeGenOpt.Level, # = CodeGenOpt.Default + ).require_only(4) + + +@TargetRegistry +class TargetRegistry: + printRegisteredTargetsForVersion = StaticMethod() + + lookupTarget = CustomStaticMethod('TargetRegistry_lookupTarget', + PyObjectPtr, # const Target* + cast(str, ConstCharPtr), # triple + PyObjectPtr, # std::string &Error + ) + + lookupTarget |= CustomStaticMethod('TargetRegistry_lookupTarget', + PyObjectPtr, # const Target* + cast(str, ConstCharPtr), # arch + ref(Triple), # triple + PyObjectPtr, # std::string &Error + ) + + getClosestTargetForJIT = CustomStaticMethod( + 'TargetRegistry_getClosestTargetForJIT', + PyObjectPtr, # const Target* + PyObjectPtr, # std::string &Error + ) diff --git a/llvmpy/src/Target/TargetLibraryInfo.py b/llvmpy/src/Target/TargetLibraryInfo.py index d98b00b..9c47814 100644 --- a/llvmpy/src/Target/TargetLibraryInfo.py +++ b/llvmpy/src/Target/TargetLibraryInfo.py @@ -1,8 +1,7 @@ from binding import * from ..namespace import llvm -from ..ADT.Triple import Triple -from ..Pass import ImmutablePass -from ..ADT.StringRef import StringRef + +from src.Pass import ImmutablePass TargetLibraryInfo = llvm.Class(ImmutablePass) @@ -54,6 +53,10 @@ LibFunc.Enum('Func', ''' # not in llvm-3.2 abs, ffs, ffsl, ffsll, fprintf, isascii, # isdigit, labs, llabs, printf, sprintf, toascii +from src.ADT.Triple import Triple +from src.ADT.StringRef import StringRef + + @TargetLibraryInfo class TargetLibraryInfo: _include_ = 'llvm/Target/TargetLibraryInfo.h' diff --git a/llvmpy/src/Target/TargetMachine.py b/llvmpy/src/Target/TargetMachine.py index e60ed5c..29960fa 100644 --- a/llvmpy/src/Target/TargetMachine.py +++ b/llvmpy/src/Target/TargetMachine.py @@ -1,17 +1,18 @@ from binding import * -from ..namespace import llvm -from ..ADT.StringRef import StringRef -from ..Support.CodeGen import CodeModel, TLSModel, CodeGenOpt, Reloc -from ..GlobalValue import GlobalValue -from ..Support.Target import Target -from ..DataLayout import DataLayout -from ..TargetTransformInfo import (ScalarTargetTransformInfo, - VectorTargetTransformInfo) -from ..PassManager import PassManagerBase -from ..Support.FormattedStream import formatted_raw_ostream +from src.namespace import llvm TargetMachine = llvm.Class() +from src.Support.TargetRegistry import Target +from src.ADT.StringRef import StringRef +from src.Support.CodeGen import CodeModel, TLSModel, CodeGenOpt, Reloc +from src.GlobalValue import GlobalValue +from src.DataLayout import DataLayout +from src.TargetTransformInfo import (ScalarTargetTransformInfo, + VectorTargetTransformInfo) +from src.PassManager import PassManagerBase +from src.Support.FormattedStream import formatted_raw_ostream + @TargetMachine class TargetMachine: _include_ = 'llvm/Target/TargetMachine.h' diff --git a/llvmpy/src/Target/TargetOptions.py b/llvmpy/src/Target/TargetOptions.py new file mode 100644 index 0000000..0e28677 --- /dev/null +++ b/llvmpy/src/Target/TargetOptions.py @@ -0,0 +1,12 @@ +from binding import * +from src.namespace import llvm + +llvm.includes.add('llvm/Target/TargetOptions.h') + +TargetOptions = llvm.Class() + +@TargetOptions +class TargetOptions: + new = Constructor() + delete = Destructor() + diff --git a/llvmpy/test_binding.py b/llvmpy/test_binding.py index e1e12e5..01e6c38 100644 --- a/llvmpy/test_binding.py +++ b/llvmpy/test_binding.py @@ -7,9 +7,10 @@ import llvmpy.capsule llvmpy.capsule.set_debug(True) +llvm.InitializeNativeTarget() +llvm.InitializeNativeTargetAsmPrinter() + def test_basic_jit_use(): - llvm.InitializeNativeTarget() - llvm.InitializeNativeTargetAsmPrinter() context = llvm.getGlobalContext() m = llvm.Module.new("modname", context) @@ -332,6 +333,42 @@ def test_intrinsic(): fn.eraseFromParent() assert 'llvm.sin.f32' not in str(m) +def test_passregistry(): + passreg = llvm.PassRegistry.getPassRegistry() + + llvm.initializeScalarOpts(passreg) + + passinfo = passreg.getPassInfo("dce") + dcepass = passinfo.createPass() + print dcepass.getPassName() + + print passreg.enumerate() + +def test_targetregistry(): + llvm.TargetRegistry.printRegisteredTargetsForVersion() + errmsg = StringIO() + + target = llvm.TargetRegistry.getClosestTargetForJIT(errmsg) + errmsg.close() + + print target.getName() + print target.getShortDescription() + assert target.hasJIT() + assert target.hasTargetMachine() + + next = target.getNext() + if next: + print next.getName() + print next.getShortDescription() + + triple = llvm.sys.getDefaultTargetTriple() + cpu = llvm.sys.getHostCPUName() + features = {} + assert not llvm.sys.getHostCPUFeatures(features), "Only for Linux and ARM?" + + targetoptions = llvm.TargetOptions.new() + tm = target.createTargetMachine(triple, cpu, "", targetoptions) + def main(): for name, value in globals().items(): if name.startswith('test_') and callable(value): From a97b26415e7e21d63abfe66ed9c31b3e9a1d1e7d Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 11 Feb 2013 18:15:22 -0600 Subject: [PATCH 68/85] Update old API to use the new binding. Have not run the testsuite yet. --- llvm/__init__.py | 4 + llvm/core.py | 30 ++++ llvm/ee.py | 334 ++++++++++++++++++++++++++++++++++++++++++ llvm/passes.py | 371 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 739 insertions(+) diff --git a/llvm/__init__.py b/llvm/__init__.py index 23f3f4d..4cf374c 100644 --- a/llvm/__init__.py +++ b/llvm/__init__.py @@ -1,5 +1,6 @@ class Wrapper(object): def __init__(self, ptr): + assert ptr self.__ptr = ptr @property @@ -9,3 +10,6 @@ class Wrapper(object): def _extract_ptrs(objs): return [x._ptr for x in objs] + +class LLVMException(Exception): + pass diff --git a/llvm/core.py b/llvm/core.py index 2f7adb5..3c3e027 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -1,3 +1,33 @@ +# +# Copyright (c) 2008-10, Mahadevan R All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# * Neither the name of this software, nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + try: from cStringIO import StringIO except ImportError: diff --git a/llvm/ee.py b/llvm/ee.py index e69de29..8523998 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -0,0 +1,334 @@ +# +# Copyright (c) 2008-10, Mahadevan R All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# * Neither the name of this software, nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +"Execution Engine and related classes." + +try: + from cStringIO import StringIO +except ImportError: + from StringIO import StringIO +import contextlib + +import llvm +from llvm import core +from llvmpy import api + +#===----------------------------------------------------------------------=== +# Enumerations +#===----------------------------------------------------------------------=== + +BO_BIG_ENDIAN = 0 +BO_LITTLE_ENDIAN = 1 + +# CodeModel +CM_DEFAULT = api.llvm.CodeModel.Model.Default +CM_JITDEFAULT = api.llvm.CodeModel.Model.JITDefault +CM_SMALL = api.llvm.CodeModel.Model.Small +CM_KERNEL = api.llvm.CodeModel.Model.Kernel +CM_MEDIUM = api.llvm.CodeModel.Model.Medium +CM_LARGE = api.llvm.CodeModel.Model.Large + +#===----------------------------------------------------------------------=== +# Generic value +#===----------------------------------------------------------------------=== + +class GenericValue(llvm.Wrapper): + + @staticmethod + def int(ty, intval): + ptr = api.llvm.CreateInt(ty._ptr, intval, False) + return GenericValue(ptr) + + @staticmethod + def int_signed(ty, intval): + ptr = api.llvm.CreateInt(ty._ptr, intval, True) + return GenericValue(ptr) + + @staticmethod + def real(ty, floatval): + if str(ty) == 'float': + ptr = api.llvm.CreateFloat(floatval) + elif str(ty) == 'double': + ptr = api.llvm.CreateDouble(floatval) + else: + raise Exception('Unreachable') + return GenericValue(ptr) + + @staticmethod + def pointer(addr): + ''' + One argument version takes (addr). + Two argument version takes (ty, addr). [Deprecated] + + `ty` is unused. + `addr` is an integer representing an address. + + ''' + ptr = api.llvm.CreatePointer(addr) + return GenericValue(ptr) + + def as_int(self): + return self._ptr.toUnsignedInt() + + def as_int_signed(self): + return self._ptr.toSignedInt() + + def as_real(self, ty): + return self._ptr.toFloat() + + def as_pointer(self): + return self._ptr.toPointer() + +#===----------------------------------------------------------------------=== +# Engine builder +#===----------------------------------------------------------------------=== + +class EngineBuilder(llvm.Wrapper): + @staticmethod + def new(module): + ptr = api.llvm.EngineBuilder.new(module) + return EngineBuilder(ptr) + + def force_jit(self): + self._ptr.setEngineKind(api.llvm.EngineKind.Kind.JIT) + return self + + def force_interpreter(self): + self._ptr.setEngineKind(api.llvm.EngineKind.Kind.Interpreter) + return self + + def opt(self, level): + ''' + level valid [0, 1, 2, 3] -- [None, Less, Default, Aggressive] + ''' + assert 0 <= level <= 3 + self._ptr.setOptLevel = level + return self + + def mattrs(self, string): + '''set machine attributes as a comma/space separated string + + e.g: +sse,-3dnow + ''' + self._ptr.setMAttrs(string.split(',')) + return self + + def create(self, tm=None): + ''' + tm --- Optional. Provide a TargetMachine. Ownership is transfered + to the returned execution engine. + ''' + if tm is not None: + engine = self._ptr.create(tm._ptr) + else: + engine = self._ptr.create() + return ExecutionEngine(engine) + + def select_target(self, *args): + '''get the corresponding target machine + + Accept no arguments or (triple, march, mcpu, mattrs) + ''' + if args: + triple, march, mcpu, mattrs = args + ptr = self._ptr.select_target(triple, march, mcpu, + mattrs.split(',')) + else: + ptr = self._ptr.select_target() + return TargetMachine(ptr) + + +#===----------------------------------------------------------------------=== +# Execution engine +#===----------------------------------------------------------------------=== + +class ExecutionEngine(llvm.Wrapper): + + @staticmethod + def new(module, force_interpreter=False): + eb = EngineBuilder.new(module) + if force_interpreter: + eb.force_interpreter() + return eb.create() + + def disable_lazy_compilation(self, disabled=True): + self._ptr.DisableLazyCompilation(disabled) + + def run_function(self, fn, args): + return self._ptr.runFunction(fn._ptr, map(lambda x: x._ptr, args)) + + def get_pointer_to_function(self, fn): + return self._ptr.getPointerToFunction(fn._ptr) + + def get_pointer_to_global(self, val): + return self._ptr.getPointerToGlobal(val._ptr) + + def add_global_mapping(self, gvar, addr): + assert addr >= 0, "Address cannot not be negative" + self._ptr.addGlobalMapping(gvar._ptr, addr) + + def run_static_ctors(self): + self._ptr.runStaticConstructorDestructors(False) + + def run_static_dtors(self): + self._ptr.runStaticConstructorDestructors(True) + + def free_machine_code_for(self, fn): + self.freeMachineCodeForFunction(fn._ptr) + + def add_module(self, module): + self._ptr.addModule(module._ptr) + + def remove_module(self, module): + return self._ptr.removeModule(module._ptr) + + @property + def target_data(self): + ptr = self._ptr.getDataLayout() + return TargetData(ptr) + +#===----------------------------------------------------------------------=== +# Target machine +#===----------------------------------------------------------------------=== + +def print_registered_targets(): + ''' + Note: print directly to stdout + ''' + llvm.TargetRegistry.printRegisteredTargetsForVersion() + +def get_host_cpu_name(): + '''return the string name of the host CPU + ''' + return llvm.sys.getHostCPUName() + +def get_default_triple(): + '''return the target triple of the host in str-rep + ''' + return llvm.sys.getDefaultTargetTriple() + + +class TargetMachine(llvm.Wrapper): + + @staticmethod + def new(triple='', cpu='', features='', opt=2, cm=CM_DEFAULT): + if not triple: + triple = get_default_triple() + if not cpu: + cpu = get_host_cpu_name() + with contextlib.closing(StringIO) as error: + target = api.llvm.TargetRegistry.lookupTarget(triple, error) + if not target: + raise llvm.LLVMException(error) + if not target.hasTargetMachine(): + raise llvm.LLVMException(target, "No target machine.") + target_options = api.llvm.TargetOptions() + tm = target.createTargetMachine(triple, cpu, features, + target_options, + api.llvm.Reloc.Model.Default, + cm, opt) + if not tm: + raise llvm.LLVMException("Cannot create target machine") + return TargetMachine(ptr) + + @staticmethod + def lookup(arch, cpu='', features='', opt=2, cm=CM_DEFAULT): + '''create a targetmachine given an architecture name + + For a list of architectures, + use: `llc -help` + + For a list of available CPUs, + use: `llvm-as < /dev/null | llc -march=xyz -mcpu=help` + + For a list of available attributes (features), + use: `llvm-as < /dev/null | llc -march=xyz -mattr=help` + ''' + triple = api.llvm.Triple.new() + with contextlib.closing(StringIO) as error: + target = api.llvm.TargetMachine.lookupTarget(arch, triple, error) + if not target: + raise llvm.LLVMException(error) + if not target.hasTargetMachine(): + raise llvm.LLVMException(target, "No target machine.") + target_options = api.llvm.TargetOptions() + tm = target.createTargetMachine(str(triple), cpu, features, + target_options, + api.llvm.Reloc.Model.Default, + cm, opt) + if not tm: + raise llvm.LLVMException("Cannot create target machine") + return TargetMachine(ptr) + + def _emit_file(self, module, cgft): + pm = api.llvm.PassManager.new() + os = api.extra.make_raw_ostream_for_printing() + failed = self._ptr.addPassesToEmitFile(pm, os, cgft) + pm.run(module) + return os.str() + + def emit_assembly(self, module): + '''returns byte string of the module as assembly code of the target machine + ''' + CGFT = api.llvm.TargetMachine.CodeGenFileType + return self._emit_file(module, CGFT.CGFT_AssemblyFile) + + def emit_object(self, module): + '''returns byte string of the module as native code of the target machine + ''' + CGFT = api.llvm.TargetMachine.CodeGenFileType + return self._emit_file(module, CGFT.CGFT_ObjectFile) + + @property + def target_data(self): + '''get target data of this machine + ''' + return TargetData(self._ptr.getDataLayout) + + @property + def target_name(self): + return self._ptr.getTarget().getName() + + @property + def target_short_description(self): + return self._ptr.getTarget().getShortDescription() + + @property + def triple(self): + return self._ptr.getTargetTriple() + + @property + def cpu(self): + return self._ptr.getTargetCPU() + + @property + def feature_string(self): + return self._ptr.getTargetFeatureString() + diff --git a/llvm/passes.py b/llvm/passes.py index e69de29..545a19d 100644 --- a/llvm/passes.py +++ b/llvm/passes.py @@ -0,0 +1,371 @@ +# +# Copyright (c) 2008-10, Mahadevan R All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# * Neither the name of this software, nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# + +"""Pass managers and passes. + +This module provides the LLVM pass managers and the passes themselves. +All transformation passes listed at http://www.llvm.org/docs/Passes.html +are available. +""" + +import llvm # top-level, for common stuff +import llvm.core as core # module, function etc. +from llvmpy import api + +#===----------------------------------------------------------------------=== +# Pass manager builder +#===----------------------------------------------------------------------=== + +class PassManagerBuilder(llvm.Wrapper): + @staticmethod + def new(): + return PassManagerBuilder(api.llvm.PassManagerBuilder()) + + def populate(self, pm): + if isinstance(pm, FunctionPassManager): + self._ptr.populateFunctionPassManager(pm._ptr) + else: + self._ptr.populateModulePassManager(pm._ptr) + + @property + def opt_level(self): + return self._ptr.OptLevel + + @opt_level.setter + def _set_opt_level(self, optlevel): + self._ptr.OptLevel = optlevel + + @property + def size_level(self): + return self._ptr.SizeLevel + + @size_level.setter + def _set_size_level(self, sizelevel): + self._ptr.SizeLevel = sizelevel + + @property + def vectorize(self): + return self._ptr.Vectorize + + @vectorize.setter + def _set_vectorize(self, enable): + self._ptr.Vectroize = enable + + @property + def loop_vectorize(self): + try: + return self._ptr.LoopVectorize + except AttributeError: + return False + + @loop_vectorize.setter + def loop_vectorize(self, enable): + if llvm.version >= (3, 2): + self._ptr.LoopVectorize = enable + elif enable: + warnings.warn("Ignored. LLVM-3.1 & prior do not support loop vectorizer.") + + @property + def disable_unit_at_a_time(self): + return self._ptr.DisableUnitAtATime + + @disable_unit_at_a_time.setter + def disable_unit_at_a_time(self, disable): + self._ptr.DisableUnitAtATime = disable + + @property + def disable_unroll_loops(self): + return self._ptr.DisableUnrollLoops + + @disable_unroll_loops.setter + def disable_unroll_loops(self, disable): + self._ptr.DisableUnrollLoops = disable + + @property + def disable_simplify_lib_calls(self): + return self._ptr.DisableSimplifyLibCalls + + @disable_simplify_lib_calls.setter + def disable_simplify_lib_calls(self, disable): + self._ptr.DisableSimplifyLibCalls = disable + + def use_inliner_with_threshold(self, threshold): + self._ptr.Inliner = api.llvm.createFunctionInliningPass(threshold) + + +#===----------------------------------------------------------------------=== +# Pass manager +#===----------------------------------------------------------------------=== + +class PassManager(llvm.Wrapper): + + @staticmethod + def new(): + return PassManager(api.llvm.PassManager.new()) + + def add(self, pass_obj): + '''Add a pass to the pass manager. + + pass_obj --- Either a Pass instance, a string name of a pass + ''' + if isinstance(pass_obj, Pass): + self._ptr.add(pass_obj._ptr) + else: + self._add_pass(str(pass_obj)) + + def _add_pass(self, pass_name): + passreg = api.llvm.PassRegistry.getPassRegistry() + a_pass = passreg.getPassInfo(pass_name) + if not a_pass: + assert pass_name not in PASSES, "Registered but not found?" + raise llvm.LLVMException('Invalid pass name "%s"' % pass_name) + self._ptr.add(a_pass) + + def run(self, module): + return self._ptr.run(module._ptr) + +class FunctionPassManager(PassManager): + + @staticmethod + def new(module): + ptr = api.llvm.FunctionPassManager.new(module) + return FunctionPassManager(ptr) + + def __init__(self, ptr): + PassManager.__init__(self, ptr) + + def initialize(self): + self._ptr.doInitization() + + def run(self, fn): + return self._ptr.run(fn) + + def finalize(self): + self._ptr.doFinalization() + +#===----------------------------------------------------------------------=== +# Passes +#===----------------------------------------------------------------------=== + +class Pass(llvm.Wrapper): + '''Pass Inferface + ''' + + @staticmethod + def new(name): + '''Create a new pass by name. + + Note: Not all pass has a default constructor. LLVM will kill + the process if an the pass requires arguments to construct. + The error cannot be caught. + ''' + passreg = api.llvm.PassRegistry.getPassRegistry() + a_pass = passreg.getPassInfo(pass_name) + p = Pass(a_pass) + p.__name = name + return p + + @property + def name(self): + '''The name used in PassRegistry. + ''' + return p.__name + + @property + def description(self): + return self._ptr.getPassName() + + def dump(self): + return self._ptr.dump() + +#===----------------------------------------------------------------------=== +# Target data +#===----------------------------------------------------------------------=== + +class TargetData(Pass): + + @staticmethod + def new(strrep): + ptr = api.llvm.DataLayout.new(strrep) + return TargetData(ptr) + + def clone(self): + return TargetData.new(str(self)) + + def __str__(self): + return self._ptr.getStringRepresentation() + + @property + def byte_order(self): + if self._ptr.isLittleEndian(): + return 1 + else: + return 0 + + @property + def pointer_size(self): + return self._ptr.getPointerSize() + + @property + def target_integer_type(self): + return self._ptr.core.IntegerType(core.Type.getInt32Ty()) + + def size(self, ty): + return self._ptr.getTypeSizeInBits(ty._ptr) + + def store_size(self, ty): + return self._ptr.getTypeStoreSize(ty._ptr) + + def abi_size(self, ty): + return self._ptr.getTypeAllocSize(ty._ptr) + + def abi_alignment(self, ty): + return self._ptr.getABITypeAlignment(ty._ptr) + + def callframe_alignment(self, ty): + return self._ptr.getCallFrameTypeAlignment(ty._ptr) + + def preferred_alignment(self, ty_or_gv): + if isinstance(ty_or_gv, core.Type): + return self._ptr.getPrefTypeAlignment(ty_or_gv._ptr) + elif isinstance(ty_or_gv, core.GlobalVariable): + return self._ptr._core.getPreferredAlignment(ty_or_gv._ptr) + else: + raise core.LLVMException("argument is neither a type nor a global variable") + + def element_at_offset(self, ty, ofs): + return self._ptr.getStructLayout(ty).getElementContainingOffset(ofs) + + def offset_of_element(self, ty, el): + return self._ptr.getStructLayout(ty).getElementOffset(el) + +#===----------------------------------------------------------------------=== +# Target Library Info +#===----------------------------------------------------------------------=== + +class TargetLibraryInfo(Pass): + @staticmethod + def new(triple): + triple = api.llvm.Triple.new(str(triple)) + ptr = api.llvm.TargetLibraryInfo.new(triple) + return TargetLibraryInfo(ptr) + +#===----------------------------------------------------------------------=== +# Helpers +#===----------------------------------------------------------------------=== + +def build_pass_managers(tm, opt=2, loop_vectorize=False, vectorize=False, + inline_threshold=2000, pm=True, fpm=True, mod=None): + ''' + tm --- The TargetMachine for which the passes are optimizing for. + The TargetMachine must stay alive until the pass managers + are removed. + opt --- [0-3] Optimization level. Default to 2. + loop_vectorize --- [boolean] Whether to use loop-vectorizer. + vectorize --- [boolean] Whether to use basic-block vectorizer. + inline_threshold --- [int] Threshold for the inliner. + features --- [str] CPU feature string. + pm --- [boolean] Whether to build a module-level pass-manager. + fpm --- [boolean] Whether to build a function-level pass-manager. + mod --- [Module] The module object for the FunctionPassManager. + ''' + if pm: + pm = PassManager.new() + if fpm: + if not mod: + raise TypeError("Keyword 'mod' must be defined") + fpm = FunctionPassManager.new(mod) + + # Populate PassManagers with target specific passes + pmb = PassManagerBuilder.new() + pmb.opt_level = opt + pmb.vectorize = vectorize + pmb.loop_vectorize = loop_vectorize + if inline_threshold: + pmb.use_inliner_with_threshold(inline_threshold) + if pm: + pm.add(tm.target_data.clone()) + pm.add(TargetLibraryInfo.new(tm.triple)) + if llvm.version >= (3, 2): + pm.add(TargetTransformInfo.new(tm)) + pmb.populate(pm) + + if fpm: + fpm.add(tm.target_data) + fpm.add(TargetLibraryInfo.new(tm.triple)) + if llvm.version >= (3, 2): + fpm.add(TargetTransformInfo.new(tm)) + pmb.populate(fpm) + fpm.initialize() + + from collections import namedtuple + return namedtuple('passmanagers', ['pm', 'fpm'])(pm=pm, fpm=fpm) + +#===----------------------------------------------------------------------=== +# Misc. +#===----------------------------------------------------------------------=== + +# Intialize passes +PASSES = None + +def _dump_all_passes(): + passreg = api.llvm.PassRegistry.getPassRegistry() + for name, desc in passreg.enumerate(): + yield name, desc + +def _initialize_passes(): + global PASSES + + passreg = api.llvm.PassRegistry.getPassRegistry() + + api.llvm.initializeCore(passreg) + api.llvm.initializeScalarOpts(passreg) + api.llvm.initializeVectorization(passreg) + api.llvm.initializeIPO(passreg) + api.llvm.initializeAnalysis(passreg) + api.llvm.initializeIPA(passreg) + api.llvm.initializeTransformUtils(passreg) + api.llvm.initializeInstCombine(passreg) + api.llvm.initializeInstrumentation(passreg) + api.llvm.initializeTarget(passreg) + + PASSES = dict(_dump_all_passes()) + + # build globals + def transform(name): + return "PASS_%s" % (name.upper().replace('-', '_')) + + global_symbols = globals() + for i in PASSES: + assert i not in global_symbols + global_symbols[transform(i)] = i + +_initialize_passes() + From a09394cacdcc841c22d205976ef3d059686cd716 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 13 Feb 2013 15:09:26 -0600 Subject: [PATCH 69/85] Fix a lots of bugs in the newbinding to pass all the tests. NOTE: debug info has not been implemented yet. --- llvm/__init__.py | 22 +- llvm/_version.py | 193 +++ llvm/core.py | 1065 ++++++++------ llvm/ee.py | 60 +- llvm/passes.py | 49 +- llvm/tbaa.py | 51 + llvm/test_llvmpy.py | 1243 +++++++++++++++++ llvmpy/capsule.py | 6 +- llvmpy/gen/binding.py | 17 +- llvmpy/include/llvm_binding/conversion.h | 21 +- llvmpy/include/llvm_binding/extra.h | 54 +- llvmpy/src/Argument.py | 4 +- llvmpy/src/Attributes.py | 2 +- llvmpy/src/BasicBlock.py | 4 +- llvmpy/src/Constant.py | 33 +- llvmpy/src/DerivedTypes.py | 1 + llvmpy/src/ExecutionEngine/ExecutionEngine.py | 2 +- llvmpy/src/Function.py | 4 +- llvmpy/src/GenericValue.py | 4 +- llvmpy/src/IRBuilder.py | 7 +- llvmpy/src/Instruction.py | 6 +- llvmpy/src/Metadata.py | 2 + llvmpy/src/Target/TargetMachine.py | 6 +- llvmpy/src/TargetTransformInfo.py | 10 +- llvmpy/src/Transforms/PassManagerBuilder.py | 11 +- llvmpy/src/Transforms/Utils/Cloning.py | 10 +- llvmpy/src/Type.py | 20 +- llvmpy/src/Value.py | 9 + test/constants.py | 2 - test/malloc.py | 16 + test/operands.py | 2 + test/testall.py | 29 +- 32 files changed, 2419 insertions(+), 546 deletions(-) create mode 100644 llvm/_version.py create mode 100644 llvm/tbaa.py create mode 100644 llvm/test_llvmpy.py create mode 100644 test/malloc.py diff --git a/llvm/__init__.py b/llvm/__init__.py index 4cf374c..c18d066 100644 --- a/llvm/__init__.py +++ b/llvm/__init__.py @@ -1,3 +1,12 @@ +from ._version import get_versions +__version__ = get_versions()['version'] +del get_versions + + +from llvmpy import extra +version = extra.get_llvm_version() +del extra + class Wrapper(object): def __init__(self, ptr): assert ptr @@ -9,7 +18,18 @@ class Wrapper(object): def _extract_ptrs(objs): - return [x._ptr for x in objs] + return [(x._ptr if x is not None else None) + for x in objs] class LLVMException(Exception): pass + +def test(verbosity=1): + """test(verbosity=1) -> TextTestResult + + Run self-test, and return unittest.runner.TextTestResult object. + """ + from llvm.test_llvmpy import run + + return run(verbosity=verbosity) + diff --git a/llvm/_version.py b/llvm/_version.py new file mode 100644 index 0000000..a90c5b8 --- /dev/null +++ b/llvm/_version.py @@ -0,0 +1,193 @@ + +IN_LONG_VERSION_PY = True +# This file helps to compute a version number in source trees obtained from +# git-archive tarball (such as those provided by github's download-from-tag +# feature). Distribution tarballs (build by setup.py sdist) and build +# directories (produced by setup.py build) will contain a much shorter file +# that just contains the computed version number. + +# This file is released into the public domain. Generated by +# versioneer-0.7+ (https://github.com/warner/python-versioneer) + +# these strings will be replaced by git during git-archive +git_refnames = "$Format:%d$" +git_full = "$Format:%H$" +GIT = "git" + +import subprocess +import sys + +def run_command(args, cwd=None, verbose=False): + try: + # remember shell=False, so use git.cmd on windows, not just git + p = subprocess.Popen(args, stdout=subprocess.PIPE, cwd=cwd) + except EnvironmentError: + e = sys.exc_info()[1] + if verbose: + print("unable to run %s" % args[0]) + print(e) + return None + stdout = p.communicate()[0].strip() + if sys.version >= '3': + stdout = stdout.decode() + if p.returncode != 0: + if verbose: + print("unable to run %s (error)" % args[0]) + return None + return stdout + + +import sys +import re +import os.path + +def get_expanded_variables(versionfile_source): + # the code embedded in _version.py can just fetch the value of these + # variables. When used from setup.py, we don't want to import + # _version.py, so we do it with a regexp instead. This function is not + # used from _version.py. + variables = {} + try: + for line in open(versionfile_source,"r").readlines(): + if line.strip().startswith("git_refnames ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + variables["refnames"] = mo.group(1) + if line.strip().startswith("git_full ="): + mo = re.search(r'=\s*"(.*)"', line) + if mo: + variables["full"] = mo.group(1) + except EnvironmentError: + pass + return variables + +def versions_from_expanded_variables(variables, tag_prefix, verbose=False): + refnames = variables["refnames"].strip() + if refnames.startswith("$Format"): + if verbose: + print("variables are unexpanded, not using") + return {} # unexpanded, so not in an unpacked git-archive tarball + refs = set([r.strip() for r in refnames.strip("()").split(",")]) + for ref in list(refs): + if not re.search(r'\d', ref): + if verbose: + print("discarding '%s', no digits" % ref) + refs.discard(ref) + # Assume all version tags have a digit. git's %d expansion + # behaves like git log --decorate=short and strips out the + # refs/heads/ and refs/tags/ prefixes that would let us + # distinguish between branches and tags. By ignoring refnames + # without digits, we filter out many common branch names like + # "release" and "stabilization", as well as "HEAD" and "master". + if verbose: + print("remaining refs: %s" % ",".join(sorted(refs))) + for ref in sorted(refs): + # sorting will prefer e.g. "2.0" over "2.0rc1" + if ref.startswith(tag_prefix): + r = ref[len(tag_prefix):] + if verbose: + print("picking %s" % r) + return { "version": r, + "full": variables["full"].strip() } + # no suitable tags, so we use the full revision id + if verbose: + print("no suitable tags, using full revision id") + return { "version": variables["full"].strip(), + "full": variables["full"].strip() } + +def versions_from_vcs(tag_prefix, versionfile_source, verbose=False): + # this runs 'git' from the root of the source tree. That either means + # someone ran a setup.py command (and this code is in versioneer.py, so + # IN_LONG_VERSION_PY=False, thus the containing directory is the root of + # the source tree), or someone ran a project-specific entry point (and + # this code is in _version.py, so IN_LONG_VERSION_PY=True, thus the + # containing directory is somewhere deeper in the source tree). This only + # gets called if the git-archive 'subst' variables were *not* expanded, + # and _version.py hasn't already been rewritten with a short version + # string, meaning we're inside a checked out source tree. + + try: + here = os.path.abspath(__file__) + except NameError: + # some py2exe/bbfreeze/non-CPython implementations don't do __file__ + return {} # not always correct + + # versionfile_source is the relative path from the top of the source tree + # (where the .git directory might live) to this file. Invert this to find + # the root from __file__. + root = here + if IN_LONG_VERSION_PY: + for i in range(len(versionfile_source.split("/"))): + root = os.path.dirname(root) + else: + root = os.path.dirname(here) + if not os.path.exists(os.path.join(root, ".git")): + if verbose: + print("no .git in %s" % root) + return {} + + stdout = run_command([GIT, "describe", "--tags", "--dirty", "--always"], + cwd=root) + if stdout is None: + return {} + if not stdout.startswith(tag_prefix): + if verbose: + print("tag '%s' doesn't start with prefix '%s'" % (stdout, tag_prefix)) + return {} + tag = stdout[len(tag_prefix):] + stdout = run_command([GIT, "rev-parse", "HEAD"], cwd=root) + if stdout is None: + return {} + full = stdout.strip() + if tag.endswith("-dirty"): + full += "-dirty" + return {"version": tag, "full": full} + + +def versions_from_parentdir(parentdir_prefix, versionfile_source, verbose=False): + if IN_LONG_VERSION_PY: + # We're running from _version.py. If it's from a source tree + # (execute-in-place), we can work upwards to find the root of the + # tree, and then check the parent directory for a version string. If + # it's in an installed application, there's no hope. + try: + here = os.path.abspath(__file__) + except NameError: + # py2exe/bbfreeze/non-CPython don't have __file__ + return {} # without __file__, we have no hope + # versionfile_source is the relative path from the top of the source + # tree to _version.py. Invert this to find the root from __file__. + root = here + for i in range(len(versionfile_source.split("/"))): + root = os.path.dirname(root) + else: + # we're running from versioneer.py, which means we're running from + # the setup.py in a source tree. sys.argv[0] is setup.py in the root. + here = os.path.abspath(sys.argv[0]) + root = os.path.dirname(here) + + # Source tarballs conventionally unpack into a directory that includes + # both the project name and a version string. + dirname = os.path.basename(root) + if not dirname.startswith(parentdir_prefix): + if verbose: + print("guessing rootdir is '%s', but '%s' doesn't start with prefix '%s'" % + (root, dirname, parentdir_prefix)) + return None + return {"version": dirname[len(parentdir_prefix):], "full": ""} + +tag_prefix = "" +parentdir_prefix = "llvmpy-" +versionfile_source = "llvm/_version.py" + +def get_versions(default={"version": "unknown", "full": ""}, verbose=False): + variables = { "refnames": git_refnames, "full": git_full } + ver = versions_from_expanded_variables(variables, tag_prefix, verbose) + if not ver: + ver = versions_from_vcs(tag_prefix, versionfile_source, verbose) + if not ver: + ver = versions_from_parentdir(parentdir_prefix, versionfile_source, + verbose) + if not ver: + ver = default + return ver diff --git a/llvm/core.py b/llvm/core.py index 3c3e027..1c3184c 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -32,11 +32,12 @@ try: from cStringIO import StringIO except ImportError: from StringIO import StringIO -import contextlib +import contextlib, weakref import llvm +from llvm._intrinsic_ids import * -import api +from llvmpy import api #===----------------------------------------------------------------------=== # Enumerations @@ -88,167 +89,180 @@ VALUE_PSEUDO_SOURCE_VALUE = api.llvm.Value.ValueTy.PseudoSourceVal VALUE_FIXED_STACK_PSEUDO_SOURCE_VALUE = api.llvm.Value.ValueTy.FixedStackPseudoSourceValueVal VALUE_INSTRUCTION = api.llvm.Value.ValueTy.InstructionVal -## instruction opcodes (from include/llvm/Instruction.def) -#OPCODE_RET = 1 -#OPCODE_BR = 2 -#OPCODE_SWITCH = 3 -#OPCODE_INDIRECT_BR = 4 -#OPCODE_INVOKE = 5 -#OPCODE_RESUME = 6 -#OPCODE_UNREACHABLE = 7 -#OPCODE_ADD = 8 -#OPCODE_FADD = 9 -#OPCODE_SUB = 10 -#OPCODE_FSUB = 11 -#OPCODE_MUL = 12 -#OPCODE_FMUL = 13 -#OPCODE_UDIV = 14 -#OPCODE_SDIV = 15 -#OPCODE_FDIV = 16 -#OPCODE_UREM = 17 -#OPCODE_SREM = 18 -#OPCODE_FREM = 19 -#OPCODE_SHL = 20 -#OPCODE_LSHR = 21 -#OPCODE_ASHR = 22 -#OPCODE_AND = 23 -#OPCODE_OR = 24 -#OPCODE_XOR = 25 -#OPCODE_ALLOCA = 26 -#OPCODE_LOAD = 27 -#OPCODE_STORE = 28 -#OPCODE_GETELEMENTPTR = 29 -#OPCODE_FENCE = 30 -#OPCODE_ATOMICCMPXCHG = 31 -#OPCODE_ATOMICRMW = 32 -#OPCODE_TRUNC = 33 -#OPCODE_ZEXT = 34 -#OPCODE_SEXT = 35 -#OPCODE_FPTOUI = 36 -#OPCODE_FPTOSI = 37 -#OPCODE_UITOFP = 38 -#OPCODE_SITOFP = 39 -#OPCODE_FPTRUNC = 40 -#OPCODE_FPEXT = 41 -#OPCODE_PTRTOINT = 42 -#OPCODE_INTTOPTR = 43 -#OPCODE_BITCAST = 44 -#OPCODE_ICMP = 45 -#OPCODE_FCMP = 46 -#OPCODE_PHI = 47 -#OPCODE_CALL = 48 -#OPCODE_SELECT = 49 -#OPCODE_USEROP1 = 50 -#OPCODE_USEROP2 = 51 -#OPCODE_VAARG = 52 -#OPCODE_EXTRACTELEMENT = 53 -#OPCODE_INSERTELEMENT = 54 -#OPCODE_SHUFFLEVECTOR = 55 -#OPCODE_EXTRACTVALUE = 56 -#OPCODE_INSERTVALUE = 57 -#OPCODE_LANDINGPAD = 58 -# -## calling conventions -#CC_C = 0 -#CC_FASTCALL = 8 -#CC_COLDCALL = 9 -#CC_GHC = 10 -#CC_X86_STDCALL = 64 -#CC_X86_FASTCALL = 65 -#CC_ARM_APCS = 66 -#CC_ARM_AAPCS = 67 -#CC_ARM_AAPCS_VFP = 68 -#CC_MSP430_INTR = 69 -#CC_X86_THISCALL = 70 -#CC_PTX_KERNEL = 71 -#CC_PTX_DEVICE = 72 -#CC_MBLAZE_INTR = 73 -#CC_MBLAZE_SVOL = 74 -# -# -## int predicates -#ICMP_EQ = 32 -#ICMP_NE = 33 -#ICMP_UGT = 34 -#ICMP_UGE = 35 -#ICMP_ULT = 36 -#ICMP_ULE = 37 -#ICMP_SGT = 38 -#ICMP_SGE = 39 -#ICMP_SLT = 40 -#ICMP_SLE = 41 -# -## same as ICMP_xx, for backward compatibility -#IPRED_EQ = ICMP_EQ -#IPRED_NE = ICMP_NE -#IPRED_UGT = ICMP_UGT -#IPRED_UGE = ICMP_UGE -#IPRED_ULT = ICMP_ULT -#IPRED_ULE = ICMP_ULE -#IPRED_SGT = ICMP_SGT -#IPRED_SGE = ICMP_SGE -#IPRED_SLT = ICMP_SLT -#IPRED_SLE = ICMP_SLE -# -## real predicates -#FCMP_FALSE = 0 -#FCMP_OEQ = 1 -#FCMP_OGT = 2 -#FCMP_OGE = 3 -#FCMP_OLT = 4 -#FCMP_OLE = 5 -#FCMP_ONE = 6 -#FCMP_ORD = 7 -#FCMP_UNO = 8 -#FCMP_UEQ = 9 -#FCMP_UGT = 10 -#FCMP_UGE = 11 -#FCMP_ULT = 12 -#FCMP_ULE = 13 -#FCMP_UNE = 14 -#FCMP_TRUE = 15 -# -## real predicates -#RPRED_FALSE = FCMP_FALSE -#RPRED_OEQ = FCMP_OEQ -#RPRED_OGT = FCMP_OGT -#RPRED_OGE = FCMP_OGE -#RPRED_OLT = FCMP_OLT -#RPRED_OLE = FCMP_OLE -#RPRED_ONE = FCMP_ONE -#RPRED_ORD = FCMP_ORD -#RPRED_UNO = FCMP_UNO -#RPRED_UEQ = FCMP_UEQ -#RPRED_UGT = FCMP_UGT -#RPRED_UGE = FCMP_UGE -#RPRED_ULT = FCMP_ULT -#RPRED_ULE = FCMP_ULE -#RPRED_UNE = FCMP_UNE -#RPRED_TRUE = FCMP_TRUE -# -## linkages (see llvm-c/Core.h) -#LINKAGE_EXTERNAL = 0 -#LINKAGE_AVAILABLE_EXTERNALLY = 1 -#LINKAGE_LINKONCE_ANY = 2 -#LINKAGE_LINKONCE_ODR = 3 -#LINKAGE_WEAK_ANY = 4 -#LINKAGE_WEAK_ODR = 5 -#LINKAGE_APPENDING = 6 -#LINKAGE_INTERNAL = 7 -#LINKAGE_PRIVATE = 8 -#LINKAGE_DLLIMPORT = 9 -#LINKAGE_DLLEXPORT = 10 -#LINKAGE_EXTERNAL_WEAK = 11 -#LINKAGE_GHOST = 12 -#LINKAGE_COMMON = 13 -#LINKAGE_LINKER_PRIVATE = 14 -#LINKAGE_LINKER_PRIVATE_WEAK = 15 -#LINKAGE_LINKER_PRIVATE_WEAK_DEF_AUTO = 16 -# -## visibility (see llvm/GlobalValue.h) -#VISIBILITY_DEFAULT = 0 -#VISIBILITY_HIDDEN = 1 -#VISIBILITY_PROTECTED = 2 +# instruction opcodes (from include/llvm/Instruction.def) +OPCODE_RET = 1 +OPCODE_BR = 2 +OPCODE_SWITCH = 3 +OPCODE_INDIRECT_BR = 4 +OPCODE_INVOKE = 5 +OPCODE_RESUME = 6 +OPCODE_UNREACHABLE = 7 +OPCODE_ADD = 8 +OPCODE_FADD = 9 +OPCODE_SUB = 10 +OPCODE_FSUB = 11 +OPCODE_MUL = 12 +OPCODE_FMUL = 13 +OPCODE_UDIV = 14 +OPCODE_SDIV = 15 +OPCODE_FDIV = 16 +OPCODE_UREM = 17 +OPCODE_SREM = 18 +OPCODE_FREM = 19 +OPCODE_SHL = 20 +OPCODE_LSHR = 21 +OPCODE_ASHR = 22 +OPCODE_AND = 23 +OPCODE_OR = 24 +OPCODE_XOR = 25 +OPCODE_ALLOCA = 26 +OPCODE_LOAD = 27 +OPCODE_STORE = 28 +OPCODE_GETELEMENTPTR = 29 +OPCODE_FENCE = 30 +OPCODE_ATOMICCMPXCHG = 31 +OPCODE_ATOMICRMW = 32 +OPCODE_TRUNC = 33 +OPCODE_ZEXT = 34 +OPCODE_SEXT = 35 +OPCODE_FPTOUI = 36 +OPCODE_FPTOSI = 37 +OPCODE_UITOFP = 38 +OPCODE_SITOFP = 39 +OPCODE_FPTRUNC = 40 +OPCODE_FPEXT = 41 +OPCODE_PTRTOINT = 42 +OPCODE_INTTOPTR = 43 +OPCODE_BITCAST = 44 +OPCODE_ICMP = 45 +OPCODE_FCMP = 46 +OPCODE_PHI = 47 +OPCODE_CALL = 48 +OPCODE_SELECT = 49 +OPCODE_USEROP1 = 50 +OPCODE_USEROP2 = 51 +OPCODE_VAARG = 52 +OPCODE_EXTRACTELEMENT = 53 +OPCODE_INSERTELEMENT = 54 +OPCODE_SHUFFLEVECTOR = 55 +OPCODE_EXTRACTVALUE = 56 +OPCODE_INSERTVALUE = 57 +OPCODE_LANDINGPAD = 58 + +# calling conventions +CC_C = api.llvm.CallingConv.ID.C +CC_FASTCALL = api.llvm.CallingConv.ID.Fast +CC_COLDCALL = api.llvm.CallingConv.ID.Cold +CC_GHC = api.llvm.CallingConv.ID.GHC +CC_X86_STDCALL = api.llvm.CallingConv.ID.X86_StdCall +CC_X86_FASTCALL = api.llvm.CallingConv.ID.X86_FastCall +CC_ARM_APCS = api.llvm.CallingConv.ID.ARM_APCS +CC_ARM_AAPCS = api.llvm.CallingConv.ID.ARM_AAPCS +CC_ARM_AAPCS_VFP = api.llvm.CallingConv.ID.ARM_AAPCS_VFP +CC_MSP430_INTR = api.llvm.CallingConv.ID.MSP430_INTR +CC_X86_THISCALL = api.llvm.CallingConv.ID.X86_ThisCall +CC_PTX_KERNEL = api.llvm.CallingConv.ID.PTX_Kernel +CC_PTX_DEVICE = api.llvm.CallingConv.ID.PTX_Device +CC_MBLAZE_INTR = api.llvm.CallingConv.ID.MBLAZE_INTR +CC_MBLAZE_SVOL = api.llvm.CallingConv.ID.MBLAZE_SVOL + + +# int predicates +ICMP_EQ = api.llvm.CmpInst.Predicate.ICMP_EQ +ICMP_NE = api.llvm.CmpInst.Predicate.ICMP_NE +ICMP_UGT = api.llvm.CmpInst.Predicate.ICMP_UGT +ICMP_UGE = api.llvm.CmpInst.Predicate.ICMP_UGE +ICMP_ULT = api.llvm.CmpInst.Predicate.ICMP_ULT +ICMP_ULE = api.llvm.CmpInst.Predicate.ICMP_ULE +ICMP_SGT = api.llvm.CmpInst.Predicate.ICMP_SGT +ICMP_SGE = api.llvm.CmpInst.Predicate.ICMP_SGE +ICMP_SLT = api.llvm.CmpInst.Predicate.ICMP_SLT +ICMP_SLE = api.llvm.CmpInst.Predicate.ICMP_SLE + +# same as ICMP_xx, for backward compatibility +IPRED_EQ = ICMP_EQ +IPRED_NE = ICMP_NE +IPRED_UGT = ICMP_UGT +IPRED_UGE = ICMP_UGE +IPRED_ULT = ICMP_ULT +IPRED_ULE = ICMP_ULE +IPRED_SGT = ICMP_SGT +IPRED_SGE = ICMP_SGE +IPRED_SLT = ICMP_SLT +IPRED_SLE = ICMP_SLE + +# real predicates +FCMP_FALSE = api.llvm.CmpInst.Predicate.FCMP_FALSE +FCMP_OEQ = api.llvm.CmpInst.Predicate.FCMP_OEQ +FCMP_OGT = api.llvm.CmpInst.Predicate.FCMP_OGT +FCMP_OGE = api.llvm.CmpInst.Predicate.FCMP_OGE +FCMP_OLT = api.llvm.CmpInst.Predicate.FCMP_OLT +FCMP_OLE = api.llvm.CmpInst.Predicate.FCMP_OLE +FCMP_ONE = api.llvm.CmpInst.Predicate.FCMP_ONE +FCMP_ORD = api.llvm.CmpInst.Predicate.FCMP_ORD +FCMP_UNO = api.llvm.CmpInst.Predicate.FCMP_UNO +FCMP_UEQ = api.llvm.CmpInst.Predicate.FCMP_UEQ +FCMP_UGT = api.llvm.CmpInst.Predicate.FCMP_UGT +FCMP_UGE = api.llvm.CmpInst.Predicate.FCMP_UGE +FCMP_ULT = api.llvm.CmpInst.Predicate.FCMP_ULT +FCMP_ULE = api.llvm.CmpInst.Predicate.FCMP_ULE +FCMP_UNE = api.llvm.CmpInst.Predicate.FCMP_UNE +FCMP_TRUE = api.llvm.CmpInst.Predicate.FCMP_TRUE + +# real predicates +RPRED_FALSE = FCMP_FALSE +RPRED_OEQ = FCMP_OEQ +RPRED_OGT = FCMP_OGT +RPRED_OGE = FCMP_OGE +RPRED_OLT = FCMP_OLT +RPRED_OLE = FCMP_OLE +RPRED_ONE = FCMP_ONE +RPRED_ORD = FCMP_ORD +RPRED_UNO = FCMP_UNO +RPRED_UEQ = FCMP_UEQ +RPRED_UGT = FCMP_UGT +RPRED_UGE = FCMP_UGE +RPRED_ULT = FCMP_ULT +RPRED_ULE = FCMP_ULE +RPRED_UNE = FCMP_UNE +RPRED_TRUE = FCMP_TRUE + +# linkages (see llvm::GlobalValue::LinkageTypes) +LINKAGE_EXTERNAL = \ + api.llvm.GlobalValue.LinkageTypes.ExternalLinkage +LINKAGE_AVAILABLE_EXTERNALLY = \ + api.llvm.GlobalValue.LinkageTypes.AvailableExternallyLinkage +LINKAGE_LINKONCE_ANY = \ + api.llvm.GlobalValue.LinkageTypes.LinkOnceAnyLinkage +LINKAGE_LINKONCE_ODR = \ + api.llvm.GlobalValue.LinkageTypes.LinkOnceODRLinkage +LINKAGE_WEAK_ANY = \ + api.llvm.GlobalValue.LinkageTypes.WeakAnyLinkage +LINKAGE_WEAK_ODR = \ + api.llvm.GlobalValue.LinkageTypes.WeakODRLinkage +LINKAGE_APPENDING = \ + api.llvm.GlobalValue.LinkageTypes.AppendingLinkage +LINKAGE_INTERNAL = \ + api.llvm.GlobalValue.LinkageTypes.InternalLinkage +LINKAGE_PRIVATE = \ + api.llvm.GlobalValue.LinkageTypes.PrivateLinkage +LINKAGE_DLLIMPORT = \ + api.llvm.GlobalValue.LinkageTypes.DLLImportLinkage +LINKAGE_DLLEXPORT = \ + api.llvm.GlobalValue.LinkageTypes.DLLExportLinkage +LINKAGE_EXTERNAL_WEAK = \ + api.llvm.GlobalValue.LinkageTypes.ExternalWeakLinkage +LINKAGE_COMMON = \ + api.llvm.GlobalValue.LinkageTypes.CommonLinkage +LINKAGE_LINKER_PRIVATE = \ + api.llvm.GlobalValue.LinkageTypes.LinkerPrivateLinkage +LINKAGE_LINKER_PRIVATE_WEAK = \ + api.llvm.GlobalValue.LinkageTypes.LinkerPrivateWeakLinkage + +# visibility (see llvm/GlobalValue.h) +VISIBILITY_DEFAULT = api.llvm.GlobalValue.VisibilityTypes.DefaultVisibility +VISIBILITY_HIDDEN = api.llvm.GlobalValue.VisibilityTypes.HiddenVisibility +VISIBILITY_PROTECTED = api.llvm.GlobalValue.VisibilityTypes.ProtectedVisibility # parameter attributes llvm::Attributes::AttrVal (see llvm/Attributes.h) ATTR_NONE = api.llvm.Attributes.AttrVal.None_ @@ -291,6 +305,16 @@ class Module(llvm.Wrapper): module_obj = Module.new('my_module') """ + __cache = weakref.WeakValueDictionary() + + def __new__(cls, ptr): + cached = cls.__cache.get(ptr) + if cached: + return cached + obj = object.__new__(cls) + cls.__cache[ptr] = obj + return obj + @staticmethod def new(id): """Create a new Module instance. @@ -314,6 +338,7 @@ class Module(llvm.Wrapper): else: bc = fileobj_or_str.read() errbuf = StringIO() + context = api.llvm.getGlobalContext() m = api.llvm.ParseBitCodeFile(bc, context, errbuf) if not m: raise Exception(errbuf.getvalue()) @@ -335,7 +360,9 @@ class Module(llvm.Wrapper): else: ir = fileobj_or_str.read() errbuf = StringIO() - m = api.llvm.ParseAssemblyString(ir, None, api.llvm.SMDIagnostic.new(), context) + context = api.llvm.getGlobalContext() + m = api.llvm.ParseAssemblyString(ir, None, api.llvm.SMDiagnostic.new(), + context) errbuf.close() return Module(m) @@ -351,6 +378,7 @@ class Module(llvm.Wrapper): return str(self._ptr) def __eq__(self, rhs): + assert isinstance(rhs, Module), type(rhs) if isinstance(rhs, Module): return str(self) == str(rhs) else: @@ -386,7 +414,7 @@ class Module(llvm.Wrapper): @property def pointer_size(self): - return self.getPointerSize() + return self._ptr.getPointerSize() def link_in(self, other, preserve=False): """Link the `other' module into this one. @@ -401,20 +429,21 @@ class Module(llvm.Wrapper): Linker class. """ assert isinstance(other, Module) - enum_mode = api.llvm.Linker.LinkMode + enum_mode = api.llvm.Linker.LinkerMode mode = enum_mode.PreserveSource if preserve else enum_mode.DestroySource with contextlib.closing(StringIO()) as errmsg: - failed = api.llvm.Linker.LinkModule(self._ptr, - other._ptr, - mode, - errmsg) + failed = api.llvm.Linker.LinkModules(self._ptr, + other._ptr, + mode, + errmsg) if failed: raise llvm.LLVMException(errmsg) def get_type_named(self, name): typ = self._ptr.getTypeByName(name) - return StructType(typ) + if typ: + return StructType(typ) def add_global_variable(self, ty, name, addrspace=0): """Add a global variable of given type with given name.""" @@ -422,7 +451,7 @@ class Module(llvm.Wrapper): notthreadlocal = api.llvm.GlobalVariable.ThreadLocalMode.NotThreadLocal init = None insertbefore = None - ptr = api.llvm.GlobalVariable.new(self, + ptr = api.llvm.GlobalVariable.new(self._ptr, ty._ptr, False, external, @@ -431,16 +460,18 @@ class Module(llvm.Wrapper): insertbefore, notthreadlocal, addrspace) - return GlobalVariable(ptr) + return _make_value(ptr) def get_global_variable_named(self, name): """Return a GlobalVariable object for the given name.""" ptr = self._ptr.getNamedGlobal(name) - return GlobalVariable(ptr) + if ptr is None: + raise llvm.LLVMException("No global named: %s" % name) + return _make_value(ptr) @property def global_variables(self): - return self._ptr.list_globals() + return map(_make_value, self._ptr.list_globals()) def add_function(self, ty, name): """Add a function of given type with given name.""" @@ -452,21 +483,25 @@ class Module(llvm.Wrapper): def get_function_named(self, name): """Return a Function object representing function with given name.""" fn = self._ptr.getFunction(name) - if fn is None: - return None - return Function(fn) + if fn is not None: + return _make_value(fn) def get_or_insert_function(self, ty, name): """Like get_function_named(), but does add_function() first, if function is not present.""" constant = self._ptr.getOrInsertFunction(name, ty._ptr) - fn = constant._downcast(api.llvm.Function) - return Function(fn) + try: + fn = constant._downcast(api.llvm.Function) + except ValueError: + # bitcasted to function type + return _make_value(constant) + else: + return _make_value(fn) @property def functions(self): """All functions in this module.""" - return map(Function, self._ptr.list_functions()) + return map(_make_value, self._ptr.list_functions()) def verify(self): """Verify module. @@ -498,7 +533,7 @@ class Module(llvm.Wrapper): return fileobj.getvalue() def _get_id(self): - return self._ptr.getModuleIdentifier(self._ptr) + return self._ptr.getModuleIdentifier() def _set_id(self, string): self._ptr.setModuleIdentifier(string) @@ -506,13 +541,18 @@ class Module(llvm.Wrapper): id = property(_get_id, _set_id) def _to_native_something(self, fileobj, cgft): - ret = False - if fileobj is None: - ret = True - fileobj = StringIO() + cgft = api.llvm.TargetMachine.CodeGenFileType.CGFT_AssemblyFile cgft = api.llvm.TargetMachine.CodeGenFileType.CGFT_ObjectFile - failed = tm.addPassesToEmitFile(pm, formatted, cgft, False) + + from llvm.ee import TargetMachine + from llvm.passes import PassManager + from llvmpy import extra + tm = TargetMachine.new()._ptr + pm = PassManager.new()._ptr + formatted + failed = tm.addPassesToEmitFile(pm, fileobj, cgft, False) + if failed: raise llvm.LLVMException("Failed to write native object file") if ret: @@ -525,8 +565,16 @@ class Module(llvm.Wrapper): If a fileobj is given, the output is written to it; Otherwise, the output is returned ''' - CGFT = api.llvm.TargetMachine.CodeGenFileType - return self._to_native_something(fileobj, CGFT.CGFT_ObjectFile) + ret = False + if fileobj is None: + ret = True + fileobj = StringIO() + from llvm.ee import TargetMachine + tm = TargetMachine.new() + fileobj.write(tm.emit_object(self)) + if ret: + return fileobj.getvalue() + def to_native_assembly(self, fileobj=None): '''Outputs the byte string of the module as native assembly code @@ -534,17 +582,27 @@ class Module(llvm.Wrapper): If a fileobj is given, the output is written to it; Otherwise, the output is returned ''' - CGFT = api.llvm.TargetMachine.CodeGenFileType - return self._to_native_something(fileobj, CGFT.CGFT_AssemblyFile) + ret = False + if fileobj is None: + ret = True + fileobj = StringIO() + from llvm.ee import TargetMachine + tm = TargetMachine.new() + fileobj.write(tm.emit_assembly(self)) + if ret: + return fileobj.getvalue() + def get_or_insert_named_metadata(self, name): - return NamedMetadata(self._ptr.getOrInsertNamedMetadata(name)) + return NamedMetaData(self._ptr.getOrInsertNamedMetadata(name)) def get_named_metadata(self, name): - return NamedMetadata(self._ptr.get_named_metadata(name)) + md = self._ptr.getNamedMetadata(name) + if md: + return NamedMetaData(md) def clone(self): - return NamedMetadata(api.llvm.CloneModule(self._ptr)) + return Module(api.llvm.CloneModule(self._ptr)) class Type(llvm.Wrapper): """Represents a type, like a 32-bit integer or an 80-bit x86 float. @@ -552,6 +610,11 @@ class Type(llvm.Wrapper): Use one of the static methods to create an instance. Example: ty = Type.double() """ + _type_ = api.llvm.Type + + def __init__(self, ptr): + ptr = ptr._downcast(type(self)._type_) + super(Type, self).__init__(ptr) @staticmethod def int(bits=32): @@ -614,6 +677,8 @@ class Type(llvm.Wrapper): def opaque(name): """Create a opaque StructType""" context = api.llvm.getGlobalContext() + if not name: + raise llvm.LLVMException("Opaque type must have a non-empty name") ptr = api.llvm.StructType.create(context, name) return StructType(ptr) @@ -629,8 +694,15 @@ class Type(llvm.Wrapper): otherwise, creates a literal type.""" context = api.llvm.getGlobalContext() is_packed = False - ptr = api.llvm.StructType.create(context) - ptr.setBody(_extract_ptrs(element_tys), is_packed) + if name: + ptr = api.llvm.StructType.create(context, name) + ptr.setBody(llvm._extract_ptrs(element_tys), is_packed) + else: + ptr = api.llvm.StructType.get(context, + llvm._extract_ptrs(element_tys), + is_packed) + + return StructType(ptr) @staticmethod @@ -646,7 +718,7 @@ class Type(llvm.Wrapper): context = api.llvm.getGlobalContext() is_packed = True ptr = api.llvm.StructType.create(context) - ptr.setBody(_extract_ptrs(element_tys), is_packed) + ptr.setBody(llvm._extract_ptrs(element_tys), is_packed) return StructType(ptr) @staticmethod @@ -723,6 +795,7 @@ class Type(llvm.Wrapper): class IntegerType(Type): """Represents an integer type.""" + _type_ = api.llvm.IntegerType @property def width(self): @@ -731,6 +804,7 @@ class IntegerType(Type): class FunctionType(Type): """Represents a function type.""" + _type_ = api.llvm.FunctionType @property def return_type(self): @@ -746,7 +820,7 @@ class FunctionType(Type): def args(self): """An iterable that yields Type objects, representing the types of the arguments accepted by this function, in order.""" - tys = [Type(self._ptr.getParamType(i)) for i in range(self.arg_count)] + return [Type(self._ptr.getParamType(i)) for i in range(self.arg_count)] @property def arg_count(self): @@ -759,6 +833,7 @@ class FunctionType(Type): class StructType(Type): """Represents a structure type.""" + _type_ = api.llvm.StructType @property def element_count(self): @@ -798,18 +873,19 @@ class StructType(Type): @property def is_literal(self): - return self.isLiteral() + return self._ptr.isLiteral() @property def is_identified(self): - return not self.is_literal() + return not self.is_literal @property def is_opaque(self): - return self.isOpaque() + return self._ptr.isOpaque() class ArrayType(Type): """Represents an array type.""" + _type_ = api.llvm.ArrayType @property def element(self): @@ -820,6 +896,7 @@ class ArrayType(Type): return self._ptr.getNumElements() class PointerType(Type): + _type_ = api.llvm.PointerType @property def pointee(self): @@ -830,7 +907,8 @@ class PointerType(Type): return self._ptr.getAddressSpace() class VectorType(Type): - + _type_ = api.llvm.VectorType + @property def element(self): return self._ptr.getVectorElementType() @@ -840,6 +918,34 @@ class VectorType(Type): return self._ptr.getNumElements() class Value(llvm.Wrapper): + _type_ = api.llvm.Value + + + def __init__(self, builder, ptr): + assert builder is _ValueFactory + + if type(self._type_) is type: + if isinstance(ptr, self._type_): # is not downcast + casted = ptr + else: + casted = ptr._downcast(self._type_) + else: + try: + for ty in self._type_: + if isinstance(ptr, ty): # is not downcast + casted = ptr + else: + try: + casted = ptr._downcast(ty) + except ValueError: + pass + else: + break + else: + casted = ptr + except TypeError: + casted = ptr + super(Value, self).__init__(casted) def __str__(self): return str(self._ptr) @@ -875,9 +981,10 @@ class Value(llvm.Wrapper): @property def uses(self): - return map(User, self._ptr.list_use()) + return map(_make_value, self._ptr.list_use()) class User(Value): + _type_ = api.llvm.User @property def operand_count(self): @@ -886,193 +993,198 @@ class User(Value): @property def operands(self): """Yields operands of this instruction.""" - return [Value(self._ptr.getOperand(i)) + return [_make_value(self._ptr.getOperand(i)) for i in range(self.operand_count)] - def _get_operand(self, i): - return _make_value(_core.LLVMUserGetOperand(self._ptr, i)) class Constant(User): + _type_ = api.llvm.Constant @staticmethod def null(ty): - return Value(api.llvm.Constant.getNullValue(ty._ptr)) + return _make_value(api.llvm.Constant.getNullValue(ty._ptr)) @staticmethod def all_ones(ty): - return Value(api.llvm.Constant.getAllOnesValue(ty._ptr)) + return _make_value(api.llvm.Constant.getAllOnesValue(ty._ptr)) @staticmethod def undef(ty): - return Value(api.llvm.UndefValue.get(ty._ptr)) + return _make_value(api.llvm.UndefValue.get(ty._ptr)) @staticmethod def int(ty, value): - return Value(api.llvm.ConstantInt.get(ty._ptr, value, False)) + return _make_value(api.llvm.ConstantInt.get(ty._ptr, int(value), False)) @staticmethod def int_signextend(ty, value): - return Value(api.llvm.ConstantInt.get(ty._ptr, value, True)) + return _make_value(api.llvm.ConstantInt.get(ty._ptr, int(value), True)) @staticmethod def real(ty, value): - return Value(api.llvm.ConstantFP.get(ty._ptr, value)) + return _make_value(api.llvm.ConstantFP.get(ty._ptr, float(value))) @staticmethod def string(strval): # dont_null_terminate=True - return Value(api.llvm.ConstantDataArray.getString(strval, False)) + cxt = api.llvm.getGlobalContext() + return _make_value(api.llvm.ConstantDataArray.getString(cxt, strval, False)) @staticmethod def stringz(strval): # dont_null_terminate=False - return Value(api.llvm.ConstantDataArray.getString(strval, True)) + cxt = api.llvm.getGlobalContext() + return _make_value(api.llvm.ConstantDataArray.getString(cxt, strval, True)) @staticmethod def array(ty, consts): - return Value(api.llvm.ConstantArray.get(ty._ptr, consts)) + aryty = Type.array(ty, len(consts)) + return _make_value(api.llvm.ConstantArray.get(aryty._ptr, + llvm._extract_ptrs(consts))) @staticmethod def struct(consts): # not packed - return Value(api.llvm.ConstantStruct.getAnon(llvm._extract_ptrs(consts), + return _make_value(api.llvm.ConstantStruct.getAnon(llvm._extract_ptrs(consts), False)) @staticmethod def packed_struct(consts): - return Value(api.llvm.ConstantStruct.getAnon(llvm._extract_ptrs(consts), + return _make_value(api.llvm.ConstantStruct.getAnon(llvm._extract_ptrs(consts), False)) @staticmethod def vector(consts): - return Value(api.llvm.ConstantVector.get(llvm._extract_ptrs(consts))) + return _make_value(api.llvm.ConstantVector.get(llvm._extract_ptrs(consts))) @staticmethod def sizeof(ty): - return Value(api.llvm.ConstantExpr.getSizeOf(ty._ptr)) + return _make_value(api.llvm.ConstantExpr.getSizeOf(ty._ptr)) def neg(self): - return Value(api.llvm.ConstantExpr.getNeg(self._ptr)) + return _make_value(api.llvm.ConstantExpr.getNeg(self._ptr)) def not_(self): - return Value(api.llvm.ConstantExpr.getNot(self._ptr)) + return _make_value(api.llvm.ConstantExpr.getNot(self._ptr)) def add(self, rhs): - return Value(api.llvm.ConstantExpr.getAdd(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getAdd(self._ptr, rhs._ptr)) def fadd(self, rhs): - return Value(api.llvm.ConstantExpr.getFAdd(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getFAdd(self._ptr, rhs._ptr)) def sub(self, rhs): - return Value(api.llvm.ConstantExpr.getSub(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getSub(self._ptr, rhs._ptr)) def fsub(self, rhs): - return Value(api.llvm.ConstantExpr.getFSub(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getFSub(self._ptr, rhs._ptr)) def mul(self, rhs): - return Value(api.llvm.ConstantExpr.getMul(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getMul(self._ptr, rhs._ptr)) def fmul(self, rhs): - return Value(api.llvm.ConstantExpr.getFMul(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getFMul(self._ptr, rhs._ptr)) def udiv(self, rhs): - return Value(api.llvm.ConstantExpr.getUDiv(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getUDiv(self._ptr, rhs._ptr)) def sdiv(self, rhs): - return Value(api.llvm.ConstantExpr.getSDiv(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getSDiv(self._ptr, rhs._ptr)) def fdiv(self, rhs): - return Value(api.llvm.ConstantExpr.getFDiv(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getFDiv(self._ptr, rhs._ptr)) def urem(self, rhs): - return Value(api.llvm.ConstantExpr.getURem(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getURem(self._ptr, rhs._ptr)) def srem(self, rhs): - return Value(api.llvm.ConstantExpr.getSRem(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getSRem(self._ptr, rhs._ptr)) def frem(self, rhs): - return Value(api.llvm.ConstantExpr.getFRem(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getFRem(self._ptr, rhs._ptr)) def and_(self, rhs): - return Value(api.llvm.ConstantExpr.getAnd(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getAnd(self._ptr, rhs._ptr)) def or_(self, rhs): - return Value(api.llvm.ConstantExpr.getOr(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getOr(self._ptr, rhs._ptr)) def xor(self, rhs): - return Value(api.llvm.ConstantExpr.getXor(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getXor(self._ptr, rhs._ptr)) def icmp(self, int_pred, rhs): - return Value(api.llvm.ConstantExpr.getICmp(int_pred, self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getICmp(int_pred, self._ptr, rhs._ptr)) def fcmp(self, real_pred, rhs): - return Value(api.llvm.ConstantExpr.getFCmp(real_pred, self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getFCmp(real_pred, self._ptr, rhs._ptr)) def shl(self, rhs): - return Value(api.llvm.ConstantExpr.getShl(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getShl(self._ptr, rhs._ptr)) def lshr(self, rhs): - return Value(api.llvm.ConstantExpr.getLShr(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getLShr(self._ptr, rhs._ptr)) def ashr(self, rhs): - return Value(api.llvm.ConstantExpr.getAShr(self._ptr, rhs._ptr)) + return _make_value(api.llvm.ConstantExpr.getAShr(self._ptr, rhs._ptr)) def gep(self, indices): indices = llvm._extract_ptrs(indices) - return Value(api.llvm.ConstantExpr.getGetElementPtr(self._ptr, indices)) + return _make_value(api.llvm.ConstantExpr.getGetElementPtr(self._ptr, indices)) def trunc(self, ty): - return Value(api.llvm.ConstantExpr.getTrunc(self._ptr, ty)) + return _make_value(api.llvm.ConstantExpr.getTrunc(self._ptr, ty._ptr)) def sext(self, ty): - return Value(api.llvm.ConstantExpr.getSExt(self._ptr, ty)) + return _make_value(api.llvm.ConstantExpr.getSExt(self._ptr, ty._ptr)) def zext(self, ty): - return Value(api.llvm.ConstantExpr.getZExt(self._ptr, ty)) + return _make_value(api.llvm.ConstantExpr.getZExt(self._ptr, ty._ptr)) def fptrunc(self, ty): - return Value(api.llvm.ConstantExpr.getFPTrunc(self._ptr, ty)) + return _make_value(api.llvm.ConstantExpr.getFPTrunc(self._ptr, ty._ptr)) def fpext(self, ty): - return Value(api.llvm.ConstantExpr.getFPExtend(self._ptr, ty)) + return _make_value(api.llvm.ConstantExpr.getFPExtend(self._ptr, ty._ptr)) def uitofp(self, ty): - return Value(api.llvm.ConstantExpr.getUIToFP(self._ptr, ty)) + return _make_value(api.llvm.ConstantExpr.getUIToFP(self._ptr, ty._ptr)) def sitofp(self, ty): - return Value(api.llvm.ConstantExpr.getSIToFP(self._ptr, ty)) + return _make_value(api.llvm.ConstantExpr.getSIToFP(self._ptr, ty._ptr)) def fptoui(self, ty): - return Value(api.llvm.ConstantExpr.getFPToUI(self._ptr, ty)) + return _make_value(api.llvm.ConstantExpr.getFPToUI(self._ptr, ty._ptr)) def fptosi(self, ty): - return Value(api.llvm.ConstantExpr.getFPToSI(self._ptr, ty)) + return _make_value(api.llvm.ConstantExpr.getFPToSI(self._ptr, ty._ptr)) def ptrtoint(self, ty): - return Value(api.llvm.ConstantExpr.getPtrToInt(self._ptr, ty)) + return _make_value(api.llvm.ConstantExpr.getPtrToInt(self._ptr, ty._ptr)) def inttoptr(self, ty): - return Value(api.llvm.ConstantExpr.getIntToPtr(self._ptr, ty)) + return _make_value(api.llvm.ConstantExpr.getIntToPtr(self._ptr, ty._ptr)) def bitcast(self, ty): - return Value(api.llvm.ConstantExpr.getBitCast(self._ptr, ty)) + return _make_value(api.llvm.ConstantExpr.getBitCast(self._ptr, ty._ptr)) def select(self, true_const, false_const): - return Value(api.llvm.ConstantExpr.getSelect(self._ptr, + return _make_value(api.llvm.ConstantExpr.getSelect(self._ptr, true_const._ptr, false_const._ptr)) def extract_element(self, index): # note: self must be a _vector_ constant - return Value(api.llvm.ConstantExpr.getExtractElement(self._ptr, index._ptr)) + return _make_value(api.llvm.ConstantExpr.getExtractElement(self._ptr, index._ptr)) def insert_element(self, value, index): - return Value(api.llvm.ConstantExpr.getExtractElement(self._ptr, + return _make_value(api.llvm.ConstantExpr.getExtractElement(self._ptr, value._ptr, index._ptr)) def shuffle_vector(self, vector_b, mask): - return Value(api.llvm.ConstantExpr.getShuffleVector(self._ptr, + return _make_value(api.llvm.ConstantExpr.getShuffleVector(self._ptr, vector_b._ptr, mask._ptr)) class ConstantExpr(Constant): + _type_ = api.llvm.ConstantExpr + @property def opcode(self): return self._ptr.getOpcode() @@ -1094,6 +1206,8 @@ class ConstantDataVector(Constant): class ConstantInt(Constant): + _type_ = api.llvm.ConstantInt + @property def z_ext_value(self): '''Obtain the zero extended value for an integer constant value.''' @@ -1130,8 +1244,8 @@ class ConstantPointerNull(Constant): class UndefValue(Constant): pass - class GlobalValue(Constant): + _type_ = api.llvm.GlobalValue def _get_linkage(self): return self._ptr.getLinkage() @@ -1176,6 +1290,7 @@ class GlobalValue(Constant): class GlobalVariable(GlobalValue): + _type_ = api.llvm.GlobalVariable @staticmethod def new(module, ty, name, addrspace=0): @@ -1183,7 +1298,7 @@ class GlobalVariable(GlobalValue): external_linkage = linkage.ExternalLinkage tlmode = api.llvm.GlobalVariable.ThreadLocalMode not_threadlocal = tlmode.NotThreadLocal - gv = api.llvm.GlobalVariablel.new(module._ptr, + gv = api.llvm.GlobalVariable.new(module._ptr, ty._ptr, False, # is constant external_linkage, @@ -1192,22 +1307,23 @@ class GlobalVariable(GlobalValue): None, # insert before not_threadlocal, addrspace) - return GlobalVariable(gv) + return _make_value(gv) @staticmethod def get(module, name): - gv = GlobalVariable(module._ptr.getNamedGlobal(name)) + gv = _make_value(module._ptr.getNamedGlobal(name)) if not gv: llvm.LLVMException("no global named `%s`" % name) return gv def delete(self): + _ValueFactory.delete(self._ptr) self._ptr.eraseFromParent() def _get_initializer(self): if not self._ptr.hasInitializer(): return None - return Constant(self._ptr.getInitializer()) + return _make_value(self._ptr.getInitializer()) def _set_initializer(self, const): self._ptr.setInitializer(const._ptr) @@ -1235,21 +1351,25 @@ class GlobalVariable(GlobalValue): thread_local = property(_get_thread_local, _set_thread_local) class Argument(Value): + _type_ = api.llvm.Argument def add_attribute(self, attr): - attrbldr = api.llvm.AttrBuilder() + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() attrbldr.addAttribute(attr) attrs = api.llvm.Attributes.get(context, attrbldr) self._ptr.addAttr(attrs) def remove_attribute(self, attr): - attrbldr = api.llvm.AttrBuilder() + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() attrbldr.addAttribute(attr) attrs = api.llvm.Attributes.get(context, attrbldr) self._ptr.removeAttr(attrs) def _set_alignment(self, align): - attrbldr = api.llvm.AttrBuilder() + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() attrbldr.addAlignmentAttr(align) attrs = api.llvm.Attributes.get(context, attrbldr) self._ptr.addAttr(attrs) @@ -1261,6 +1381,7 @@ class Argument(Value): _set_alignment) class Function(GlobalValue): + _type_ = api.llvm.Function @staticmethod def new(module, func_ty, name): @@ -1277,11 +1398,12 @@ class Function(GlobalValue): @staticmethod def intrinsic(module, intrinsic_id, types): fn = api.llvm.Intrinsic.getDeclaration(module._ptr, - intrinsic_id, - types) - return Function(fn) + intrinsic_id, + llvm._extract_ptrs(types)) + return _make_value(fn) def delete(self): + _ValueFactory.delete(self._ptr) self._ptr.eraseFromParent() @property @@ -1310,13 +1432,14 @@ class Function(GlobalValue): def _set_does_not_throw(self,value): assert value - self._ptr.setDoesNotThow() + self._ptr.setDoesNotThrow() does_not_throw = property(_get_does_not_throw, _set_does_not_throw) @property def args(self): - return self._ptr.getArgumentList() + args = self._ptr.getArgumentList() + return map(_make_value, args) @property def basic_block_count(self): @@ -1324,25 +1447,27 @@ class Function(GlobalValue): @property def entry_basic_block(self): - return self._ptr.getEntryBlock() + assert self.basic_block_count + return _make_value(self._ptr.getEntryBlock()) def append_basic_block(self, name): context = api.llvm.getGlobalContext() bb = api.llvm.BasicBlock.Create(context, name, self._ptr, None) - return BasicBlock(bb) + return _make_value(bb) @property def basic_blocks(self): - return self._ptr.getBasicBlockList() + return map(_make_value, self._ptr.getBasicBlockList()) def viewCFG(self): return self._ptr.viewCFG() def add_attribute(self, attr): - _core.LLVMAddFunctionAttr(self._ptr, attr) + self._ptr.addFnAttr(attr) def remove_attribute(self, attr): - attrbldr = api.llvm.AttrBuilder() + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() attrbldr.addAttribute(attr) attrs = api.llvm.Attributes.get(context, attrbldr) self._ptr.removeFnAttr(attrs) @@ -1356,25 +1481,30 @@ class Function(GlobalValue): # Note: LLVM has a bug in preverifier that will always abort # the process upon failure. - return api.llvm.verifyFunction() + actions = api.llvm.VerifierFailureAction + return api.llvm.verifyFunction(self._ptr, actions.PrintMessageAction) #===----------------------------------------------------------------------=== # InlineAsm #===----------------------------------------------------------------------=== class InlineAsm(Value): + _type_ = api.llvm.InlineAsm + @staticmethod def get(functype, asm, constrains, side_effect=False, align_stack=False, dialect=api.llvm.InlineAsm.AsmDialect.AD_ATT): - ilasm = api.llvm.InlineAsm.get(functype._ptr, asm, contrains, side_effect, - align_stack, dialect) - return InlineAsm(ilasm) + ilasm = api.llvm.InlineAsm.get(functype._ptr, asm, constrains, + side_effect, align_stack, dialect) + return _make_value(ilasm) #===----------------------------------------------------------------------=== # MetaData #===----------------------------------------------------------------------=== class MetaData(Value): + _type_ = api.llvm.MDNode + @staticmethod def get(module, values): ''' @@ -1382,13 +1512,15 @@ class MetaData(Value): ''' context = api.llvm.getGlobalContext() ptr = api.llvm.MDNode.get(context, llvm._extract_ptrs(values)) - return MetaData(ptr) + return _make_value(ptr) @staticmethod def get_named_operands(module, name): - namedmd = module.get_named_metadata(name)._ptr - return [MetaData(namedmd.getOperand(i)) - for i in namedmd.getNumOperands()] + namedmd = module.get_named_metadata(name) + if not namedmd: + return [] + return [_make_value(namedmd._ptr.getOperand(i)) + for i in range(namedmd._ptr.getNumOperands())] @staticmethod def add_named_operand(module, name, operand): @@ -1397,20 +1529,28 @@ class MetaData(Value): @property def operand_count(self): - return self._ptr.getOperand() + return self._ptr.getNumOperands() @property def operands(self): """Yields operands of this metadata.""" - return [Value(self._ptr.getOperand(i)) for i in self.operand_count] - + res = [] + for i in range(self.operand_count): + op = self._ptr.getOperand(i) + if op is None: + res.append(None) + else: + res.append(_make_value(op)) + return res class MetaDataString(Value): + _type_ = api.llvm.MDString + @staticmethod def get(module, s): context = api.llvm.getGlobalContext() ptr = api.llvm.MDString.get(context, s) - return MetaDataString(ptr) + return _make_value(ptr) @property def string(self): @@ -1419,6 +1559,7 @@ class MetaDataString(Value): class NamedMetaData(llvm.Wrapper): + @staticmethod def get_or_insert(mod, name): return mod.get_or_insert_named_metadata(name) @@ -1446,10 +1587,11 @@ class NamedMetaData(llvm.Wrapper): #===----------------------------------------------------------------------=== class Instruction(User): + _type_ = api.llvm.Instruction @property def basic_block(self): - return BasicBlock(self._ptr.getParent()) + return _make_value(self._ptr.getParent()) @property def is_terminator(self): @@ -1517,6 +1659,7 @@ class Instruction(User): class CallOrInvokeInstruction(Instruction): + _type_ = api.llvm.CallInst, api.llvm.InvokeInst def _get_cc(self): return self._ptr.getCallingConv() @@ -1527,19 +1670,22 @@ class CallOrInvokeInstruction(Instruction): calling_convention = property(_get_cc, _set_cc) def add_parameter_attribute(self, idx, attr): - attrbldr = api.llvm.AttrBuilder() + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() attrbldr.addAttribute(attr) attrs = api.llvm.Attributes.get(context, attrbldr) self._ptr.addAttribute(idx, attrs) def remove_parameter_attribute(self, idx, attr): - attrbldr = api.llvm.AttrBuilder() + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() attrbldr.addAttribute(attr) attrs = api.llvm.Attributes.get(context, attrbldr) self._ptr.removeAttribute(idx, attrs) def set_parameter_alignment(self, idx, align): - attrbldr = api.llvm.AttrBuilder() + context = api.llvm.getGlobalContext() + attrbldr = api.llvm.AttrBuilder.new() attrbldr.addAlignmentAttr(align) attrs = api.llvm.Attributes.get(context, attrbldr) self._ptr.addAttribute(idx, attrs) @@ -1547,7 +1693,7 @@ class CallOrInvokeInstruction(Instruction): def _get_called_function(self): function = self._ptr.getCalledFunction() if function: # Return value can be None on indirect call/invoke - return Value(function) + return _make_value(function) def _set_called_function(self, function): self._ptr.setCalledFunction(function) @@ -1556,6 +1702,7 @@ class CallOrInvokeInstruction(Instruction): class PHINode(Instruction): + _type_ = api.llvm.PHINode @property def incoming_count(self): @@ -1565,10 +1712,10 @@ class PHINode(Instruction): self._ptr.addIncoming(value._ptr, block._ptr) def get_incoming_value(self, idx): - return self._ptr.getIncomingValue(idx) + return _make_value(self._ptr.getIncomingValue(idx)) def get_incoming_block(self, idx): - return self._ptr.getIncomingBlock(idx) + return _make_value(self._ptr.getIncomingBlock(idx)) class SwitchInstruction(Instruction): @@ -1582,36 +1729,108 @@ class CompareInstruction(Instruction): @property def predicate(self): return self._ptr.getPredicate() - - #===----------------------------------------------------------------------=== # Basic block #===----------------------------------------------------------------------=== class BasicBlock(Value): + _type_ = api.llvm.BasicBlock def insert_before(self, name): context = api.llvm.getGlobalContext() ptr = api.llvm.BasicBlock.Create(context, name, self.function._ptr, self._ptr) - return BasicBlock(ptr) + return _make_value(ptr) def delete(self): + _ValueFactory.delete(self._ptr) self._ptr.eraseFromParent() @property def function(self): - return Function(self._ptr.getParent()) + return _make_value(self._ptr.getParent()) @property def instructions(self): - return map(Value, self._ptr.getInstList()) + return map(_make_value, self._ptr.getInstList()) +#===----------------------------------------------------------------------=== +# Value factory method +#===----------------------------------------------------------------------=== + + +class _ValueFactory(object): + cache = weakref.WeakValueDictionary() + + # value ID -> class map + class_for_valueid = { + VALUE_ARGUMENT : Argument, + VALUE_BASIC_BLOCK : BasicBlock, + VALUE_FUNCTION : Function, + VALUE_GLOBAL_ALIAS : GlobalValue, + VALUE_GLOBAL_VARIABLE : GlobalVariable, + VALUE_UNDEF_VALUE : UndefValue, + VALUE_CONSTANT_EXPR : ConstantExpr, + VALUE_CONSTANT_AGGREGATE_ZERO : ConstantAggregateZero, + VALUE_CONSTANT_DATA_ARRAY : ConstantDataArray, + VALUE_CONSTANT_DATA_VECTOR : ConstantDataVector, + VALUE_CONSTANT_INT : ConstantInt, + VALUE_CONSTANT_FP : ConstantFP, + VALUE_CONSTANT_ARRAY : ConstantArray, + VALUE_CONSTANT_STRUCT : ConstantStruct, + VALUE_CONSTANT_VECTOR : ConstantVector, + VALUE_CONSTANT_POINTER_NULL : ConstantPointerNull, + VALUE_MD_NODE : MetaData, + VALUE_MD_STRING : MetaDataString, + VALUE_INLINE_ASM : InlineAsm, + VALUE_INSTRUCTION + OPCODE_PHI : PHINode, + VALUE_INSTRUCTION + OPCODE_CALL : CallOrInvokeInstruction, + VALUE_INSTRUCTION + OPCODE_INVOKE : CallOrInvokeInstruction, + VALUE_INSTRUCTION + OPCODE_SWITCH : SwitchInstruction, + VALUE_INSTRUCTION + OPCODE_ICMP : CompareInstruction, + VALUE_INSTRUCTION + OPCODE_FCMP : CompareInstruction + } + + @classmethod + def build(cls, ptr): + # try to look in the cache + addr = ptr._capsule.pointer + try: + obj = cls.cache[addr] + return obj + except KeyError: + pass + # find class by value id + id = ptr.getValueID() + ctorcls = cls.class_for_valueid.get(id) + if not ctorcls: + if id > VALUE_INSTRUCTION: # "generic" instruction + ctorcls = Instruction + else: # "generic" value + ctorcls = Value + # cache the obj + obj = ctorcls(_ValueFactory, ptr) + cls.cache[addr] = obj + return obj + + @classmethod + def delete(cls, ptr): + del cls.cache[ptr._capsule.pointer] + +def _make_value(ptr): + return _ValueFactory.build(ptr) #===----------------------------------------------------------------------=== # Builder #===----------------------------------------------------------------------=== +_atomic_orderings = { 'unordered' : api.llvm.AtomicOrdering.Unordered, + 'monotonic' : api.llvm.AtomicOrdering.Monotonic, + 'acquire' : api.llvm.AtomicOrdering.Acquire, + 'release' : api.llvm.AtomicOrdering.Release, + 'acq_rel' : api.llvm.AtomicOrdering.AcquireRelease, + 'seq_cst' : api.llvm.AtomicOrdering.SequentiallyConsistent} + class Builder(llvm.Wrapper): @staticmethod @@ -1628,7 +1847,7 @@ class Builder(llvm.Wrapper): # Instruction list won't be long anyway, # Does not matter much to build a list of all instructions - instrs = bblk._ptr.getInstList() + instrs = bblk.instructions if instrs: self.position_before(instrs[0]) else: @@ -1650,150 +1869,163 @@ class Builder(llvm.Wrapper): @property def basic_block(self): """The basic block where the builder is positioned.""" - return BasicBlock(self._ptr.GetInsertBlock()) + return _make_value(self._ptr.GetInsertBlock()) # terminator instructions + def _guard_terminators(self): + if __debug__: + import warnings + for instr in self.basic_block.instructions: + if instr.is_terminator: + warnings.warn("BasicBlock can only have one terminator") def ret_void(self): - return Value(self._ptr.CreateRetVoid()) + self._guard_terminators() + return _make_value(self._ptr.CreateRetVoid()) def ret(self, value): - return Value(self._ptr.CreateRet(value._ptr)) + self._guard_terminators() + return _make_value(self._ptr.CreateRet(value._ptr)) def ret_many(self, values): + self._guard_terminators() values = llvm._extract_ptrs(values) - return Value(self._ptr.CreateAggregateRet(values, len(values))) + return _make_value(self._ptr.CreateAggregateRet(values, len(values))) def branch(self, bblk): - if __debug__: - for instr in self.basic_block.instructions: - assert not instr.is_terminator, "BasicBlock can only have one terminator" - return Value(self._ptr.CreateBr(bblk._ptr)) + self._guard_terminators() + return _make_value(self._ptr.CreateBr(bblk._ptr)) def cbranch(self, if_value, then_blk, else_blk): - return Value(self._ptr.CreateCondBr(if_value._ptr, + self._guard_terminators() + return _make_value(self._ptr.CreateCondBr(if_value._ptr, then_blk._ptr, else_blk._ptr)) def switch(self, value, else_blk, n=10): - return Value(self._ptr.CreateSwitch(self.value._ptr, - self.else_blk._ptr, - n)) + self._guard_terminators() + return _make_value(self._ptr.CreateSwitch(value._ptr, + else_blk._ptr, + n)) def invoke(self, func, args, then_blk, catch_blk, name=""): - return Value(self._ptr.CreateInvoke(self.func._ptr, - self.then_blk._ptr, - self.catch_blk._ptr, - args)) + self._guard_terminators() + return _make_value(self._ptr.CreateInvoke(func._ptr, + then_blk._ptr, + catch_blk._ptr, + llvm._extract_ptrs(args))) def unreachable(self): - return Value(self._ptr.CreateUnreachable()) + self._guard_terminators() + return _make_value(self._ptr.CreateUnreachable()) # arithmethic, bitwise and logical def add(self, lhs, rhs, name=""): - return Value(self._ptr.CreateAdd(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateAdd(lhs._ptr, rhs._ptr, name)) def fadd(self, lhs, rhs, name=""): - return Value(self._ptr.CreateFAdd(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateFAdd(lhs._ptr, rhs._ptr, name)) def sub(self, lhs, rhs, name=""): - return Value(self._ptr.CreateSub(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateSub(lhs._ptr, rhs._ptr, name)) def fsub(self, lhs, rhs, name=""): - return Value(self._ptr.CreateFSub(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateFSub(lhs._ptr, rhs._ptr, name)) def mul(self, lhs, rhs, name=""): - return Value(self._ptr.CreateMul(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateMul(lhs._ptr, rhs._ptr, name)) def fmul(self, lhs, rhs, name=""): - return Value(self._ptr.CreateFMul(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateFMul(lhs._ptr, rhs._ptr, name)) def udiv(self, lhs, rhs, name=""): - return Value(self._ptr.CreateUDiv(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateUDiv(lhs._ptr, rhs._ptr, name)) def sdiv(self, lhs, rhs, name=""): - return Value(self._ptr.CreateSDiv(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateSDiv(lhs._ptr, rhs._ptr, name)) def fdiv(self, lhs, rhs, name=""): - return Value(self._ptr.CreateFDiv(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateFDiv(lhs._ptr, rhs._ptr, name)) def urem(self, lhs, rhs, name=""): - return Value(self._ptr.CreateURem(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateURem(lhs._ptr, rhs._ptr, name)) def srem(self, lhs, rhs, name=""): - return Value(self._ptr.CreateSRem(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateSRem(lhs._ptr, rhs._ptr, name)) def frem(self, lhs, rhs, name=""): - return Value(self._ptr.CreateFRem(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateFRem(lhs._ptr, rhs._ptr, name)) def shl(self, lhs, rhs, name=""): - return Value(self._ptr.CreateShl(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateShl(lhs._ptr, rhs._ptr, name)) def lshr(self, lhs, rhs, name=""): - return Value(self._ptr.CreateLShr(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateLShr(lhs._ptr, rhs._ptr, name)) def ashr(self, lhs, rhs, name=""): - return Value(self._ptr.CreateAShr(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateAShr(lhs._ptr, rhs._ptr, name)) def and_(self, lhs, rhs, name=""): - return Value(self._ptr.CreateAnd(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateAnd(lhs._ptr, rhs._ptr, name)) def or_(self, lhs, rhs, name=""): - return Value(self._ptr.CreateOr(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateOr(lhs._ptr, rhs._ptr, name)) def xor(self, lhs, rhs, name=""): - return Value(self._ptr.CreateXor(lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateXor(lhs._ptr, rhs._ptr, name)) def neg(self, val, name=""): - return Value(self._ptr.CreateNeg(val._ptr, name)) + return _make_value(self._ptr.CreateNeg(val._ptr, name)) def not_(self, val, name=""): - return Value(self._ptr.CreateNot(val._ptr, name)) + return _make_value(self._ptr.CreateNot(val._ptr, name)) # memory def malloc(self, ty, name=""): context = api.llvm.getGlobalContext() - intty = api.llvm.Type.getInt32Ty(context) - sizeof = api.llvm.ConstantExpr.getSizeOf(ty) - zero = api.llvm.ConstantInt.get(intty, 0) - # XXX: how do I know when to insert? - # assume to end of block for now - inst = api.llvm.CallInst.CreateMalloc(self.basic_block._ptr, - intty, - ty._ptr, - sizeof, - zero, - None, - name) - return Value(inst) - + allocsz = api.llvm.ConstantExpr.getSizeOf(ty._ptr) + ity = allocsz.getType() + malloc = api.llvm.CallInst.CreateMalloc(self.basic_block._ptr, + ity, + ty._ptr, + allocsz, + None, + None, + "") + inst = self._ptr.Insert(malloc, name) + return _make_value(inst) + def malloc_array(self, ty, size, name=""): - sizeof = api.llvm.ConstantExpr.getSizeOf(ty) - # XXX: how do I know when to insert? - # assume to end of block for now - inst = api.llvm.CallInst.CreateMalloc(self.basic_block._ptr, - size.type._ptr, - ty._ptr, - sizeof, - size._ptr, - None, - name) - return Value(inst) + context = api.llvm.getGlobalContext() + allocsz = api.llvm.ConstantExpr.getSizeOf(ty._ptr) + ity = allocsz.getType() + malloc = api.llvm.CallInst.CreateMalloc(self.basic_block._ptr, + ity, + ty._ptr, + allocsz, + size._ptr, + None, + "") + inst = self._ptr.Insert(malloc, name) + return _make_value(inst) def alloca(self, ty, name=""): - zero = api.llvm.ConstantInt.get(intty, 0) - return Value(self._ptr.CreateAlloca(ty._ptr, zero, name)) + intty = Type.int() + zero = api.llvm.ConstantInt.get(intty._ptr, 0) + return _make_value(self._ptr.CreateAlloca(ty._ptr, zero, name)) def alloca_array(self, ty, size, name=""): - return Value(self._ptr.CreateAlloca(ty._ptr, size._ptr, name)) + return _make_value(self._ptr.CreateAlloca(ty._ptr, size._ptr, name)) def free(self, ptr): - return Value(api.llvm.CallInst.CreateFree(ptr._ptr, self.basic_block._ptr)) + free = api.llvm.CallInst.CreateFree(ptr._ptr, self.basic_block._ptr) + inst = self._ptr.Insert(free) + return _make_value(inst) def load(self, ptr, name="", align=0, volatile=False, invariant=False): - inst = Value(self._ptr.CreateLoad(ptr._ptr, name)) + inst = _make_value(self._ptr.CreateLoad(ptr._ptr, name)) if align: inst._ptr.setAlignment(align) if volatile: @@ -1805,7 +2037,7 @@ class Builder(llvm.Wrapper): return inst def store(self, value, ptr, align=0, volatile=False): - inst = Value(self._ptr.CreateStore(value._ptr, ptr._ptr)) + inst = _make_value(self._ptr.CreateStore(value._ptr, ptr._ptr)) if align: inst._ptr.setAlignment(align) if volatile: @@ -1821,118 +2053,119 @@ class Builder(llvm.Wrapper): ret = self._ptr.CreateGEP(ptr._ptr, llvm._extract_ptrs(indices), name) - return Value(ret) + return _make_value(ret) # casts and extensions def trunc(self, value, dest_ty, name=""): - return Value(self._ptr.CreateTrunc(value._ptr, dest_ty._ptr, name)) + return _make_value(self._ptr.CreateTrunc(value._ptr, dest_ty._ptr, name)) def zext(self, value, dest_ty, name=""): - return Value(self._ptr.CreateZext(value._ptr, dest_ty._ptr, name)) + return _make_value(self._ptr.CreateZExt(value._ptr, dest_ty._ptr, name)) def sext(self, value, dest_ty, name=""): - return Value(self._ptr.CreateSext(value._ptr, dest_ty._ptr, name)) + return _make_value(self._ptr.CreateSExt(value._ptr, dest_ty._ptr, name)) def fptoui(self, value, dest_ty, name=""): - return Value(self._ptr.CreateFPToUI(value._ptr, dest_ty._ptr, name)) + return _make_value(self._ptr.CreateFPToUI(value._ptr, dest_ty._ptr, name)) def fptosi(self, value, dest_ty, name=""): - return Value(self._ptr.CreateFPToSI(value._ptr, dest_ty._ptr, name)) + return _make_value(self._ptr.CreateFPToSI(value._ptr, dest_ty._ptr, name)) def uitofp(self, value, dest_ty, name=""): - return Value(self._ptr.CreateUIToFP(value._ptr, dest_ty._ptr, name)) + return _make_value(self._ptr.CreateUIToFP(value._ptr, dest_ty._ptr, name)) def sitofp(self, value, dest_ty, name=""): - return Value(self._ptr.CreateSIToFP(value._ptr, dest_ty._ptr, name)) + return _make_value(self._ptr.CreateSIToFP(value._ptr, dest_ty._ptr, name)) def fptrunc(self, value, dest_ty, name=""): - return Value(self._ptr.CreateFPTrunc(value._ptr, dest_ty._ptr, name)) + return _make_value(self._ptr.CreateFPTrunc(value._ptr, dest_ty._ptr, name)) def fpext(self, value, dest_ty, name=""): - return Value(self._ptr.CreateFPExt(value._ptr, dest_ty._ptr, name)) + return _make_value(self._ptr.CreateFPExt(value._ptr, dest_ty._ptr, name)) def ptrtoint(self, value, dest_ty, name=""): - return Value(self._ptr.CreatePtrToInt(value._ptr, dest_ty._ptr, name)) + return _make_value(self._ptr.CreatePtrToInt(value._ptr, dest_ty._ptr, name)) def inttoptr(self, value, dest_ty, name=""): - return Value(self._ptr.CreateIntToPtr(value._ptr, dest_ty._ptr, name)) + return _make_value(self._ptr.CreateIntToPtr(value._ptr, dest_ty._ptr, name)) def bitcast(self, value, dest_ty, name=""): - return Value(self._ptr.CreateBitCast(value._ptr, dest_ty._ptr, name)) + return _make_value(self._ptr.CreateBitCast(value._ptr, dest_ty._ptr, name)) # comparisons def icmp(self, ipred, lhs, rhs, name=""): - return Value(self._ptr.CreateICmp(ipred, lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateICmp(ipred, lhs._ptr, rhs._ptr, name)) def fcmp(self, rpred, lhs, rhs, name=""): - return Value(self._ptr.CreateFCmp(rpred, lhs._ptr, rhs._ptr, name)) + return _make_value(self._ptr.CreateFCmp(rpred, lhs._ptr, rhs._ptr, name)) # misc def extract_value(self, retval, idx, name=""): - return Value(self._ptr.CreateExtractValue(retval._ptr, [idx], name)) + return _make_value(self._ptr.CreateExtractValue(retval._ptr, [idx], name)) # obsolete synonym for extract_value getresult = extract_value def insert_value(self, retval, rhs, idx, name=""): - return Value(self._ptr.CreateInsertValue(retval._ptr, + return _make_value(self._ptr.CreateInsertValue(retval._ptr, rhs._ptr, [idx], name)) def phi(self, ty, name=""): - return Value(self._ptr.CreatePHI(ty._ptr, 2, name)) + return _make_value(self._ptr.CreatePHI(ty._ptr, 2, name)) def call(self, fn, args, name=""): err_template = 'Argument type mismatch: expected %s but got %s' + for i, (t, v) in enumerate(zip(fn.type.pointee.args, args)): if t != v.type: raise TypeError(err_template % (t, v.type)) arg_ptrs = llvm._extract_ptrs(args) - return Value(self._ptr.CreateCall(fn._ptr, arg_ptrs, name)) + return _make_value(self._ptr.CreateCall(fn._ptr, arg_ptrs, name)) def select(self, cond, then_value, else_value, name=""): - return Value(self._ptr.CreateSelect(cond._ptr, then_value._ptr, + return _make_value(self._ptr.CreateSelect(cond._ptr, then_value._ptr, else_value._ptr, name)) def vaarg(self, list_val, ty, name=""): - return Value(self._ptr.CreateVAArg(list_val._ptr, ty._ptr, name)) + return _make_value(self._ptr.CreateVAArg(list_val._ptr, ty._ptr, name)) def extract_element(self, vec_val, idx_val, name=""): - return Value(self._ptr.CreateExtractElement(vec_val._ptr, - idx_val_.ptr, - name)) + return _make_value(self._ptr.CreateExtractElement(vec_val._ptr, + idx_val._ptr, + name)) def insert_element(self, vec_val, elt_val, idx_val, name=""): - return Value(self._ptr.CreateExtractElement(vec_val._ptr, - elt_val._ptr, - idx_val_.ptr, - name)) + return _make_value(self._ptr.CreateInsertElement(vec_val._ptr, + elt_val._ptr, + idx_val._ptr, + name)) def shuffle_vector(self, vecA, vecB, mask, name=""): - return Value(self._ptr.CreateShuffleVector(vecA._ptr, - vecB._ptr, - mask._ptr, - name)) + return _make_value(self._ptr.CreateShuffleVector(vecA._ptr, + vecB._ptr, + mask._ptr, + name)) # atomics def atomic_cmpxchg(self, ptr, old, new, ordering, crossthread=True): - return Value(self._ptr.CreateAtomicCmpXchg(ptr._ptr, + return _make_value(self._ptr.CreateAtomicCmpXchg(ptr._ptr, old._ptr, new._ptr, - ordering, + _atomic_orderings[ordering], _sync_scope(crossthread))) def atomic_rmw(self, op, ptr, val, ordering, crossthread=True): op_dict = dict((k.lower(), v) - for k, v in vars(api.llvm.AtomicRMWInst.BinOp)) + for k, v in vars(api.llvm.AtomicRMWInst.BinOp).items()) op = op_dict[op] - return Value(self._ptr.CreateAtomicRMW(op, ptr._ptr, val._ptr, - ordering, + return _make_value(self._ptr.CreateAtomicRMW(op, ptr._ptr, val._ptr, + _atomic_orderings[ordering], _sync_scope(crossthread))) def atomic_xchg(self, *args, **kwargs): @@ -1970,21 +2203,22 @@ class Builder(llvm.Wrapper): def atomic_load(self, ptr, ordering, align=1, crossthread=True, volatile=False, name=""): - inst = self._ptr.load(ptr, align=align, volatile=volatile, name=name) - inst._ptr.setAtomic(ordering, _sync_scope(crossthread)) + inst = self.load(ptr, align=align, volatile=volatile, name=name) + inst._ptr.setAtomic(_atomic_orderings[ordering], + _sync_scope(crossthread)) return inst def atomic_store(self, value, ptr, ordering, align=1, crossthread=True, volatile=False): - inst = self._ptr.store(ptr, value, align=align, volatile=volatile, - name=name) - inst._ptr.setAtomic(ordering, _sync_scope(crossthread)) + inst = self.store(value, ptr, align=align, volatile=volatile) + inst._ptr.setAtomic(_atomic_orderings[ordering], + _sync_scope(crossthread)) return inst def fence(self, ordering, crossthread=True): - return Value(self._ptr.CreateFence(ordering, - _sync_scope(crossthread))) + return _make_value(self._ptr.CreateFence(_atomic_orderings[ordering], + _sync_scope(crossthread))) def _sync_scope(crossthread): if crossthread: @@ -2000,12 +2234,13 @@ def load_library_permanently(filename): path of the .so file) using LLVM. Symbols from these are available from the execution engine thereafter.""" with contextlib.closing(StringIO()) as errmsg: - failed = api.llvm.sys.LoadLibraryPermanently(filename, errmsg) + failed = api.llvm.sys.DynamicLibrary.LoadPermanentLibrary(filename, + errmsg) if failed: raise llvm.LLVMException(errmsg.getvalue()) def inline_function(call): - info = api.llvm.InlineFunctionInfo() + info = api.llvm.InlineFunctionInfo.new() return api.llvm.InlineFunction(call._ptr, info) def parse_environment_options(progname, envname): diff --git a/llvm/ee.py b/llvm/ee.py index 8523998..8598ad9 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -38,8 +38,8 @@ import contextlib import llvm from llvm import core -from llvmpy import api - +from llvm.passes import TargetData, TargetTransformInfo +from llvmpy import api, extra #===----------------------------------------------------------------------=== # Enumerations #===----------------------------------------------------------------------=== @@ -63,20 +63,20 @@ class GenericValue(llvm.Wrapper): @staticmethod def int(ty, intval): - ptr = api.llvm.CreateInt(ty._ptr, intval, False) + ptr = api.llvm.GenericValue.CreateInt(ty._ptr, int(intval), False) return GenericValue(ptr) @staticmethod def int_signed(ty, intval): - ptr = api.llvm.CreateInt(ty._ptr, intval, True) + ptr = api.llvm.GenericValue.CreateInt(ty._ptr, int(intval), True) return GenericValue(ptr) @staticmethod def real(ty, floatval): if str(ty) == 'float': - ptr = api.llvm.CreateFloat(floatval) + ptr = api.llvm.GenericValue.CreateFloat(float(floatval)) elif str(ty) == 'double': - ptr = api.llvm.CreateDouble(floatval) + ptr = api.llvm.GenericValue.CreateDouble(float(floatval)) else: raise Exception('Unreachable') return GenericValue(ptr) @@ -91,7 +91,7 @@ class GenericValue(llvm.Wrapper): `addr` is an integer representing an address. ''' - ptr = api.llvm.CreatePointer(addr) + ptr = api.llvm.GenericValue.CreatePointer(int(addr)) return GenericValue(ptr) def as_int(self): @@ -101,7 +101,7 @@ class GenericValue(llvm.Wrapper): return self._ptr.toSignedInt() def as_real(self, ty): - return self._ptr.toFloat() + return self._ptr.toFloat(ty._ptr) def as_pointer(self): return self._ptr.toPointer() @@ -113,7 +113,7 @@ class GenericValue(llvm.Wrapper): class EngineBuilder(llvm.Wrapper): @staticmethod def new(module): - ptr = api.llvm.EngineBuilder.new(module) + ptr = api.llvm.EngineBuilder.new(module._ptr) return EngineBuilder(ptr) def force_jit(self): @@ -158,10 +158,10 @@ class EngineBuilder(llvm.Wrapper): ''' if args: triple, march, mcpu, mattrs = args - ptr = self._ptr.select_target(triple, march, mcpu, + ptr = self._ptr.selectTarget(triple, march, mcpu, mattrs.split(',')) else: - ptr = self._ptr.select_target() + ptr = self._ptr.selectTarget() return TargetMachine(ptr) @@ -182,7 +182,8 @@ class ExecutionEngine(llvm.Wrapper): self._ptr.DisableLazyCompilation(disabled) def run_function(self, fn, args): - return self._ptr.runFunction(fn._ptr, map(lambda x: x._ptr, args)) + ptr = self._ptr.runFunction(fn._ptr, map(lambda x: x._ptr, args)) + return GenericValue(ptr) def get_pointer_to_function(self, fn): return self._ptr.getPointerToFunction(fn._ptr) @@ -195,13 +196,13 @@ class ExecutionEngine(llvm.Wrapper): self._ptr.addGlobalMapping(gvar._ptr, addr) def run_static_ctors(self): - self._ptr.runStaticConstructorDestructors(False) + self._ptr.runStaticConstructorsDestructors(False) def run_static_dtors(self): - self._ptr.runStaticConstructorDestructors(True) + self._ptr.runStaticConstructorsDestructors(True) def free_machine_code_for(self, fn): - self.freeMachineCodeForFunction(fn._ptr) + self._ptr.freeMachineCodeForFunction(fn._ptr) def add_module(self, module): self._ptr.addModule(module._ptr) @@ -222,17 +223,17 @@ def print_registered_targets(): ''' Note: print directly to stdout ''' - llvm.TargetRegistry.printRegisteredTargetsForVersion() + api.llvm.TargetRegistry.printRegisteredTargetsForVersion() def get_host_cpu_name(): '''return the string name of the host CPU ''' - return llvm.sys.getHostCPUName() + return api.llvm.sys.getHostCPUName() def get_default_triple(): '''return the target triple of the host in str-rep ''' - return llvm.sys.getDefaultTargetTriple() + return api.llvm.sys.getDefaultTargetTriple() class TargetMachine(llvm.Wrapper): @@ -243,20 +244,20 @@ class TargetMachine(llvm.Wrapper): triple = get_default_triple() if not cpu: cpu = get_host_cpu_name() - with contextlib.closing(StringIO) as error: + with contextlib.closing(StringIO()) as error: target = api.llvm.TargetRegistry.lookupTarget(triple, error) if not target: raise llvm.LLVMException(error) if not target.hasTargetMachine(): raise llvm.LLVMException(target, "No target machine.") - target_options = api.llvm.TargetOptions() + target_options = api.llvm.TargetOptions.new() tm = target.createTargetMachine(triple, cpu, features, target_options, api.llvm.Reloc.Model.Default, cm, opt) if not tm: raise llvm.LLVMException("Cannot create target machine") - return TargetMachine(ptr) + return TargetMachine(tm) @staticmethod def lookup(arch, cpu='', features='', opt=2, cm=CM_DEFAULT): @@ -272,24 +273,25 @@ class TargetMachine(llvm.Wrapper): use: `llvm-as < /dev/null | llc -march=xyz -mattr=help` ''' triple = api.llvm.Triple.new() - with contextlib.closing(StringIO) as error: - target = api.llvm.TargetMachine.lookupTarget(arch, triple, error) + with contextlib.closing(StringIO()) as error: + target = api.llvm.TargetRegistry.lookupTarget(arch, triple, error) if not target: raise llvm.LLVMException(error) if not target.hasTargetMachine(): raise llvm.LLVMException(target, "No target machine.") - target_options = api.llvm.TargetOptions() + target_options = api.llvm.TargetOptions.new() tm = target.createTargetMachine(str(triple), cpu, features, target_options, api.llvm.Reloc.Model.Default, cm, opt) if not tm: raise llvm.LLVMException("Cannot create target machine") - return TargetMachine(ptr) + return TargetMachine(tm) def _emit_file(self, module, cgft): pm = api.llvm.PassManager.new() - os = api.extra.make_raw_ostream_for_printing() + os = extra.make_raw_ostream_for_printing() + pm.add(api.llvm.DataLayout.new(str(self.target_data))) failed = self._ptr.addPassesToEmitFile(pm, os, cgft) pm.run(module) return os.str() @@ -298,19 +300,19 @@ class TargetMachine(llvm.Wrapper): '''returns byte string of the module as assembly code of the target machine ''' CGFT = api.llvm.TargetMachine.CodeGenFileType - return self._emit_file(module, CGFT.CGFT_AssemblyFile) + return self._emit_file(module._ptr, CGFT.CGFT_AssemblyFile) def emit_object(self, module): '''returns byte string of the module as native code of the target machine ''' CGFT = api.llvm.TargetMachine.CodeGenFileType - return self._emit_file(module, CGFT.CGFT_ObjectFile) + return self._emit_file(module._ptr, CGFT.CGFT_ObjectFile) @property def target_data(self): '''get target data of this machine ''' - return TargetData(self._ptr.getDataLayout) + return TargetData(self._ptr.getDataLayout()) @property def target_name(self): diff --git a/llvm/passes.py b/llvm/passes.py index 545a19d..36e7d97 100644 --- a/llvm/passes.py +++ b/llvm/passes.py @@ -46,7 +46,7 @@ from llvmpy import api class PassManagerBuilder(llvm.Wrapper): @staticmethod def new(): - return PassManagerBuilder(api.llvm.PassManagerBuilder()) + return PassManagerBuilder(api.llvm.PassManagerBuilder.new()) def populate(self, pm): if isinstance(pm, FunctionPassManager): @@ -59,7 +59,7 @@ class PassManagerBuilder(llvm.Wrapper): return self._ptr.OptLevel @opt_level.setter - def _set_opt_level(self, optlevel): + def opt_level(self, optlevel): self._ptr.OptLevel = optlevel @property @@ -67,7 +67,7 @@ class PassManagerBuilder(llvm.Wrapper): return self._ptr.SizeLevel @size_level.setter - def _set_size_level(self, sizelevel): + def size_level(self, sizelevel): self._ptr.SizeLevel = sizelevel @property @@ -75,8 +75,9 @@ class PassManagerBuilder(llvm.Wrapper): return self._ptr.Vectorize @vectorize.setter - def _set_vectorize(self, enable): - self._ptr.Vectroize = enable + def vectorize(self, enable): + self._ptr.Vectorize = enable + @property def loop_vectorize(self): @@ -142,10 +143,11 @@ class PassManager(llvm.Wrapper): def _add_pass(self, pass_name): passreg = api.llvm.PassRegistry.getPassRegistry() - a_pass = passreg.getPassInfo(pass_name) + a_pass = passreg.getPassInfo(pass_name).createPass() if not a_pass: assert pass_name not in PASSES, "Registered but not found?" raise llvm.LLVMException('Invalid pass name "%s"' % pass_name) + print a_pass self._ptr.add(a_pass) def run(self, module): @@ -155,17 +157,17 @@ class FunctionPassManager(PassManager): @staticmethod def new(module): - ptr = api.llvm.FunctionPassManager.new(module) + ptr = api.llvm.FunctionPassManager.new(module._ptr) return FunctionPassManager(ptr) def __init__(self, ptr): PassManager.__init__(self, ptr) def initialize(self): - self._ptr.doInitization() + self._ptr.doInitialization() def run(self, fn): - return self._ptr.run(fn) + return self._ptr.run(fn._ptr) def finalize(self): self._ptr.doFinalization() @@ -187,7 +189,7 @@ class Pass(llvm.Wrapper): The error cannot be caught. ''' passreg = api.llvm.PassRegistry.getPassRegistry() - a_pass = passreg.getPassInfo(pass_name) + a_pass = passreg.getPassInfo(name).createPass() p = Pass(a_pass) p.__name = name return p @@ -196,7 +198,10 @@ class Pass(llvm.Wrapper): def name(self): '''The name used in PassRegistry. ''' - return p.__name + try: + return self.__name + except AttributeError: + return @property def description(self): @@ -235,7 +240,8 @@ class TargetData(Pass): @property def target_integer_type(self): - return self._ptr.core.IntegerType(core.Type.getInt32Ty()) + context = api.llvm.getGlobalContext() + return api.llvm.IntegerType(api.llvm.Type.getInt32Ty(context)) def size(self, ty): return self._ptr.getTypeSizeInBits(ty._ptr) @@ -256,15 +262,15 @@ class TargetData(Pass): if isinstance(ty_or_gv, core.Type): return self._ptr.getPrefTypeAlignment(ty_or_gv._ptr) elif isinstance(ty_or_gv, core.GlobalVariable): - return self._ptr._core.getPreferredAlignment(ty_or_gv._ptr) + return self._ptr.getPreferredAlignment(ty_or_gv._ptr) else: raise core.LLVMException("argument is neither a type nor a global variable") def element_at_offset(self, ty, ofs): - return self._ptr.getStructLayout(ty).getElementContainingOffset(ofs) + return self._ptr.getStructLayout(ty._ptr).getElementContainingOffset(ofs) def offset_of_element(self, ty, el): - return self._ptr.getStructLayout(ty).getElementOffset(el) + return self._ptr.getStructLayout(ty._ptr).getElementOffset(el) #===----------------------------------------------------------------------=== # Target Library Info @@ -277,6 +283,19 @@ class TargetLibraryInfo(Pass): ptr = api.llvm.TargetLibraryInfo.new(triple) return TargetLibraryInfo(ptr) +#===----------------------------------------------------------------------=== +# Target Transformation Info +#===----------------------------------------------------------------------=== + +class TargetTransformInfo(Pass): + @staticmethod + def new(targetmachine): + scalartti = targetmachine._ptr.getScalarTargetTransformInfo() + vectortti = targetmachine._ptr.getVectorTargetTransformInfo() + ptr = api.llvm.TargetTransformInfo.new(scalartti, vectortti) + return TargetTransformInfo(ptr) + + #===----------------------------------------------------------------------=== # Helpers #===----------------------------------------------------------------------=== diff --git a/llvm/tbaa.py b/llvm/tbaa.py new file mode 100644 index 0000000..b510ce2 --- /dev/null +++ b/llvm/tbaa.py @@ -0,0 +1,51 @@ +from llvm.core import * + +class TBAABuilder(object): + '''Simplify creation of TBAA metadata. + + Each TBAABuidler object operates on a module. + User can create multiple TBAABuilder on a module + ''' + + def __init__(self, module, rootid): + ''' + module --- the module to use. + root --- string name to identify the TBAA root. + ''' + self.__module = module + self.__rootid = rootid + self.__rootmd = self.__new_md(rootid) + + @classmethod + def new(cls, module, rootid): + return cls(module, rootid) + + def get_node(self, name, parent=None, const=False): + '''Returns a MetaData object representing a TBAA node. + + Use loadstore_instruction.set_metadata('tbaa', node) to + bind a type to a memory. + ''' + parent = parent or self.root + const = Constant.int(Type.int(), int(bool(const))) + return self.__new_md(name, parent, const) + + @property + def module(self): + return self.__module + + @property + def root(self): + return self.__rootmd + + @property + def root_name(self): + return self.__rootid + + def __new_md(self, *args): + contents = list(args) + for i, v in enumerate(contents): + if isinstance(v, str): + contents[i] = MetaDataString.get(self.module, v) + return MetaData.get(self.module, contents) + diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py new file mode 100644 index 0000000..5b26e39 --- /dev/null +++ b/llvm/test_llvmpy.py @@ -0,0 +1,1243 @@ +""" +LLVM tests +""" +import os +import sys +import math +import shutil +import unittest +import subprocess +import tempfile +import contextlib + +is_py3k = bool(sys.version_info[0] == 3) +BITS = tuple.__itemsize__ * 8 + +if is_py3k: + from io import StringIO +else: + from cStringIO import StringIO + + +import llvm +from llvm.core import (Module, Type, GlobalVariable, Function, Builder, + Constant, MetaData, MetaDataString, inline_function) +from llvm.ee import EngineBuilder +import llvm.core as lc +import llvm.passes as lp +import llvm.ee as le +import llvmpy + + +tests = [] + + +# --------------------------------------------------------------------------- + +if sys.version_info[:2] <= (2, 6): + # create custom TestCase + class TestCase(unittest.TestCase): + def assertIn(self, item, container): + self.assertTrue(item in container) + + def assertNotIn(self, item, container): + self.assertFalse(item in container) + + def assertLess(self, a, b): + self.assertTrue(a < b) + + def assertIs(self, a, b): + self.assertTrue(a is b) + + @contextlib.contextmanager + def assertRaises(self, exc): + try: + yield + except exc: + pass + else: + raise self.failureException("Did not raise %s" % exc) + +else: + TestCase = unittest.TestCase + + +# --------------------------------------------------------------------------- + +class TestAsm(TestCase): + def setUp(self): + self.tmpdir = tempfile.mkdtemp() + + def tearDown(self): + shutil.rmtree(self.tmpdir) + + def test_asm(self): + # 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) + + testasm_ll = os.path.join(self.tmpdir, 'testasm.ll') + with open(testasm_ll, "w") as fout: + fout.write(asm) + + # read it back into a module + with open(testasm_ll) as fin: + m2 = Module.from_assembly(fin) + # The default `m.id` is ''. + m2.id = m.id # Copy the name from `m` + + self.assertEqual(str(m2).strip(), asm.strip()) + + def test_bitcode(self): + # 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) + + testasm_bc = os.path.join(self.tmpdir, 'testasm.bc') + with open(testasm_bc, "wb") as fout: + m.to_bitcode(fout) + + # read it back into a module + with open(testasm_bc, "rb") as fin: + m2 = Module.from_bitcode(fin) + # The default `m.id` is ''. + m2.id = m.id # Copy the name from `m` + + self.assertEqual(str(m2).strip(), asm.strip()) + +tests.append(TestAsm) + +# --------------------------------------------------------------------------- + +class TestAttr(TestCase): + def make_module(self): + test_module = """ + define void @sum(i32*, i32*) { + entry: + ret void + } + """ + return Module.from_assembly(StringIO(test_module)) + + def test_align(self): + m = self.make_module() + f = m.get_function_named('sum') + f.args[0].alignment = 16 + self.assert_("align 16" in str(f)) + self.assertEqual(f.args[0].alignment, 16) + +tests.append(TestAttr) + +# --------------------------------------------------------------------------- + +class TestAtomic(TestCase): + orderings = ['unordered', 'monotonic', 'acquire', + 'release', 'acq_rel', 'seq_cst'] + + atomic_op = ['xchg', 'add', 'sub', 'and', 'nand', 'or', 'xor', + 'max', 'min', 'umax', 'umin'] + + def test_atomic_cmpxchg(self): + mod = Module.new('mod') + functype = Type.function(Type.void(), []) + func = mod.add_function(functype, name='foo') + bb = func.append_basic_block('entry') + bldr = Builder.new(bb) + ptr = bldr.alloca(Type.int()) + + old = bldr.load(ptr) + new = Constant.int(Type.int(), 1234) + + for ordering in self.orderings: + inst = bldr.atomic_cmpxchg(ptr, old, new, ordering) + self.assertEqual(ordering, str(inst).strip().split(' ')[-1]) + + inst = bldr.atomic_cmpxchg(ptr, old, new, ordering, crossthread=False) + self.assertEqual('singlethread', str(inst).strip().split(' ')[-2]) + + def test_atomic_rmw(self): + mod = Module.new('mod') + functype = Type.function(Type.void(), []) + func = mod.add_function(functype, name='foo') + bb = func.append_basic_block('entry') + bldr = Builder.new(bb) + ptr = bldr.alloca(Type.int()) + + old = bldr.load(ptr) + val = Constant.int(Type.int(), 1234) + + for ordering in self.orderings: + inst = bldr.atomic_rmw('xchg', ptr, val, ordering) + self.assertEqual(ordering, str(inst).split(' ')[-1]) + + for op in self.atomic_op: + inst = bldr.atomic_rmw(op, ptr, val, ordering) + self.assertEqual(op, str(inst).strip().split(' ')[3]) + + inst = bldr.atomic_rmw('xchg', ptr, val, ordering, crossthread=False) + self.assertEqual('singlethread', str(inst).strip().split(' ')[-2]) + + for op in self.atomic_op: + atomic_op = getattr(bldr, 'atomic_%s' % op) + inst = atomic_op(ptr, val, ordering) + self.assertEqual(op, str(inst).strip().split(' ')[3]) + + def test_atomic_ldst(self): + mod = Module.new('mod') + functype = Type.function(Type.void(), []) + func = mod.add_function(functype, name='foo') + bb = func.append_basic_block('entry') + bldr = Builder.new(bb) + ptr = bldr.alloca(Type.int()) + + val = Constant.int(Type.int(), 1234) + + for ordering in self.orderings: + loaded = bldr.atomic_load(ptr, ordering) + self.assert_('load atomic' in str(loaded)) + self.assertEqual(ordering, + str(loaded).strip().split(' ')[-3].rstrip(',')) + self.assert_('align 1' in str(loaded)) + + stored = bldr.atomic_store(loaded, ptr, ordering) + self.assert_('store atomic' in str(stored)) + self.assertEqual(ordering, + str(stored).strip().split(' ')[-3].rstrip(',')) + self.assert_('align 1' in str(stored)) + + fenced = bldr.fence(ordering) + self.assertEqual(['fence', ordering], + str(fenced).strip().split(' ')) + +tests.append(TestAtomic) + +# --------------------------------------------------------------------------- + +class TestConstExpr(TestCase): + + def test_constexpr_opcode(self): + mod = Module.new('test_constexpr_opcode') + func = mod.add_function(Type.function(Type.void(), []), name="foo") + builder = Builder.new(func.append_basic_block('entry')) + a = builder.inttoptr(Constant.int(Type.int(), 123), + Type.pointer(Type.int())) + self.assertTrue(isinstance(a, lc.ConstantExpr)) + self.assertEqual(a.opcode, lc.OPCODE_INTTOPTR) + self.assertEqual(a.opcode_name, "inttoptr") + +tests.append(TestConstExpr) + +# --------------------------------------------------------------------------- + +class TestOperands(TestCase): + # implement a test function + test_module = """ +define i32 @prod(i32, i32) { +entry: + %2 = mul i32 %0, %1 + ret i32 %2 +} + +define i32 @test_func(i32, i32, i32) { +entry: + %tmp1 = call i32 @prod(i32 %0, i32 %1) + %tmp2 = add i32 %tmp1, %2 + %tmp3 = add i32 %tmp2, 1 + %tmp4 = add i32 %tmp3, -1 + %tmp5 = add i64 -81985529216486895, 12297829382473034410 + ret i32 %tmp4 +} +""" + def test_operands(self): + m = Module.from_assembly(StringIO(self.test_module)) + + test_func = m.get_function_named("test_func") + prod = m.get_function_named("prod") + + # test operands + i1 = test_func.basic_blocks[0].instructions[0] + i2 = test_func.basic_blocks[0].instructions[1] + i3 = test_func.basic_blocks[0].instructions[2] + i4 = test_func.basic_blocks[0].instructions[3] + i5 = test_func.basic_blocks[0].instructions[4] + + self.assertEqual(i1.operand_count, 3) + self.assertEqual(i2.operand_count, 2) + + self.assertEqual(i3.operands[1].z_ext_value, 1) + self.assertEqual(i3.operands[1].s_ext_value, 1) + self.assertEqual(i4.operands[1].z_ext_value, 0xffffffff) + self.assertEqual(i4.operands[1].s_ext_value, -1) + self.assertEqual(i5.operands[0].s_ext_value, -81985529216486895) + self.assertEqual(i5.operands[1].z_ext_value, 12297829382473034410) + + self.assert_(i1.operands[-1] is prod) + self.assert_(i1.operands[0] is test_func.args[0]) + self.assert_(i1.operands[1] is test_func.args[1]) + self.assert_(i2.operands[0] is i1) + self.assert_(i2.operands[1] is test_func.args[2]) + self.assertEqual(len(i1.operands), 3) + self.assertEqual(len(i2.operands), 2) + + self.assert_(i1.called_function is prod) + +tests.append(TestOperands) + +# --------------------------------------------------------------------------- + +class TestPasses(TestCase): + # Create a module. + asm = """ + +define i32 @test() nounwind { + ret i32 42 +} + +define i32 @test1() nounwind { +entry: + %tmp = alloca i32 + store i32 42, i32* %tmp, align 4 + %tmp1 = load i32* %tmp, align 4 + %tmp2 = call i32 @test() + %tmp3 = load i32* %tmp, align 4 + %tmp4 = load i32* %tmp, align 4 + ret i32 %tmp1 +} + +define i32 @test2() nounwind { +entry: + %tmp = call i32 @test() + ret i32 %tmp +} +""" + def test_passes(self): + m = Module.from_assembly(StringIO(self.asm)) + + fn_test1 = m.get_function_named('test1') + fn_test2 = m.get_function_named('test2') + + original_test1 = str(fn_test1) + original_test2 = str(fn_test2) + + # Let's run a module-level inlining pass. First, create a pass manager. + pm = lp.PassManager.new() + + # Add the target data as the first "pass". This is mandatory. + pm.add(le.TargetData.new('')) + + # Add the inlining pass. + pm.add(lp.PASS_INLINE) + + # Run it! + pm.run(m) + + # Done with the pass manager. + del pm + + # Make sure test2 is inlined + self.assertNotEqual(str(fn_test2).strip(), original_test2.strip()) + + bb_entry = fn_test2.basic_blocks[0] + + self.assertEqual(len(bb_entry.instructions), 1) + self.assertEqual(bb_entry.instructions[0].opcode_name, 'ret') + + # Let's run a DCE pass on the the function 'test1' now. First create a + # function pass manager. + fpm = lp.FunctionPassManager.new(m) + + # Add the target data as first "pass". This is mandatory. + fpm.add(le.TargetData.new('')) + + # Add a DCE pass + fpm.add(lp.PASS_ADCE) + + # Run the pass on the function 'test1' + fpm.run(m.get_function_named('test1')) + + # Make sure test1 is modified + self.assertNotEqual(str(fn_test1).strip(), original_test1.strip()) + + def test_passes_with_pmb(self): + m = Module.from_assembly(StringIO(self.asm)) + + fn_test1 = m.get_function_named('test1') + fn_test2 = m.get_function_named('test2') + + original_test1 = str(fn_test1) + original_test2 = str(fn_test2) + + # Try out the PassManagerBuilder + + pmb = lp.PassManagerBuilder.new() + + self.assertEqual(pmb.opt_level, 2) # ensure default is level 2 + pmb.opt_level = 3 + self.assertEqual(pmb.opt_level, 3) # make sure it works + + self.assertEqual(pmb.size_level, 0) # ensure default is level 0 + pmb.size_level = 2 + self.assertEqual(pmb.size_level, 2) # make sure it works + + self.assertFalse(pmb.vectorize) # ensure default is False + pmb.vectorize = True + self.assertTrue(pmb.vectorize) # make sure it works + + # make sure the default is False + self.assertFalse(pmb.disable_unit_at_a_time) + self.assertFalse(pmb.disable_unroll_loops) + self.assertFalse(pmb.disable_simplify_lib_calls) + + pmb.disable_unit_at_a_time = True + self.assertTrue(pmb.disable_unit_at_a_time) + + # Do function pass + fpm = lp.FunctionPassManager.new(m) + pmb.populate(fpm) + fpm.run(fn_test1) + + # Make sure test1 has changed + self.assertNotEqual(str(fn_test1).strip(), original_test1.strip()) + + # Do module pass + pm = lp.PassManager.new() + pmb.populate(pm) + pm.run(m) + + # Make sure test2 has changed + self.assertNotEqual(str(fn_test2).strip(), original_test2.strip()) + + def test_dump_passes(self): + self.assertTrue(len(lp.PASSES)>0, msg="Cannot have no passes") + +tests.append(TestPasses) + +# --------------------------------------------------------------------------- + +class TestEngineBuilder(TestCase): + + def make_test_module(self): + module = Module.new("testmodule") + fnty = Type.function(Type.int(), []) + function = module.add_function(fnty, 'foo') + bb_entry = function.append_basic_block('entry') + builder = Builder.new(bb_entry) + builder.ret(Constant.int(Type.int(), 0xcafe)) + module.verify() + return module + + def run_foo(self, ee, module): + function = module.get_function_named('foo') + retval = ee.run_function(function, []) + self.assertEqual(retval.as_int(), 0xcafe) + + + def test_enginebuilder_basic(self): + module = self.make_test_module() + self.assertTrue(llvmpy.capsule.has_ownership(module._ptr._ptr)) + ee = EngineBuilder.new(module).create() + self.assertFalse(llvmpy.capsule.has_ownership(module._ptr._ptr)) + self.run_foo(ee, module) + + + def test_enginebuilder_with_tm(self): + tm = le.TargetMachine.new() + module = self.make_test_module() + self.assertTrue(llvmpy.capsule.has_ownership(module._ptr._ptr)) + ee = EngineBuilder.new(module).create(tm) + self.assertFalse(llvmpy.capsule.has_ownership(module._ptr._ptr)) + self.run_foo(ee, module) + + def test_enginebuilder_force_jit(self): + module = self.make_test_module() + ee = EngineBuilder.new(module).force_jit().create() + + self.run_foo(ee, module) +# +# def test_enginebuilder_force_interpreter(self): +# module = self.make_test_module() +# ee = EngineBuilder.new(module).force_interpreter().create() +# +# self.run_foo(ee, module) + + def test_enginebuilder_opt(self): + module = self.make_test_module() + ee = EngineBuilder.new(module).opt(3).create() + + self.run_foo(ee, module) + +tests.append(TestEngineBuilder) + +# --------------------------------------------------------------------------- + +class TestExecutionEngine(TestCase): + def test_get_pointer_to_global(self): + module = lc.Module.new(str(self)) + gvar = module.add_global_variable(Type.int(), 'hello') + X = 1234 + gvar.initializer = lc.Constant.int(Type.int(), X) + + ee = le.ExecutionEngine.new(module) + ptr = ee.get_pointer_to_global(gvar) + from ctypes import c_void_p, cast, c_int, POINTER + casted = cast(c_void_p(ptr), POINTER(c_int)) + self.assertEqual(X, casted[0]) + + def test_add_global_mapping(self): + module = lc.Module.new(str(self)) + gvar = module.add_global_variable(Type.int(), 'hello') + + fnty = lc.Type.function(Type.int(), []) + foo = module.add_function(fnty, name='foo') + bldr = lc.Builder.new(foo.append_basic_block('entry')) + bldr.ret(bldr.load(gvar)) + + ee = le.ExecutionEngine.new(module) + from ctypes import c_int, addressof, CFUNCTYPE + value = 0xABCD + value_ctype = c_int(value) + value_pointer = addressof(value_ctype) + + ee.add_global_mapping(gvar, value_pointer) + + foo_addr = ee.get_pointer_to_function(foo) + prototype = CFUNCTYPE(c_int) + foo_callable = prototype(foo_addr) + self.assertEqual(foo_callable(), value) + + + +tests.append(TestExecutionEngine) +# --------------------------------------------------------------------------- + +class TestObjCache(TestCase): + + def test_objcache(self): + # Testing module aliasing + m1 = Module.new('a') + t = Type.int() + ft = Type.function(t, [t]) + f1 = m1.add_function(ft, "func") + m2 = f1.module + self.assert_(m1 is m2) + + # Testing global vairable aliasing 1 + gv1 = GlobalVariable.new(m1, t, "gv") + gv2 = GlobalVariable.get(m1, "gv") + self.assert_(gv1 is gv2) + + # Testing global vairable aliasing 2 + gv3 = m1.global_variables[0] + self.assert_(gv1 is gv3) + + # Testing global vairable aliasing 3 + gv2 = None + gv3 = None + + gv1.delete() + + gv4 = GlobalVariable.new(m1, t, "gv") + + self.assert_(gv1 is not gv4) + + # Testing function aliasing 1 + b1 = f1.append_basic_block('entry') + f2 = b1.function + self.assert_(f1 is f2) + + # Testing function aliasing 2 + f3 = m1.get_function_named("func") + self.assert_(f1 is f3) + + # Testing function aliasing 3 + f4 = Function.get_or_insert(m1, ft, "func") + self.assert_(f1 is f4) + + # Testing function aliasing 4 + f5 = Function.get(m1, "func") + self.assert_(f1 is f5) + + # Testing function aliasing 5 + f6 = m1.get_or_insert_function(ft, "func") + self.assert_(f1 is f6) + + # Testing function aliasing 6 + f7 = m1.functions[0] + self.assert_(f1 is f7) + + # Testing argument aliasing + a1 = f1.args[0] + a2 = f1.args[0] + self.assert_(a1 is a2) + + # Testing basic block aliasing 1 + b2 = f1.basic_blocks[0] + self.assert_(b1 is b2) + + # Testing basic block aliasing 2 + b3 = f1.entry_basic_block + self.assert_(b1 is b3) + + # Testing basic block aliasing 3 + b31 = f1.entry_basic_block + self.assert_(b1 is b31) + + # Testing basic block aliasing 4 + bldr = Builder.new(b1) + b4 = bldr.basic_block + self.assert_(b1 is b4) + + # Testing basic block aliasing 5 + i1 = bldr.ret_void() + b5 = i1.basic_block + self.assert_(b1 is b5) + + # Testing instruction aliasing 1 + i2 = b5.instructions[0] + self.assert_(i1 is i2) + + # phi node + phi = bldr.phi(t) + phi.add_incoming(f1.args[0], b1) + v2 = phi.get_incoming_value(0) + b6 = phi.get_incoming_block(0) + + # Testing PHI / basic block aliasing 5 + self.assert_(b1 is b6) + + # Testing PHI / value aliasing + self.assert_(f1.args[0] is v2) + +tests.append(TestObjCache) + +# --------------------------------------------------------------------------- + +class TestTargetMachines(TestCase): + '''Exercise target machines + + Require PTX backend + ''' + def test_native(self): + m, _ = self._build_module() + tm = le.EngineBuilder.new(m).select_target() + + self.assertTrue(tm.target_name) + self.assertTrue(tm.target_data) + self.assertTrue(tm.target_short_description) + self.assertTrue(tm.triple) + self.assertIn('foo', tm.emit_assembly(m).decode('utf-8')) + self.assertTrue(le.get_host_cpu_name()) + + def test_ptx(self): + if lc.HAS_PTX: + arch = 'ptx64' + elif lc.HAS_NVPTX: + arch = 'nvptx64' + else: + return # skip this test + print arch + m, func = self._build_module() + func.calling_convention = lc.CC_PTX_KERNEL # set calling conv + ptxtm = le.TargetMachine.lookup(arch=arch, cpu='sm_20') + self.assertTrue(ptxtm.triple) + self.assertTrue(ptxtm.cpu) + ptxasm = ptxtm.emit_assembly(m).decode('utf-8') + self.assertIn('foo', ptxasm) + if lc.HAS_NVPTX: + self.assertIn('.address_size 64', ptxasm) + self.assertIn('sm_20', ptxasm) + + def _build_module(self): + m = Module.new('TestTargetMachines') + + fnty = Type.function(Type.void(), []) + func = m.add_function(fnty, name='foo') + + bldr = Builder.new(func.append_basic_block('entry')) + bldr.ret_void() + m.verify() + return m, func + + def _build_bad_archname(self): + with self.assertRaises(RuntimeError): + tm = TargetMachine.lookup("ain't no arch name") + +tests.append(TestTargetMachines) + +# --------------------------------------------------------------------------- + +class TestNative(TestCase): + def setUp(self): + self.tmpdir = tempfile.mkdtemp() + + def tearDown(self): + shutil.rmtree(self.tmpdir) + + + def _make_module(self): + m = Module.new('module1') + m.add_global_variable(Type.int(), 'i') + + fty = Type.function(Type.int(), []) + f = m.add_function(fty, name='main') + + bldr = Builder.new(f.append_basic_block('entry')) + bldr.ret(Constant.int(Type.int(), 0xab)) + + return m + + def _compile(self, src): + dst = os.path.join(self.tmpdir, 'llvmobj.out') + s = subprocess.call(['cc', '-o', dst, src]) + if s != 0: + raise Exception("Cannot compile") + + s = subprocess.call([dst]) + self.assertEqual(s, 0xab) + + def test_assembly(self): + if sys.platform == 'darwin': + # skip this test on MacOSX for now + return + + m = self._make_module() + output = m.to_native_assembly() + + src = os.path.join(self.tmpdir, 'llvmasm.s') + with open(src, 'wb') as fout: + fout.write(output) + + self._compile(src) + + def test_object(self): + if sys.platform == 'darwin': + # skip this test on MacOSX for now + return + + m = self._make_module() + output = m.to_native_object() + + src = os.path.join(self.tmpdir, 'llvmobj.o') + with open(src, 'wb') as fout: + fout.write(output) + + self._compile(src) + +if sys.platform != 'win32': + tests.append(TestNative) + +# --------------------------------------------------------------------------- + +class TestNativeAsm(TestCase): + + def test_asm(self): + m = Module.new('module1') + + foo = m.add_function(Type.function(Type.int(), + [Type.int(), Type.int()]), + name="foo") + bldr = Builder.new(foo.append_basic_block('entry')) + x = bldr.add(foo.args[0], foo.args[1]) + bldr.ret(x) + + att_syntax = m.to_native_assembly() + os.environ["LLVMPY_OPTIONS"] = "-x86-asm-syntax=intel" + lc.parse_environment_options(sys.argv[0], "LLVMPY_OPTIONS") + intel_syntax = m.to_native_assembly() + + self.assertNotEqual(att_syntax, intel_syntax) + +tests.append(TestNativeAsm) + +# --------------------------------------------------------------------------- + +class TestUses(TestCase): + + def test_uses(self): + m = Module.new('a') + t = Type.int() + ft = Type.function(t, [t, t, t]) + f = m.add_function(ft, "func") + b = f.append_basic_block('entry') + bld = Builder.new(b) + tmp1 = bld.add(Constant.int(t, 100), f.args[0], "tmp1") + tmp2 = bld.add(tmp1, f.args[1], "tmp2") + tmp3 = bld.add(tmp1, f.args[2], "tmp3") + bld.ret(tmp3) + + # Testing use count + self.assertEqual(f.args[0].use_count, 1) + self.assertEqual(f.args[1].use_count, 1) + self.assertEqual(f.args[2].use_count, 1) + self.assertEqual(tmp1.use_count, 2) + self.assertEqual(tmp2.use_count, 0) + self.assertEqual(tmp3.use_count, 1) + + # Testing uses + self.assert_(f.args[0].uses[0] is tmp1) + self.assertEqual(len(f.args[0].uses), 1) + self.assert_(f.args[1].uses[0] is tmp2) + self.assertEqual(len(f.args[1].uses), 1) + self.assert_(f.args[2].uses[0] is tmp3) + self.assertEqual(len(f.args[2].uses), 1) + self.assertEqual(len(tmp1.uses), 2) + self.assertEqual(len(tmp2.uses), 0) + self.assertEqual(len(tmp3.uses), 1) + +tests.append(TestUses) + +# --------------------------------------------------------------------------- + +class TestMetaData(TestCase): + # test module metadata + def test_metadata(self): + m = Module.new('a') + t = Type.int() + metadata = MetaData.get(m, [Constant.int(t, 100), + MetaDataString.get(m, 'abcdef'), + None]) + MetaData.add_named_operand(m, 'foo', metadata) + self.assertEqual(MetaData.get_named_operands(m, 'foo'), [metadata]) + self.assertEqual(MetaData.get_named_operands(m, 'bar'), []) + self.assertEqual(len(metadata.operands), 3) + self.assertEqual(metadata.operands[0].z_ext_value, 100) + self.assertEqual(metadata.operands[1].string, 'abcdef') + self.assertTrue(metadata.operands[2] is None) + +tests.append(TestMetaData) + +# --------------------------------------------------------------------------- + +class TestInlining(TestCase): + def test_inline_call(self): + mod = Module.new(__name__) + callee = mod.add_function(Type.function(Type.int(), [Type.int()]), + name='bar') + + builder = Builder.new(callee.append_basic_block('entry')) + builder.ret(builder.add(callee.args[0], callee.args[0])) + + caller = mod.add_function(Type.function(Type.int(), []), + name='foo') + + builder = Builder.new(caller.append_basic_block('entry')) + callinst = builder.call(callee, [Constant.int(Type.int(), 1234)]) + builder.ret(callinst) + + pre_inlining = str(caller) + self.assertIn('call', pre_inlining) + + self.assertTrue(inline_function(callinst)) + + post_inlining = str(caller) + self.assertNotIn('call', post_inlining) + self.assertIn('2468', post_inlining) + +tests.append(TestInlining) + +# --------------------------------------------------------------------------- + +class TestIssue10(TestCase): + def test_issue10(self): + m = Module.new('a') + ti = Type.int() + tf = Type.function(ti, [ti, ti]) + + f = m.add_function(tf, "func1") + + bb = f.append_basic_block('entry') + + b = Builder.new(bb) + + # There are no instructions in bb. Positioning of the + # builder at beginning (or end) should succeed (trivially). + b.position_at_end(bb) + b.position_at_beginning(bb) + +tests.append(TestIssue10) + +# --------------------------------------------------------------------------- + +class TestOpaque(TestCase): + + def test_opaque(self): + # Create an opaque type + ts = Type.opaque('mystruct') + self.assertTrue('type opaque' in str(ts)) + self.assertTrue(ts.is_opaque) + self.assertTrue(ts.is_identified) + self.assertFalse(ts.is_literal) + #print(ts) + + # Create a recursive type + ts.set_body([Type.int(), Type.pointer(ts)]) + + self.assertEqual(ts.elements[0], Type.int()) + self.assertEqual(ts.elements[1], Type.pointer(ts)) + self.assertEqual(ts.elements[1].pointee, ts) + self.assertFalse(ts.is_opaque) # is not longer a opaque type + #print(ts) + + with self.assertRaises(llvm.LLVMException): + # Cannot redefine + ts.set_body([]) + + def test_opaque_with_no_name(self): + with self.assertRaises(llvm.LLVMException): + Type.opaque('') + +tests.append(TestOpaque) + +# --------------------------------------------------------------------------- +class TestCPUSupport(TestCase): + + def _build_test_module(self): + mod = Module.new('test') + + float = Type.double() + mysinty = Type.function( float, [float] ) + mysin = mod.add_function(mysinty, "mysin") + block = mysin.append_basic_block("entry") + b = Builder.new(block) + + sqrt = Function.intrinsic(mod, lc.INTR_SQRT, [float]) + pow = Function.intrinsic(mod, lc.INTR_POWI, [float]) + cos = Function.intrinsic(mod, lc.INTR_COS, [float]) + + mysin.args[0].name = "x" + x = mysin.args[0] + one = Constant.real(float, "1") + cosx = b.call(cos, [x], "cosx") + cos2 = b.call(pow, [cosx, Constant.int(Type.int(), 2)], "cos2") + onemc2 = b.fsub(one, cos2, "onemc2") # Should use fsub + sin = b.call(sqrt, [onemc2], "sin") + b.ret(sin) + return mod, mysin + + def _template(self, mattrs): + mod, func = self._build_test_module() + ee = self._build_engine(mod, mattrs=mattrs) + + arg = le.GenericValue.real(Type.double(), 1.234) + retval = ee.run_function(func, [arg]) + + golden = math.sin(1.234) + answer = retval.as_real(Type.double()) + self.assertTrue(abs(answer-golden)/golden < 1e-5) + + + def _build_engine(self, mod, mattrs): + if mattrs: + return EngineBuilder.new(mod).mattrs(mattrs).create() + else: + return EngineBuilder.new(mod).create() + + def test_cpu_support2(self): + features = 'sse3', 'sse41', 'sse42', 'avx' + mattrs = ','.join(map(lambda s: '-%s' % s, features)) + print 'disable mattrs', mattrs + self._template(mattrs) + + def test_cpu_support3(self): + features = 'sse41', 'sse42', 'avx' + mattrs = ','.join(map(lambda s: '-%s' % s, features)) + print 'disable mattrs', mattrs + self._template(mattrs) + + def test_cpu_support4(self): + features = 'sse42', 'avx' + mattrs = ','.join(map(lambda s: '-%s' % s, features)) + print 'disable mattrs', mattrs + self._template(mattrs) + + def test_cpu_support5(self): + features = 'avx', + mattrs = ','.join(map(lambda s: '-%s' % s, features)) + print 'disable mattrs', mattrs + self._template(mattrs) + + def test_cpu_support6(self): + features = [] + mattrs = ','.join(map(lambda s: '-%s' % s, features)) + print 'disable mattrs', mattrs + self._template(mattrs) + +tests.append(TestCPUSupport) + +# --------------------------------------------------------------------------- +class TestIntrinsicBasic(TestCase): + + def _build_module(self, float): + mod = Module.new('test') + functy = Type.function(float, [float]) + func = mod.add_function(functy, "mytest%s" % float) + block = func.append_basic_block("entry") + b = Builder.new(block) + return mod, func, b + + def _template(self, mod, func, pyfunc): + float = func.type.pointee.return_type + ee = le.ExecutionEngine.new(mod) + arg = le.GenericValue.real(float, 1.234) + retval = ee.run_function(func, [arg]) + golden = pyfunc(1.234) + answer = retval.as_real(float) + self.assertTrue(abs(answer - golden) / golden < 1e-7) + + def test_sqrt_f32(self): + float = Type.float() + mod, func, b = self._build_module(float) + intr = Function.intrinsic(mod, lc.INTR_SQRT, [float]) + b.ret(b.call(intr, func.args)) + self._template(mod, func, math.sqrt) + + def test_sqrt_f64(self): + float = Type.double() + mod, func, b = self._build_module(float) + intr = Function.intrinsic(mod, lc.INTR_SQRT, [float]) + b.ret(b.call(intr, func.args)) + self._template(mod, func, math.sqrt) + + def test_cos_f32(self): + if sys.platform == 'win32' and BITS == 32: + # float32 support is known to fail on 32-bit Windows + return + float = Type.float() + mod, func, b = self._build_module(float) + intr = Function.intrinsic(mod, lc.INTR_COS, [float]) + b.ret(b.call(intr, func.args)) + self._template(mod, func, math.cos) + + def test_cos_f64(self): + float = Type.double() + mod, func, b = self._build_module(float) + intr = Function.intrinsic(mod, lc.INTR_COS, [float]) + b.ret(b.call(intr, func.args)) + self._template(mod, func, math.cos) + + def test_sin_f32(self): + if sys.platform == 'win32' and BITS == 32: + # float32 support is known to fail on 32-bit Windows + return + float = Type.float() + mod, func, b = self._build_module(float) + intr = Function.intrinsic(mod, lc.INTR_SIN, [float]) + b.ret(b.call(intr, func.args)) + self._template(mod, func, math.sin) + + def test_sin_f64(self): + float = Type.double() + mod, func, b = self._build_module(float) + intr = Function.intrinsic(mod, lc.INTR_SIN, [float]) + b.ret(b.call(intr, func.args)) + self._template(mod, func, math.sin) + + def test_powi_f32(self): + float = Type.float() + mod, func, b = self._build_module(float) + intr = Function.intrinsic(mod, lc.INTR_POWI, [float]) + b.ret(b.call(intr, [func.args[0], lc.Constant.int(Type.int(), 2)])) + self._template(mod, func, lambda x: x**2) + + def test_powi_f64(self): + float = Type.double() + mod, func, b = self._build_module(float) + intr = Function.intrinsic(mod, lc.INTR_POWI, [float]) + b.ret(b.call(intr, [func.args[0], lc.Constant.int(Type.int(), 2)])) + self._template(mod, func, lambda x: x**2) + + + +tests.append(TestIntrinsicBasic) + +# --------------------------------------------------------------------------- + +class TestIntrinsic(TestCase): + def test_bswap(self): + # setup a function and a builder + mod = Module.new('test') + functy = Type.function(Type.int(), []) + func = mod.add_function(functy, "showme") + block = func.append_basic_block("entry") + b = Builder.new(block) + + # let's do bswap on a 32-bit integer using llvm.bswap + val = Constant.int(Type.int(), 0x42) + bswap = Function.intrinsic(mod, lc.INTR_BSWAP, [Type.int()]) + + bswap_res = b.call(bswap, [val]) + b.ret(bswap_res) + + # logging.debug(mod) + + # the output is: + # + # ; ModuleID = 'test' + # + # define void @showme() { + # entry: + # %0 = call i32 @llvm.bswap.i32(i32 42) + # ret i32 %0 + # } + + # let's run the function + ee = le.ExecutionEngine.new(mod) + retval = ee.run_function(func, []) + self.assertEqual(retval.as_int(), 0x42000000) + + def test_mysin(self): + if sys.platform == 'win32' and BITS == 32: + # float32 support is known to fail on 32-bit Windows + return + + # mysin(x) = sqrt(1.0 - pow(cos(x), 2)) + mod = Module.new('test') + + float = Type.float() + mysinty = Type.function( float, [float] ) + mysin = mod.add_function(mysinty, "mysin") + block = mysin.append_basic_block("entry") + b = Builder.new(block) + + sqrt = Function.intrinsic(mod, lc.INTR_SQRT, [float]) + pow = Function.intrinsic(mod, lc.INTR_POWI, [float]) + cos = Function.intrinsic(mod, lc.INTR_COS, [float]) + + mysin.args[0].name = "x" + x = mysin.args[0] + one = Constant.real(float, "1") + cosx = b.call(cos, [x], "cosx") + cos2 = b.call(pow, [cosx, Constant.int(Type.int(), 2)], "cos2") + onemc2 = b.fsub(one, cos2, "onemc2") # Should use fsub + sin = b.call(sqrt, [onemc2], "sin") + b.ret(sin) + #logging.debug(mod) + +# ; ModuleID = 'test' +# +# define void @showme() { +# entry: +# call i32 @llvm.bswap.i32( i32 42 ) ; :0 [#uses +# } +# +# declare i32 @llvm.bswap.i32(i32) nounwind readnone +# +# define float @mysin(float %x) { +# entry: +# %cosx = call float @llvm.cos.f32( float %x ) ; [#uses +# %sin = call float @llvm.sqrt.f32( float %onemc2 ) +# ret float %sin +# } +# +# declare float @llvm.sqrt.f32(float) nounwind readnone +# +# declare float @llvm.powi.f32(float, i32) nounwind readnone +# +# declare float @llvm.cos.f32(float) nounwind readnone + + # let's run the function + ee = le.ExecutionEngine.new(mod) + arg = le.GenericValue.real(Type.float(), 1.234) + retval = ee.run_function(mysin, [arg]) + + golden = math.sin(1.234) + answer = retval.as_real(Type.float()) + self.assertTrue(abs(answer-golden)/golden < 1e-5) + +tests.append(TestIntrinsic) + +# --------------------------------------------------------------------------- + +class TestVolatile(TestCase): + + def test_volatile(self): + mod = Module.new('mod') + functype = Type.function(Type.void(), []) + func = mod.add_function(functype, name='foo') + bb = func.append_basic_block('entry') + bldr = Builder.new(bb) + ptr = bldr.alloca(Type.int()) + + # test load inst + val = bldr.load(ptr) + self.assertFalse(val.is_volatile, "default must be non-volatile") + val.set_volatile(True) + self.assertTrue(val.is_volatile, "fail to set volatile") + val.set_volatile(False) + self.assertFalse(val.is_volatile, "fail to unset volatile") + + # test store inst + store_inst = bldr.store(val, ptr) + self.assertFalse(store_inst.is_volatile, "default must be non-volatile") + store_inst.set_volatile(True) + self.assertTrue(store_inst.is_volatile, "fail to set volatile") + store_inst.set_volatile(False) + self.assertFalse(store_inst.is_volatile, "fail to unset volatile") + + def test_volatile_another(self): + mod = Module.new('mod') + functype = Type.function(Type.void(), []) + func = mod.add_function(functype, name='foo') + bb = func.append_basic_block('entry') + bldr = Builder.new(bb) + ptr = bldr.alloca(Type.int()) + + # test load inst + val = bldr.load(ptr, volatile=True) + self.assertTrue(val.is_volatile, "volatile kwarg does not work") + val.set_volatile(False) + self.assertFalse(val.is_volatile, "fail to unset volatile") + val.set_volatile(True) + self.assertTrue(val.is_volatile, "fail to set volatile") + + # test store inst + store_inst = bldr.store(val, ptr, volatile=True) + self.assertTrue(store_inst.is_volatile, "volatile kwarg does not work") + store_inst.set_volatile(False) + self.assertFalse(store_inst.is_volatile, "fail to unset volatile") + store_inst.set_volatile(True) + self.assertTrue(store_inst.is_volatile, "fail to set volatile") + +tests.append(TestVolatile) + +# --------------------------------------------------------------------------- + +class TestNamedMetaData(TestCase): + def test_named_md(self): + m = Module.new('test_named_md') + nmd = m.get_or_insert_named_metadata('something') + md = MetaData.get(m, [Constant.int(Type.int(), 0xbeef)]) + nmd.add(md) + self.assertTrue(str(nmd).startswith('!something')) + ir = str(m) + self.assertTrue('!something' in ir) + +tests.append(TestNamedMetaData) + +# --------------------------------------------------------------------------- + +def run(verbosity=1): + print('llvmpy is installed in: ' + os.path.dirname(__file__)) + print('llvmpy version: ' + llvm.__version__) + print(sys.version) + + suite = unittest.TestSuite() + for cls in tests: + suite.addTest(unittest.makeSuite(cls)) + + # The default stream fails in IPython qtconsole on Windows, + # so just using sys.stdout + runner = unittest.TextTestRunner(verbosity=verbosity, stream=sys.stdout) + return runner.run(suite) + + +if __name__ == '__main__': + run() diff --git a/llvmpy/capsule.py b/llvmpy/capsule.py index 7a7ceaf..03aa286 100644 --- a/llvmpy/capsule.py +++ b/llvmpy/capsule.py @@ -196,4 +196,8 @@ def downcast(obj, cls): old = unwrap(obj) new = caster(old) used_to_own = has_ownership(old) - return wrap(new, owned=not used_to_own) + res = wrap(new, owned=not used_to_own) + if not res: + raise ValueError("Downcast failed") + return res + diff --git a/llvmpy/gen/binding.py b/llvmpy/gen/binding.py index 6d73cd3..aaa33e4 100644 --- a/llvmpy/gen/binding.py +++ b/llvmpy/gen/binding.py @@ -719,13 +719,26 @@ class cast(_Type): def wrap(self, writer, val): dst = self.python_type.__name__ - return writer.call('py_%(dst)s_from' % locals(), 'PyObject*', val) + if dst == 'int': + unsigned = set([Unsigned, UnsignedLongLong, Uint64, + Size_t, VoidPtr]) + signed = set([LongLong, Int64, Int]) + assert self.binding_type in unsigned|signed + if self.binding_type in signed: + signflag = 'signed' + else: + signflag = 'unsigned' + fn = 'py_%(dst)s_from_%(signflag)s' % locals() + else: + fn = 'py_%(dst)s_from' % locals() + return writer.call(fn, 'PyObject*', val) def unwrap(self, writer, val): src = self.python_type.__name__ dst = self.binding_type.fullname ret = writer.declare(dst) - status = writer.call('py_%(src)s_to' % locals(), 'int', val, ret) + fn = 'py_%(src)s_to' % locals() + status = writer.call(fn, 'int', val, ret) writer.die_if_false(status) return ret diff --git a/llvmpy/include/llvm_binding/conversion.h b/llvmpy/include/llvm_binding/conversion.h index cf4e639..7b8e6df 100644 --- a/llvmpy/include/llvm_binding/conversion.h +++ b/llvmpy/include/llvm_binding/conversion.h @@ -67,7 +67,7 @@ int py_str_to(PyObject *strobj, const char* &strref){ static int py_int_to(PyObject *intobj, int64_t & val){ - if (!PyInt_Check(intobj)) { + if (!PyInt_Check(intobj) and !PyLong_Check(intobj)) { // raise TypeError PyErr_SetString(PyExc_TypeError, "Expecting an int"); return 0; @@ -88,7 +88,7 @@ int py_int_to(PyObject *intobj, int64_t & val){ static int py_int_to(PyObject *intobj, unsigned & val){ - if (!PyInt_Check(intobj)) { + if (!PyInt_Check(intobj) and !PyLong_Check(intobj)) { // raise TypeError PyErr_SetString(PyExc_TypeError, "Expecting an int"); return 0; @@ -100,9 +100,8 @@ int py_int_to(PyObject *intobj, unsigned & val){ static int py_int_to(PyObject *intobj, unsigned long long & val){ - if (!PyInt_Check(intobj)) { + if (!PyInt_Check(intobj) and !PyLong_Check(intobj)) { // raise TypeError - puts(PyString_AsString(PyObject_Str(PyObject_Type(intobj)))); PyErr_SetString(PyExc_TypeError, "Expecting an int 2"); return 0; } @@ -126,12 +125,12 @@ int py_int_to(PyObject *intobj, size_t & val){ static int py_int_to(PyObject *intobj, void* & val){ - if (!PyLong_Check(intobj)) { + if (!PyInt_Check(intobj) and !PyLong_Check(intobj)) { // raise TypeError PyErr_SetString(PyExc_TypeError, "Expecting an int"); return 0; } - val = PyLong_FromVoidPtr(intobj); + val = PyLong_AsVoidPtr(intobj); // success return 1; } @@ -202,13 +201,19 @@ PyObject* py_bool_from(bool val){ } } + static -PyObject* py_int_from(const long long & val){ +PyObject* py_int_from_signed(const long long & val){ return PyLong_FromLongLong(val); } static -PyObject* py_int_from(void * addr){ +PyObject* py_int_from_unsigned(const unsigned long long & val){ + return PyLong_FromUnsignedLongLong(val); +} + +static +PyObject* py_int_from_unsigned(void * addr){ return PyLong_FromVoidPtr(addr); } diff --git a/llvmpy/include/llvm_binding/extra.h b/llvmpy/include/llvm_binding/extra.h index 2bbad42..76c8a16 100644 --- a/llvmpy/include/llvm_binding/extra.h +++ b/llvmpy/include/llvm_binding/extra.h @@ -137,12 +137,19 @@ PyObject* make_small_vector_from_unsigned(PyObject* self, PyObject* args) return pycapsule_new(SV, "llvm::SmallVector"); } +static +PyObject* get_llvm_version(PyObject* self, PyObject* args) +{ + return Py_BuildValue("(ii)", LLVM_VERSION_MAJOR, LLVM_VERSION_MINOR); +} + static PyMethodDef extra_methodtable[] = { #define method(func) { #func, (PyCFunction)func, METH_VARARGS, NULL } method( make_raw_ostream_for_printing ), method( make_small_vector_from_types ), method( make_small_vector_from_values ), method( make_small_vector_from_unsigned ), + method( get_llvm_version ), #undef method { NULL } }; @@ -185,7 +192,8 @@ struct extract { template static - bool from_py_sequence(VecTy& vec, PyObject* seq, const char *capsuleName) + bool from_py_sequence(VecTy& vec, PyObject* seq, const char *capsuleName, + bool accept_null=false) { Py_ssize_t N = PySequence_Size(seq); for (Py_ssize_t i = 0; i < N; ++i) { @@ -193,15 +201,23 @@ struct extract { if (!item) { return false; } - auto_pyobject capsule = PyObject_GetAttrString(*item, "_ptr"); - if (!capsule) { - return false; + if (accept_null and Py_None == *item) { + vec.push_back(NULL); + } else { + auto_pyobject capsule = PyObject_GetAttrString(*item, "_ptr"); + if (!capsule) { + return false; + } + void* ptr = PyCapsule_GetPointer(*capsule, capsuleName); + if (!ptr) { + return false; + } + ElemTy* res = typecast::from(ptr); + if (!res) { + return false; + } + vec.push_back(res); } - void* ptr = PyCapsule_GetPointer(*capsule, capsuleName); - if (!ptr) { - return false; - } - vec.push_back(static_cast(ptr)); } return true; } @@ -609,6 +625,18 @@ PyObject* StructType_setBody(llvm::StructType* Self, Py_RETURN_NONE; } +static +PyObject* StructType_get(llvm::LLVMContext& Cxt, + PyObject* Elems, + bool isPacked=false) +{ + using namespace llvm; + std::vector elements; + extract::from_py_sequence(elements, Elems, "llvm::Type"); + StructType *sty = StructType::get(Cxt, elements, isPacked); + return pycapsule_new(sty, "llvm::Type", "llvm::StructType"); +} + static PyObject* Module_list_globals(llvm::Module* Mod) { @@ -656,7 +684,7 @@ PyObject* ConstantArray_get(llvm::ArrayType* Ty, PyObject* Consts) std::vector vec_consts; bool ok = extract::from_py_sequence(vec_consts, Consts, - "llvm::Value"); + "llvm::Value"); if (not ok) return NULL; Constant* ary = ConstantArray::get(Ty, vec_consts); return pycapsule_new(ary, "llvm::Value", "llvm::Constant"); @@ -724,7 +752,9 @@ static PyObject* MDNode_get(llvm::LLVMContext &Cxt, PyObject* Vals) { std::vector vals; - bool ok = extract::from_py_sequence(vals, Vals, "llvm::Value"); + bool accept_null = true; + bool ok = extract::from_py_sequence(vals, Vals, "llvm::Value", + accept_null); if (not ok) return NULL; llvm::MDNode* md = llvm::MDNode::get(Cxt, vals); return pycapsule_new(md, "llvm::Value", "llvm::MDNode"); @@ -750,7 +780,7 @@ PyObject* IRBuilder_CreateAggregateRet(llvm::IRBuilder<>* builder, if (not ok) return NULL; Value** ptr_values = &vec_values[0]; ReturnInst* inst = builder->CreateAggregateRet(ptr_values, N); - return pycapsule_new(inst, "llvm::Value", "llvm:ReturnInst"); + return pycapsule_new(inst, "llvm::Value", "llvm::ReturnInst"); } static diff --git a/llvmpy/src/Argument.py b/llvmpy/src/Argument.py index eac4b07..64db072 100644 --- a/llvmpy/src/Argument.py +++ b/llvmpy/src/Argument.py @@ -1,12 +1,14 @@ from binding import * from namespace import llvm -from Value import Argument +from Value import Argument, Value from Attributes import Attributes @Argument class Argument: _include_ = 'llvm/Argument.h' + _downcast_ = Value + addAttr = Method(Void, ref(Attributes)) removeAttr = Method(Void, ref(Attributes)) getParamAlignment = Method(cast(Unsigned, int)) diff --git a/llvmpy/src/Attributes.py b/llvmpy/src/Attributes.py index 235d2c8..c6a8d97 100644 --- a/llvmpy/src/Attributes.py +++ b/llvmpy/src/Attributes.py @@ -20,7 +20,7 @@ class Attributes: delete = Destructor() - get = Method(Attributes, ref(LLVMContext), ref(AttrBuilder)) + get = StaticMethod(Attributes, ref(LLVMContext), ref(AttrBuilder)) @AttrBuilder diff --git a/llvmpy/src/BasicBlock.py b/llvmpy/src/BasicBlock.py index 81edf37..4ed4f66 100644 --- a/llvmpy/src/BasicBlock.py +++ b/llvmpy/src/BasicBlock.py @@ -21,4 +21,6 @@ class BasicBlock: removePredecessor = Method(Void, ptr(BasicBlock), cast(bool, Bool)) removePredecessor |= Method(Void, ptr(BasicBlock)) - getInstList = CustomMethod('BasicBlock_getInstList', PyObjectPtr) \ No newline at end of file + getInstList = CustomMethod('BasicBlock_getInstList', PyObjectPtr) + + eraseFromParent = Method() diff --git a/llvmpy/src/Constant.py b/llvmpy/src/Constant.py index 5407d71..0a79bd3 100644 --- a/llvmpy/src/Constant.py +++ b/llvmpy/src/Constant.py @@ -1,18 +1,9 @@ from binding import * from namespace import llvm - -from Value import Constant, Value - -UndefValue = llvm.Class(Constant) -ConstantInt = llvm.Class(Constant) -ConstantFP = llvm.Class(Constant) -ConstantArray = llvm.Class(Constant) -ConstantStruct = llvm.Class(Constant) -ConstantVector = llvm.Class(Constant) -ConstantDataSequential = llvm.Class(Constant) -ConstantDataArray = llvm.Class(ConstantDataSequential) -ConstantExpr = llvm.Class(Constant) - +from Value import Value +from Value import Constant, UndefValue, ConstantInt, ConstantFP, ConstantArray +from Value import ConstantStruct, ConstantVector, ConstantVector +from Value import ConstantDataSequential, ConstantDataArray, ConstantExpr from LLVMContext import LLVMContext from ADT.StringRef import StringRef from ADT.SmallVector import SmallVector_Value, SmallVector_Unsigned @@ -81,6 +72,8 @@ class UndefValue: @ConstantInt class ConstantInt: + _downcast_ = Constant, Value + get = StaticMethod(ptr(ConstantInt), ptr(IntegerType), cast(int, Unsigned), @@ -95,6 +88,8 @@ class ConstantInt: @ConstantFP class ConstantFP: + _downcast_ = Constant, Value + get = StaticMethod(ptr(Constant), ptr(Type), cast(float, Double)) getNegativeZero = StaticMethod(ptr(ConstantFP), ptr(Type)) getInfinity = StaticMethod(ptr(ConstantFP), ptr(Type), cast(bool, Bool)) @@ -107,6 +102,8 @@ class ConstantFP: @ConstantArray class ConstantArray: + _downcast_ = Constant, Value + get = CustomStaticMethod('ConstantArray_get', PyObjectPtr, # ptr(Constant), ptr(ArrayType), @@ -116,6 +113,8 @@ class ConstantArray: @ConstantStruct class ConstantStruct: + _downcast_ = Constant, Value + get = CustomStaticMethod('ConstantStruct_get', PyObjectPtr, # ptr(Constant) ptr(StructType), @@ -130,6 +129,8 @@ class ConstantStruct: @ConstantVector class ConstantVector: + _downcast_ = Constant, Value + get = CustomStaticMethod('ConstantVector_get', PyObjectPtr, # ptr(Constant) PyObjectPtr, # constants @@ -138,11 +139,13 @@ class ConstantVector: @ConstantDataSequential class ConstantDataSequential: - pass + _downcast_ = Constant, Value @ConstantDataArray class ConstantDataArray: + _downcast_ = Constant, Value + getString = StaticMethod(ptr(Constant), ref(LLVMContext), cast(str, StringRef), @@ -174,6 +177,8 @@ def _factory_const_type(): @ConstantExpr class ConstantExpr: + _downcast_ = Constant, Value + getAlignOf = _factory(ptr(Type)) getSizeOf = _factory(ptr(Type)) getOffsetOf = _factory(ptr(Type), ptr(Constant)) diff --git a/llvmpy/src/DerivedTypes.py b/llvmpy/src/DerivedTypes.py index a34c2f1..40724e0 100644 --- a/llvmpy/src/DerivedTypes.py +++ b/llvmpy/src/DerivedTypes.py @@ -9,6 +9,7 @@ FunctionType = llvm.Class(Type) @FunctionType class FunctionType: _include_ = 'llvm/DerivedTypes.h' + _downcast_ = Type _get = StaticMethod(ptr(FunctionType), ptr(Type), cast(bool, Bool)) _get |= StaticMethod(ptr(FunctionType), ptr(Type), ref(SmallVector_Type), diff --git a/llvmpy/src/ExecutionEngine/ExecutionEngine.py b/llvmpy/src/ExecutionEngine/ExecutionEngine.py index 0bd4714..bcf66fd 100644 --- a/llvmpy/src/ExecutionEngine/ExecutionEngine.py +++ b/llvmpy/src/ExecutionEngine/ExecutionEngine.py @@ -41,7 +41,7 @@ class ExecutionEngine: @CustomPythonMethod def removeModule(self, module): if self._removeModule(module): - capsule.obtain_ownership(module._ptr) + capsule.obtain_ownership(module._capsule) return True return False diff --git a/llvmpy/src/Function.py b/llvmpy/src/Function.py index d82b5d3..52db622 100644 --- a/llvmpy/src/Function.py +++ b/llvmpy/src/Function.py @@ -1,6 +1,6 @@ from binding import * from namespace import llvm -from Value import GlobalValue, Constant, Function, Argument +from Value import GlobalValue, Constant, Function, Argument, Value from BasicBlock import BasicBlock from Attributes import Attributes from Type import Type @@ -11,7 +11,7 @@ from CallingConv import CallingConv @Function class Function: _include_ = 'llvm/Function.h' - _downcast_ = GlobalValue, Constant + _downcast_ = GlobalValue, Constant, Value getReturnType = Method(ptr(Type)) getFunctionType = Method(ptr(FunctionType)) diff --git a/llvmpy/src/GenericValue.py b/llvmpy/src/GenericValue.py index 74587ba..73a3709 100644 --- a/llvmpy/src/GenericValue.py +++ b/llvmpy/src/GenericValue.py @@ -26,8 +26,8 @@ class GenericValue: valueIntWidth = _accessor('ValueIntWidth', cast(Unsigned, int)) - toSignedInt = _accessor('ToSignedInt', cast(UnsignedLongLong, int)) - toUnsignedInt = _accessor('ToUnsignedInt', cast(LongLong, int)) + toSignedInt = _accessor('ToSignedInt', cast(LongLong, int)) + toUnsignedInt = _accessor('ToUnsignedInt', cast(UnsignedLongLong, int)) toFloat = _accessor('ToFloat', cast(Double, float), ptr(Type)) diff --git a/llvmpy/src/IRBuilder.py b/llvmpy/src/IRBuilder.py index 095122f..445ff11 100644 --- a/llvmpy/src/IRBuilder.py +++ b/llvmpy/src/IRBuilder.py @@ -281,7 +281,7 @@ class IRBuilder: _CreateExtractValue.realname = 'CreateExtractValue' @CustomPythonMethod - def CreateExtractValue(self, args): + def CreateExtractValue(self, *args): from llvmpy import extra args = list(args) valuelist = args[1] @@ -316,3 +316,8 @@ class IRBuilder: # New in llvm 3.3 #CreateVectorSplat = Method(ptr(Value), cast(int, Unsigned), ptr(Value), # cast(str, StringRef)) + + + Insert = Method(ptr(Instruction), + ptr(Instruction), + cast(str, StringRef)).require_only(1) diff --git a/llvmpy/src/Instruction.py b/llvmpy/src/Instruction.py index b3fa701..9763e7c 100644 --- a/llvmpy/src/Instruction.py +++ b/llvmpy/src/Instruction.py @@ -1,6 +1,6 @@ from binding import * from namespace import llvm -from Value import Value, MDNode, User, BasicBlock, Function +from Value import Value, MDNode, User, BasicBlock, Function, ConstantInt Instruction = llvm.Class(User) @@ -66,13 +66,14 @@ SynchronizationScope = llvm.Enum('SynchronizationScope', from ADT.StringRef import StringRef from CallingConv import CallingConv from Attributes import Attributes -from Constant import ConstantInt from Type import Type @Instruction class Instruction: + _downcast_ = Value, User + removeFromParent = Method() eraseFromParent = Method() eraseFromParent.disowning = True @@ -133,6 +134,7 @@ class BinaryOperator: @CallInst class CallInst: _downcast_ = Value, Instruction + getCallingConv = Method(CallingConv.ID) setCallingConv = Method(Void, CallingConv.ID) getParamAlignment = Method(cast(Unsigned, int), cast(int, Unsigned)) diff --git a/llvmpy/src/Metadata.py b/llvmpy/src/Metadata.py index 94088ca..d5cc4b1 100644 --- a/llvmpy/src/Metadata.py +++ b/llvmpy/src/Metadata.py @@ -10,6 +10,7 @@ from Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter @MDNode class MDNode: + _downcast_ = Value replaceOperandWith = Method(Void, cast(int, Unsigned), ptr(Value)) getOperand = Method(ptr(Value), cast(int, Unsigned)) getNumOperands = Method(cast(Unsigned, int)) @@ -24,6 +25,7 @@ class MDNode: @MDString class MDString: + _downcast_ = Value get = StaticMethod(ptr(MDString), ref(LLVMContext), cast(str, StringRef)) getString = Method(cast(StringRef, str)) getLength = Method(cast(int, Unsigned)) diff --git a/llvmpy/src/Target/TargetMachine.py b/llvmpy/src/Target/TargetMachine.py index 29960fa..1bd6843 100644 --- a/llvmpy/src/Target/TargetMachine.py +++ b/llvmpy/src/Target/TargetMachine.py @@ -9,7 +9,7 @@ from src.Support.CodeGen import CodeModel, TLSModel, CodeGenOpt, Reloc from src.GlobalValue import GlobalValue from src.DataLayout import DataLayout from src.TargetTransformInfo import (ScalarTargetTransformInfo, - VectorTargetTransformInfo) + VectorTargetTransformInfo) from src.PassManager import PassManagerBase from src.Support.FormattedStream import formatted_raw_ostream @@ -40,9 +40,9 @@ class TargetMachine: getDataLayout = Method(const(ownedptr(DataLayout))) getScalarTargetTransformInfo = Method(const( - ownedptr(ScalarTargetTransformInfo))) + ownedptr(ScalarTargetTransformInfo))) getVectorTargetTransformInfo = Method(const( - ownedptr(VectorTargetTransformInfo))) + ownedptr(VectorTargetTransformInfo))) addPassesToEmitFile = Method(cast(bool, Bool), ref(PassManagerBase), diff --git a/llvmpy/src/TargetTransformInfo.py b/llvmpy/src/TargetTransformInfo.py index 5761281..1208050 100644 --- a/llvmpy/src/TargetTransformInfo.py +++ b/llvmpy/src/TargetTransformInfo.py @@ -1,11 +1,14 @@ from binding import * -from namespace import llvm +from src.namespace import llvm +from src.Pass import ImmutablePass llvm.includes.add('llvm/TargetTransformInfo.h') +TargetTransformInfo = llvm.Class(ImmutablePass) ScalarTargetTransformInfo = llvm.Class() VectorTargetTransformInfo = llvm.Class() + @ScalarTargetTransformInfo class ScalarTargetTransformInfo: delete = Destructor() @@ -14,3 +17,8 @@ class ScalarTargetTransformInfo: class VectorTargetTransformInfo: delete = Destructor() +@TargetTransformInfo +class TargetTransformInfo: + new = Constructor(ptr(ScalarTargetTransformInfo), + ptr(VectorTargetTransformInfo)) + diff --git a/llvmpy/src/Transforms/PassManagerBuilder.py b/llvmpy/src/Transforms/PassManagerBuilder.py index a95b6df..c940062 100644 --- a/llvmpy/src/Transforms/PassManagerBuilder.py +++ b/llvmpy/src/Transforms/PassManagerBuilder.py @@ -1,10 +1,13 @@ from binding import * from ..namespace import llvm -from ..PassManager import PassManagerBase, FunctionPassManager -from ..Target.TargetLibraryInfo import TargetLibraryInfo -from ..Pass import Pass -@llvm.Class() +PassManagerBuilder = llvm.Class() + +from src.PassManager import PassManagerBase, FunctionPassManager +from src.Target.TargetLibraryInfo import TargetLibraryInfo +from src.Pass import Pass + +@PassManagerBuilder class PassManagerBuilder: _include_ = 'llvm/Transforms/IPO/PassManagerBuilder.h' diff --git a/llvmpy/src/Transforms/Utils/Cloning.py b/llvmpy/src/Transforms/Utils/Cloning.py index 1971177..c6eaf0a 100644 --- a/llvmpy/src/Transforms/Utils/Cloning.py +++ b/llvmpy/src/Transforms/Utils/Cloning.py @@ -1,11 +1,15 @@ from binding import * from src.namespace import llvm -from src.Module import Module -from src.Instruction import CallInst llvm.includes.add('llvm/Transforms/Utils/Cloning.h') -@llvm.Class() +InlineFunctionInfo = llvm.Class() + + +from src.Module import Module +from src.Instruction import CallInst + +@InlineFunctionInfo class InlineFunctionInfo: new = Constructor() delete = Destructor() diff --git a/llvmpy/src/Type.py b/llvmpy/src/Type.py index ec0bf88..8e62137 100644 --- a/llvmpy/src/Type.py +++ b/llvmpy/src/Type.py @@ -146,25 +146,27 @@ class Type: @IntegerType class IntegerType: - pass + _downcast_ = Type @CompositeType class CompositeType: - pass + _downcast_ = Type @SequentialType class SequentialType: - pass + _downcast_ = Type @ArrayType class ArrayType: + _downcast_ = Type getNumElements = Method(cast(Uint64, int)) get = StaticMethod(ptr(ArrayType), ptr(Type), cast(int, Uint64)) isValidElementType = StaticMethod(cast(Bool, bool), ptr(Type)) @PointerType class PointerType: + _downcast_ = Type getAddressSpace = Method(cast(Unsigned, int)) get = StaticMethod(ptr(PointerType), ptr(Type), cast(int, Unsigned)) getUnqual = StaticMethod(ptr(PointerType), ptr(Type)) @@ -172,6 +174,7 @@ class PointerType: @VectorType class VectorType: + _downcast_ = Type getNumElements = Method(cast(Unsigned, int)) getBitWidth = Method(cast(Unsigned, int)) get = StaticMethod(ptr(VectorType), ptr(Type), cast(int, Unsigned)) @@ -184,6 +187,7 @@ class VectorType: @StructType class StructType: + _downcast_ = Type isPacked = Method(cast(Bool, bool)) isLiteral = Method(cast(Bool, bool)) isOpaque = Method(cast(Bool, bool)) @@ -203,10 +207,12 @@ class StructType: cast(str, StringRef), ).require_only(1) - get = StaticMethod(ptr(StructType), - ref(LLVMContext), - cast(bool, Bool), # is packed - ).require_only(1) + get = CustomStaticMethod('StructType_get', + PyObjectPtr, # StructType* + ref(LLVMContext), + PyObjectPtr, # ArrayRef elements + cast(bool, Bool), # is packed + ).require_only(2) isValidElementType = StaticMethod(cast(Bool, bool), ptr(Type)) diff --git a/llvmpy/src/Value.py b/llvmpy/src/Value.py index 88f221c..b10807a 100644 --- a/llvmpy/src/Value.py +++ b/llvmpy/src/Value.py @@ -11,6 +11,15 @@ BasicBlock = llvm.Class(Value) Constant = llvm.Class(User) GlobalValue = llvm.Class(Constant) Function = llvm.Class(GlobalValue) +UndefValue = llvm.Class(Constant) +ConstantInt = llvm.Class(Constant) +ConstantFP = llvm.Class(Constant) +ConstantArray = llvm.Class(Constant) +ConstantStruct = llvm.Class(Constant) +ConstantVector = llvm.Class(Constant) +ConstantDataSequential = llvm.Class(Constant) +ConstantDataArray = llvm.Class(ConstantDataSequential) +ConstantExpr = llvm.Class(Constant) from Support.raw_ostream import raw_ostream from Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter diff --git a/test/constants.py b/test/constants.py index afe1020..90a5a53 100644 --- a/test/constants.py +++ b/test/constants.py @@ -21,8 +21,6 @@ def _build_test_module(datatype, constants): bb_entry = func_subject.append_basic_block('entry') builder = Builder.new(bb_entry) - - for k in constants: builder.call(func_subject.args[0], [k]) diff --git a/test/malloc.py b/test/malloc.py new file mode 100644 index 0000000..1613a36 --- /dev/null +++ b/test/malloc.py @@ -0,0 +1,16 @@ +from llvm.core import * + +def test(): + m = Module.new('sdf') + f = m.add_function(Type.function(Type.void(), []), 'foo') + bb = f.append_basic_block('entry') + b = Builder.new(bb) + alloc = b.malloc(Type.int(), 'ha') + inst = b.free(alloc) + alloc = b.malloc_array(Type.int(), Constant.int(Type.int(), 10), 'hee') + inst = b.free(alloc) + b.ret_void() + print m + +if __name__ == '__main__': + test() diff --git a/test/operands.py b/test/operands.py index 674bc9e..32fb811 100644 --- a/test/operands.py +++ b/test/operands.py @@ -49,6 +49,7 @@ class TestOperands(unittest.TestCase): i1 = test_func.basic_blocks[0].instructions[0] i2 = test_func.basic_blocks[0].instructions[1] + logging.debug("Testing User.operand_count ..") self.assertEqual(i1.operand_count, 3) @@ -61,6 +62,7 @@ class TestOperands(unittest.TestCase): self.assert_(i1.operands[1] is test_func.args[1]) self.assert_(i2.operands[0] is i1) self.assert_(i2.operands[1] is test_func.args[2]) + self.assertEqual(len(i1.operands), 3) self.assertEqual(len(i2.operands), 2) diff --git a/test/testall.py b/test/testall.py index 3b5f0c3..231bca3 100644 --- a/test/testall.py +++ b/test/testall.py @@ -18,16 +18,6 @@ def do_llvmexception(): e = LLVMException() -def do_ownable(): - print(" Testing class Ownable") - o = Ownable(None, lambda x: None) - try: - o._own(None) - o._disown() - except LLVMException: - pass - - def do_misc(): print(" Testing miscellaneous functions") try: @@ -44,7 +34,6 @@ def do_misc(): def do_llvm(): print(" Testing module llvm") do_llvmexception() - do_ownable() do_misc() @@ -208,7 +197,9 @@ def do_constant(): Constant.struct([Constant.int(ti,42)]*10) Constant.packed_struct([Constant.int(ti,42)]*10) Constant.vector([Constant.int(ti,42)]*10) + Constant.sizeof(ti) + k = Constant.int(ti, 10) f = Constant.real(Type.float(), 3.1415) k.neg().not_().add(k).sub(k).mul(k).udiv(k).sdiv(k).urem(k) @@ -271,7 +262,8 @@ def do_global_variable(): def do_argument(): print(" Testing class Argument") m = Module.new('a') - ft = Type.function(ti, [ti]) + tip = Type.pointer(ti) + ft = Type.function(tip, [tip]) f = Function.new(m, ft, 'func') a = f.args[0] a.add_attribute(ATTR_ZEXT) @@ -301,13 +293,14 @@ def do_function(): c = f.collector a = list(f.args) g = f.basic_block_count - g = f.get_entry_basic_block() - g = f.append_basic_block('a') - g = f.get_entry_basic_block() +# g = f.entry_basic_block +# g = f.append_basic_block('a') +# g = f.entry_basic_block g = list(f.basic_blocks) f.add_attribute(ATTR_NO_RETURN) f.add_attribute(ATTR_ALWAYS_INLINE) f.remove_attribute(ATTR_NO_RETURN) + # LLVM misbehaves: #try: # f.verify() @@ -414,7 +407,7 @@ def do_builder(): b.position_at_beginning(blk) b.position_at_end(blk) b.position_before(blk.instructions[0]) - blk2 = b.block + blk2 = b.basic_block b.ret_void() b.ret(Constant.int(ti, 10)) _do_builder_mrv() @@ -552,7 +545,7 @@ def do_genericvalue(): def do_executionengine(): print(" Testing class ExecutionEngine") m = Module.new('a') - ee = ExecutionEngine.new(m, True) + ee = ExecutionEngine.new(m, False) # True) ft = Type.function(ti, []) f = m.add_function(ft, 'func') bb = f.append_basic_block('entry') @@ -573,7 +566,7 @@ def do_executionengine(): ee3 = ExecutionEngine.new(m4, False) ee3.add_module(m5) x = ee3.remove_module(m5) - check_is_module(x) + isinstance(x, Module) def do_llvm_ee(): From d2dc34cdd3f5d772be398efdbcd222ad6b1df826 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 13 Feb 2013 17:12:54 -0600 Subject: [PATCH 70/85] Try to fix invalid dtor call --- llvm/core.py | 72 +++++++++++++++++++++++++------------ llvmpy/capsule.py | 20 ++++++----- llvmpy/gen/binding.py | 2 +- llvmpy/gen/codegen.py | 4 ++- llvmpy/src/IRBuilder.py | 2 +- llvmpy/src/Instruction.py | 75 +++++++++++++++++++++------------------ 6 files changed, 108 insertions(+), 67 deletions(-) diff --git a/llvm/core.py b/llvm/core.py index 1c3184c..f2af943 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -475,28 +475,31 @@ class Module(llvm.Wrapper): def add_function(self, ty, name): """Add a function of given type with given name.""" - fn = self.get_function_named(name) - if fn is not None: - raise llvm.LLVMException("Duplicated function %s" % name) - return self.get_or_insert_function(ty, name) + return Function.new(self, ty, name) +# fn = self.get_function_named(name) +# if fn is not None: +# raise llvm.LLVMException("Duplicated function %s" % name) +# return self.get_or_insert_function(ty, name) def get_function_named(self, name): """Return a Function object representing function with given name.""" - fn = self._ptr.getFunction(name) - if fn is not None: - return _make_value(fn) + return Function.get(self, name) +# fn = self._ptr.getFunction(name) +# if fn is not None: +# return _make_value(fn) def get_or_insert_function(self, ty, name): """Like get_function_named(), but does add_function() first, if function is not present.""" - constant = self._ptr.getOrInsertFunction(name, ty._ptr) - try: - fn = constant._downcast(api.llvm.Function) - except ValueError: - # bitcasted to function type - return _make_value(constant) - else: - return _make_value(fn) + return Function.get_or_insert(self, ty, name) +# constant = self._ptr.getOrInsertFunction(name, ty._ptr) +# try: +# fn = constant._downcast(api.llvm.Function) +# except ValueError: +# # bitcasted to function type +# return _make_value(constant) +# else: +# return _make_value(fn) @property def functions(self): @@ -616,6 +619,10 @@ class Type(llvm.Wrapper): ptr = ptr._downcast(type(self)._type_) super(Type, self).__init__(ptr) + @property + def kind(self): + return self._ptr.getTypeID() + @staticmethod def int(bits=32): """Create an integer type having the given bit width.""" @@ -830,7 +837,6 @@ class FunctionType(Type): return self._ptr.getNumParams() - class StructType(Type): """Represents a structure type.""" _type_ = api.llvm.StructType @@ -1385,15 +1391,32 @@ class Function(GlobalValue): @staticmethod def new(module, func_ty, name): - return module.add_function(func_ty, name) + try: + fn = Function.get(module, name) + except llvm.LLVMException: + return Function.get_or_insert(module, func_ty, name) + else: + raise llvm.LLVMException("Duplicated function %s" % name) + @staticmethod def get_or_insert(module, func_ty, name): - return module.get_or_insert_function(func_ty, name) + constant = module._ptr.getOrInsertFunction(name, func_ty._ptr) + try: + fn = constant._downcast(api.llvm.Function) + except ValueError: + # bitcasted to function type + return _make_value(constant) + else: + return _make_value(fn) @staticmethod def get(module, name): - return module.get_function_named(name) + fn = module._ptr.getFunction(name) + if fn is None: + raise llvm.LLVMException("no function named `%s`" % name) + else: + return _make_value(fn) @staticmethod def intrinsic(module, intrinsic_id, types): @@ -1450,6 +1473,10 @@ class Function(GlobalValue): assert self.basic_block_count return _make_value(self._ptr.getEntryBlock()) + def get_entry_basic_block(self): + "Deprecated. Use entry_basic_block instead" + return self.entry_basic_block + def append_basic_block(self, name): context = api.llvm.getGlobalContext() bb = api.llvm.BasicBlock.Create(context, name, self._ptr, None) @@ -1857,6 +1884,7 @@ class Builder(llvm.Wrapper): """Position the builder at the end of the given block. Next instruction inserted will be last one in the block.""" + self._ptr.SetInsertPoint(bblk._ptr) def position_before(self, instr): @@ -2111,9 +2139,9 @@ class Builder(llvm.Wrapper): def insert_value(self, retval, rhs, idx, name=""): return _make_value(self._ptr.CreateInsertValue(retval._ptr, - rhs._ptr, - [idx], - name)) + rhs._ptr, + [idx], + name)) def phi(self, ty, name=""): return _make_value(self._ptr.CreatePHI(ty._ptr, 2, name)) diff --git a/llvmpy/capsule.py b/llvmpy/capsule.py index 03aa286..0b1f203 100644 --- a/llvmpy/capsule.py +++ b/llvmpy/capsule.py @@ -19,13 +19,14 @@ def set_debug(enabled): def _capsule_weakref_dtor(item): addr = item.pointer + name = item.name _addr2refct[addr] -= 1 refct = _addr2refct[addr] assert refct >= 0, "RefCt drop below 0" if refct == 0: - dtor = _addr2dtor.pop(addr, None) + dtor = _addr2dtor.pop((name, addr), None) if dtor is not None: - logger.debug('Destroy %s %s', item.name, hex(item.pointer)) + logger.debug('Destroy %s %s', name, hex(addr)) dtor(item.capsule) class Capsule(object): @@ -92,26 +93,28 @@ _cache = defaultdict(WeakValueDictionary) def release_ownership(old): logger.debug('Release %s', old) addr = Capsule.getPointer(old) - - if _addr2dtor.get(addr) is None: + name = Capsule.getName(old) + if _addr2dtor.get((name, addr)) is None: clsname = Capsule.getClassName(old) if not _pyclasses[clsname]._has_dtor(): return # Guard duplicated release raise Exception("Already released") - _addr2dtor[addr] = None + _addr2dtor[(name, addr)] = None def obtain_ownership(cap): cls = cap.get_class() if cls._has_dtor(): addr = cap.pointer + name = cap.name assert _addr2dtor[addr] is None - _addr2dtor[addr] = cls._delete_ + _addr2dtor[(name, addr)] = cls._delete_ def has_ownership(cap): addr = Capsule.getPointer(cap) - return _addr2dtor.get(addr) is not None + name = Capsule.getName(cap) + return _addr2dtor.get((name, addr)) is not None def wrap(cap, owned=False): '''Wrap a PyCapsule with the corresponding Wrapper class. @@ -125,11 +128,12 @@ def wrap(cap, owned=False): cap = Capsule(cap) cls = cap.get_class() addr = cap.pointer + name = cap.name try: # lookup cached object return _cache[cls][addr] except KeyError: if not owned and cls._has_dtor(): - _addr2dtor[addr] = cls._delete_ + _addr2dtor[(name, addr)] = cls._delete_ obj = cap.instantiate() _cache[cls][addr] = obj # cache it return obj diff --git a/llvmpy/gen/binding.py b/llvmpy/gen/binding.py index aaa33e4..4454d72 100644 --- a/llvmpy/gen/binding.py +++ b/llvmpy/gen/binding.py @@ -329,7 +329,7 @@ class Class(SubModule, _Type): fmt = 'PyCapsule_GetPointer(%(val)s, "%(name)s")' name = self.capsule_name raw = writer.declare('void*', fmt % locals()) - writer.die_if_false(raw) + writer.die_if_false(raw, verbose=name) ptrty = ptr(self).fullname ty = self.fullname fmt = 'typecast< %(ty)s >::from(%(raw)s)' diff --git a/llvmpy/gen/codegen.py b/llvmpy/gen/codegen.py index dd499d6..abde437 100644 --- a/llvmpy/gen/codegen.py +++ b/llvmpy/gen/codegen.py @@ -208,8 +208,10 @@ class CppCodeWriter(CodeWriterBase): self.return_null() return ret - def die_if_false(self, val): + def die_if_false(self, val, verbose=None): with self.block('if(!%(val)s)' % locals()): + if verbose: + self.println('puts("Error: %s");' % verbose) self.return_null() def raises(self, exccls, msg): diff --git a/llvmpy/src/IRBuilder.py b/llvmpy/src/IRBuilder.py index 445ff11..8590430 100644 --- a/llvmpy/src/IRBuilder.py +++ b/llvmpy/src/IRBuilder.py @@ -294,7 +294,7 @@ class IRBuilder: _CreateInsertValue.realname = 'CreateInsertValue' @CustomPythonMethod - def CreateInsertValue(self, args): + def CreateInsertValue(self, *args): from llvmpy import extra args = list(args) valuelist = args[2] diff --git a/llvmpy/src/Instruction.py b/llvmpy/src/Instruction.py index 9763e7c..4761e16 100644 --- a/llvmpy/src/Instruction.py +++ b/llvmpy/src/Instruction.py @@ -120,16 +120,17 @@ class Instruction: @AtomicCmpXchgInst class AtomicCmpXchgInst: - pass + _downcast_ = Value, Instruction @AtomicRMWInst class AtomicRMWInst: + _downcast_ = Value, Instruction BinOp = Enum('Xchg', 'Add', 'Sub', 'And', 'Nand', 'Or', 'Xor', 'Max', 'Min', 'UMax', 'UMin', 'FIRST_BINOP', 'LAST_BINOP', 'BAD_BINOP') @BinaryOperator class BinaryOperator: - pass + _downcast_ = Value, Instruction @CallInst class CallInst: @@ -159,6 +160,7 @@ class CallInst: @CmpInst class CmpInst: + _downcast_ = Value, Instruction Predicate = Enum('FCMP_FALSE', 'FCMP_OEQ', 'FCMP_OGT', 'FCMP_OGE', 'FCMP_OLT', 'FCMP_OLE', 'FCMP_ONE', 'FCMP_ORD', 'FCMP_UNO', 'FCMP_UEQ', 'FCMP_UGT', 'FCMP_UGE', 'FCMP_ULT', 'FCMP_ULE', @@ -175,30 +177,31 @@ class CmpInst: @ExtractElementInst class ExtractElementInst: - pass + _downcast_ = Value, Instruction @FenceInst class FenceInst: - pass + _downcast_ = Value, Instruction @GetElementPtrInst class GetElementPtrInst: - pass + _downcast_ = Value, Instruction @InsertElementInst class InsertElementInst: - pass + _downcast_ = Value, Instruction @InsertValueInst class InsertValueInst: - pass + _downcast_ = Value, Instruction @LandingPadInst class LandingPadInst: - pass + _downcast_ = Value, Instruction @PHINode class PHINode: + _downcast_ = Value, Instruction getNumIncomingValues = Method(cast(Unsigned, int)) getIncomingValue = Method(ptr(Value), cast(int, Unsigned)) setIncomingValue = Method(Void, cast(int, Unsigned), ptr(Value)) @@ -210,15 +213,15 @@ class PHINode: @SelectInst class SelectInst: - pass + _downcast_ = Value, Instruction @ShuffleVectorInst class ShuffleVectorInst: - pass + _downcast_ = Value, Instruction @StoreInst class StoreInst: - _downcast_ = Instruction + _downcast_ = Value, Instruction isVolatile = Method(cast(Bool, bool)) isSimple = Method(cast(Bool, bool)) isUnordered = Method(cast(Bool, bool)) @@ -237,38 +240,40 @@ class StoreInst: @TerminatorInst class TerminatorInst: + _downcast_ = Value, Instruction getNumSuccessors = Method(cast(Unsigned, int)) getSuccessor = Method(ptr(BasicBlock), cast(int, Unsigned)) setSuccessor = Method(Void, cast(int, Unsigned), ptr(BasicBlock)) @UnaryInstruction class UnaryInstruction: - pass + _downcast_ = Value, Instruction #call @IntrinsicInst class IntrinsicInst: - pass + _include_ = 'llvm/IntrinsicInst.h' + _downcast_ = Value, Instruction #compare @FCmpInst class FCmpInst: - pass + _downcast_ = Value, Instruction @ICmpInst class ICmpInst: - pass + _downcast_ = Value, Instruction # terminator @BranchInst class BranchInst: - pass + _downcast_ = Value, Instruction @IndirectBrInst class IndirectBrInst: - pass + _downcast_ = Value, Instruction @InvokeInst class InvokeInst: @@ -284,14 +289,16 @@ class InvokeInst: @ResumeInst class ResumeInst: - pass + _downcast_ = Value, Instruction @ReturnInst class ReturnInst: - pass + _downcast_ = Value, Instruction @SwitchInst class SwitchInst: + _downcast_ = Value, Instruction + getCondition = Method(ptr(Value)) setCondition = Method(Void, ptr(Value)) getDefaultDest = Method(ptr(BasicBlock)) @@ -302,20 +309,20 @@ class SwitchInst: @UnreachableInst class UnreachableInst: - pass + _downcast_ = Value, Instruction # unary @AllocaInst class AllocaInst: - pass + _downcast_ = Value, Instruction @CastInst class CastInst: - pass + _downcast_ = Value, Instruction @ExtractValueInst class ExtractValueInst: - pass + _downcast_ = Value, Instruction @LoadInst class LoadInst: @@ -338,46 +345,46 @@ class LoadInst: @VAArgInst class VAArgInst: - pass + _downcast_ = Value, Instruction # intrinsic @DbgInfoIntrinsic class DbgInfoIntrinsic: - pass + _downcast_ = Value, Instruction @MemIntrinsic class MemIntrinsic: - pass + _downcast_ = Value, Instruction @VACopyInst class VACopyInst: - pass + _downcast_ = Value, Instruction @VAEndInst class VAEndInst: - pass + _downcast_ = Value, Instruction @VAStartInst class VAStartInst: - pass + _downcast_ = Value, Instruction @BitCastInst class BitCastInst: - pass + _downcast_ = Value, Instruction @FPExtInst class FPExtInst: - pass + _downcast_ = Value, Instruction @FPToSIInst class FPToSIInst: - pass + _downcast_ = Value, Instruction @FPToUIInst class FPToUIInst: - pass + _downcast_ = Value, Instruction @FPTruncInst class FPTruncInst: - pass + _downcast_ = Value, Instruction From cb00dcc52c4ddf390a3ef51b33726babbf5e769c Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 13 Feb 2013 18:12:45 -0600 Subject: [PATCH 71/85] Fix a bug in CreatInsertValue and one in ConstantInt. --- llvm/core.py | 3 +-- llvmpy/src/Constant.py | 2 +- llvmpy/src/IRBuilder.py | 11 +++++++---- llvmpy/test_binding.py | 5 +++++ 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/llvm/core.py b/llvm/core.py index f2af943..60c05fa 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -2041,8 +2041,7 @@ class Builder(llvm.Wrapper): def alloca(self, ty, name=""): intty = Type.int() - zero = api.llvm.ConstantInt.get(intty._ptr, 0) - return _make_value(self._ptr.CreateAlloca(ty._ptr, zero, name)) + return _make_value(self._ptr.CreateAlloca(ty._ptr, None, name)) def alloca_array(self, ty, size, name=""): return _make_value(self._ptr.CreateAlloca(ty._ptr, size._ptr, name)) diff --git a/llvmpy/src/Constant.py b/llvmpy/src/Constant.py index 0a79bd3..3cbb40b 100644 --- a/llvmpy/src/Constant.py +++ b/llvmpy/src/Constant.py @@ -76,7 +76,7 @@ class ConstantInt: get = StaticMethod(ptr(ConstantInt), ptr(IntegerType), - cast(int, Unsigned), + cast(int, Uint64), cast(bool, Bool), ).require_only(2) isValueValidForType = StaticMethod(cast(Bool, bool), diff --git a/llvmpy/src/IRBuilder.py b/llvmpy/src/IRBuilder.py index 8590430..efdf453 100644 --- a/llvmpy/src/IRBuilder.py +++ b/llvmpy/src/IRBuilder.py @@ -288,9 +288,12 @@ class IRBuilder: args[1] = extra.make_small_vector_from_unsigned(*valuelist) return self._CreateExtractValue(*args) - _CreateInsertValue = Method(ptr(Value), ptr(Value), ptr(Value), - ref(SmallVector_Unsigned), cast(str, StringRef)) - _CreateInsertValue.require_only(3) + _CreateInsertValue = Method(ptr(Value), + ptr(Value), # Agg + ptr(Value), # Val + ref(SmallVector_Unsigned), # ArrayRef + cast(str, StringRef), # name + ).require_only(3) _CreateInsertValue.realname = 'CreateInsertValue' @CustomPythonMethod @@ -298,7 +301,7 @@ class IRBuilder: from llvmpy import extra args = list(args) valuelist = args[2] - args[1] = extra.make_small_vector_from_unsigned(*valuelist) + args[2] = extra.make_small_vector_from_unsigned(*valuelist) return self._CreateInsertValue(*args) CreateLandingPad = Method(ptr(LandingPadInst), ptr(Type), ptr(Value), diff --git a/llvmpy/test_binding.py b/llvmpy/test_binding.py index 01e6c38..8eb56f6 100644 --- a/llvmpy/test_binding.py +++ b/llvmpy/test_binding.py @@ -323,6 +323,11 @@ def test_constants(): aryconst = llvm.ConstantArray.get(ary_int32x4, [intconst] * 4) assert str(aryconst.getAggregateElement(0)) == str(intconst) + bignum = 4415104608 + int64ty = llvm.Type.getInt64Ty(context) + const_bignum = llvm.ConstantInt.get(int64ty, 4415104608) + assert str(bignum) in str(const_bignum) + def test_intrinsic(): context = llvm.getGlobalContext() m = llvm.Module.new("modname", context) From bf121485ad4d9c564cc6f6ed3ad033187ca03e2e Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 15 Feb 2013 11:18:51 -0600 Subject: [PATCH 72/85] Fix problem with caching llvm.core.Value objects. --- llvm/__init__.py | 9 ++++++++- llvm/core.py | 17 ++++++++++------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/llvm/__init__.py b/llvm/__init__.py index c18d066..e3e785f 100644 --- a/llvm/__init__.py +++ b/llvm/__init__.py @@ -14,7 +14,14 @@ class Wrapper(object): @property def _ptr(self): - return self.__ptr + try: + return self.__ptr + except AttributeError: + raise AttributeError("_ptr resource has been removed") + + @_ptr.deleter + def _ptr(self): + del self.__ptr def _extract_ptrs(objs): diff --git a/llvm/core.py b/llvm/core.py index 60c05fa..66f7c5f 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -926,7 +926,6 @@ class VectorType(Type): class Value(llvm.Wrapper): _type_ = api.llvm.Value - def __init__(self, builder, ptr): assert builder is _ValueFactory @@ -1596,6 +1595,7 @@ class NamedMetaData(llvm.Wrapper): return mod.get_named_metadata(name) def delete(self): + _ValueFactory.delete(self._ptr) self._ptr.eraseFromParent() @property @@ -1822,13 +1822,14 @@ class _ValueFactory(object): def build(cls, ptr): # try to look in the cache addr = ptr._capsule.pointer + id = ptr.getValueID() + key = id, addr try: - obj = cls.cache[addr] + obj = cls.cache[key] return obj except KeyError: pass # find class by value id - id = ptr.getValueID() ctorcls = cls.class_for_valueid.get(id) if not ctorcls: if id > VALUE_INSTRUCTION: # "generic" instruction @@ -1837,12 +1838,12 @@ class _ValueFactory(object): ctorcls = Value # cache the obj obj = ctorcls(_ValueFactory, ptr) - cls.cache[addr] = obj + cls.cache[key] = obj return obj @classmethod def delete(cls, ptr): - del cls.cache[ptr._capsule.pointer] + del cls.cache[(ptr.getValueID(), ptr._capsule.pointer)] def _make_value(ptr): return _ValueFactory.build(ptr) @@ -1851,12 +1852,14 @@ def _make_value(ptr): # Builder #===----------------------------------------------------------------------=== -_atomic_orderings = { 'unordered' : api.llvm.AtomicOrdering.Unordered, +_atomic_orderings = { + 'unordered' : api.llvm.AtomicOrdering.Unordered, 'monotonic' : api.llvm.AtomicOrdering.Monotonic, 'acquire' : api.llvm.AtomicOrdering.Acquire, 'release' : api.llvm.AtomicOrdering.Release, 'acq_rel' : api.llvm.AtomicOrdering.AcquireRelease, - 'seq_cst' : api.llvm.AtomicOrdering.SequentiallyConsistent} + 'seq_cst' : api.llvm.AtomicOrdering.SequentiallyConsistent +} class Builder(llvm.Wrapper): From 1647580a4172fdc46b8ea2396acdf90fd20fcaf3 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Sat, 16 Feb 2013 21:54:12 -0600 Subject: [PATCH 73/85] LinkModules should release ownership of the other module when not preserving --- llvmpy/src/Linker.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/llvmpy/src/Linker.py b/llvmpy/src/Linker.py index 0b846d6..acca503 100644 --- a/llvmpy/src/Linker.py +++ b/llvmpy/src/Linker.py @@ -41,7 +41,7 @@ class Linker: PyObjectPtr, # errmsg ) - LinkModules = CustomStaticMethod('Linker_LinkModules', + _LinkModules = CustomStaticMethod('Linker_LinkModules', PyObjectPtr, # boolean ptr(Module), ptr(Module), @@ -49,3 +49,10 @@ class Linker: PyObjectPtr, # errsg ) + @CustomPythonStaticMethod + def LinkModules(module, other, mode, errmsg): + failed = Linker._LinkModules(module, other, mode, errmsg) + if not failed and mode != Linker.LinkerMode.PreserveSource: + capsule.release_ownership(other._ptr) + return failed + From 42f7219c3f571cecf265ff723f0240b5edccad1b Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 22 Feb 2013 10:43:11 -0600 Subject: [PATCH 74/85] Allow function.verify to raise exception on error. --- llvm/core.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/llvm/core.py b/llvm/core.py index 66f7c5f..bc1ff45 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -1508,7 +1508,13 @@ class Function(GlobalValue): # Note: LLVM has a bug in preverifier that will always abort # the process upon failure. actions = api.llvm.VerifierFailureAction - return api.llvm.verifyFunction(self._ptr, actions.PrintMessageAction) + broken = api.llvm.verifyFunction(self._ptr, + actions.ReturnStatusAction) + if broken: + # If broken, then re-run to print the message + api.llvm.verifyFunction(self._ptr, actions.PrintMessageAction) + raise llvm.LLVMException("Function %s failed verification" % + self.name) #===----------------------------------------------------------------------=== # InlineAsm From d270e885cc37b86e66cf08fce2b7045251409c58 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 22 Feb 2013 10:43:34 -0600 Subject: [PATCH 75/85] Add ptrtoint cast in cbuilder --- llvm_cbuilder/builder.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/llvm_cbuilder/builder.py b/llvm_cbuilder/builder.py index 64083b1..917b37e 100644 --- a/llvm_cbuilder/builder.py +++ b/llvm_cbuilder/builder.py @@ -1153,6 +1153,10 @@ class PointerCasting(OperatorMixin): if _is_pointer(ty): return self._temp(self.parent.builder.bitcast(self.value, ty)) + + if _is_int(ty): + return self._temp(self.parent.builder.ptrtoint(self.value, ty)) + raise CastError(self.type, ty) From 435b92b4a49fc9974e3aed40d2cd67e21c7553cd Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 22 Feb 2013 10:50:18 -0600 Subject: [PATCH 76/85] Fix VectorType.element --- llvm/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/core.py b/llvm/core.py index bc1ff45..f38028b 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -917,7 +917,7 @@ class VectorType(Type): @property def element(self): - return self._ptr.getVectorElementType() + return Type(self._ptr.getVectorElementType()) @property def count(self): From 74982d6fefe23c42544ce89591fb8e2cda971a26 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 22 Feb 2013 13:42:05 -0600 Subject: [PATCH 77/85] Adapt to work in python2.6 --- llvmpy/capsule.cpp | 4 +- llvmpy/gen/gen.py | 2 + llvmpy/include/capsulethunk.h | 108 ++++++++++++++++++ llvmpy/include/llvm_binding/capsule_context.h | 20 +++- llvmpy/src/ADT/__init__.py | 12 +- llvmpy/src/Analysis/__init__.py | 12 +- llvmpy/src/Assembly/__init__.py | 12 +- llvmpy/src/Bitcode/__init__.py | 12 +- llvmpy/src/CodeGen/__init__.py | 12 +- llvmpy/src/ExecutionEngine/__init__.py | 12 +- llvmpy/src/Support/__init__.py | 12 +- llvmpy/src/Target/__init__.py | 12 +- llvmpy/src/Transforms/Utils/__init__.py | 17 +-- llvmpy/src/Transforms/__init__.py | 17 +-- llvmpy/src/__init__.py | 9 +- 15 files changed, 154 insertions(+), 119 deletions(-) create mode 100644 llvmpy/include/capsulethunk.h diff --git a/llvmpy/capsule.cpp b/llvmpy/capsule.cpp index e7e4932..b7fa81b 100644 --- a/llvmpy/capsule.cpp +++ b/llvmpy/capsule.cpp @@ -1,4 +1,5 @@ #include +#include #include static @@ -53,12 +54,13 @@ CapsuleContext* getContext(PyObject* self, PyObject* args) { PyErr_SetString(PyExc_TypeError, "PyCapsule has no context."); return NULL; } - return (CapsuleContext*)context; + return static_cast(context); } static PyObject* getClassName(PyObject* self, PyObject* args) { CapsuleContext* context = getContext(self, args); + //Assert(context->_magic == 0xdead); if (!context) { return NULL; } else { diff --git a/llvmpy/gen/gen.py b/llvmpy/gen/gen.py index c5d30de..066ed23 100644 --- a/llvmpy/gen/gen.py +++ b/llvmpy/gen/gen.py @@ -40,6 +40,8 @@ populate_submodules(module, submodule_%(ns)s); def populate_headers(println): includes = [ 'cstring', + 'Python.h', + 'capsulethunk.h', 'llvm_binding/conversion.h', 'llvm_binding/binding.h', 'llvm_binding/capsule_context.h', diff --git a/llvmpy/include/capsulethunk.h b/llvmpy/include/capsulethunk.h new file mode 100644 index 0000000..9061782 --- /dev/null +++ b/llvmpy/include/capsulethunk.h @@ -0,0 +1,108 @@ +/** + + This is a modified version of capsulethunk.h for use in llvmpy + +**/ + +#ifndef __CAPSULETHUNK_H +#define __CAPSULETHUNK_H + +//#define Assert(X) do_assert(!!(X), #X, __FILE__, __LINE__) +#define Assert(X) + +static +void do_assert(int cond, const char * msg, const char *file, unsigned line){ + if (not cond) { + fprintf(stderr, "Assertion failed %s:%d\n%s\n", file, line, msg); + exit(1); + } +} + +#if ( (PY_VERSION_HEX < 0x02070000) \ + || ((PY_VERSION_HEX >= 0x03000000) \ + && (PY_VERSION_HEX < 0x03010000)) ) + +typedef void (*PyCapsule_Destructor)(PyObject *); + +struct FakePyCapsule_Desc { + const char *name; + void *context; + PyCapsule_Destructor dtor; + PyObject *parent; + + FakePyCapsule_Desc() : name(0), context(0), dtor(0) {} +}; + +static +FakePyCapsule_Desc* get_pycobj_desc(PyObject *p){ + void *desc = ((PyCObject*)p)->desc; + Assert(desc && "No desc in PyCObject"); + return static_cast(desc); +} + +static +void pycobject_pycapsule_dtor(void *p, void *desc){ + Assert(desc); + Assert(p); + FakePyCapsule_Desc *fpc_desc = static_cast(desc); + Assert(fpc_desc->parent); + Assert(PyCObject_Check(fpc_desc->parent)); + fpc_desc->dtor(static_cast(fpc_desc->parent)); + delete fpc_desc; +} + +static +PyObject* PyCapsule_New(void* ptr, const char *name, PyCapsule_Destructor dtor) +{ + FakePyCapsule_Desc *desc = new FakePyCapsule_Desc; + desc->name = name; + desc->context = NULL; + desc->dtor = dtor; + PyObject *p = PyCObject_FromVoidPtrAndDesc(ptr, desc, + pycobject_pycapsule_dtor); + desc->parent = p; + return p; +} + +static +int PyCapsule_CheckExact(PyObject *p) +{ + return PyCObject_Check(p); +} + +static +void* PyCapsule_GetPointer(PyObject *p, const char *name) +{ + Assert(PyCapsule_CheckExact(p)); + if (strcmp(get_pycobj_desc(p)->name, name) != 0) { + PyErr_SetString(PyExc_ValueError, "Invalid PyCapsule object"); + } + return PyCObject_AsVoidPtr(p); +} + +static +void* PyCapsule_GetContext(PyObject *p) +{ + Assert(p); + Assert(PyCapsule_CheckExact(p)); + return get_pycobj_desc(p)->context; +} + +static +int PyCapsule_SetContext(PyObject *p, void *context) +{ + Assert(PyCapsule_CheckExact(p)); + get_pycobj_desc(p)->context = context; + return 0; +} + +static +const char * PyCapsule_GetName(PyObject *p) +{ +// Assert(PyCapsule_CheckExact(p)); + return get_pycobj_desc(p)->name; +} + +#endif /* #if PY_VERSION_HEX < 0x02070000 */ + +#endif /* __CAPSULETHUNK_H */ diff --git a/llvmpy/include/llvm_binding/capsule_context.h b/llvmpy/include/llvm_binding/capsule_context.h index 6ed1381..0256088 100644 --- a/llvmpy/include/llvm_binding/capsule_context.h +++ b/llvmpy/include/llvm_binding/capsule_context.h @@ -3,10 +3,10 @@ #include #include - -typedef PyObject* Destructor_Fn; +#include "capsulethunk.h" struct CapsuleContext { + //const unsigned _magic; const char* className; CapsuleContext(const char* cn) @@ -14,6 +14,17 @@ struct CapsuleContext { { } }; +static +void pycapsule_dtor_free_context(PyObject *pycap) +{ + void * context = PyCapsule_GetContext(pycap); + Assert(context); + CapsuleContext* cc = static_cast(context); + //Assert(cc->_magic == 0xdead); + delete cc; +} + + static PyObject* pycapsule_new(void* ptr, @@ -26,15 +37,16 @@ PyObject* pycapsule_new(void* ptr, if (!ptr) { Py_RETURN_NONE; } - PyObject* cap = PyCapsule_New(ptr, basename, NULL); + PyObject* cap = PyCapsule_New(ptr, basename, pycapsule_dtor_free_context); if (!cap) { PyErr_SetString(PyExc_TypeError, "Error creating new PyCapsule"); return NULL; } CapsuleContext* context = new CapsuleContext(classname); - if (PyCapsule_SetContext(cap, context)) { + if (0 != PyCapsule_SetContext(cap, context)) { return NULL; } + //Assert(context->_magic == 0xdead); return cap; } diff --git a/llvmpy/src/ADT/__init__.py b/llvmpy/src/ADT/__init__.py index da0beed..944426e 100644 --- a/llvmpy/src/ADT/__init__.py +++ b/llvmpy/src/ADT/__init__.py @@ -1,10 +1,2 @@ -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() +from src import _init +_init(__name__, __file__) diff --git a/llvmpy/src/Analysis/__init__.py b/llvmpy/src/Analysis/__init__.py index da0beed..944426e 100644 --- a/llvmpy/src/Analysis/__init__.py +++ b/llvmpy/src/Analysis/__init__.py @@ -1,10 +1,2 @@ -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() +from src import _init +_init(__name__, __file__) diff --git a/llvmpy/src/Assembly/__init__.py b/llvmpy/src/Assembly/__init__.py index da0beed..944426e 100644 --- a/llvmpy/src/Assembly/__init__.py +++ b/llvmpy/src/Assembly/__init__.py @@ -1,10 +1,2 @@ -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() +from src import _init +_init(__name__, __file__) diff --git a/llvmpy/src/Bitcode/__init__.py b/llvmpy/src/Bitcode/__init__.py index da0beed..944426e 100644 --- a/llvmpy/src/Bitcode/__init__.py +++ b/llvmpy/src/Bitcode/__init__.py @@ -1,10 +1,2 @@ -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() +from src import _init +_init(__name__, __file__) diff --git a/llvmpy/src/CodeGen/__init__.py b/llvmpy/src/CodeGen/__init__.py index da0beed..944426e 100644 --- a/llvmpy/src/CodeGen/__init__.py +++ b/llvmpy/src/CodeGen/__init__.py @@ -1,10 +1,2 @@ -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() +from src import _init +_init(__name__, __file__) diff --git a/llvmpy/src/ExecutionEngine/__init__.py b/llvmpy/src/ExecutionEngine/__init__.py index da0beed..944426e 100644 --- a/llvmpy/src/ExecutionEngine/__init__.py +++ b/llvmpy/src/ExecutionEngine/__init__.py @@ -1,10 +1,2 @@ -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() +from src import _init +_init(__name__, __file__) diff --git a/llvmpy/src/Support/__init__.py b/llvmpy/src/Support/__init__.py index da0beed..944426e 100644 --- a/llvmpy/src/Support/__init__.py +++ b/llvmpy/src/Support/__init__.py @@ -1,10 +1,2 @@ -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() +from src import _init +_init(__name__, __file__) diff --git a/llvmpy/src/Target/__init__.py b/llvmpy/src/Target/__init__.py index da0beed..944426e 100644 --- a/llvmpy/src/Target/__init__.py +++ b/llvmpy/src/Target/__init__.py @@ -1,10 +1,2 @@ -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() +from src import _init +_init(__name__, __file__) diff --git a/llvmpy/src/Transforms/Utils/__init__.py b/llvmpy/src/Transforms/Utils/__init__.py index 98c06fc..944426e 100644 --- a/llvmpy/src/Transforms/Utils/__init__.py +++ b/llvmpy/src/Transforms/Utils/__init__.py @@ -1,15 +1,2 @@ -import os.path, importlib - -def _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() - +from src import _init +_init(__name__, __file__) diff --git a/llvmpy/src/Transforms/__init__.py b/llvmpy/src/Transforms/__init__.py index 98c06fc..944426e 100644 --- a/llvmpy/src/Transforms/__init__.py +++ b/llvmpy/src/Transforms/__init__.py @@ -1,15 +1,2 @@ -import os.path, importlib - -def _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() - +from src import _init +_init(__name__, __file__) diff --git a/llvmpy/src/__init__.py b/llvmpy/src/__init__.py index 98c06fc..ed34608 100644 --- a/llvmpy/src/__init__.py +++ b/llvmpy/src/__init__.py @@ -1,7 +1,7 @@ -import os.path, importlib +import os.path -def _init(): - base = os.path.dirname(__file__) +def _init(root=__name__, file=__file__): + base = os.path.dirname(file) for fname in os.listdir(base): print fname is_python_script = fname.endswith('.py') or fname.endswith('.pyc') @@ -9,7 +9,8 @@ def _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__) + #importlib.import_module('.' + modname, __name__) + __import__('.'.join([root, modname])) _init() From a275068193c87c5a27758c17d7699e963a0bdfa8 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 22 Feb 2013 17:58:38 -0600 Subject: [PATCH 78/85] Fix formatted_raw_ostream ownership error with the underlying stream. --- llvmpy/src/Support/FormattedStream.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/llvmpy/src/Support/FormattedStream.py b/llvmpy/src/Support/FormattedStream.py index 17c259b..26f906d 100644 --- a/llvmpy/src/Support/FormattedStream.py +++ b/llvmpy/src/Support/FormattedStream.py @@ -5,5 +5,11 @@ from raw_ostream import raw_ostream @llvm.Class(raw_ostream) class formatted_raw_ostream: _include_ = 'llvm/Support/FormattedStream.h' - new = Constructor(ref(raw_ostream), cast(bool, Bool)) + _new = Constructor(ref(raw_ostream), cast(bool, Bool)) + + @CustomPythonStaticMethod + def new(stream, destroy=False): + inst = formatted_raw_ostream._new(stream, destroy) + inst.__underlying_stream = stream # to prevent it being freed first + return inst From 45e70333fd70ec2449a0a95a7a7f4f68c47a36d5 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Fri, 22 Feb 2013 19:17:56 -0600 Subject: [PATCH 79/85] Adapt to python 3.3 --- llvmpy/capsule.cpp | 1 + llvmpy/capsule.py | 12 ++- llvmpy/extra.py | 2 +- llvmpy/gen/binding.py | 2 +- llvmpy/gen/codegen.py | 2 +- llvmpy/gen/gen.py | 1 + llvmpy/include/llvm_binding/conversion.h | 23 ++++++ llvmpy/include/llvm_binding/extra.h | 8 +- llvmpy/include/python3adapt.h | 32 ++++++++ llvmpy/src/ADT/Triple.py | 2 +- llvmpy/src/Argument.py | 6 +- llvmpy/src/Attributes.py | 4 +- llvmpy/src/BasicBlock.py | 10 +-- llvmpy/src/Bitcode/ReaderWriter.py | 2 +- llvmpy/src/CallingConv.py | 2 +- llvmpy/src/Constant.py | 20 ++--- llvmpy/src/DataLayout.py | 16 ++-- llvmpy/src/DerivedTypes.py | 8 +- llvmpy/src/EngineBuilder.py | 16 ++-- llvmpy/src/ExecutionEngine/ExecutionEngine.py | 2 +- llvmpy/src/Function.py | 16 ++-- llvmpy/src/GenericValue.py | 4 +- llvmpy/src/GlobalValue.py | 8 +- llvmpy/src/GlobalVariable.py | 12 +-- llvmpy/src/IRBuilder.py | 28 +++---- llvmpy/src/InlineAsm.py | 8 +- llvmpy/src/Instruction.py | 12 +-- llvmpy/src/Intrinsics.py | 6 +- llvmpy/src/JITMemoryManager.py | 2 +- llvmpy/src/LLVMContext.py | 2 +- llvmpy/src/Linker.py | 8 +- llvmpy/src/Metadata.py | 16 ++-- llvmpy/src/Module.py | 22 +++--- llvmpy/src/Pass.py | 8 +- llvmpy/src/PassManager.py | 8 +- llvmpy/src/PassRegistry.py | 2 +- llvmpy/src/PassSupport.py | 2 +- llvmpy/src/Support/FormattedStream.py | 2 +- llvmpy/src/Type.py | 8 +- llvmpy/src/User.py | 4 +- llvmpy/src/Value.py | 12 +-- llvmpy/src/__init__.py | 5 +- llvmpy/test_binding.py | 73 ++++++++++--------- 43 files changed, 251 insertions(+), 188 deletions(-) create mode 100644 llvmpy/include/python3adapt.h diff --git a/llvmpy/capsule.cpp b/llvmpy/capsule.cpp index b7fa81b..561b28a 100644 --- a/llvmpy/capsule.cpp +++ b/llvmpy/capsule.cpp @@ -1,4 +1,5 @@ #include +#include #include #include diff --git a/llvmpy/capsule.py b/llvmpy/capsule.py index 0b1f203..ec6fdde 100644 --- a/llvmpy/capsule.py +++ b/llvmpy/capsule.py @@ -32,7 +32,7 @@ def _capsule_weakref_dtor(item): class Capsule(object): "Wraps PyCapsule so that we can build weakref of it." - from _capsule import check, getClassName, getName, getPointer + from ._capsule import check, getClassName, getName, getPointer def __init__(self, capsule): assert Capsule.valid(capsule) @@ -75,6 +75,9 @@ class Capsule(object): else: return False + def __hash__(self): + return super(Capsule, self).__hash__() + def __ne__(self, other): return not (self == other) @@ -122,7 +125,7 @@ def wrap(cap, owned=False): ''' if not Capsule.valid(cap): if isinstance(cap, list): - return map(wrap, cap) + return list(map(wrap, cap)) return cap # bypass if cap is not a PyCapsule and not a list cap = Capsule(cap) @@ -170,6 +173,9 @@ class Wrapper(object): def _ptr(self): return self._capsule.capsule + def __hash__(self): + return super(Wrapper, self).__hash__() + def __eq__(self, other): return self._capsule == other._capsule @@ -184,7 +190,7 @@ class Wrapper(object): return hasattr(cls, '_delete_') def downcast(obj, cls): - import _api + from . import _api if type(obj) is cls: return obj fromty = obj._llvm_type_ diff --git a/llvmpy/extra.py b/llvmpy/extra.py index a2e744f..99035a7 100644 --- a/llvmpy/extra.py +++ b/llvmpy/extra.py @@ -11,7 +11,7 @@ from llvmpy import _api def _wrapper(func): "Wrap the re-exported functions" def _core(*args): - unwrapped = map(capsule.unwrap, args) + unwrapped = list(map(capsule.unwrap, args)) ret = func(*unwrapped) return capsule.wrap(ret) return _core diff --git a/llvmpy/gen/binding.py b/llvmpy/gen/binding.py index 4454d72..0f5c4fd 100644 --- a/llvmpy/gen/binding.py +++ b/llvmpy/gen/binding.py @@ -348,7 +348,7 @@ class Enum(object): def __init__(self, *value_names): self.parent = None if len(value_names) == 1: - value_names = filter(bool, value_names[0].replace(',', ' ').split()) + value_names = list(filter(bool, value_names[0].replace(',', ' ').split())) self.value_names = value_names self.includes = set() diff --git a/llvmpy/gen/codegen.py b/llvmpy/gen/codegen.py index abde437..f9585fd 100644 --- a/llvmpy/gen/codegen.py +++ b/llvmpy/gen/codegen.py @@ -259,7 +259,7 @@ class PyCodeWriter(CodeWriterBase): def unwrap_many(self, args): unwrapped = self.new_symbol('unwrapped') - self.println('%(unwrapped)s = map(capsule.unwrap, %(args)s)' % locals()) + self.println('%(unwrapped)s = list(map(capsule.unwrap, %(args)s))' % locals()) return unwrapped def unwrap(self, val): diff --git a/llvmpy/gen/gen.py b/llvmpy/gen/gen.py index 066ed23..263c289 100644 --- a/llvmpy/gen/gen.py +++ b/llvmpy/gen/gen.py @@ -41,6 +41,7 @@ def populate_headers(println): includes = [ 'cstring', 'Python.h', + 'python3adapt.h', 'capsulethunk.h', 'llvm_binding/conversion.h', 'llvm_binding/binding.h', diff --git a/llvmpy/include/llvm_binding/conversion.h b/llvmpy/include/llvm_binding/conversion.h index 7b8e6df..abc3749 100644 --- a/llvmpy/include/llvm_binding/conversion.h +++ b/llvmpy/include/llvm_binding/conversion.h @@ -4,6 +4,29 @@ // python object unwrapper +static +int py_bytes_to(PyObject *bytesobj, llvm::StringRef &strref){ + // type check + if (!PyBytes_Check(bytesobj)) { + // raises TypeError + PyErr_SetString(PyExc_TypeError, "Expecting a str"); + return 0; + } + // get len and buffer + const Py_ssize_t len = PyBytes_Size(bytesobj); + const char * buf = PyBytes_AsString(bytesobj); + if (!buf) { + // raises TypeError + return 0; + } + // set output + strref = llvm::StringRef(buf, len); + // success + return 1; +} + + + static int py_str_to(PyObject *strobj, llvm::StringRef &strref){ // type check diff --git a/llvmpy/include/llvm_binding/extra.h b/llvmpy/include/llvm_binding/extra.h index 76c8a16..3874bb3 100644 --- a/llvmpy/include/llvm_binding/extra.h +++ b/llvmpy/include/llvm_binding/extra.h @@ -497,11 +497,9 @@ PyObject* llvm_WriteBitcodeToFile(const llvm::Module *M, PyObject* FObj) 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; + PyObject* buf = PyBytes_FromStringAndSize(ref.data(), ref.size()); + puts(PyString_AsString(PyObject_Str(PyObject_Type(buf)))); + return PyObject_CallMethod(FObj, "write", "O", buf); } static diff --git a/llvmpy/include/python3adapt.h b/llvmpy/include/python3adapt.h new file mode 100644 index 0000000..5b19ebe --- /dev/null +++ b/llvmpy/include/python3adapt.h @@ -0,0 +1,32 @@ +#ifndef PYTHON3ADAPT_H +#define PYTHON3ADAPT_H + +#if (PY_VERSION_HEX < 0x03000000) + +#define PyBytes_Check PyString_Check +#define PyBytes_Size PyString_Size +#define PyBytes_AsString PyString_AsString +#define PyBytes_FromStringAndSize PyString_FromStringAndSize +#define PyBytes_FromString PyString_FromString + +#endif + +#if (PY_VERSION_HEX >= 0x03000000) + +#define PyString_Check PyUnicode_Check +#define PyString_Size PyUnicode_GET_SIZE +#define PyString_AsString PyUnicode_AsUTF8 +#define PyString_FromStringAndSize PyUnicode_FromStringAndSize +#define PyString_FromString PyUnicode_FromString + +#define PyInt_Check PyLong_Check +#define PyInt_FromLong PyLong_FromLong +#define PyInt_AsLong PyLong_AsLong +#define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask +#define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask + +#define PyFile_Check(x) (1) + +#endif + +#endif //PYTHON3ADAPT_H \ No newline at end of file diff --git a/llvmpy/src/ADT/Triple.py b/llvmpy/src/ADT/Triple.py index 82de57e..1615c1c 100644 --- a/llvmpy/src/ADT/Triple.py +++ b/llvmpy/src/ADT/Triple.py @@ -1,6 +1,6 @@ from binding import * from ..namespace import llvm -from StringRef import StringRef +from .StringRef import StringRef Triple = llvm.Class() diff --git a/llvmpy/src/Argument.py b/llvmpy/src/Argument.py index 64db072..4f0b7a4 100644 --- a/llvmpy/src/Argument.py +++ b/llvmpy/src/Argument.py @@ -1,7 +1,7 @@ from binding import * -from namespace import llvm -from Value import Argument, Value -from Attributes import Attributes +from .namespace import llvm +from .Value import Argument, Value +from .Attributes import Attributes @Argument class Argument: diff --git a/llvmpy/src/Attributes.py b/llvmpy/src/Attributes.py index c6a8d97..4fe7651 100644 --- a/llvmpy/src/Attributes.py +++ b/llvmpy/src/Attributes.py @@ -1,6 +1,6 @@ from binding import * -from namespace import llvm -from LLVMContext import LLVMContext +from .namespace import llvm +from .LLVMContext import LLVMContext llvm.includes.add('llvm/Attributes.h') diff --git a/llvmpy/src/BasicBlock.py b/llvmpy/src/BasicBlock.py index 4ed4f66..77eaf01 100644 --- a/llvmpy/src/BasicBlock.py +++ b/llvmpy/src/BasicBlock.py @@ -1,9 +1,9 @@ from binding import * -from namespace import llvm -from Value import Function, BasicBlock -from Instruction import Instruction, TerminatorInst -from LLVMContext import LLVMContext -from ADT.StringRef import StringRef +from .namespace import llvm +from .Value import Function, BasicBlock +from .Instruction import Instruction, TerminatorInst +from .LLVMContext import LLVMContext +from .ADT.StringRef import StringRef @BasicBlock class BasicBlock: diff --git a/llvmpy/src/Bitcode/ReaderWriter.py b/llvmpy/src/Bitcode/ReaderWriter.py index a8e8c43..b950ba4 100644 --- a/llvmpy/src/Bitcode/ReaderWriter.py +++ b/llvmpy/src/Bitcode/ReaderWriter.py @@ -9,7 +9,7 @@ llvm.includes.add('llvm/Bitcode/ReaderWriter.h') ParseBitCodeFile = llvm.CustomFunction('ParseBitCodeFile', 'llvm_ParseBitCodeFile', PyObjectPtr, # returns Module* - cast(str, StringRef), + cast(bytes, StringRef), ref(LLVMContext), PyObjectPtr, # file-like object ).require_only(2) diff --git a/llvmpy/src/CallingConv.py b/llvmpy/src/CallingConv.py index 71b4ad3..efca1fc 100644 --- a/llvmpy/src/CallingConv.py +++ b/llvmpy/src/CallingConv.py @@ -1,5 +1,5 @@ from binding import * -from namespace import llvm +from .namespace import llvm CallingConv = llvm.Namespace('CallingConv') ID = CallingConv.Enum('ID', ''' diff --git a/llvmpy/src/Constant.py b/llvmpy/src/Constant.py index 3cbb40b..70dc3bf 100644 --- a/llvmpy/src/Constant.py +++ b/llvmpy/src/Constant.py @@ -1,14 +1,14 @@ from binding import * -from namespace import llvm -from Value import Value -from Value import Constant, UndefValue, ConstantInt, ConstantFP, ConstantArray -from Value import ConstantStruct, ConstantVector, ConstantVector -from Value import ConstantDataSequential, ConstantDataArray, ConstantExpr -from LLVMContext import LLVMContext -from ADT.StringRef import StringRef -from ADT.SmallVector import SmallVector_Value, SmallVector_Unsigned -from Type import Type, IntegerType, ArrayType, StructType -from Instruction import CmpInst +from .namespace import llvm +from .Value import Value +from .Value import Constant, UndefValue, ConstantInt, ConstantFP, ConstantArray +from .Value import ConstantStruct, ConstantVector, ConstantVector +from .Value import ConstantDataSequential, ConstantDataArray, ConstantExpr +from .LLVMContext import LLVMContext +from .ADT.StringRef import StringRef +from .ADT.SmallVector import SmallVector_Value, SmallVector_Unsigned +from .Type import Type, IntegerType, ArrayType, StructType +from .Instruction import CmpInst @Constant class Constant: diff --git a/llvmpy/src/DataLayout.py b/llvmpy/src/DataLayout.py index 9582d53..7085f52 100644 --- a/llvmpy/src/DataLayout.py +++ b/llvmpy/src/DataLayout.py @@ -1,16 +1,16 @@ from binding import * -from namespace import llvm -from Pass import ImmutablePass +from .namespace import llvm +from .Pass import ImmutablePass DataLayout = llvm.Class(ImmutablePass) StructLayout = llvm.Class() -from LLVMContext import LLVMContext -from ADT.StringRef import StringRef -from Module import Module -from Type import Type, IntegerType, StructType -from ADT.SmallVector import SmallVector_Value -from GlobalVariable import GlobalVariable +from .LLVMContext import LLVMContext +from .ADT.StringRef import StringRef +from .Module import Module +from .Type import Type, IntegerType, StructType +from .ADT.SmallVector import SmallVector_Value +from .GlobalVariable import GlobalVariable @DataLayout diff --git a/llvmpy/src/DerivedTypes.py b/llvmpy/src/DerivedTypes.py index 40724e0..02eec8c 100644 --- a/llvmpy/src/DerivedTypes.py +++ b/llvmpy/src/DerivedTypes.py @@ -1,8 +1,8 @@ from binding import * -from namespace import llvm -from LLVMContext import LLVMContext -from Type import Type -from ADT.SmallVector import SmallVector_Type +from .namespace import llvm +from .LLVMContext import LLVMContext +from .Type import Type +from .ADT.SmallVector import SmallVector_Type FunctionType = llvm.Class(Type) diff --git a/llvmpy/src/EngineBuilder.py b/llvmpy/src/EngineBuilder.py index c3feafe..4e8ed12 100644 --- a/llvmpy/src/EngineBuilder.py +++ b/llvmpy/src/EngineBuilder.py @@ -1,12 +1,12 @@ from binding import * -from namespace import llvm -from Module import Module -from JITMemoryManager import JITMemoryManager -from Support.CodeGen import CodeGenOpt, Reloc, CodeModel -from ADT.StringRef import StringRef -from ExecutionEngine.ExecutionEngine import ExecutionEngine -from Target.TargetMachine import TargetMachine -from ADT.Triple import Triple +from .namespace import llvm +from .Module import Module +from .JITMemoryManager import JITMemoryManager +from .Support.CodeGen import CodeGenOpt, Reloc, CodeModel +from .ADT.StringRef import StringRef +from .ExecutionEngine.ExecutionEngine import ExecutionEngine +from .Target.TargetMachine import TargetMachine +from .ADT.Triple import Triple EngineBuilder = llvm.Class() diff --git a/llvmpy/src/ExecutionEngine/ExecutionEngine.py b/llvmpy/src/ExecutionEngine/ExecutionEngine.py index bcf66fd..038d344 100644 --- a/llvmpy/src/ExecutionEngine/ExecutionEngine.py +++ b/llvmpy/src/ExecutionEngine/ExecutionEngine.py @@ -98,6 +98,6 @@ class ExecutionEngine: @CustomPythonMethod def runFunction(self, fn, args): from llvmpy import capsule - unwrapped = map(capsule.unwrap, args) + unwrapped = list(map(capsule.unwrap, args)) return self._runFunction(fn, tuple(unwrapped)) diff --git a/llvmpy/src/Function.py b/llvmpy/src/Function.py index 52db622..55a50d9 100644 --- a/llvmpy/src/Function.py +++ b/llvmpy/src/Function.py @@ -1,12 +1,12 @@ from binding import * -from namespace import llvm -from Value import GlobalValue, Constant, Function, Argument, Value -from BasicBlock import BasicBlock -from Attributes import Attributes -from Type import Type -from DerivedTypes import FunctionType -from LLVMContext import LLVMContext -from CallingConv import CallingConv +from .namespace import llvm +from .Value import GlobalValue, Constant, Function, Argument, Value +from .BasicBlock import BasicBlock +from .Attributes import Attributes +from .Type import Type +from .DerivedTypes import FunctionType +from .LLVMContext import LLVMContext +from .CallingConv import CallingConv @Function class Function: diff --git a/llvmpy/src/GenericValue.py b/llvmpy/src/GenericValue.py index 73a3709..e587b5f 100644 --- a/llvmpy/src/GenericValue.py +++ b/llvmpy/src/GenericValue.py @@ -1,6 +1,6 @@ from binding import * -from namespace import llvm -from Type import Type +from .namespace import llvm +from .Type import Type GenericValue = llvm.Class() diff --git a/llvmpy/src/GlobalValue.py b/llvmpy/src/GlobalValue.py index f21d5af..2583c6a 100644 --- a/llvmpy/src/GlobalValue.py +++ b/llvmpy/src/GlobalValue.py @@ -1,8 +1,8 @@ from binding import * -from namespace import llvm -from Value import GlobalValue -from Module import Module -from ADT.StringRef import StringRef +from .namespace import llvm +from .Value import GlobalValue +from .Module import Module +from .ADT.StringRef import StringRef @GlobalValue class GlobalValue: diff --git a/llvmpy/src/GlobalVariable.py b/llvmpy/src/GlobalVariable.py index 2280e24..c38df27 100644 --- a/llvmpy/src/GlobalVariable.py +++ b/llvmpy/src/GlobalVariable.py @@ -1,13 +1,13 @@ from binding import * -from namespace import llvm +from .namespace import llvm -from GlobalValue import GlobalValue +from .GlobalValue import GlobalValue GlobalVariable = llvm.Class(GlobalValue) -from Module import Module -from Type import Type -from ADT.StringRef import StringRef -from Value import Constant +from .Module import Module +from .Type import Type +from .ADT.StringRef import StringRef +from .Value import Constant @GlobalVariable class GlobalVariable: diff --git a/llvmpy/src/IRBuilder.py b/llvmpy/src/IRBuilder.py index efdf453..afd78a0 100644 --- a/llvmpy/src/IRBuilder.py +++ b/llvmpy/src/IRBuilder.py @@ -1,18 +1,18 @@ from binding import * -from namespace import llvm -from LLVMContext import LLVMContext -from BasicBlock import BasicBlock -from Instruction import Instruction -from Instruction import ReturnInst, CallInst, BranchInst, SwitchInst -from Instruction import IndirectBrInst, InvokeInst, ResumeInst, PHINode -from Instruction import UnreachableInst, AllocaInst, LoadInst, StoreInst -from Instruction import FenceInst, AtomicCmpXchgInst, AtomicRMWInst, CmpInst -from Instruction import LandingPadInst, VAArgInst -from Instruction import AtomicOrdering, SynchronizationScope -from ADT.SmallVector import SmallVector_Value, SmallVector_Unsigned -from ADT.StringRef import StringRef -from Value import Value, MDNode -from Type import Type, IntegerType +from .namespace import llvm +from .LLVMContext import LLVMContext +from .BasicBlock import BasicBlock +from .Instruction import Instruction +from .Instruction import ReturnInst, CallInst, BranchInst, SwitchInst +from .Instruction import IndirectBrInst, InvokeInst, ResumeInst, PHINode +from .Instruction import UnreachableInst, AllocaInst, LoadInst, StoreInst +from .Instruction import FenceInst, AtomicCmpXchgInst, AtomicRMWInst, CmpInst +from .Instruction import LandingPadInst, VAArgInst +from .Instruction import AtomicOrdering, SynchronizationScope +from .ADT.SmallVector import SmallVector_Value, SmallVector_Unsigned +from .ADT.StringRef import StringRef +from .Value import Value, MDNode +from .Type import Type, IntegerType IRBuilder = llvm.Class() diff --git a/llvmpy/src/InlineAsm.py b/llvmpy/src/InlineAsm.py index a4ce16b..8793343 100644 --- a/llvmpy/src/InlineAsm.py +++ b/llvmpy/src/InlineAsm.py @@ -1,8 +1,8 @@ from binding import * -from namespace import llvm -from Value import Value -from DerivedTypes import FunctionType -from ADT.StringRef import StringRef +from .namespace import llvm +from .Value import Value +from .DerivedTypes import FunctionType +from .ADT.StringRef import StringRef llvm.includes.add('llvm/InlineAsm.h') diff --git a/llvmpy/src/Instruction.py b/llvmpy/src/Instruction.py index 4761e16..1974aad 100644 --- a/llvmpy/src/Instruction.py +++ b/llvmpy/src/Instruction.py @@ -1,6 +1,6 @@ from binding import * -from namespace import llvm -from Value import Value, MDNode, User, BasicBlock, Function, ConstantInt +from .namespace import llvm +from .Value import Value, MDNode, User, BasicBlock, Function, ConstantInt Instruction = llvm.Class(User) @@ -63,10 +63,10 @@ SynchronizationScope = llvm.Enum('SynchronizationScope', -from ADT.StringRef import StringRef -from CallingConv import CallingConv -from Attributes import Attributes -from Type import Type +from .ADT.StringRef import StringRef +from .CallingConv import CallingConv +from .Attributes import Attributes +from .Type import Type diff --git a/llvmpy/src/Intrinsics.py b/llvmpy/src/Intrinsics.py index 5314112..7e1decd 100644 --- a/llvmpy/src/Intrinsics.py +++ b/llvmpy/src/Intrinsics.py @@ -1,8 +1,8 @@ from binding import * -from namespace import llvm +from .namespace import llvm -from Module import Module -from Function import Function +from .Module import Module +from .Function import Function Intrinsic = llvm.Namespace('Intrinsic') diff --git a/llvmpy/src/JITMemoryManager.py b/llvmpy/src/JITMemoryManager.py index f134735..e34e678 100644 --- a/llvmpy/src/JITMemoryManager.py +++ b/llvmpy/src/JITMemoryManager.py @@ -1,5 +1,5 @@ from binding import * -from namespace import llvm +from .namespace import llvm @llvm.Class() class JITMemoryManager: diff --git a/llvmpy/src/LLVMContext.py b/llvmpy/src/LLVMContext.py index f2526db..4a6b49a 100644 --- a/llvmpy/src/LLVMContext.py +++ b/llvmpy/src/LLVMContext.py @@ -1,5 +1,5 @@ from binding import * -from namespace import llvm +from .namespace import llvm @llvm.Class() class LLVMContext: diff --git a/llvmpy/src/Linker.py b/llvmpy/src/Linker.py index acca503..960bd90 100644 --- a/llvmpy/src/Linker.py +++ b/llvmpy/src/Linker.py @@ -1,8 +1,8 @@ from binding import * -from namespace import llvm -from ADT.StringRef import StringRef -from Module import Module -from LLVMContext import LLVMContext +from .namespace import llvm +from .ADT.StringRef import StringRef +from .Module import Module +from .LLVMContext import LLVMContext llvm.includes.add('llvm/Linker.h') diff --git a/llvmpy/src/Metadata.py b/llvmpy/src/Metadata.py index d5cc4b1..cfeb6ce 100644 --- a/llvmpy/src/Metadata.py +++ b/llvmpy/src/Metadata.py @@ -1,12 +1,12 @@ from binding import * -from namespace import llvm -from Value import Value, MDNode, MDString -from LLVMContext import LLVMContext -from ADT.StringRef import StringRef -from Module import Module -from Function import Function -from Support.raw_ostream import raw_ostream -from Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter +from .namespace import llvm +from .Value import Value, MDNode, MDString +from .LLVMContext import LLVMContext +from .ADT.StringRef import StringRef +from .Module import Module +from .Function import Function +from .Support.raw_ostream import raw_ostream +from .Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter @MDNode class MDNode: diff --git a/llvmpy/src/Module.py b/llvmpy/src/Module.py index d68be36..46fad5a 100644 --- a/llvmpy/src/Module.py +++ b/llvmpy/src/Module.py @@ -1,18 +1,18 @@ from binding import * -from namespace import llvm +from .namespace import llvm Module = llvm.Class() -from LLVMContext import LLVMContext -from ADT.StringRef import StringRef -from Constant import Constant -from GlobalVariable import GlobalVariable -from Function import Function -from DerivedTypes import FunctionType -from Support.raw_ostream import raw_ostream -from Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter -from Type import Type, StructType -from Metadata import NamedMDNode +from .LLVMContext import LLVMContext +from .ADT.StringRef import StringRef +from .Constant import Constant +from .GlobalVariable import GlobalVariable +from .Function import Function +from .DerivedTypes import FunctionType +from .Support.raw_ostream import raw_ostream +from .Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter +from .Type import Type, StructType +from .Metadata import NamedMDNode @Module class Module: diff --git a/llvmpy/src/Pass.py b/llvmpy/src/Pass.py index f36856c..ad03d9a 100644 --- a/llvmpy/src/Pass.py +++ b/llvmpy/src/Pass.py @@ -1,14 +1,14 @@ from binding import * -from namespace import llvm +from .namespace import llvm Pass = llvm.Class() ModulePass = llvm.Class(Pass) FunctionPass = llvm.Class(Pass) ImmutablePass = llvm.Class(ModulePass) -from ADT.StringRef import StringRef -from Module import Module -from Value import Function +from .ADT.StringRef import StringRef +from .Module import Module +from .Value import Function @Pass class Pass: diff --git a/llvmpy/src/PassManager.py b/llvmpy/src/PassManager.py index 91a98f4..4d59e9f 100644 --- a/llvmpy/src/PassManager.py +++ b/llvmpy/src/PassManager.py @@ -1,8 +1,8 @@ from binding import * -from namespace import llvm -from Pass import Pass -from Module import Module -from Value import Function +from .namespace import llvm +from .Pass import Pass +from .Module import Module +from .Value import Function PassManagerBase = llvm.Class() PassManager = llvm.Class(PassManagerBase) diff --git a/llvmpy/src/PassRegistry.py b/llvmpy/src/PassRegistry.py index 495de51..ede026c 100644 --- a/llvmpy/src/PassRegistry.py +++ b/llvmpy/src/PassRegistry.py @@ -1,5 +1,5 @@ from binding import * -from namespace import llvm +from .namespace import llvm from src.ADT.StringRef import StringRef PassRegistry = llvm.Class() diff --git a/llvmpy/src/PassSupport.py b/llvmpy/src/PassSupport.py index 8dba872..d239a6d 100644 --- a/llvmpy/src/PassSupport.py +++ b/llvmpy/src/PassSupport.py @@ -1,5 +1,5 @@ from binding import * -from namespace import llvm +from .namespace import llvm PassInfo = llvm.Class() diff --git a/llvmpy/src/Support/FormattedStream.py b/llvmpy/src/Support/FormattedStream.py index 26f906d..3e9159b 100644 --- a/llvmpy/src/Support/FormattedStream.py +++ b/llvmpy/src/Support/FormattedStream.py @@ -1,6 +1,6 @@ from binding import * from ..namespace import llvm -from raw_ostream import raw_ostream +from .raw_ostream import raw_ostream @llvm.Class(raw_ostream) class formatted_raw_ostream: diff --git a/llvmpy/src/Type.py b/llvmpy/src/Type.py index 8e62137..ea1f0e5 100644 --- a/llvmpy/src/Type.py +++ b/llvmpy/src/Type.py @@ -1,8 +1,8 @@ from binding import * -from namespace import llvm -from LLVMContext import LLVMContext -from Support.raw_ostream import raw_ostream -from ADT.StringRef import StringRef +from .namespace import llvm +from .LLVMContext import LLVMContext +from .Support.raw_ostream import raw_ostream +from .ADT.StringRef import StringRef Type = llvm.Class() IntegerType = llvm.Class(Type) diff --git a/llvmpy/src/User.py b/llvmpy/src/User.py index 9a077c1..1d3cc1f 100644 --- a/llvmpy/src/User.py +++ b/llvmpy/src/User.py @@ -1,6 +1,6 @@ from binding import * -from namespace import llvm -from Value import Value, User +from .namespace import llvm +from .Value import Value, User @User class User: diff --git a/llvmpy/src/Value.py b/llvmpy/src/Value.py index b10807a..669ed80 100644 --- a/llvmpy/src/Value.py +++ b/llvmpy/src/Value.py @@ -1,5 +1,5 @@ from binding import * -from namespace import llvm +from .namespace import llvm # forward declarations Value = llvm.Class() @@ -21,11 +21,11 @@ ConstantDataSequential = llvm.Class(Constant) ConstantDataArray = llvm.Class(ConstantDataSequential) ConstantExpr = llvm.Class(Constant) -from Support.raw_ostream import raw_ostream -from Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter -from Type import Type -from LLVMContext import LLVMContext -from ADT.StringRef import StringRef +from .Support.raw_ostream import raw_ostream +from .Assembly.AssemblyAnnotationWriter import AssemblyAnnotationWriter +from .Type import Type +from .LLVMContext import LLVMContext +from .ADT.StringRef import StringRef @Value diff --git a/llvmpy/src/__init__.py b/llvmpy/src/__init__.py index ed34608..36bc12f 100644 --- a/llvmpy/src/__init__.py +++ b/llvmpy/src/__init__.py @@ -3,11 +3,12 @@ import os.path def _init(root=__name__, file=__file__): 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 : + is_python_module = is_directory and not fname.startswith('__') + if (is_python_module or is_python_script) and not is_init_script: + print(fname) modname = os.path.basename(fname).rsplit('.', 1)[0] #importlib.import_module('.' + modname, __name__) __import__('.'.join([root, modname])) diff --git a/llvmpy/test_binding.py b/llvmpy/test_binding.py index 8eb56f6..c7ceb49 100644 --- a/llvmpy/test_binding.py +++ b/llvmpy/test_binding.py @@ -1,9 +1,10 @@ -from StringIO import StringIO +from io import BytesIO, StringIO from llvmpy.api import llvm from llvmpy import extra from llvmpy import _capsule import llvmpy.capsule +import collections llvmpy.capsule.set_debug(True) @@ -14,19 +15,19 @@ def test_basic_jit_use(): context = llvm.getGlobalContext() m = llvm.Module.new("modname", context) - print m.getModuleIdentifier() + print(m.getModuleIdentifier()) m.setModuleIdentifier('modname2') - print m.getModuleIdentifier() - print 'endianness', m.getEndianness() + print(m.getModuleIdentifier()) + print('endianness', m.getEndianness()) assert m.getEndianness() == llvm.Module.Endianness.AnyEndianness - print 'pointer-size', m.getPointerSize() + print('pointer-size', m.getPointerSize()) assert m.getPointerSize() == llvm.Module.PointerSize.AnyPointerSize m.dump() os = extra.make_raw_ostream_for_printing() m.print_(os, None) - print os.str() + print(os.str()) int1ty = llvm.Type.getInt1Ty(context) @@ -40,11 +41,11 @@ def test_basic_jit_use(): types = [llvm.Type.getIntNTy(context, 8), llvm.Type.getIntNTy(context, 32)] fnty = llvm.FunctionType.get(llvm.Type.getIntNTy(context, 8), types, False) - print fnty + print(fnty) const = m.getOrInsertFunction("foo", fnty) fn = const._downcast(llvm.Function) - print fn + print(fn) assert fn.hasName() assert 'foo' == fn.getName() fn.setName('bar') @@ -63,7 +64,7 @@ def test_basic_jit_use(): assert len(fn_uselist) == 0 builder = llvm.IRBuilder.new(context) - print builder + print(builder) bb = llvm.BasicBlock.Create(context, "entry", fn, None) assert bb.empty() @@ -72,19 +73,19 @@ def test_basic_jit_use(): assert bb.getTerminator() is None arg0, arg1 = fn.getArgumentList() - print arg0, arg1 + print(arg0, arg1) 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 + print(m) # verifier action = llvm.VerifierFailureAction.ReturnStatusAction @@ -92,7 +93,7 @@ def test_basic_jit_use(): corrupted = llvm.verifyFunction(fn, action) assert not corrupted corrupted = llvm.verifyModule(m, action, errio) - print corrupted + print(corrupted) assert not corrupted, errio.getvalue() # build pass manager @@ -114,13 +115,13 @@ def test_basic_jit_use(): pm.run(m) - print m + print(m) # build engine ee = llvm.ExecutionEngine.createJIT(m, errio) - print ee, errio.getvalue() - print ee.getDataLayout().getStringRepresentation() + 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' @@ -149,7 +150,7 @@ def test_basic_jit_use(): assert 44 == gvR.toUnsignedInt() # write bitcode - bc_buffer = StringIO() + bc_buffer = BytesIO() llvm.WriteBitcodeToFile(m, bc_buffer) bc = bc_buffer.getvalue() bc_buffer.close() @@ -187,7 +188,7 @@ def test_engine_builder(): builder.SetInsertPoint(bb) builder.CreateRet(fn.getArgumentList()[0]) - print fn + print(fn) eb = llvm.EngineBuilder.new(m) eb2 = eb.setEngineKind(llvm.EngineKind.Kind.JIT) @@ -196,13 +197,13 @@ def test_engine_builder(): tm = eb.selectTarget() - print 'target triple:', tm.getTargetTriple() - print 'target cpu:', tm.getTargetCPU() - print 'target feature string:', tm.getTargetFeatureString() + print('target triple:', tm.getTargetTriple()) + print('target cpu:', tm.getTargetCPU()) + print('target feature string:', tm.getTargetFeatureString()) target = tm.getTarget() - print 'target name:', target.getName() - print 'target short description:', target.getShortDescription() + print('target name:', target.getName()) + print('target short description:', target.getShortDescription()) assert target.hasJIT() assert target.hasTargetMachine() @@ -218,7 +219,7 @@ def test_engine_builder(): triple_32variant = triple.get32BitArchVariant() assert triple_32variant.isArch32Bit() - print tm.getDataLayout() + print(tm.getDataLayout()) pm = llvm.PassManager.new() pm.add(llvm.DataLayout.new(str(tm.getDataLayout()))) @@ -240,7 +241,7 @@ def test_engine_builder(): formatted.flush() raw.flush() asm = raw.str() - print asm + print(asm) assert 'foo' in asm @@ -301,7 +302,7 @@ def test_globalvariable(): gvar2 = m.getNamedGlobal('apple') assert gvar2 is gvar - print m.list_globals() + print(m.list_globals()) def test_sequentialtypes(): @@ -345,9 +346,9 @@ def test_passregistry(): passinfo = passreg.getPassInfo("dce") dcepass = passinfo.createPass() - print dcepass.getPassName() + print(dcepass.getPassName()) - print passreg.enumerate() + print(passreg.enumerate()) def test_targetregistry(): llvm.TargetRegistry.printRegisteredTargetsForVersion() @@ -356,15 +357,15 @@ def test_targetregistry(): target = llvm.TargetRegistry.getClosestTargetForJIT(errmsg) errmsg.close() - print target.getName() - print target.getShortDescription() + print(target.getName()) + print(target.getShortDescription()) assert target.hasJIT() assert target.hasTargetMachine() next = target.getNext() if next: - print next.getName() - print next.getShortDescription() + print(next.getName()) + print(next.getShortDescription()) triple = llvm.sys.getDefaultTargetTriple() cpu = llvm.sys.getHostCPUName() @@ -375,9 +376,9 @@ def test_targetregistry(): tm = target.createTargetMachine(triple, cpu, "", targetoptions) def main(): - for name, value in globals().items(): - if name.startswith('test_') and callable(value): - print name.center(80, '-') + for name, value in list(globals().items()): + if name.startswith('test_') and isinstance(value, collections.Callable): + print(name.center(80, '-')) value() From d270f47328820bfa7da6477a142555d4ebb646b9 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Sun, 24 Feb 2013 13:21:42 -0600 Subject: [PATCH 80/85] Fix writing to file-like obj in python3.3 --- llvmpy/include/llvm_binding/conversion.h | 2 +- llvmpy/include/llvm_binding/extra.h | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/llvmpy/include/llvm_binding/conversion.h b/llvmpy/include/llvm_binding/conversion.h index abc3749..1c629b7 100644 --- a/llvmpy/include/llvm_binding/conversion.h +++ b/llvmpy/include/llvm_binding/conversion.h @@ -9,7 +9,7 @@ int py_bytes_to(PyObject *bytesobj, llvm::StringRef &strref){ // type check if (!PyBytes_Check(bytesobj)) { // raises TypeError - PyErr_SetString(PyExc_TypeError, "Expecting a str"); + PyErr_SetString(PyExc_TypeError, "Expecting a bytes"); return 0; } // get len and buffer diff --git a/llvmpy/include/llvm_binding/extra.h b/llvmpy/include/llvm_binding/extra.h index 3874bb3..b33a8a0 100644 --- a/llvmpy/include/llvm_binding/extra.h +++ b/llvmpy/include/llvm_binding/extra.h @@ -477,9 +477,13 @@ PyObject* llvm_ParseBitCodeFile(llvm::StringRef Buf, llvm::LLVMContext& Ctx, if (FObj) { std::string ErrStr; M = ParseBitcodeFile(MB, Ctx, &ErrStr); - if (-1 == PyFile_WriteString(ErrStr.c_str(), FObj)) { + auto_pyobject buf = PyBytes_FromString(ErrStr.c_str()); + if (NULL == PyObject_CallMethod(FObj, "write", "O", *buf)){ return NULL; } +// if (-1 == PyFile_WriteString(ErrStr.c_str(), FObj)) { +// return NULL; +// } } else { M = ParseBitcodeFile(MB, Ctx); } @@ -497,9 +501,8 @@ PyObject* llvm_WriteBitcodeToFile(const llvm::Module *M, PyObject* FObj) llvm::WriteBitcodeToFile(M, rso); rso.flush(); StringRef ref = rso.str(); - PyObject* buf = PyBytes_FromStringAndSize(ref.data(), ref.size()); - puts(PyString_AsString(PyObject_Str(PyObject_Type(buf)))); - return PyObject_CallMethod(FObj, "write", "O", buf); + auto_pyobject buf = PyBytes_FromStringAndSize(ref.data(), ref.size()); + return PyObject_CallMethod(FObj, "write", "O", *buf); } static From c1b46e4384958a37493dc9130710f2eecac7624d Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Mon, 25 Feb 2013 10:02:49 -0600 Subject: [PATCH 81/85] Fix test --- llvmpy/test_binding.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvmpy/test_binding.py b/llvmpy/test_binding.py index c7ceb49..aee0167 100644 --- a/llvmpy/test_binding.py +++ b/llvmpy/test_binding.py @@ -156,7 +156,7 @@ def test_basic_jit_use(): bc_buffer.close() # read bitcode - errbuf = StringIO() + errbuf = BytesIO() m2 = llvm.ParseBitCodeFile(bc, context, errbuf) if not m2: raise Exception(errbuf.getvalue()) From dd9ba65328f18c881318ebeddcee73d2b48217b2 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Tue, 26 Feb 2013 18:43:49 -0600 Subject: [PATCH 82/85] Bug fixes --- llvm/core.py | 2 +- llvmpy/include/llvm_binding/conversion.h | 4 ++-- llvmpy/src/Instruction.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/llvm/core.py b/llvm/core.py index f38028b..268318a 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -1729,7 +1729,7 @@ class CallOrInvokeInstruction(Instruction): return _make_value(function) def _set_called_function(self, function): - self._ptr.setCalledFunction(function) + self._ptr.setCalledFunction(function._ptr) called_function = property(_get_called_function, _set_called_function) diff --git a/llvmpy/include/llvm_binding/conversion.h b/llvmpy/include/llvm_binding/conversion.h index 1c629b7..5395a3f 100644 --- a/llvmpy/include/llvm_binding/conversion.h +++ b/llvmpy/include/llvm_binding/conversion.h @@ -124,8 +124,8 @@ int py_int_to(PyObject *intobj, unsigned & val){ static int py_int_to(PyObject *intobj, unsigned long long & val){ if (!PyInt_Check(intobj) and !PyLong_Check(intobj)) { - // raise TypeError - PyErr_SetString(PyExc_TypeError, "Expecting an int 2"); + // raise TypeError; + PyErr_SetString(PyExc_TypeError, "Expecting an int"); return 0; } val = PyInt_AsUnsignedLongLongMask(intobj); diff --git a/llvmpy/src/Instruction.py b/llvmpy/src/Instruction.py index 1974aad..beb94f1 100644 --- a/llvmpy/src/Instruction.py +++ b/llvmpy/src/Instruction.py @@ -134,7 +134,7 @@ class BinaryOperator: @CallInst class CallInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction getCallingConv = Method(CallingConv.ID) setCallingConv = Method(Void, CallingConv.ID) @@ -277,7 +277,7 @@ class IndirectBrInst: @InvokeInst class InvokeInst: - _downcast_ = Value, Instruction + _downcast_ = Value, User, Instruction getCallingConv = Method(CallingConv.ID) setCallingConv = Method(Void, CallingConv.ID) getParamAlignment = Method(cast(Unsigned, int), cast(int, Unsigned)) From c3a08a446fead9268a136aeac4f853097ca4bf78 Mon Sep 17 00:00:00 2001 From: cuda Date: Wed, 27 Feb 2013 11:28:07 -0600 Subject: [PATCH 83/85] Fix import and Makefile on Linux --- llvmpy/Makefile | 3 +-- llvmpy/src/PassManager.py | 8 +++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/llvmpy/Makefile b/llvmpy/Makefile index 9de1fb0..e9cc1c3 100644 --- a/llvmpy/Makefile +++ b/llvmpy/Makefile @@ -10,8 +10,7 @@ api.cpp api/__init__.py: src/*.py include/llvm_binding/*.h gen/gen.py gen/bindin clean: cleantemp rm -f _api.so _capsule.so - rm -rf api - py_clean + rm -rf api cleantemp: rm -f api.cpp diff --git a/llvmpy/src/PassManager.py b/llvmpy/src/PassManager.py index 4d59e9f..760f080 100644 --- a/llvmpy/src/PassManager.py +++ b/llvmpy/src/PassManager.py @@ -1,13 +1,15 @@ from binding import * from .namespace import llvm -from .Pass import Pass -from .Module import Module -from .Value import Function PassManagerBase = llvm.Class() PassManager = llvm.Class(PassManagerBase) FunctionPassManager = llvm.Class(PassManagerBase) +from .Pass import Pass +from .Module import Module +from .Value import Function + + @PassManagerBase class PassManagerBase: _include_ = 'llvm/PassManager.h' From 740d2595eeae16592b0ae7d2dbdd43e0b6d0ef18 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 27 Feb 2013 13:25:19 -0600 Subject: [PATCH 84/85] Replace StringIO with BytesIO --- llvm/core.py | 21 +++++++++------------ llvm/ee.py | 9 +++------ llvm/test_llvmpy.py | 15 +++++---------- 3 files changed, 17 insertions(+), 28 deletions(-) diff --git a/llvm/core.py b/llvm/core.py index 268318a..49b5561 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -28,10 +28,7 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -try: - from cStringIO import StringIO -except ImportError: - from StringIO import StringIO +from io import BytesIO import contextlib, weakref import llvm @@ -337,7 +334,7 @@ class Module(llvm.Wrapper): bc = fileobj_or_str else: bc = fileobj_or_str.read() - errbuf = StringIO() + errbuf = BytesIO() context = api.llvm.getGlobalContext() m = api.llvm.ParseBitCodeFile(bc, context, errbuf) if not m: @@ -359,7 +356,7 @@ class Module(llvm.Wrapper): ir = fileobj_or_str else: ir = fileobj_or_str.read() - errbuf = StringIO() + errbuf = BytesIO() context = api.llvm.getGlobalContext() m = api.llvm.ParseAssemblyString(ir, None, api.llvm.SMDiagnostic.new(), context) @@ -432,7 +429,7 @@ class Module(llvm.Wrapper): enum_mode = api.llvm.Linker.LinkerMode mode = enum_mode.PreserveSource if preserve else enum_mode.DestroySource - with contextlib.closing(StringIO()) as errmsg: + with contextlib.closing(BytesIO()) as errmsg: failed = api.llvm.Linker.LinkModules(self._ptr, other._ptr, mode, @@ -512,7 +509,7 @@ class Module(llvm.Wrapper): Checks module for errors. Raises `llvm.LLVMException' on any error.""" action = api.llvm.VerifierFailureAction.ReturnStatusAction - errio = StringIO() + errio = BytesIO() broken = api.llvm.verifyModule(self._ptr, action, errio) if broken: raise llvm.LLVMException(errio.getvalue()) @@ -530,7 +527,7 @@ class Module(llvm.Wrapper): ret = False if fileobj is None: ret = True - fileobj = StringIO + fileobj = BytesIO api.llvm.WriteBitcodeToFile(self._ptr, fileobj) if ret: return fileobj.getvalue() @@ -571,7 +568,7 @@ class Module(llvm.Wrapper): ret = False if fileobj is None: ret = True - fileobj = StringIO() + fileobj = BytesIO() from llvm.ee import TargetMachine tm = TargetMachine.new() fileobj.write(tm.emit_object(self)) @@ -588,7 +585,7 @@ class Module(llvm.Wrapper): ret = False if fileobj is None: ret = True - fileobj = StringIO() + fileobj = BytesIO() from llvm.ee import TargetMachine tm = TargetMachine.new() fileobj.write(tm.emit_assembly(self)) @@ -2269,7 +2266,7 @@ def load_library_permanently(filename): Load the given shared library (filename argument specifies the full path of the .so file) using LLVM. Symbols from these are available from the execution engine thereafter.""" - with contextlib.closing(StringIO()) as errmsg: + with contextlib.closing(BytesIO()) as errmsg: failed = api.llvm.sys.DynamicLibrary.LoadPermanentLibrary(filename, errmsg) if failed: diff --git a/llvm/ee.py b/llvm/ee.py index 8598ad9..030eacb 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -30,10 +30,7 @@ "Execution Engine and related classes." -try: - from cStringIO import StringIO -except ImportError: - from StringIO import StringIO +from io import BytesIO import contextlib import llvm @@ -244,7 +241,7 @@ class TargetMachine(llvm.Wrapper): triple = get_default_triple() if not cpu: cpu = get_host_cpu_name() - with contextlib.closing(StringIO()) as error: + with contextlib.closing(BytesIO()) as error: target = api.llvm.TargetRegistry.lookupTarget(triple, error) if not target: raise llvm.LLVMException(error) @@ -273,7 +270,7 @@ class TargetMachine(llvm.Wrapper): use: `llvm-as < /dev/null | llc -march=xyz -mattr=help` ''' triple = api.llvm.Triple.new() - with contextlib.closing(StringIO()) as error: + with contextlib.closing(BytesIO()) as error: target = api.llvm.TargetRegistry.lookupTarget(arch, triple, error) if not target: raise llvm.LLVMException(error) diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index 5b26e39..8c9b800 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -10,13 +10,8 @@ import subprocess import tempfile import contextlib -is_py3k = bool(sys.version_info[0] == 3) BITS = tuple.__itemsize__ * 8 - -if is_py3k: - from io import StringIO -else: - from cStringIO import StringIO +from io import BytesIO import llvm @@ -123,7 +118,7 @@ class TestAttr(TestCase): ret void } """ - return Module.from_assembly(StringIO(test_module)) + return Module.from_assembly(BytesIO(test_module)) def test_align(self): m = self.make_module() @@ -255,7 +250,7 @@ entry: } """ def test_operands(self): - m = Module.from_assembly(StringIO(self.test_module)) + m = Module.from_assembly(BytesIO(self.test_module)) test_func = m.get_function_named("test_func") prod = m.get_function_named("prod") @@ -317,7 +312,7 @@ entry: } """ def test_passes(self): - m = Module.from_assembly(StringIO(self.asm)) + m = Module.from_assembly(BytesIO(self.asm)) fn_test1 = m.get_function_named('test1') fn_test2 = m.get_function_named('test2') @@ -365,7 +360,7 @@ entry: self.assertNotEqual(str(fn_test1).strip(), original_test1.strip()) def test_passes_with_pmb(self): - m = Module.from_assembly(StringIO(self.asm)) + m = Module.from_assembly(BytesIO(self.asm)) fn_test1 = m.get_function_named('test1') fn_test2 = m.get_function_named('test2') From 93cd20e9336e337016e0c73faf1172d017ba3e0b Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 27 Feb 2013 13:48:08 -0600 Subject: [PATCH 85/85] Fix for python 3 --- llvm/core.py | 25 +++++++++++++++++-------- llvm/ee.py | 2 +- llvm/passes.py | 1 - llvm/test_llvmpy.py | 33 +++++++++++++++++++-------------- test/inlineasm.py | 2 +- test/malloc.py | 2 +- test/tbaa.py | 2 +- test/test_debuginfo.py | 2 +- 8 files changed, 41 insertions(+), 28 deletions(-) diff --git a/llvm/core.py b/llvm/core.py index 49b5561..bed5763 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -29,6 +29,14 @@ # from io import BytesIO +try: + from StringIO import StringIO +except ImportError: + try: + from cStringIO import StringIO + except ImportError: + from io import StringIO + import contextlib, weakref import llvm @@ -468,7 +476,7 @@ class Module(llvm.Wrapper): @property def global_variables(self): - return map(_make_value, self._ptr.list_globals()) + return list(map(_make_value, self._ptr.list_globals())) def add_function(self, ty, name): """Add a function of given type with given name.""" @@ -501,7 +509,7 @@ class Module(llvm.Wrapper): @property def functions(self): """All functions in this module.""" - return map(_make_value, self._ptr.list_functions()) + return list(map(_make_value, self._ptr.list_functions())) def verify(self): """Verify module. @@ -585,10 +593,11 @@ class Module(llvm.Wrapper): ret = False if fileobj is None: ret = True - fileobj = BytesIO() + fileobj = StringIO() from llvm.ee import TargetMachine tm = TargetMachine.new() - fileobj.write(tm.emit_assembly(self)) + asm = tm.emit_assembly(self) + fileobj.write(asm) if ret: return fileobj.getvalue() @@ -983,7 +992,7 @@ class Value(llvm.Wrapper): @property def uses(self): - return map(_make_value, self._ptr.list_use()) + return list(map(_make_value, self._ptr.list_use())) class User(Value): _type_ = api.llvm.User @@ -1458,7 +1467,7 @@ class Function(GlobalValue): @property def args(self): args = self._ptr.getArgumentList() - return map(_make_value, args) + return list(map(_make_value, args)) @property def basic_block_count(self): @@ -1480,7 +1489,7 @@ class Function(GlobalValue): @property def basic_blocks(self): - return map(_make_value, self._ptr.getBasicBlockList()) + return list(map(_make_value, self._ptr.getBasicBlockList())) def viewCFG(self): return self._ptr.viewCFG() @@ -1782,7 +1791,7 @@ class BasicBlock(Value): @property def instructions(self): - return map(_make_value, self._ptr.getInstList()) + return list(map(_make_value, self._ptr.getInstList())) #===----------------------------------------------------------------------=== # Value factory method diff --git a/llvm/ee.py b/llvm/ee.py index 030eacb..672a0b6 100644 --- a/llvm/ee.py +++ b/llvm/ee.py @@ -179,7 +179,7 @@ class ExecutionEngine(llvm.Wrapper): self._ptr.DisableLazyCompilation(disabled) def run_function(self, fn, args): - ptr = self._ptr.runFunction(fn._ptr, map(lambda x: x._ptr, args)) + ptr = self._ptr.runFunction(fn._ptr, list(map(lambda x: x._ptr, args))) return GenericValue(ptr) def get_pointer_to_function(self, fn): diff --git a/llvm/passes.py b/llvm/passes.py index 36e7d97..9f706d8 100644 --- a/llvm/passes.py +++ b/llvm/passes.py @@ -147,7 +147,6 @@ class PassManager(llvm.Wrapper): if not a_pass: assert pass_name not in PASSES, "Registered but not found?" raise llvm.LLVMException('Invalid pass name "%s"' % pass_name) - print a_pass self._ptr.add(a_pass) def run(self, module): diff --git a/llvm/test_llvmpy.py b/llvm/test_llvmpy.py index 8c9b800..3656621 100644 --- a/llvm/test_llvmpy.py +++ b/llvm/test_llvmpy.py @@ -11,7 +11,11 @@ import tempfile import contextlib BITS = tuple.__itemsize__ * 8 -from io import BytesIO + +try: + from StringIO import StringIO +except ImportError: + from io import StringIO import llvm @@ -118,7 +122,8 @@ class TestAttr(TestCase): ret void } """ - return Module.from_assembly(BytesIO(test_module)) + buf = StringIO(test_module) + return Module.from_assembly(buf) def test_align(self): m = self.make_module() @@ -250,7 +255,7 @@ entry: } """ def test_operands(self): - m = Module.from_assembly(BytesIO(self.test_module)) + m = Module.from_assembly(StringIO(self.test_module)) test_func = m.get_function_named("test_func") prod = m.get_function_named("prod") @@ -312,7 +317,7 @@ entry: } """ def test_passes(self): - m = Module.from_assembly(BytesIO(self.asm)) + m = Module.from_assembly(StringIO(self.asm)) fn_test1 = m.get_function_named('test1') fn_test2 = m.get_function_named('test2') @@ -360,7 +365,7 @@ entry: self.assertNotEqual(str(fn_test1).strip(), original_test1.strip()) def test_passes_with_pmb(self): - m = Module.from_assembly(BytesIO(self.asm)) + m = Module.from_assembly(StringIO(self.asm)) fn_test1 = m.get_function_named('test1') fn_test2 = m.get_function_named('test2') @@ -626,7 +631,7 @@ class TestTargetMachines(TestCase): self.assertTrue(tm.target_data) self.assertTrue(tm.target_short_description) self.assertTrue(tm.triple) - self.assertIn('foo', tm.emit_assembly(m).decode('utf-8')) + self.assertIn('foo', tm.emit_assembly(m)) self.assertTrue(le.get_host_cpu_name()) def test_ptx(self): @@ -636,13 +641,13 @@ class TestTargetMachines(TestCase): arch = 'nvptx64' else: return # skip this test - print arch + print(arch) m, func = self._build_module() func.calling_convention = lc.CC_PTX_KERNEL # set calling conv ptxtm = le.TargetMachine.lookup(arch=arch, cpu='sm_20') self.assertTrue(ptxtm.triple) self.assertTrue(ptxtm.cpu) - ptxasm = ptxtm.emit_assembly(m).decode('utf-8') + ptxasm = ptxtm.emit_assembly(m) self.assertIn('foo', ptxasm) if lc.HAS_NVPTX: self.assertIn('.address_size 64', ptxasm) @@ -936,31 +941,31 @@ class TestCPUSupport(TestCase): def test_cpu_support2(self): features = 'sse3', 'sse41', 'sse42', 'avx' mattrs = ','.join(map(lambda s: '-%s' % s, features)) - print 'disable mattrs', mattrs + print('disable mattrs', mattrs) self._template(mattrs) def test_cpu_support3(self): features = 'sse41', 'sse42', 'avx' mattrs = ','.join(map(lambda s: '-%s' % s, features)) - print 'disable mattrs', mattrs + print('disable mattrs', mattrs) self._template(mattrs) def test_cpu_support4(self): features = 'sse42', 'avx' mattrs = ','.join(map(lambda s: '-%s' % s, features)) - print 'disable mattrs', mattrs + print('disable mattrs', mattrs) self._template(mattrs) def test_cpu_support5(self): features = 'avx', mattrs = ','.join(map(lambda s: '-%s' % s, features)) - print 'disable mattrs', mattrs + print('disable mattrs', mattrs) self._template(mattrs) def test_cpu_support6(self): features = [] mattrs = ','.join(map(lambda s: '-%s' % s, features)) - print 'disable mattrs', mattrs + print('disable mattrs', mattrs) self._template(mattrs) tests.append(TestCPUSupport) @@ -1235,4 +1240,4 @@ def run(verbosity=1): if __name__ == '__main__': - run() + unittest.main() diff --git a/test/inlineasm.py b/test/inlineasm.py index df91d71..64a4cbe 100644 --- a/test/inlineasm.py +++ b/test/inlineasm.py @@ -20,7 +20,7 @@ class TestInlineAsm(TestCase): inlineasm = InlineAsm.get(iaty, "bswap $0", "=r,r") self.assertIn('asm "bswap $0", "=r,r"', str(inlineasm)) builder.ret(builder.call(inlineasm, [fn.args[0]])) - print fn + print(fn) if __name__ == '__main__': unittest.main() diff --git a/test/malloc.py b/test/malloc.py index 1613a36..be37dcd 100644 --- a/test/malloc.py +++ b/test/malloc.py @@ -10,7 +10,7 @@ def test(): alloc = b.malloc_array(Type.int(), Constant.int(Type.int(), 10), 'hee') inst = b.free(alloc) b.ret_void() - print m + print(m) if __name__ == '__main__': test() diff --git a/test/tbaa.py b/test/tbaa.py index 242ed19..ad11081 100644 --- a/test/tbaa.py +++ b/test/tbaa.py @@ -29,7 +29,7 @@ class TestTBAABuilder(TestCase): bldr.ret_void() - print mod + print(mod) if __name__ == '__main__': unittest.main() diff --git a/test/test_debuginfo.py b/test/test_debuginfo.py index 33dbbdb..b6a5d6f 100644 --- a/test/test_debuginfo.py +++ b/test/test_debuginfo.py @@ -122,7 +122,7 @@ def debug_in_gdb(lfunc): # Now let's compile and run! retval = ee.run_function(lfunc, [arg1]) - print retval.as_real(float_type) + print(retval.as_real(float_type)) if __name__ == '__main__':