All of DataLayout, IRBuilder and started on ExecutionEngine.

This commit is contained in:
Siu Kwan Lam 2013-01-29 17:47:15 -06:00
commit 437b1e9490
20 changed files with 688 additions and 41 deletions

View file

@ -5,11 +5,15 @@ import codegen as cg
_rank = 0 _rank = 0
namespaces = {} namespaces = {}
RESERVED = frozenset(['None'])
class Namespace(object): class Namespace(object):
def __init__(self, name): def __init__(self, name):
self.name = name self.name = name
self.enums = []
self.classes = [] self.classes = []
self.functions = [] self.functions = []
self.includes = set()
namespaces[name] = self namespaces[name] = self
def Class(self, *bases): def Class(self, *bases):
@ -22,6 +26,13 @@ class Namespace(object):
self.functions.append(fn) self.functions.append(fn)
return 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 @property
def fullname(self): def fullname(self):
return self.name return self.name
@ -43,11 +54,16 @@ class BuiltinTypes(_Type):
def wrap(self, writer, var): def wrap(self, writer, var):
return var return var
def unwrap(self, writer, var):
return var
Void = BuiltinTypes('void') Void = BuiltinTypes('void')
Unsigned = BuiltinTypes('unsigned') Unsigned = BuiltinTypes('unsigned')
Uint64 = BuiltinTypes('uint64_t')
Bool = BuiltinTypes('bool') Bool = BuiltinTypes('bool')
ConstStdString = BuiltinTypes('const std::string') ConstStdString = BuiltinTypes('const std::string')
PyObjectPtr = BuiltinTypes('PyObject*') PyObjectPtr = BuiltinTypes('PyObject*')
PyObjectPtr.format='O'
class Class(_Type): class Class(_Type):
format = 'O' format = 'O'
@ -78,6 +94,7 @@ class Class(_Type):
self.enums.append(v) self.enums.append(v)
v.name = k v.name = k
v.parent = self v.parent = self
setattr(self, k, v)
elif isinstance(v, CustomPythonMethod): elif isinstance(v, CustomPythonMethod):
self.pymethods.append(v) self.pymethods.append(v)
elif k == '_include_': elif k == '_include_':
@ -108,7 +125,7 @@ class Class(_Type):
fmt = '{ "%(name)s", (PyCFunction)%(func)s, METH_VARARGS, NULL },' fmt = '{ "%(name)s", (PyCFunction)%(func)s, METH_VARARGS, NULL },'
for meth in self.methods: for meth in self.methods:
name = meth.name name = meth.name
func = cg.mangle(meth.fullname) func = meth.c_name
writer.println(fmt % locals()) writer.println(fmt % locals())
writer.println('{ NULL },') writer.println('{ NULL },')
writer.println('};') writer.println('};')
@ -161,9 +178,12 @@ class Class(_Type):
return casted return casted
class Enum(object): class Enum(object):
format = 'O'
def __init__(self, *value_names): def __init__(self, *value_names):
self.parent = None self.parent = None
self.value_names = value_names self.value_names = value_names
self.includes = set()
@property @property
def fullname(self): def fullname(self):
@ -191,11 +211,34 @@ class Enum(object):
writer.raises(ValueError, 'Invalid enum %s' % v) writer.raises(ValueError, 'Invalid enum %s' % v)
return ret 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): def compile_py(self, writer):
with writer.block('class %s:' % self.name): with writer.block('class %s:' % self.name):
writer.println('_llvm_type_ = "%s"' % self.fullname) writer.println('_llvm_type_ = "%s"' % self.fullname)
for v in self.value_names: 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() writer.println()
class Method(object): class Method(object):
@ -236,11 +279,15 @@ class Method(object):
def realname(self, v): def realname(self, v):
self.__realname = v self.__realname = v
@property
def c_name(self):
return cg.mangle("%s_%s" % (self.parent, self.name))
def __str__(self): def __str__(self):
return self.fullname return self.fullname
def compile_cpp(self, writer): def compile_cpp(self, writer):
with writer.py_function(self.fullname): with writer.py_function(self.c_name):
if len(self.signatures) == 1: if len(self.signatures) == 1:
sig = self.signatures[0] sig = self.signatures[0]
retty = sig[0] retty = sig[0]
@ -270,13 +317,40 @@ class Method(object):
with decl as (this, varargs): with decl as (this, varargs):
unwrap_this = writer.unwrap(this) unwrap_this = writer.unwrap(this)
unwrapped = writer.unwrap_many(varargs) unwrapped = writer.unwrap_many(varargs)
self.process_ownedptr_args(writer, unwrapped)
func = '.'.join([self.parent.name, self.name]) func = '.'.join([self.parent.name, self.name])
ret = writer.call('_api.%s' % func, ret = writer.call('_api.%s' % func,
args=(unwrap_this,), varargs=unwrapped) args=(unwrap_this,), varargs=unwrapped)
wrapped = writer.wrap(ret)
wrapped = writer.wrap(ret, self.is_return_ownedptr())
writer.return_value(wrapped) writer.return_value(wrapped)
writer.println() 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): class CustomMethod(Method):
def __init__(self, methodname, retty, *argtys): def __init__(self, methodname, retty, *argtys):
@ -289,7 +363,6 @@ class CustomMethod(Method):
writer.return_value(retty.wrap(writer, ret)) writer.return_value(retty.wrap(writer, ret))
class StaticMethod(Method): class StaticMethod(Method):
def compile_cpp_body(self, writer, retty, argtys): def compile_cpp_body(self, writer, retty, argtys):
@ -307,12 +380,24 @@ class StaticMethod(Method):
decl = writer.function(self.name, varargs='args') decl = writer.function(self.name, varargs='args')
with decl as varargs: with decl as varargs:
unwrapped = writer.unwrap_many(varargs) unwrapped = writer.unwrap_many(varargs)
self.process_ownedptr_args(writer, unwrapped)
func = '.'.join([self.parent.name, self.name]) func = '.'.join([self.parent.name, self.name])
ret = writer.call('_api.%s' % func, varargs=unwrapped) 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.return_value(wrapped)
writer.println() 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): class Function(Method):
_kind_ = 'func' _kind_ = 'func'
@ -329,10 +414,11 @@ class Function(Method):
def compile_py(self, writer): def compile_py(self, writer):
with writer.function(self.name, varargs='args') as varargs: with writer.function(self.name, varargs='args') as varargs:
unwrapped = writer.unwrap_many(varargs) unwrapped = writer.unwrap_many(varargs)
self.process_ownedptr_args(writer, unwrapped)
func = self.fullname.split('::', 1)[1].replace('::', '.') func = self.fullname.split('::', 1)[1].replace('::', '.')
ret = writer.call('_api.%s' % func, ret = writer.call('_api.%s' % func,
varargs=unwrapped) varargs=unwrapped)
wrapped = writer.wrap(ret) wrapped = writer.wrap(ret, self.is_return_ownedptr())
writer.return_value(wrapped) writer.return_value(wrapped)
writer.println() writer.println()
@ -400,10 +486,14 @@ class ptr(_Type):
def __init__(self, element): def __init__(self, element):
assert isinstance(element, Class) assert isinstance(element, Class)
self.element = element self.element = element
self.const = False
@property @property
def fullname(self): def fullname(self):
return '%s*' % self.element if self.const:
return 'const %s*' % self.element
else:
return '%s*' % self.element
@property @property
def format(self): def format(self):
@ -420,6 +510,13 @@ class ptr(_Type):
return writer.pycapsule_new(val, self.element.capsule_name, return writer.pycapsule_new(val, self.element.capsule_name,
self.element.fullname) self.element.fullname)
class ownedptr(ptr):
pass
def const(ptr):
ptr.const = True
return ptr
class cast(_Type): class cast(_Type):
format = 'O' format = 'O'
@ -458,7 +555,6 @@ class cast(_Type):
return ret return ret
class CustomPythonMethod(object): class CustomPythonMethod(object):
def __init__(self, fn): def __init__(self, fn):
src = inspect.getsource(fn) src = inspect.getsource(fn)

View file

@ -23,10 +23,11 @@ class WeakRef(ref):
_pyclasses = {} _pyclasses = {}
_addr2obj = WeakValueDictionary() _addr2obj = WeakValueDictionary()
_owners = {} _owners = {} # address to weak reference
def _sentry(ptr): def _sentry(ptr):
assert _capsule.check(ptr) if not _capsule.check(ptr):
raise ValueError('Must provide a PyCapsule object.')
def classof(cap): def classof(cap):
cls = _capsule.getClassName(cap) cls = _capsule.getClassName(cap)
@ -38,17 +39,16 @@ def _capsule_destructor(weak):
addr = _capsule.getPointer(cap) addr = _capsule.getPointer(cap)
cls = _capsule.getClassName(cap) cls = _capsule.getClassName(cap)
logger.debug("destroy pointer 0x%08X to %s", addr, cls) logger.debug("destroy pointer 0x%08X to %s", addr, cls)
weak.dtor(cap) # weak.dtor(cap)
del _owners[addr] del _owners[addr]
def release_ownership(old): def release_ownership(old):
addr = _capsule.getPointer(old) addr = _capsule.getPointer(old)
if hasattr(old, '_delete_'): oldweak = _owners[addr]
oldweak = _owners[addr] oldweak.owning = False # dis-own
oldweak.owning = False # dis-own del _owners[addr]
del _owners[addr]
def wrap(cap): def wrap(cap, owned=False):
'''Wrap a PyCapsule with the corresponding Wrapper class. '''Wrap a PyCapsule with the corresponding Wrapper class.
If `cap` is not a PyCapsule, returns `cap` If `cap` is not a PyCapsule, returns `cap`
''' '''
@ -66,7 +66,8 @@ def wrap(cap):
obj = cls(cap) obj = cls(cap)
_addr2obj[addr] = obj # cache object by address _addr2obj[addr] = obj # cache object by address
# set ownership if *cls* defines *_delete_* # 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) weak = WeakRef(obj, _capsule_destructor)
_owners[addr] = weak _owners[addr] = weak
weak.capsule = cap weak.capsule = cap
@ -84,10 +85,11 @@ def wrap(cap):
def downcast(old, new): def downcast(old, new):
assert old is not new assert old is not new
assert _capsule.getPointer(old) not in _owners
oldcls = classof(old) oldcls = classof(old)
newcls = classof(new) newcls = classof(new)
assert issubclass(newcls, oldcls) assert issubclass(newcls, oldcls)
release_ownership(old) # release_ownership(old)
del _addr2obj[_capsule.getPointer(old)] # clear cache del _addr2obj[_capsule.getPointer(old)] # clear cache
return wrap(new) return wrap(new)

View file

@ -104,10 +104,9 @@ class CodeWriterBase(object):
@contextlib.contextmanager @contextlib.contextmanager
def py_function(self, name): def py_function(self, name):
mangled = mangle(name)
self.println('static') self.println('static')
self.println('PyObject*') 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('self')
self.used_symbols.add('args') self.used_symbols.add('args')
yield yield
@ -175,7 +174,7 @@ class CppCodeWriter(CodeWriterBase):
arglist = ', '.join(args) arglist = ', '.join(args)
stmt = '%(func)s(%(arglist)s)' % locals() stmt = '%(func)s(%(arglist)s)' % locals()
if retty == 'void': if retty == 'void':
self.println(stmt) self.println(stmt + ';')
else: else:
return self.declare(retty, stmt) return self.declare(retty, stmt)
@ -247,6 +246,9 @@ class PyCodeWriter(CodeWriterBase):
yield yield
self.used_symbols = self.old self.used_symbols = self.old
def release_ownership(self, val):
self.println('capsule.release_ownership(%(val)s)' % locals())
def unwrap_many(self, args): def unwrap_many(self, args):
unwrapped = self.new_symbol('unwrapped') unwrapped = self.new_symbol('unwrapped')
self.println('%(unwrapped)s = map(capsule.unwrap, %(args)s)' % locals()) self.println('%(unwrapped)s = map(capsule.unwrap, %(args)s)' % locals())
@ -255,9 +257,9 @@ class PyCodeWriter(CodeWriterBase):
def unwrap(self, val): def unwrap(self, val):
return self.call('capsule.unwrap', args=(val,), ret='unwrapped') return self.call('capsule.unwrap', args=(val,), ret='unwrapped')
def wrap(self, val): def wrap(self, val, owned):
wrapped = self.new_symbol('wrapped') 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 return wrapped
def call(self, func, args=(), varargs=None, ret='ret'): def call(self, func, args=(), varargs=None, ret='ret'):

View file

@ -39,6 +39,7 @@ populate_submodules(module, submodules);
def populate_headers(println): def populate_headers(println):
includes = [ includes = [
'cstring',
'llvm_binding/conversion.h', 'llvm_binding/conversion.h',
'llvm_binding/binding.h', 'llvm_binding/binding.h',
'llvm_binding/capsule_context.h', 'llvm_binding/capsule_context.h',
@ -70,6 +71,9 @@ def main():
for cls in ns.classes: for cls in ns.classes:
print cls print cls
units.append(cls) units.append(cls)
for enum in ns.enums:
print enum
units.append(enum)
# add extra stuffs # add extra stuffs
downcastlist = [] downcastlist = []
@ -84,7 +88,7 @@ def main():
units.append(fn) units.append(fn)
# generate cpp source # Generate C++ source
with open('%s.cpp' % outputfilename, 'w') as cppfile: with open('%s.cpp' % outputfilename, 'w') as cppfile:
println = wrap_println_from_file(cppfile) println = wrap_println_from_file(cppfile)
@ -93,6 +97,8 @@ def main():
# required headers # required headers
includes = set() includes = set()
for ns in namespaces.values():
includes |= ns.includes
for u in units: for u in units:
includes |= u.includes includes |= u.includes
@ -128,7 +134,7 @@ static
for u in units: for u in units:
if isinstance(u, Function): if isinstance(u, Function):
name = u.name name = u.name
func = codegen.mangle(u.fullname) func = u.c_name
writer.println(fmt % locals()) writer.println(fmt % locals())
writer.println('{ NULL },') writer.println('{ NULL },')
writer.println('};') writer.println('};')
@ -154,6 +160,7 @@ static
println(extension_entry % {'module': '_api', 'methtable': 'methtable'}) println(extension_entry % {'module': '_api', 'methtable': 'methtable'})
# Generate Python source
with open('%s.py' % outputfilename, 'w') as pyfile: with open('%s.py' % outputfilename, 'w') as pyfile:
println = wrap_println_from_file(pyfile) println = wrap_println_from_file(pyfile)
println('import _api, capsule') println('import _api, capsule')

View file

@ -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<void*>(ptr), basename, classname);
}
#endif //LLVMPY_CAPSULE_CONTEXT_H_ #endif //LLVMPY_CAPSULE_CONTEXT_H_

View file

@ -3,7 +3,7 @@
#include <llvm/Value.h> #include <llvm/Value.h>
#include <llvm/Function.h> #include <llvm/Function.h>
#include <llvm/Support/raw_ostream.h> #include <llvm/Support/raw_ostream.h>
#include <llvm/ExecutionEngine/ExecutionEngine.h>
namespace extra{ namespace extra{
using namespace llvm; 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<unsigned, 8> 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<unsigned,8>");
}
static PyMethodDef extra_methodtable[] = { static PyMethodDef extra_methodtable[] = {
#define method(func) { #func, (PyCFunction)func, METH_VARARGS, NULL } #define method(func) { #func, (PyCFunction)func, METH_VARARGS, NULL }
method( make_raw_ostream_for_printing ), method( make_raw_ostream_for_printing ),
method( make_small_vector_from_types ), method( make_small_vector_from_types ),
method( make_small_vector_from_values ), method( make_small_vector_from_values ),
method( make_small_vector_from_unsigned ),
#undef method #undef method
{ NULL } { NULL }
}; };
@ -139,11 +162,20 @@ PyObject* iplist_to_pylist(iplist &IPL, const char * capsuleName,
className); 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 static
PyObject* Value_use_iterator_to_list(llvm::Value* val) PyObject* Value_use_iterator_to_list(llvm::Value* val)
{ {
return iterator_to_pylist(val->use_begin(), val->use_end(), return iterator_to_pylist(val->use_begin(), val->use_end(),
"llvm::Value", "llvm::User"); "llvm::Value", "llvm::User");
} }
static static
@ -158,4 +190,47 @@ PyObject* Function_getBasicBlockList(llvm::Function* fn)
{ {
return iplist_to_pylist(fn->getBasicBlockList(), "llvm::Value", return iplist_to_pylist(fn->getBasicBlockList(), "llvm::Value",
"llvm::BasicBlock"); "llvm::BasicBlock");
} }
/*
* 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;
}

19
newbinding/src/CodeGen.py Normal file
View file

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

View file

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

View file

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

View file

@ -0,0 +1,8 @@
from binding import *
from namespace import llvm
from GlobalValue import GlobalValue
@llvm.Class(GlobalValue)
class GlobalVariable:
pass

View file

@ -2,10 +2,16 @@ from binding import *
from namespace import llvm from namespace import llvm
from LLVMContext import LLVMContext from LLVMContext import LLVMContext
from BasicBlock import BasicBlock from BasicBlock import BasicBlock
from Instruction import ReturnInst, CallInst from Instruction import ReturnInst, CallInst, BranchInst, SwitchInst
from SmallVector import SmallVector_Value 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 StringRef import StringRef
from Value import Value from Value import Value, MDNode
from Type import Type, IntegerType
IRBuilder = llvm.Class() IRBuilder = llvm.Class()
@ -24,15 +30,238 @@ class IRBuilder:
CreateRetVoid = Method(ptr(ReturnInst)) CreateRetVoid = Method(ptr(ReturnInst))
CreateRet = Method(ptr(ReturnInst), ptr(Value)) 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)) 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' _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 @CustomPythonMethod
def CreateCall(self, *args): def CreateCall(self, *args):
import extra import extra
args = list(args) args = list(args)
valuelist = args[1] valuelist = args[1]
args[1] = extra.make_small_vector_from_values(*valuelist) 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))

View file

@ -26,9 +26,9 @@ IntrinsicInst = llvm.Class(CallInst)
FCmpInst = llvm.Class(CmpInst) FCmpInst = llvm.Class(CmpInst)
ICmpInst = llvm.Class(CmpInst) ICmpInst = llvm.Class(CmpInst)
BranchInst = llvm.Class(TerminatorInst) BranchInst = llvm.Class(TerminatorInst)
IndirectBrInst = llvm.Class(TerminatorInst) IndirectBrInst = llvm.Class(TerminatorInst)
InvokeInst = llvm.Class(TerminatorInst)
ResumeInst = llvm.Class(TerminatorInst) ResumeInst = llvm.Class(TerminatorInst)
ReturnInst = llvm.Class(TerminatorInst) ReturnInst = llvm.Class(TerminatorInst)
SwitchInst = llvm.Class(TerminatorInst) SwitchInst = llvm.Class(TerminatorInst)
@ -56,14 +56,14 @@ FPTruncInst = llvm.Class(CastInst)
class Instruction: class Instruction:
pass pass
@AtomicCmpXchgInst @AtomicCmpXchgInst
class AtomicCmpXchgInst: class AtomicCmpXchgInst:
pass pass
@AtomicRMWInst @AtomicRMWInst
class AtomicRMWInst: class AtomicRMWInst:
pass BinOp = Enum('Xchg', 'Add', 'Sub', 'And', 'Nand', 'Or', 'Xor', 'Max', 'Min',
'UMax', 'UMin', 'FIRST_BINOP', 'LAST_BINOP', 'BAD_BINOP')
@BinaryOperator @BinaryOperator
class BinaryOperator: class BinaryOperator:
@ -75,7 +75,17 @@ class CallInst:
@CmpInst @CmpInst
class 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 @ExtractElementInst
class ExtractElementInst: class ExtractElementInst:
@ -146,11 +156,14 @@ class ICmpInst:
class BranchInst: class BranchInst:
pass pass
@IndirectBrInst @IndirectBrInst
class IndirectBrInst: class IndirectBrInst:
pass pass
@InvokeInst
class InvokeInst:
pass
@ResumeInst @ResumeInst
class ResumeInst: class ResumeInst:
pass pass
@ -228,3 +241,12 @@ class FPToUIInst:
@FPTruncInst @FPTruncInst
class FPTruncInst: class FPTruncInst:
pass pass
AtomicOrdering = llvm.Enum('AtomicOrdering',
'NotAtomic', 'Unordered', 'Monotonic', 'Acquire',
'Release', 'AcquireRelease',
'SequentiallyConsistent')
SynchronizationScope = llvm.Enum('SynchronizationScope',
'SingleThread', 'CrossThread')

View file

@ -0,0 +1,7 @@
from binding import *
from namespace import llvm
@llvm.Class()
class JITMemoryManager:
pass

View file

@ -0,0 +1,7 @@
from binding import *
from namespace import llvm
from Value import MDNode
@MDNode
class MDNode:
pass

View file

@ -36,7 +36,8 @@ class Module:
appendModuleInlineAsm = Method(Void, cast(str, StringRef)) appendModuleInlineAsm = Method(Void, cast(str, StringRef))
# Function Accessors # Function Accessors
getOrInsertFunction = Method(ptr(Constant), cast(str, StringRef), ptr(FunctionType)) getOrInsertFunction = Method(ptr(Constant), cast(str, StringRef),
ptr(FunctionType))
# Utilities # Utilities
dump = Method(Void) dump = Method(Void)

View file

@ -11,3 +11,7 @@ class SmallVector_Value:
_realname_ = 'SmallVector<llvm::Value*,8>' _realname_ = 'SmallVector<llvm::Value*,8>'
delete = Destructor() delete = Destructor()
@llvm.Class()
class SmallVector_Unsigned:
_realname_ = 'SmallVector<unsigned,8>'
delete = Destructor()

View file

@ -0,0 +1,8 @@
from binding import *
from namespace import llvm
llvm.includes.add('llvm/Support/TargetSelect.h')
llvm.Function('InitializeNativeTarget')
#llvm.Function('InitializeAllTargets')

View file

@ -6,6 +6,7 @@ from raw_ostream import raw_ostream
Type = llvm.Class() Type = llvm.Class()
IntegerType = llvm.Class(Type) IntegerType = llvm.Class(Type)
CompositeType = llvm.Class(Type) CompositeType = llvm.Class(Type)
StructType = llvm.Class(CompositeType)
SequentialType = llvm.Class(CompositeType) SequentialType = llvm.Class(CompositeType)
PointerType = llvm.Class(SequentialType) PointerType = llvm.Class(SequentialType)
@ -113,3 +114,6 @@ class SequentialType:
class PointerType: class PointerType:
pass pass
@StructType
class StructType:
pass

View file

@ -9,6 +9,7 @@ from StringRef import StringRef
Value = llvm.Class() Value = llvm.Class()
# forward declarations # forward declarations
Argument = llvm.Class(Value) Argument = llvm.Class(Value)
MDNode = llvm.Class(Value)
User = llvm.Class(Value) User = llvm.Class(Value)
BasicBlock = llvm.Class(Value) BasicBlock = llvm.Class(Value)
Constant = llvm.Class(User) Constant = llvm.Class(User)

View file

@ -1,7 +1,11 @@
import api import api
import extra import extra
import _capsule import _capsule
from StringIO import StringIO
api.capsule.set_debug(True) api.capsule.set_debug(True)
api.InitializeNativeTarget()
context = api.getGlobalContext() context = api.getGlobalContext()
@ -71,3 +75,13 @@ builder.CreateRet(ret)
print fn 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))))