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