Read about our upcoming Code of Conduct on this issue

rffi.py 57.8 KB
Newer Older
Armin Rigo's avatar
Armin Rigo committed
1
import py
Alexander Hesse's avatar
Alexander Hesse committed
2
from rpython.annotator import model as annmodel
3
from rpython.rtyper.llannotation import SomePtr
4
from rpython.rtyper.lltypesystem import lltype
Alexander Hesse's avatar
Alexander Hesse committed
5
from rpython.rtyper.lltypesystem import ll2ctypes
Alexander Hesse's avatar
Alexander Hesse committed
6
from rpython.rtyper.lltypesystem.llmemory import cast_ptr_to_adr
7
from rpython.rtyper.lltypesystem.llmemory import itemoffsetof
8
from rpython.rtyper.llannotation import lltype_to_annotation
9
from rpython.tool.sourcetools import func_with_new_name
10
from rpython.rlib.objectmodel import Symbolic, specialize, not_rpython
Alexander Hesse's avatar
Alexander Hesse committed
11
from rpython.rlib.objectmodel import keepalive_until_here, enforceargs
Alexander Hesse's avatar
Alexander Hesse committed
12
13
14
15
16
from rpython.rlib import rarithmetic, rgc
from rpython.rtyper.extregistry import ExtRegistryEntry
from rpython.rlib.unroll import unrolling_iterable
from rpython.rtyper.tool.rfficache import platform, sizeof_c_type
from rpython.translator.tool.cbuild import ExternalCompilationInfo
Alexander Hesse's avatar
Alexander Hesse committed
17
from rpython.rtyper.annlowlevel import llhelper
Armin Rigo's avatar
fix    
Armin Rigo committed
18
from rpython.rlib.objectmodel import we_are_translated, we_are_translated_to_c
Alexander Hesse's avatar
Alexander Hesse committed
19
20
21
22
23
from rpython.rlib.rstring import StringBuilder, UnicodeBuilder, assert_str0
from rpython.rlib import jit
from rpython.rtyper.lltypesystem import llmemory
from rpython.rlib.rarithmetic import maxint, LONG_BIT
from rpython.translator.platform import CompilationError
24
import os, sys
25
26
27
28
29
30
31
32

class CConstant(Symbolic):
    """ A C-level constant, maybe #define, rendered directly.
    """
    def __init__(self, c_name, TP):
        self.c_name = c_name
        self.TP = TP

33
34
35
36
    def __repr__(self):
        return '%s(%r, %s)' % (self.__class__.__name__,
                               self.c_name, self.TP)

37
38
39
40
41
42
    def annotation(self):
        return lltype_to_annotation(self.TP)

    def lltype(self):
        return self.TP

43
def _isfunctype(TP):
44
45
46
47
    """ Evil hack to get rid of flow objspace inability
    to accept .TO when TP is not a pointer
    """
    return isinstance(TP, lltype.Ptr) and isinstance(TP.TO, lltype.FuncType)
48
49
50
51
52
53
54
55
_isfunctype._annspecialcase_ = 'specialize:memo'

def _isllptr(p):
    """ Second evil hack to detect if 'p' is a low-level pointer or not """
    return isinstance(p, lltype._ptr)
class _IsLLPtrEntry(ExtRegistryEntry):
    _about_ = _isllptr
    def compute_result_annotation(self, s_p):
56
        result = isinstance(s_p, SomePtr)
57
58
        return self.bookkeeper.immutablevalue(result)
    def specialize_call(self, hop):
59
        hop.exception_cannot_occur()
60
        return hop.inputconst(lltype.Bool, hop.s_result.const)
61

Armin Rigo's avatar
more    
Armin Rigo committed
62
63
64
RFFI_SAVE_ERRNO          = 1     # save the real errno after the call
RFFI_READSAVED_ERRNO     = 2     # copy saved errno into real errno before call
RFFI_ZERO_ERRNO_BEFORE   = 4     # copy the value 0 into real errno before call
65
RFFI_FULL_ERRNO          = RFFI_SAVE_ERRNO | RFFI_READSAVED_ERRNO
Armin Rigo's avatar
more    
Armin Rigo committed
66
RFFI_FULL_ERRNO_ZERO     = RFFI_SAVE_ERRNO | RFFI_ZERO_ERRNO_BEFORE
67
68
RFFI_SAVE_LASTERROR      = 8     # win32: save GetLastError() after the call
RFFI_READSAVED_LASTERROR = 16    # win32: call SetLastError() before the call
69
RFFI_SAVE_WSALASTERROR   = 32    # win32: save WSAGetLastError() after the call
70
71
72
RFFI_FULL_LASTERROR      = RFFI_SAVE_LASTERROR | RFFI_READSAVED_LASTERROR
RFFI_ERR_NONE            = 0
RFFI_ERR_ALL             = RFFI_FULL_ERRNO | RFFI_FULL_LASTERROR
73
RFFI_ALT_ERRNO           = 64    # read, save using alt tl destination
Armin Rigo's avatar
Armin Rigo committed
74
75
def llexternal(name, args, result, _callable=None,
               compilation_info=ExternalCompilationInfo(),
76
               sandboxsafe=False, releasegil='auto',
77
               _nowrapper=False, calling_conv=None,
78
               elidable_function=False, macro=None,
79
80
               random_effects_on_gcobjs='auto',
               save_err=RFFI_ERR_NONE):
81
82
    """Build an external function that will invoke the C function 'name'
    with the given 'args' types and 'result' type.
83

84
85
86
87
88
    You get by default a wrapper that casts between number types as needed
    to match the arguments.  You can also pass an RPython string when a
    CCHARP argument is expected, and the C function receives a 'const char*'
    pointing to a read-only null-terminated character of arrays, as usual
    for C.
89

90
91
92
93
    The C function can have callbacks, but they must be specified explicitly
    as constant RPython functions.  We don't support yet C functions that
    invoke callbacks passed otherwise (e.g. set by a previous C call).

94
    releasegil: whether it's ok to release the GIL around the call.
95
96
97
98
                Default is yes, unless sandboxsafe is set, in which case
                we consider that the function is really short-running and
                don't bother releasing the GIL.  An explicit True or False
                overrides this logic.
99

100
101
    calling_conv: if 'unknown' or 'win', the C function is not directly seen
                  by the JIT.  If 'c', it can be seen (depending on
102
103
                  releasegil=False).  For tests only, or if _nowrapper,
                  it defaults to 'c'.
104
    """
105
106
107
108
109
    if calling_conv is None:
        if sys.platform == 'win32' and not _nowrapper:
            calling_conv = 'unknown'
        else:
            calling_conv = 'c'
Armin Rigo's avatar
Armin Rigo committed
110
111
    if _callable is not None:
        assert callable(_callable)
112
    ext_type = lltype.FuncType(args, result)
113
    if _callable is None:
114
115
116
117
118
119
        if macro is not None:
            if macro is True:
                macro = name
            _callable = generate_macro_wrapper(
                name, macro, ext_type, compilation_info)
        else:
120
121
            _callable = ll2ctypes.LL2CtypesCallable(ext_type,
                'c' if calling_conv == 'unknown' else calling_conv)
122
123
    else:
        assert macro is None, "'macro' is useless if you specify '_callable'"
124
125
    if elidable_function:
        _callable._elidable_function_ = True
126
    kwds = {}
127
128
129
130
131
132
133
134
135
136

    has_callback = False
    for ARG in args:
        if _isfunctype(ARG):
            has_callback = True
    if has_callback:
        kwds['_callbacks'] = callbackholder = CallbackHolder()
    else:
        callbackholder = None

137
    if releasegil in (False, True):
138
139
        # invoke the around-handlers, which release the GIL, if and only if
        # the C function is thread-safe.
140
        invoke_around_handlers = releasegil
141
142
143
144
    else:
        # default case:
        # invoke the around-handlers only for "not too small" external calls;
        # sandboxsafe is a hint for "too-small-ness" (e.g. math functions).
145
146
        # Also, _nowrapper functions cannot release the GIL, by default.
        invoke_around_handlers = not sandboxsafe and not _nowrapper
147

Armin Rigo's avatar
Armin Rigo committed
148
149
150
    if _nowrapper and isinstance(_callable, ll2ctypes.LL2CtypesCallable):
        kwds['_real_integer_addr'] = _callable.get_real_address

Armin Rigo's avatar
Armin Rigo committed
151
152
153
154
    if random_effects_on_gcobjs not in (False, True):
        random_effects_on_gcobjs = (
            invoke_around_handlers or   # because it can release the GIL
            has_callback)               # because the callback can do it
155
    assert not (elidable_function and random_effects_on_gcobjs)
Armin Rigo's avatar
Armin Rigo committed
156

Armin Rigo's avatar
Armin Rigo committed
157
    funcptr = lltype.functionptr(ext_type, name, external='C',
Armin Rigo's avatar
Armin Rigo committed
158
                                 compilation_info=compilation_info,
159
160
161
                                 _callable=_callable,
                                 _safe_not_sandboxed=sandboxsafe,
                                 _debugexc=True, # on top of llinterp
162
                                 canraise=False,
Armin Rigo's avatar
Armin Rigo committed
163
164
                                 random_effects_on_gcobjs=
                                     random_effects_on_gcobjs,
165
                                 calling_conv=calling_conv,
166
                                 **kwds)
167
168
169
    if isinstance(_callable, ll2ctypes.LL2CtypesCallable):
        _callable.funcptr = funcptr

170
    if _nowrapper:
171
        assert save_err == RFFI_ERR_NONE
172
173
        return funcptr

174
175
176
177
178
179
180
181
182
183
    if invoke_around_handlers:
        # The around-handlers are releasing the GIL in a threaded pypy.
        # We need tons of care to ensure that no GC operation and no
        # exception checking occurs while the GIL is released.

        # The actual call is done by this small piece of non-inlinable
        # generated code in order to avoid seeing any GC pointer:
        # neither '*args' nor the GC objects originally passed in as
        # argument to wrapper(), if any (e.g. RPython strings).

Armin Rigo's avatar
Armin Rigo committed
184
        argnames = ', '.join(['a%d' % i for i in range(len(args))])
185
        source = py.code.Source("""
Armin Rigo's avatar
Armin Rigo committed
186
            from rpython.rlib import rgil
187
            def call_external_function(%(argnames)s):
Armin Rigo's avatar
Armin Rigo committed
188
                rgil.release()
189
                # NB. it is essential that no exception checking occurs here!
Armin Rigo's avatar
Armin Rigo committed
190
                if %(save_err)d:
Armin Rigo's avatar
Armin Rigo committed
191
                    from rpython.rlib import rposix
Armin Rigo's avatar
Armin Rigo committed
192
                    rposix._errno_before(%(save_err)d)
193
194
195
196
197
198
199
200
                if we_are_translated():
                    res = funcptr(%(argnames)s)
                else:
                    try:    # only when non-translated
                        res = funcptr(%(argnames)s)
                    except:
                        rgil.acquire()
                        raise
Armin Rigo's avatar
Armin Rigo committed
201
                if %(save_err)d:
Armin Rigo's avatar
Armin Rigo committed
202
                    from rpython.rlib import rposix
Armin Rigo's avatar
Armin Rigo committed
203
                    rposix._errno_after(%(save_err)d)
Armin Rigo's avatar
Armin Rigo committed
204
                rgil.acquire()
205
206
                return res
        """ % locals())
Armin Rigo's avatar
Armin Rigo committed
207
        miniglobals = {'funcptr':     funcptr,
208
                       '__name__':    __name__, # for module name propagation
209
                       'we_are_translated': we_are_translated,
210
                       }
211
        exec source.compile() in miniglobals
212
213
214
        call_external_function = miniglobals['call_external_function']
        call_external_function._dont_inline_ = True
        call_external_function._annspecialcase_ = 'specialize:ll'
Armin Rigo's avatar
Armin Rigo committed
215
        call_external_function._gctransformer_hint_close_stack_ = True
216
217
218
219
220
        #
        # '_call_aroundstate_target_' is used by the JIT to generate a
        # CALL_RELEASE_GIL directly to 'funcptr'.  This doesn't work if
        # 'funcptr' might be a C macro, though.
        if macro is None:
Armin Rigo's avatar
Armin Rigo committed
221
            call_external_function._call_aroundstate_target_ = funcptr, save_err
222
        #
223
224
225
226
227
        call_external_function = func_with_new_name(call_external_function,
                                                    'ccall_' + name)
        # don't inline, as a hack to guarantee that no GC pointer is alive
        # anywhere in call_external_function
    else:
Armin Rigo's avatar
Armin Rigo committed
228
        # if we don't have to invoke the GIL handling, we can just call
229
        # the low-level function pointer carelessly
230
231
232
        # ...well, unless it's a macro, in which case we still have
        # to hide it from the JIT...
        need_wrapper = (macro is not None or save_err != RFFI_ERR_NONE)
233
234
235
        # ...and unless we're on Windows and the calling convention is
        # 'win' or 'unknown'
        if calling_conv != 'c':
236
237
238
            need_wrapper = True
        #
        if not need_wrapper:
239
240
            call_external_function = funcptr
        else:
Armin Rigo's avatar
Armin Rigo committed
241
            argnames = ', '.join(['a%d' % i for i in range(len(args))])
242
243
            source = py.code.Source("""
                def call_external_function(%(argnames)s):
Armin Rigo's avatar
Armin Rigo committed
244
                    if %(save_err)d:
Armin Rigo's avatar
Armin Rigo committed
245
                        from rpython.rlib import rposix
Armin Rigo's avatar
Armin Rigo committed
246
                        rposix._errno_before(%(save_err)d)
247
                    res = funcptr(%(argnames)s)
Armin Rigo's avatar
Armin Rigo committed
248
                    if %(save_err)d:
Armin Rigo's avatar
Armin Rigo committed
249
                        from rpython.rlib import rposix
Armin Rigo's avatar
Armin Rigo committed
250
                        rposix._errno_after(%(save_err)d)
251
                    return res
252
253
254
255
            """ % locals())
            miniglobals = {'funcptr':     funcptr,
                           '__name__':    __name__,
                           }
256
            exec source.compile() in miniglobals
257
            call_external_function = miniglobals['call_external_function']
258
259
            call_external_function = func_with_new_name(call_external_function,
                                                        'ccall_' + name)
260
261
            call_external_function = jit.dont_look_inside(
                call_external_function)
262

263
264
265
266
267
    def _oops():
        raise AssertionError("can't pass (any more) a unicode string"
                             " directly to a VOIDP argument")
    _oops._annspecialcase_ = 'specialize:memo'

268
    nb_args = len(args)
269
270
    unrolling_arg_tps = unrolling_iterable(enumerate(args))
    def wrapper(*args):
271
        assert len(args) == nb_args
272
        real_args = ()
273
274
        # XXX 'to_free' leaks if an allocation fails with MemoryError
        # and was not the first in this function
275
276
277
        to_free = ()
        for i, TARGET in unrolling_arg_tps:
            arg = args[i]
278
            if TARGET == CCHARP or TARGET is VOIDP:
279
                if arg is None:
280
                    from rpython.rtyper.annlowlevel import llstr
281
                    arg = lltype.nullptr(CCHARP.TO)   # None => (char*)NULL
282
                    to_free = to_free + (arg, llstr(None), '\x04')
283
                elif isinstance(arg, str):
284
                    tup = get_nonmovingbuffer_ll_final_null(arg)
285
286
287
288
                    to_free = to_free + tup
                    arg = tup[0]
                elif isinstance(arg, unicode):
                    _oops()
Benjamin Peterson's avatar
Benjamin Peterson committed
289
290
291
            elif TARGET == CWCHARP:
                if arg is None:
                    arg = lltype.nullptr(CWCHARP.TO)   # None => (wchar_t*)NULL
292
                    to_free = to_free + (arg,)
Benjamin Peterson's avatar
Benjamin Peterson committed
293
294
                elif isinstance(arg, unicode):
                    arg = unicode2wcharp(arg)
295
                    to_free = to_free + (arg,)
296
            elif _isfunctype(TARGET) and not _isllptr(arg):
297
                # XXX pass additional arguments
Armin Rigo's avatar
Armin Rigo committed
298
299
300
                use_gil = invoke_around_handlers
                arg = llhelper(TARGET, _make_wrapper_for(TARGET, arg,
                                                         callbackholder,
Armin Rigo's avatar
Armin Rigo committed
301
                                                         use_gil))
302
            else:
303
304
305
306
                SOURCE = lltype.typeOf(arg)
                if SOURCE != TARGET:
                    if TARGET is lltype.Float:
                        arg = float(arg)
307
308
309
310
                    elif ((isinstance(SOURCE, lltype.Number)
                           or SOURCE is lltype.Bool)
                      and (isinstance(TARGET, lltype.Number)
                           or TARGET is lltype.Bool)):
311
312
                        arg = cast(TARGET, arg)
            real_args = real_args + (arg,)
313
        res = call_external_function(*real_args)
314
        for i, TARGET in unrolling_arg_tps:
315
316
317
            arg = args[i]
            if TARGET == CCHARP or TARGET is VOIDP:
                if arg is None:
318
                    to_free = to_free[3:]
319
                elif isinstance(arg, str):
320
321
                    free_nonmovingbuffer_ll(to_free[0], to_free[1], to_free[2])
                    to_free = to_free[3:]
322
323
            elif TARGET == CWCHARP:
                if arg is None:
324
                    to_free = to_free[1:]
325
                elif isinstance(arg, unicode):
326
327
328
                    free_wcharp(to_free[0])
                    to_free = to_free[1:]
        assert len(to_free) == 0
329
330
331
332
333
334
        if rarithmetic.r_int is not r_int:
            if result is INT:
                return cast(lltype.Signed, res)
            elif result is UINT:
                return cast(lltype.Unsigned, res)
        return res
335
    wrapper._annspecialcase_ = 'specialize:ll'
336
    wrapper._always_inline_ = 'try'
337
338
    # for debugging, stick ll func ptr to that
    wrapper._ptr = funcptr
339
340
    wrapper = func_with_new_name(wrapper, name)
    return wrapper
341

342

343
344
345
346
class CallbackHolder:
    def __init__(self):
        self.callbacks = {}

Armin Rigo's avatar
Armin Rigo committed
347
def _make_wrapper_for(TP, callable, callbackholder, use_gil):
348
349
350
    """ Function creating wrappers for callbacks. Note that this is
    cheating as we assume constant callbacks and we just memoize wrappers
    """
Alexander Hesse's avatar
Alexander Hesse committed
351
352
    from rpython.rtyper.lltypesystem import lltype
    from rpython.rtyper.lltypesystem.lloperation import llop
353
354
355
    if hasattr(callable, '_errorcode_'):
        errorcode = callable._errorcode_
    else:
356
        errorcode = TP.TO.RESULT._defl()
357
    callable_name = getattr(callable, '__name__', '?')
358
359
    if callbackholder is not None:
        callbackholder.callbacks[callable] = True
Armin Rigo's avatar
Armin Rigo committed
360
361
    args = ', '.join(['a%d' % i for i in range(len(TP.TO.ARGS))])
    source = py.code.Source(r"""
Armin Rigo's avatar
Armin Rigo committed
362
363
364
365
        rgil = None
        if use_gil:
            from rpython.rlib import rgil

366
        def wrapper(%(args)s):    # no *args - no GIL for mallocing the tuple
Armin Rigo's avatar
Armin Rigo committed
367
            if rgil is not None:
Armin Rigo's avatar
Armin Rigo committed
368
                rgil.acquire_maybe_in_new_thread()
Armin Rigo's avatar
Armin Rigo committed
369
            # from now on we hold the GIL
370
            llop.gc_stack_bottom(lltype.Void)   # marker to enter RPython from C
Armin Rigo's avatar
Armin Rigo committed
371
            try:
372
                result = callable(%(args)s)
Armin Rigo's avatar
Armin Rigo committed
373
374
375
            except Exception, e:
                os.write(2,
                    "Warning: uncaught exception in callback: %%s %%s\n" %%
376
                    (callable_name, str(e)))
377
378
379
                if not we_are_translated():
                    import traceback
                    traceback.print_exc()
Armin Rigo's avatar
Armin Rigo committed
380
                result = errorcode
Armin Rigo's avatar
Armin Rigo committed
381
382
            if rgil is not None:
                rgil.release()
Armin Rigo's avatar
Armin Rigo committed
383
384
            # here we don't hold the GIL any more. As in the wrapper() produced
            # by llexternal, it is essential that no exception checking occurs
Armin Rigo's avatar
Armin Rigo committed
385
            # after the call to rgil.release().
Maciej Fijalkowski's avatar
Maciej Fijalkowski committed
386
            return result
387
    """ % locals())
Armin Rigo's avatar
Armin Rigo committed
388
389
390
    miniglobals = locals().copy()
    miniglobals['Exception'] = Exception
    miniglobals['os'] = os
391
    miniglobals['we_are_translated'] = we_are_translated
392
    exec source.compile() in miniglobals
Armin Rigo's avatar
Armin Rigo committed
393
    return miniglobals['wrapper']
394
395
_make_wrapper_for._annspecialcase_ = 'specialize:memo'

396
AroundFnPtr = lltype.Ptr(lltype.FuncType([], lltype.Void))
397

Armin Rigo's avatar
Armin Rigo committed
398

399
400
401
402
403
404
def llexternal_use_eci(compilation_info):
    """Return a dummy function that, if called in a RPython program,
    adds the given ExternalCompilationInfo to it."""
    eci = ExternalCompilationInfo(post_include_bits=['#define PYPY_NO_OP()'])
    eci = eci.merge(compilation_info)
    return llexternal('PYPY_NO_OP', [], lltype.Void,
Armin Rigo's avatar
Armin Rigo committed
405
406
                      compilation_info=eci, sandboxsafe=True, _nowrapper=True,
                      _callable=lambda: None)
407

408
409
410
411
412
def generate_macro_wrapper(name, macro, functype, eci):
    """Wraps a function-like macro inside a real function, and expose
    it with llexternal."""

    # Generate the function call
Alexander Hesse's avatar
Alexander Hesse committed
413
414
    from rpython.translator.c.database import LowLevelDatabase
    from rpython.translator.c.support import cdecl
415
416
417
418
419
    wrapper_name = 'pypy_macro_wrapper_%s' % (name,)
    argnames = ['arg%d' % (i,) for i in range(len(functype.ARGS))]
    db = LowLevelDatabase()
    implementationtypename = db.gettype(functype, argnames=argnames)
    if functype.RESULT is lltype.Void:
Armin Rigo's avatar
Armin Rigo committed
420
        pattern = '%s%s { %s(%s); }'
421
    else:
Armin Rigo's avatar
Armin Rigo committed
422
        pattern = '%s%s { return %s(%s); }'
423
    source = pattern % (
424
        'RPY_EXTERN ',
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
        cdecl(implementationtypename, wrapper_name),
        macro, ', '.join(argnames))

    # Now stuff this source into a "companion" eci that will be used
    # by ll2ctypes.  We replace eci._with_ctypes, so that only one
    # shared library is actually compiled (when ll2ctypes calls the
    # first function)
    ctypes_eci = eci.merge(ExternalCompilationInfo(
            separate_module_sources=[source],
            ))
    if hasattr(eci, '_with_ctypes'):
        ctypes_eci = eci._with_ctypes.merge(ctypes_eci)
    eci._with_ctypes = ctypes_eci
    func = llexternal(wrapper_name, functype.ARGS, functype.RESULT,
                      compilation_info=eci, _nowrapper=True)
    # _nowrapper=True returns a pointer which is not hashable
    return lambda *args: func(*args)

443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
# ____________________________________________________________
# Few helpers for keeping callback arguments alive
# this makes passing opaque objects possible (they don't even pass
# through C, only integer specifying number passes)

_KEEPER_CACHE = {}

def _keeper_for_type(TP):
    try:
        return _KEEPER_CACHE[TP]
    except KeyError:
        tp_str = str(TP) # make annotator happy
        class KeepaliveKeeper(object):
            def __init__(self):
                self.stuff_to_keepalive = []
                self.free_positions = []
        keeper = KeepaliveKeeper()
        _KEEPER_CACHE[TP] = keeper
        return keeper
_keeper_for_type._annspecialcase_ = 'specialize:memo'

def register_keepalive(obj):
    """ Register object obj to be kept alive,
    returns a position for that object
    """
    keeper = _keeper_for_type(lltype.typeOf(obj))
    if len(keeper.free_positions):
        pos = keeper.free_positions.pop()
        keeper.stuff_to_keepalive[pos] = obj
        return pos
    # we don't have any free positions
    pos = len(keeper.stuff_to_keepalive)
    keeper.stuff_to_keepalive.append(obj)
    return pos
register_keepalive._annspecialcase_ = 'specialize:argtype(0)'

def get_keepalive_object(pos, TP):
    keeper = _keeper_for_type(TP)
    return keeper.stuff_to_keepalive[pos]
get_keepalive_object._annspecialcase_ = 'specialize:arg(1)'

def unregister_keepalive(pos, TP):
    """ Unregister an object of type TP, stored at position
    pos (position previously returned by register_keepalive)
    """
    keeper = _keeper_for_type(TP)
    keeper.stuff_to_keepalive[pos] = None
    keeper.free_positions.append(pos)
unregister_keepalive._annspecialcase_ = 'specialize:arg(1)'

493
494
# ____________________________________________________________

495
496
497
498
499
TYPES = []
for _name in 'short int long'.split():
    for name in (_name, 'unsigned ' + _name):
        TYPES.append(name)
TYPES += ['signed char', 'unsigned char',
500
          'long long', 'unsigned long long',
501
          'size_t', 'time_t', 'wchar_t',
Armin Rigo's avatar
Armin Rigo committed
502
          'uintptr_t', 'intptr_t',    # C note: these two are _integer_ types
503
          'void*']    # generic pointer type
stian's avatar
stian committed
504
505

# This is a bit of a hack since we can't use rffi_platform here.
506
try:
507
    sizeof_c_type('__int128_t', ignore_errors=True)
508
    TYPES += ['__int128_t', '__uint128_t']
stian's avatar
stian committed
509
510
except CompilationError:
    pass
511

512
513
514
if os.name != 'nt':
    TYPES.append('mode_t')
    TYPES.append('pid_t')
Amaury Forgeot d'Arc's avatar
Amaury Forgeot d'Arc committed
515
    TYPES.append('ssize_t')
Armin Rigo's avatar
Armin Rigo committed
516
517
518
519
520
521
522
523
524
525
526
    # the types below are rare enough and not available on Windows
    TYPES.extend(['ptrdiff_t',
          'int_least8_t',  'uint_least8_t',
          'int_least16_t', 'uint_least16_t',
          'int_least32_t', 'uint_least32_t',
          'int_least64_t', 'uint_least64_t',
          'int_fast8_t',  'uint_fast8_t',
          'int_fast16_t', 'uint_fast16_t',
          'int_fast32_t', 'uint_fast32_t',
          'int_fast64_t', 'uint_fast64_t',
          'intmax_t', 'uintmax_t'])
527
else:
528
    # MODE_T is set later
529
    PID_T = lltype.Signed
Amaury Forgeot d'Arc's avatar
Amaury Forgeot d'Arc committed
530
    SSIZE_T = lltype.Signed
Matti Picus's avatar
Matti Picus committed
531
    PTRDIFF_T = lltype.Signed
532

533
534
535
def populate_inttypes():
    names = []
    populatelist = []
536
537
    for name in TYPES:
        c_name = name
538
539
540
        if name.startswith('unsigned'):
            name = 'u' + name[9:]
            signed = False
541
542
        elif (name == 'size_t' or name.startswith('uint')
                               or name.startswith('__uint')):
Armin Rigo's avatar
Armin Rigo committed
543
            signed = False
544
545
        elif name == 'wchar_t' and sys.platform == 'win32':
            signed = False
546
        else:
Armin Rigo's avatar
Armin Rigo committed
547
            signed = True
548
        name = name.replace(' ', '')
549
550
551
552
553
554
555
556
557
558
559
560
        names.append(name)
        populatelist.append((name.upper(), c_name, signed))
    platform.populate_inttypes(populatelist)
    return names

def setup():
    """ creates necessary c-level types
    """
    names = populate_inttypes()
    result = []
    for name in names:
        tp = platform.types[name.upper()]
561
562
        globals()['r_' + name] = platform.numbertype_to_rclass[tp]
        globals()[name.upper()] = tp
563
564
        tpp = lltype.Ptr(lltype.Array(tp, hints={'nolength': True}))
        globals()[name.upper()+'P'] = tpp
565
566
        result.append(tp)
    return result
567

568
NUMBER_TYPES = setup()
569
platform.numbertype_to_rclass[lltype.Signed] = int     # avoid "r_long" for common cases
570
r_int_real = rarithmetic.build_int("r_int_real", r_int.SIGN, r_int.BITS, True)
571
572
INT_real = lltype.build_number("INT", r_int_real)
platform.numbertype_to_rclass[INT_real] = r_int_real
573
NUMBER_TYPES.append(INT_real)
574

575
576
577
578
# ^^^ this creates at least the following names:
# --------------------------------------------------------------------
#        Type           RPython integer class doing wrap-around
# --------------------------------------------------------------------
Armin Rigo's avatar
Armin Rigo committed
579
#        SIGNEDCHAR     r_signedchar
580
581
582
583
584
585
586
587
588
#        UCHAR          r_uchar
#        SHORT          r_short
#        USHORT         r_ushort
#        INT            r_int
#        UINT           r_uint
#        LONG           r_long
#        ULONG          r_ulong
#        LONGLONG       r_longlong
#        ULONGLONG      r_ulonglong
589
#        WCHAR_T        r_wchar_t
590
#        SIZE_T         r_size_t
Amaury Forgeot d'Arc's avatar
Amaury Forgeot d'Arc committed
591
#        SSIZE_T        r_ssize_t
592
#        TIME_T         r_time_t
593
# --------------------------------------------------------------------
594
595
596
597
# Note that rffi.r_int is not necessarily the same as
# rarithmetic.r_int, etc!  rffi.INT/r_int correspond to the C-level
# 'int' type, whereas rarithmetic.r_int corresponds to the
# Python-level int type (which is a C long).  Fun.
598

599
600
601
if os.name == 'nt':
    MODE_T = INT

602
603
604
605
606
607
608
609
610
611
612
613
def CStruct(name, *fields, **kwds):
    """ A small helper to create external C structure, not the
    pypy one
    """
    hints = kwds.get('hints', {})
    hints = hints.copy()
    kwds['hints'] = hints
    hints['external'] = 'C'
    hints['c_name'] = name
    # Hack: prefix all attribute names with 'c_' to cope with names starting
    # with '_'.  The genc backend removes the 'c_' prefixes...
    c_fields = [('c_' + key, value) for key, value in fields]
614
615
616
617
618
619
620
    return lltype.Struct(name, *c_fields, **kwds)

def CStructPtr(*args, **kwds):
    return lltype.Ptr(CStruct(*args, **kwds))

def CFixedArray(tp, size):
    return lltype.FixedSizeArray(tp, size)
Maciej Fijalkowski's avatar
Maciej Fijalkowski committed
621
CFixedArray._annspecialcase_ = 'specialize:memo'
622
623
624

def CArray(tp):
    return lltype.Array(tp, hints={'nolength': True})
625
CArray._annspecialcase_ = 'specialize:memo'
626

Maciej Fijalkowski's avatar
Maciej Fijalkowski committed
627
628
def CArrayPtr(tp):
    return lltype.Ptr(CArray(tp))
Armin Rigo's avatar
Armin Rigo committed
629
CArrayPtr._annspecialcase_ = 'specialize:memo'
Maciej Fijalkowski's avatar
Maciej Fijalkowski committed
630

631
632
633
634
def CCallback(args, res):
    return lltype.Ptr(lltype.FuncType(args, res))
CCallback._annspecialcase_ = 'specialize:memo'

Amaury Forgeot d'Arc's avatar
Amaury Forgeot d'Arc committed
635
def COpaque(name=None, ptr_typedef=None, hints=None, compilation_info=None):
Armin Rigo's avatar
Armin Rigo committed
636
637
    if compilation_info is None:
        compilation_info = ExternalCompilationInfo()
638
639
    if hints is None:
        hints = {}
640
641
    else:
        hints = hints.copy()
642
    hints['external'] = 'C'
Amaury Forgeot d'Arc's avatar
Amaury Forgeot d'Arc committed
643
644
645
646
    if name is not None:
        hints['c_name'] = name
    if ptr_typedef is not None:
        hints['c_pointer_typedef'] = ptr_typedef
647
    def lazy_getsize(cache={}):
Alexander Hesse's avatar
Alexander Hesse committed
648
        from rpython.rtyper.tool import rffi_platform
649
650
651
652
653
654
        try:
            return cache[name]
        except KeyError:
            val = rffi_platform.sizeof(name, compilation_info)
            cache[name] = val
            return val
655

656
    hints['getsize'] = lazy_getsize
657
658
659
    return lltype.OpaqueType(name, hints)

def COpaquePtr(*args, **kwds):
Amaury Forgeot d'Arc's avatar
Amaury Forgeot d'Arc committed
660
661
    typedef = kwds.pop('typedef', None)
    return lltype.Ptr(COpaque(ptr_typedef=typedef, *args, **kwds))
662

Armin Rigo's avatar
Armin Rigo committed
663
def CExternVariable(TYPE, name, eci, _CConstantClass=CConstant,
664
                    sandboxsafe=False, _nowrapper=False,
Armin Rigo's avatar
Armin Rigo committed
665
666
                    c_type=None, getter_only=False,
                    declare_as_extern=(sys.platform != 'win32')):
667
668
669
    """Return a pair of functions - a getter and a setter - to access
    the given global C variable.
    """
Alexander Hesse's avatar
Alexander Hesse committed
670
671
    from rpython.translator.c.primitive import PrimitiveType
    from rpython.translator.tool.cbuild import ExternalCompilationInfo
Maciej Fijalkowski's avatar
Maciej Fijalkowski committed
672
673
    # XXX we cannot really enumerate all C types here, do it on a case-by-case
    #     basis
674
675
676
677
678
679
680
681
682
683
684
    if c_type is None:
        if TYPE == CCHARPP:
            c_type = 'char **'
        elif TYPE == CCHARP:
            c_type = 'char *'
        elif TYPE == INT or TYPE == LONG:
            assert False, "ambiguous type on 32-bit machines: give a c_type"
        else:
            c_type = PrimitiveType[TYPE]
            assert c_type.endswith(' @')
            c_type = c_type[:-2] # cut the trailing ' @'
685

Maciej Fijalkowski's avatar
Maciej Fijalkowski committed
686
687
    getter_name = 'get_' + name
    setter_name = 'set_' + name
688
    getter_prototype = (
689
       "RPY_EXTERN %(c_type)s %(getter_name)s ();" % locals())
690
    setter_prototype = (
691
       "RPY_EXTERN void %(setter_name)s (%(c_type)s v);" % locals())
Maciej Fijalkowski's avatar
Maciej Fijalkowski committed
692
693
    c_getter = "%(c_type)s %(getter_name)s () { return %(name)s; }" % locals()
    c_setter = "void %(setter_name)s (%(c_type)s v) { %(name)s = v; }" % locals()
694

Armin Rigo's avatar
Armin Rigo committed
695
    lines = ["#include <%s>" % i for i in eci.includes]
Armin Rigo's avatar
Armin Rigo committed
696
    if declare_as_extern:
697
        lines.append('extern %s %s;' % (c_type, name))
Maciej Fijalkowski's avatar
Maciej Fijalkowski committed
698
    lines.append(c_getter)
699
700
701
702
703
    if not getter_only:
        lines.append(c_setter)
    prototypes = [getter_prototype]
    if not getter_only:
        prototypes.append(setter_prototype)
Maciej Fijalkowski's avatar
Maciej Fijalkowski committed
704
    sources = ('\n'.join(lines),)
Armin Rigo's avatar
Armin Rigo committed
705
706
    new_eci = eci.merge(ExternalCompilationInfo(
        separate_module_sources = sources,
707
        post_include_bits = prototypes,
Armin Rigo's avatar
Armin Rigo committed
708
    ))
709

Armin Rigo's avatar
Armin Rigo committed
710
    getter = llexternal(getter_name, [], TYPE, compilation_info=new_eci,
711
                        sandboxsafe=sandboxsafe, _nowrapper=_nowrapper)
712
713
714
715
716
717
718
    if getter_only:
        return getter
    else:
        setter = llexternal(setter_name, [TYPE], lltype.Void,
                            compilation_info=new_eci, sandboxsafe=sandboxsafe,
                            _nowrapper=_nowrapper)
        return getter, setter
719

Armin Rigo's avatar
Armin Rigo committed
720
721
722
723
# char, represented as a Python character
# (use SIGNEDCHAR or UCHAR for the small integer types)
CHAR = lltype.Char

724
# double
725
DOUBLE = lltype.Float
726
LONGDOUBLE = lltype.LongFloat
727

Alexander Hesse's avatar
Alexander Hesse committed
728
# float - corresponds to rpython.rlib.rarithmetic.r_float, and supports no
729
730
#         operation except rffi.cast() between FLOAT and DOUBLE
FLOAT = lltype.SingleFloat
731
r_singlefloat = rarithmetic.r_singlefloat
732

Armin Rigo's avatar
Armin Rigo committed
733
# void *   - for now, represented as char *
Amaury Forgeot d'Arc's avatar
Amaury Forgeot d'Arc committed
734
VOIDP = lltype.Ptr(lltype.Array(lltype.Char, hints={'nolength': True, 'render_as_void': True}))
735
NULL = None
736

737
738
739
# void **
VOIDPP = CArrayPtr(VOIDP)

740
741
# char *
CCHARP = lltype.Ptr(lltype.Array(lltype.Char, hints={'nolength': True}))
Armin Rigo's avatar
fixeol    
Armin Rigo committed
742

743
744
745
746
# const char *
CONST_CCHARP = lltype.Ptr(lltype.Array(lltype.Char, hints={'nolength': True,
                                       'render_as_const': True}))

747
748
749
# wchar_t *
CWCHARP = lltype.Ptr(lltype.Array(lltype.UniChar, hints={'nolength': True}))

Armin Rigo's avatar
fixeol    
Armin Rigo committed
750
751
752
# int *, unsigned int *, etc.
#INTP = ...    see setup() above

753
754
755
# double *
DOUBLEP = lltype.Ptr(lltype.Array(DOUBLE, hints={'nolength': True}))

756
757
758
# float *
FLOATP = lltype.Ptr(lltype.Array(FLOAT, hints={'nolength': True}))

Armin Rigo's avatar
Armin Rigo committed
759
760
761
# long double *
LONGDOUBLEP = lltype.Ptr(lltype.Array(LONGDOUBLE, hints={'nolength': True}))

762
763
# Signed, Signed *
SIGNED = lltype.Signed
764
765
SIGNEDP = lltype.Ptr(lltype.Array(lltype.Signed, hints={'nolength': True}))
SIGNEDPP = lltype.Ptr(lltype.Array(SIGNEDP, hints={'nolength': True}))
766

767
768
769
770
# Unsigned, Unsigned *
UNSIGNED = lltype.Unsigned
UNSIGNEDP = lltype.Ptr(lltype.Array(lltype.Unsigned, hints={'nolength': True}))

771

772
# various type mapping
773
774
775
776

# conversions between str and char*
# conversions between unicode and wchar_t*
def make_string_mappings(strtype):
777

778
    if strtype is str:
779
        from rpython.rtyper.lltypesystem.rstr import (STR as STRTYPE,
780
781
                                                      copy_string_to_raw,
                                                      copy_raw_to_string,
Armin Rigo's avatar
Armin Rigo committed
782
783
                                                      copy_string_contents,
                                                      mallocstr as mallocfn)
Alexander Hesse's avatar
Alexander Hesse committed
784
785
        from rpython.rtyper.annlowlevel import llstr as llstrtype
        from rpython.rtyper.annlowlevel import hlstr as hlstrtype
786
787
788
789
        TYPEP = CCHARP
        ll_char_type = lltype.Char
        lastchar = '\x00'
    else:
790
791
        from rpython.rtyper.lltypesystem.rstr import (
            UNICODE as STRTYPE,
792
793
            copy_unicode_to_raw as copy_string_to_raw,
            copy_raw_to_unicode as copy_raw_to_string,
Armin Rigo's avatar
Armin Rigo committed
794
795
            copy_unicode_contents as copy_string_contents,
            mallocunicode as mallocfn)
Alexander Hesse's avatar
Alexander Hesse committed
796
797
        from rpython.rtyper.annlowlevel import llunicode as llstrtype
        from rpython.rtyper.annlowlevel import hlunicode as hlstrtype
798
799
800
        TYPEP = CWCHARP
        ll_char_type = lltype.UniChar
        lastchar = u'\x00'
801

802
    # str -> char*
803
    def str2charp(s, track_allocation=True):
804
805
        """ str -> char*
        """
Romain Guillebert's avatar
Romain Guillebert committed
806
807
808
809
        if track_allocation:
            array = lltype.malloc(TYPEP.TO, len(s) + 1, flavor='raw', track_allocation=True)
        else:
            array = lltype.malloc(TYPEP.TO, len(s) + 1, flavor='raw', track_allocation=False)
Benjamin Peterson's avatar
Benjamin Peterson committed
810
        i = len(s)
811
812
        ll_s = llstrtype(s)
        copy_string_to_raw(ll_s, array, 0, i)
Benjamin Peterson's avatar
Benjamin Peterson committed
813
        array[i] = lastchar
814
        return array
Romain Guillebert's avatar
Romain Guillebert committed
815
    str2charp._annenforceargs_ = [strtype, bool]
816

817
    def free_charp(cp, track_allocation=True):
Romain Guillebert's avatar
Romain Guillebert committed
818
819
820
821
        if track_allocation:
            lltype.free(cp, flavor='raw', track_allocation=True)
        else:
            lltype.free(cp, flavor='raw', track_allocation=False)
822
    free_charp._annenforceargs_ = [None, bool]
823

824
825
    # str -> already-existing char[maxsize]
    def str2chararray(s, array, maxsize):
Armin Rigo's avatar
Armin Rigo committed
826
        length = min(len(s), maxsize)
827
        ll_s = llstrtype(s)
Armin Rigo's avatar
Armin Rigo committed
828
829
        copy_string_to_raw(ll_s, array, 0, length)
        return length
830
831
    str2chararray._annenforceargs_ = [strtype, None, int]

Armin Rigo's avatar
Armin Rigo committed
832
833
834
835
836
837
    # s[start:start+length] -> already-existing char[],
    # all characters including zeros
    def str2rawmem(s, array, start, length):
        ll_s = llstrtype(s)
        copy_string_to_raw(ll_s, array, start, length)

838
839
840
    # char* -> str
    # doesn't free char*
    def charp2str(cp):
841
842
843
844
845
846
847
848
849
850
        if not we_are_translated():
            res = []
            size = 0
            while True:
                c = cp[size]
                if c == lastchar:
                    return assert_str0("".join(res))
                res.append(c)
                size += 1

851
852
853
        size = 0
        while cp[size] != lastchar:
            size += 1
Armin Rigo's avatar
Armin Rigo committed
854
        return assert_str0(charpsize2str(cp, size))
855
    charp2str._annenforceargs_ = [lltype.SomePtr(TYPEP)]
856

857
    # str -> (buf, llobj, flag)
858
859
    # Can't inline this because of the raw address manipulation.
    @jit.dont_look_inside
860
    def get_nonmovingbuffer_ll(data):
861
862
863
        """
        Either returns a non-moving copy or performs neccessary pointer
        arithmetic to return a pointer to the characters of a string if the
Gregor Wegberg's avatar
Gregor Wegberg committed
864
        string is already nonmovable or could be pinned.  Must be followed by a
865
        free_nonmovingbuffer_ll call.
866

867
868
869
870
871
        The return type is a 3-tuple containing the "char *" result,
        a pointer to the low-level string object, and a flag as a char:

         * \4: no pinning, returned pointer is inside nonmovable 'llobj'
         * \5: 'llobj' was pinned, returned pointer is inside
872
         * \6: pinning failed, returned pointer is raw malloced
873
874
875

        For strings (not unicodes), the len()th character of the resulting
        raw buffer is available, but not initialized.  Use
876
        get_nonmovingbuffer_ll_final_null() instead of get_nonmovingbuffer_ll()
877
        to get a regular null-terminated "char *".
878
        """
879

880
        llobj = llstrtype(data)
881
882
        count = len(data)

883
        if rgc.must_split_gc_address_space():
Armin Rigo's avatar
Armin Rigo committed
884
            flag = '\x06'    # always make a copy in this case
885
        elif we_are_translated_to_c() and not rgc.can_move(llobj):
Armin Rigo's avatar
Armin Rigo committed
886
            flag = '\x04'    # no copy needed
887
        else:
888
            if we_are_translated_to_c() and rgc.pin(llobj):
Armin Rigo's avatar
Armin Rigo committed
889
                flag = '\x05'     # successfully pinned
890
            else:
Armin Rigo's avatar
Armin Rigo committed
891
892
893
894
                flag = '\x06'     # must still make a copy
        if flag == '\x06':
            buf = lltype.malloc(TYPEP.TO, count + (TYPEP is CCHARP),
                                flavor='raw')
895
896
            copy_string_to_raw(llobj, buf, 0, count)
            return buf, llobj, '\x06'
897
            # ^^^ raw malloc used to get a nonmovable copy
Gregor Wegberg's avatar
Gregor Wegberg committed
898
        #
899
        # following code is executed after we're translated to C, if:
900
901
        # - rgc.can_move(data) and rgc.pin(data) both returned true
        # - rgc.can_move(data) returned false
902
        data_start = cast_ptr_to_adr(llobj) + \
903
904
            offsetof(STRTYPE, 'chars') + itemoffsetof(STRTYPE.chars, 0)

905
        return cast(TYPEP, data_start), llobj, flag
906
907
        # ^^^ already nonmovable. Therefore it's not raw allocated nor
        # pinned.
908
909
    get_nonmovingbuffer_ll._always_inline_ = 'try' # get rid of the returned tuple
    get_nonmovingbuffer_ll._annenforceargs_ = [strtype]
910

911

912
    @jit.dont_look_inside
913
914
915
    def get_nonmovingbuffer_ll_final_null(data):
        tup = get_nonmovingbuffer_ll(data)
        buf = tup[0]
916
        buf[len(data)] = lastchar
Armin Rigo's avatar
tweak    
Armin Rigo committed
917
        return tup
918
919
    get_nonmovingbuffer_ll_final_null._always_inline_ = 'try'
    get_nonmovingbuffer_ll_final_null._annenforceargs_ = [strtype]
920

921
    # args-from-tuple-returned-by-get_nonmoving_buffer() -> None
922
923
    # Can't inline this because of the raw address manipulation.
    @jit.dont_look_inside
924
    def free_nonmovingbuffer_ll(buf, llobj, flag):
925
        """
926
        Keep 'llobj' alive and unpin it if it was pinned (flag==\5).
927
        Otherwise free the non-moving copy (flag==\6).
928
        """
929
        if flag == '\x05':
930
            rgc.unpin(llobj)
931
        if flag == '\x06':
932
            lltype.free(buf, flavor='raw')
933
        # if flag == '\x04': data was already nonmovable,
934
        # we have nothing to clean up
935
        keepalive_until_here(llobj)
936