Update StructType to LLVM 3.x (incomplete).

Bring back StructType.elements.
This commit is contained in:
Siu Kwan Lam 2012-07-22 00:00:04 -07:00
commit b71d22b570
6 changed files with 444 additions and 300 deletions

View file

@ -298,15 +298,19 @@ _wLLVMGetFunctionTypeParams(PyObject *self, PyObject *args)
/*===-- Struct types -----------------------------------------------------===*/ /*===-- Struct types -----------------------------------------------------===*/
_wrap_listint2obj(LLVMStructType, LLVMTypeRef, LLVMTypeRef) _wrap_listint2obj(LLVMStructType, LLVMTypeRef, LLVMTypeRef)
_wrap_str2obj(LLVMStructTypeIdentified, LLVMTypeRef)
_wrap_objlistint2none(LLVMSetStructBody, LLVMTypeRef, LLVMTypeRef)
_wrap_obj2obj(LLVMCountStructElementTypes, LLVMTypeRef, int) _wrap_obj2obj(LLVMCountStructElementTypes, LLVMTypeRef, int)
_wrap_obj2str(LLVMGetStructName, LLVMTypeRef)
_wrap_objstr2none(LLVMSetStructName, LLVMTypeRef)
/*
static PyObject * static PyObject *
_wLLVMGetStructElementTypes(PyObject *self, PyObject *args) _wLLVMGetStructElementTypes(PyObject *self, PyObject *args)
{ {
return obj2arr(self, args, LLVMCountStructElementTypes, LLVMGetStructElementTypes); return obj2arr(self, args, LLVMCountStructElementTypes, LLVMGetStructElementTypes);
} }
*/
_wrap_obj2obj(LLVMIsPackedStruct, LLVMTypeRef, int) _wrap_obj2obj(LLVMIsPackedStruct, LLVMTypeRef, int)
@ -1370,9 +1374,13 @@ static PyMethodDef core_methods[] = {
/* Struct types */ /* Struct types */
_method( LLVMStructType ) _method( LLVMStructType )
_method( LLVMStructTypeIdentified )
_method( LLVMSetStructBody )
_method( LLVMCountStructElementTypes ) _method( LLVMCountStructElementTypes )
//_method( LLVMGetStructElementTypes ) _method( LLVMGetStructElementTypes )
_method( LLVMIsPackedStruct ) _method( LLVMIsPackedStruct )
_method( LLVMGetStructName )
_method( LLVMSetStructName )
/* Array types */ /* Array types */
_method( LLVMArrayType ) _method( LLVMArrayType )

View file

@ -585,24 +585,42 @@ class Type(object):
var_arg), TYPE_FUNCTION) var_arg), TYPE_FUNCTION)
@staticmethod @staticmethod
def struct(element_tys): # not packed def struct(element_tys, name=''): # not packed
"""Create a (unpacked) structure type. """Create a (unpacked) structure type.
Creates a structure type with elements of types as given in the Creates a structure type with elements of types as given in the
iterable `element_tys'. This method creates a unpacked iterable `element_tys'. This method creates a unpacked
structure. For a packed one, use the packed_struct() method.""" structure. For a packed one, use the packed_struct() method.
If name is not '', creates a identified type;
otherwise, creates a literal type."""
elems = unpack_types(element_tys) elems = unpack_types(element_tys)
return _make_type(_core.LLVMStructType(elems, 0), TYPE_STRUCT)
if name: # create Identified StructType
objptr = _core.LLVMStructTypeIdentified(name)
_core.LLVMSetStructBody(objptr, elems, 0)
else: # create Literal StructType
objptr = _core.LLVMStructType(elems, 0)
return _make_type(objptr, TYPE_STRUCT)
@staticmethod @staticmethod
def packed_struct(element_tys): def packed_struct(element_tys, name=''):
"""Create a (packed) structure type. """Create a (packed) structure type.
Creates a structure type with elements of types as given in the Creates a structure type with elements of types as given in the
iterable `element_tys'. This method creates a packed iterable `element_tys'. This method creates a packed
structure. For an unpacked one, use the struct() method.""" structure. For an unpacked one, use the struct() method.
If name is not '', creates a identified type;
otherwise, creates a literal type."""
elems = unpack_types(element_tys) elems = unpack_types(element_tys)
return _make_type(_core.LLVMStructType(elems, 1), TYPE_STRUCT)
if name: # create Identified StructType
objptr = _core.LLVMStructTypeIdentified(name)
_core.LLVMSetStructBody(objptr, elems, 0)
else: # create Literal StructType
objptr = _core.LLVMStructType(elems, 1)
@staticmethod @staticmethod
def array(element_ty, count): def array(element_ty, count):
@ -725,18 +743,25 @@ class StructType(Type):
Same as len(obj.elements), but faster.""" Same as len(obj.elements), but faster."""
return _core.LLVMCountStructElementTypes(self.ptr) return _core.LLVMCountStructElementTypes(self.ptr)
#@property @property
#def elements(self): def elements(self):
# """An iterable that yieldsd Type objects, representing the types of the """An iterable that yieldsd Type objects, representing the types of the
# elements (members) of the structure, in order.""" elements (members) of the structure, in order."""
# pp = _core.LLVMGetStructElementTypes(self.ptr) pp = _core.LLVMGetStructElementTypes(self.ptr)
# return [ _make_type(p, _core.LLVMGetTypeKind(p)) for p in pp ] return [ _make_type(p, _core.LLVMGetTypeKind(p)) for p in pp ]
@property @property
def packed(self): def packed(self):
"""True if the structure is packed, False otherwise.""" """True if the structure is packed, False otherwise."""
return _core.LLVMIsPackedStruct(self.ptr) != 0 return _core.LLVMIsPackedStruct(self.ptr) != 0
def _set_name(self, name):
_core.LLVMSetStructName(self.ptr, name)
def _get_name(self):
return _core.LLVMGetStructName(self.ptr)
name = property(_get_name, _set_name)
class ArrayType(Type): class ArrayType(Type):
"""Represents an array type.""" """Represents an array type."""

View file

@ -90,6 +90,25 @@ char *do_print(W obj)
return strdup(buf.str().c_str()); return strdup(buf.str().c_str());
} }
LLVMTypeRef LLVMStructTypeIdentified(const char * name)
{
using namespace llvm;
return wrap(StructType::create(getGlobalContext(), name));
}
void LLVMSetStructBody(LLVMTypeRef type, LLVMTypeRef* elemtys, unsigned elemct, int is_packed)
{
using namespace llvm;
ArrayRef<Type*> elemtys_aryref(unwrap(elemtys), elemct);
unwrap<StructType>(type)->setBody(elemtys_aryref, is_packed);
}
void LLVMSetStructName(LLVMTypeRef type, const char * name)
{
llvm::StructType *st = llvm::unwrap<llvm::StructType>(type);
st->setName(name);
}
char *LLVMGetModuleIdentifier(LLVMModuleRef module) char *LLVMGetModuleIdentifier(LLVMModuleRef module)
{ {
return strdup(llvm::unwrap(module)->getModuleIdentifier().c_str()); return strdup(llvm::unwrap(module)->getModuleIdentifier().c_str());

View file

@ -41,6 +41,21 @@
extern "C" { extern "C" {
#endif #endif
/*
* Wraps StructType::create()
*/
LLVMTypeRef LLVMStructTypeIdentified(const char * name);
/*
* StructType::setBody()
*/
void LLVMSetStructBody(LLVMTypeRef type, LLVMTypeRef* elemtys, unsigned elemct, int is_packed);
/*
* Wraps llvm::StructType::setName()
*/
void LLVMSetStructName(LLVMTypeRef type, const char * name);
/* /*
* Wraps llvm::Module::getModuleIdentifier() * Wraps llvm::Module::getModuleIdentifier()

View file

@ -868,6 +868,35 @@ _w ## func (PyObject *self, PyObject *args) \
return ctor_ ## outtype (ret); \ return ctor_ ## outtype (ret); \
} }
/**
* Wrap LLVM functions of the type
* void func(intype1 arg1, intype2 *arg2v, unsigned arg2n, int arg3)
* where arg2v is an array of intype2 elements, arg2n in length.
*/
#define _wrap_objlistint2none(func, intype1, intype2) \
static PyObject * \
_w ## func (PyObject *self, PyObject *args) \
{ \
PyObject *obj1, *obj2; \
intype1 arg1; \
intype2 *arg2v; \
unsigned arg2n; \
int arg3; \
\
if (!PyArg_ParseTuple(args, "OOi", &obj1, &obj2, &arg3)) \
return NULL; \
\
arg1 = ( intype1 ) PyCapsule_GetPointer(obj1, NULL); \
arg2n = (unsigned) PyList_Size(obj2); \
if (!(arg2v = ( intype2 *)make_array_from_list(obj2, arg2n)))\
return PyErr_NoMemory(); \
\
func (arg1, arg2v, arg2n, arg3); \
free(arg2v); \
Py_RETURN_NONE; \
}
/** /**
* Wrap LLVM functions of the type * Wrap LLVM functions of the type
* outtype func(intype1 arg1, int arg2, intype3 *arg3v, unsigned arg3n) * outtype func(intype1 arg1, int arg2, intype3 *arg3v, unsigned arg3n)
@ -1706,6 +1735,35 @@ _w ## func (PyObject *self, PyObject *args) \
return ctor_ ## outtype (ret); \ return ctor_ ## outtype (ret); \
} }
/**
* Wrap LLVM functions of the type
* void func(intype1 arg1, intype2 *arg2v, unsigned arg2n, int arg3)
* where arg2v is an array of intype2 elements, arg2n in length.
*/
#define _wrap_objlistint2none(func, intype1, intype2) \
static PyObject * \
_w ## func (PyObject *self, PyObject *args) \
{ \
PyObject *obj1, *obj2; \
intype1 arg1; \
intype2 *arg2v; \
unsigned arg2n; \
int arg3; \
\
if (!PyArg_ParseTuple(args, "OOi", &obj1, &obj2, &arg3)) \
return NULL; \
\
arg1 = ( intype1 ) PyCObject_AsVoidPtr(obj1); \
arg2n = (unsigned) PyList_Size(obj2); \
if (!(arg2v = ( intype2 *)make_array_from_list(obj2, arg2n))) \
return PyErr_NoMemory(); \
\
func (arg1, arg2v, arg2n, arg3); \
free(arg2v); \
Py_RETURN_NONE; \
}
/** /**
* Wrap LLVM functions of the type * Wrap LLVM functions of the type
* outtype func(intype1 arg1, int arg2, intype3 *arg3v, unsigned arg3n) * outtype func(intype1 arg1, int arg2, intype3 *arg3v, unsigned arg3n)

View file

@ -3,17 +3,17 @@
# watch out for uncollected objects # watch out for uncollected objects
import gc import gc
import unittest, sys import unittest, sys, logging
from llvm import * from llvm import *
from llvm.core import * from llvm.core import *
class TestModule(unittest.TestCase): class TestModule(unittest.TestCase):
def setUp(self): def setUp(self):
pass pass
def testdata_layout(self): def testdata_layout(self):
"""Data layout property.""" """Data layout property."""
m = Module.new("test2.1") m = Module.new("test2.1")
@ -33,23 +33,39 @@ class TestModule(unittest.TestCase):
reqd = '; ModuleID = \'test3.1\'\ntarget triple = "some_value"\n' reqd = '; ModuleID = \'test3.1\'\ntarget triple = "some_value"\n'
self.assertEqual(str(m), reqd) self.assertEqual(str(m), reqd)
# Type system is rewritten in LLVM 3.0.
# Only named StructType is supported.
# See http://blog.llvm.org/2011/11/llvm-30-type-system-rewrite.html
#
# def testtype_name(self):
# """Type names."""
# m = Module.new("test4.1")
# r = m.add_type_name("typename41", Type.int())
# self.assertEqual(r, 0)
# r = m.add_type_name("typename41", Type.int())
# self.assertEqual(r, 1)
# reqd = "; ModuleID = 'test4.1'\n\n%typename41 = type i32\n"
# self.assertEqual(str(m), reqd)
# r = m.delete_type_name("typename41")
# reqd = "; ModuleID = 'test4.1'\n"
# self.assertEqual(str(m), reqd)
# r = m.delete_type_name("no such name") # nothing should happen
# reqd = "; ModuleID = 'test4.1'\n"
# self.assertEqual(str(m), reqd)
def testtype_name(self): def testtype_name(self):
"""Type names."""
m = Module.new("test4.1") m = Module.new("test4.1")
r = m.add_type_name("typename41", Type.int()) struct = Type.struct([Type.int(), Type.int()], name="struct.two.int")
self.assertEqual(r, 0) self.assertEqual(struct.name, "struct.two.int")
r = m.add_type_name("typename41", Type.int()) got_struct = m.get_type_named(struct.name)
self.assertEqual(r, 1) self.assertEqual(got_struct.name, struct.name)
reqd = "; ModuleID = 'test4.1'\n\n%typename41 = type i32\n"
self.assertEqual(str(m), reqd)
r = m.delete_type_name("typename41")
reqd = "; ModuleID = 'test4.1'\n"
self.assertEqual(str(m), reqd)
r = m.delete_type_name("no such name") # nothing should happen
reqd = "; ModuleID = 'test4.1'\n"
self.assertEqual(str(m), reqd)
self.assertEqual(got_struct.element_count, struct.element_count)
self.assertEqual(len(struct.elements), struct.element_count)
self.assertEqual(struct.elements, got_struct.elements)
for elty in struct.elements:
self.assertEqual(elty, Type.int())
def testglobal_variable(self): def testglobal_variable(self):
"""Global variables.""" """Global variables."""
@ -65,11 +81,14 @@ def main():
gc.set_debug(gc.DEBUG_LEAK) gc.set_debug(gc.DEBUG_LEAK)
# run tests # run tests
unittest.main() unittest.main(exit=False) # set exit to False so that it will return.
# done # done
if gc.garbage: for it in gc.garbage:
print("garbage = ", gc.garbage) logging.debug('garbage = %s', it)
if __name__ == '__main__':
main()
main()