def call(self, funcspec, args, RESULT, init_result=0, is_struct=False): """ Call the specified function after constructing and ArgChain with the arguments in ``args``. The function is specified with ``funcspec``, which is a tuple of the form (lib, name, argtypes, restype). This method is overridden by metainterp/test/test_fficall.py in order to do the call in a loop and JIT it. The optional arguments are used only by that overridden method. """ lib, name, argtypes, restype = funcspec func = lib.getpointer(name, argtypes, restype) chain = ArgChain() for arg in args: if isinstance(arg, r_singlefloat): chain.arg_singlefloat(float(arg)) elif IS_32_BIT and isinstance(arg, r_longlong): chain.arg_longlong(longlong2float(arg)) elif IS_32_BIT and isinstance(arg, r_ulonglong): arg = rffi.cast(rffi.LONGLONG, arg) chain.arg_longlong(longlong2float(arg)) elif isinstance(arg, tuple): methname, arg = arg meth = getattr(chain, methname) meth(arg) else: chain.arg(arg) return func.call(chain, RESULT, is_struct=is_struct)
def test_slonglong_args(self): """ long long sum_xy_longlong(long long x, long long y) { return x+y; } """ maxint32 = 2147483647 # we cannot really go above maxint on 64 bits # (and we would not test anything, as there long # is the same as long long) libfoo = self.get_libfoo() func = (libfoo, 'sum_xy_longlong', [types.slonglong, types.slonglong], types.slonglong) if IS_32_BIT: x = r_longlong(maxint32+1) y = r_longlong(maxint32+2) zero = longlong2float(r_longlong(0)) else: x = maxint32+1 y = maxint32+2 zero = 0 res = self.call(func, [x, y], rffi.LONGLONG, init_result=zero) if IS_32_BIT: # obscure, on 32bit it's really a long long, so it returns a # DOUBLE because of the JIT hack res = float2longlong(res) expected = maxint32*2 + 3 assert res == expected
def arg_longlong(self, space, argchain, kind, w_arg): bigarg = space.bigint_w(w_arg) if kind == 'I': llval = bigarg.tolonglong() elif kind == 'U': ullval = bigarg.toulonglong() llval = rffi.cast(rffi.LONGLONG, ullval) else: assert False # this is a hack: we store the 64 bits of the long long into the # 64 bits of a float (i.e., a C double) floatval = libffi.longlong2float(llval) argchain.arg_longlong(floatval)
def call(self, funcspec, args, RESULT, init_result=0, is_struct=False): """ Call the function specified by funcspec in a loop, and let the jit to see and optimize it. """ # lib, name, argtypes, restype = funcspec method_and_args = [] for argval in args: if type(argval) is r_singlefloat: method_name = 'arg_singlefloat' argval = float(argval) elif IS_32_BIT and type(argval) in [r_longlong, r_ulonglong]: method_name = 'arg_longlong' argval = rffi.cast(rffi.LONGLONG, argval) argval = longlong2float(argval) elif isinstance(argval, tuple): method_name, argval = argval else: method_name = 'arg' method_and_args.append((method_name, argval)) method_and_args = unrolling_iterable(method_and_args) # reds = ['n', 'res', 'func'] if (RESULT in [rffi.FLOAT, rffi.DOUBLE] or IS_32_BIT and RESULT in [rffi.LONGLONG, rffi.ULONGLONG]): reds = ['n', 'func', 'res'] # floats must be *after* refs driver = JitDriver(reds=reds, greens=[]) # def f(n): func = lib.getpointer(name, argtypes, restype) res = init_result while n < 10: driver.jit_merge_point(n=n, res=res, func=func) driver.can_enter_jit(n=n, res=res, func=func) func = hint(func, promote=True) argchain = ArgChain() # this loop is unrolled for method_name, argval in method_and_args: getattr(argchain, method_name)(argval) res = func.call(argchain, RESULT, is_struct=is_struct) n += 1 return res # res = self.meta_interp(f, [0], backendopt=True) return res
def fn(x): d = longlong2float(x) ll = float2longlong(d) return ll