Added manual linkage to nobitey when target module isn't the same as the source module.

This commit is contained in:
Jon Riehl 2012-10-16 10:18:13 -05:00
commit 40b84ffd74
5 changed files with 44 additions and 12 deletions

View file

@ -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

View file

@ -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

View file

@ -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))

View file

@ -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'):

View file

@ -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),