Compare commits
2 commits
master
...
improvefun
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ca192850ee | ||
|
|
7a77be01cc |
7 changed files with 176 additions and 1 deletions
2
llvm_array/__init__.py
Normal file
2
llvm_array/__init__.py
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
from __future__ import absolute_imports
|
||||
from .array.py import *
|
||||
144
llvm_array/array.py
Normal file
144
llvm_array/array.py
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
# This should be moved to llvmpy
|
||||
#
|
||||
# There are different array kinds parameterized by eltype and nd
|
||||
#
|
||||
# Contiguous or Fortran
|
||||
# struct {
|
||||
# eltype *data;
|
||||
# intp shape[nd];
|
||||
# } contiguous_array(eltype, nd)
|
||||
#
|
||||
# struct {
|
||||
# eltype *data;
|
||||
# diminfo shape[nd];
|
||||
# } strided_array(eltype, nd)
|
||||
#
|
||||
# struct {
|
||||
# eltype *data;
|
||||
# intp shape[nd];
|
||||
# intp stride[nd];
|
||||
# } strided_soa_array(eltype, nd)
|
||||
#
|
||||
# struct {
|
||||
# intp dim;
|
||||
# intp stride;
|
||||
#} diminfo
|
||||
#
|
||||
|
||||
import llvm.core as lc
|
||||
from llvm.core import Type
|
||||
import llvm_cbuilder.shortnames as C
|
||||
|
||||
CONTIGUOUS = 1 << 8
|
||||
STRIDED = CONTIGUOUS + 1
|
||||
STRIDED_SOA = CONTIGUOUS + 2
|
||||
|
||||
array_kinds = (CONTIGUOUS, STRIDED, STRIDED_SOA)
|
||||
|
||||
void_type = C.void
|
||||
int_type = C.int
|
||||
char_type = C.char
|
||||
int16_type = C.int16
|
||||
intp_type = C.intp
|
||||
|
||||
diminfo_type = Type.struct([intp_type, # shape
|
||||
intp_type # stride
|
||||
], name='diminfo')
|
||||
|
||||
# This is the way we define LLVM arrays.
|
||||
def cont_array_type(nd, el_type=char_type, name=''):
|
||||
terms = [Type.pointer(el_type), # data
|
||||
Type.array(intp_type, nd) # shape
|
||||
]
|
||||
return Type.struct(terms, name=name)
|
||||
|
||||
def strided_array_type(nd, el_type=char_type, name=''):
|
||||
terms = [Type.pointer(el_type), # data
|
||||
Type.array(diminfo_type, nd) # diminfo
|
||||
]
|
||||
return Type.struct(terms, name=name)
|
||||
|
||||
def strided_soa_type(nd, el_type=char_type, name=''):
|
||||
terms = [Type.pointer(el_type), # data
|
||||
Type.array(intp_type, nd), # shape[nd]
|
||||
Type.array(intp_type, nd) # strides[nd]
|
||||
]
|
||||
return Type.struct(terms, name=name)
|
||||
|
||||
def check_array(arrtyp):
|
||||
if not isinstance(arrtyp, lc.StructType):
|
||||
return None
|
||||
if arrtyp.element_count not in [2, 3]:
|
||||
return None
|
||||
if not isinstance(arrtyp.elements[0], lc.PointerType) or \
|
||||
not isinstance(arrtyp.elements[1], lc.ArrayType):
|
||||
return None
|
||||
|
||||
data_type = arrtyp.elements[0].pointee
|
||||
s1 = arrtyp.elements[1]
|
||||
nd = s1.count
|
||||
|
||||
if arrtyp.element_count == 3:
|
||||
if not isinstance(arrtyp.elements[2], lc.ArrayType):
|
||||
return None
|
||||
s2 = arrtyp.elements[2]
|
||||
if s1.element != intp_type or s2.element != intp_type:
|
||||
return None
|
||||
if s1.count != s2.count:
|
||||
return None
|
||||
return STRIDED_SOA, nd, data_type
|
||||
|
||||
if s1.element == diminfo_type:
|
||||
return STRIDED, nd, data_type
|
||||
elif s1.element == intp_type:
|
||||
return CONTIGUOUS, nd, data_type
|
||||
else:
|
||||
return None
|
||||
|
||||
def is_cont_array(arrtyp):
|
||||
if not isinstance(arrtyp, lc.StructType):
|
||||
return False
|
||||
if arrtyp.element_count != 2 or \
|
||||
not isinstance(arrtyp.elements[0], lc.PointerType) or \
|
||||
not isinstance(arrtyp.elements[1], lc.ArrayType):
|
||||
return False
|
||||
if arrtyp.elements[1].element != intp_type:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_strided_array(arrtyp, kind=diminfo_type):
|
||||
if not isinstance(arrtyp, lc.StructType):
|
||||
return False
|
||||
if arrtyp.element_count != 2 or \
|
||||
not isinstance(arrtyp.elements[0], lc.PointerType) or \
|
||||
not isinstance(arrtyp.elements[1], lc.ArrayType):
|
||||
return False
|
||||
if arrtyp.elements[1].element != kind:
|
||||
return False
|
||||
return True
|
||||
|
||||
def is_strided_soa_array(arrtyp):
|
||||
if not isinstance(arrtyp, lc.StructType):
|
||||
return False
|
||||
if arrtyp.element_count != 3 or \
|
||||
not isinstance(arrtyp.elements[0], lc.PointerType) or \
|
||||
not isinstance(arrtyp.elements[1], lc.ArrayType) or \
|
||||
not isinstance(arrtyp.elements[2], lc.ArrayType):
|
||||
return False
|
||||
s1, s2 = arrtyp.elements[1:]
|
||||
if s1.element != intp_type or s2.element != intp_type:
|
||||
return False
|
||||
if s1.count != s2.count:
|
||||
return False
|
||||
return True
|
||||
|
||||
def test():
|
||||
arr = cont_array_type(5)
|
||||
assert check_array(arr) == (CONTIGUOUS, 5, char_type)
|
||||
arr = strided_array_type(4)
|
||||
assert check_array(arr) == (STRIDED, 4, char_type)
|
||||
arr = strided_soa_type(3)
|
||||
assert check_array(arr) == (STRIDED_SOA, 3, char_type)
|
||||
|
||||
if __name__ == '__main__':
|
||||
test()
|
||||
|
|
@ -3,6 +3,15 @@ from collections import defaultdict
|
|||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def silent_logger():
|
||||
'''
|
||||
Silent logger for unless we have a error message.
|
||||
'''
|
||||
logger.setLevel(logging.ERROR)
|
||||
|
||||
# comment out the line below to re-enable logging at DEBUG level.
|
||||
silent_logger()
|
||||
|
||||
def set_debug(enabled):
|
||||
'''
|
||||
Side-effect: configure logger with it is not configured.
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ from binding import *
|
|||
from .namespace import llvm
|
||||
from .Value import GlobalValue, Constant, Function, Argument, Value
|
||||
from .BasicBlock import BasicBlock
|
||||
from .ValueSymbolTable import ValueSymbolTable
|
||||
from .Attributes import Attributes
|
||||
from .Type import Type
|
||||
from .DerivedTypes import FunctionType
|
||||
|
|
@ -23,7 +24,7 @@ class Function:
|
|||
getCallingConv = Method(CallingConv.ID)
|
||||
setCallingConv = Method(Void, CallingConv.ID)
|
||||
|
||||
hasGC = Method(cast(bool, Bool))
|
||||
hasGC = Method(cast(Bool, bool))
|
||||
getGC = Method(cast(ConstCharPtr, str))
|
||||
setGC = Method(Void, cast(str, ConstCharPtr))
|
||||
|
||||
|
|
@ -31,6 +32,7 @@ class Function:
|
|||
getArgumentList = CustomMethod('Function_getArgumentList', PyObjectPtr)
|
||||
getBasicBlockList = CustomMethod('Function_getBasicBlockList', PyObjectPtr)
|
||||
getEntryBlock = Method(ref(BasicBlock))
|
||||
getValueSymbolTable = Method(ref(ValueSymbolTable))
|
||||
|
||||
copyAttributesFrom = Method(Void, ptr(GlobalValue))
|
||||
|
||||
|
|
@ -49,6 +51,9 @@ class Function:
|
|||
|
||||
addFnAttr = Method(Void, Attributes.AttrVal)
|
||||
removeFnAttr = Method(Void, ref(Attributes))
|
||||
#hasFnAttribute = Method(cast(Bool, bool), Attributes.AttrVal)
|
||||
|
||||
Create = Method(ptr(Function))
|
||||
|
||||
eraseFromParent = Method()
|
||||
eraseFromParent.disowning = True
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ MDNode = llvm.Class(Value)
|
|||
MDString = llvm.Class(Value)
|
||||
User = llvm.Class(Value)
|
||||
BasicBlock = llvm.Class(Value)
|
||||
ValueSymbolTable = llvm.Class()
|
||||
Constant = llvm.Class(User)
|
||||
GlobalValue = llvm.Class(Constant)
|
||||
Function = llvm.Class(GlobalValue)
|
||||
|
|
|
|||
13
llvmpy/src/ValueSymbolTable.py
Normal file
13
llvmpy/src/ValueSymbolTable.py
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
from binding import *
|
||||
from .Value import ValueSymbolTable, Value
|
||||
from .ADT.StringRef import StringRef
|
||||
|
||||
@ValueSymbolTable
|
||||
class ValueSymbolTable:
|
||||
new = Constructor()
|
||||
delete = Destructor()
|
||||
lookup = Method(ptr(Value), cast(str, StringRef))
|
||||
empty = Method(cast(Bool, bool))
|
||||
size = Method(cast(Unsigned, int))
|
||||
dump = Method(Void)
|
||||
|
||||
1
setup.py
1
setup.py
|
|
@ -180,6 +180,7 @@ setup(
|
|||
packages = ['llvm', 'llvm.workaround',
|
||||
'llvm_cbuilder',
|
||||
'llpython',
|
||||
'llvm_array',
|
||||
'llvmpy.api', 'llvmpy.api.llvm'],
|
||||
py_modules = ['llvmpy',
|
||||
'llvmpy._capsule',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue