diff --git a/byte_translator.py b/byte_translator.py index 91753dd..b7149cf 100644 --- a/byte_translator.py +++ b/byte_translator.py @@ -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 # ______________________________________________________________________ diff --git a/bytecode_visitor.py b/bytecode_visitor.py index 6048ba8..091e138 100644 --- a/bytecode_visitor.py +++ b/bytecode_visitor.py @@ -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 # ______________________________________________________________________ diff --git a/nobitey.py b/nobitey.py index 5ae133f..67d134e 100644 --- a/nobitey.py +++ b/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:])