1
from pypy.objspace.flow.model import Constant
2
from pypy.rpython.rclass import getclassrepr, getinstancerepr, get_type_repr
3
from pypy.rpython.lltypesystem import lltype
4
from pypy.rpython.lltypesystem.rclass import InstanceRepr, CLASSTYPE
5
from pypy.rpython.lltypesystem.rclass import MissingRTypeAttribute
6
from pypy.rpython.lltypesystem.rclass import ll_issubclass_const
7
from pypy.rpython.rmodel import TyperError, inputconst
10
class TaggedInstanceRepr(InstanceRepr):
12
def __init__(self, rtyper, classdef, unboxedclassdef):
13
InstanceRepr.__init__(self, rtyper, classdef)
14
self.unboxedclassdef = unboxedclassdef
15
self.is_parent = unboxedclassdef is not classdef
17
def _setup_repr(self):
18
InstanceRepr._setup_repr(self)
19
flds = self.allinstancefields.keys()
20
flds.remove('__class__')
23
raise TyperError("%r is a base class of an UnboxedValue,"
24
"so it cannot have fields: %r" % (
28
raise TyperError("%r must have exactly one field: %r" % (
30
self.specialfieldname = flds[0]
32
def new_instance(self, llops, classcallhop=None):
34
raise TyperError("don't instantiate %r, it is a parent of an "
35
"UnboxedValue class" % (self.classdef,))
36
if classcallhop is None:
37
raise TyperError("must instantiate %r by calling the class" % (
40
if not (hop.spaceop.opname == 'simple_call' and hop.nb_args == 2):
41
raise TyperError("must instantiate %r with a simple class call" % (
43
v_value = hop.inputarg(lltype.Signed, arg=1)
44
c_one = hop.inputconst(lltype.Signed, 1)
45
hop.exception_is_here()
46
v2 = hop.genop('int_lshift_ovf', [v_value, c_one],
47
resulttype = lltype.Signed)
48
v2p1 = hop.genop('int_add', [v2, c_one],
49
resulttype = lltype.Signed)
50
v_instance = hop.genop('cast_int_to_ptr', [v2p1],
51
resulttype = self.lowleveltype)
52
return v_instance, False # don't call __init__
54
def convert_const_exact(self, value):
56
number = value.getvalue()
57
return ll_int_to_unboxed(self.lowleveltype, number)
59
def getvalue_from_unboxed(self, llops, vinst):
60
assert not self.is_parent
61
v2 = llops.genop('cast_ptr_to_int', [vinst], resulttype=lltype.Signed)
62
c_one = inputconst(lltype.Signed, 1)
63
return llops.genop('int_rshift', [v2, c_one], resulttype=lltype.Signed)
65
def gettype_from_unboxed(self, llops, vinst):
66
unboxedclass_repr = getclassrepr(self.rtyper, self.unboxedclassdef)
67
cunboxedcls = inputconst(CLASSTYPE, unboxedclass_repr.getvtable())
69
# If the lltype of vinst shows that it cannot be a tagged value,
70
# we can directly read the typeptr. Otherwise, call a helper that
71
# checks if the tag bit is set in the pointer.
72
unboxedinstance_repr = getinstancerepr(self.rtyper,
75
lltype.castable(unboxedinstance_repr.lowleveltype,
77
except lltype.InvalidCast:
81
vinst = llops.genop('cast_pointer', [vinst],
82
resulttype=self.common_repr())
84
return llops.gendirectcall(ll_unboxed_getclass, vinst,
87
ctypeptr = inputconst(lltype.Void, 'typeptr')
88
return llops.genop('getfield', [vinst, ctypeptr],
89
resulttype = CLASSTYPE)
93
def getfield(self, vinst, attr, llops, force_cast=False, flags={}):
94
if not self.is_parent and attr == self.specialfieldname:
95
return self.getvalue_from_unboxed(llops, vinst)
96
elif attr == '__class__':
97
return self.gettype_from_unboxed(llops, vinst)
99
raise MissingRTypeAttribute(attr)
101
def rtype_type(self, hop):
102
[vinst] = hop.inputargs(self)
103
return self.gettype_from_unboxed(hop.llops, vinst)
105
def rtype_setattr(self, hop):
106
# only for UnboxedValue.__init__(), which is not actually called
107
hop.genop('UnboxedValue_setattr', [])
110
if lltype.cast_ptr_to_int(i) & 1:
111
from pypy.rpython.lltypesystem import rstr
112
from pypy.rpython.rint import signed_repr
113
llstr1 = signed_repr.ll_str(ll_unboxed_to_int(i))
114
return rstr.ll_strconcat(rstr.unboxed_instance_str_prefix,
115
rstr.ll_strconcat(llstr1,
116
rstr.unboxed_instance_str_suffix))
118
return InstanceRepr.ll_str(self, i)
120
def rtype_isinstance(self, hop):
121
if not hop.args_s[1].is_constant():
122
raise TyperError("isinstance() too complicated")
123
[classdesc] = hop.args_s[1].descriptions
124
classdef = classdesc.getuniqueclassdef()
126
class_repr = get_type_repr(self.rtyper)
127
instance_repr = self.common_repr()
128
v_obj, v_cls = hop.inputargs(instance_repr, class_repr)
130
answer = self.unboxedclassdef.issubclass(classdef)
131
c_answer_if_unboxed = hop.inputconst(lltype.Bool, answer)
132
minid = hop.inputconst(lltype.Signed, cls.subclassrange_min)
133
maxid = hop.inputconst(lltype.Signed, cls.subclassrange_max)
134
return hop.gendirectcall(ll_unboxed_isinstance_const, v_obj,
135
minid, maxid, c_answer_if_unboxed)
138
def ll_int_to_unboxed(PTRTYPE, value):
139
return lltype.cast_int_to_ptr(PTRTYPE, value*2+1)
141
def ll_unboxed_to_int(p):
142
return lltype.cast_ptr_to_int(p) >> 1
144
def ll_unboxed_getclass(instance, class_if_unboxed):
145
if lltype.cast_ptr_to_int(instance) & 1:
146
return class_if_unboxed
148
return instance.typeptr
150
def ll_unboxed_isinstance_const(obj, minid, maxid, answer_if_unboxed):
153
if lltype.cast_ptr_to_int(obj) & 1:
154
return answer_if_unboxed
156
return ll_issubclass_const(obj.typeptr, minid, maxid)