Example #1
0
def cast_call_args(ARGS, args_i, args_r, args_f, args_in_order=None):
    argsiter_i = iter(args_i or [])
    argsiter_r = iter(args_r or [])
    argsiter_f = iter(args_f or [])
    if args_in_order is not None:
        orderiter = iter(args_in_order)
    args = []
    for TYPE in ARGS:
        if TYPE is lltype.Void:
            x = None
        else:
            if isinstance(TYPE, lltype.Ptr) and TYPE.TO._gckind == "gc":
                if args_in_order is not None:
                    n = orderiter.next()
                    assert n == "r"
                x = argsiter_r.next()
                x = cast_from_ptr(TYPE, x)
            elif TYPE is lltype.Float or longlong.is_longlong(TYPE):
                if args_in_order is not None:
                    n = orderiter.next()
                    assert n == "f"
                x = argsiter_f.next()
                x = cast_from_floatstorage(TYPE, x)
            else:
                if args_in_order is not None:
                    n = orderiter.next()
                    assert n == "i"
                x = argsiter_i.next()
                x = cast_from_int(TYPE, x)
        args.append(x)
    assert list(argsiter_i) == []
    assert list(argsiter_r) == []
    assert list(argsiter_f) == []
    return args
Example #2
0
def cast_from_floatstorage(TYPE, x):
    assert isinstance(x, longlong.r_float_storage)
    if TYPE is lltype.Float:
        return longlong.getrealfloat(x)
    if longlong.is_longlong(TYPE):
        return rffi.cast(TYPE, x)
    raise TypeError(TYPE)
Example #3
0
def cast_call_args(ARGS, args_i, args_r, args_f, args_in_order=None):
    argsiter_i = iter(args_i or [])
    argsiter_r = iter(args_r or [])
    argsiter_f = iter(args_f or [])
    if args_in_order is not None:
        orderiter = iter(args_in_order)
    args = []
    for TYPE in ARGS:
        if TYPE is lltype.Void:
            x = None
        else:
            if isinstance(TYPE, lltype.Ptr) and TYPE.TO._gckind == 'gc':
                if args_in_order is not None:
                    n = orderiter.next()
                    assert n == 'r'
                x = argsiter_r.next()
                x = cast_from_ptr(TYPE, x)
            elif TYPE is lltype.Float or longlong.is_longlong(TYPE):
                if args_in_order is not None:
                    n = orderiter.next()
                    assert n == 'f'
                x = argsiter_f.next()
                x = cast_from_floatstorage(TYPE, x)
            else:
                if args_in_order is not None:
                    n = orderiter.next()
                    assert n == 'i'
                x = argsiter_i.next()
                x = cast_from_int(TYPE, x)
        args.append(x)
    assert list(argsiter_i) == []
    assert list(argsiter_r) == []
    assert list(argsiter_f) == []
    return args
Example #4
0
def wrap(cpu, value, in_const_box=False):
    if isinstance(lltype.typeOf(value), lltype.Ptr):
        if lltype.typeOf(value).TO._gckind == 'gc':
            value = lltype.cast_opaque_ptr(llmemory.GCREF, value)
            if in_const_box:
                return history.ConstPtr(value)
            else:
                return history.BoxPtr(value)
        else:
            adr = llmemory.cast_ptr_to_adr(value)
            value = heaptracker.adr2int(adr)
            # fall through to the end of the function
    elif (isinstance(value, float)
          or longlong.is_longlong(lltype.typeOf(value))):
        if isinstance(value, float):
            value = longlong.getfloatstorage(value)
        else:
            value = rffi.cast(lltype.SignedLongLong, value)
        if in_const_box:
            return history.ConstFloat(value)
        else:
            return history.BoxFloat(value)
    elif isinstance(value, str) or isinstance(value, unicode):
        assert len(value) == 1  # must be a character
        value = ord(value)
    elif lltype.typeOf(value) is lltype.SingleFloat:
        value = longlong.singlefloat2int(value)
    else:
        value = intmask(value)
    if in_const_box:
        return history.ConstInt(value)
    else:
        return history.BoxInt(value)
Example #5
0
def cast_from_floatstorage(TYPE, x):
    assert isinstance(x, longlong.r_float_storage)
    if TYPE is lltype.Float:
        return longlong.getrealfloat(x)
    if longlong.is_longlong(TYPE):
        return rffi.cast(TYPE, x)
    raise TypeError(TYPE)
Example #6
0
def wrap(cpu, value, in_const_box=False):
    if isinstance(lltype.typeOf(value), lltype.Ptr):
        if lltype.typeOf(value).TO._gckind == 'gc':
            value = lltype.cast_opaque_ptr(llmemory.GCREF, value)
            if in_const_box:
                return history.ConstPtr(value)
            else:
                return resoperation.InputArgRef(value)
        else:
            adr = llmemory.cast_ptr_to_adr(value)
            value = heaptracker.adr2int(adr)
            # fall through to the end of the function
    elif (isinstance(value, float) or
          longlong.is_longlong(lltype.typeOf(value))):
        if isinstance(value, float):
            value = longlong.getfloatstorage(value)
        else:
            value = rffi.cast(lltype.SignedLongLong, value)
        if in_const_box:
            return history.ConstFloat(value)
        else:
            return resoperation.InputArgFloat(value)
    elif isinstance(value, str) or isinstance(value, unicode):
        assert len(value) == 1     # must be a character
        value = ord(value)
    elif lltype.typeOf(value) is lltype.SingleFloat:
        value = longlong.singlefloat2int(value)
    else:
        value = intmask(value)
    if in_const_box:
        return history.ConstInt(value)
    else:
        return resoperation.InputArgInt(value)
Example #7
0
 def emit_const(self, const, kind, allow_short=False):
     value = const.value
     value_key = value
     if kind == 'int':
         TYPE = const.concretetype
         if isinstance(TYPE, lltype.Ptr):
             assert TYPE.TO._gckind == 'raw'
             self.see_raw_object(value)
             value = llmemory.cast_ptr_to_adr(value)
             TYPE = llmemory.Address
         if TYPE == llmemory.Address:
             value = adr2int(value)
         if TYPE is lltype.SingleFloat:
             value = longlong.singlefloat2int(value)
         if not isinstance(value,
                           (llmemory.AddressAsInt, ComputedIntSymbolic)):
             value = lltype.cast_primitive(lltype.Signed, value)
             if type(value) is r_int:
                 value = int(value)
             if allow_short:
                 try:
                     short_num = -128 <= value <= 127
                 except TypeError:  # "Symbolics cannot be compared!"
                     short_num = False
                 if short_num:
                     # emit the constant as a small integer
                     self.code.append(chr(value & 0xFF))
                     return True
         constants = self.constants_i
     elif kind == 'ref':
         value = lltype.cast_opaque_ptr(llmemory.GCREF, value)
         constants = self.constants_r
         if not value:
             # nullptr
             value_key = None
         else:
             value_key = value._obj.container
     elif kind == 'float':
         if const.concretetype == lltype.Float:
             value = longlong.getfloatstorage(value)
         else:
             assert longlong.is_longlong(const.concretetype)
             value = rffi.cast(lltype.SignedLongLong, value)
         constants = self.constants_f
     else:
         raise AssemblerError('unimplemented %r in %r' %
                              (const, self.ssareprname))
     key = (kind, Constant(value_key))
     try:
         val = self.constants_dict[key]
     except KeyError:
         constants.append(value)
         val = 256 - len(constants)
         assert val >= 0, "too many constants"
         self.constants_dict[key] = val
     # emit the constant normally, as one byte that is an index in the
     # list of constants
     self.code.append(chr(val))
     return False
Example #8
0
def map_type_to_argclass(ARG, accept_void=False):
    kind = getkind(ARG)
    if kind == 'int':
        if ARG is lltype.SingleFloat: return 'S'
        else: return 'i'
    elif kind == 'ref': return 'r'
    elif kind == 'float':
        if is_longlong(ARG): return 'L'
        else: return 'f'
    elif kind == 'void':
        if accept_void: return 'v'
    raise NotImplementedError('ARG = %r' % (ARG, ))
Example #9
0
def map_type_to_argclass(ARG, accept_void=False):
    kind = getkind(ARG)
    if   kind == 'int':
        if ARG is lltype.SingleFloat: return 'S'
        else:                         return 'i'
    elif kind == 'ref':               return 'r'
    elif kind == 'float':
        if is_longlong(ARG):          return 'L'
        else:                         return 'f'
    elif kind == 'void':
        if accept_void:               return 'v'
    raise NotImplementedError('ARG = %r' % (ARG,))
Example #10
0
def get_type_flag(TYPE):
    if isinstance(TYPE, lltype.Ptr):
        if TYPE.TO._gckind == 'gc':
            return FLAG_POINTER
        else:
            return FLAG_UNSIGNED
    if isinstance(TYPE, lltype.Struct):
        return FLAG_STRUCT
    if TYPE is lltype.Float or is_longlong(TYPE):
        return FLAG_FLOAT
    if (TYPE is not lltype.Bool and isinstance(TYPE, lltype.Number) and
           rffi.cast(TYPE, -1) == -1):
        return FLAG_SIGNED
    return FLAG_UNSIGNED
Example #11
0
def get_type_flag(TYPE):
    if isinstance(TYPE, lltype.Ptr):
        if TYPE.TO._gckind == 'gc':
            return FLAG_POINTER
        else:
            return FLAG_UNSIGNED
    if isinstance(TYPE, lltype.Struct):
        return FLAG_STRUCT
    if TYPE is lltype.Float or is_longlong(TYPE):
        return FLAG_FLOAT
    if (TYPE is not lltype.Bool and isinstance(TYPE, lltype.Number)
            and rffi.cast(TYPE, -1) == -1):
        return FLAG_SIGNED
    return FLAG_UNSIGNED
Example #12
0
 def emit_const(self, const, kind, allow_short=False):
     value = const.value
     if kind == 'int':
         TYPE = const.concretetype
         if isinstance(TYPE, lltype.Ptr):
             assert TYPE.TO._gckind == 'raw'
             self.see_raw_object(value)
             value = llmemory.cast_ptr_to_adr(value)
             TYPE = llmemory.Address
         if TYPE == llmemory.Address:
             value = heaptracker.adr2int(value)
         if TYPE is lltype.SingleFloat:
             value = longlong.singlefloat2int(value)
         if not isinstance(value, (llmemory.AddressAsInt,
                                   ComputedIntSymbolic)):
             value = lltype.cast_primitive(lltype.Signed, value)
             if allow_short:
                 try:
                     short_num = -128 <= value <= 127
                 except TypeError:    # "Symbolics cannot be compared!"
                     short_num = False
                 if short_num:
                     # emit the constant as a small integer
                     self.code.append(chr(value & 0xFF))
                     return True
         constants = self.constants_i
     elif kind == 'ref':
         value = lltype.cast_opaque_ptr(llmemory.GCREF, value)
         constants = self.constants_r
     elif kind == 'float':
         if const.concretetype == lltype.Float:
             value = longlong.getfloatstorage(value)
         else:
             assert longlong.is_longlong(const.concretetype)
             value = rffi.cast(lltype.SignedLongLong, value)
         constants = self.constants_f
     else:
         raise AssemblerError('unimplemented %r in %r' %
                              (const, self.ssareprname))
     key = (kind, Constant(value))
     if key not in self.constants_dict:
         constants.append(value)
         val = 256 - len(constants)
         assert val >= 0, "too many constants"
         self.constants_dict[key] = val
     # emit the constant normally, as one byte that is an index in the
     # list of constants
     self.code.append(chr(self.constants_dict[key]))
     return False
Example #13
0
def specialize_value(TYPE, x):
    """'x' must be a Signed, a GCREF or a FLOATSTORAGE.
    This function casts it to a more specialized type, like Char or Ptr(..).
    """
    INPUT = lltype.typeOf(x)
    if INPUT is lltype.Signed:
        if isinstance(TYPE, lltype.Ptr) and TYPE.TO._gckind == 'raw':
            # non-gc pointer
            return rffi.cast(TYPE, x)
        elif TYPE is lltype.SingleFloat:
            return longlong.int2singlefloat(x)
        else:
            return lltype.cast_primitive(TYPE, x)
    elif INPUT is longlong.FLOATSTORAGE:
        if longlong.is_longlong(TYPE):
            return rffi.cast(TYPE, x)
        assert TYPE is lltype.Float
        return longlong.getrealfloat(x)
    else:
        return lltype.cast_opaque_ptr(TYPE, x)
Example #14
0
def specialize_value(TYPE, x):
    """'x' must be a Signed, a GCREF or a FLOATSTORAGE.
    This function casts it to a more specialized type, like Char or Ptr(..).
    """
    INPUT = lltype.typeOf(x)
    if INPUT is lltype.Signed:
        if isinstance(TYPE, lltype.Ptr) and TYPE.TO._gckind == 'raw':
            # non-gc pointer
            return rffi.cast(TYPE, x)
        elif TYPE is lltype.SingleFloat:
            return longlong.int2singlefloat(x)
        else:
            return lltype.cast_primitive(TYPE, x)
    elif INPUT is longlong.FLOATSTORAGE:
        if longlong.is_longlong(TYPE):
            return rffi.cast(TYPE, x)
        assert TYPE is lltype.Float
        return longlong.getrealfloat(x)
    else:
        return lltype.cast_opaque_ptr(TYPE, x)
Example #15
0
def wrap(cpu, value, in_const_box=False):
    if isinstance(lltype.typeOf(value), lltype.Ptr):
        if lltype.typeOf(value).TO._gckind == 'gc':
            value = lltype.cast_opaque_ptr(llmemory.GCREF, value)
            if in_const_box:
                return history.ConstPtr(value)
            else:
                res = history.RefFrontendOp(0)
                res.setref_base(value)
                return res
        else:
            value = ptr2int(value)
            # fall through to the end of the function
    elif (isinstance(value, float) or
          longlong.is_longlong(lltype.typeOf(value))):
        if isinstance(value, float):
            value = longlong.getfloatstorage(value)
        else:
            value = rffi.cast(lltype.SignedLongLong, value)
        if in_const_box:
            return history.ConstFloat(value)
        else:
            res = history.FloatFrontendOp(0)
            res.setfloatstorage(value)
            return res
    elif isinstance(value, str) or isinstance(value, unicode):
        assert len(value) == 1     # must be a character
        value = ord(value)
    elif lltype.typeOf(value) is lltype.SingleFloat:
        value = longlong.singlefloat2int(value)
    else:
        value = intmask(value)
    if in_const_box:
        return history.ConstInt(value)
    else:
        res = history.IntFrontendOp(0)
        res.setint(value)
        return res
Example #16
0
    def _run(self, atypes, rtype, avalues, rvalue,
             expected_call_release_gil=1,
             supports_floats=True,
             supports_longlong=False,
             supports_singlefloats=False):

        cif_description = get_description(atypes, rtype)

        def verify(*args):
            for a, exp_a in zip(args, avalues):
                if (lltype.typeOf(exp_a) == rffi.ULONG and
                    lltype.typeOf(a) == lltype.Signed):
                    a = rffi.cast(rffi.ULONG, a)
                assert a == exp_a
            return rvalue
        FUNC = lltype.FuncType([lltype.typeOf(avalue) for avalue in avalues],
                               lltype.typeOf(rvalue))
        func = lltype.functionptr(FUNC, 'verify', _callable=verify)
        func_addr = rffi.cast(rffi.VOIDP, func)

        for i in range(len(avalues)):
            cif_description.exchange_args[i] = (i+1) * 16
        cif_description.exchange_result = (len(avalues)+1) * 16

        unroll_avalues = unrolling_iterable(avalues)

        def fake_call_impl_any(cif_description, func_addr, exchange_buffer):
            ofs = 16
            for avalue in unroll_avalues:
                TYPE = rffi.CArray(lltype.typeOf(avalue))
                data = rffi.ptradd(exchange_buffer, ofs)
                got = rffi.cast(lltype.Ptr(TYPE), data)[0]
                if lltype.typeOf(avalue) is lltype.SingleFloat:
                    got = float(got)
                    avalue = float(avalue)
                elif (lltype.typeOf(avalue) is rffi.SIGNEDCHAR or
                      lltype.typeOf(avalue) is rffi.UCHAR):
                    got = intmask(got)
                    avalue = intmask(avalue)
                assert got == avalue
                ofs += 16
            if rvalue is not None:
                write_rvalue = rvalue
            else:
                write_rvalue = 12923  # ignored
            TYPE = rffi.CArray(lltype.typeOf(write_rvalue))
            data = rffi.ptradd(exchange_buffer, ofs)
            rffi.cast(lltype.Ptr(TYPE), data)[0] = write_rvalue

        def f(i):
            exbuf = lltype.malloc(rffi.CCHARP.TO, (len(avalues)+2) * 16,
                                  flavor='raw')

            targetptr = rffi.ptradd(exbuf, 16)
            for avalue in unroll_avalues:
                TYPE = rffi.CArray(lltype.typeOf(avalue))
                if i >= 9:    # a guard that can fail
                    pass
                rffi.cast(lltype.Ptr(TYPE), targetptr)[0] = avalue
                targetptr = rffi.ptradd(targetptr, 16)

            jit_ffi_call(cif_description, func_addr, exbuf)

            if rvalue is None:
                res = 654321
            else:
                TYPE = rffi.CArray(lltype.typeOf(rvalue))
                res = rffi.cast(lltype.Ptr(TYPE), targetptr)[0]
            lltype.free(exbuf, flavor='raw')
            if lltype.typeOf(res) is lltype.SingleFloat:
                res = float(res)
            return res

        def matching_result(res, rvalue):
            if rvalue is None:
                return res == 654321
            if isinstance(rvalue, r_singlefloat):
                rvalue = float(rvalue)
            if lltype.typeOf(rvalue) is rffi.ULONG:
                res = intmask(res)
                rvalue = intmask(rvalue)
            return res == rvalue

        with FakeFFI(fake_call_impl_any):
            res = f(-42)
            assert matching_result(res, rvalue)
            res = self.interp_operations(f, [-42],
                            supports_floats = supports_floats,
                          supports_longlong = supports_longlong,
                      supports_singlefloats = supports_singlefloats)
            if is_longlong(FUNC.RESULT):
                # longlongs are returned as floats, but that's just
                # an inconvenience of interp_operations().  Normally both
                # longlong and floats are passed around as longlongs.
                res = float2longlong(res)
            assert matching_result(res, rvalue)
            self.check_operations_history(call_may_force=0,
                                          call_release_gil=expected_call_release_gil)

            ##################################################
            driver = jit.JitDriver(reds=['i'], greens=[])
            def main():
                i = 0
                while 1:
                    driver.jit_merge_point(i=i)
                    res = f(i)
                    i += 1
                    if i == 12:
                        return res
            self.meta_interp(main, [])
Example #17
0
    def _run(self, atypes, rtype, avalues, rvalue,
             expected_call_release_gil=1,
             supports_floats=True,
             supports_longlong=True,
             supports_singlefloats=True):

        cif_description = get_description(atypes, rtype)

        def verify(*args):
            assert args == tuple(avalues)
            return rvalue
        FUNC = lltype.FuncType([lltype.typeOf(avalue) for avalue in avalues],
                               lltype.typeOf(rvalue))
        func = lltype.functionptr(FUNC, 'verify', _callable=verify)
        func_addr = rffi.cast(rffi.VOIDP, func)

        for i in range(len(avalues)):
            cif_description.exchange_args[i] = (i+1) * 16
        cif_description.exchange_result = (len(avalues)+1) * 16

        unroll_avalues = unrolling_iterable(avalues)

        def fake_call_impl_any(cif_description, func_addr, exchange_buffer):
            ofs = 16
            for avalue in unroll_avalues:
                TYPE = rffi.CArray(lltype.typeOf(avalue))
                data = rffi.ptradd(exchange_buffer, ofs)
                got = rffi.cast(lltype.Ptr(TYPE), data)[0]
                if lltype.typeOf(avalue) is lltype.SingleFloat:
                    got = float(got)
                    avalue = float(avalue)
                assert got == avalue
                ofs += 16
            if rvalue is not None:
                write_rvalue = rvalue
            else:
                write_rvalue = 12923  # ignored
            TYPE = rffi.CArray(lltype.typeOf(write_rvalue))
            data = rffi.ptradd(exchange_buffer, ofs)
            rffi.cast(lltype.Ptr(TYPE), data)[0] = write_rvalue

        def f():
            exbuf = lltype.malloc(rffi.CCHARP.TO, (len(avalues)+2) * 16,
                                  flavor='raw', zero=True)
            ofs = 16
            for avalue in unroll_avalues:
                TYPE = rffi.CArray(lltype.typeOf(avalue))
                data = rffi.ptradd(exbuf, ofs)
                rffi.cast(lltype.Ptr(TYPE), data)[0] = avalue
                ofs += 16

            jit_ffi_call(cif_description, func_addr, exbuf)

            if rvalue is None:
                res = 654321
            else:
                TYPE = rffi.CArray(lltype.typeOf(rvalue))
                data = rffi.ptradd(exbuf, ofs)
                res = rffi.cast(lltype.Ptr(TYPE), data)[0]
            lltype.free(exbuf, flavor='raw')
            if lltype.typeOf(res) is lltype.SingleFloat:
                res = float(res)
            return res

        def matching_result(res, rvalue):
            if rvalue is None:
                return res == 654321
            if isinstance(rvalue, r_singlefloat):
                rvalue = float(rvalue)
            return res == rvalue

        with FakeFFI(fake_call_impl_any):
            res = f()
            assert matching_result(res, rvalue)
            res = self.interp_operations(f, [],
                            supports_floats = supports_floats,
                          supports_longlong = supports_longlong,
                      supports_singlefloats = supports_singlefloats)
            if is_longlong(FUNC.RESULT):
                # longlongs are returned as floats, but that's just
                # an inconvenience of interp_operations().  Normally both
                # longlong and floats are passed around as longlongs.
                res = float2longlong(res)
            assert matching_result(res, rvalue)
            self.check_operations_history(call_may_force=0,
                                          call_release_gil=expected_call_release_gil)
    def _run(self,
             atypes,
             rtype,
             avalues,
             rvalue,
             expected_call_release_gil=1,
             supports_floats=True,
             supports_longlong=False,
             supports_singlefloats=False):

        cif_description = get_description(atypes, rtype)

        def verify(*args):
            for a, exp_a in zip(args, avalues):
                if (lltype.typeOf(exp_a) == rffi.ULONG
                        and lltype.typeOf(a) == lltype.Signed):
                    a = rffi.cast(rffi.ULONG, a)
                assert a == exp_a
            return rvalue

        FUNC = lltype.FuncType([lltype.typeOf(avalue) for avalue in avalues],
                               lltype.typeOf(rvalue))
        func = lltype.functionptr(FUNC, 'verify', _callable=verify)
        func_addr = rffi.cast(rffi.VOIDP, func)

        for i in range(len(avalues)):
            cif_description.exchange_args[i] = (i + 1) * 16
        cif_description.exchange_result = (len(avalues) + 1) * 16

        unroll_avalues = unrolling_iterable(avalues)

        def fake_call_impl_any(cif_description, func_addr, exchange_buffer):
            ofs = 16
            for avalue in unroll_avalues:
                TYPE = rffi.CArray(lltype.typeOf(avalue))
                data = rffi.ptradd(exchange_buffer, ofs)
                got = rffi.cast(lltype.Ptr(TYPE), data)[0]
                if lltype.typeOf(avalue) is lltype.SingleFloat:
                    got = float(got)
                    avalue = float(avalue)
                elif (lltype.typeOf(avalue) is rffi.SIGNEDCHAR
                      or lltype.typeOf(avalue) is rffi.UCHAR):
                    got = intmask(got)
                    avalue = intmask(avalue)
                assert got == avalue
                ofs += 16
            if rvalue is not None:
                write_rvalue = rvalue
            else:
                write_rvalue = 12923  # ignored
            TYPE = rffi.CArray(lltype.typeOf(write_rvalue))
            data = rffi.ptradd(exchange_buffer, ofs)
            rffi.cast(lltype.Ptr(TYPE), data)[0] = write_rvalue

        def f(i):
            exbuf = lltype.malloc(rffi.CCHARP.TO, (len(avalues) + 2) * 16,
                                  flavor='raw')

            targetptr = rffi.ptradd(exbuf, 16)
            for avalue in unroll_avalues:
                TYPE = rffi.CArray(lltype.typeOf(avalue))
                if i >= 9:  # a guard that can fail
                    pass
                rffi.cast(lltype.Ptr(TYPE), targetptr)[0] = avalue
                targetptr = rffi.ptradd(targetptr, 16)

            jit_ffi_call(cif_description, func_addr, exbuf)

            if rvalue is None:
                res = 654321
            else:
                TYPE = rffi.CArray(lltype.typeOf(rvalue))
                res = rffi.cast(lltype.Ptr(TYPE), targetptr)[0]
            lltype.free(exbuf, flavor='raw')
            if lltype.typeOf(res) is lltype.SingleFloat:
                res = float(res)
            return res

        def matching_result(res, rvalue):
            if rvalue is None:
                return res == 654321
            if isinstance(rvalue, r_singlefloat):
                rvalue = float(rvalue)
            if lltype.typeOf(rvalue) is rffi.ULONG:
                res = intmask(res)
                rvalue = intmask(rvalue)
            return res == rvalue

        with FakeFFI(fake_call_impl_any):
            res = f(-42)
            assert matching_result(res, rvalue)
            res = self.interp_operations(
                f, [-42],
                supports_floats=supports_floats,
                supports_longlong=supports_longlong,
                supports_singlefloats=supports_singlefloats)
            if is_longlong(FUNC.RESULT):
                # longlongs are returned as floats, but that's just
                # an inconvenience of interp_operations().  Normally both
                # longlong and floats are passed around as longlongs.
                res = float2longlong(res)
            assert matching_result(res, rvalue)
            self.check_operations_history(
                call_may_force=0, call_release_gil=expected_call_release_gil)

            ##################################################
            driver = jit.JitDriver(reds=['i'], greens=[])

            def main():
                i = 0
                while 1:
                    driver.jit_merge_point(i=i)
                    res = f(i)
                    i += 1
                    if i == 12:
                        return res

            self.meta_interp(main, [])