Got nobitey unit test working using llnumba for wrapper generation.
This commit is contained in:
parent
40b84ffd74
commit
ba309ea6c5
3 changed files with 211 additions and 439 deletions
|
|
@ -6,6 +6,7 @@
|
|||
# Module imports
|
||||
|
||||
import opcode
|
||||
import types
|
||||
|
||||
import llvm.core as lc
|
||||
|
||||
|
|
@ -68,6 +69,9 @@ class LLVMCaster (object):
|
|||
ret_val = builder.sitofp(lval1, lty2)
|
||||
return ret_val
|
||||
|
||||
def build_int_to_ptr_cast(_, builder, lval1, lty2):
|
||||
return builder.inttoptr(lval1, lty2)
|
||||
|
||||
def build_float_to_int_cast(_, builder, lval1, lty2, unsigned = False):
|
||||
ret_val = None
|
||||
if unsigned:
|
||||
|
|
@ -83,6 +87,7 @@ class LLVMCaster (object):
|
|||
(lc.TYPE_DOUBLE, lc.TYPE_FLOAT) : build_float_trunc,
|
||||
(lc.TYPE_INTEGER, lc.TYPE_FLOAT) : build_int_to_float_cast,
|
||||
(lc.TYPE_INTEGER, lc.TYPE_DOUBLE) : build_int_to_float_cast,
|
||||
(lc.TYPE_INTEGER, lc.TYPE_POINTER) : build_int_to_ptr_cast,
|
||||
(lc.TYPE_FLOAT, lc.TYPE_INTEGER) : build_float_to_int_cast,
|
||||
(lc.TYPE_DOUBLE, lc.TYPE_INTEGER) : build_float_to_int_cast,
|
||||
|
||||
|
|
@ -156,6 +161,8 @@ class LLVMTranslator (BytecodeFlowVisitor):
|
|||
if not name.startswith('_'))
|
||||
self.loop_stack = []
|
||||
self.llvm_type = llvm_type
|
||||
self.target_function_name = env.get('target_function_name',
|
||||
function.__name__)
|
||||
self.function = function
|
||||
self.code_obj = opcode_util.get_code_object(function)
|
||||
func_globals = getattr(function, 'func_globals',
|
||||
|
|
@ -170,6 +177,7 @@ class LLVMTranslator (BytecodeFlowVisitor):
|
|||
del self.cfg
|
||||
del self.globals
|
||||
del self.code_obj
|
||||
del self.target_function_name
|
||||
del self.function
|
||||
del self.llvm_type
|
||||
del self.loop_stack
|
||||
|
|
@ -178,7 +186,7 @@ class LLVMTranslator (BytecodeFlowVisitor):
|
|||
def enter_flow_object (self, flow):
|
||||
super(LLVMTranslator, self).enter_flow_object(flow)
|
||||
self.llvm_function = self.llvm_module.add_function(
|
||||
self.llvm_type, self.function.__name__)
|
||||
self.llvm_type, self.target_function_name)
|
||||
self.llvm_blocks = {}
|
||||
self.llvm_definitions = {}
|
||||
self.pending_phis = {}
|
||||
|
|
@ -195,6 +203,7 @@ class LLVMTranslator (BytecodeFlowVisitor):
|
|||
del self.llvm_definitions
|
||||
del self.llvm_blocks
|
||||
del self.llvm_function
|
||||
if __debug__: print(ret_val)
|
||||
return ret_val
|
||||
|
||||
def enter_block (self, block):
|
||||
|
|
@ -353,19 +362,21 @@ class LLVMTranslator (BytecodeFlowVisitor):
|
|||
fn = args[0]
|
||||
args = args[1:]
|
||||
fn_name = getattr(fn, '__name__', None)
|
||||
if isinstance(fn, lc.Type):
|
||||
if isinstance(fn, (types.FunctionType, types.MethodType)):
|
||||
ret_val = [fn(self.builder, *args)]
|
||||
elif isinstance(fn, lc.Value):
|
||||
ret_val = [self.builder.call(fn, args)]
|
||||
elif isinstance(fn, lc.Type):
|
||||
if isinstance(fn, lc.FunctionType):
|
||||
ret_val = [self.builder.call(
|
||||
self.llvm_module.get_or_insert_function(fn, fn_name),
|
||||
args)]
|
||||
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__:
|
||||
ret_val = [fn(self.builder, *args)]
|
||||
else:
|
||||
raise NotImplementedError("Don't know how to call %s() (%r)!" %
|
||||
(fn_name, fn))
|
||||
raise NotImplementedError("Don't know how to call %s() (%r @ %d)!"
|
||||
% (fn_name, fn, i))
|
||||
return ret_val
|
||||
|
||||
def op_CALL_FUNCTION_KW (self, i, op, arg, *args, **kws):
|
||||
|
|
@ -456,9 +467,15 @@ class LLVMTranslator (BytecodeFlowVisitor):
|
|||
(py_val,))
|
||||
return ret_val
|
||||
|
||||
def op_LOAD_DEREF (self, i, op, arg, *args, **kws):
|
||||
ret_val = self.globals[self.code_obj.co_freevars[arg]]
|
||||
if isinstance(ret_val, lc.Type) and not hasattr(ret_val, '__name__'):
|
||||
ret_val.__name__ = self.code_obj.co_names[arg]
|
||||
return [ret_val]
|
||||
|
||||
def op_LOAD_GLOBAL (self, i, op, arg, *args, **kws):
|
||||
ret_val = self.globals[self.code_obj.co_names[arg]]
|
||||
if isinstance(fn, lc.Type) and not hasattr(ret_val, '__name__'):
|
||||
if isinstance(ret_val, lc.Type) and not hasattr(ret_val, '__name__'):
|
||||
ret_val.__name__ = self.code_obj.co_names[arg]
|
||||
return [ret_val]
|
||||
|
||||
|
|
@ -522,8 +539,8 @@ def translate_function (func, lltype, llvm_module = None, **kws):
|
|||
'''Given a function and an LLVM function type, emit LLVM code for
|
||||
that function using a new LLVMTranslator instance.'''
|
||||
translator = LLVMTranslator(llvm_module)
|
||||
translator.translate(func, lltype, kws)
|
||||
return translator
|
||||
ret_val = translator.translate(func, lltype, kws)
|
||||
return ret_val
|
||||
|
||||
# ______________________________________________________________________
|
||||
|
||||
|
|
|
|||
|
|
@ -24,359 +24,128 @@ class BytecodeVisitor (object):
|
|||
'BytecodeVisitor.visit_synthetic_op() must be overloaded if using '
|
||||
'synthetic opcodes.')
|
||||
|
||||
def op_BINARY_ADD (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_BINARY_ADD")
|
||||
|
||||
def op_BINARY_AND (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_BINARY_AND")
|
||||
|
||||
def op_BINARY_DIVIDE (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_BINARY_DIVIDE")
|
||||
|
||||
def op_BINARY_FLOOR_DIVIDE (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_BINARY_FLOOR_DIVIDE")
|
||||
|
||||
def op_BINARY_LSHIFT (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_BINARY_LSHIFT")
|
||||
|
||||
def op_BINARY_MODULO (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_BINARY_MODULO")
|
||||
|
||||
def op_BINARY_MULTIPLY (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_BINARY_MULTIPLY")
|
||||
|
||||
def op_BINARY_OR (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_BINARY_OR")
|
||||
|
||||
def op_BINARY_POWER (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_BINARY_POWER")
|
||||
|
||||
def op_BINARY_RSHIFT (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_BINARY_RSHIFT")
|
||||
|
||||
def op_BINARY_SUBSCR (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_BINARY_SUBSCR")
|
||||
|
||||
def op_BINARY_SUBTRACT (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_BINARY_SUBTRACT")
|
||||
|
||||
def op_BINARY_TRUE_DIVIDE (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_BINARY_TRUE_DIVIDE")
|
||||
|
||||
def op_BINARY_XOR (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_BINARY_XOR")
|
||||
|
||||
def op_BREAK_LOOP (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_BREAK_LOOP")
|
||||
|
||||
def op_BUILD_CLASS (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_BUILD_CLASS")
|
||||
|
||||
def op_BUILD_LIST (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_BUILD_LIST")
|
||||
|
||||
def op_BUILD_MAP (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_BUILD_MAP")
|
||||
|
||||
def op_BUILD_SET (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_BUILD_SET")
|
||||
|
||||
def op_BUILD_SLICE (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_BUILD_SLICE")
|
||||
|
||||
def op_BUILD_TUPLE (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_BUILD_TUPLE")
|
||||
|
||||
def op_CALL_FUNCTION (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_CALL_FUNCTION")
|
||||
|
||||
def op_CALL_FUNCTION_KW (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_CALL_FUNCTION_KW")
|
||||
|
||||
def op_CALL_FUNCTION_VAR (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_CALL_FUNCTION_VAR")
|
||||
|
||||
def op_CALL_FUNCTION_VAR_KW (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_CALL_FUNCTION_VAR_KW")
|
||||
|
||||
def op_COMPARE_OP (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_COMPARE_OP")
|
||||
|
||||
def op_CONTINUE_LOOP (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_CONTINUE_LOOP")
|
||||
|
||||
def op_DELETE_ATTR (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_DELETE_ATTR")
|
||||
|
||||
def op_DELETE_DEREF (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_DELETE_DEREF")
|
||||
|
||||
def op_DELETE_FAST (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_DELETE_FAST")
|
||||
|
||||
def op_DELETE_GLOBAL (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_DELETE_GLOBAL")
|
||||
|
||||
def op_DELETE_NAME (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_DELETE_NAME")
|
||||
|
||||
def op_DELETE_SLICE (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_DELETE_SLICE")
|
||||
|
||||
def op_DELETE_SUBSCR (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_DELETE_SUBSCR")
|
||||
|
||||
def op_DUP_TOP (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_DUP_TOP")
|
||||
|
||||
def op_DUP_TOPX (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_DUP_TOPX")
|
||||
|
||||
def op_DUP_TOP_TWO (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_DUP_TOP_TWO")
|
||||
|
||||
def op_END_FINALLY (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_END_FINALLY")
|
||||
|
||||
def op_EXEC_STMT (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_EXEC_STMT")
|
||||
|
||||
def op_EXTENDED_ARG (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_EXTENDED_ARG")
|
||||
|
||||
def op_FOR_ITER (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_FOR_ITER")
|
||||
|
||||
def op_GET_ITER (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_GET_ITER")
|
||||
|
||||
def op_IMPORT_FROM (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_IMPORT_FROM")
|
||||
|
||||
def op_IMPORT_NAME (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_IMPORT_NAME")
|
||||
|
||||
def op_IMPORT_STAR (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_IMPORT_STAR")
|
||||
|
||||
def op_INPLACE_ADD (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_INPLACE_ADD")
|
||||
|
||||
def op_INPLACE_AND (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_INPLACE_AND")
|
||||
|
||||
def op_INPLACE_DIVIDE (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_INPLACE_DIVIDE")
|
||||
|
||||
def op_INPLACE_FLOOR_DIVIDE (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_INPLACE_FLOOR_DIVIDE")
|
||||
|
||||
def op_INPLACE_LSHIFT (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_INPLACE_LSHIFT")
|
||||
|
||||
def op_INPLACE_MODULO (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_INPLACE_MODULO")
|
||||
|
||||
def op_INPLACE_MULTIPLY (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_INPLACE_MULTIPLY")
|
||||
|
||||
def op_INPLACE_OR (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_INPLACE_OR")
|
||||
|
||||
def op_INPLACE_POWER (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_INPLACE_POWER")
|
||||
|
||||
def op_INPLACE_RSHIFT (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_INPLACE_RSHIFT")
|
||||
|
||||
def op_INPLACE_SUBTRACT (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_INPLACE_SUBTRACT")
|
||||
|
||||
def op_INPLACE_TRUE_DIVIDE (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_INPLACE_TRUE_DIVIDE")
|
||||
|
||||
def op_INPLACE_XOR (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_INPLACE_XOR")
|
||||
|
||||
def op_JUMP_ABSOLUTE (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_JUMP_ABSOLUTE")
|
||||
|
||||
def op_JUMP_FORWARD (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_JUMP_FORWARD")
|
||||
|
||||
def op_JUMP_IF_FALSE (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_JUMP_IF_FALSE")
|
||||
|
||||
def op_JUMP_IF_FALSE_OR_POP (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_JUMP_IF_FALSE_OR_POP")
|
||||
|
||||
def op_JUMP_IF_TRUE (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_JUMP_IF_TRUE")
|
||||
|
||||
def op_JUMP_IF_TRUE_OR_POP (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_JUMP_IF_TRUE_OR_POP")
|
||||
|
||||
def op_LIST_APPEND (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_LIST_APPEND")
|
||||
|
||||
def op_LOAD_ATTR (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_LOAD_ATTR")
|
||||
|
||||
def op_LOAD_BUILD_CLASS (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_LOAD_BUILD_CLASS")
|
||||
|
||||
def op_LOAD_CLOSURE (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_LOAD_CLOSURE")
|
||||
|
||||
def op_LOAD_CONST (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_LOAD_CONST")
|
||||
|
||||
def op_LOAD_DEREF (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_LOAD_DEREF")
|
||||
|
||||
def op_LOAD_FAST (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_LOAD_FAST")
|
||||
|
||||
def op_LOAD_GLOBAL (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_LOAD_GLOBAL")
|
||||
|
||||
def op_LOAD_LOCALS (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_LOAD_LOCALS")
|
||||
|
||||
def op_LOAD_NAME (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_LOAD_NAME")
|
||||
|
||||
def op_MAKE_CLOSURE (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_MAKE_CLOSURE")
|
||||
|
||||
def op_MAKE_FUNCTION (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_MAKE_FUNCTION")
|
||||
|
||||
def op_MAP_ADD (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_MAP_ADD")
|
||||
|
||||
def op_NOP (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_NOP")
|
||||
|
||||
def op_POP_BLOCK (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_POP_BLOCK")
|
||||
|
||||
def op_POP_EXCEPT (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_POP_EXCEPT")
|
||||
|
||||
def op_POP_JUMP_IF_FALSE (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_POP_JUMP_IF_FALSE")
|
||||
|
||||
def op_POP_JUMP_IF_TRUE (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_POP_JUMP_IF_TRUE")
|
||||
|
||||
def op_POP_TOP (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_POP_TOP")
|
||||
|
||||
def op_PRINT_EXPR (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_PRINT_EXPR")
|
||||
|
||||
def op_PRINT_ITEM (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_PRINT_ITEM")
|
||||
|
||||
def op_PRINT_ITEM_TO (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_PRINT_ITEM_TO")
|
||||
|
||||
def op_PRINT_NEWLINE (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_PRINT_NEWLINE")
|
||||
|
||||
def op_PRINT_NEWLINE_TO (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_PRINT_NEWLINE_TO")
|
||||
|
||||
def op_RAISE_VARARGS (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_RAISE_VARARGS")
|
||||
|
||||
def op_RETURN_VALUE (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_RETURN_VALUE")
|
||||
|
||||
def op_ROT_FOUR (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_ROT_FOUR")
|
||||
|
||||
def op_ROT_THREE (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_ROT_THREE")
|
||||
|
||||
def op_ROT_TWO (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_ROT_TWO")
|
||||
|
||||
def op_SETUP_EXCEPT (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_SETUP_EXCEPT")
|
||||
|
||||
def op_SETUP_FINALLY (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_SETUP_FINALLY")
|
||||
|
||||
def op_SETUP_LOOP (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_SETUP_LOOP")
|
||||
|
||||
def op_SETUP_WITH (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_SETUP_WITH")
|
||||
|
||||
def op_SET_ADD (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_SET_ADD")
|
||||
|
||||
def op_SLICE (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_SLICE")
|
||||
|
||||
def op_STOP_CODE (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_STOP_CODE")
|
||||
|
||||
def op_STORE_ATTR (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_STORE_ATTR")
|
||||
|
||||
def op_STORE_DEREF (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_STORE_DEREF")
|
||||
|
||||
def op_STORE_FAST (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_STORE_FAST")
|
||||
|
||||
def op_STORE_GLOBAL (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_STORE_GLOBAL")
|
||||
|
||||
def op_STORE_LOCALS (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_STORE_LOCALS")
|
||||
|
||||
def op_STORE_MAP (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_STORE_MAP")
|
||||
|
||||
def op_STORE_NAME (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_STORE_NAME")
|
||||
|
||||
def op_STORE_SLICE (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_STORE_SLICE")
|
||||
|
||||
def op_STORE_SUBSCR (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_STORE_SUBSCR")
|
||||
|
||||
def op_UNARY_CONVERT (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_UNARY_CONVERT")
|
||||
|
||||
def op_UNARY_INVERT (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_UNARY_INVERT")
|
||||
|
||||
def op_UNARY_NEGATIVE (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_UNARY_NEGATIVE")
|
||||
|
||||
def op_UNARY_NOT (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_UNARY_NOT")
|
||||
|
||||
def op_UNARY_POSITIVE (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_UNARY_POSITIVE")
|
||||
|
||||
def op_UNPACK_EX (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_UNPACK_EX")
|
||||
|
||||
def op_UNPACK_SEQUENCE (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_UNPACK_SEQUENCE")
|
||||
|
||||
def op_WITH_CLEANUP (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_WITH_CLEANUP")
|
||||
|
||||
def op_YIELD_VALUE (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_YIELD_VALUE")
|
||||
def _not_implemented (self, i, op, arg, *args, **kws):
|
||||
raise NotImplementedError("BytecodeVisitor.op_%s (@ bytecode index %d)"
|
||||
% (self.opnames[op], i))
|
||||
|
||||
op_BINARY_ADD = _not_implemented
|
||||
op_BINARY_AND = _not_implemented
|
||||
op_BINARY_DIVIDE = _not_implemented
|
||||
op_BINARY_FLOOR_DIVIDE = _not_implemented
|
||||
op_BINARY_LSHIFT = _not_implemented
|
||||
op_BINARY_MODULO = _not_implemented
|
||||
op_BINARY_MULTIPLY = _not_implemented
|
||||
op_BINARY_OR = _not_implemented
|
||||
op_BINARY_POWER = _not_implemented
|
||||
op_BINARY_RSHIFT = _not_implemented
|
||||
op_BINARY_SUBSCR = _not_implemented
|
||||
op_BINARY_SUBTRACT = _not_implemented
|
||||
op_BINARY_TRUE_DIVIDE = _not_implemented
|
||||
op_BINARY_XOR = _not_implemented
|
||||
op_BREAK_LOOP = _not_implemented
|
||||
op_BUILD_CLASS = _not_implemented
|
||||
op_BUILD_LIST = _not_implemented
|
||||
op_BUILD_MAP = _not_implemented
|
||||
op_BUILD_SET = _not_implemented
|
||||
op_BUILD_SLICE = _not_implemented
|
||||
op_BUILD_TUPLE = _not_implemented
|
||||
op_CALL_FUNCTION = _not_implemented
|
||||
op_CALL_FUNCTION_KW = _not_implemented
|
||||
op_CALL_FUNCTION_VAR = _not_implemented
|
||||
op_CALL_FUNCTION_VAR_KW = _not_implemented
|
||||
op_COMPARE_OP = _not_implemented
|
||||
op_CONTINUE_LOOP = _not_implemented
|
||||
op_DELETE_ATTR = _not_implemented
|
||||
op_DELETE_DEREF = _not_implemented
|
||||
op_DELETE_FAST = _not_implemented
|
||||
op_DELETE_GLOBAL = _not_implemented
|
||||
op_DELETE_NAME = _not_implemented
|
||||
op_DELETE_SLICE = _not_implemented
|
||||
op_DELETE_SUBSCR = _not_implemented
|
||||
op_DUP_TOP = _not_implemented
|
||||
op_DUP_TOPX = _not_implemented
|
||||
op_DUP_TOP_TWO = _not_implemented
|
||||
op_END_FINALLY = _not_implemented
|
||||
op_EXEC_STMT = _not_implemented
|
||||
op_EXTENDED_ARG = _not_implemented
|
||||
op_FOR_ITER = _not_implemented
|
||||
op_GET_ITER = _not_implemented
|
||||
op_IMPORT_FROM = _not_implemented
|
||||
op_IMPORT_NAME = _not_implemented
|
||||
op_IMPORT_STAR = _not_implemented
|
||||
op_INPLACE_ADD = _not_implemented
|
||||
op_INPLACE_AND = _not_implemented
|
||||
op_INPLACE_DIVIDE = _not_implemented
|
||||
op_INPLACE_FLOOR_DIVIDE = _not_implemented
|
||||
op_INPLACE_LSHIFT = _not_implemented
|
||||
op_INPLACE_MODULO = _not_implemented
|
||||
op_INPLACE_MULTIPLY = _not_implemented
|
||||
op_INPLACE_OR = _not_implemented
|
||||
op_INPLACE_POWER = _not_implemented
|
||||
op_INPLACE_RSHIFT = _not_implemented
|
||||
op_INPLACE_SUBTRACT = _not_implemented
|
||||
op_INPLACE_TRUE_DIVIDE = _not_implemented
|
||||
op_INPLACE_XOR = _not_implemented
|
||||
op_JUMP_ABSOLUTE = _not_implemented
|
||||
op_JUMP_FORWARD = _not_implemented
|
||||
op_JUMP_IF_FALSE = _not_implemented
|
||||
op_JUMP_IF_FALSE_OR_POP = _not_implemented
|
||||
op_JUMP_IF_TRUE = _not_implemented
|
||||
op_JUMP_IF_TRUE_OR_POP = _not_implemented
|
||||
op_LIST_APPEND = _not_implemented
|
||||
op_LOAD_ATTR = _not_implemented
|
||||
op_LOAD_BUILD_CLASS = _not_implemented
|
||||
op_LOAD_CLOSURE = _not_implemented
|
||||
op_LOAD_CONST = _not_implemented
|
||||
op_LOAD_DEREF = _not_implemented
|
||||
op_LOAD_FAST = _not_implemented
|
||||
op_LOAD_GLOBAL = _not_implemented
|
||||
op_LOAD_LOCALS = _not_implemented
|
||||
op_LOAD_NAME = _not_implemented
|
||||
op_MAKE_CLOSURE = _not_implemented
|
||||
op_MAKE_FUNCTION = _not_implemented
|
||||
op_MAP_ADD = _not_implemented
|
||||
op_NOP = _not_implemented
|
||||
op_POP_BLOCK = _not_implemented
|
||||
op_POP_EXCEPT = _not_implemented
|
||||
op_POP_JUMP_IF_FALSE = _not_implemented
|
||||
op_POP_JUMP_IF_TRUE = _not_implemented
|
||||
op_POP_TOP = _not_implemented
|
||||
op_PRINT_EXPR = _not_implemented
|
||||
op_PRINT_ITEM = _not_implemented
|
||||
op_PRINT_ITEM_TO = _not_implemented
|
||||
op_PRINT_NEWLINE = _not_implemented
|
||||
op_PRINT_NEWLINE_TO = _not_implemented
|
||||
op_RAISE_VARARGS = _not_implemented
|
||||
op_RETURN_VALUE = _not_implemented
|
||||
op_ROT_FOUR = _not_implemented
|
||||
op_ROT_THREE = _not_implemented
|
||||
op_ROT_TWO = _not_implemented
|
||||
op_SETUP_EXCEPT = _not_implemented
|
||||
op_SETUP_FINALLY = _not_implemented
|
||||
op_SETUP_LOOP = _not_implemented
|
||||
op_SETUP_WITH = _not_implemented
|
||||
op_SET_ADD = _not_implemented
|
||||
op_SLICE = _not_implemented
|
||||
op_STOP_CODE = _not_implemented
|
||||
op_STORE_ATTR = _not_implemented
|
||||
op_STORE_DEREF = _not_implemented
|
||||
op_STORE_FAST = _not_implemented
|
||||
op_STORE_GLOBAL = _not_implemented
|
||||
op_STORE_LOCALS = _not_implemented
|
||||
op_STORE_MAP = _not_implemented
|
||||
op_STORE_NAME = _not_implemented
|
||||
op_STORE_SLICE = _not_implemented
|
||||
op_STORE_SUBSCR = _not_implemented
|
||||
op_UNARY_CONVERT = _not_implemented
|
||||
op_UNARY_INVERT = _not_implemented
|
||||
op_UNARY_NEGATIVE = _not_implemented
|
||||
op_UNARY_NOT = _not_implemented
|
||||
op_UNARY_POSITIVE = _not_implemented
|
||||
op_UNPACK_EX = _not_implemented
|
||||
op_UNPACK_SEQUENCE = _not_implemented
|
||||
op_WITH_CLEANUP = _not_implemented
|
||||
op_YIELD_VALUE = _not_implemented
|
||||
|
||||
# ______________________________________________________________________
|
||||
|
||||
|
|
|
|||
136
nobitey.py
136
nobitey.py
|
|
@ -11,7 +11,7 @@ import llvm.core as lc
|
|||
import llvm.ee as le
|
||||
|
||||
import bytetype
|
||||
|
||||
import byte_translator
|
||||
from pyaddfunc import pyaddfunc
|
||||
|
||||
LLVM_TO_INT_PARSE_STR_MAP = {
|
||||
|
|
@ -80,80 +80,54 @@ class NoBitey (object):
|
|||
return result
|
||||
|
||||
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(
|
||||
lc.Type.function(_pyobj_p, (_pyobj_p, _pyobj_p)),
|
||||
llvm_function.name + "_wrapper")
|
||||
entry_block = self.crnt_function.append_basic_block('entry')
|
||||
args_ok_block = self.crnt_function.append_basic_block('args_ok')
|
||||
exit_block = self.crnt_function.append_basic_block('exit')
|
||||
_int32_zero = lc.Constant.int(bytetype.li32, 0)
|
||||
_Py_BuildValue = self.target_module.get_or_insert_function(
|
||||
lc.Type.function(_pyobj_p, [_char_p], True), 'Py_BuildValue')
|
||||
_PyArg_ParseTuple = self.target_module.get_or_insert_function(
|
||||
lc.Type.function(bytetype.lc_int, [_pyobj_p, _char_p], True),
|
||||
'PyArg_ParseTuple')
|
||||
_PyEval_SaveThread = self.target_module.get_or_insert_function(
|
||||
lc.Type.function(_void_p, []), 'PyEval_SaveThread')
|
||||
_PyEval_RestoreThread = self.target_module.get_or_insert_function(
|
||||
lc.Type.function(lc.Type.void(), [_void_p]),
|
||||
'PyEval_RestoreThread')
|
||||
# __________________________________________________
|
||||
# entry:
|
||||
builder = lc.Builder.new(entry_block)
|
||||
arg_types = llvm_function.type.pointee.args
|
||||
parse_str = builder.gep(
|
||||
get_string_constant(
|
||||
self.target_module,
|
||||
self.build_parse_string(arg_types)),
|
||||
[_int32_zero, _int32_zero])
|
||||
parse_args = [builder.alloca(arg_ty) for arg_ty in arg_types]
|
||||
parse_args.insert(0, parse_str)
|
||||
parse_args.insert(0, self.crnt_function.args[1])
|
||||
parse_result = builder.call(_PyArg_ParseTuple, parse_args)
|
||||
builder.cbranch(builder.icmp(lc.ICMP_NE, parse_result, _int32_zero),
|
||||
args_ok_block, exit_block)
|
||||
return_type = llvm_function.type.pointee.return_type
|
||||
li32_0 = lc.Constant.int(bytetype.li32, 0)
|
||||
def get_llvm_function (builder):
|
||||
if self.target_module != llvm_function.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
|
||||
ret_val = builder.load(llvm_function_ptr)
|
||||
else:
|
||||
ret_val = llvm_function
|
||||
return ret_val
|
||||
def build_parse_args (builder):
|
||||
return [builder.alloca(arg_type) for arg_type in arg_types]
|
||||
def build_parse_string (builder):
|
||||
parse_str = get_string_constant(
|
||||
self.target_module, self.build_parse_string(arg_types))
|
||||
return builder.gep(parse_str, (li32_0, li32_0))
|
||||
def load_target_args (builder, args):
|
||||
return [builder.load(arg) for arg in args]
|
||||
def build_build_string (builder):
|
||||
build_str = get_string_constant(
|
||||
self.target_module, self._build_parse_string(return_type))
|
||||
return builder.gep(build_str, (li32_0, li32_0))
|
||||
handle_abi_casts = self.handle_abi_casts
|
||||
target_function_name = llvm_function.name + "_wrapper"
|
||||
# __________________________________________________
|
||||
# args_ok:
|
||||
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:]]
|
||||
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(
|
||||
get_string_constant(
|
||||
self.target_module,
|
||||
self._build_parse_string(result.type)),
|
||||
[_int32_zero, _int32_zero])
|
||||
py_result = builder.call(_Py_BuildValue, [build_str, result_cast])
|
||||
builder.branch(exit_block)
|
||||
@byte_translator.llnumba(bytetype.l_pyfunc, self.target_module,
|
||||
**locals())
|
||||
def _wrapper (self, args):
|
||||
ret_val = l_pyobj_p(0)
|
||||
parse_args = build_parse_args()
|
||||
parse_result = PyArg_ParseTuple(args, build_parse_string(),
|
||||
*parse_args)
|
||||
if parse_result != li32(0):
|
||||
thread_state = PyEval_SaveThread()
|
||||
target_args = load_target_args(parse_args)
|
||||
llresult = handle_abi_casts(get_llvm_function()(*target_args))
|
||||
PyEval_RestoreThread(thread_state)
|
||||
ret_val = Py_BuildValue(build_build_string(), llresult)
|
||||
return ret_val
|
||||
# __________________________________________________
|
||||
# exit:
|
||||
builder = lc.Builder.new(exit_block)
|
||||
rval = builder.phi(bytetype.l_pyobject_head_struct_p)
|
||||
rval.add_incoming(lc.Constant.null(bytetype.l_pyobject_head_struct_p),
|
||||
entry_block)
|
||||
rval.add_incoming(py_result, args_ok_block)
|
||||
builder.ret(rval)
|
||||
return self.crnt_function
|
||||
return _wrapper
|
||||
|
||||
def wrap_llvm_module (self, llvm_module, engine = None, py_module = None):
|
||||
'''
|
||||
|
|
@ -167,6 +141,7 @@ class NoBitey (object):
|
|||
engine = le.ExecutionEngine.new(llvm_module)
|
||||
wrappers = [self.build_wrapper_function(func, engine)
|
||||
for func in functions]
|
||||
if __debug__: print(self.target_module)
|
||||
if self.target_module != llvm_module:
|
||||
engine.add_module(self.target_module)
|
||||
py_wrappers = [pyaddfunc(wrapper.name,
|
||||
|
|
@ -360,11 +335,13 @@ def build_test_module ():
|
|||
|
||||
# ______________________________________________________________________
|
||||
|
||||
def main (*args):
|
||||
def test_wrap_module (arg = None):
|
||||
# Build up a module.
|
||||
m = build_test_module()
|
||||
wrap_module = NoBitey().wrap_llvm_module_in_python(m)
|
||||
print(m)
|
||||
if arg and arg.lower() == 'separated':
|
||||
wrap_module = NoBitey().wrap_llvm_module_in_python(m)
|
||||
else:
|
||||
wrap_module = NoBitey(m).wrap_llvm_module_in_python(m)
|
||||
# Now try running the generated wrappers.
|
||||
for py_wf_name in ('add_42_i32', 'add_42_i64', 'add_42_float',
|
||||
'add_42_double'):
|
||||
|
|
@ -376,6 +353,15 @@ def main (*args):
|
|||
result, expected, py_wf)
|
||||
return wrap_module
|
||||
|
||||
# ______________________________________________________________________
|
||||
|
||||
def main (*args):
|
||||
if args:
|
||||
for arg in args:
|
||||
test_wrap_module(arg)
|
||||
else:
|
||||
test_wrap_module()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(*sys.argv[1:])
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue