Major refactoring

This commit is contained in:
Siu Kwan Lam 2013-01-25 12:29:31 -06:00
commit eba88b32ba
22 changed files with 999 additions and 924 deletions

View file

@ -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

View file

@ -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)

279
newbinding/codegen.py Normal file
View file

@ -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)

20
newbinding/extra.py Normal file
View file

@ -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())

View file

@ -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()

View file

@ -0,0 +1,38 @@
#ifndef AUTO_PYOBJECT_H_
#define AUTO_PYOBJECT_H_
#include <Python.h>
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_

View file

@ -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){

View file

@ -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"

View file

@ -2,4 +2,6 @@ from binding import *
from namespace import llvm
from User import User
Constant = User.Subclass()
@llvm.Class(User)
class Constant:
pass

View file

@ -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))

View file

@ -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))

View file

@ -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()

View file

@ -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()

View file

@ -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"

View file

@ -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

View file

@ -2,4 +2,7 @@ from binding import *
from namespace import llvm
from Value import Value
User = Value.Subclass()
@llvm.Class(Value)
class User:
pass

View file

@ -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)
hasName = Method(cast(Bool, bool))
# skip getValueName, setValueName
getName = Method(cast(StringRef, str))
setName = Method(Void, cast(str, StringRef))
replaceAllUsesWith = Method(Void, ptr(Value))

View file

@ -0,0 +1,2 @@
from . import Module

View file

@ -1,4 +1,3 @@
from binding import *
extra = Namespace('llvm_extra')
llvm = Namespace('llvm')

View file

@ -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))

View file

@ -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()

View file

@ -1,6 +0,0 @@
def indent_println(println):
def _println(s):
println("%s%s" % (' '* 4, s))
return _println