/rpython/rtyper/rbuiltin.py
Python | 777 lines | 621 code | 116 blank | 40 comment | 80 complexity | db1328bd02d895c76bb73bc438a97a64 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
- from collections import OrderedDict
- from rpython.annotator import model as annmodel
- from rpython.flowspace.model import Constant
- from rpython.rlib import rarithmetic, objectmodel
- from rpython.rtyper import raddress, rptr, extregistry, rrange
- from rpython.rtyper.error import TyperError
- from rpython.rtyper.lltypesystem import lltype, llmemory, rstr
- from rpython.rtyper import rclass
- from rpython.rtyper.rmodel import Repr
- from rpython.tool.pairtype import pairtype
- BUILTIN_TYPER = {}
- def typer_for(func):
- def wrapped(rtyper_func):
- BUILTIN_TYPER[func] = rtyper_func
- return rtyper_func
- return wrapped
- class __extend__(annmodel.SomeBuiltin):
- def rtyper_makerepr(self, rtyper):
- if not self.is_constant():
- raise TyperError("non-constant built-in function!")
- return BuiltinFunctionRepr(self.const)
- def rtyper_makekey(self):
- const = getattr(self, 'const', None)
- if extregistry.is_registered(const):
- const = extregistry.lookup(const)
- return self.__class__, const
- class __extend__(annmodel.SomeBuiltinMethod):
- def rtyper_makerepr(self, rtyper):
- assert self.methodname is not None
- result = BuiltinMethodRepr(rtyper, self.s_self, self.methodname)
- return result
- def rtyper_makekey(self):
- # NOTE: we hash by id of self.s_self here. This appears to be
- # necessary because it ends up in hop.args_s[0] in the method call,
- # and there is no telling what information the called
- # rtype_method_xxx() will read from that hop.args_s[0].
- # See test_method_join in test_rbuiltin.
- # There is no problem with self.s_self being garbage-collected and
- # its id reused, because the BuiltinMethodRepr keeps a reference
- # to it.
- return (self.__class__, self.methodname, id(self.s_self))
- def call_args_expand(hop):
- hop = hop.copy()
- from rpython.annotator.argument import ArgumentsForTranslation
- arguments = ArgumentsForTranslation.fromshape(
- hop.args_s[1].const, # shape
- range(hop.nb_args-2))
- assert arguments.w_stararg is None
- keywords = arguments.keywords
- # prefix keyword arguments with 'i_'
- kwds_i = {}
- for key in keywords:
- kwds_i['i_' + key] = keywords[key]
- return hop, kwds_i
- class BuiltinFunctionRepr(Repr):
- lowleveltype = lltype.Void
- def __init__(self, builtinfunc):
- self.builtinfunc = builtinfunc
- def findbltintyper(self, rtyper):
- "Find the function to use to specialize calls to this built-in func."
- try:
- return BUILTIN_TYPER[self.builtinfunc]
- except (KeyError, TypeError):
- pass
- if extregistry.is_registered(self.builtinfunc):
- entry = extregistry.lookup(self.builtinfunc)
- return entry.specialize_call
- raise TyperError("don't know about built-in function %r" % (
- self.builtinfunc,))
- def _call(self, hop2, **kwds_i):
- bltintyper = self.findbltintyper(hop2.rtyper)
- hop2.llops._called_exception_is_here_or_cannot_occur = False
- v_result = bltintyper(hop2, **kwds_i)
- if not hop2.llops._called_exception_is_here_or_cannot_occur:
- raise TyperError("missing hop.exception_cannot_occur() or "
- "hop.exception_is_here() in %s" % bltintyper)
- return v_result
- def rtype_simple_call(self, hop):
- hop2 = hop.copy()
- hop2.r_s_popfirstarg()
- return self._call(hop2)
- def rtype_call_args(self, hop):
- # calling a built-in function with keyword arguments:
- # mostly for rpython.objectmodel.hint()
- hop, kwds_i = call_args_expand(hop)
- hop2 = hop.copy()
- hop2.r_s_popfirstarg()
- hop2.r_s_popfirstarg()
- # the RPython-level keyword args are passed with an 'i_' prefix and
- # the corresponding value is an *index* in the hop2 arguments,
- # to be used with hop.inputarg(arg=..)
- return self._call(hop2, **kwds_i)
- class BuiltinMethodRepr(Repr):
- def __init__(self, rtyper, s_self, methodname):
- self.s_self = s_self
- self.self_repr = rtyper.getrepr(s_self)
- self.methodname = methodname
- # methods of a known name are implemented as just their 'self'
- self.lowleveltype = self.self_repr.lowleveltype
- def convert_const(self, obj):
- return self.self_repr.convert_const(obj.__self__)
- def rtype_simple_call(self, hop):
- # methods: look up the rtype_method_xxx()
- name = 'rtype_method_' + self.methodname
- try:
- bltintyper = getattr(self.self_repr, name)
- except AttributeError:
- raise TyperError("missing %s.%s" % (
- self.self_repr.__class__.__name__, name))
- # hack based on the fact that 'lowleveltype == self_repr.lowleveltype'
- hop2 = hop.copy()
- assert hop2.args_r[0] is self
- if isinstance(hop2.args_v[0], Constant):
- c = hop2.args_v[0].value # get object from bound method
- c = c.__self__
- hop2.args_v[0] = Constant(c)
- hop2.args_s[0] = self.s_self
- hop2.args_r[0] = self.self_repr
- return bltintyper(hop2)
- class __extend__(pairtype(BuiltinMethodRepr, BuiltinMethodRepr)):
- def convert_from_to((r_from, r_to), v, llops):
- # convert between two MethodReprs only if they are about the same
- # methodname. (Useful for the case r_from.s_self == r_to.s_self but
- # r_from is not r_to.) See test_rbuiltin.test_method_repr.
- if r_from.methodname != r_to.methodname:
- return NotImplemented
- return llops.convertvar(v, r_from.self_repr, r_to.self_repr)
- def parse_kwds(hop, *argspec_i_r):
- lst = [i for (i, r) in argspec_i_r if i is not None]
- lst.sort()
- if lst != range(hop.nb_args - len(lst), hop.nb_args):
- raise TyperError("keyword args are expected to be at the end of "
- "the 'hop' arg list")
- result = []
- for i, r in argspec_i_r:
- if i is not None:
- if r is None:
- r = hop.args_r[i]
- result.append(hop.inputarg(r, arg=i))
- else:
- result.append(None)
- del hop.args_v[hop.nb_args - len(lst):]
- return result
- # ____________________________________________________________
- @typer_for(bool)
- def rtype_builtin_bool(hop):
- # not called any more?
- assert hop.nb_args == 1
- return hop.args_r[0].rtype_bool(hop)
- @typer_for(int)
- def rtype_builtin_int(hop):
- if isinstance(hop.args_s[0], annmodel.SomeString):
- assert 1 <= hop.nb_args <= 2
- return hop.args_r[0].rtype_int(hop)
- assert hop.nb_args == 1
- return hop.args_r[0].rtype_int(hop)
- @typer_for(float)
- def rtype_builtin_float(hop):
- assert hop.nb_args == 1
- return hop.args_r[0].rtype_float(hop)
- @typer_for(chr)
- def rtype_builtin_chr(hop):
- assert hop.nb_args == 1
- return hop.args_r[0].rtype_chr(hop)
- @typer_for(unichr)
- def rtype_builtin_unichr(hop):
- assert hop.nb_args == 1
- return hop.args_r[0].rtype_unichr(hop)
- @typer_for(unicode)
- def rtype_builtin_unicode(hop):
- return hop.args_r[0].rtype_unicode(hop)
- @typer_for(bytearray)
- def rtype_builtin_bytearray(hop):
- return hop.args_r[0].rtype_bytearray(hop)
- @typer_for(list)
- def rtype_builtin_list(hop):
- return hop.args_r[0].rtype_bltn_list(hop)
- #def rtype_builtin_range(hop): see rrange.py
- #def rtype_builtin_xrange(hop): see rrange.py
- #def rtype_builtin_enumerate(hop): see rrange.py
- #def rtype_r_dict(hop): see rdict.py
- @typer_for(rarithmetic.intmask)
- def rtype_intmask(hop):
- hop.exception_cannot_occur()
- vlist = hop.inputargs(lltype.Signed)
- return vlist[0]
- @typer_for(rarithmetic.longlongmask)
- def rtype_longlongmask(hop):
- hop.exception_cannot_occur()
- vlist = hop.inputargs(lltype.SignedLongLong)
- return vlist[0]
- @typer_for(min)
- def rtype_builtin_min(hop):
- v1, v2 = hop.inputargs(hop.r_result, hop.r_result)
- hop.exception_cannot_occur()
- return hop.gendirectcall(ll_min, v1, v2)
- def ll_min(i1, i2):
- if i1 < i2:
- return i1
- return i2
- @typer_for(max)
- def rtype_builtin_max(hop):
- v1, v2 = hop.inputargs(hop.r_result, hop.r_result)
- hop.exception_cannot_occur()
- return hop.gendirectcall(ll_max, v1, v2)
- def ll_max(i1, i2):
- if i1 > i2:
- return i1
- return i2
- @typer_for(reversed)
- def rtype_builtin_reversed(hop):
- hop.exception_cannot_occur()
- return hop.r_result.newiter(hop)
- @typer_for(getattr(object.__init__, 'im_func', object.__init__))
- def rtype_object__init__(hop):
- hop.exception_cannot_occur()
- @typer_for(getattr(EnvironmentError.__init__, 'im_func',
- EnvironmentError.__init__))
- def rtype_EnvironmentError__init__(hop):
- hop.exception_cannot_occur()
- v_self = hop.args_v[0]
- r_self = hop.args_r[0]
- if hop.nb_args <= 2:
- v_errno = hop.inputconst(lltype.Signed, 0)
- if hop.nb_args == 2:
- v_strerror = hop.inputarg(rstr.string_repr, arg=1)
- r_self.setfield(v_self, 'strerror', v_strerror, hop.llops)
- else:
- v_errno = hop.inputarg(lltype.Signed, arg=1)
- v_strerror = hop.inputarg(rstr.string_repr, arg=2)
- r_self.setfield(v_self, 'strerror', v_strerror, hop.llops)
- if hop.nb_args >= 4:
- v_filename = hop.inputarg(rstr.string_repr, arg=3)
- r_self.setfield(v_self, 'filename', v_filename, hop.llops)
- r_self.setfield(v_self, 'errno', v_errno, hop.llops)
- try:
- WindowsError
- except NameError:
- pass
- else:
- @typer_for(
- getattr(WindowsError.__init__, 'im_func', WindowsError.__init__))
- def rtype_WindowsError__init__(hop):
- hop.exception_cannot_occur()
- if hop.nb_args == 2:
- raise TyperError("WindowsError() should not be called with "
- "a single argument")
- if hop.nb_args >= 3:
- v_self = hop.args_v[0]
- r_self = hop.args_r[0]
- v_error = hop.inputarg(lltype.Signed, arg=1)
- r_self.setfield(v_self, 'winerror', v_error, hop.llops)
- @typer_for(objectmodel.hlinvoke)
- def rtype_hlinvoke(hop):
- _, s_repr = hop.r_s_popfirstarg()
- r_callable = s_repr.const
- r_func, nimplicitarg = r_callable.get_r_implfunc()
- s_callable = r_callable.get_s_callable()
- nbargs = len(hop.args_s) - 1 + nimplicitarg
- s_sigs = r_func.get_s_signatures((nbargs, (), False))
- if len(s_sigs) != 1:
- raise TyperError("cannot hlinvoke callable %r with not uniform"
- "annotations: %r" % (r_callable,
- s_sigs))
- args_s, s_ret = s_sigs[0]
- rinputs = [hop.rtyper.getrepr(s_obj) for s_obj in args_s]
- rresult = hop.rtyper.getrepr(s_ret)
- args_s = args_s[nimplicitarg:]
- rinputs = rinputs[nimplicitarg:]
- new_args_r = [r_callable] + rinputs
- for i in range(len(new_args_r)):
- assert hop.args_r[i].lowleveltype == new_args_r[i].lowleveltype
- hop.args_r = new_args_r
- hop.args_s = [s_callable] + args_s
- hop.s_result = s_ret
- assert hop.r_result.lowleveltype == rresult.lowleveltype
- hop.r_result = rresult
- return hop.dispatch()
- typer_for(range)(rrange.rtype_builtin_range)
- typer_for(xrange)(rrange.rtype_builtin_xrange)
- typer_for(enumerate)(rrange.rtype_builtin_enumerate)
- # annotation of low-level types
- @typer_for(lltype.malloc)
- def rtype_malloc(hop, i_flavor=None, i_zero=None, i_track_allocation=None,
- i_add_memory_pressure=None, i_nonmovable=None):
- assert hop.args_s[0].is_constant()
- vlist = [hop.inputarg(lltype.Void, arg=0)]
- opname = 'malloc'
- kwds_v = parse_kwds(
- hop,
- (i_flavor, lltype.Void),
- (i_zero, None),
- (i_track_allocation, None),
- (i_add_memory_pressure, None),
- (i_nonmovable, None))
- (v_flavor, v_zero, v_track_allocation,
- v_add_memory_pressure, v_nonmovable) = kwds_v
- flags = {'flavor': 'gc'}
- if v_flavor is not None:
- flags['flavor'] = v_flavor.value
- if i_zero is not None:
- flags['zero'] = v_zero.value
- if i_track_allocation is not None:
- flags['track_allocation'] = v_track_allocation.value
- if i_add_memory_pressure is not None:
- flags['add_memory_pressure'] = v_add_memory_pressure.value
- if i_nonmovable is not None:
- flags['nonmovable'] = v_nonmovable
- vlist.append(hop.inputconst(lltype.Void, flags))
- assert 1 <= hop.nb_args <= 2
- if hop.nb_args == 2:
- vlist.append(hop.inputarg(lltype.Signed, arg=1))
- opname += '_varsize'
- hop.has_implicit_exception(MemoryError) # record that we know about it
- hop.exception_is_here()
- return hop.genop(opname, vlist, resulttype=hop.r_result.lowleveltype)
- @typer_for(lltype.free)
- def rtype_free(hop, i_flavor, i_track_allocation=None):
- vlist = [hop.inputarg(hop.args_r[0], arg=0)]
- v_flavor, v_track_allocation = parse_kwds(hop,
- (i_flavor, lltype.Void),
- (i_track_allocation, None))
- #
- assert v_flavor is not None and v_flavor.value == 'raw'
- flags = {'flavor': 'raw'}
- if i_track_allocation is not None:
- flags['track_allocation'] = v_track_allocation.value
- vlist.append(hop.inputconst(lltype.Void, flags))
- #
- hop.exception_cannot_occur()
- hop.genop('free', vlist)
- @typer_for(lltype.render_immortal)
- def rtype_render_immortal(hop, i_track_allocation=None):
- vlist = [hop.inputarg(hop.args_r[0], arg=0)]
- v_track_allocation = parse_kwds(hop,
- (i_track_allocation, None))
- hop.exception_cannot_occur()
- if i_track_allocation is None or v_track_allocation.value:
- hop.genop('track_alloc_stop', vlist)
- @typer_for(lltype.typeOf)
- @typer_for(lltype.nullptr)
- @typer_for(lltype.getRuntimeTypeInfo)
- @typer_for(lltype.Ptr)
- def rtype_const_result(hop):
- hop.exception_cannot_occur()
- return hop.inputconst(hop.r_result.lowleveltype, hop.s_result.const)
- @typer_for(lltype.cast_pointer)
- def rtype_cast_pointer(hop):
- assert hop.args_s[0].is_constant()
- assert isinstance(hop.args_r[1], rptr.PtrRepr)
- v_type, v_input = hop.inputargs(lltype.Void, hop.args_r[1])
- hop.exception_cannot_occur()
- return hop.genop('cast_pointer', [v_input], # v_type implicit in r_result
- resulttype = hop.r_result.lowleveltype)
- @typer_for(lltype.cast_opaque_ptr)
- def rtype_cast_opaque_ptr(hop):
- assert hop.args_s[0].is_constant()
- assert isinstance(hop.args_r[1], rptr.PtrRepr)
- v_type, v_input = hop.inputargs(lltype.Void, hop.args_r[1])
- hop.exception_cannot_occur()
- return hop.genop('cast_opaque_ptr', [v_input], # v_type implicit in r_result
- resulttype = hop.r_result.lowleveltype)
- @typer_for(lltype.length_of_simple_gcarray_from_opaque)
- def rtype_length_of_simple_gcarray_from_opaque(hop):
- assert isinstance(hop.args_r[0], rptr.PtrRepr)
- v_opaque_ptr, = hop.inputargs(hop.args_r[0])
- hop.exception_cannot_occur()
- return hop.genop('length_of_simple_gcarray_from_opaque', [v_opaque_ptr],
- resulttype = hop.r_result.lowleveltype)
- @typer_for(lltype.direct_fieldptr)
- def rtype_direct_fieldptr(hop):
- assert isinstance(hop.args_r[0], rptr.PtrRepr)
- assert hop.args_s[1].is_constant()
- vlist = hop.inputargs(hop.args_r[0], lltype.Void)
- hop.exception_cannot_occur()
- return hop.genop('direct_fieldptr', vlist,
- resulttype=hop.r_result.lowleveltype)
- @typer_for(lltype.direct_arrayitems)
- def rtype_direct_arrayitems(hop):
- assert isinstance(hop.args_r[0], rptr.PtrRepr)
- vlist = hop.inputargs(hop.args_r[0])
- hop.exception_cannot_occur()
- return hop.genop('direct_arrayitems', vlist,
- resulttype=hop.r_result.lowleveltype)
- @typer_for(lltype.direct_ptradd)
- def rtype_direct_ptradd(hop):
- assert isinstance(hop.args_r[0], rptr.PtrRepr)
- vlist = hop.inputargs(hop.args_r[0], lltype.Signed)
- hop.exception_cannot_occur()
- return hop.genop('direct_ptradd', vlist,
- resulttype=hop.r_result.lowleveltype)
- @typer_for(lltype.cast_primitive)
- def rtype_cast_primitive(hop):
- assert hop.args_s[0].is_constant()
- TGT = hop.args_s[0].const
- v_type, v_value = hop.inputargs(lltype.Void, hop.args_r[1])
- hop.exception_cannot_occur()
- return gen_cast(hop.llops, TGT, v_value)
- _cast_to_Signed = {
- lltype.Signed: None,
- lltype.Bool: 'cast_bool_to_int',
- lltype.Char: 'cast_char_to_int',
- lltype.UniChar: 'cast_unichar_to_int',
- lltype.Float: 'cast_float_to_int',
- lltype.Unsigned: 'cast_uint_to_int',
- lltype.SignedLongLong: 'truncate_longlong_to_int',
- }
- _cast_from_Signed = {
- lltype.Signed: None,
- lltype.Char: 'cast_int_to_char',
- lltype.UniChar: 'cast_int_to_unichar',
- lltype.Float: 'cast_int_to_float',
- lltype.Unsigned: 'cast_int_to_uint',
- lltype.SignedLongLong: 'cast_int_to_longlong',
- }
- def gen_cast(llops, TGT, v_value):
- ORIG = v_value.concretetype
- if ORIG == TGT:
- return v_value
- if (isinstance(TGT, lltype.Primitive) and
- isinstance(ORIG, lltype.Primitive)):
- if ORIG in _cast_to_Signed and TGT in _cast_from_Signed:
- op = _cast_to_Signed[ORIG]
- if op:
- v_value = llops.genop(op, [v_value], resulttype=lltype.Signed)
- op = _cast_from_Signed[TGT]
- if op:
- v_value = llops.genop(op, [v_value], resulttype=TGT)
- return v_value
- elif ORIG is lltype.Signed and TGT is lltype.Bool:
- return llops.genop('int_is_true', [v_value], resulttype=lltype.Bool)
- else:
- # use the generic operation if there is no alternative
- return llops.genop('cast_primitive', [v_value], resulttype=TGT)
- elif isinstance(TGT, lltype.Ptr):
- if isinstance(ORIG, lltype.Ptr):
- if (isinstance(TGT.TO, lltype.OpaqueType) or
- isinstance(ORIG.TO, lltype.OpaqueType)):
- return llops.genop('cast_opaque_ptr', [v_value], resulttype=TGT)
- else:
- return llops.genop('cast_pointer', [v_value], resulttype=TGT)
- elif ORIG == llmemory.Address:
- return llops.genop('cast_adr_to_ptr', [v_value], resulttype=TGT)
- elif isinstance(ORIG, lltype.Primitive):
- v_value = gen_cast(llops, lltype.Signed, v_value)
- return llops.genop('cast_int_to_ptr', [v_value], resulttype=TGT)
- elif TGT == llmemory.Address and isinstance(ORIG, lltype.Ptr):
- return llops.genop('cast_ptr_to_adr', [v_value], resulttype=TGT)
- elif isinstance(TGT, lltype.Primitive):
- if isinstance(ORIG, lltype.Ptr):
- v_value = llops.genop('cast_ptr_to_int', [v_value],
- resulttype=lltype.Signed)
- elif ORIG == llmemory.Address:
- v_value = llops.genop('cast_adr_to_int', [v_value],
- resulttype=lltype.Signed)
- else:
- raise TypeError("don't know how to cast from %r to %r" % (ORIG,
- TGT))
- return gen_cast(llops, TGT, v_value)
- raise TypeError("don't know how to cast from %r to %r" % (ORIG, TGT))
- @typer_for(lltype.cast_ptr_to_int)
- def rtype_cast_ptr_to_int(hop):
- assert isinstance(hop.args_r[0], rptr.PtrRepr)
- vlist = hop.inputargs(hop.args_r[0])
- hop.exception_cannot_occur()
- return hop.genop('cast_ptr_to_int', vlist,
- resulttype=lltype.Signed)
- @typer_for(lltype.cast_int_to_ptr)
- def rtype_cast_int_to_ptr(hop):
- assert hop.args_s[0].is_constant()
- v_type, v_input = hop.inputargs(lltype.Void, lltype.Signed)
- hop.exception_cannot_occur()
- return hop.genop('cast_int_to_ptr', [v_input],
- resulttype=hop.r_result.lowleveltype)
- @typer_for(lltype.identityhash)
- def rtype_identity_hash(hop):
- vlist = hop.inputargs(hop.args_r[0])
- hop.exception_cannot_occur()
- return hop.genop('gc_identityhash', vlist, resulttype=lltype.Signed)
- @typer_for(lltype.runtime_type_info)
- def rtype_runtime_type_info(hop):
- assert isinstance(hop.args_r[0], rptr.PtrRepr)
- vlist = hop.inputargs(hop.args_r[0])
- hop.exception_cannot_occur()
- return hop.genop('runtime_type_info', vlist,
- resulttype=hop.r_result.lowleveltype)
- # _________________________________________________________________
- # memory addresses
- @typer_for(llmemory.raw_malloc)
- def rtype_raw_malloc(hop):
- v_size, = hop.inputargs(lltype.Signed)
- hop.exception_cannot_occur()
- return hop.genop('raw_malloc', [v_size], resulttype=llmemory.Address)
- @typer_for(llmemory.raw_malloc_usage)
- def rtype_raw_malloc_usage(hop):
- v_size, = hop.inputargs(lltype.Signed)
- hop.exception_cannot_occur()
- return hop.genop('raw_malloc_usage', [v_size], resulttype=lltype.Signed)
- @typer_for(llmemory.raw_free)
- def rtype_raw_free(hop):
- s_addr = hop.args_s[0]
- if s_addr.is_null_address():
- raise TyperError("raw_free(x) where x is the constant NULL")
- v_addr, = hop.inputargs(llmemory.Address)
- hop.exception_cannot_occur()
- return hop.genop('raw_free', [v_addr])
- @typer_for(llmemory.raw_memcopy)
- def rtype_raw_memcopy(hop):
- for s_addr in hop.args_s[:2]:
- if s_addr.is_null_address():
- raise TyperError("raw_memcopy() with a constant NULL")
- v_list = hop.inputargs(llmemory.Address, llmemory.Address, lltype.Signed)
- hop.exception_cannot_occur()
- return hop.genop('raw_memcopy', v_list)
- @typer_for(llmemory.raw_memclear)
- def rtype_raw_memclear(hop):
- s_addr = hop.args_s[0]
- if s_addr.is_null_address():
- raise TyperError("raw_memclear(x, n) where x is the constant NULL")
- v_list = hop.inputargs(llmemory.Address, lltype.Signed)
- hop.exception_cannot_occur()
- return hop.genop('raw_memclear', v_list)
- @typer_for(llmemory.offsetof)
- def rtype_offsetof(hop):
- TYPE, field = hop.inputargs(lltype.Void, lltype.Void)
- hop.exception_cannot_occur()
- return hop.inputconst(lltype.Signed,
- llmemory.offsetof(TYPE.value, field.value))
- # _________________________________________________________________
- # non-gc objects
- @typer_for(objectmodel.free_non_gc_object)
- def rtype_free_non_gc_object(hop):
- hop.exception_cannot_occur()
- vinst, = hop.inputargs(hop.args_r[0])
- flavor = hop.args_r[0].gcflavor
- assert flavor != 'gc'
- flags = {'flavor': flavor}
- cflags = hop.inputconst(lltype.Void, flags)
- return hop.genop('free', [vinst, cflags])
- @typer_for(objectmodel.keepalive_until_here)
- def rtype_keepalive_until_here(hop):
- hop.exception_cannot_occur()
- for v in hop.args_v:
- hop.genop('keepalive', [v], resulttype=lltype.Void)
- return hop.inputconst(lltype.Void, None)
- @typer_for(llmemory.cast_ptr_to_adr)
- def rtype_cast_ptr_to_adr(hop):
- vlist = hop.inputargs(hop.args_r[0])
- assert isinstance(vlist[0].concretetype, lltype.Ptr)
- hop.exception_cannot_occur()
- return hop.genop('cast_ptr_to_adr', vlist,
- resulttype=llmemory.Address)
- @typer_for(llmemory.cast_adr_to_ptr)
- def rtype_cast_adr_to_ptr(hop):
- assert isinstance(hop.args_r[0], raddress.AddressRepr)
- adr, TYPE = hop.inputargs(hop.args_r[0], lltype.Void)
- hop.exception_cannot_occur()
- return hop.genop('cast_adr_to_ptr', [adr],
- resulttype=TYPE.value)
- @typer_for(llmemory.cast_adr_to_int)
- def rtype_cast_adr_to_int(hop):
- assert isinstance(hop.args_r[0], raddress.AddressRepr)
- adr = hop.inputarg(hop.args_r[0], arg=0)
- if len(hop.args_s) == 1:
- mode = "emulated"
- else:
- mode = hop.args_s[1].const
- hop.exception_cannot_occur()
- return hop.genop('cast_adr_to_int',
- [adr, hop.inputconst(lltype.Void, mode)],
- resulttype=lltype.Signed)
- @typer_for(llmemory.cast_int_to_adr)
- def rtype_cast_int_to_adr(hop):
- v_input, = hop.inputargs(lltype.Signed)
- hop.exception_cannot_occur()
- return hop.genop('cast_int_to_adr', [v_input],
- resulttype=llmemory.Address)
- @typer_for(objectmodel.instantiate)
- def rtype_instantiate(hop, i_nonmovable=None):
- hop.exception_cannot_occur()
- s_class = hop.args_s[0]
- assert isinstance(s_class, annmodel.SomePBC)
- v_nonmovable, = parse_kwds(hop, (i_nonmovable, None))
- nonmovable = (i_nonmovable is not None and v_nonmovable.value)
- if len(s_class.descriptions) != 1:
- # instantiate() on a variable class
- if nonmovable:
- raise TyperError("instantiate(x, nonmovable=True) cannot be used "
- "if x is not a constant class")
- vtypeptr, = hop.inputargs(rclass.get_type_repr(hop.rtyper))
- r_class = hop.args_r[0]
- return r_class._instantiate_runtime_class(hop, vtypeptr,
- hop.r_result.lowleveltype)
- classdef = s_class.any_description().getuniqueclassdef()
- return rclass.rtype_new_instance(hop.rtyper, classdef, hop.llops,
- nonmovable=nonmovable)
- @typer_for(hasattr)
- def rtype_builtin_hasattr(hop):
- hop.exception_cannot_occur()
- if hop.s_result.is_constant():
- return hop.inputconst(lltype.Bool, hop.s_result.const)
- raise TyperError("hasattr is only suported on a constant")
- @typer_for(OrderedDict)
- @typer_for(objectmodel.r_dict)
- @typer_for(objectmodel.r_ordereddict)
- def rtype_dict_constructor(hop, i_force_non_null=None):
- # 'i_force_non_null' is ignored here; if it has any effect, it
- # has already been applied to 'hop.r_result'
- hop.exception_cannot_occur()
- r_dict = hop.r_result
- cDICT = hop.inputconst(lltype.Void, r_dict.DICT)
- v_result = hop.gendirectcall(r_dict.ll_newdict, cDICT)
- if r_dict.custom_eq_hash:
- v_eqfn = hop.inputarg(r_dict.r_rdict_eqfn, arg=0)
- v_hashfn = hop.inputarg(r_dict.r_rdict_hashfn, arg=1)
- if r_dict.r_rdict_eqfn.lowleveltype != lltype.Void:
- cname = hop.inputconst(lltype.Void, 'fnkeyeq')
- hop.genop('setfield', [v_result, cname, v_eqfn])
- if r_dict.r_rdict_hashfn.lowleveltype != lltype.Void:
- cname = hop.inputconst(lltype.Void, 'fnkeyhash')
- hop.genop('setfield', [v_result, cname, v_hashfn])
- return v_result
- # _________________________________________________________________
- # weakrefs
- import weakref
- from rpython.rtyper.lltypesystem import llmemory
- @typer_for(llmemory.weakref_create)
- @typer_for(weakref.ref)
- def rtype_weakref_create(hop):
- from rpython.rtyper.rweakref import BaseWeakRefRepr
- v_inst, = hop.inputargs(hop.args_r[0])
- hop.exception_cannot_occur()
- if isinstance(hop.r_result, BaseWeakRefRepr):
- return hop.r_result._weakref_create(hop, v_inst)
- else:
- # low-level <PtrRepr * WeakRef>
- assert hop.rtyper.getconfig().translation.rweakref
- return hop.genop('weakref_create', [v_inst],
- resulttype=llmemory.WeakRefPtr)
- @typer_for(llmemory.weakref_deref)
- def rtype_weakref_deref(hop):
- assert hop.rtyper.getconfig().translation.rweakref
- c_ptrtype, v_wref = hop.inputargs(lltype.Void, hop.args_r[1])
- assert v_wref.concretetype == llmemory.WeakRefPtr
- hop.exception_cannot_occur()
- return hop.genop('weakref_deref', [v_wref], resulttype=c_ptrtype.value)
- @typer_for(llmemory.cast_ptr_to_weakrefptr)
- def rtype_cast_ptr_to_weakrefptr(hop):
- assert hop.rtyper.getconfig().translation.rweakref
- vlist = hop.inputargs(hop.args_r[0])
- hop.exception_cannot_occur()
- return hop.genop('cast_ptr_to_weakrefptr', vlist,
- resulttype=llmemory.WeakRefPtr)
- @typer_for(llmemory.cast_weakrefptr_to_ptr)
- def rtype_cast_weakrefptr_to_ptr(hop):
- assert hop.rtyper.getconfig().translation.rweakref
- c_ptrtype, v_wref = hop.inputargs(lltype.Void, hop.args_r[1])
- assert v_wref.concretetype == llmemory.WeakRefPtr
- hop.exception_cannot_occur()
- return hop.genop('cast_weakrefptr_to_ptr', [v_wref],
- resulttype=c_ptrtype.value)