~ubuntu-branches/ubuntu/karmic/pypy/karmic

« back to all changes in this revision

Viewing changes to pypy/rpython/rbuiltin.py

  • Committer: Bazaar Package Importer
  • Author(s): Alexandre Fayolle
  • Date: 2007-04-13 09:33:09 UTC
  • Revision ID: james.westby@ubuntu.com-20070413093309-yoojh4jcoocu2krz
Tags: upstream-1.0.0
ImportĀ upstreamĀ versionĀ 1.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
from pypy.annotation.pairtype import pairtype
 
2
from pypy.annotation import model as annmodel
 
3
from pypy.objspace.flow.model import Constant
 
4
from pypy.rpython.lltypesystem import lltype, rclass, llmemory
 
5
from pypy.rpython import rint, raddress
 
6
from pypy.rlib import rarithmetic, rstack, objectmodel
 
7
from pypy.rpython.error import TyperError
 
8
from pypy.rpython.rmodel import Repr, IntegerRepr, inputconst
 
9
from pypy.rpython.rrange import rtype_builtin_range, rtype_builtin_xrange
 
10
from pypy.rpython import rstr
 
11
from pypy.rpython import rptr
 
12
from pypy.rpython.robject import pyobj_repr
 
13
from pypy.tool import sourcetools
 
14
from pypy.rpython import extregistry
 
15
 
 
16
class __extend__(annmodel.SomeBuiltin):
 
17
    def rtyper_makerepr(self, rtyper):
 
18
        if self.s_self is None:
 
19
            # built-in function case
 
20
            if not self.is_constant():
 
21
                raise TyperError("non-constant built-in function!")
 
22
            return BuiltinFunctionRepr(self.const)
 
23
        else:
 
24
            # built-in method case
 
25
            assert self.methodname is not None
 
26
            result = BuiltinMethodRepr(rtyper, self.s_self, self.methodname)
 
27
            if result.self_repr == pyobj_repr:
 
28
                return pyobj_repr   # special case: methods of 'PyObject*'
 
29
            else:
 
30
                return result
 
31
    def rtyper_makekey(self):
 
32
        if self.s_self is None:
 
33
            # built-in function case
 
34
 
 
35
            const = getattr(self, 'const', None)
 
36
 
 
37
            if extregistry.is_registered(const):
 
38
                const = extregistry.lookup(const)
 
39
 
 
40
            return self.__class__, const
 
41
        else:
 
42
            # built-in method case
 
43
            # NOTE: we hash by id of self.s_self here.  This appears to be
 
44
            # necessary because it ends up in hop.args_s[0] in the method call,
 
45
            # and there is no telling what information the called
 
46
            # rtype_method_xxx() will read from that hop.args_s[0].
 
47
            # See test_method_join in test_rbuiltin.
 
48
            # There is no problem with self.s_self being garbage-collected and
 
49
            # its id reused, because the BuiltinMethodRepr keeps a reference
 
50
            # to it.
 
51
            return (self.__class__, self.methodname, id(self.s_self))
 
52
 
 
53
def call_args_expand(hop, takes_kwds = True):
 
54
    hop = hop.copy()
 
55
    from pypy.interpreter.argument import Arguments
 
56
    arguments = Arguments.fromshape(None, hop.args_s[1].const, # shape
 
57
                                    range(hop.nb_args-2))
 
58
    if arguments.w_starstararg is not None:
 
59
        raise TyperError("**kwds call not implemented")
 
60
    if arguments.w_stararg is not None:
 
61
        # expand the *arg in-place -- it must be a tuple
 
62
        from pypy.rpython.rtuple import AbstractTupleRepr
 
63
        if arguments.w_stararg != hop.nb_args - 3:
 
64
            raise TyperError("call pattern too complex")
 
65
        hop.nb_args -= 1
 
66
        v_tuple = hop.args_v.pop()
 
67
        s_tuple = hop.args_s.pop()
 
68
        r_tuple = hop.args_r.pop()
 
69
        if not isinstance(r_tuple, AbstractTupleRepr):
 
70
            raise TyperError("*arg must be a tuple")
 
71
        for i in range(len(r_tuple.items_r)):
 
72
            v_item = r_tuple.getitem_internal(hop.llops, v_tuple, i)
 
73
            hop.nb_args += 1
 
74
            hop.args_v.append(v_item)
 
75
            hop.args_s.append(s_tuple.items[i])
 
76
            hop.args_r.append(r_tuple.items_r[i])
 
77
 
 
78
    kwds = arguments.kwds_w or {}
 
79
    if not takes_kwds and kwds:
 
80
        raise TyperError("kwds args not supported")
 
81
    # prefix keyword arguments with 'i_'
 
82
    kwds_i = {}
 
83
    for key, index in kwds.items():
 
84
        kwds_i['i_'+key] = index
 
85
 
 
86
    return hop, kwds_i
 
87
 
 
88
 
 
89
class BuiltinFunctionRepr(Repr):
 
90
    lowleveltype = lltype.Void
 
91
 
 
92
    def __init__(self, builtinfunc):
 
93
        self.builtinfunc = builtinfunc
 
94
 
 
95
    def findbltintyper(self, rtyper):
 
96
        "Find the function to use to specialize calls to this built-in func."
 
97
        try:
 
98
            return BUILTIN_TYPER[self.builtinfunc]
 
99
        except (KeyError, TypeError):
 
100
            pass
 
101
        try:
 
102
            return rtyper.type_system.rbuiltin.BUILTIN_TYPER[self.builtinfunc]
 
103
        except (KeyError, TypeError):
 
104
            pass
 
105
        if extregistry.is_registered(self.builtinfunc):
 
106
            entry = extregistry.lookup(self.builtinfunc)
 
107
            return entry.specialize_call
 
108
        raise TyperError("don't know about built-in function %r" % (
 
109
            self.builtinfunc,))
 
110
 
 
111
    def rtype_simple_call(self, hop):
 
112
        bltintyper = self.findbltintyper(hop.rtyper)
 
113
        hop2 = hop.copy()
 
114
        hop2.r_s_popfirstarg()
 
115
        return bltintyper(hop2)
 
116
 
 
117
    def rtype_call_args(self, hop):
 
118
        # calling a built-in function with keyword arguments:
 
119
        # mostly for rpython.objectmodel.hint() and for constructing
 
120
        # rctypes structures
 
121
        hop, kwds_i = call_args_expand(hop)
 
122
 
 
123
        bltintyper = self.findbltintyper(hop.rtyper)
 
124
        hop2 = hop.copy()
 
125
        hop2.r_s_popfirstarg()
 
126
        hop2.r_s_popfirstarg()
 
127
        # the RPython-level keyword args are passed with an 'i_' prefix and
 
128
        # the corresponding value is an *index* in the hop2 arguments,
 
129
        # to be used with hop.inputarg(arg=..)
 
130
        return bltintyper(hop2, **kwds_i)
 
131
 
 
132
 
 
133
class BuiltinMethodRepr(Repr):
 
134
 
 
135
    def __init__(self, rtyper, s_self, methodname):
 
136
        self.s_self = s_self
 
137
        self.self_repr = rtyper.getrepr(s_self)
 
138
        self.methodname = methodname
 
139
        # methods of a known name are implemented as just their 'self'
 
140
        self.lowleveltype = self.self_repr.lowleveltype
 
141
 
 
142
    def convert_const(self, obj):
 
143
        return self.self_repr.convert_const(get_builtin_method_self(obj))
 
144
 
 
145
    def rtype_simple_call(self, hop):
 
146
        # methods: look up the rtype_method_xxx()
 
147
        name = 'rtype_method_' + self.methodname
 
148
        try:
 
149
            bltintyper = getattr(self.self_repr, name)
 
150
        except AttributeError:
 
151
            raise TyperError("missing %s.%s" % (
 
152
                self.self_repr.__class__.__name__, name))
 
153
        # hack based on the fact that 'lowleveltype == self_repr.lowleveltype'
 
154
        hop2 = hop.copy()
 
155
        assert hop2.args_r[0] is self
 
156
        if isinstance(hop2.args_v[0], Constant):
 
157
            c = hop2.args_v[0].value    # get object from bound method
 
158
            c = get_builtin_method_self(c)
 
159
            hop2.args_v[0] = Constant(c)
 
160
        hop2.args_s[0] = self.s_self
 
161
        hop2.args_r[0] = self.self_repr
 
162
        return bltintyper(hop2)
 
163
 
 
164
class __extend__(pairtype(BuiltinMethodRepr, BuiltinMethodRepr)):
 
165
    def convert_from_to((r_from, r_to), v, llops):
 
166
        # convert between two MethodReprs only if they are about the same
 
167
        # methodname.  (Useful for the case r_from.s_self == r_to.s_self but
 
168
        # r_from is not r_to.)  See test_rbuiltin.test_method_repr.
 
169
        if r_from.methodname != r_to.methodname:
 
170
            return NotImplemented
 
171
        return llops.convertvar(v, r_from.self_repr, r_to.self_repr)
 
172
 
 
173
def parse_kwds(hop, *argspec_i_r):
 
174
    lst = [i for (i, r) in argspec_i_r if i is not None]
 
175
    lst.sort()
 
176
    if lst != range(hop.nb_args - len(lst), hop.nb_args):
 
177
        raise TyperError("keyword args are expected to be at the end of "
 
178
                         "the 'hop' arg list")
 
179
    result = []
 
180
    for i, r in argspec_i_r:
 
181
        if i is not None:
 
182
            if r is None:
 
183
                r = hop.args_r[i]
 
184
            result.append(hop.inputarg(r, arg=i))
 
185
        else:
 
186
            result.append(None)
 
187
    hop.nb_args -= len(lst)
 
188
    return result
 
189
 
 
190
def get_builtin_method_self(x):
 
191
    try:
 
192
        return x.__self__   # on top of CPython
 
193
    except AttributeError:
 
194
        return x.im_self    # on top of PyPy
 
195
 
 
196
# ____________________________________________________________
 
197
 
 
198
def rtype_builtin_bool(hop):
 
199
    assert hop.nb_args == 1
 
200
    return hop.args_r[0].rtype_is_true(hop)
 
201
 
 
202
def rtype_builtin_int(hop):
 
203
    if isinstance(hop.args_s[0], annmodel.SomeString):
 
204
        assert 1 <= hop.nb_args <= 2
 
205
        return hop.args_r[0].rtype_int(hop)
 
206
    assert hop.nb_args == 1
 
207
    return hop.args_r[0].rtype_int(hop)
 
208
 
 
209
def rtype_builtin_float(hop):
 
210
    assert hop.nb_args == 1
 
211
    return hop.args_r[0].rtype_float(hop)
 
212
 
 
213
def rtype_builtin_chr(hop):
 
214
    assert hop.nb_args == 1
 
215
    return hop.args_r[0].rtype_chr(hop)
 
216
 
 
217
def rtype_builtin_unichr(hop):
 
218
    assert hop.nb_args == 1
 
219
    return hop.args_r[0].rtype_unichr(hop)
 
220
 
 
221
def rtype_builtin_list(hop):
 
222
    return hop.args_r[0].rtype_bltn_list(hop)
 
223
 
 
224
#def rtype_builtin_range(hop): see rrange.py
 
225
 
 
226
#def rtype_builtin_xrange(hop): see rrange.py
 
227
 
 
228
#def rtype_r_dict(hop): see rdict.py
 
229
 
 
230
def rtype_intmask(hop):
 
231
    hop.exception_cannot_occur()
 
232
    vlist = hop.inputargs(lltype.Signed)
 
233
    return vlist[0]
 
234
 
 
235
def rtype_builtin_min(hop):
 
236
    rint1, rint2 = hop.args_r
 
237
    assert isinstance(rint1, IntegerRepr)
 
238
    assert isinstance(rint2, IntegerRepr)
 
239
    assert rint1.lowleveltype == rint2.lowleveltype
 
240
    v1, v2 = hop.inputargs(rint1, rint2)
 
241
    return hop.gendirectcall(ll_min, v1, v2)
 
242
 
 
243
def ll_min(i1, i2):
 
244
    if i1 < i2:
 
245
        return i1
 
246
    return i2
 
247
 
 
248
def rtype_builtin_max(hop):
 
249
    rint1, rint2 = hop.args_r
 
250
    assert isinstance(rint1, IntegerRepr)
 
251
    assert isinstance(rint2, IntegerRepr)
 
252
    assert rint1.lowleveltype == rint2.lowleveltype
 
253
    v1, v2 = hop.inputargs(rint1, rint2)
 
254
    return hop.gendirectcall(ll_max, v1, v2)
 
255
 
 
256
def ll_max(i1, i2):
 
257
    if i1 > i2:
 
258
        return i1
 
259
    return i2
 
260
 
 
261
def rtype_Exception__init__(hop):
 
262
    pass
 
263
 
 
264
def rtype_object__init__(hop):
 
265
    pass
 
266
 
 
267
def rtype_OSError__init__(hop):
 
268
    if hop.nb_args == 2:
 
269
        raise TyperError("OSError() should not be called with "
 
270
                         "a single argument")
 
271
    if hop.nb_args >= 3:
 
272
        v_self = hop.args_v[0]
 
273
        r_self = hop.args_r[0]
 
274
        v_errno = hop.inputarg(lltype.Signed, arg=1)
 
275
        r_self.setfield(v_self, 'errno', v_errno, hop.llops)
 
276
 
 
277
def rtype_we_are_translated(hop):
 
278
    hop.exception_cannot_occur()
 
279
    return hop.inputconst(lltype.Bool, True)
 
280
 
 
281
def rtype_yield_current_frame_to_caller(hop):
 
282
    return hop.genop('yield_current_frame_to_caller', [],
 
283
                     resulttype=hop.r_result)
 
284
 
 
285
def rtype_hlinvoke(hop):
 
286
    _, s_repr = hop.r_s_popfirstarg()
 
287
    r_callable = s_repr.const
 
288
 
 
289
    r_func, nimplicitarg = r_callable.get_r_implfunc()
 
290
    s_callable = r_callable.get_s_callable()
 
291
 
 
292
    nbargs = len(hop.args_s) - 1 + nimplicitarg 
 
293
    s_sigs = r_func.get_s_signatures((nbargs, (), False, False))
 
294
    if len(s_sigs) != 1:
 
295
        raise TyperError("cannot hlinvoke callable %r with not uniform"
 
296
                         "annotations: %r" % (r_callable,
 
297
                                              s_sigs))
 
298
    args_s, s_ret = s_sigs[0]
 
299
    rinputs = [hop.rtyper.getrepr(s_obj) for s_obj in args_s]
 
300
    rresult = hop.rtyper.getrepr(s_ret)
 
301
 
 
302
    args_s = args_s[nimplicitarg:]
 
303
    rinputs = rinputs[nimplicitarg:]
 
304
 
 
305
    new_args_r = [r_callable] + rinputs
 
306
 
 
307
    for i in range(len(new_args_r)):
 
308
        assert hop.args_r[i].lowleveltype == new_args_r[i].lowleveltype
 
309
 
 
310
    hop.args_r = new_args_r
 
311
    hop.args_s = [s_callable] + args_s
 
312
 
 
313
    hop.s_result = s_ret
 
314
    assert hop.r_result.lowleveltype == rresult.lowleveltype
 
315
    hop.r_result = rresult
 
316
 
 
317
    return hop.dispatch()
 
318
 
 
319
 
 
320
# collect all functions
 
321
import __builtin__, exceptions
 
322
BUILTIN_TYPER = {}
 
323
for name, value in globals().items():
 
324
    if name.startswith('rtype_builtin_'):
 
325
        original = getattr(__builtin__, name[14:])
 
326
        BUILTIN_TYPER[original] = value
 
327
 
 
328
BUILTIN_TYPER[getattr(OSError.__init__, 'im_func', OSError.__init__)] = (
 
329
    rtype_OSError__init__)
 
330
 
 
331
BUILTIN_TYPER[object.__init__] = rtype_object__init__
 
332
# annotation of low-level types
 
333
 
 
334
def rtype_malloc(hop, i_flavor=None, i_extra_args=None, i_zero=None):
 
335
    assert hop.args_s[0].is_constant()
 
336
    vlist = [hop.inputarg(lltype.Void, arg=0)]
 
337
    opname = 'malloc'
 
338
    v_flavor, v_extra_args, v_zero = parse_kwds(hop, (i_flavor, lltype.Void),
 
339
                                                     (i_extra_args, None),
 
340
                                                     (i_zero, None))
 
341
    if v_flavor is not None:
 
342
        vlist.insert(0, v_flavor)
 
343
        opname = 'flavored_' + opname
 
344
    if i_zero is not None:
 
345
        assert i_extra_args is i_flavor is None
 
346
        opname = 'zero_' + opname
 
347
    if hop.nb_args == 2:
 
348
        vlist.append(hop.inputarg(lltype.Signed, arg=1))
 
349
        opname += '_varsize'
 
350
 
 
351
    if v_extra_args is not None:
 
352
        # items of the v_extra_args tuple become additional args to the op
 
353
        from pypy.rpython.rtuple import AbstractTupleRepr
 
354
        r_tup = hop.args_r[i_extra_args]
 
355
        assert isinstance(r_tup, AbstractTupleRepr)
 
356
        for n, r in enumerate(r_tup.items_r):
 
357
            v = r_tup.getitem(hop.llops, v_extra_args, n)
 
358
            vlist.append(v)
 
359
 
 
360
    return hop.genop(opname, vlist, resulttype = hop.r_result.lowleveltype)
 
361
 
 
362
def rtype_free(hop, i_flavor):
 
363
    assert i_flavor == 1
 
364
    vlist = hop.inputargs(hop.args_r[0], lltype.Void)
 
365
    vlist.reverse()   # just for confusion
 
366
    hop.genop('flavored_free', vlist)
 
367
 
 
368
def rtype_const_result(hop):
 
369
    return hop.inputconst(hop.r_result.lowleveltype, hop.s_result.const)
 
370
 
 
371
def rtype_cast_pointer(hop):
 
372
    assert hop.args_s[0].is_constant()
 
373
    assert isinstance(hop.args_r[1], rptr.PtrRepr)
 
374
    v_type, v_input = hop.inputargs(lltype.Void, hop.args_r[1])
 
375
    hop.exception_cannot_occur()
 
376
    return hop.genop('cast_pointer', [v_input],    # v_type implicit in r_result
 
377
                     resulttype = hop.r_result.lowleveltype)
 
378
 
 
379
def rtype_cast_opaque_ptr(hop):
 
380
    assert hop.args_s[0].is_constant()
 
381
    assert isinstance(hop.args_r[1], rptr.PtrRepr)
 
382
    v_type, v_input = hop.inputargs(lltype.Void, hop.args_r[1])
 
383
    hop.exception_cannot_occur()
 
384
    return hop.genop('cast_opaque_ptr', [v_input], # v_type implicit in r_result
 
385
                     resulttype = hop.r_result.lowleveltype)
 
386
 
 
387
def rtype_direct_fieldptr(hop):
 
388
    assert isinstance(hop.args_r[0], rptr.PtrRepr)
 
389
    assert hop.args_s[1].is_constant()
 
390
    vlist = hop.inputargs(hop.args_r[0], lltype.Void)
 
391
    hop.exception_cannot_occur()
 
392
    return hop.genop('direct_fieldptr', vlist,
 
393
                     resulttype=hop.r_result.lowleveltype)
 
394
 
 
395
def rtype_direct_arrayitems(hop):
 
396
    assert isinstance(hop.args_r[0], rptr.PtrRepr)
 
397
    vlist = hop.inputargs(hop.args_r[0])
 
398
    hop.exception_cannot_occur()
 
399
    return hop.genop('direct_arrayitems', vlist,
 
400
                     resulttype=hop.r_result.lowleveltype)
 
401
 
 
402
def rtype_direct_ptradd(hop):
 
403
    assert isinstance(hop.args_r[0], rptr.PtrRepr)
 
404
    vlist = hop.inputargs(hop.args_r[0], lltype.Signed)
 
405
    hop.exception_cannot_occur()
 
406
    return hop.genop('direct_ptradd', vlist,
 
407
                     resulttype=hop.r_result.lowleveltype)
 
408
 
 
409
def rtype_cast_primitive(hop):
 
410
    assert hop.args_s[0].is_constant()
 
411
    TGT = hop.args_s[0].const
 
412
    v_type, v_value = hop.inputargs(lltype.Void, hop.args_r[1])
 
413
    return gen_cast(hop.llops, TGT, v_value)
 
414
 
 
415
_cast_to_Signed = {
 
416
    lltype.Signed:   None,
 
417
    lltype.Bool:     'cast_bool_to_int',
 
418
    lltype.Char:     'cast_char_to_int',
 
419
    lltype.UniChar:  'cast_unichar_to_int',
 
420
    lltype.Float:    'cast_float_to_int',
 
421
    lltype.Unsigned: 'cast_uint_to_int',
 
422
    }
 
423
_cast_from_Signed = {
 
424
    lltype.Signed:   None,
 
425
    lltype.Bool:     'int_is_true',
 
426
    lltype.Char:     'cast_int_to_char',
 
427
    lltype.UniChar:  'cast_int_to_unichar',
 
428
    lltype.Float:    'cast_int_to_float',
 
429
    lltype.Unsigned: 'cast_int_to_uint',
 
430
    }
 
431
def gen_cast(llops, TGT, v_value):
 
432
    ORIG = v_value.concretetype
 
433
    if ORIG == TGT:
 
434
        return v_value
 
435
    if (isinstance(TGT, lltype.Primitive) and
 
436
        isinstance(ORIG, lltype.Primitive)):
 
437
        if ORIG in _cast_to_Signed and TGT in _cast_from_Signed:
 
438
            op = _cast_to_Signed[ORIG]
 
439
            if op:
 
440
                v_value = llops.genop(op, [v_value], resulttype=lltype.Signed)
 
441
            op = _cast_from_Signed[TGT]
 
442
            if op:
 
443
                v_value = llops.genop(op, [v_value], resulttype=TGT)
 
444
            return v_value
 
445
        else:
 
446
            # use the generic operation if there is no alternative
 
447
            return llops.genop('cast_primitive', [v_value], resulttype=TGT)
 
448
    elif isinstance(TGT, lltype.Ptr):
 
449
        if isinstance(ORIG, lltype.Ptr):
 
450
            if (isinstance(TGT.TO, lltype.OpaqueType) or
 
451
                isinstance(ORIG.TO, lltype.OpaqueType)):
 
452
                return llops.genop('cast_opaque_ptr', [v_value],
 
453
                                                              resulttype = TGT)
 
454
            else:
 
455
                return llops.genop('cast_pointer', [v_value], resulttype = TGT)
 
456
        elif ORIG == llmemory.Address:
 
457
            return llops.genop('cast_adr_to_ptr', [v_value], resulttype = TGT)
 
458
    elif TGT == llmemory.Address and isinstance(ORIG, lltype.Ptr):
 
459
        return llops.genop('cast_ptr_to_adr', [v_value], resulttype = TGT)
 
460
    raise TypeError("don't know how to cast from %r to %r" % (ORIG, TGT))
 
461
 
 
462
def rtype_cast_ptr_to_int(hop):
 
463
    assert isinstance(hop.args_r[0], rptr.PtrRepr)
 
464
    vlist = hop.inputargs(hop.args_r[0])
 
465
    hop.exception_cannot_occur()
 
466
    return hop.genop('cast_ptr_to_int', vlist,
 
467
                     resulttype = lltype.Signed)
 
468
 
 
469
def rtype_cast_int_to_ptr(hop):
 
470
    assert hop.args_s[0].is_constant()
 
471
    v_type, v_input = hop.inputargs(lltype.Void, lltype.Signed)
 
472
    hop.exception_cannot_occur()
 
473
    return hop.genop('cast_int_to_ptr', [v_input],
 
474
                     resulttype = hop.r_result.lowleveltype)
 
475
 
 
476
def rtype_runtime_type_info(hop):
 
477
    assert isinstance(hop.args_r[0], rptr.PtrRepr)
 
478
    vlist = hop.inputargs(hop.args_r[0])
 
479
    return hop.genop('runtime_type_info', vlist,
 
480
                     resulttype = hop.r_result.lowleveltype)
 
481
 
 
482
BUILTIN_TYPER[lltype.malloc] = rtype_malloc
 
483
BUILTIN_TYPER[lltype.free] = rtype_free
 
484
BUILTIN_TYPER[lltype.cast_primitive] = rtype_cast_primitive
 
485
BUILTIN_TYPER[lltype.cast_pointer] = rtype_cast_pointer
 
486
BUILTIN_TYPER[lltype.cast_opaque_ptr] = rtype_cast_opaque_ptr
 
487
BUILTIN_TYPER[lltype.direct_fieldptr] = rtype_direct_fieldptr
 
488
BUILTIN_TYPER[lltype.direct_arrayitems] = rtype_direct_arrayitems
 
489
BUILTIN_TYPER[lltype.direct_ptradd] = rtype_direct_ptradd
 
490
BUILTIN_TYPER[lltype.cast_ptr_to_int] = rtype_cast_ptr_to_int
 
491
BUILTIN_TYPER[lltype.cast_int_to_ptr] = rtype_cast_int_to_ptr
 
492
BUILTIN_TYPER[lltype.typeOf] = rtype_const_result
 
493
BUILTIN_TYPER[lltype.nullptr] = rtype_const_result
 
494
BUILTIN_TYPER[lltype.getRuntimeTypeInfo] = rtype_const_result
 
495
BUILTIN_TYPER[lltype.Ptr] = rtype_const_result
 
496
BUILTIN_TYPER[lltype.runtime_type_info] = rtype_runtime_type_info
 
497
BUILTIN_TYPER[rarithmetic.intmask] = rtype_intmask
 
498
BUILTIN_TYPER[objectmodel.we_are_translated] = rtype_we_are_translated
 
499
BUILTIN_TYPER[rstack.yield_current_frame_to_caller] = (
 
500
    rtype_yield_current_frame_to_caller)
 
501
 
 
502
BUILTIN_TYPER[objectmodel.hlinvoke] = rtype_hlinvoke
 
503
 
 
504
from pypy.rpython import extfunctable
 
505
 
 
506
def rnormalize(rtyper, r):
 
507
    # this replaces char_repr with string_repr, because so far we have
 
508
    # no external function expecting a char, but only external functions
 
509
    # that happily crash if passed a char instead of a string
 
510
    if r == rtyper.type_system.rstr.char_repr:
 
511
        r = rtyper.type_system.rstr.string_repr
 
512
    return r
 
513
 
 
514
def make_rtype_extfunc(extfuncinfo):
 
515
    if extfuncinfo.ll_annotable:
 
516
        def rtype_extfunc(hop):
 
517
            ll_function = extfuncinfo.get_ll_function(hop.rtyper.type_system)
 
518
            vars = hop.inputargs(*[rnormalize(hop.rtyper, r)
 
519
                                   for r in hop.args_r])
 
520
            hop.exception_is_here()
 
521
            return hop.gendirectcall(ll_function, *vars)
 
522
    else:
 
523
        def rtype_extfunc(hop):
 
524
            ll_function = extfuncinfo.get_ll_function(hop.rtyper.type_system)
 
525
            resulttype = hop.r_result
 
526
            vars = hop.inputargs(*[rnormalize(hop.rtyper, r)
 
527
                                   for r in hop.args_r])
 
528
            hop.exception_is_here()
 
529
            return hop.llops.genexternalcall(ll_function.__name__, vars, resulttype=resulttype,
 
530
                                             _callable = ll_function)
 
531
            
 
532
    if extfuncinfo.func is not None:
 
533
        rtype_extfunc = sourcetools.func_with_new_name(rtype_extfunc,
 
534
            "rtype_extfunc_%s" % extfuncinfo.func.__name__)
 
535
    return rtype_extfunc
 
536
 
 
537
 
 
538
def update_exttable():
 
539
    """import rtyping information for external functions 
 
540
    from the extfunctable.table  into our own specific table
 
541
    """
 
542
    for func, extfuncinfo in extfunctable.table.iteritems():
 
543
        if func not in BUILTIN_TYPER:
 
544
            BUILTIN_TYPER[func] = make_rtype_extfunc(extfuncinfo)
 
545
 
 
546
# Note: calls to declare() may occur after rbuiltin.py is first imported.
 
547
# We must track future changes to the extfunctable.
 
548
extfunctable.table_callbacks.append(update_exttable)
 
549
update_exttable()
 
550
 
 
551
 
 
552
# _________________________________________________________________
 
553
# memory addresses
 
554
 
 
555
from pypy.rpython.memory import lladdress
 
556
from pypy.rpython.lltypesystem import llmemory
 
557
 
 
558
def rtype_raw_malloc(hop):
 
559
    v_size, = hop.inputargs(lltype.Signed)
 
560
    return hop.genop('raw_malloc', [v_size], resulttype=llmemory.Address)
 
561
 
 
562
def rtype_raw_malloc_usage(hop):
 
563
    v_size, = hop.inputargs(lltype.Signed)
 
564
    hop.exception_cannot_occur()
 
565
    return hop.genop('raw_malloc_usage', [v_size], resulttype=lltype.Signed)
 
566
 
 
567
def rtype_raw_free(hop):
 
568
    v_addr, = hop.inputargs(llmemory.Address)
 
569
    return hop.genop('raw_free', [v_addr])
 
570
 
 
571
def rtype_raw_memcopy(hop):
 
572
    v_list = hop.inputargs(llmemory.Address, llmemory.Address, lltype.Signed)
 
573
    return hop.genop('raw_memcopy', v_list)
 
574
 
 
575
def rtype_raw_memclear(hop):
 
576
    v_list = hop.inputargs(llmemory.Address, lltype.Signed)
 
577
    return hop.genop('raw_memclear', v_list)
 
578
 
 
579
BUILTIN_TYPER[lladdress.raw_malloc] = rtype_raw_malloc
 
580
BUILTIN_TYPER[lladdress.raw_malloc_usage] = rtype_raw_malloc_usage
 
581
BUILTIN_TYPER[lladdress.raw_free] = rtype_raw_free
 
582
BUILTIN_TYPER[lladdress.raw_memclear] = rtype_raw_memclear
 
583
BUILTIN_TYPER[lladdress.raw_memcopy] = rtype_raw_memcopy
 
584
 
 
585
BUILTIN_TYPER[llmemory.raw_malloc] = rtype_raw_malloc
 
586
BUILTIN_TYPER[llmemory.raw_malloc_usage] = rtype_raw_malloc_usage
 
587
BUILTIN_TYPER[llmemory.raw_free] = rtype_raw_free
 
588
BUILTIN_TYPER[llmemory.raw_memclear] = rtype_raw_memclear
 
589
BUILTIN_TYPER[llmemory.raw_memcopy] = rtype_raw_memcopy
 
590
 
 
591
def rtype_offsetof(hop):
 
592
    TYPE, field = hop.inputargs(lltype.Void, lltype.Void)
 
593
    return hop.inputconst(lltype.Signed,
 
594
                          llmemory.offsetof(TYPE.value, field.value))
 
595
 
 
596
BUILTIN_TYPER[llmemory.offsetof] = rtype_offsetof
 
597
 
 
598
# _________________________________________________________________
 
599
# non-gc objects
 
600
 
 
601
def rtype_free_non_gc_object(hop):
 
602
    vinst, = hop.inputargs(hop.args_r[0])
 
603
    flavor = hop.args_r[0].gcflavor
 
604
    assert not flavor.startswith('gc')
 
605
    cflavor = hop.inputconst(lltype.Void, flavor)
 
606
    return hop.genop('flavored_free', [cflavor, vinst])
 
607
    
 
608
BUILTIN_TYPER[objectmodel.free_non_gc_object] = rtype_free_non_gc_object
 
609
 
 
610
# keepalive_until_here
 
611
 
 
612
def rtype_keepalive_until_here(hop):
 
613
    for v in hop.args_v:
 
614
        hop.genop('keepalive', [v], resulttype=lltype.Void)
 
615
    return hop.inputconst(lltype.Void, None)
 
616
 
 
617
BUILTIN_TYPER[objectmodel.keepalive_until_here] = rtype_keepalive_until_here
 
618
 
 
619
def rtype_cast_ptr_to_adr(hop):
 
620
    vlist = hop.inputargs(hop.args_r[0])
 
621
    assert isinstance(vlist[0].concretetype, lltype.Ptr)
 
622
    hop.exception_cannot_occur()
 
623
    return hop.genop('cast_ptr_to_adr', vlist,
 
624
                     resulttype = llmemory.Address)
 
625
 
 
626
def rtype_cast_adr_to_ptr(hop):
 
627
    assert isinstance(hop.args_r[0], raddress.AddressRepr)
 
628
    adr, TYPE = hop.inputargs(hop.args_r[0], lltype.Void)
 
629
    hop.exception_cannot_occur()
 
630
    return hop.genop('cast_adr_to_ptr', [adr],
 
631
                     resulttype = TYPE.value)
 
632
 
 
633
def rtype_cast_adr_to_int(hop):
 
634
    assert isinstance(hop.args_r[0], raddress.AddressRepr)
 
635
    adr, = hop.inputargs(hop.args_r[0])
 
636
    hop.exception_cannot_occur()
 
637
    return hop.genop('cast_adr_to_int', [adr],
 
638
                     resulttype = lltype.Signed)
 
639
 
 
640
def rtype_cast_int_to_adr(hop):
 
641
    v_input, = hop.inputargs(lltype.Signed)
 
642
    hop.exception_cannot_occur()
 
643
    return hop.genop('cast_int_to_adr', [v_input],
 
644
                     resulttype = llmemory.Address)
 
645
 
 
646
def rtype_cast_ptr_to_weakadr(hop):
 
647
    vlist = hop.inputargs(hop.args_r[0])
 
648
    assert isinstance(vlist[0].concretetype, lltype.Ptr)
 
649
    hop.exception_cannot_occur()
 
650
    return hop.genop('cast_ptr_to_weakadr', vlist,
 
651
                     resulttype = llmemory.WeakGcAddress)
 
652
 
 
653
def rtype_cast_weakadr_to_ptr(hop):
 
654
    assert isinstance(hop.args_r[0], raddress.WeakGcAddressRepr)
 
655
    adr, TYPE = hop.inputargs(hop.args_r[0], lltype.Void)
 
656
    hop.exception_cannot_occur()
 
657
    return hop.genop('cast_weakadr_to_ptr', [adr],
 
658
                     resulttype = TYPE.value)
 
659
 
 
660
BUILTIN_TYPER[llmemory.cast_ptr_to_adr] = rtype_cast_ptr_to_adr
 
661
BUILTIN_TYPER[llmemory.cast_adr_to_ptr] = rtype_cast_adr_to_ptr
 
662
BUILTIN_TYPER[llmemory.cast_adr_to_int] = rtype_cast_adr_to_int
 
663
BUILTIN_TYPER[llmemory.cast_int_to_adr] = rtype_cast_int_to_adr
 
664
BUILTIN_TYPER[llmemory.cast_ptr_to_weakadr] = rtype_cast_ptr_to_weakadr
 
665
BUILTIN_TYPER[llmemory.cast_weakadr_to_ptr] = rtype_cast_weakadr_to_ptr
 
666