Update StructType to LLVM 3.x (incomplete).
Bring back StructType.elements.
This commit is contained in:
parent
c68c5b0aac
commit
b71d22b570
6 changed files with 444 additions and 300 deletions
14
llvm/_core.c
14
llvm/_core.c
|
|
@ -298,15 +298,19 @@ _wLLVMGetFunctionTypeParams(PyObject *self, PyObject *args)
|
|||
/*===-- Struct types -----------------------------------------------------===*/
|
||||
|
||||
_wrap_listint2obj(LLVMStructType, LLVMTypeRef, LLVMTypeRef)
|
||||
_wrap_str2obj(LLVMStructTypeIdentified, LLVMTypeRef)
|
||||
_wrap_objlistint2none(LLVMSetStructBody, LLVMTypeRef, LLVMTypeRef)
|
||||
_wrap_obj2obj(LLVMCountStructElementTypes, LLVMTypeRef, int)
|
||||
_wrap_obj2str(LLVMGetStructName, LLVMTypeRef)
|
||||
_wrap_objstr2none(LLVMSetStructName, LLVMTypeRef)
|
||||
|
||||
|
||||
/*
|
||||
static PyObject *
|
||||
_wLLVMGetStructElementTypes(PyObject *self, PyObject *args)
|
||||
{
|
||||
return obj2arr(self, args, LLVMCountStructElementTypes, LLVMGetStructElementTypes);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
_wrap_obj2obj(LLVMIsPackedStruct, LLVMTypeRef, int)
|
||||
|
||||
|
|
@ -1370,9 +1374,13 @@ static PyMethodDef core_methods[] = {
|
|||
|
||||
/* Struct types */
|
||||
_method( LLVMStructType )
|
||||
_method( LLVMStructTypeIdentified )
|
||||
_method( LLVMSetStructBody )
|
||||
_method( LLVMCountStructElementTypes )
|
||||
//_method( LLVMGetStructElementTypes )
|
||||
_method( LLVMGetStructElementTypes )
|
||||
_method( LLVMIsPackedStruct )
|
||||
_method( LLVMGetStructName )
|
||||
_method( LLVMSetStructName )
|
||||
|
||||
/* Array types */
|
||||
_method( LLVMArrayType )
|
||||
|
|
|
|||
49
llvm/core.py
49
llvm/core.py
|
|
@ -585,24 +585,42 @@ class Type(object):
|
|||
var_arg), TYPE_FUNCTION)
|
||||
|
||||
@staticmethod
|
||||
def struct(element_tys): # not packed
|
||||
def struct(element_tys, name=''): # not packed
|
||||
"""Create a (unpacked) structure type.
|
||||
|
||||
Creates a structure type with elements of types as given in the
|
||||
iterable `element_tys'. This method creates a unpacked
|
||||
structure. For a packed one, use the packed_struct() method."""
|
||||
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)
|
||||
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
|
||||
def packed_struct(element_tys):
|
||||
def packed_struct(element_tys, name=''):
|
||||
"""Create a (packed) structure type.
|
||||
|
||||
Creates a structure type with elements of types as given in the
|
||||
iterable `element_tys'. This method creates a packed
|
||||
structure. For an unpacked one, use the struct() method."""
|
||||
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)
|
||||
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
|
||||
def array(element_ty, count):
|
||||
|
|
@ -725,18 +743,25 @@ class StructType(Type):
|
|||
Same as len(obj.elements), but faster."""
|
||||
return _core.LLVMCountStructElementTypes(self.ptr)
|
||||
|
||||
#@property
|
||||
#def elements(self):
|
||||
# """An iterable that yieldsd Type objects, representing the types of the
|
||||
# elements (members) of the structure, in order."""
|
||||
# pp = _core.LLVMGetStructElementTypes(self.ptr)
|
||||
# return [ _make_type(p, _core.LLVMGetTypeKind(p)) for p in pp ]
|
||||
@property
|
||||
def elements(self):
|
||||
"""An iterable that yieldsd Type objects, representing the types of the
|
||||
elements (members) of the structure, in order."""
|
||||
pp = _core.LLVMGetStructElementTypes(self.ptr)
|
||||
return [ _make_type(p, _core.LLVMGetTypeKind(p)) for p in pp ]
|
||||
|
||||
@property
|
||||
def packed(self):
|
||||
"""True if the structure is packed, False otherwise."""
|
||||
return _core.LLVMIsPackedStruct(self.ptr) != 0
|
||||
|
||||
def _set_name(self, name):
|
||||
_core.LLVMSetStructName(self.ptr, name)
|
||||
|
||||
def _get_name(self):
|
||||
return _core.LLVMGetStructName(self.ptr)
|
||||
|
||||
name = property(_get_name, _set_name)
|
||||
|
||||
class ArrayType(Type):
|
||||
"""Represents an array type."""
|
||||
|
|
|
|||
|
|
@ -90,6 +90,25 @@ char *do_print(W obj)
|
|||
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)
|
||||
{
|
||||
return strdup(llvm::unwrap(module)->getModuleIdentifier().c_str());
|
||||
|
|
|
|||
15
llvm/extra.h
15
llvm/extra.h
|
|
@ -41,6 +41,21 @@
|
|||
extern "C" {
|
||||
#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()
|
||||
|
|
|
|||
58
llvm/wrap.h
58
llvm/wrap.h
|
|
@ -868,6 +868,35 @@ _w ## func (PyObject *self, PyObject *args) \
|
|||
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
|
||||
* outtype func(intype1 arg1, int arg2, intype3 *arg3v, unsigned arg3n)
|
||||
|
|
@ -1706,6 +1735,35 @@ _w ## func (PyObject *self, PyObject *args) \
|
|||
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
|
||||
* outtype func(intype1 arg1, int arg2, intype3 *arg3v, unsigned arg3n)
|
||||
|
|
|
|||
57
test/test.py
57
test/test.py
|
|
@ -3,17 +3,17 @@
|
|||
# watch out for uncollected objects
|
||||
import gc
|
||||
|
||||
import unittest, sys
|
||||
import unittest, sys, logging
|
||||
|
||||
from llvm import *
|
||||
from llvm.core import *
|
||||
|
||||
|
||||
class TestModule(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
pass
|
||||
|
||||
|
||||
def testdata_layout(self):
|
||||
"""Data layout property."""
|
||||
m = Module.new("test2.1")
|
||||
|
|
@ -33,23 +33,39 @@ class TestModule(unittest.TestCase):
|
|||
reqd = '; ModuleID = \'test3.1\'\ntarget triple = "some_value"\n'
|
||||
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):
|
||||
"""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)
|
||||
struct = Type.struct([Type.int(), Type.int()], name="struct.two.int")
|
||||
self.assertEqual(struct.name, "struct.two.int")
|
||||
got_struct = m.get_type_named(struct.name)
|
||||
self.assertEqual(got_struct.name, struct.name)
|
||||
|
||||
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):
|
||||
"""Global variables."""
|
||||
|
|
@ -65,11 +81,14 @@ def main():
|
|||
gc.set_debug(gc.DEBUG_LEAK)
|
||||
|
||||
# run tests
|
||||
unittest.main()
|
||||
unittest.main(exit=False) # set exit to False so that it will return.
|
||||
|
||||
# done
|
||||
if gc.garbage:
|
||||
print("garbage = ", gc.garbage)
|
||||
for it in gc.garbage:
|
||||
logging.debug('garbage = %s', it)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
||||
|
||||
|
||||
main()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue