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
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)
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
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)
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)
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
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, ))
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,))
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
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
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)
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
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, [])
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, [])