def __init__(self, llvm_module=None, *args, **kws): '''Constructor for LLVMTranslator.''' super(LLVMTranslator, self).__init__(*args, **kws) if llvm_module is None: llvm_module = lc.Module.new('Translated_Module_%d' % (id(self), )) self.llvm_module = llvm_module self.bytecode_flow_builder = BytecodeFlowBuilder() self.control_flow_builder = ControlFlowBuilder() self.phi_injector = PhiInjector()
def __init__ (self, llvm_module = None, *args, **kws): super(LLVMTranslator, self).__init__(*args, **kws) if llvm_module is None: llvm_module = lc.Module.new('Translated_Module_%d' % (id(self),)) self.llvm_module = llvm_module self.bytecode_flow_builder = BytecodeFlowBuilder() self.control_flow_builder = ControlFlowBuilder() self.phi_injector = PhiInjector()
class LLVMTranslator (BytecodeFlowVisitor): '''Transformer responsible for visiting a set of bytecode flow trees, emitting LLVM code. Unlike other translators in :py:mod:`numba.llnumba`, this incorporates the full transformation chain, starting with :py:class:`numba.llnumba.byte_flow.BytecodeFlowBuilder`, then :py:class:`numba.llnumba.byte_control.ControlFlowBuilder`, and then :py:class:`numba.llnumba.phi_injector.PhiInjector`.''' def __init__ (self, llvm_module = None, *args, **kws): '''Constructor for LLVMTranslator.''' super(LLVMTranslator, self).__init__(*args, **kws) if llvm_module is None: llvm_module = lc.Module.new('Translated_Module_%d' % (id(self),)) self.llvm_module = llvm_module self.bytecode_flow_builder = BytecodeFlowBuilder() self.control_flow_builder = ControlFlowBuilder() self.phi_injector = PhiInjector() def translate (self, function, llvm_type = None, llvm_function = None, env = None): '''Translate a function to the given LLVM function type. If no type is given, then assume the function is of LLVM type "void ()". The optional env parameter allows extension of the global environment.''' if llvm_type is None: if llvm_function is None: llvm_type = lc.Type.function(lvoid, ()) else: llvm_type = llvm_function.type.pointee if env is None: env = {} else: env = env.copy() env.update((name, method) for name, method in lc.Builder.__dict__.items() if not name.startswith('_')) env.update((name, value) for name, value in bytetype.__dict__.items() 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', getattr(function, '__globals__', {})).copy() func_globals.update(env) self.globals = func_globals nargs = self.code_obj.co_argcount self.cfg = self.control_flow_builder.visit( self.bytecode_flow_builder.visit(self.code_obj), nargs) self.llvm_function = llvm_function flow = self.phi_injector.visit_cfg(self.cfg, nargs) ret_val = self.visit(flow) 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 return ret_val def enter_flow_object (self, flow): super(LLVMTranslator, self).enter_flow_object(flow) if self.llvm_function is None: self.llvm_function = self.llvm_module.add_function( self.llvm_type, self.target_function_name) self.llvm_blocks = {} self.llvm_definitions = {} self.pending_phis = {} for block in self.block_list: if 0 in self.cfg.blocks_reaching[block]: bb = self.llvm_function.append_basic_block( 'BLOCK_%d' % (block,)) self.llvm_blocks[block] = bb def exit_flow_object (self, flow): super(LLVMTranslator, self).exit_flow_object(flow) ret_val = self.llvm_function del self.pending_phis del self.llvm_definitions del self.llvm_blocks if __debug__ and logger.getEffectiveLevel() < logging.DEBUG: logger.debug(str(ret_val)) return ret_val def enter_block (self, block): ret_val = False if block in self.llvm_blocks: self.llvm_block = self.llvm_blocks[block] self.builder = lc.Builder.new(self.llvm_block) ret_val = True return ret_val def exit_block (self, block): del self.llvm_block del self.builder def visit_synthetic_op (self, i, op, arg, *args, **kws): method = getattr(self, 'op_%s' % (synthetic_opname[op],)) return method(i, op, arg, *args, **kws) def op_REF_ARG (self, i, op, arg, *args, **kws): return [self.llvm_function.args[arg]] def op_BUILD_PHI (self, i, op, arg, *args, **kws): phi_type = None incoming = [] pending = [] for child_arg in arg: child_block, _, child_opname, child_arg, _ = child_arg assert child_opname == 'REF_DEF' if child_arg in self.llvm_definitions: child_def = self.llvm_definitions[child_arg] if phi_type is None: phi_type = child_def.type incoming.append((child_block, child_def)) else: pending.append((child_arg, child_block)) phi = self.builder.phi(phi_type) for block_index, defn in incoming: phi.add_incoming(defn, self.llvm_blocks[block_index]) for defn_index, block_index in pending: if defn_index not in self.pending_phis: self.pending_phis[defn_index] = [] self.pending_phis[defn_index].append((phi, block_index)) return [phi] def op_DEFINITION (self, i, op, def_index, *args, **kws): assert len(args) == 1 arg = args[0] if def_index in self.pending_phis: for phi, block_index in self.pending_phis[def_index]: phi.add_incoming(arg, self.llvm_blocks[block_index]) self.llvm_definitions[def_index] = arg return args def op_REF_DEF (self, i, op, arg, *args, **kws): return [self.llvm_definitions[arg]] def op_BINARY_ADD (self, i, op, arg, *args, **kws): arg1, arg2 = args if arg1.type.kind == lc.TYPE_INTEGER: ret_val = [self.builder.add(arg1, arg2)] elif arg1.type.kind in (lc.TYPE_FLOAT, lc.TYPE_DOUBLE): ret_val = [self.builder.fadd(arg1, arg2)] elif arg1.type.kind == lc.TYPE_POINTER: ret_val = [self.builder.gep(arg1, [arg2])] else: raise NotImplementedError("LLVMTranslator.op_BINARY_ADD for %r" % (args,)) return ret_val def op_BINARY_AND (self, i, op, arg, *args, **kws): return [self.builder.and_(args[0], args[1])] def op_BINARY_DIVIDE (self, i, op, arg, *args, **kws): arg1, arg2 = args if arg1.type.kind == lc.TYPE_INTEGER: ret_val = [self.builder.sdiv(arg1, arg2)] elif arg1.type.kind in (lc.TYPE_FLOAT, lc.TYPE_DOUBLE): ret_val = [self.builder.fdiv(arg1, arg2)] else: raise NotImplementedError("LLVMTranslator.op_BINARY_DIVIDE for %r" % (args,)) return ret_val def op_BINARY_FLOOR_DIVIDE (self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_BINARY_FLOOR_DIVIDE") def op_BINARY_LSHIFT (self, i, op, arg, *args, **kws): return [self.builder.shl(args[0], args[1])] def op_BINARY_MODULO (self, i, op, arg, *args, **kws): arg1, arg2 = args if arg1.type.kind == lc.TYPE_INTEGER: ret_val = [self.builder.srem(arg1, arg2)] elif arg1.type.kind in (lc.TYPE_FLOAT, lc.TYPE_DOUBLE): ret_val = [self.builder.frem(arg1, arg2)] else: raise NotImplementedError("LLVMTranslator.op_BINARY_MODULO for %r" % (args,)) return ret_val def op_BINARY_MULTIPLY (self, i, op, arg, *args, **kws): arg1, arg2 = args if arg1.type.kind == lc.TYPE_INTEGER: ret_val = [self.builder.mul(arg1, arg2)] elif arg1.type.kind in (lc.TYPE_FLOAT, lc.TYPE_DOUBLE): ret_val = [self.builder.fmul(arg1, arg2)] else: raise NotImplementedError("LLVMTranslator.op_BINARY_MULTIPLY for " "%r" % (args,)) return ret_val def op_BINARY_OR (self, i, op, arg, *args, **kws): return [self.builder.or_(args[0], args[1])] def op_BINARY_POWER (self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_BINARY_POWER") def op_BINARY_RSHIFT (self, i, op, arg, *args, **kws): return [self.builder.lshr(args[0], args[1])] def op_BINARY_SUBSCR (self, i, op, arg, *args, **kws): arr_val = args[0] index_vals = args[1:] ret_val = gep_result = self.builder.gep(arr_val, index_vals) if (gep_result.type.kind == lc.TYPE_POINTER and gep_result.type.pointee.kind != lc.TYPE_POINTER): ret_val = self.builder.load(gep_result) return [ret_val] def op_BINARY_SUBTRACT (self, i, op, arg, *args, **kws): arg1, arg2 = args if arg1.type.kind == lc.TYPE_INTEGER: ret_val = [self.builder.sub(arg1, arg2)] elif arg1.type.kind in (lc.TYPE_FLOAT, lc.TYPE_DOUBLE): ret_val = [self.builder.fsub(arg1, arg2)] else: raise NotImplementedError("LLVMTranslator.op_BINARY_SUBTRACT for " "%r" % (args,)) return ret_val op_BINARY_TRUE_DIVIDE = op_BINARY_DIVIDE def op_BINARY_XOR (self, i, op, arg, *args, **kws): return [self.builder.xor(args[0], args[1])] def op_BREAK_LOOP (self, i, op, arg, *args, **kws): return [self.builder.branch(self.llvm_blocks[arg])] def op_BUILD_SLICE (self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_BUILD_SLICE") def op_BUILD_TUPLE (self, i, op, arg, *args, **kws): return args 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, (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)] else: assert len(args) == 1 ret_val = [LLVMCaster.build_cast(self.builder, args[0], fn)] else: 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): raise NotImplementedError("LLVMTranslator.op_CALL_FUNCTION_KW") def op_CALL_FUNCTION_VAR (self, i, op, arg, *args, **kws): 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") def op_COMPARE_OP (self, i, op, arg, *args, **kws): arg1, arg2 = args cmp_kind = opcode.cmp_op[arg] if isinstance(arg1.type, lc.IntegerType): ret_val = [self.builder.icmp(_compare_mapping_sint[cmp_kind], arg1, arg2)] elif arg1.type.kind in (lc.TYPE_FLOAT, lc.TYPE_DOUBLE): ret_val = [self.builder.fcmp(_compare_mapping_float[cmp_kind], arg1, arg2)] else: raise NotImplementedError('Comparison of type %r' % (arg1.type,)) return ret_val def op_CONTINUE_LOOP (self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_CONTINUE_LOOP") def op_DELETE_ATTR (self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_DELETE_ATTR") def op_DELETE_SLICE (self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_DELETE_SLICE") def op_FOR_ITER (self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_FOR_ITER") def op_GET_ITER (self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_GET_ITER") op_INPLACE_ADD = op_BINARY_ADD op_INPLACE_AND = op_BINARY_AND op_INPLACE_DIVIDE = op_BINARY_DIVIDE op_INPLACE_FLOOR_DIVIDE = op_BINARY_FLOOR_DIVIDE op_INPLACE_LSHIFT = op_BINARY_LSHIFT op_INPLACE_MODULO = op_BINARY_MODULO op_INPLACE_MULTIPLY = op_BINARY_MULTIPLY op_INPLACE_OR = op_BINARY_OR op_INPLACE_POWER = op_BINARY_POWER op_INPLACE_RSHIFT = op_BINARY_RSHIFT op_INPLACE_SUBTRACT = op_BINARY_SUBTRACT op_INPLACE_TRUE_DIVIDE = op_BINARY_TRUE_DIVIDE op_INPLACE_XOR = op_BINARY_XOR def op_JUMP_ABSOLUTE (self, i, op, arg, *args, **kws): return [self.builder.branch(self.llvm_blocks[arg])] def op_JUMP_FORWARD (self, i, op, arg, *args, **kws): return [self.builder.branch(self.llvm_blocks[i + arg + 3])] def op_JUMP_IF_FALSE (self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_JUMP_IF_FALSE") def op_JUMP_IF_FALSE_OR_POP (self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_JUMP_IF_FALSE_OR_POP") def op_JUMP_IF_TRUE (self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_JUMP_IF_TRUE") def op_JUMP_IF_TRUE_OR_POP (self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_JUMP_IF_TRUE_OR_POP") def op_LOAD_ATTR (self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_LOAD_ATTR") def op_LOAD_CONST (self, i, op, arg, *args, **kws): py_val = self.code_obj.co_consts[arg] if isinstance(py_val, int): ret_val = [lc.Constant.int(bytetype.lc_int, py_val)] elif isinstance(py_val, float): ret_val = [lc.Constant.double(py_val)] elif py_val == None: ret_val = [None] else: raise NotImplementedError('Constant converstion for %r' % (py_val,)) return ret_val def op_LOAD_DEREF (self, i, op, arg, *args, **kws): name = self.code_obj.co_freevars[arg] ret_val = self.globals[name] if isinstance(ret_val, lc.Type) and not hasattr(ret_val, '__name__'): ret_val.__name__ = name return [ret_val] def op_LOAD_GLOBAL (self, i, op, arg, *args, **kws): name = self.code_obj.co_names[arg] ret_val = self.globals[name] if isinstance(ret_val, lc.Type) and not hasattr(ret_val, '__name__'): ret_val.__name__ = name return [ret_val] def op_POP_BLOCK (self, i, op, arg, *args, **kws): self.loop_stack.pop() return [self.builder.branch(self.llvm_blocks[i + 1])] def op_POP_JUMP_IF_FALSE (self, i, op, arg, *args, **kws): return [self.builder.cbranch(args[0], self.llvm_blocks[i + 3], self.llvm_blocks[arg])] def op_POP_JUMP_IF_TRUE (self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_POP_JUMP_IF_TRUE") def op_POP_TOP (self, i, op, arg, *args, **kws): return args def op_RETURN_VALUE (self, i, op, arg, *args, **kws): if args[0] is None: ret_val = [self.builder.ret_void()] else: ret_val = [self.builder.ret(args[0])] return ret_val def op_SETUP_LOOP (self, i, op, arg, *args, **kws): self.loop_stack.append((i, arg)) return [self.builder.branch(self.llvm_blocks[i + 3])] def op_SLICE (self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_SLICE") def op_STORE_ATTR (self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_STORE_ATTR") def op_STORE_SLICE (self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_STORE_SLICE") def op_STORE_SUBSCR (self, i, op, arg, *args, **kws): store_val, arr_val, index_val = args dest_addr = self.builder.gep(arr_val, [index_val]) return [self.builder.store(store_val, dest_addr)] def op_UNARY_CONVERT (self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_UNARY_CONVERT") def op_UNARY_INVERT (self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_UNARY_INVERT") def op_UNARY_NEGATIVE (self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_UNARY_NEGATIVE") def op_UNARY_NOT (self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_UNARY_NOT") def op_UNARY_POSITIVE (self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_UNARY_POSITIVE")
class LLVMTranslator(BytecodeFlowVisitor): '''Transformer responsible for visiting a set of bytecode flow trees, emitting LLVM code. Unlike other translators in :py:mod:`llpython`, this incorporates the full transformation chain, starting with :py:class:`llpython.byte_flow.BytecodeFlowBuilder`, then :py:class:`llpython.byte_control.ControlFlowBuilder`, and then :py:class:`llpython.phi_injector.PhiInjector`.''' def __init__(self, llvm_module=None, *args, **kws): '''Constructor for LLVMTranslator.''' super(LLVMTranslator, self).__init__(*args, **kws) if llvm_module is None: llvm_module = lc.Module.new('Translated_Module_%d' % (id(self), )) self.llvm_module = llvm_module self.bytecode_flow_builder = BytecodeFlowBuilder() self.control_flow_builder = ControlFlowBuilder() self.phi_injector = PhiInjector() def translate(self, function, llvm_type=None, llvm_function=None, env=None): '''Translate a function to the given LLVM function type. If no type is given, then assume the function is of LLVM type "void ()". The optional env parameter allows extension of the global environment.''' if llvm_type is None: if llvm_function is None: llvm_type = lc.Type.function(lvoid, ()) else: llvm_type = llvm_function.type.pointee if env is None: env = {} else: env = env.copy() env.update((name, method) for name, method in lc.Builder.__dict__.items() if not name.startswith('_')) env.update((name, value) for name, value in bytetype.__dict__.items() 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', getattr(function, '__globals__', {})).copy() func_globals.update(env) self.globals = func_globals nargs = self.code_obj.co_argcount self.cfg = self.control_flow_builder.visit( self.bytecode_flow_builder.visit(self.code_obj), nargs) self.llvm_function = llvm_function flow = self.phi_injector.visit_cfg(self.cfg, nargs) ret_val = self.visit(flow) 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 return ret_val def enter_flow_object(self, flow): super(LLVMTranslator, self).enter_flow_object(flow) if self.llvm_function is None: self.llvm_function = self.llvm_module.add_function( self.llvm_type, self.target_function_name) self.llvm_blocks = {} self.llvm_definitions = {} self.pending_phis = {} for block in self.block_list: if 0 in self.cfg.blocks_reaching[block]: bb = self.llvm_function.append_basic_block('BLOCK_%d' % (block, )) self.llvm_blocks[block] = bb def exit_flow_object(self, flow): super(LLVMTranslator, self).exit_flow_object(flow) ret_val = self.llvm_function del self.pending_phis del self.llvm_definitions del self.llvm_blocks if __debug__ and logger.getEffectiveLevel() < logging.DEBUG: logger.debug(str(ret_val)) return ret_val def enter_block(self, block): ret_val = False if block in self.llvm_blocks: self.llvm_block = self.llvm_blocks[block] self.builder = lc.Builder.new(self.llvm_block) ret_val = True return ret_val def exit_block(self, block): del self.llvm_block del self.builder def visit_synthetic_op(self, i, op, arg, *args, **kws): method = getattr(self, 'op_%s' % (synthetic_opname[op], )) return method(i, op, arg, *args, **kws) def op_REF_ARG(self, i, op, arg, *args, **kws): return [self.llvm_function.args[arg]] def op_BUILD_PHI(self, i, op, arg, *args, **kws): phi_type = None incoming = [] pending = [] for child_arg in arg: child_block, _, child_opname, child_arg, _ = child_arg assert child_opname == 'REF_DEF' if child_arg in self.llvm_definitions: child_def = self.llvm_definitions[child_arg] if phi_type is None: phi_type = child_def.type incoming.append((child_block, child_def)) else: pending.append((child_arg, child_block)) phi = self.builder.phi(phi_type) for block_index, defn in incoming: phi.add_incoming(defn, self.llvm_blocks[block_index]) for defn_index, block_index in pending: if defn_index not in self.pending_phis: self.pending_phis[defn_index] = [] self.pending_phis[defn_index].append((phi, block_index)) return [phi] def op_DEFINITION(self, i, op, def_index, *args, **kws): assert len(args) == 1 arg = args[0] if def_index in self.pending_phis: for phi, block_index in self.pending_phis[def_index]: phi.add_incoming(arg, self.llvm_blocks[block_index]) self.llvm_definitions[def_index] = arg return args def op_REF_DEF(self, i, op, arg, *args, **kws): return [self.llvm_definitions[arg]] def op_BINARY_ADD(self, i, op, arg, *args, **kws): arg1, arg2 = args if arg1.type.kind == lc.TYPE_INTEGER: ret_val = [self.builder.add(arg1, arg2)] elif arg1.type.kind in (lc.TYPE_FLOAT, lc.TYPE_DOUBLE): ret_val = [self.builder.fadd(arg1, arg2)] elif arg1.type.kind == lc.TYPE_POINTER: ret_val = [self.builder.gep(arg1, [arg2])] else: raise NotImplementedError("LLVMTranslator.op_BINARY_ADD for %r" % (args, )) return ret_val def op_BINARY_AND(self, i, op, arg, *args, **kws): return [self.builder.and_(args[0], args[1])] def op_BINARY_DIVIDE(self, i, op, arg, *args, **kws): arg1, arg2 = args if arg1.type.kind == lc.TYPE_INTEGER: ret_val = [self.builder.sdiv(arg1, arg2)] elif arg1.type.kind in (lc.TYPE_FLOAT, lc.TYPE_DOUBLE): ret_val = [self.builder.fdiv(arg1, arg2)] else: raise NotImplementedError( "LLVMTranslator.op_BINARY_DIVIDE for %r" % (args, )) return ret_val def op_BINARY_FLOOR_DIVIDE(self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_BINARY_FLOOR_DIVIDE") def op_BINARY_LSHIFT(self, i, op, arg, *args, **kws): return [self.builder.shl(args[0], args[1])] def op_BINARY_MODULO(self, i, op, arg, *args, **kws): arg1, arg2 = args if arg1.type.kind == lc.TYPE_INTEGER: ret_val = [self.builder.srem(arg1, arg2)] elif arg1.type.kind in (lc.TYPE_FLOAT, lc.TYPE_DOUBLE): ret_val = [self.builder.frem(arg1, arg2)] else: raise NotImplementedError( "LLVMTranslator.op_BINARY_MODULO for %r" % (args, )) return ret_val def op_BINARY_MULTIPLY(self, i, op, arg, *args, **kws): arg1, arg2 = args if arg1.type.kind == lc.TYPE_INTEGER: ret_val = [self.builder.mul(arg1, arg2)] elif arg1.type.kind in (lc.TYPE_FLOAT, lc.TYPE_DOUBLE): ret_val = [self.builder.fmul(arg1, arg2)] else: raise NotImplementedError("LLVMTranslator.op_BINARY_MULTIPLY for " "%r" % (args, )) return ret_val def op_BINARY_OR(self, i, op, arg, *args, **kws): return [self.builder.or_(args[0], args[1])] def op_BINARY_POWER(self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_BINARY_POWER") def op_BINARY_RSHIFT(self, i, op, arg, *args, **kws): return [self.builder.lshr(args[0], args[1])] def op_BINARY_SUBSCR(self, i, op, arg, *args, **kws): arr_val = args[0] index_vals = args[1:] ret_val = gep_result = self.builder.gep(arr_val, index_vals) if (gep_result.type.kind == lc.TYPE_POINTER and gep_result.type.pointee.kind != lc.TYPE_POINTER): ret_val = self.builder.load(gep_result) return [ret_val] def op_BINARY_SUBTRACT(self, i, op, arg, *args, **kws): arg1, arg2 = args if arg1.type.kind == lc.TYPE_INTEGER: ret_val = [self.builder.sub(arg1, arg2)] elif arg1.type.kind in (lc.TYPE_FLOAT, lc.TYPE_DOUBLE): ret_val = [self.builder.fsub(arg1, arg2)] else: raise NotImplementedError("LLVMTranslator.op_BINARY_SUBTRACT for " "%r" % (args, )) return ret_val op_BINARY_TRUE_DIVIDE = op_BINARY_DIVIDE def op_BINARY_XOR(self, i, op, arg, *args, **kws): return [self.builder.xor(args[0], args[1])] def op_BREAK_LOOP(self, i, op, arg, *args, **kws): return [self.builder.branch(self.llvm_blocks[arg])] def op_BUILD_SLICE(self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_BUILD_SLICE") def op_BUILD_TUPLE(self, i, op, arg, *args, **kws): return args 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, (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) ] else: assert len(args) == 1 ret_val = [LLVMCaster.build_cast(self.builder, args[0], fn)] else: 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): raise NotImplementedError("LLVMTranslator.op_CALL_FUNCTION_KW") def op_CALL_FUNCTION_VAR(self, i, op, arg, *args, **kws): 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") def op_COMPARE_OP(self, i, op, arg, *args, **kws): arg1, arg2 = args cmp_kind = opcode.cmp_op[arg] if isinstance(arg1.type, lc.IntegerType): ret_val = [ self.builder.icmp(_compare_mapping_sint[cmp_kind], arg1, arg2) ] elif arg1.type.kind in (lc.TYPE_FLOAT, lc.TYPE_DOUBLE): ret_val = [ self.builder.fcmp(_compare_mapping_float[cmp_kind], arg1, arg2) ] else: raise NotImplementedError('Comparison of type %r' % (arg1.type, )) return ret_val def op_CONTINUE_LOOP(self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_CONTINUE_LOOP") def op_DELETE_ATTR(self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_DELETE_ATTR") def op_DELETE_SLICE(self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_DELETE_SLICE") def op_FOR_ITER(self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_FOR_ITER") def op_GET_ITER(self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_GET_ITER") op_INPLACE_ADD = op_BINARY_ADD op_INPLACE_AND = op_BINARY_AND op_INPLACE_DIVIDE = op_BINARY_DIVIDE op_INPLACE_FLOOR_DIVIDE = op_BINARY_FLOOR_DIVIDE op_INPLACE_LSHIFT = op_BINARY_LSHIFT op_INPLACE_MODULO = op_BINARY_MODULO op_INPLACE_MULTIPLY = op_BINARY_MULTIPLY op_INPLACE_OR = op_BINARY_OR op_INPLACE_POWER = op_BINARY_POWER op_INPLACE_RSHIFT = op_BINARY_RSHIFT op_INPLACE_SUBTRACT = op_BINARY_SUBTRACT op_INPLACE_TRUE_DIVIDE = op_BINARY_TRUE_DIVIDE op_INPLACE_XOR = op_BINARY_XOR def op_JUMP_ABSOLUTE(self, i, op, arg, *args, **kws): return [self.builder.branch(self.llvm_blocks[arg])] def op_JUMP_FORWARD(self, i, op, arg, *args, **kws): return [self.builder.branch(self.llvm_blocks[i + arg + 3])] def op_JUMP_IF_FALSE(self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_JUMP_IF_FALSE") def op_JUMP_IF_FALSE_OR_POP(self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_JUMP_IF_FALSE_OR_POP") def op_JUMP_IF_TRUE(self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_JUMP_IF_TRUE") def op_JUMP_IF_TRUE_OR_POP(self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_JUMP_IF_TRUE_OR_POP") def op_LOAD_ATTR(self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_LOAD_ATTR") def op_LOAD_CONST(self, i, op, arg, *args, **kws): py_val = self.code_obj.co_consts[arg] if isinstance(py_val, int): ret_val = [lc.Constant.int(bytetype.lc_int, py_val)] elif isinstance(py_val, float): ret_val = [lc.Constant.double(py_val)] elif py_val == None: ret_val = [None] else: raise NotImplementedError('Constant converstion for %r' % (py_val, )) return ret_val def op_LOAD_DEREF(self, i, op, arg, *args, **kws): name = self.code_obj.co_freevars[arg] ret_val = self.globals[name] if isinstance(ret_val, lc.Type) and not hasattr(ret_val, '__name__'): ret_val.__name__ = name return [ret_val] def op_LOAD_GLOBAL(self, i, op, arg, *args, **kws): name = self.code_obj.co_names[arg] ret_val = self.globals[name] if isinstance(ret_val, lc.Type) and not hasattr(ret_val, '__name__'): ret_val.__name__ = name return [ret_val] def op_POP_BLOCK(self, i, op, arg, *args, **kws): self.loop_stack.pop() return [self.builder.branch(self.llvm_blocks[i + 1])] def op_POP_JUMP_IF_FALSE(self, i, op, arg, *args, **kws): return [ self.builder.cbranch(args[0], self.llvm_blocks[i + 3], self.llvm_blocks[arg]) ] def op_POP_JUMP_IF_TRUE(self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_POP_JUMP_IF_TRUE") def op_POP_TOP(self, i, op, arg, *args, **kws): return args def op_RETURN_VALUE(self, i, op, arg, *args, **kws): if args[0] is None: ret_val = [self.builder.ret_void()] else: ret_val = [self.builder.ret(args[0])] return ret_val def op_SETUP_LOOP(self, i, op, arg, *args, **kws): self.loop_stack.append((i, arg)) return [self.builder.branch(self.llvm_blocks[i + 3])] def op_SLICE(self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_SLICE") def op_STORE_ATTR(self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_STORE_ATTR") def op_STORE_SLICE(self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_STORE_SLICE") def op_STORE_SUBSCR(self, i, op, arg, *args, **kws): store_val, arr_val, index_val = args dest_addr = self.builder.gep(arr_val, [index_val]) return [self.builder.store(store_val, dest_addr)] def op_UNARY_CONVERT(self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_UNARY_CONVERT") def op_UNARY_INVERT(self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_UNARY_INVERT") def op_UNARY_NEGATIVE(self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_UNARY_NEGATIVE") def op_UNARY_NOT(self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_UNARY_NOT") def op_UNARY_POSITIVE(self, i, op, arg, *args, **kws): raise NotImplementedError("LLVMTranslator.op_UNARY_POSITIVE")