67 lines
2 KiB
Python
67 lines
2 KiB
Python
'''
|
|
This is mostly a convenience module for testing with ctypes.
|
|
'''
|
|
|
|
from llvm.core import Type, Module
|
|
import llvm.ee as le
|
|
import ctypes as ct
|
|
|
|
MAP_CTYPES = {
|
|
'void' : None,
|
|
'bool' : ct.c_bool,
|
|
'char' : ct.c_char,
|
|
'uchar' : ct.c_ubyte,
|
|
'short' : ct.c_short,
|
|
'ushort' : ct.c_ushort,
|
|
'int' : ct.c_int,
|
|
'uint' : ct.c_uint,
|
|
'long' : ct.c_long,
|
|
'ulong' : ct.c_ulong,
|
|
|
|
'int8' : ct.c_int8,
|
|
'uint8' : ct.c_uint8,
|
|
'int16' : ct.c_int16,
|
|
'uint16' : ct.c_uint16,
|
|
'int32' : ct.c_int32,
|
|
'uint32' : ct.c_uint32,
|
|
'int64' : ct.c_int64,
|
|
'uint64' : ct.c_uint64,
|
|
|
|
'float' : ct.c_float,
|
|
'double' : ct.c_double,
|
|
'longdouble' : ct.c_longdouble,
|
|
}
|
|
|
|
class CExecutor(object):
|
|
'''a convenient class for creating ctype functions from LLVM modules
|
|
'''
|
|
def __init__(self, mod_or_engine):
|
|
if isinstance(mod_or_engine, Module):
|
|
self.engine = le.EngineBuilder.new(mod_or_engine).opt(3).create()
|
|
else:
|
|
self.engine = mod_or_engine
|
|
|
|
def get_ctype_function(self, fn, *typeinfo):
|
|
'''create a ctype function from a LLVM function
|
|
|
|
typeinfo : string of types (see `MAP_CTYPES`) or
|
|
list of ctypes datatype.
|
|
First value is the return type.
|
|
A function that takes no argument and return nothing
|
|
should use `"void"` or `None`.
|
|
'''
|
|
if len(typeinfo)==1 and isinstance(typeinfo[0], str):
|
|
types = [ MAP_CTYPES[s.strip()] for s in typeinfo[0].split(',') ]
|
|
if not types:
|
|
retty = None
|
|
argtys = []
|
|
else:
|
|
retty = types[0]
|
|
argtys = types[1:]
|
|
else:
|
|
retty = typeinfo[0]
|
|
argtys = typeinfo[1:]
|
|
prototype = ct.CFUNCTYPE(retty, *argtys)
|
|
fnptr = self.engine.get_pointer_to_function(fn)
|
|
return prototype(fnptr)
|
|
|