Fix a lots of bugs in the newbinding to pass all the tests.

NOTE: debug info has not been implemented yet.
This commit is contained in:
Siu Kwan Lam 2013-02-13 15:09:26 -06:00
commit a09394cacd
32 changed files with 2419 additions and 546 deletions

View file

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

193
llvm/_version.py Normal file
View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

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

51
llvm/tbaa.py Normal file
View file

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

1243
llvm/test_llvmpy.py Normal file

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

View file

@ -137,12 +137,19 @@ PyObject* make_small_vector_from_unsigned(PyObject* self, PyObject* args)
return pycapsule_new(SV, "llvm::SmallVector<unsigned,8>");
}
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<class VecTy>
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<ElemTy>::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<ElemTy*>(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<Type*> elements;
extract<Type>::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<Constant*> vec_consts;
bool ok = extract<Constant>::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<llvm::Value*> vals;
bool ok = extract<llvm::Value>::from_py_sequence(vals, Vals, "llvm::Value");
bool accept_null = true;
bool ok = extract<llvm::Value>::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

View file

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

View file

@ -20,7 +20,7 @@ class Attributes:
delete = Destructor()
get = Method(Attributes, ref(LLVMContext), ref(AttrBuilder))
get = StaticMethod(Attributes, ref(LLVMContext), ref(AttrBuilder))
@AttrBuilder

View file

@ -21,4 +21,6 @@ class BasicBlock:
removePredecessor = Method(Void, ptr(BasicBlock), cast(bool, Bool))
removePredecessor |= Method(Void, ptr(BasicBlock))
getInstList = CustomMethod('BasicBlock_getInstList', PyObjectPtr)
getInstList = CustomMethod('BasicBlock_getInstList', PyObjectPtr)
eraseFromParent = Method()

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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 <Type*> elements
cast(bool, Bool), # is packed
).require_only(2)
isValidElementType = StaticMethod(cast(Bool, bool), ptr(Type))

View file

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

View file

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

16
test/malloc.py Normal file
View file

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

View file

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

View file

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