Example #1
0
 def graph2delayed(self, graph, FUNCTYPE=None):
     if FUNCTYPE is None:
         FUNCTYPE = lltype.ForwardReference()
     # obscure hack: embed the name of the function in the string, so
     # that the genc database can get it even before the delayedptr
     # is really computed
     name = "delayed!%s" % (graph.name,)
     delayedptr = lltype._ptr(lltype.Ptr(FUNCTYPE), name, solid=True)
     self.delayedfuncs.append((delayedptr, graph))
     return delayedptr
Example #2
0
    def delayedconst(self, repr, obj):
        if repr.is_setup_delayed():
            # record the existence of this 'obj' for the bookkeeper - e.g.
            # if 'obj' is an instance, this will populate the classdef with
            # the prebuilt attribute values of the instance
            bk = self.rtyper.annotator.bookkeeper
            bk.immutablevalue(obj)

            delayedptr = lltype._ptr(repr.lowleveltype, "delayed!")
            self.delayedconsts.append((delayedptr, repr, obj))
            return delayedptr
        else:
            return repr.convert_const(obj)
Example #3
0
def ctypes2lltype(T, cobj):
    """Convert the ctypes object 'cobj' to its lltype equivalent.
    'T' is the expected lltype type.
    """
    if isinstance(T, lltype.Ptr):
        if not cobj:  # NULL pointer
            return lltype.nullptr(T.TO)
        if isinstance(T.TO, lltype.Struct):
            if T.TO._arrayfld is not None:
                lgt = getattr(cobj.contents, T.TO._arrayfld).length
                container = lltype._struct(T.TO, lgt)
            else:
                container = lltype._struct(T.TO)
            struct_use_ctypes_storage(container, cobj.contents)
        elif isinstance(T.TO, lltype.Array):
            if T.TO._hints.get('nolength', False):
                container = _array_of_unknown_length(T.TO)
                container._storage = cobj.contents
            else:
                raise NotImplementedError("array with an explicit length")
        elif isinstance(T.TO, lltype.FuncType):
            _callable = get_ctypes_trampoline(T.TO, cobj)
            return lltype.functionptr(T.TO,
                                      getattr(cobj, '__name__', '?'),
                                      _callable=_callable)
        elif isinstance(T.TO, lltype.OpaqueType):
            container = lltype._opaque(T.TO)
        else:
            raise NotImplementedError(T)
        llobj = lltype._ptr(T, container, solid=True)
    elif T is lltype.Char:
        llobj = chr(cobj)
    elif T is lltype.UniChar:
        llobj = unichr(cobj)
    elif T is lltype.Signed:
        llobj = cobj
    elif T is lltype.SingleFloat:
        if isinstance(cobj, ctypes.c_float):
            cobj = cobj.value
        llobj = r_singlefloat(cobj)
    else:
        from pypy.rpython.lltypesystem import rffi
        try:
            inttype = rffi.platform.numbertype_to_rclass[T]
        except KeyError:
            llobj = cobj
        else:
            llobj = inttype(cobj)

    assert lltype.typeOf(llobj) == T
    return llobj
Example #4
0
def ctypes2lltype(T, cobj):
    """Convert the ctypes object 'cobj' to its lltype equivalent.
    'T' is the expected lltype type.
    """
    if isinstance(T, lltype.Ptr):
        if not cobj:   # NULL pointer
            return lltype.nullptr(T.TO)
        if isinstance(T.TO, lltype.Struct):
            if T.TO._arrayfld is not None:
                raise NotImplementedError("XXX var-sized structs")
            container = lltype._struct(T.TO)
            struct_use_ctypes_storage(container, cobj.contents)
        elif isinstance(T.TO, lltype.Array):
            if T.TO._hints.get('nolength', False):
                container = _array_of_unknown_length(T.TO)
                container._storage = cobj.contents
            else:
                raise NotImplementedError("array with an explicit length")
        elif isinstance(T.TO, lltype.FuncType):
            _callable = get_ctypes_trampoline(T.TO, cobj)
            return lltype.functionptr(T.TO, getattr(cobj, '__name__', '?'),
                                      _callable=_callable)
        elif isinstance(T.TO, lltype.OpaqueType):
            container = lltype._opaque(T.TO)
        else:
            raise NotImplementedError(T)
        llobj = lltype._ptr(T, container, solid=True)
    elif T is lltype.Char:
        llobj = chr(cobj)
    elif T is lltype.UniChar:
        llobj = unichr(cobj)
    elif T is lltype.Signed:
        llobj = cobj
    elif T is lltype.SingleFloat:
        if isinstance(cobj, ctypes.c_float):
            cobj = cobj.value
        llobj = r_singlefloat(cobj)
    else:
        from pypy.rpython.lltypesystem import rffi
        try:
            inttype = rffi.platform.numbertype_to_rclass[T]
        except KeyError:
            llobj = cobj
        else:
            llobj = inttype(cobj)

    assert lltype.typeOf(llobj) == T
    return llobj
Example #5
0
def guess_size_obj(obj):
    TYPE = typeOf(obj)
    ptr = _ptr(Ptr(TYPE), obj)
    if TYPE._is_varsize():
        arrayfld = getattr(TYPE, '_arrayfld', None)
        if arrayfld:
            length = len(getattr(ptr, arrayfld))
        else:
            try:
                length = len(ptr)
            except TypeError:
                print "couldn't find size of", ptr
                return 0
    else:
        length = None
    return convert_offset_to_int(llmemory.sizeof(TYPE, length))
Example #6
0
 def graph2delayed(self, graph, FUNCTYPE=None):
     if self.rtyper.type_system.name == 'lltypesystem':
         if FUNCTYPE is None:
             FUNCTYPE = lltype.ForwardReference()
         # obscure hack: embed the name of the function in the string, so
         # that the genc database can get it even before the delayedptr
         # is really computed
         name = "delayed!%s" % (graph.name, )
         delayedptr = lltype._ptr(lltype.Ptr(FUNCTYPE), name, solid=True)
     else:
         if FUNCTYPE is None:
             FUNCTYPE = ootype.ForwardReference()
         name = "delayed!%s" % (graph.name, )
         delayedptr = ootype._forward_static_meth(FUNCTYPE, _name=name)
     self.delayedfuncs.append((delayedptr, graph))
     return delayedptr
Example #7
0
def guess_size_obj(obj):
    TYPE = typeOf(obj)
    ptr = _ptr(Ptr(TYPE), obj)
    if TYPE._is_varsize():
        arrayfld = getattr(TYPE, '_arrayfld', None)
        if arrayfld:
            length = len(getattr(ptr, arrayfld))
        else:
            try:
                length = len(ptr)
            except TypeError:
                print "couldn't find size of", ptr
                return 0
    else:
        length = None
    return convert_offset_to_int(llmemory.sizeof(TYPE, length))
Example #8
0
    def delayedconst(self, repr, obj):
        if repr.is_setup_delayed():
            # record the existence of this 'obj' for the bookkeeper - e.g.
            # if 'obj' is an instance, this will populate the classdef with
            # the prebuilt attribute values of the instance
            bk = self.rtyper.annotator.bookkeeper
            bk.immutablevalue(obj)

            if self.rtyper.type_system.name == 'lltypesystem':
                delayedptr = lltype._ptr(repr.lowleveltype, "delayed!")
            else:
                delayedptr = ootype.make_instance(repr.lowleveltype)
            self.delayedconsts.append((delayedptr, repr, obj))
            return delayedptr
        else:
            return repr.convert_const(obj)
Example #9
0
def cast_object_to_ptr(PTR, object):
    """NOT_RPYTHON: hack. The object may be disguised as a PTR now.
    Limited to casting a given object to a single type.
    """
    if isinstance(PTR, lltype.Ptr):
        TO = PTR.TO
    else:
        TO = PTR
    if not hasattr(object, '_carry_around_for_tests'):
        assert not hasattr(object, '_TYPE')
        object._carry_around_for_tests = True
        object._TYPE = TO
    else:
        assert object._TYPE == TO
    #
    if isinstance(PTR, lltype.Ptr):
        return lltype._ptr(PTR, object, True)
    elif isinstance(PTR, ootype.Instance):
        return object
    else:
        raise NotImplementedError("cast_object_to_ptr(%r, ...)" % PTR)
Example #10
0
def cast_object_to_ptr(PTR, object):
    """NOT_RPYTHON: hack. The object may be disguised as a PTR now.
    Limited to casting a given object to a single type.
    """
    if isinstance(PTR, lltype.Ptr):
        TO = PTR.TO
    else:
        TO = PTR
    if not hasattr(object, '_carry_around_for_tests'):
        assert not hasattr(object, '_TYPE')
        object._carry_around_for_tests = True
        object._TYPE = TO
    else:
        assert object._TYPE == TO
    #
    if isinstance(PTR, lltype.Ptr):
        return lltype._ptr(PTR, object, True)
    elif isinstance(PTR, ootype.Instance):
        return object
    else:
        raise NotImplementedError("cast_object_to_ptr(%r, ...)" % PTR)
Example #11
0
def ctypes2lltype(T, cobj):
    """Convert the ctypes object 'cobj' to its lltype equivalent.
    'T' is the expected lltype type.
    """
    if T is lltype.Void:
        return None
    if isinstance(T, lltype.Typedef):
        T = T.OF
    if isinstance(T, lltype.Ptr):
        ptrval = ctypes.cast(cobj, ctypes.c_void_p).value
        if not cobj or not ptrval:   # NULL pointer
            # CFunctionType.__nonzero__ is broken before Python 2.6
            return lltype.nullptr(T.TO)
        if isinstance(T.TO, lltype.Struct):
            if T.TO._gckind == 'gc' and ptrval & 1: # a tagged pointer
                gcref = _opaque_objs[ptrval // 2].hide()
                return lltype.cast_opaque_ptr(T, gcref)
            REAL_TYPE = T.TO
            if T.TO._arrayfld is not None:
                carray = getattr(cobj.contents, T.TO._arrayfld)
                container = lltype._struct(T.TO, carray.length)
            else:
                # special treatment of 'OBJECT' subclasses
                if get_rtyper() and lltype._castdepth(REAL_TYPE, OBJECT) >= 0:
                    # figure out the real type of the object
                    containerheader = lltype._struct(OBJECT)
                    cobjheader = ctypes.cast(cobj,
                                       get_ctypes_type(lltype.Ptr(OBJECT)))
                    struct_use_ctypes_storage(containerheader,
                                              cobjheader)
                    REAL_TYPE = get_rtyper().get_type_for_typeptr(
                        containerheader.typeptr)
                    REAL_T = lltype.Ptr(REAL_TYPE)
                    cobj = ctypes.cast(cobj, get_ctypes_type(REAL_T))
                container = lltype._struct(REAL_TYPE)
            struct_use_ctypes_storage(container, cobj)
            if REAL_TYPE != T.TO:
                p = container._as_ptr()
                container = lltype.cast_pointer(T, p)._as_obj()
            # special treatment of 'OBJECT_VTABLE' subclasses
            if get_rtyper() and lltype._castdepth(REAL_TYPE,
                                                  OBJECT_VTABLE) >= 0:
                # figure out the real object that this vtable points to,
                # and just return that
                p = get_rtyper().get_real_typeptr_for_typeptr(
                    container._as_ptr())
                container = lltype.cast_pointer(T, p)._as_obj()
        elif isinstance(T.TO, lltype.Array):
            if T.TO._hints.get('nolength', False):
                container = _array_of_unknown_length(T.TO)
                container._storage = type(cobj)(cobj.contents)
            else:
                container = _array_of_known_length(T.TO)
                container._storage = type(cobj)(cobj.contents)
        elif isinstance(T.TO, lltype.FuncType):
            cobjkey = intmask(ctypes.cast(cobj, ctypes.c_void_p).value)
            if cobjkey in _int2obj:
                container = _int2obj[cobjkey]
            else:
                _callable = get_ctypes_trampoline(T.TO, cobj)
                return lltype.functionptr(T.TO, getattr(cobj, '__name__', '?'),
                                          _callable=_callable)
        elif isinstance(T.TO, lltype.OpaqueType):
            if T == llmemory.GCREF:
                container = _llgcopaque(cobj)
            else:
                container = lltype._opaque(T.TO)
                cbuf = ctypes.cast(cobj, ctypes.c_void_p)
                add_storage(container, _parentable_mixin, cbuf)
        else:
            raise NotImplementedError(T)
        llobj = lltype._ptr(T, container, solid=True)
    elif T is llmemory.Address:
        if cobj is None:
            llobj = llmemory.NULL
        else:
            llobj = _lladdress(cobj)
    elif T is lltype.Char:
        llobj = chr(cobj)
    elif T is lltype.UniChar:
        try:
            llobj = unichr(cobj)
        except (ValueError, OverflowError):
            for tc in 'HIL':
                if array(tc).itemsize == array('u').itemsize:
                    import struct
                    cobj &= 256 ** struct.calcsize(tc) - 1
                    llobj = array('u', array(tc, (cobj,)).tostring())[0]
                    break
            else:
                raise
    elif T is lltype.Signed:
        llobj = cobj
    elif T is lltype.Bool:
        assert cobj == True or cobj == False    # 0 and 1 work too
        llobj = bool(cobj)
    elif T is lltype.SingleFloat:
        if isinstance(cobj, ctypes.c_float):
            cobj = cobj.value
        llobj = r_singlefloat(cobj)
    elif T is lltype.LongFloat:
        if isinstance(cobj, ctypes.c_longdouble):
            cobj = cobj.value
        llobj = r_longfloat(cobj)
    elif T is lltype.Void:
        llobj = cobj
    else:
        from pypy.rpython.lltypesystem import rffi
        try:
            inttype = rffi.platform.numbertype_to_rclass[T]
        except KeyError:
            llobj = cobj
        else:
            llobj = inttype(cobj)

    assert lltype.typeOf(llobj) == T
    return llobj
Example #12
0
def ctypes2lltype(T, cobj):
    """Convert the ctypes object 'cobj' to its lltype equivalent.
    'T' is the expected lltype type.
    """
    if T is lltype.Void:
        return None
    if isinstance(T, lltype.Ptr):
        if not cobj:   # NULL pointer
            return lltype.nullptr(T.TO)
        if isinstance(T.TO, lltype.Struct):
            REAL_TYPE = T.TO
            if T.TO._arrayfld is not None:
                carray = getattr(cobj.contents, T.TO._arrayfld)
                container = lltype._struct(T.TO, carray.length)
            else:
                # special treatment of 'OBJECT' subclasses
                if get_rtyper() and lltype._castdepth(REAL_TYPE, OBJECT) >= 0:
                    # figure out the real type of the object
                    containerheader = lltype._struct(OBJECT)
                    cobjheader = ctypes.cast(cobj,
                                       get_ctypes_type(lltype.Ptr(OBJECT)))
                    struct_use_ctypes_storage(containerheader,
                                              cobjheader.contents)
                    REAL_TYPE = get_rtyper().get_type_for_typeptr(
                        containerheader.typeptr)
                    REAL_T = lltype.Ptr(REAL_TYPE)
                    cobj = ctypes.cast(cobj, get_ctypes_type(REAL_T))
                container = lltype._struct(REAL_TYPE)
            struct_use_ctypes_storage(container, cobj.contents)
            if REAL_TYPE != T.TO:
                p = container._as_ptr()
                container = lltype.cast_pointer(T, p)._as_obj()
            # special treatment of 'OBJECT_VTABLE' subclasses
            if get_rtyper() and lltype._castdepth(REAL_TYPE,
                                                  OBJECT_VTABLE) >= 0:
                # figure out the real object that this vtable points to,
                # and just return that
                p = get_rtyper().get_real_typeptr_for_typeptr(
                    container._as_ptr())
                container = lltype.cast_pointer(T, p)._as_obj()
        elif isinstance(T.TO, lltype.Array):
            if T.TO._hints.get('nolength', False):
                container = _array_of_unknown_length(T.TO)
                container._storage = cobj.contents
            else:
                container = _array_of_known_length(T.TO)
                container._storage = cobj.contents
        elif isinstance(T.TO, lltype.FuncType):
            cobjkey = ctypes.cast(cobj, ctypes.c_void_p).value
            if cobjkey in _callback2obj:
                container = _callback2obj[cobjkey]
            else:
                _callable = get_ctypes_trampoline(T.TO, cobj)
                return lltype.functionptr(T.TO, getattr(cobj, '__name__', '?'),
                                          _callable=_callable)
        elif isinstance(T.TO, lltype.OpaqueType):
            if T == llmemory.GCREF:
                container = _llgcopaque(cobj)
            else:
                container = lltype._opaque(T.TO)
        else:
            raise NotImplementedError(T)
        llobj = lltype._ptr(T, container, solid=True)
    elif T is llmemory.Address:
        if cobj is None:
            llobj = llmemory.NULL
        else:
            llobj = _lladdress(cobj)
    elif T is lltype.Char:
        llobj = chr(cobj)
    elif T is lltype.UniChar:
        llobj = unichr(cobj)
    elif T is lltype.Signed:
        llobj = cobj
    elif T is lltype.Bool:
        assert cobj == True or cobj == False    # 0 and 1 work too
        llobj = bool(cobj)
    elif T is lltype.SingleFloat:
        if isinstance(cobj, ctypes.c_float):
            cobj = cobj.value
        llobj = r_singlefloat(cobj)
    elif T is lltype.Void:
        llobj = cobj
    else:
        from pypy.rpython.lltypesystem import rffi
        try:
            inttype = rffi.platform.numbertype_to_rclass[T]
        except KeyError:
            llobj = cobj
        else:
            llobj = inttype(cobj)

    assert lltype.typeOf(llobj) == T
    return llobj
Example #13
0
    def __init__(self, translator):
        from pypy.rpython.memory.gc.base import choose_gc_from_config
        super(FrameworkGCTransformer, self).__init__(translator, inline=True)
        if hasattr(self, 'GC_PARAMS'):
            # for tests: the GC choice can be specified as class attributes
            from pypy.rpython.memory.gc.marksweep import MarkSweepGC
            GCClass = getattr(self, 'GCClass', MarkSweepGC)
            GC_PARAMS = self.GC_PARAMS
        else:
            # for regular translation: pick the GC from the config
            GCClass, GC_PARAMS = choose_gc_from_config(translator.config)

        self.layoutbuilder = TransformerLayoutBuilder(self)
        self.get_type_id = self.layoutbuilder.get_type_id

        # set up dummy a table, to be overwritten with the real one in finish()
        type_info_table = lltype._ptr(
            lltype.Ptr(gctypelayout.GCData.TYPE_INFO_TABLE),
            "delayed!type_info_table", solid=True)
        gcdata = gctypelayout.GCData(type_info_table)

        # initialize the following two fields with a random non-NULL address,
        # to make the annotator happy.  The fields are patched in finish()
        # to point to a real array.
        foo = lltype.malloc(lltype.FixedSizeArray(llmemory.Address, 1),
                            immortal=True, zero=True)
        a_random_address = llmemory.cast_ptr_to_adr(foo)
        gcdata.static_root_start = a_random_address      # patched in finish()
        gcdata.static_root_nongcend = a_random_address   # patched in finish()
        gcdata.static_root_end = a_random_address        # patched in finish()
        self.gcdata = gcdata
        self.malloc_fnptr_cache = {}

        gcdata.gc = GCClass(**GC_PARAMS)
        root_walker = self.build_root_walker()
        gcdata.set_query_functions(gcdata.gc)
        gcdata.gc.set_root_walker(root_walker)
        self.num_pushs = 0
        self.write_barrier_calls = 0

        def frameworkgc_setup():
            # run-time initialization code
            root_walker.setup_root_walker()
            gcdata.gc.setup()

        bk = self.translator.annotator.bookkeeper

        # the point of this little dance is to not annotate
        # self.gcdata.static_root_xyz as constants. XXX is it still needed??
        data_classdef = bk.getuniqueclassdef(gctypelayout.GCData)
        data_classdef.generalize_attr(
            'static_root_start',
            annmodel.SomeAddress())
        data_classdef.generalize_attr(
            'static_root_nongcend',
            annmodel.SomeAddress())
        data_classdef.generalize_attr(
            'static_root_end',
            annmodel.SomeAddress())

        annhelper = annlowlevel.MixLevelHelperAnnotator(self.translator.rtyper)

        def getfn(ll_function, args_s, s_result, inline=False,
                  minimal_transform=True):
            graph = annhelper.getgraph(ll_function, args_s, s_result)
            if minimal_transform:
                self.need_minimal_transform(graph)
            if inline:
                self.graphs_to_inline[graph] = True
            return annhelper.graph2const(graph)

        self.frameworkgc_setup_ptr = getfn(frameworkgc_setup, [],
                                           annmodel.s_None)
        if root_walker.need_root_stack:
            self.incr_stack_ptr = getfn(root_walker.incr_stack,
                                       [annmodel.SomeInteger()],
                                       annmodel.SomeAddress(),
                                       inline = True)
            self.decr_stack_ptr = getfn(root_walker.decr_stack,
                                       [annmodel.SomeInteger()],
                                       annmodel.SomeAddress(),
                                       inline = True)
        else:
            self.incr_stack_ptr = None
            self.decr_stack_ptr = None
        self.weakref_deref_ptr = self.inittime_helper(
            ll_weakref_deref, [llmemory.WeakRefPtr], llmemory.Address)
        
        classdef = bk.getuniqueclassdef(GCClass)
        s_gc = annmodel.SomeInstance(classdef)
        s_gcref = annmodel.SomePtr(llmemory.GCREF)

        malloc_fixedsize_clear_meth = GCClass.malloc_fixedsize_clear.im_func
        self.malloc_fixedsize_clear_ptr = getfn(
            malloc_fixedsize_clear_meth,
            [s_gc, annmodel.SomeInteger(nonneg=True),
             annmodel.SomeInteger(nonneg=True),
             annmodel.SomeBool(), annmodel.SomeBool(),
             annmodel.SomeBool()], s_gcref,
            inline = False)
        if hasattr(GCClass, 'malloc_fixedsize'):
            malloc_fixedsize_meth = GCClass.malloc_fixedsize.im_func
            self.malloc_fixedsize_ptr = getfn(
                malloc_fixedsize_meth,
                [s_gc, annmodel.SomeInteger(nonneg=True),
                 annmodel.SomeInteger(nonneg=True),
                 annmodel.SomeBool(), annmodel.SomeBool(),
                 annmodel.SomeBool()], s_gcref,
                inline = False)
        else:
            malloc_fixedsize_meth = None
            self.malloc_fixedsize_ptr = self.malloc_fixedsize_clear_ptr
##         self.malloc_varsize_ptr = getfn(
##             GCClass.malloc_varsize.im_func,
##             [s_gc] + [annmodel.SomeInteger(nonneg=True) for i in range(5)]
##             + [annmodel.SomeBool(), annmodel.SomeBool()], s_gcref)
        self.malloc_varsize_clear_ptr = getfn(
            GCClass.malloc_varsize_clear.im_func,
            [s_gc] + [annmodel.SomeInteger(nonneg=True) for i in range(5)]
            + [annmodel.SomeBool(), annmodel.SomeBool()], s_gcref)
        self.collect_ptr = getfn(GCClass.collect.im_func,
            [s_gc], annmodel.s_None)
        self.can_move_ptr = getfn(GCClass.can_move.im_func,
                                  [s_gc, annmodel.SomeAddress()],
                                  annmodel.SomeBool())

        # in some GCs we can inline the common case of
        # malloc_fixedsize(typeid, size, True, False, False)
        if getattr(GCClass, 'inline_simple_malloc', False):
            # make a copy of this function so that it gets annotated
            # independently and the constants are folded inside
            if malloc_fixedsize_meth is None:
                malloc_fast_meth = malloc_fixedsize_clear_meth
                self.malloc_fast_is_clearing = True
            else:
                malloc_fast_meth = malloc_fixedsize_meth
                self.malloc_fast_is_clearing = False
            malloc_fast = func_with_new_name(
                malloc_fast_meth,
                "malloc_fast")
            s_False = annmodel.SomeBool(); s_False.const = False
            s_True  = annmodel.SomeBool(); s_True .const = True
            self.malloc_fast_ptr = getfn(
                malloc_fast,
                [s_gc, annmodel.SomeInteger(nonneg=True),
                 annmodel.SomeInteger(nonneg=True),
                 s_True, s_False,
                 s_False], s_gcref,
                inline = True)
        else:
            self.malloc_fast_ptr = None

        # in some GCs we can also inline the common case of
        # malloc_varsize(typeid, length, (3 constant sizes), True, False)
        if getattr(GCClass, 'inline_simple_malloc_varsize', False):
            # make a copy of this function so that it gets annotated
            # independently and the constants are folded inside
            malloc_varsize_clear_fast = func_with_new_name(
                GCClass.malloc_varsize_clear.im_func,
                "malloc_varsize_clear_fast")
            s_False = annmodel.SomeBool(); s_False.const = False
            s_True  = annmodel.SomeBool(); s_True .const = True
            self.malloc_varsize_clear_fast_ptr = getfn(
                malloc_varsize_clear_fast,
                [s_gc, annmodel.SomeInteger(nonneg=True),
                 annmodel.SomeInteger(nonneg=True),
                 annmodel.SomeInteger(nonneg=True),
                 annmodel.SomeInteger(nonneg=True),
                 annmodel.SomeInteger(nonneg=True),
                 s_True, s_False], s_gcref,
                inline = True)
        else:
            self.malloc_varsize_clear_fast_ptr = None

        if getattr(GCClass, 'malloc_varsize_nonmovable', False):
            malloc_nonmovable = func_with_new_name(
                GCClass.malloc_varsize_nonmovable.im_func,
                "malloc_varsize_nonmovable")
            self.malloc_varsize_nonmovable_ptr = getfn(
                malloc_nonmovable,
                [s_gc, annmodel.SomeInteger(nonneg=True),
                 annmodel.SomeInteger(nonneg=True)], s_gcref)
        else:
            self.malloc_varsize_nonmovable_ptr = None

        if getattr(GCClass, 'malloc_varsize_resizable', False):
            malloc_resizable = func_with_new_name(
                GCClass.malloc_varsize_resizable.im_func,
                "malloc_varsize_resizable")
            self.malloc_varsize_resizable_ptr = getfn(
                malloc_resizable,
                [s_gc, annmodel.SomeInteger(nonneg=True),
                 annmodel.SomeInteger(nonneg=True)], s_gcref)
        else:
            self.malloc_varsize_resizable_ptr = None

        if getattr(GCClass, 'realloc', False):
            self.realloc_ptr = getfn(
                GCClass.realloc.im_func,
                [s_gc, s_gcref] +
                [annmodel.SomeInteger(nonneg=True)] * 4 +
                [annmodel.SomeBool()],
                s_gcref)

        if GCClass.moving_gc:
            self.id_ptr = getfn(GCClass.id.im_func,
                                [s_gc, s_gcref], annmodel.SomeInteger(),
                                inline = False,
                                minimal_transform = False)
        else:
            self.id_ptr = None

        self.set_max_heap_size_ptr = getfn(GCClass.set_max_heap_size.im_func,
                                           [s_gc,
                                            annmodel.SomeInteger(nonneg=True)],
                                           annmodel.s_None)

        if GCClass.needs_write_barrier:
            self.write_barrier_ptr = getfn(GCClass.write_barrier.im_func,
                                           [s_gc,
                                            annmodel.SomeAddress(),
                                            annmodel.SomeAddress()],
                                           annmodel.s_None,
                                           inline=True)
        else:
            self.write_barrier_ptr = None
        self.statistics_ptr = getfn(GCClass.statistics.im_func,
                                    [s_gc, annmodel.SomeInteger()],
                                    annmodel.SomeInteger())

        # experimental gc_x_* operations
        s_x_pool  = annmodel.SomePtr(marksweep.X_POOL_PTR)
        s_x_clone = annmodel.SomePtr(marksweep.X_CLONE_PTR)
        # the x_*() methods use some regular mallocs that must be
        # transformed in the normal way
        self.x_swap_pool_ptr = getfn(GCClass.x_swap_pool.im_func,
                                     [s_gc, s_x_pool],
                                     s_x_pool,
                                     minimal_transform = False)
        self.x_clone_ptr = getfn(GCClass.x_clone.im_func,
                                 [s_gc, s_x_clone],
                                 annmodel.s_None,
                                 minimal_transform = False)

        # thread support
        if translator.config.translation.thread:
            if not hasattr(root_walker, "need_thread_support"):
                raise Exception("%s does not support threads" % (
                    root_walker.__class__.__name__,))
            root_walker.need_thread_support()
            self.thread_prepare_ptr = getfn(root_walker.thread_prepare,
                                            [], annmodel.s_None)
            self.thread_run_ptr = getfn(root_walker.thread_run,
                                        [], annmodel.s_None,
                                        inline=True)
            self.thread_die_ptr = getfn(root_walker.thread_die,
                                        [], annmodel.s_None)

        annhelper.finish()   # at this point, annotate all mix-level helpers
        annhelper.backend_optimize()

        self.collect_analyzer = CollectAnalyzer(self.translator)
        self.collect_analyzer.analyze_all()

        s_gc = self.translator.annotator.bookkeeper.valueoftype(GCClass)
        r_gc = self.translator.rtyper.getrepr(s_gc)
        self.c_const_gc = rmodel.inputconst(r_gc, self.gcdata.gc)
        self.malloc_zero_filled = GCClass.malloc_zero_filled

        HDR = self._gc_HDR = self.gcdata.gc.gcheaderbuilder.HDR
        self._gc_fields = fields = []
        for fldname in HDR._names:
            FLDTYPE = getattr(HDR, fldname)
            fields.append(('_' + fldname, FLDTYPE))
Example #14
0
    def __init__(self, translator):
        from pypy.rpython.memory.gc.base import choose_gc_from_config
        super(FrameworkGCTransformer, self).__init__(translator, inline=True)
        if hasattr(self, 'GC_PARAMS'):
            # for tests: the GC choice can be specified as class attributes
            from pypy.rpython.memory.gc.marksweep import MarkSweepGC
            GCClass = getattr(self, 'GCClass', MarkSweepGC)
            GC_PARAMS = self.GC_PARAMS
        else:
            # for regular translation: pick the GC from the config
            GCClass, GC_PARAMS = choose_gc_from_config(translator.config)

        self.layoutbuilder = TransformerLayoutBuilder(self)
        self.get_type_id = self.layoutbuilder.get_type_id

        # set up dummy a table, to be overwritten with the real one in finish()
        type_info_table = lltype._ptr(
            lltype.Ptr(gctypelayout.GCData.TYPE_INFO_TABLE),
            "delayed!type_info_table", solid=True)
        gcdata = gctypelayout.GCData(type_info_table)

        # initialize the following two fields with a random non-NULL address,
        # to make the annotator happy.  The fields are patched in finish()
        # to point to a real array.
        foo = lltype.malloc(lltype.FixedSizeArray(llmemory.Address, 1),
                            immortal=True, zero=True)
        a_random_address = llmemory.cast_ptr_to_adr(foo)
        gcdata.static_root_start = a_random_address      # patched in finish()
        gcdata.static_root_nongcend = a_random_address   # patched in finish()
        gcdata.static_root_end = a_random_address        # patched in finish()
        self.gcdata = gcdata
        self.malloc_fnptr_cache = {}

        gcdata.gc = GCClass(**GC_PARAMS)
        root_walker = self.build_root_walker()
        gcdata.set_query_functions(gcdata.gc)
        gcdata.gc.set_root_walker(root_walker)
        self.num_pushs = 0
        self.write_barrier_calls = 0

        def frameworkgc_setup():
            # run-time initialization code
            root_walker.setup_root_walker()
            gcdata.gc.setup()

        bk = self.translator.annotator.bookkeeper

        # the point of this little dance is to not annotate
        # self.gcdata.static_root_xyz as constants. XXX is it still needed??
        data_classdef = bk.getuniqueclassdef(gctypelayout.GCData)
        data_classdef.generalize_attr(
            'static_root_start',
            annmodel.SomeAddress())
        data_classdef.generalize_attr(
            'static_root_nongcend',
            annmodel.SomeAddress())
        data_classdef.generalize_attr(
            'static_root_end',
            annmodel.SomeAddress())

        annhelper = annlowlevel.MixLevelHelperAnnotator(self.translator.rtyper)

        def getfn(ll_function, args_s, s_result, inline=False,
                  minimal_transform=True):
            graph = annhelper.getgraph(ll_function, args_s, s_result)
            if minimal_transform:
                self.need_minimal_transform(graph)
            if inline:
                self.graphs_to_inline[graph] = True
            return annhelper.graph2const(graph)

        self.frameworkgc_setup_ptr = getfn(frameworkgc_setup, [],
                                           annmodel.s_None)
        if root_walker.need_root_stack:
            self.incr_stack_ptr = getfn(root_walker.incr_stack,
                                       [annmodel.SomeInteger()],
                                       annmodel.SomeAddress(),
                                       inline = True)
            self.decr_stack_ptr = getfn(root_walker.decr_stack,
                                       [annmodel.SomeInteger()],
                                       annmodel.SomeAddress(),
                                       inline = True)
        else:
            self.incr_stack_ptr = None
            self.decr_stack_ptr = None
        self.weakref_deref_ptr = self.inittime_helper(
            ll_weakref_deref, [llmemory.WeakRefPtr], llmemory.Address)
        
        classdef = bk.getuniqueclassdef(GCClass)
        s_gc = annmodel.SomeInstance(classdef)
        s_gcref = annmodel.SomePtr(llmemory.GCREF)

        malloc_fixedsize_clear_meth = GCClass.malloc_fixedsize_clear.im_func
        self.malloc_fixedsize_clear_ptr = getfn(
            malloc_fixedsize_clear_meth,
            [s_gc, annmodel.SomeInteger(nonneg=True),
             annmodel.SomeInteger(nonneg=True),
             annmodel.SomeBool(), annmodel.SomeBool(),
             annmodel.SomeBool()], s_gcref,
            inline = False)
        if hasattr(GCClass, 'malloc_fixedsize'):
            malloc_fixedsize_meth = GCClass.malloc_fixedsize.im_func
            self.malloc_fixedsize_ptr = getfn(
                malloc_fixedsize_meth,
                [s_gc, annmodel.SomeInteger(nonneg=True),
                 annmodel.SomeInteger(nonneg=True),
                 annmodel.SomeBool(), annmodel.SomeBool(),
                 annmodel.SomeBool()], s_gcref,
                inline = False)
        else:
            malloc_fixedsize_meth = None
            self.malloc_fixedsize_ptr = self.malloc_fixedsize_clear_ptr
##         self.malloc_varsize_ptr = getfn(
##             GCClass.malloc_varsize.im_func,
##             [s_gc] + [annmodel.SomeInteger(nonneg=True) for i in range(5)]
##             + [annmodel.SomeBool(), annmodel.SomeBool()], s_gcref)
        self.malloc_varsize_clear_ptr = getfn(
            GCClass.malloc_varsize_clear.im_func,
            [s_gc] + [annmodel.SomeInteger(nonneg=True) for i in range(5)]
            + [annmodel.SomeBool(), annmodel.SomeBool()], s_gcref)
        self.collect_ptr = getfn(GCClass.collect.im_func,
            [s_gc], annmodel.s_None)

        # in some GCs we can inline the common case of
        # malloc_fixedsize(typeid, size, True, False, False)
        if getattr(GCClass, 'inline_simple_malloc', False):
            # make a copy of this function so that it gets annotated
            # independently and the constants are folded inside
            if malloc_fixedsize_meth is None:
                malloc_fast_meth = malloc_fixedsize_clear_meth
                self.malloc_fast_is_clearing = True
            else:
                malloc_fast_meth = malloc_fixedsize_meth
                self.malloc_fast_is_clearing = False
            malloc_fast = func_with_new_name(
                malloc_fast_meth,
                "malloc_fast")
            s_False = annmodel.SomeBool(); s_False.const = False
            s_True  = annmodel.SomeBool(); s_True .const = True
            self.malloc_fast_ptr = getfn(
                malloc_fast,
                [s_gc, annmodel.SomeInteger(nonneg=True),
                 annmodel.SomeInteger(nonneg=True),
                 s_True, s_False,
                 s_False], s_gcref,
                inline = True)
        else:
            self.malloc_fast_ptr = None

        # in some GCs we can also inline the common case of
        # malloc_varsize(typeid, length, (3 constant sizes), True, False)
        if getattr(GCClass, 'inline_simple_malloc_varsize', False):
            # make a copy of this function so that it gets annotated
            # independently and the constants are folded inside
            malloc_varsize_clear_fast = func_with_new_name(
                GCClass.malloc_varsize_clear.im_func,
                "malloc_varsize_clear_fast")
            s_False = annmodel.SomeBool(); s_False.const = False
            s_True  = annmodel.SomeBool(); s_True .const = True
            self.malloc_varsize_clear_fast_ptr = getfn(
                malloc_varsize_clear_fast,
                [s_gc, annmodel.SomeInteger(nonneg=True),
                 annmodel.SomeInteger(nonneg=True),
                 annmodel.SomeInteger(nonneg=True),
                 annmodel.SomeInteger(nonneg=True),
                 annmodel.SomeInteger(nonneg=True),
                 s_True, s_False], s_gcref,
                inline = True)
        else:
            self.malloc_varsize_clear_fast_ptr = None

        if GCClass.moving_gc:
            self.id_ptr = getfn(GCClass.id.im_func,
                                [s_gc, s_gcref], annmodel.SomeInteger(),
                                inline = False,
                                minimal_transform = False)
        else:
            self.id_ptr = None

        self.set_max_heap_size_ptr = getfn(GCClass.set_max_heap_size.im_func,
                                           [s_gc,
                                            annmodel.SomeInteger(nonneg=True)],
                                           annmodel.s_None)

        if GCClass.needs_write_barrier:
            self.write_barrier_ptr = getfn(GCClass.write_barrier.im_func,
                                           [s_gc, annmodel.SomeAddress(),
                                            annmodel.SomeAddress(),
                                            annmodel.SomeAddress()],
                                           annmodel.s_None,
                                           inline=True)
        else:
            self.write_barrier_ptr = None
        if hasattr(GCClass, "coalloc_fixedsize_clear"):
            self.coalloc_clear_ptr = getfn(
                GCClass.coalloc_fixedsize_clear.im_func,
                [s_gc, annmodel.SomeAddress(),
                 annmodel.SomeInteger(nonneg=True),
                 annmodel.SomeInteger(nonneg=True)],
                s_gcref, inline=True)
            self.coalloc_varsize_clear_ptr = getfn(
                GCClass.coalloc_varsize_clear.im_func,
                [s_gc, annmodel.SomeAddress()] +
                [annmodel.SomeInteger(nonneg=True) for i in range(5)],
                s_gcref, inline=True)
        else:
            self.coalloc_clear_ptr = self.coalloc_varsize_clear_ptr = None
        self.statistics_ptr = getfn(GCClass.statistics.im_func,
                                    [s_gc, annmodel.SomeInteger()],
                                    annmodel.SomeInteger())

        # experimental gc_x_* operations
        s_x_pool  = annmodel.SomePtr(marksweep.X_POOL_PTR)
        s_x_clone = annmodel.SomePtr(marksweep.X_CLONE_PTR)
        # the x_*() methods use some regular mallocs that must be
        # transformed in the normal way
        self.x_swap_pool_ptr = getfn(GCClass.x_swap_pool.im_func,
                                     [s_gc, s_x_pool],
                                     s_x_pool,
                                     minimal_transform = False)
        self.x_clone_ptr = getfn(GCClass.x_clone.im_func,
                                 [s_gc, s_x_clone],
                                 annmodel.s_None,
                                 minimal_transform = False)

        annhelper.finish()   # at this point, annotate all mix-level helpers
        annhelper.backend_optimize()

        self.collect_analyzer = CollectAnalyzer(self.translator)
        self.collect_analyzer.analyze_all()

        s_gc = self.translator.annotator.bookkeeper.valueoftype(GCClass)
        r_gc = self.translator.rtyper.getrepr(s_gc)
        self.c_const_gc = rmodel.inputconst(r_gc, self.gcdata.gc)
        self.malloc_zero_filled = GCClass.malloc_zero_filled

        HDR = self._gc_HDR = self.gcdata.gc.gcheaderbuilder.HDR
        self._gc_fields = fields = []
        for fldname in HDR._names:
            FLDTYPE = getattr(HDR, fldname)
            fields.append(('_' + fldname, FLDTYPE))
Example #15
0
def ctypes2lltype(T, cobj):
    """Convert the ctypes object 'cobj' to its lltype equivalent.
    'T' is the expected lltype type.
    """
    if T is lltype.Void:
        return None
    if isinstance(T, lltype.Ptr):
        if not cobj:   # NULL pointer
            return lltype.nullptr(T.TO)
        if T is base_ptr_lltype():
            return _opaque_list[ctypes.cast(cobj, ctypes.c_void_p).value]
        if isinstance(T.TO, lltype.Struct):
            if T.TO._arrayfld is not None:
                carray = getattr(cobj.contents, T.TO._arrayfld)
                container = lltype._struct(T.TO, carray.length)
            else:
                # special treatment of 'OBJECT' subclasses
                if get_rtyper() and lltype._castdepth(T.TO, OBJECT) > 0:
                    ctypes_object = get_ctypes_type(lltype.Ptr(OBJECT))
                    as_obj = ctypes2lltype(lltype.Ptr(OBJECT),
                                           ctypes.cast(cobj, ctypes_object))
                    TObj = get_rtyper().get_type_for_typeptr(as_obj.typeptr)
                    if TObj != T.TO:
                        ctypes_instance = get_ctypes_type(lltype.Ptr(TObj))
                        return lltype.cast_pointer(T,
                            ctypes2lltype(lltype.Ptr(TObj),
                                          ctypes.cast(cobj, ctypes_instance)))
                container = lltype._struct(T.TO)
            struct_use_ctypes_storage(container, cobj.contents)
        elif isinstance(T.TO, lltype.Array):
            if T.TO._hints.get('nolength', False):
                container = _array_of_unknown_length(T.TO)
                container._storage = cobj.contents
            else:
                container = _array_of_known_length(T.TO)
                container._storage = cobj.contents
        elif isinstance(T.TO, lltype.FuncType):
            cobjkey = ctypes.cast(cobj, ctypes.c_void_p).value
            if cobjkey in _callback2obj:
                container = _callback2obj[cobjkey]
            else:
                _callable = get_ctypes_trampoline(T.TO, cobj)
                return lltype.functionptr(T.TO, getattr(cobj, '__name__', '?'),
                                          _callable=_callable)
        elif isinstance(T.TO, lltype.OpaqueType):
            if T == llmemory.GCREF:
                # XXX obscure hack
                return _llgcref(cobj)
            else:
                container = lltype._opaque(T.TO)
        else:
            raise NotImplementedError(T)
        llobj = lltype._ptr(T, container, solid=True)
    elif T is llmemory.Address:
        if cobj is None:
            llobj = llmemory.NULL
        else:
            llobj = _lladdress(cobj)
    elif T is lltype.Char:
        llobj = chr(cobj)
    elif T is lltype.UniChar:
        llobj = unichr(cobj)
    elif T is lltype.Signed:
        llobj = cobj
    elif T is lltype.SingleFloat:
        if isinstance(cobj, ctypes.c_float):
            cobj = cobj.value
        llobj = r_singlefloat(cobj)
    elif T is lltype.Void:
        llobj = cobj
    else:
        from pypy.rpython.lltypesystem import rffi
        try:
            inttype = rffi.platform.numbertype_to_rclass[T]
        except KeyError:
            llobj = cobj
        else:
            llobj = inttype(cobj)

    assert lltype.typeOf(llobj) == T
    return llobj
Example #16
0
def ctypes2lltype(T, cobj):
    """Convert the ctypes object 'cobj' to its lltype equivalent.
    'T' is the expected lltype type.
    """
    if T is lltype.Void:
        return None
    if isinstance(T, lltype.Ptr):
        if not cobj:  # NULL pointer
            return lltype.nullptr(T.TO)
        if T is base_ptr_lltype():
            return _opaque_list[ctypes.cast(cobj, ctypes.c_void_p).value]
        if isinstance(T.TO, lltype.Struct):
            if T.TO._arrayfld is not None:
                carray = getattr(cobj.contents, T.TO._arrayfld)
                container = lltype._struct(T.TO, carray.length)
            else:
                # special treatment of 'OBJECT' subclasses
                if get_rtyper() and lltype._castdepth(T.TO, OBJECT) > 0:
                    ctypes_object = get_ctypes_type(lltype.Ptr(OBJECT))
                    as_obj = ctypes2lltype(lltype.Ptr(OBJECT),
                                           ctypes.cast(cobj, ctypes_object))
                    TObj = get_rtyper().get_type_for_typeptr(as_obj.typeptr)
                    if TObj != T.TO:
                        ctypes_instance = get_ctypes_type(lltype.Ptr(TObj))
                        return lltype.cast_pointer(
                            T,
                            ctypes2lltype(lltype.Ptr(TObj),
                                          ctypes.cast(cobj, ctypes_instance)))
                container = lltype._struct(T.TO)
            struct_use_ctypes_storage(container, cobj.contents)
            addr = ctypes.addressof(cobj.contents)
            if addr in _parent_cache:
                setparentstructure(container, _parent_cache[addr])
        elif isinstance(T.TO, lltype.Array):
            if T.TO._hints.get('nolength', False):
                container = _array_of_unknown_length(T.TO)
                container._storage = cobj.contents
            else:
                container = _array_of_known_length(T.TO)
                container._storage = cobj.contents
        elif isinstance(T.TO, lltype.FuncType):
            cobjkey = ctypes.cast(cobj, ctypes.c_void_p).value
            if cobjkey in _callback2obj:
                container = _callback2obj[cobjkey]
            else:
                _callable = get_ctypes_trampoline(T.TO, cobj)
                return lltype.functionptr(T.TO,
                                          getattr(cobj, '__name__', '?'),
                                          _callable=_callable)
        elif isinstance(T.TO, lltype.OpaqueType):
            if T == llmemory.GCREF:
                container = _llgcopaque(cobj)
            else:
                container = lltype._opaque(T.TO)
        else:
            raise NotImplementedError(T)
        llobj = lltype._ptr(T, container, solid=True)
    elif T is llmemory.Address:
        if cobj is None:
            llobj = llmemory.NULL
        else:
            llobj = _lladdress(cobj)
    elif T is lltype.Char:
        llobj = chr(cobj)
    elif T is lltype.UniChar:
        llobj = unichr(cobj)
    elif T is lltype.Signed:
        llobj = cobj
    elif T is lltype.Bool:
        assert cobj == True or cobj == False  # 0 and 1 work too
        llobj = bool(cobj)
    elif T is lltype.SingleFloat:
        if isinstance(cobj, ctypes.c_float):
            cobj = cobj.value
        llobj = r_singlefloat(cobj)
    elif T is lltype.Void:
        llobj = cobj
    else:
        from pypy.rpython.lltypesystem import rffi
        try:
            inttype = rffi.platform.numbertype_to_rclass[T]
        except KeyError:
            llobj = cobj
        else:
            llobj = inttype(cobj)

    assert lltype.typeOf(llobj) == T
    return llobj
Example #17
0
def ctypes2lltype(T, cobj):
    """Convert the ctypes object 'cobj' to its lltype equivalent.
    'T' is the expected lltype type.
    """
    if T is lltype.Void:
        return None
    if isinstance(T, lltype.Ptr):
        if not cobj:  # NULL pointer
            return lltype.nullptr(T.TO)
        if isinstance(T.TO, lltype.Struct):
            REAL_TYPE = T.TO
            if T.TO._arrayfld is not None:
                carray = getattr(cobj.contents, T.TO._arrayfld)
                container = lltype._struct(T.TO, carray.length)
            else:
                # special treatment of 'OBJECT' subclasses
                if get_rtyper() and lltype._castdepth(REAL_TYPE, OBJECT) >= 0:
                    # figure out the real type of the object
                    containerheader = lltype._struct(OBJECT)
                    cobjheader = ctypes.cast(
                        cobj, get_ctypes_type(lltype.Ptr(OBJECT)))
                    struct_use_ctypes_storage(containerheader,
                                              cobjheader.contents)
                    REAL_TYPE = get_rtyper().get_type_for_typeptr(
                        containerheader.typeptr)
                    REAL_T = lltype.Ptr(REAL_TYPE)
                    cobj = ctypes.cast(cobj, get_ctypes_type(REAL_T))
                container = lltype._struct(REAL_TYPE)
            struct_use_ctypes_storage(container, cobj.contents)
            if REAL_TYPE != T.TO:
                p = container._as_ptr()
                container = lltype.cast_pointer(T, p)._as_obj()
            # special treatment of 'OBJECT_VTABLE' subclasses
            if get_rtyper() and lltype._castdepth(REAL_TYPE,
                                                  OBJECT_VTABLE) >= 0:
                # figure out the real object that this vtable points to,
                # and just return that
                p = get_rtyper().get_real_typeptr_for_typeptr(
                    container._as_ptr())
                container = lltype.cast_pointer(T, p)._as_obj()
        elif isinstance(T.TO, lltype.Array):
            if T.TO._hints.get('nolength', False):
                container = _array_of_unknown_length(T.TO)
                container._storage = cobj.contents
            else:
                container = _array_of_known_length(T.TO)
                container._storage = cobj.contents
        elif isinstance(T.TO, lltype.FuncType):
            cobjkey = ctypes.cast(cobj, ctypes.c_void_p).value
            if cobjkey in _callback2obj:
                container = _callback2obj[cobjkey]
            else:
                _callable = get_ctypes_trampoline(T.TO, cobj)
                return lltype.functionptr(T.TO,
                                          getattr(cobj, '__name__', '?'),
                                          _callable=_callable)
        elif isinstance(T.TO, lltype.OpaqueType):
            if T == llmemory.GCREF:
                container = _llgcopaque(cobj)
            else:
                container = lltype._opaque(T.TO)
        else:
            raise NotImplementedError(T)
        llobj = lltype._ptr(T, container, solid=True)
    elif T is llmemory.Address:
        if cobj is None:
            llobj = llmemory.NULL
        else:
            llobj = _lladdress(cobj)
    elif T is lltype.Char:
        llobj = chr(cobj)
    elif T is lltype.UniChar:
        llobj = unichr(cobj)
    elif T is lltype.Signed:
        llobj = cobj
    elif T is lltype.Bool:
        assert cobj == True or cobj == False  # 0 and 1 work too
        llobj = bool(cobj)
    elif T is lltype.SingleFloat:
        if isinstance(cobj, ctypes.c_float):
            cobj = cobj.value
        llobj = r_singlefloat(cobj)
    elif T is lltype.Void:
        llobj = cobj
    else:
        from pypy.rpython.lltypesystem import rffi
        try:
            inttype = rffi.platform.numbertype_to_rclass[T]
        except KeyError:
            llobj = cobj
        else:
            llobj = inttype(cobj)

    assert lltype.typeOf(llobj) == T
    return llobj