Ejemplo n.º 1
0
def test_jit_ffi_call():
    cd = lltype.malloc(CIF_DESCRIPTION, 1, flavor='raw')
    cd.abi = clibffi.FFI_DEFAULT_ABI
    cd.nargs = 1
    cd.rtype = clibffi.cast_type_to_ffitype(rffi.DOUBLE)
    atypes = lltype.malloc(clibffi.FFI_TYPE_PP.TO, 1, flavor='raw')
    atypes[0] = clibffi.cast_type_to_ffitype(rffi.DOUBLE)
    cd.atypes = atypes
    cd.exchange_size = 64    # 64 bytes of exchange data
    cd.exchange_result = 24
    cd.exchange_args[0] = 16
    #
    jit_ffi_prep_cif(cd)
    #
    assert rffi.sizeof(rffi.DOUBLE) == 8
    exb = lltype.malloc(rffi.DOUBLEP.TO, 8, flavor='raw')
    exb[2] = 1.23
    jit_ffi_call(cd, math_sin, rffi.cast(rffi.CCHARP, exb))
    res = exb[3]
    lltype.free(exb, flavor='raw')
    #
    lltype.free(atypes, flavor='raw')
    lltype.free(cd, flavor='raw')
    #
    assert res == math.sin(1.23)
Ejemplo n.º 2
0
def test_jit_ffi_call():
    cd = lltype.malloc(CIF_DESCRIPTION, 1, flavor='raw')
    cd.abi = clibffi.FFI_DEFAULT_ABI
    cd.nargs = 1
    cd.rtype = clibffi.cast_type_to_ffitype(rffi.DOUBLE)
    atypes = lltype.malloc(clibffi.FFI_TYPE_PP.TO, 1, flavor='raw')
    atypes[0] = clibffi.cast_type_to_ffitype(rffi.DOUBLE)
    cd.atypes = atypes
    cd.exchange_size = 64  # 64 bytes of exchange data
    cd.exchange_result = 24
    cd.exchange_args[0] = 16
    #
    jit_ffi_prep_cif(cd)
    #
    assert rffi.sizeof(rffi.DOUBLE) == 8
    exb = lltype.malloc(rffi.DOUBLEP.TO, 8, flavor='raw')
    exb[2] = 1.23
    jit_ffi_call(cd, math_sin, rffi.cast(rffi.CCHARP, exb))
    res = exb[3]
    lltype.free(exb, flavor='raw')
    #
    lltype.free(atypes, flavor='raw')
    lltype.free(cd, flavor='raw')
    #
    assert res == math.sin(1.23)
 def f():
     #
     jit_ffi_prep_cif(cd)
     #
     assert rffi.sizeof(rffi.DOUBLE) == 8
     exb = lltype.malloc(rffi.DOUBLEP.TO, 8, flavor='raw')
     exb[2] = 1.23
     jit_ffi_call(cd, math_sin, rffi.cast(rffi.CCHARP, exb))
     res = exb[3]
     lltype.free(exb, flavor='raw')
     #
     return res
Ejemplo n.º 4
0
 def f():
     #
     jit_ffi_prep_cif(cd)
     #
     assert rffi.sizeof(rffi.DOUBLE) == 8
     exb = lltype.malloc(rffi.DOUBLEP.TO, 8, flavor='raw')
     exb[2] = 1.23
     jit_ffi_call(cd, math_sin, rffi.cast(rffi.CCHARP, exb))
     res = exb[3]
     lltype.free(exb, flavor='raw')
     #
     return res
Ejemplo n.º 5
0
    def prepare_cif(self):
        argc = len(self.argtypes)

        # atypes points to an array of ffi_type pointers
        cif = lltype.malloc(jit_libffi.CIF_DESCRIPTION, argc, flavor='raw')
        cif.abi = clibffi.FFI_DEFAULT_ABI
        cif.atypes = lltype.malloc(clibffi.FFI_TYPE_PP.TO, argc, flavor='raw')
        for i in range(argc):
            cif.atypes[i] = self.argtypes[i].cast_to_ffitype()
        cif.nargs = argc
        restype = self.restype
        if restype is null:
            cif.rtype = clibffi.ffi_type_void
        # MSVC returns small structures in registers.  Pretend int32 or
        # int64 return type.  This is needed as a workaround for what
        # is really a bug of libffi_msvc seen as an independent library
        # (ctypes and pypy has a similar workaround).
        # Implementation of this workaround doesn't reach to elsewhere from here.
        elif USE_C_LIBFFI_MSVC and isinstance(restype,
                                              Struct) and restype.size <= 4:
            cif.rtype = clibffi.ffi_type_sint32
        elif USE_C_LIBFFI_MSVC and isinstance(restype,
                                              Struct) and restype.size <= 8:
            cif.rtype = clibffi.ffi_type_sint64
        else:
            cif.rtype = restype.cast_to_ffitype()

        exchange_size = argc * rffi.sizeof(rffi.VOIDPP)
        exchange_size = align(exchange_size, 8)
        for i in range(argc):
            argtype = self.argtypes[i]
            assert isinstance(argtype, Type)  # checked prior that this holds.
            exchange_size = align(exchange_size, max(8, argtype.align))
            cif.exchange_args[i] = int(exchange_size)
            exchange_size += sizeof(argtype)
        #cif.exchange_result_libffi = exchange_size
        if restype is null:
            exchange_size = align(exchange_size, 8)
            cif.exchange_result = int(exchange_size)
            exchange_size += jit_libffi.SIZE_OF_FFI_ARG
        elif isinstance(restype, Type):
            exchange_size = align(exchange_size, max(8, restype.align))
            cif.exchange_result = int(exchange_size)
            exchange_size += max(sizeof(restype), jit_libffi.SIZE_OF_FFI_ARG)
        else:  # SIZE_OF_FFI_ARG
            assert False  # checked prior that this holds.
        cif.exchange_size = int(align(exchange_size, 8))
        jit_libffi.jit_ffi_prep_cif(cif)
        self.cif = cif
Ejemplo n.º 6
0
    def rawallocate(self, ctypefunc):
        space = ctypefunc.space
        self.space = space

        # compute the total size needed in the CIF_DESCRIPTION buffer
        self.nb_bytes = 0
        self.bufferp = lltype.nullptr(rffi.CCHARP.TO)
        self.fb_build()

        # allocate the buffer
        if we_are_translated():
            rawmem = lltype.malloc(rffi.CCHARP.TO, self.nb_bytes, flavor="raw")
            rawmem = rffi.cast(CIF_DESCRIPTION_P, rawmem)
        else:
            # gross overestimation of the length below, but too bad
            rawmem = lltype.malloc(CIF_DESCRIPTION_P.TO, self.nb_bytes, flavor="raw")

        # the buffer is automatically managed from the W_CTypeFunc instance
        ctypefunc.cif_descr = rawmem

        # call again fb_build() to really build the libffi data structures
        self.bufferp = rffi.cast(rffi.CCHARP, rawmem)
        self.fb_build()
        assert self.bufferp == rffi.ptradd(rffi.cast(rffi.CCHARP, rawmem), self.nb_bytes)

        # fill in the 'exchange_*' fields
        self.fb_build_exchange(rawmem)

        # fill in the extra fields
        self.fb_extra_fields(rawmem)

        # call libffi's ffi_prep_cif() function
        res = jit_libffi.jit_ffi_prep_cif(rawmem)
        if res != clibffi.FFI_OK:
            raise OperationError(space.w_SystemError, space.wrap("libffi failed to build this function type"))
Ejemplo n.º 7
0
    def prepare_cif(self):
        argc = len(self.argtypes)

        # atypes points to an array of ffi_type pointers
        cif = lltype.malloc(jit_libffi.CIF_DESCRIPTION, argc, flavor='raw')
        cif.abi = clibffi.FFI_DEFAULT_ABI
        cif.atypes = lltype.malloc(clibffi.FFI_TYPE_PP.TO, argc, flavor='raw')
        for i in range(argc):
            cif.atypes[i] = self.argtypes[i].cast_to_ffitype()
        cif.nargs = argc
        restype = self.restype
        if restype is null:
            cif.rtype = clibffi.ffi_type_void
        # MSVC returns small structures in registers.  Pretend int32 or
        # int64 return type.  This is needed as a workaround for what
        # is really a bug of libffi_msvc seen as an independent library
        # (ctypes and pypy has a similar workaround).
        # Implementation of this workaround doesn't reach to elsewhere from here.
        elif USE_C_LIBFFI_MSVC and isinstance(restype, Struct) and restype.size <= 4:
            cif.rtype = clibffi.ffi_type_sint32
        elif USE_C_LIBFFI_MSVC and isinstance(restype, Struct) and restype.size <= 8:
            cif.rtype = clibffi.ffi_type_sint64
        else:
            cif.rtype = restype.cast_to_ffitype()
 
        exchange_size = argc * rffi.sizeof(rffi.VOIDPP)
        exchange_size = align(exchange_size, 8)
        for i in range(argc):
            argtype = self.argtypes[i]
            assert isinstance(argtype, Type) # checked prior that this holds.
            exchange_size = align(exchange_size, max(8, argtype.align))
            cif.exchange_args[i] = int(exchange_size)
            exchange_size += sizeof(argtype)
        #cif.exchange_result_libffi = exchange_size
        if restype is null:
            exchange_size = align(exchange_size, 8)
            cif.exchange_result = int(exchange_size)
            exchange_size += jit_libffi.SIZE_OF_FFI_ARG
        elif isinstance(restype, Type):
            exchange_size = align(exchange_size, max(8, restype.align))
            cif.exchange_result = int(exchange_size)
            exchange_size += max(sizeof(restype), jit_libffi.SIZE_OF_FFI_ARG)
        else: # SIZE_OF_FFI_ARG
            assert False # checked prior that this holds.
        cif.exchange_size = int(align(exchange_size, 8))
        jit_libffi.jit_ffi_prep_cif(cif)
        self.cif = cif
Ejemplo n.º 8
0
Archivo: ffi.py Proyecto: Xsan-21/pixie
    def thaw(self):
        if not self._is_inited:
            self._f_ptr = self._lib.get_fn_ptr(self._name)
            nargs = len(self._arg_types)

            exchange_buffer_size = nargs * rffi.sizeof(rffi.CCHARP)

            cd = lltype.malloc(CIF_DESCRIPTION, nargs, flavor="raw")
            cd.abi = clibffi.FFI_DEFAULT_ABI
            cd.nargs = nargs
            cd.rtype = self._ret_type.ffi_type()

            atypes = lltype.malloc(clibffi.FFI_TYPE_PP.TO, nargs, flavor="raw")
            arg0_offset = exchange_buffer_size
            for idx in range(nargs):
                cd.exchange_args[idx] = exchange_buffer_size
                tp = self._arg_types[idx]
                native_size = tp.ffi_size()
                atypes[idx] = tp.ffi_type()
                exchange_buffer_size += native_size

            ret_offset = exchange_buffer_size
            exchange_buffer_size += self._ret_type.ffi_size()



            cd.atypes = atypes
            cd.exchange_size = exchange_buffer_size
            cd.exchange_result = ret_offset
            cd.exchange_result_libffi = ret_offset

            jit_ffi_prep_cif(cd)
            self._cd = cd
            self._transfer_size = exchange_buffer_size
            self._arg0_offset = arg0_offset
            self._ret_offset = ret_offset

            self._is_inited = True

        return self
Ejemplo n.º 9
0
    def thaw(self):
        if not self._is_inited:
            self._f_ptr = self._lib.get_fn_ptr(self._name)
            transfer_size = 0
            arg0_offset = len(self._arg_types) * rffi.sizeof(rffi.CCHARP)
            exchange_result = arg0_offset
            for x in self._arg_types:
                exchange_result = transfer_size
                transfer_size += get_native_size(x)

            ret_offset = transfer_size
            transfer_size += get_native_size(self._ret_type)

            cd = lltype.malloc(CIF_DESCRIPTION, len(self._arg_types), flavor="raw")
            cd.abi = clibffi.FFI_DEFAULT_ABI
            cd.nargs = len(self._arg_types)
            cd.rtype = get_clibffi_type(self._ret_type)
            atypes = lltype.malloc(clibffi.FFI_TYPE_PP.TO, len(self._arg_types), flavor="raw")

            for x in range(len(self._arg_types)):
                atypes[x] = get_clibffi_type(self._arg_types[x])



            cd.atypes = atypes
            cd.exchange_size = transfer_size
            cd.exchange_result = ret_offset
            cd.exchange_result_libffi = ret_offset
            cd.exchange_args[0] = arg0_offset

            jit_ffi_prep_cif(cd)
            self._cd = cd
            self._transfer_size = transfer_size
            self._arg0_offset = arg0_offset
            self._ret_offset = ret_offset

            self._is_inited = True

        return self
Ejemplo n.º 10
0
    def thaw(self):
        if not self._is_inited:
            self._f_ptr = self._lib.get_fn_ptr(self._name)
            nargs = len(self._arg_types)

            exchange_buffer_size = nargs * rffi.sizeof(rffi.CCHARP)

            cd = lltype.malloc(CIF_DESCRIPTION, nargs, flavor="raw")
            cd.abi = clibffi.FFI_DEFAULT_ABI
            cd.nargs = nargs
            cd.rtype = self._ret_type.ffi_type()

            atypes = lltype.malloc(clibffi.FFI_TYPE_PP.TO, nargs, flavor="raw")
            arg0_offset = exchange_buffer_size
            for idx in range(nargs):
                cd.exchange_args[idx] = exchange_buffer_size
                tp = self._arg_types[idx]
                native_size = tp.ffi_size()
                atypes[idx] = tp.ffi_type()
                exchange_buffer_size += native_size

            ret_offset = exchange_buffer_size
            exchange_buffer_size += self._ret_type.ffi_size()

            cd.atypes = atypes
            cd.exchange_size = exchange_buffer_size
            cd.exchange_result = ret_offset
            cd.exchange_result_libffi = ret_offset

            jit_ffi_prep_cif(cd)
            self._cd = cd
            self._transfer_size = exchange_buffer_size
            self._arg0_offset = arg0_offset
            self._ret_offset = ret_offset

            self._is_inited = True

        return self
Ejemplo n.º 11
0
    def prepare_cif(self):
        argc = len(self.argtypes)

        # atypes points to an array of ffi_type pointers
        cif = lltype.malloc(jit_libffi.CIF_DESCRIPTION, argc, flavor='raw')
        cif.abi = clibffi.FFI_DEFAULT_ABI
        cif.atypes = lltype.malloc(clibffi.FFI_TYPE_PP.TO, argc, flavor='raw')
        for i in range(argc):
            cif.atypes[i] = self.argtypes[i].cast_to_ffitype()
        cif.nargs = argc
        if self.restype is null:
            cif.rtype = clibffi.ffi_type_void
        else:
            cif.rtype = self.restype.cast_to_ffitype()
 
        exchange_size = argc * rffi.sizeof(rffi.VOIDPP)
        exchange_size = align(exchange_size, 8)
        for i in range(argc):
            argtype = self.argtypes[i]
            assert isinstance(argtype, Type) # checked prior that this holds.
            exchange_size = align(exchange_size, max(8, argtype.align))
            cif.exchange_args[i] = int(exchange_size)
            exchange_size += sizeof(argtype)
        #cif.exchange_result_libffi = exchange_size
        restype = self.restype
        if restype is null:
            exchange_size = align(exchange_size, 8)
            cif.exchange_result = int(exchange_size)
            exchange_size += jit_libffi.SIZE_OF_FFI_ARG
        elif isinstance(restype, Type):
            exchange_size = align(exchange_size, max(8, restype.align))
            cif.exchange_result = int(exchange_size)
            exchange_size += max(sizeof(restype), jit_libffi.SIZE_OF_FFI_ARG)
        else: # SIZE_OF_FFI_ARG
            assert False # checked prior that this holds.
        cif.exchange_size = int(align(exchange_size, 8))
        jit_libffi.jit_ffi_prep_cif(cif)
        self.cif = cif
Ejemplo n.º 12
0
    def prepare_cif(self):
        argc = len(self.argtypes)

        # atypes points to an array of ffi_type pointers
        cif = lltype.malloc(jit_libffi.CIF_DESCRIPTION, argc, flavor='raw')
        cif.abi = clibffi.FFI_DEFAULT_ABI
        cif.atypes = lltype.malloc(clibffi.FFI_TYPE_PP.TO, argc, flavor='raw')
        for i in range(argc):
            cif.atypes[i] = self.argtypes[i].cast_to_ffitype()
        cif.nargs = argc
        if self.restype is null:
            cif.rtype = clibffi.ffi_type_void
        else:
            cif.rtype = self.restype.cast_to_ffitype()
 
        exchange_size = argc * rffi.sizeof(rffi.VOIDPP)
        exchange_size = align(exchange_size, 8)
        for i in range(argc):
            argtype = self.argtypes[i]
            assert isinstance(argtype, Type) # checked prior that this holds.
            exchange_size = align(exchange_size, max(8, argtype.align))
            cif.exchange_args[i] = int(exchange_size)
            exchange_size += sizeof(argtype)
        #cif.exchange_result_libffi = exchange_size
        restype = self.restype
        if restype is null:
            exchange_size = align(exchange_size, 8)
            cif.exchange_result = int(exchange_size)
            exchange_size += jit_libffi.SIZE_OF_FFI_ARG
        elif isinstance(restype, Type):
            exchange_size = align(exchange_size, max(8, restype.align))
            cif.exchange_result = int(exchange_size)
            exchange_size += max(sizeof(restype), jit_libffi.SIZE_OF_FFI_ARG)
        else: # SIZE_OF_FFI_ARG
            assert False # checked prior that this holds.
        cif.exchange_size = int(align(exchange_size, 8))
        jit_libffi.jit_ffi_prep_cif(cif)
        self.cif = cif
Ejemplo n.º 13
0
    def prepare_cif(self):
        argc = len(self.argtypes)

        # atypes points to an array of ffi_type pointers
        cif = lltype.malloc(jit_libffi.CIF_DESCRIPTION, argc, flavor='raw')
        cif.abi = clibffi.FFI_DEFAULT_ABI
        cif.atypes = lltype.malloc(clibffi.FFI_TYPE_PP.TO, argc, flavor='raw')
        for i in range(argc):
            cif.atypes[i] = self.argtypes[i].cast_to_ffitype()
        cif.nargs = argc
        if self.restype is null:
            cif.rtype = clibffi.ffi_type_void
        else:
            cif.rtype = self.restype.cast_to_ffitype()

        exchange_size = argc * rffi.sizeof(rffi.VOIDPP)
        for i in range(argc):
            argtype = self.argtypes[i]
            assert isinstance(argtype, Type)
            exchange_size = align(exchange_size, argtype.align)
            cif.exchange_args[i] = exchange_size
            exchange_size += sizeof(argtype)
        cif.exchange_result = exchange_size
        #cif.exchange_result_libffi = exchange_size
        restype = self.restype
        if restype is null:
            exchange_size += 0
        elif isinstance(restype, Type):
            exchange_size = align(exchange_size, restype.align)
            exchange_size += sizeof(restype)
        else:
            assert False
        cif.exchange_size = align(exchange_size, 8)

        jit_libffi.jit_ffi_prep_cif(cif)
        self.cif = cif
Ejemplo n.º 14
0
    def prepare_cif(self):
        argc = len(self.argtypes)

        # atypes points to an array of ffi_type pointers
        cif = lltype.malloc(jit_libffi.CIF_DESCRIPTION, argc, flavor='raw')
        cif.abi = clibffi.FFI_DEFAULT_ABI
        cif.atypes = lltype.malloc(clibffi.FFI_TYPE_PP.TO, argc, flavor='raw')
        for i in range(argc):
            cif.atypes[i] = self.argtypes[i].cast_to_ffitype()
        cif.nargs = argc
        if self.restype is null:
            cif.rtype = clibffi.ffi_type_void
        else:
            cif.rtype = self.restype.cast_to_ffitype()
 
        exchange_size = argc * rffi.sizeof(rffi.VOIDPP)
        for i in range(argc):
            argtype = self.argtypes[i]
            assert isinstance(argtype, Type)
            exchange_size = align(exchange_size, argtype.align)
            cif.exchange_args[i] = exchange_size
            exchange_size += sizeof(argtype)
        cif.exchange_result = exchange_size
        #cif.exchange_result_libffi = exchange_size
        restype = self.restype
        if restype is null:
            exchange_size += 0
        elif isinstance(restype, Type):
            exchange_size = align(exchange_size, restype.align)
            exchange_size += sizeof(restype)
        else:
            assert False
        cif.exchange_size = align(exchange_size, 8)

        jit_libffi.jit_ffi_prep_cif(cif)
        self.cif = cif
Ejemplo n.º 15
0
    def rawallocate(self, ctypefunc):
        space = ctypefunc.space
        self.space = space

        # compute the total size needed in the CIF_DESCRIPTION buffer
        self.nb_bytes = 0
        self.bufferp = lltype.nullptr(rffi.CCHARP.TO)
        self.fb_build()

        # allocate the buffer
        if we_are_translated():
            rawmem = lltype.malloc(rffi.CCHARP.TO, self.nb_bytes, flavor='raw')
            rawmem = rffi.cast(CIF_DESCRIPTION_P, rawmem)
        else:
            # gross overestimation of the length below, but too bad
            rawmem = lltype.malloc(CIF_DESCRIPTION_P.TO,
                                   self.nb_bytes,
                                   flavor='raw')

        # the buffer is automatically managed from the W_CTypeFunc instance
        ctypefunc.cif_descr = rawmem

        # call again fb_build() to really build the libffi data structures
        self.bufferp = rffi.cast(rffi.CCHARP, rawmem)
        self.fb_build()
        assert self.bufferp == rffi.ptradd(rffi.cast(rffi.CCHARP, rawmem),
                                           self.nb_bytes)

        # fill in the 'exchange_*' fields
        self.fb_build_exchange(rawmem)

        # fill in the extra fields
        self.fb_extra_fields(rawmem)

        # call libffi's ffi_prep_cif() function
        res = jit_libffi.jit_ffi_prep_cif(rawmem)
        if res != clibffi.FFI_OK:
            raise OperationError(
                space.w_SystemError,
                space.wrap("libffi failed to build this function type"))
Ejemplo n.º 16
0
def builtin_ffi_function(ctx):
    # parameter validation
    assert len(ctx.params) == 4 and \
            ctx.params[0].type == 'str' and \
            ctx.params[1].type == 'str' \
            and ctx.params[2].type == 'str' \
            and ctx.params[3].type == 'array'
    for e in ctx.params[3].arrayvalue:
        assert e.type == 'str'

    # extract parameters
    libname = ctx.params[0].strvalue
    funcname = ctx.params[1].strvalue
    rtype = ctx.params[2].strvalue
    atypes = [e.strvalue for e in ctx.params[3].arrayvalue]

    # validate if we defined before
    if (libname, funcname) in ctx.machine.space.ffi_functions:
        ctx.machine.error = ctx.machine.space.newstr(
            'cannot define %s twice in %s.' % (funcname, libname))
        return

    # setup cif
    argc = len(atypes)
    cif = lltype.malloc(jit_libffi.CIF_DESCRIPTION, argc, flavor='raw')
    cif.abi = clibffi.FFI_DEFAULT_ABI
    cif.nargs = argc
    cif.rtype = _cast_aotype_to_ffitype(rtype)
    cif.atypes = lltype.malloc(clibffi.FFI_TYPE_PP.TO, argc, flavor='raw')

    # create room for an array of nargs pointers
    exchange_offset = rffi.sizeof(rffi.VOIDP) * argc
    exchange_offset = _align(exchange_offset)
    cif.exchange_result = exchange_offset

    # create room for return value, roundup to sizeof(ffi-arg)
    exchange_offset += max(rffi.getintfield(cif.rtype, 'c_size'),
                           jit_libffi.SIZE_OF_FFI_ARG)

    # set size for each arg
    for i in range(argc):
        atype = _cast_aotype_to_ffitype(atypes[i])
        cif.atypes[i] = atype
        exchange_offset = _align(exchange_offset)
        cif.exchange_args[i] = exchange_offset
        exchange_offset += rffi.getintfield(atype, 'c_size')

    # set total size of args + retval
    cif.exchange_size = exchange_offset

    # prepare cif
    code = jit_libffi.jit_ffi_prep_cif(cif)
    if code != clibffi.FFI_OK:
        ctx.machine.error = ctx.machine.space.newstr(
            'failed to build function %s for lib %s.' % (funcname, libname))
        return

    # cache ffi
    ffi = ctx.machine.space.newforeignfunction(libname, funcname, rtype,
                                               atypes, cif)
    ctx.machine.space.ffi_functions[(libname, funcname)] = ffi
    ctx.tos.push(ctx.machine.space.null)
Ejemplo n.º 17
0
    def build_cif_descr(self, space):
        arg_types_w = self.arg_types_w
        w_ret_type = self.w_ret_type
        assert isinstance(w_ret_type, W_TypeObject)

        ffi_arg_types = []
        for w_arg_type in arg_types_w:
            assert isinstance(w_arg_type, W_TypeObject)
            ffi_arg_type = ffitype.ffi_types[w_arg_type.typeindex]
            ffi_arg_types.append(ffi_arg_type)
        ffi_ret_type = ffitype.ffi_types[w_ret_type.typeindex]

        nargs = len(ffi_arg_types)
        # XXX combine both mallocs with alignment
        size = llmemory.raw_malloc_usage(
            llmemory.sizeof(CIF_DESCRIPTION, nargs))
        if we_are_translated():
            cif_descr = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw')
            cif_descr = rffi.cast(CIF_DESCRIPTION_P, cif_descr)
        else:
            # gross overestimation of the length below, but too bad
            cif_descr = lltype.malloc(CIF_DESCRIPTION_P.TO, size, flavor='raw')
        assert cif_descr
        #
        size = rffi.sizeof(FFI_TYPE_P) * nargs
        atypes = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw')
        atypes = rffi.cast(FFI_TYPE_PP, atypes)
        assert atypes
        #
        cif_descr.abi = clibffi.FFI_DEFAULT_ABI
        cif_descr.nargs = nargs
        cif_descr.rtype = ffi_ret_type
        cif_descr.atypes = atypes
        #
        # first, enough room for an array of 'nargs' pointers
        exchange_offset = rffi.sizeof(rffi.CCHARP) * nargs
        exchange_offset = self.align_arg(exchange_offset)
        cif_descr.exchange_result = exchange_offset
        # cif_descr.exchange_result_libffi = exchange_offset
        #
        if BIG_ENDIAN:
            assert 0, 'missing support'
            # see _cffi_backend in pypy
        # then enough room for the result, rounded up to sizeof(ffi_arg)
        exchange_offset += max(rffi.getintfield(ffi_ret_type, 'c_size'),
                               SIZE_OF_FFI_ARG)

        # loop over args
        for i, ffi_arg in enumerate(ffi_arg_types):
            # XXX do we need the "must free" logic?
            exchange_offset = self.align_arg(exchange_offset)
            cif_descr.exchange_args[i] = exchange_offset
            atypes[i] = ffi_arg
            exchange_offset += rffi.getintfield(ffi_arg, 'c_size')

        # store the exchange data size
        cif_descr.exchange_size = exchange_offset
        #
        status = jit_ffi_prep_cif(cif_descr)
        #
        if status != clibffi.FFI_OK:
            raise space.error(space.w_RuntimeError,
                              "libffi failed to build this function type")
        #
        return cif_descr
Ejemplo n.º 18
0
    def _setup(self, cppthis):
        self.converters = [converter.get_converter(self.space, arg_type, arg_dflt)
                               for arg_type, arg_dflt in self.arg_defs]
        self.executor = executor.get_executor(
            self.space, capi.c_method_result_type(self.space, self.scope, self.index))

        for conv in self.converters:
            if conv.uses_local:
                self.uses_local = True
                break

        # Each CPPMethod corresponds one-to-one to a C++ equivalent and cppthis
        # has been offset to the matching class. Hence, the libffi pointer is
        # uniquely defined and needs to be setup only once.
        methgetter = capi.c_get_methptr_getter(self.space, self.scope, self.index)
        if methgetter and cppthis:      # methods only for now
            cif_descr = lltype.nullptr(jit_libffi.CIF_DESCRIPTION)
            try:
                funcaddr = methgetter(rffi.cast(capi.C_OBJECT, cppthis))
                self._funcaddr = rffi.cast(rffi.VOIDP, funcaddr)

                nargs = self.args_expected + 1                   # +1: cppthis

                # memory block for CIF description (note: not tracked as the life
                # time of methods is normally the duration of the application)
                size = llmemory.sizeof(jit_libffi.CIF_DESCRIPTION, nargs)

                # allocate the buffer
                cif_descr = lltype.malloc(jit_libffi.CIF_DESCRIPTION_P.TO,
                                          llmemory.raw_malloc_usage(size),
                                          flavor='raw', track_allocation=False)

                # array of 'ffi_type*' values, one per argument
                size = rffi.sizeof(jit_libffi.FFI_TYPE_P) * nargs
                atypes = lltype.malloc(rffi.CCHARP.TO, llmemory.raw_malloc_usage(size),
                                       flavor='raw', track_allocation=False)
                cif_descr.atypes = rffi.cast(jit_libffi.FFI_TYPE_PP, atypes)

                # argument type specification
                cif_descr.atypes[0] = jit_libffi.types.pointer   # cppthis
                for i, conv in enumerate(self.converters):
                    if not conv.libffitype:
                        raise FastCallNotPossible
                    cif_descr.atypes[i+1] = conv.libffitype

                # result type specification
                cif_descr.rtype = self.executor.libffitype

                # exchange ---

                # first, enough room for an array of 'nargs' pointers
                exchange_offset = rffi.sizeof(rffi.CCHARP) * nargs
                exchange_offset = (exchange_offset + 7) & ~7     # alignment
                cif_descr.exchange_result = exchange_offset
                cif_descr.exchange_result_libffi = exchange_offset

                # TODO: left this out while testing (see ctypefunc.py)
                # For results of precisely these types, libffi has a
                # strange rule that they will be returned as a whole
                # 'ffi_arg' if they are smaller.  The difference
                # only matters on big-endian.

                # then enough room for the result, rounded up to sizeof(ffi_arg)
                exchange_offset += max(rffi.getintfield(cif_descr.rtype, 'c_size'),
                                       jit_libffi.SIZE_OF_FFI_ARG)

                # loop over args
                for i in range(nargs):
                    exchange_offset = (exchange_offset + 7) & ~7 # alignment
                    cif_descr.exchange_args[i] = exchange_offset
                    exchange_offset += rffi.getintfield(cif_descr.atypes[i], 'c_size')

                # store the exchange data size
                cif_descr.exchange_size = exchange_offset

                # --- exchange

                # extra
                cif_descr.abi = clibffi.FFI_DEFAULT_ABI
                cif_descr.nargs = self.args_expected + 1         # +1: cppthis

                res = jit_libffi.jit_ffi_prep_cif(cif_descr)
                if res != clibffi.FFI_OK:
                    raise FastCallNotPossible

            except Exception, e:
                if cif_descr:
                    lltype.free(cif_descr.atypes, flavor='raw', track_allocation=False)
                    lltype.free(cif_descr, flavor='raw', track_allocation=False)
                cif_descr = lltype.nullptr(jit_libffi.CIF_DESCRIPTION)
                self._funcaddr = lltype.nullptr(rffi.VOIDP.TO)

            self.cif_descr = cif_descr
Ejemplo n.º 19
0
    def build_cif_descr(self, space):
        arg_types_w = self.arg_types_w
        w_ret_type = self.w_ret_type
        assert isinstance(w_ret_type, W_TypeObject)

        ffi_arg_types = []
        for w_arg_type in arg_types_w:
            assert isinstance(w_arg_type, W_TypeObject)
            ffi_arg_type = ffitype.ffi_types[w_arg_type.typeindex]
            ffi_arg_types.append(ffi_arg_type)
        ffi_ret_type = ffitype.ffi_types[w_ret_type.typeindex]

        nargs = len(ffi_arg_types)
        # XXX combine both mallocs with alignment
        size = llmemory.raw_malloc_usage(
            llmemory.sizeof(CIF_DESCRIPTION, nargs))
        if we_are_translated():
            cif_descr = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw')
            cif_descr = rffi.cast(CIF_DESCRIPTION_P, cif_descr)
        else:
            # gross overestimation of the length below, but too bad
            cif_descr = lltype.malloc(CIF_DESCRIPTION_P.TO, size, flavor='raw')
        assert cif_descr
        #
        size = rffi.sizeof(FFI_TYPE_P) * nargs
        atypes = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw')
        atypes = rffi.cast(FFI_TYPE_PP, atypes)
        assert atypes
        #
        cif_descr.abi = clibffi.FFI_DEFAULT_ABI
        cif_descr.nargs = nargs
        cif_descr.rtype = ffi_ret_type
        cif_descr.atypes = atypes
        #
        # first, enough room for an array of 'nargs' pointers
        exchange_offset = rffi.sizeof(rffi.CCHARP) * nargs
        exchange_offset = self.align_arg(exchange_offset)
        cif_descr.exchange_result = exchange_offset
        # cif_descr.exchange_result_libffi = exchange_offset
        #
        if BIG_ENDIAN:
            assert 0, 'missing support'
            # see _cffi_backend in pypy
        # then enough room for the result, rounded up to sizeof(ffi_arg)
        exchange_offset += max(rffi.getintfield(ffi_ret_type, 'c_size'),
                               SIZE_OF_FFI_ARG)

        # loop over args
        for i, ffi_arg in enumerate(ffi_arg_types):
            # XXX do we need the "must free" logic?
            exchange_offset = self.align_arg(exchange_offset)
            cif_descr.exchange_args[i] = exchange_offset
            atypes[i] = ffi_arg
            exchange_offset += rffi.getintfield(ffi_arg, 'c_size')

        # store the exchange data size
        cif_descr.exchange_size = exchange_offset
        #
        status = jit_ffi_prep_cif(cif_descr)
        #
        if status != clibffi.FFI_OK:
            raise space.error(
                space.w_RuntimeError,
                "libffi failed to build this function type")
        #
        return cif_descr