Added manual linkage to nobitey when target module isn't the same as the source module.
This commit is contained in:
parent
fe1ba06698
commit
40b84ffd74
5 changed files with 44 additions and 12 deletions
|
|
@ -31,7 +31,8 @@ class BytecodeFlowBuilder (BytecodeIterVisitor):
|
|||
if opname in opcode.opmap)
|
||||
|
||||
def _visit_op (self, i, op, arg, opname, pops, pushes, appends):
|
||||
assert pops is not None
|
||||
assert pops is not None, ('%s not well defined in opcode_util.'
|
||||
'OPCODE_MAP' % opname)
|
||||
if pops:
|
||||
if pops < 0:
|
||||
pops = arg - pops - 1
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import opcode
|
|||
import llvm.core as lc
|
||||
|
||||
import opcode_util
|
||||
|
||||
import bytetype
|
||||
from bytecode_visitor import BytecodeFlowVisitor
|
||||
from byte_flow import BytecodeFlowBuilder
|
||||
|
|
@ -353,25 +352,30 @@ class LLVMTranslator (BytecodeFlowVisitor):
|
|||
def op_CALL_FUNCTION (self, i, op, arg, *args, **kws):
|
||||
fn = args[0]
|
||||
args = args[1:]
|
||||
fn_name = getattr(fn, '__name__', None)
|
||||
if isinstance(fn, lc.Type):
|
||||
if isinstance(fn, lc.FunctionType):
|
||||
ret_val = [self.builder.call(
|
||||
self.llvm_module.get_or_insert_function(fn, fn.__name__),
|
||||
self.llvm_module.get_or_insert_function(fn, fn_name),
|
||||
args)]
|
||||
else:
|
||||
assert len(args) == 1
|
||||
ret_val = [LLVMCaster.build_cast(self.builder, args[0], fn)]
|
||||
elif fn.__name__ in lc.Builder.__dict__:
|
||||
elif fn_name in lc.Builder.__dict__:
|
||||
ret_val = [fn(self.builder, *args)]
|
||||
else:
|
||||
raise NotImplementedError("Don't know how to call %r!" % (fn,))
|
||||
raise NotImplementedError("Don't know how to call %s() (%r)!" %
|
||||
(fn_name, fn))
|
||||
return ret_val
|
||||
|
||||
def op_CALL_FUNCTION_KW (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("LLVMTranslator.op_CALL_FUNCTION_KW")
|
||||
|
||||
def op_CALL_FUNCTION_VAR (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("LLVMTranslator.op_CALL_FUNCTION_VAR")
|
||||
args = list(args)
|
||||
var_args = list(args.pop())
|
||||
args.extend(var_args)
|
||||
return self.op_CALL_FUNCTION(i, op, arg, *args, **kws)
|
||||
|
||||
def op_CALL_FUNCTION_VAR_KW (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("LLVMTranslator.op_CALL_FUNCTION_VAR_KW")
|
||||
|
|
@ -454,7 +458,7 @@ class LLVMTranslator (BytecodeFlowVisitor):
|
|||
|
||||
def op_LOAD_GLOBAL (self, i, op, arg, *args, **kws):
|
||||
ret_val = self.globals[self.code_obj.co_names[arg]]
|
||||
if not hasattr(ret_val, '__name__'):
|
||||
if isinstance(fn, lc.Type) and not hasattr(ret_val, '__name__'):
|
||||
ret_val.__name__ = self.code_obj.co_names[arg]
|
||||
return [ret_val]
|
||||
|
||||
|
|
@ -521,6 +525,14 @@ def translate_function (func, lltype, llvm_module = None, **kws):
|
|||
translator.translate(func, lltype, kws)
|
||||
return translator
|
||||
|
||||
# ______________________________________________________________________
|
||||
|
||||
def llnumba (lltype, llvm_module = None, **kws):
|
||||
'''Decorator version of translate_function().'''
|
||||
def _llnumba (func):
|
||||
return translate_function(func, lltype, llvm_module, **kws)
|
||||
return _llnumba
|
||||
|
||||
# ______________________________________________________________________
|
||||
# Main (self-test) routine
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ li8 = lc.Type.int(8)
|
|||
li16 = lc.Type.int(16)
|
||||
li32 = lc.Type.int(32)
|
||||
li64 = lc.Type.int(64)
|
||||
liptr = lc.Type.int(ctypes.sizeof(ctypes.c_void_p) * 8)
|
||||
lc_size_t = lc.Type.int(ctypes.sizeof(
|
||||
getattr(ctypes, 'c_ssize_t', getattr(ctypes, 'c_size_t'))) * 8)
|
||||
lfloat = lc.Type.float()
|
||||
|
|
@ -25,6 +26,7 @@ lc_long = lc.Type.int(ctypes.sizeof(ctypes.c_long) * 8)
|
|||
l_pyobject_head = [lc_size_t, lc.Type.pointer(li32)]
|
||||
l_pyobject_head_struct = lc.Type.struct(l_pyobject_head)
|
||||
l_pyobj_p = l_pyobject_head_struct_p = lc.Type.pointer(l_pyobject_head_struct)
|
||||
l_pyfunc = lc.Type.function(l_pyobj_p, (l_pyobj_p, l_pyobj_p))
|
||||
|
||||
strlen = lc.Type.function(lc_size_t, (li8_ptr,))
|
||||
strncpy = lc.Type.function(li8_ptr, (li8_ptr, li8_ptr, lc_size_t))
|
||||
|
|
|
|||
25
nobitey.py
25
nobitey.py
|
|
@ -79,7 +79,20 @@ class NoBitey (object):
|
|||
result = builder.fpext(result, bytetype.ldouble)
|
||||
return result
|
||||
|
||||
def build_wrapper_function (self, llvm_function):
|
||||
def build_wrapper_function (self, llvm_function, engine = None):
|
||||
manual_linkage = False
|
||||
if self.target_module != llvm_function.module:
|
||||
manual_linkage = True
|
||||
assert engine, ("Execution engine argument currently required for "
|
||||
"linkage to separate LLVM module.")
|
||||
llvm_function_ptr = self.target_module.add_global_variable(
|
||||
llvm_function.type, llvm_function.name)
|
||||
llvm_function_ptr.initializer = lc.Constant.inttoptr(
|
||||
lc.Constant.int(bytetype.liptr,
|
||||
engine.get_pointer_to_function(llvm_function)),
|
||||
llvm_function.type)
|
||||
llvm_function_ptr.linkage = lc.LINKAGE_INTERNAL
|
||||
# __________________________________________________
|
||||
_pyobj_p = bytetype.l_pyobject_head_struct_p
|
||||
_void_p = _char_p = bytetype.li8_ptr
|
||||
self.crnt_function = self.target_module.add_function(
|
||||
|
|
@ -119,7 +132,10 @@ class NoBitey (object):
|
|||
builder = lc.Builder.new(args_ok_block)
|
||||
thread_state = builder.call(_PyEval_SaveThread, ())
|
||||
target_args = [builder.load(parse_arg) for parse_arg in parse_args[2:]]
|
||||
result = builder.call(llvm_function, target_args)
|
||||
if manual_linkage:
|
||||
result = builder.call(builder.load(llvm_function_ptr), target_args)
|
||||
else:
|
||||
result = builder.call(llvm_function, target_args)
|
||||
result_cast = self.handle_abi_casts(builder, result)
|
||||
builder.call(_PyEval_RestoreThread, (thread_state,))
|
||||
build_str = builder.gep(
|
||||
|
|
@ -147,9 +163,10 @@ class NoBitey (object):
|
|||
if not func.name.startswith("_")
|
||||
and not func.is_declaration
|
||||
and func.linkage == lc.LINKAGE_EXTERNAL]
|
||||
wrappers = [self.build_wrapper_function(func) for func in functions]
|
||||
if engine is None:
|
||||
engine = le.ExecutionEngine.new(llvm_module)
|
||||
wrappers = [self.build_wrapper_function(func, engine)
|
||||
for func in functions]
|
||||
if self.target_module != llvm_module:
|
||||
engine.add_module(self.target_module)
|
||||
py_wrappers = [pyaddfunc(wrapper.name,
|
||||
|
|
@ -346,8 +363,8 @@ def build_test_module ():
|
|||
def main (*args):
|
||||
# Build up a module.
|
||||
m = build_test_module()
|
||||
print(m)
|
||||
wrap_module = NoBitey().wrap_llvm_module_in_python(m)
|
||||
print(m)
|
||||
# Now try running the generated wrappers.
|
||||
for py_wf_name in ('add_42_i32', 'add_42_i64', 'add_42_float',
|
||||
'add_42_double'):
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ OPCODE_MAP = {
|
|||
'LOAD_LOCALS': (None, None, None),
|
||||
'LOAD_NAME': (0, 1, None),
|
||||
'MAKE_CLOSURE': (None, None, None),
|
||||
'MAKE_FUNCTION': (None, None, None),
|
||||
'MAKE_FUNCTION': (-2, 1, None),
|
||||
'MAP_ADD': (None, None, None),
|
||||
'NOP': (0, None, None),
|
||||
'POP_BLOCK': (0, None, 1),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue