def parse_tuple_and_keywords(self, args, kws, fmt, keywords, *objs): charptr = Type.pointer(Type.int(8)) charptrary = Type.pointer(charptr) argtypes = [self.pyobj, self.pyobj, charptr, charptrary] fnty = Type.function(Type.int(), argtypes, var_arg=True) fn = self._get_function(fnty, name="PyArg_ParseTupleAndKeywords") return self.builder.call(fn, [args, kws, fmt, keywords] + list(objs))
def f_main(mod): '''main function''' argc = Type.int(32) argv = Type.pointer(Type.pointer(Type.int(8))) type_ = Type.function(Type.void(), [argc, argv]) return mod.get_or_insert_function(type_, "main")
def build_ufunc_wrapper(context, func, signature): """ Wrap the scalar function with a loop that iterates over the arguments """ module = func.module byte_t = Type.int(8) byte_ptr_t = Type.pointer(byte_t) byte_ptr_ptr_t = Type.pointer(byte_ptr_t) intp_t = context.get_value_type(types.intp) intp_ptr_t = Type.pointer(intp_t) fnty = Type.function(Type.void(), [byte_ptr_ptr_t, intp_ptr_t, intp_ptr_t, byte_ptr_t]) wrapper = module.add_function(fnty, "__ufunc__." + func.name) arg_args, arg_dims, arg_steps, arg_data = wrapper.args arg_args.name = "args" arg_dims.name = "dims" arg_steps.name = "steps" arg_data.name = "data" builder = Builder.new(wrapper.append_basic_block("entry")) loopcount = builder.load(arg_dims, name="loopcount") actual_args = context.get_arguments(func) # Prepare inputs arrays = [] for i, typ in enumerate(signature.args): arrays.append( UArrayArg(context, builder, arg_args, arg_steps, i, context.get_argument_type(typ))) # Prepare output out = UArrayArg(context, builder, arg_args, arg_steps, len(actual_args), context.get_value_type(signature.return_type)) # Loop with cgutils.for_range(builder, loopcount, intp=intp_t) as ind: # Load elems = [ary.load(ind) for ary in arrays] # Compute status, retval = context.call_function(builder, func, signature.return_type, signature.args, elems) # Ignoring error status and store result # Store if out.byref: retval = builder.load(retval) out.store(retval, ind) builder.ret_void() return wrapper
def build_ufunc_wrapper(context, func, signature): """ Wrap the scalar function with a loop that iterates over the arguments """ module = func.module byte_t = Type.int(8) byte_ptr_t = Type.pointer(byte_t) byte_ptr_ptr_t = Type.pointer(byte_ptr_t) intp_t = context.get_value_type(types.intp) intp_ptr_t = Type.pointer(intp_t) fnty = Type.function(Type.void(), [byte_ptr_ptr_t, intp_ptr_t, intp_ptr_t, byte_ptr_t]) wrapper = module.add_function(fnty, "__ufunc__." + func.name) arg_args, arg_dims, arg_steps, arg_data = wrapper.args arg_args.name = "args" arg_dims.name = "dims" arg_steps.name = "steps" arg_data.name = "data" builder = Builder.new(wrapper.append_basic_block("entry")) loopcount = builder.load(arg_dims, name="loopcount") actual_args = context.get_arguments(func) # Prepare inputs arrays = [] for i, typ in enumerate(signature.args): arrays.append(UArrayArg(context, builder, arg_args, arg_steps, i, context.get_argument_type(typ))) # Prepare output out = UArrayArg(context, builder, arg_args, arg_steps, len(actual_args), context.get_value_type(signature.return_type)) # Loop with cgutils.for_range(builder, loopcount, intp=intp_t) as ind: # Load elems = [ary.load(ind) for ary in arrays] # Compute status, retval = context.call_function(builder, func, signature.return_type, signature.args, elems) # Ignoring error status and store result # Store if out.byref: retval = builder.load(retval) out.store(retval, ind) builder.ret_void() return wrapper
def get_data_type(self, ty): """ Get a data representation of the type Returns None if it is an opaque pointer """ if (isinstance(ty, types.Dummy) or isinstance(ty, types.Module) or isinstance(ty, types.Function) or isinstance(ty, types.Dispatcher) or isinstance(ty, types.Object) or isinstance(ty, types.Macro)): return Type.pointer(Type.int(8)) elif isinstance(ty, types.CPointer): dty = self.get_data_type(ty.dtype) return Type.pointer(dty) elif isinstance(ty, types.Optional): return self.get_data_type(ty.type) elif isinstance(ty, types.Array): return self.get_struct_type(self.make_array(ty)) elif isinstance(ty, types.UniTuple): dty = self.get_value_type(ty.dtype) return Type.array(dty, ty.count) elif isinstance(ty, types.Tuple): dtys = [self.get_value_type(t) for t in ty] return Type.struct(dtys) elif isinstance(ty, types.UniTupleIter): stty = self.get_struct_type(self.make_unituple_iter(ty)) return stty elif isinstance(ty, types.Record): # Record are represented as byte array return Type.struct([Type.array(Type.int(8), ty.size)]) elif isinstance(ty, types.UnicodeCharSeq): charty = Type.int(numpy_support.sizeof_unicode_char * 8) return Type.struct([Type.array(charty, ty.count)]) elif isinstance(ty, types.CharSeq): charty = Type.int(8) return Type.struct([Type.array(charty, ty.count)]) elif ty in STRUCT_TYPES: return self.get_struct_type(STRUCT_TYPES[ty]) elif isinstance(ty, types.Pair): pairty = self.make_pair(ty.first_type, ty.second_type) return self.get_struct_type(pairty) else: return LTYPEMAP[ty]
def make_keywords(self, kws): strings = [] stringtype = Type.pointer(Type.int(8)) for k in kws: strings.append(self.make_const_string(k)) strings.append(Constant.null(stringtype)) kwlist = Constant.array(stringtype, strings) kwlist = cgutils.global_constant(self.module, ".kwlist", kwlist) return Constant.bitcast(kwlist, Type.pointer(stringtype))
def ctypes_to_lltype(ctypes_repr, name = None): if type(ctypes_repr) == PyCStructType: return ctypes_struct_to_lltype(ctypes_repr, name) elif type(ctypes_repr) == PyCPointerType: elt_t = ctypes_repr._type_ if elt_t == ctypes.c_bool: return lltype.pointer(int8_t) else: return lltype.pointer(ctypes_to_lltype(elt_t)) else: return ctypes_scalar_to_lltype(ctypes_repr)
def ctypes_to_lltype(ctypes_repr, name=None): if type(ctypes_repr) == PyCStructType: return ctypes_struct_to_lltype(ctypes_repr, name) elif type(ctypes_repr) == PyCPointerType: elt_t = ctypes_repr._type_ if elt_t == ctypes.c_bool: return lltype.pointer(int8_t) else: return lltype.pointer(ctypes_to_lltype(elt_t)) else: return ctypes_scalar_to_lltype(ctypes_repr)
def body(self, index): mod = self.function.module c_int32 = lambda val: Constant.int(Type.int(32), val) # global place holder for current mutant id id_var = mod.add_global_variable(Type.int(32), "P86.mutant_id") id_var.initializer = Constant.int(Type.int(32), 0) id_var.linkage = core.LINKAGE_EXTERNAL # global place holder module name containing the currently # selected mutant str_var = mod.add_global_variable(Type.pointer(Type.int(8)), "P86.mutant_mod") str_var.initializer = Constant.null(Type.pointer(Type.int(8))) str_var.linkage = core.LINKAGE_EXTERNAL # pointer to the tail of the mutant list (reverse order) lst_var = mod.add_global_variable(Type.pointer(mutant_t), "P86.mutant_list") lst_var.initializer = Constant.null(Type.pointer(mutant_t)) lst_var.linkage = core.LINKAGE_EXTERNAL ptr = self.var(Type.pointer(mutant_t), self.builder.load(lst_var)) zero = self.constant(Type.int(32), 0) one = self.constant(Type.int(32), 1) # index zero disables all mutants with self.ifelse(index == zero) as ifelse: with ifelse.then(): self.builder.store(id_var.initializer, id_var) self.builder.store(str_var.initializer, str_var) self.ret() # iterate the list until we get to the Nth element with self.loop() as loop: with loop.condition() as setcond: setcond(index > one) with loop.body(): nxt = self.builder.gep(ptr.value, [c_int32(0), c_int32(2)]) ptr.assign(CVar(self, nxt)) index -= one # assign mutant id handle = self.builder.gep(ptr.value, [c_int32(0), c_int32(0)]) handle = self.builder.load(handle) self.builder.store(handle, id_var) # assign module name containing the mutant handle = self.builder.gep(ptr.value, [c_int32(0), c_int32(1)]) handle = self.builder.load(handle) self.builder.store(handle, str_var) self.ret()
def get_data_type(self, ty): """ Get a data representation of the type Returns None if it is an opaque pointer """ if (isinstance(ty, types.Dummy) or isinstance(ty, types.Module) or isinstance(ty, types.Function) or isinstance(ty, types.Dispatcher) or isinstance(ty, types.Object) or isinstance(ty, types.Macro)): return Type.pointer(Type.int(8)) elif isinstance(ty, types.CPointer): dty = self.get_data_type(ty.dtype) return Type.pointer(dty) elif isinstance(ty, types.Optional): return self.get_data_type(ty.type) elif isinstance(ty, types.Array): return self.get_struct_type(self.make_array(ty)) elif isinstance(ty, types.UniTuple): dty = self.get_value_type(ty.dtype) return Type.array(dty, ty.count) elif isinstance(ty, types.Tuple): dtys = [self.get_value_type(t) for t in ty] return Type.struct(dtys) elif isinstance(ty, types.UniTupleIter): stty = self.get_struct_type(self.make_unituple_iter(ty)) return stty elif isinstance(ty, types.Record): # Record are represented as byte array return Type.struct([Type.array(Type.int(8), ty.size)]) elif isinstance(ty, types.UnicodeCharSeq): charty = Type.int(numpy_support.sizeof_unicode_char * 8) return Type.struct([Type.array(charty, ty.count)]) elif isinstance(ty, types.CharSeq): charty = Type.int(8) return Type.struct([Type.array(charty, ty.count)]) elif ty in STRUCT_TYPES: return self.get_struct_type(STRUCT_TYPES[ty]) else: return LTYPEMAP[ty]
def build_llvm_arg_ptr(builder, raw_ptr_arg, dshape, kind, argtype): if kind == lla.SCALAR: src_ptr = builder.bitcast(raw_ptr_arg, Type.pointer(argtype)) src_val = builder.load(src_ptr) return src_val elif kind == lla.POINTER: src_ptr = builder.bitcast(raw_ptr_arg, Type.pointer(argtype)) return src_ptr elif isinstance(kind, tuple): src_ptr = builder.bitcast(raw_ptr_arg, Type.pointer(kind[2])) # First get the shape of this parameter. This will # be a combination of Fixed and TypeVar (Var unsupported # here for now) shape = dshapes[i][:-1] # Get the llvm array arr_var = builder.alloca(argtype.pointee) builder.store(src_ptr, builder.gep(arr_var, (lc.Constant.int(int32_type, 0), lc.Constant.int(int32_type, 0)))) for j, sz in enumerate(shape): if isinstance(sz, Fixed): # If the shape is already known at JIT compile time, # insert the constant shape_el_ptr = builder.gep(arr_var, (lc.Constant.int(int32_type, 0), lc.Constant.int(int32_type, 1), lc.Constant.int(intp_type, j))) builder.store(lc.Constant.int(intp_type, operator.index(sz)), shape_el_ptr) elif isinstance(sz, TypeVar): # TypeVar types are only known when the kernel is bound, # so copy it from the extra data pointer sz_from_extra_ptr = builder.gep(extra_struct, (lc.Constant.int(int32_type, 0), lc.Constant.int(int32_type, input_field_indices[i]), lc.Constant.int(intp_type, j))) sz_from_extra = builder.load(sz_from_extra_ptr) shape_el_ptr = builder.gep(arr_var, (lc.Constant.int(int32_type, 0), lc.Constant.int(int32_type, 1), lc.Constant.int(intp_type, j))) builder.store(sz_from_extra, shape_el_ptr) else: raise TypeError(("unbound_single_ckernel codegen doesn't " + "support dimension type %r") % type(sz)) return arr_var
def test_arg_attr(self): m = Module.new('oifjda') vptr = Type.pointer(Type.float()) sptr = Type.pointer(Type.struct([])) fnty = Type.function(Type.void(), [vptr] * 5) func = m.add_function(fnty, 'foo') attrs = [lc.ATTR_STRUCT_RET, lc.ATTR_BY_VAL, lc.ATTR_NEST, lc.ATTR_NO_ALIAS, lc.ATTR_NO_CAPTURE] for i, attr in enumerate(attrs): arg = func.args[i] self.assertEqual(i, arg.arg_no) arg.add_attribute(attr) self.assertTrue(attr in func.args[i])
def _generic_array(context, builder, shape, dtype, symbol_name, addrspace, can_dynsized=False): elemcount = reduce(operator.mul, shape) lldtype = context.get_data_type(dtype) laryty = Type.array(lldtype, elemcount) if addrspace == nvvm.ADDRSPACE_LOCAL: # Special case local addrespace allocation to use alloca # NVVM is smart enough to only use local memory if no register is # available dataptr = builder.alloca(laryty, name=symbol_name) else: lmod = cgutils.get_module(builder) # Create global variable in the requested address-space gvmem = lmod.add_global_variable(laryty, symbol_name, addrspace) if elemcount <= 0: if can_dynsized: # dynamic shared memory gvmem.linkage = lc.LINKAGE_EXTERNAL else: raise ValueError("array length <= 0") else: gvmem.linkage = lc.LINKAGE_INTERNAL gvmem.initializer = lc.Constant.undef(laryty) if dtype not in types.number_domain: raise TypeError("unsupported type: %s" % dtype) # Convert to generic address-space conv = nvvmutils.insert_addrspace_conv(lmod, Type.int(8), addrspace) addrspaceptr = gvmem.bitcast(Type.pointer(Type.int(8), addrspace)) dataptr = builder.call(conv, [addrspaceptr]) return _make_array(context, builder, dataptr, dtype, shape)
def body(self, ptr): handle = self.builder.load(ptr.value) self.builder.free(handle) null = Constant.null(Type.pointer(Type.int(8))) self.builder.store(null, ptr.value) self.ret()
def f_printf(mod): '''libc: formatted output conversion''' ret = Type.int(32) arg = Type.pointer(Type.int(8)) type_ = Type.function(ret, [arg], True) return mod.get_or_insert_function(type_, "printf")
def make_keywords(self, kws): strings = [] stringtype = Type.pointer(Type.int(8)) for k in kws: strings.append(self.make_const_string(k)) strings.append(Constant.null(stringtype)) kwlist = Constant.array(stringtype, strings) gv = self.module.add_global_variable(kwlist.type, name=".kwlist") gv.global_constant = True gv.initializer = kwlist gv.linkage = lc.LINKAGE_INTERNAL return Constant.bitcast(gv, Type.pointer(stringtype))
def f_scanf(mod): '''libc: input format conversion''' ret = Type.int(32) arg = Type.pointer(Type.int(8)) type_ = Type.function(ret, [arg], True) return mod.get_or_insert_function(type_, "scanf")
def get_argument_type(self, ty): if ty == types.boolean: return self.get_data_type(ty) elif self.is_struct_type(ty): return Type.pointer(self.get_value_type(ty)) else: return self.get_value_type(ty)
def __init__(self, context, builder, value=None, ref=None, cast_ref=False): self._type = context.get_struct_type(self) self._context = context self._builder = builder if ref is None: self._value = alloca_once(builder, self._type) if value is not None: assert not is_pointer(value.type) assert value.type == self._type, (value.type, self._type) builder.store(value, self._value) else: assert value is None assert is_pointer(ref.type) if self._type != ref.type.pointee: if cast_ref: ref = builder.bitcast(ref, Type.pointer(self._type)) else: raise TypeError( "mismatching pointer type: got %s, expected %s" % (ref.type.pointee, self._type)) self._value = ref self._namemap = {} self._fdmap = [] self._typemap = [] base = Constant.int(Type.int(), 0) for i, (k, tp) in enumerate(self._fields): self._namemap[k] = i self._fdmap.append((base, Constant.int(Type.int(), i))) self._typemap.append(tp)
def f_atoi(mod): '''libc: convert a string to an integer''' ret = Type.int(32) args = [Type.pointer(Type.int(8))] type_ = Type.function(ret, args) return mod.get_or_insert_function(type_, "atoi")
def numba_array_adaptor(self, ary, ptr): voidptr = Type.pointer(Type.int(8)) fnty = Type.function(Type.int(), [self.pyobj, voidptr]) fn = self._get_function(fnty, name="numba_adapt_ndarray") fn.args[0].add_attribute(lc.ATTR_NO_CAPTURE) fn.args[1].add_attribute(lc.ATTR_NO_CAPTURE) return self.builder.call(fn, (ary, ptr))
def insert_string_const_addrspace(self, builder, string): """ Insert a constant string in the constant addresspace and return a generic i8 pointer to the data. This function attempts to deduplicate. """ lmod = builder.basic_block.function.module text = Constant.stringz(string) name = "__conststring__.%s" % string charty = Type.int(8) for gv in lmod.global_variables: if gv.name == name and gv.type.pointee == text.type: break else: gl = lmod.add_global_variable(text.type, name=name, addrspace=nvvm.ADDRSPACE_CONSTANT) gl.linkage = LINKAGE_INTERNAL gl.global_constant = True gl.initializer = text constcharptrty = Type.pointer(charty, nvvm.ADDRSPACE_CONSTANT) charptr = builder.bitcast(gl, constcharptrty) conv = nvvmutils.insert_addrspace_conv(lmod, charty, nvvm.ADDRSPACE_CONSTANT) return builder.call(conv, [charptr])
def numba_array_adaptor(self, ary, ptr): voidptr = Type.pointer(Type.int(8)) fnty = Type.function(Type.int(), [self.pyobj, voidptr]) fn = self._get_function(fnty, name="NumbaArrayAdaptor") fn.args[0].add_attribute(lc.ATTR_NO_CAPTURE) fn.args[1].add_attribute(lc.ATTR_NO_CAPTURE) return self.builder.call(fn, (ary, ptr))
def call_function_pointer(self, builder, funcptr, signature, args): retty = self.get_value_type(signature.return_type) fnty = Type.function(retty, [a.type for a in args]) fnptrty = Type.pointer(fnty) addr = self.get_constant(types.intp, funcptr) ptr = builder.inttoptr(addr, fnptrty) return builder.call(ptr, args)
def testCreatePointer(self): ty = Type.int8() p = Type.pointer(ty) self.assertEqual(0, p.pointer_address_space()) self.assertEqual('i8*', p.name) t = p.element_type() self.assertEqual('i8', t.name)
def get_return_type(self, ty): if isinstance(ty, types.Optional): return self.get_return_type(ty.type) elif self.is_struct_type(ty): return self.get_argument_type(ty) else: argty = self.get_argument_type(ty) return Type.pointer(argty)
def testLoad(self): ty = Type.int8() pt = Type.pointer(ty) bldr = Builder.create() a = bldr.alloca(ty, 'a') b = bldr.load(a, 'b') self.assertEqual(' %b = load i8* %a', str(b))
def test_constexpr_opcode(self): mod = Module.new("test_constexpr_opcode") func = mod.add_function(Type.function(Type.void(), []), name="foo") builder = Builder.new(func.append_basic_block("entry")) a = builder.inttoptr(Constant.int(Type.int(), 123), Type.pointer(Type.int())) self.assertTrue(isinstance(a, lc.ConstantExpr)) self.assertEqual(a.opcode, lc.OPCODE_INTTOPTR) self.assertEqual(a.opcode_name, "inttoptr")
def offsetof(struct_type, fieldnum, builder): nullval = Constant.null(Type.pointer(struct_type)) if hasattr(fieldnum, '__index__'): fieldnum = fieldnum.__index__() fieldnum = Constant.int(int_type, fieldnum) offset = builder.gep(nullval, [zero_p, fieldnum]) offsetI = builder.bitcast(offset, int_type) return offsetI
def __init__(self, context, builder): """ Note: Maybe called multiple times when lowering a function """ fix_python_api() self.context = context self.builder = builder self.module = builder.basic_block.function.module # Initialize types self.pyobj = self.context.get_argument_type(types.pyobject) self.voidptr = Type.pointer(Type.int(8)) self.long = Type.int(ctypes.sizeof(ctypes.c_long) * 8) self.ulonglong = Type.int(ctypes.sizeof(ctypes.c_ulonglong) * 8) self.longlong = self.ulonglong self.double = Type.double() self.py_ssize_t = self.context.get_value_type(types.intp) self.cstring = Type.pointer(Type.int(8))
def gil_release(self, gil): """ Release the acquired GIL by gil_ensure(). Must be pair with a gil_ensure(). """ gilptrty = Type.pointer(self.gil_state) fnty = Type.function(Type.void(), [gilptrty]) fn = self._get_function(fnty, "numba_gil_release") return self.builder.call(fn, [gil])
def testAddAlias(self): ty = Type.int8() x = Global.add(self.module, ty, 'x') x.initializer = Value.const_int(ty, 1, True) pty = Type.pointer(ty) y = Global.add_alias(self.module, pty, x, 'y') g = list(GlobalIterator(self.module)) self.assertEqual([x], g)
def test_constexpr_opcode(self): mod = Module.new('test_constexpr_opcode') func = mod.add_function(Type.function(Type.void(), []), name="foo") builder = Builder.new(func.append_basic_block('entry')) a = builder.inttoptr(Constant.int(Type.int(), 123), Type.pointer(Type.int())) self.assertTrue(isinstance(a, lc.ConstantExpr)) self.assertEqual(a.opcode, lc.OPCODE_INTTOPTR) self.assertEqual(a.opcode_name, "inttoptr")
def _lifted_func_type(self, outranks, outkind): argtypes = self.argtypes[:] if self.kinds[-1] == SCALAR: argtypes.append(self.return_type) args = [] for rank, argtype, kind in zip(outranks, argtypes, self.kinds): eltype = get_eltype(argtype, kind) arr_type = array_type(rank, outkind, eltype, self.module) args.append(Type.pointer(arr_type)) return Type.function(void_type, args)
def get_array_type(typo, length): if typo == 'int': return Type.array(Type.int(32), length) elif typo == 'double': return Type.array(Type.double(), length) elif typo == 'String': ch = Type.int(8) return Type.array(Type.pointer(ch), length) elif typo == 'char': return Type.array(Type.int(8), length)
def read_type(self, expr): if expr.issym: name = expr.assym.rstrip("*") if name in self.types: tp = self.types[name] for i in range(len(name), len(expr.assym)): tp = Type.pointer(tp) return tp sys.stderr.write("type missing: {}".format(expr)) sys.exit(1)
def get_value_type(self, ty): if ty == types.boolean: return Type.int(1) dataty = self.get_data_type(ty) if isinstance(ty, types.Record): # Record data are passed by refrence memory = dataty.elements[0] return Type.struct([Type.pointer(memory)]) return dataty
def print_charseq(context, builder, sig, args): [x] = args py = context.get_python_api(builder) xp = cgutils.alloca_once(builder, x.type) builder.store(x, xp) byteptr = builder.bitcast(xp, Type.pointer(Type.int(8))) size = context.get_constant(types.intp, x.type.elements[0].count) cstr = py.bytes_from_string_and_size(byteptr, size) py.print_object(cstr) py.decref(cstr) return context.get_dummy_value()
def gil_ensure(self): """ Ensure the GIL is acquired. The returned value must be consumed by gil_release(). """ gilptrty = Type.pointer(self.gil_state) fnty = Type.function(Type.void(), [gilptrty]) fn = self._get_function(fnty, "numba_gil_ensure") gilptr = cgutils.alloca_once(self.builder, self.gil_state) self.builder.call(fn, [gilptr]) return gilptr
def test_jit_ctypes(self): # This example demonstrates calling an LLVM defined function using # ctypes. It illustrates the common C pattern of having an output # variable in the argument list to the function. The function also # returns an error code upon exit. # setup llvm types ty_errcode = Type.int() ty_float = Type.float() ty_ptr_float = Type.pointer(Type.float()) ty_func = Type.function(ty_errcode, [ty_float, ty_float, ty_ptr_float]) # setup ctypes types ct_errcode = ctypes.c_int ct_float = ctypes.c_float ct_ptr_float = ctypes.POINTER(ct_float) ct_argtypes = [ct_float, ct_float, ct_ptr_float] # generate the function using LLVM my_module = Module.new('my_module') mult = my_module.add_function(ty_func, "mult") mult.args[0].name = "a" mult.args[1].name = "b" mult.args[2].name = "out" # add nocapture to output arg mult.args[2].add_attribute(llvm.core.ATTR_NO_CAPTURE) mult.does_not_throw = True # add nounwind attribute to function bb = mult.append_basic_block("entry") builder = Builder.new(bb) tmp = builder.fmul(mult.args[0], mult.args[1]) builder.store(tmp, mult.args[2]) builder.ret(llvm.core.Constant.int(ty_errcode, 0)) # print the created module logging.debug(my_module) # compile the function ee = ExecutionEngine.new(my_module) # let ctypes know about the function func_ptr_int = ee.get_pointer_to_function(mult) FUNC_TYPE = ctypes.CFUNCTYPE(ct_errcode, *ct_argtypes) py_mult = FUNC_TYPE(func_ptr_int) # now run the function, calling via ctypes output_value = ct_float(123456.0) errcode = py_mult(2.0, 3.0, ctypes.byref(output_value)) self.assertEqual(errcode, 0, msg='unexpected error') self.assertEqual(output_value.value, 6.0)
def test_arg_attr(self): m = Module.new('oifjda') vptr = Type.pointer(Type.float()) fnty = Type.function(Type.void(), [vptr] * 5) func = m.add_function(fnty, 'foo') attrs = [lc.ATTR_STRUCT_RET, lc.ATTR_BY_VAL, lc.ATTR_NEST, lc.ATTR_NO_ALIAS, lc.ATTR_NO_CAPTURE] for i, attr in enumerate(attrs): arg = func.args[i] self.assertEqual(i, arg.arg_no) arg.add_attribute(attr) self.assertTrue(attr in func.args[i])
def get_type(typo): if typo == 'int' or typo == LexmeType.Integer: return Type.int(32) elif typo == 'double' or typo == LexmeType.Double: return Type.double() elif typo == 'String' or typo == LexmeType.String: ch = Type.int(8) return Type.pointer(ch) elif typo == 'char' or typo == LexmeType.Char: return Type.int(8) elif typo == 'void': return Type.void()
def test_opaque(self): # Create an opaque type ts = Type.opaque('mystruct') self.assertTrue('type opaque' in str(ts)) self.assertTrue(ts.is_opaque) self.assertTrue(ts.is_identified) self.assertFalse(ts.is_literal) #print(ts) # Create a recursive type ts.set_body([Type.int(), Type.pointer(ts)]) self.assertEqual(ts.elements[0], Type.int()) self.assertEqual(ts.elements[1], Type.pointer(ts)) self.assertEqual(ts.elements[1].pointee, ts) self.assertFalse(ts.is_opaque) # is not longer a opaque type #print(ts) with self.assertRaises(llvm.LLVMException): # Cannot redefine ts.set_body([])
def get_data_type(self, ty): """ Get a data representation of the type Returns None if it is an opaque pointer """ if (isinstance(ty, types.Dummy) or isinstance(ty, types.Module) or isinstance(ty, types.Function) or isinstance(ty, types.Dispatcher) or isinstance(ty, types.Object) or isinstance(ty, types.Macro)): return Type.pointer(Type.int(8)) elif isinstance(ty, types.CPointer): dty = self.get_data_type(ty.dtype) return Type.pointer(dty) elif isinstance(ty, types.Optional): return self.get_data_type(ty.type) elif isinstance(ty, types.Array): return self.get_struct_type(self.make_array(ty)) elif isinstance(ty, types.UniTuple): dty = self.get_value_type(ty.dtype) return Type.array(dty, ty.count) elif isinstance(ty, types.Tuple): dtys = [self.get_value_type(t) for t in ty] return Type.struct(dtys) elif isinstance(ty, types.UniTupleIter): stty = self.get_struct_type(self.make_unituple_iter(ty)) return stty elif ty in STRUCT_TYPES: return self.get_struct_type(STRUCT_TYPES[ty]) else: return LTYPEMAP[ty]
def insert_const_string(self, mod, string): stringtype = Type.pointer(Type.int(8)) text = Constant.stringz(string) name = ".const.%s" % string for gv in mod.global_variables: if gv.name == name and gv.type.pointee == text.type: break else: gv = mod.add_global_variable(text.type, name=name) gv.global_constant = True gv.initializer = text gv.linkage = lc.LINKAGE_INTERNAL return Constant.bitcast(gv, stringtype)