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 -----------------------------------------------------===*/
|
/*===-- 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 )
|
||||||
|
|
|
||||||
49
llvm/core.py
49
llvm/core.py
|
|
@ -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."""
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
|
|
|
||||||
15
llvm/extra.h
15
llvm/extra.h
|
|
@ -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()
|
||||||
|
|
|
||||||
58
llvm/wrap.h
58
llvm/wrap.h
|
|
@ -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)
|
||||||
|
|
|
||||||
57
test/test.py
57
test/test.py
|
|
@ -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()
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue