예제 #1
0
def do_realize_lazy_struct(w_ctype):
    """This is called by W_CTypeStructOrUnion.force_lazy_struct().
    """
    assert isinstance(w_ctype, ctypestruct.W_CTypeStructOrUnion)
    space = w_ctype.space
    ffi = w_ctype._lazy_ffi
    s = w_ctype._lazy_s
    assert w_ctype.size != -1      # not an opaque (but may be -2)
    assert ffi is not None         # still lazy

    first_field = rffi.getintfield(s, 'c_first_field_index')
    num_fields = rffi.getintfield(s, 'c_num_fields')
    fields_w = [None] * num_fields

    for i in range(num_fields):
        fld = ffi.ctxobj.ctx.c_fields[first_field + i]
        field_name   = rffi.charp2str(fld.c_name)
        field_size   = rffi.getintfield(fld, 'c_field_size')
        field_offset = rffi.getintfield(fld, 'c_field_offset')
        op = rffi.getintfield(fld, 'c_field_type_op')
        case = getop(op)

        if case == cffi_opcode.OP_NOOP:
            fbitsize = -1     # standard field
        elif case == cffi_opcode.OP_BITFIELD:
            assert field_size >= 0
            fbitsize = field_size
        else:
            raise oefmt(space.w_NotImplementedError, "field op=%d", case)

        w_ctf = realize_c_type(ffi, ffi.ctxobj.ctx.c_types, getarg(op))

        if field_offset == -1:
            # unnamed struct, with field positions and sizes entirely
            # determined by complete_struct_or_union() and not checked.
            # Or, bitfields (field_size >= 0), similarly not checked.
            assert field_size == -1 or fbitsize >= 0
        else:
            newtype.detect_custom_layout(w_ctype, newtype.SF_STD_FIELD_POS,
                                         w_ctf.size, field_size,
                                         "wrong size for field '",
                                         field_name, "'")

        fields_w[i] = space.newtuple([
            space.wrap(field_name),
            w_ctf,
            space.wrap(fbitsize),
            space.wrap(field_offset)])

    sflags = 0
    c_flags = rffi.getintfield(s, 'c_flags')
    if c_flags & cffi_opcode.F_CHECK_FIELDS:
        sflags |= newtype.SF_STD_FIELD_POS
    if c_flags & cffi_opcode.F_PACKED:
        sflags |= newtype.SF_PACKED

    assert w_ctype.size      == rffi.getintfield(s, 'c_size')
    assert w_ctype.alignment == rffi.getintfield(s, 'c_alignment')
    try:
        w_ctype.size = -1              # make opaque again
        newtype.complete_struct_or_union(
            space, w_ctype, space.newlist(fields_w), space.w_None,
            totalsize = rffi.getintfield(s, 'c_size'),
            totalalignment = rffi.getintfield(s, 'c_alignment'),
            sflags = sflags)
    except:
        w_ctype.size      = rffi.getintfield(s, 'c_size')       # restore
        w_ctype.alignment = rffi.getintfield(s, 'c_alignment')  # restore
        raise
    if rffi.getintfield(s, 'c_size') >= 0:
        assert w_ctype.size == rffi.getintfield(s, 'c_size')
        assert w_ctype.alignment > 0
        if rffi.getintfield(s, 'c_alignment') != -1:
            assert w_ctype.alignment == rffi.getintfield(s, 'c_alignment')
    assert w_ctype._fields_list is not None       # not lazy any more

    w_ctype._lazy_ffi = None
    w_ctype._lazy_s = lltype.nullptr(parse_c_type.STRUCT_UNION_S)
예제 #2
0
        elif case == cffi_opcode.OP_BITFIELD:
            assert field_size >= 0
            fbitsize = field_size
        else:
            raise oefmt(space.w_NotImplementedError, "field op=%d", case)

        w_ctf = realize_c_type(ffi, ffi.ctxobj.ctx.c_types, getarg(op))

        if field_offset == -1:
            # unnamed struct, with field positions and sizes entirely
            # determined by complete_struct_or_union() and not checked.
            # Or, bitfields (field_size >= 0), similarly not checked.
            assert field_size == -1 or fbitsize >= 0
        else:
            newtype.detect_custom_layout(w_ctype, newtype.SF_STD_FIELD_POS,
                                         w_ctf.size, field_size,
                                         "wrong size for field '",
                                         field_name, "'")

        fields_w[i] = space.newtuple([
            space.wrap(field_name),
            w_ctf,
            space.wrap(fbitsize),
            space.wrap(field_offset)])

    sflags = 0
    c_flags = rffi.getintfield(s, 'c_flags')
    if c_flags & cffi_opcode.F_CHECK_FIELDS:
        sflags |= newtype.SF_STD_FIELD_POS
    if c_flags & cffi_opcode.F_PACKED:
        sflags |= newtype.SF_PACKED