cvtype.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 2,020 行 · 第 1/5 页

C
2,020
字号
            list->len = len;
            wr = wk( ii, SWI_SYMBOL, list, p, d );
            if( wr != WR_CONTINUE ) return( wr );
            list->curr += len;
        }
    }
}

static void TypePrimitiveInfo( unsigned idx, type_info *ti )
{
    static const unsigned_8     RealSizes[] = { 4, 8, 10, 16, 6 };
    cv_primitive                prim;

    prim.s = idx;
    switch( prim.f.mode ) {
    case CV_DIRECT:
        switch( prim.f.type ) {
        case CV_SPECIAL:
            switch( prim.f.size ) {
            case 0x1:
                ti->kind = TK_ADDRESS;
                ti->size = sizeof( addr48_ptr );
                break;
            case 0x2:
                ti->size = sizeof( addr_seg );
                ti->kind = TK_DATA;
                break;
            case 0x3:
                ti->size = 0;
                ti->kind = TK_VOID;
                break;
            case 0x4:
                ti->size = 8;
                ti->kind = TK_DATA;
                break;
            case 0x5:
            case 0x6:
                /* Basic string: what size? */
                ti->size = 0;
                ti->kind = TK_STRING;
                break;
            }
            break;
        case CV_SIGNED:
            ti->modifier = TM_SIGNED;
            ti->kind = TK_INTEGER;
            ti->size = 1 << prim.f.size;
            if( ti->size == 1 ) ti->kind = TK_CHAR;
            break;
        case CV_UNSIGNED:
            ti->modifier = TM_UNSIGNED;
            ti->kind = TK_INTEGER;
            ti->size = 1 << prim.f.size;
            if( ti->size == 1 ) ti->kind = TK_CHAR;
            break;
        case CV_BOOL:
            ti->kind = TK_BOOL;
            ti->size = 1 << prim.f.size;
            break;
        case CV_REAL:
            ti->kind = TK_REAL;
            ti->size = RealSizes[ prim.f.size ];
            break;
        case CV_COMPLEX:
            ti->kind = TK_COMPLEX;
            ti->size = 2 * RealSizes[ prim.f.size ];
            break;
        case CV_SPECIAL2:
            ti->kind = TK_DATA;
            ti->size = 1;
            break;
        case CV_REALLYINT:
            switch( prim.f.size ) {
            case 0x0:
                ti->kind = TK_CHAR;
                ti->size = 1;
                break;
            case 0x1:
                ti->kind = TK_CHAR;
                ti->size = 2;
                break;
            case 0x2:
                ti->modifier = TM_SIGNED;
                ti->size = 2;
                ti->kind = TK_INTEGER;
                break;
            case 0x3:
                ti->modifier = TM_UNSIGNED;
                ti->size = 2;
                ti->kind = TK_INTEGER;
                break;
            case 0x4:
                ti->modifier = TM_SIGNED;
                ti->size = 4;
                ti->kind = TK_INTEGER;
                break;
            case 0x5:
                ti->modifier = TM_UNSIGNED;
                ti->size = 4;
                ti->kind = TK_INTEGER;
                break;
            case 0x6:
                ti->modifier = TM_SIGNED;
                ti->size = 8;
                ti->kind = TK_INTEGER;
                break;
            case 0x7:
                ti->modifier = TM_UNSIGNED;
                ti->size = 8;
                ti->kind = TK_INTEGER;
                break;
            }
            break;
        case 0x0f:
            /* my own invention: T_CODE_LBL*, T_DATA_LBL* */
            ti->kind = (prim.s & 0x08) ? TK_DATA : TK_CODE;
            ti->size = 1 << prim.f.size;
            break;
        }
        break;
    case CV_NEARP:
        ti->size = sizeof( addr32_off );
        ti->modifier = TM_NEAR;
        ti->kind = TK_POINTER;
        break;
    case CV_FARP:
        ti->size = sizeof( addr32_ptr );
        ti->modifier = TM_FAR;
        ti->kind = TK_POINTER;
        break;
    case CV_HUGEP:
        ti->size = sizeof( addr32_ptr );
        ti->modifier = TM_HUGE;
        ti->kind = TK_POINTER;
        break;
    case CV_NEAR32P:
        ti->size = sizeof( addr48_off );
        ti->modifier = TM_NEAR;
        ti->kind = TK_POINTER;
        break;
    case CV_FAR32P:
        ti->size = sizeof( addr48_ptr );
        ti->modifier = TM_FAR;
        ti->kind = TK_POINTER;
        break;
    case CV_NEAR64P:
        ti->size = 8;
        ti->modifier = TM_NEAR;
        ti->kind = TK_POINTER;
        break;
    }
}

typedef struct {
    cv_fldattr  attr;
    unsigned_16 type;
    unsigned_32 vtab_off; /* optional: only if virtual function */
} method_info;

static method_info *GetMethodInfo( imp_image_handle *ii, unsigned ml_idx,
                                unsigned mf_idx )
{
    virt_mem    mlist;
    method_info *p;

    mlist = TypeIndexVM( ii, ml_idx );
    if( mlist == 0 ) return( NULL );
    mlist += sizeof( unsigned_16 ) * 2;
    for( ;; ) {
        p = VMBlock( ii, mlist, sizeof( *p ) );
        if( p == NULL ) return( NULL );
        if( mf_idx == 0 ) return( p );
        mlist += sizeof( method_info );
        switch( p->attr.f.mprop ) {
        case CV_INTROVIRT:
        case CV_PUREINTROVIRT:
            break;
        default:
            mlist -= sizeof( p->vtab_off );
            break;
        }
        --mf_idx;
    }
}

static dip_status GetVirtBaseDisp( imp_image_handle *ii, virt_mem adj,
                location_context *lc, location_list ll, unsigned long *disp )
{
    lf_all              *p;
    void                *ptr;
    numeric_leaf        val;
    unsigned            elt_type;
    unsigned            idx;
    imp_type_handle     vbp;
    dip_status          ds;
    type_info           ti;
    union {
        unsigned_8      u8;
        unsigned_16     u16;
        unsigned_32     u32;
    }                   tmp;
    location_list       dst;

    p = VMBlock( ii, adj, sizeof( *p ) + sizeof( unsigned_32 ) * 4 );
    if( p == NULL ) return( DS_ERR|DS_FAIL );
    ptr = GetNumLeaf( &p->vbclass + 1, &val );
    LocationAdd( &ll, val.int_val * 8 );
    GetNumLeaf( ptr, &val );
    idx = val.int_val;
    ds = TypeIndexFillIn( ii, p->vbclass.f.vtype, &vbp );
    if( ds != DS_OK ) return( ds );
    ds = ImpTypeInfo( ii, &vbp, lc, &ti );
    if( ds != DS_OK ) return( ds );
    if( ti.kind != TK_POINTER ) {
        Confused();
    }
    p = VMBlock( ii, vbp.handle, sizeof( *p ) );
    if( p == NULL ) return( DS_ERR|DS_FAIL );
    if( p->pointer.f.type >= CV_FIRST_USER_TYPE ) {
        ds = TypeIndexFillIn( ii, p->pointer.f.type, &vbp );
        if( ds != DS_OK ) return( ds );
        p = VMBlock( ii, vbp.handle, sizeof( *p ) );
        if( p == NULL ) return( DS_ERR|DS_FAIL );
        if( p->common.code != LF_ARRAY || p->array.f.elemtype >= CV_FIRST_USER_TYPE ) {
            Confused();
        }
        elt_type = p->array.f.elemtype;
    } else {
        elt_type = p->pointer.f.type;
    }
    ds = DoIndirection( ii, &ti, lc, &ll );
    TypePrimitiveInfo( elt_type, &ti );
    ll.e[0].u.addr.mach.offset += ti.size * idx;
    LocationCreate( &dst, LT_INTERNAL, &tmp );
    ds = DCAssignLocation( &dst, &ll, ti.size );
    if( ds != DS_OK ) return( ds );
    switch( ti.size ) {
    case 1:
        *disp = tmp.u8;
        break;
    case 2:
        *disp = tmp.u16;
        break;
    case 4:
        *disp = tmp.u32;
        break;
    default:
        Confused();
        return( DS_ERR|DS_FAIL );
    }
    return( DS_OK );
}

struct vtab_data {
    unsigned            ptr_idx;
    unsigned long       disp;
};

static walk_result FindVTab( imp_image_handle *ii, sym_walk_info swi,
            pending_type_list *list, lf_all *p, void *d )
{
    struct vtab_data    *vd = d;

    ii = ii; list = list;
    switch( swi ) {
    case SWI_INHERIT_START:
    case SWI_INHERIT_END:
        return( WR_STOP );
    }
    /* SWI_SYMBOL: */
    switch( p->common.code ) {
    case LF_VFUNCTAB:
        vd->disp = 0;
        vd->ptr_idx = p->vfunctab.f.type;
        return( WR_STOP );
    case LF_VFUNCOFF:
        vd->disp = p->vfuncoff.f.offset;
        vd->ptr_idx = p->vfuncoff.f.type;
        return( WR_STOP );
    }
    return( WR_CONTINUE );
}

static dip_status VFuncLocation( imp_image_handle *ii, imp_sym_handle *is,
            unsigned_32 vfunc_off, location_context *lc, location_list *ll )
{
    lf_all              *p;
    virt_mem            base;
    struct vtab_data    data;
    imp_type_handle     it;
    type_info           ti;
    unsigned_8          *vfsp;
    unsigned            vfshape;
    addr_off            save;
    dip_status          ds;

    p = VMBlock( ii, is->containing_type, sizeof( *p ) );
    if( p == NULL ) return( DS_ERR|DS_FAIL );
    base = TypeIndexVM( ii, p->class_.f.field );
    if( base == 0 ) return( DS_ERR|DS_FAIL );
    switch( TypeListWalk( ii, base, is->containing_type, FindVTab, &data ) ) {
    case WR_STOP:
        break;
    default:
        return( DS_ERR|DS_FAIL );
    }
    ds = TypeIndexFillIn( ii, data.ptr_idx, &it );
    if( ds != DS_OK ) return( ds );
    ds = ImpTypeInfo( ii, &it, lc, &ti );
    if( ds != DS_OK ) return( ds );
    ds = DCItemLocation( lc, CI_OBJECT, ll );
    if( ds != DS_OK ) return( ds );
    LocationAdd( ll, data.disp * 8 );
    ds = DoIndirection( ii, &ti, lc, ll );
    if( ds != DS_OK ) return( ds );
    LocationAdd( ll, vfunc_off * 8 );
    ds = ImpTypeBase( ii, &it, &it );
    if( ds != DS_OK ) return( ds );
    vfsp = VMBlock( ii, it.handle + sizeof(unsigned_16)*2 + is->mfunc_idx/2,
                        sizeof( *vfsp ) );
    if( vfsp == NULL ) return( DS_ERR|DS_FAIL );
    if( (is->mfunc_idx % 2) != 0 ) {
        vfshape = *vfsp >> 4;
    } else {
        vfshape = *vfsp & 0x0f;
    }
    switch( vfshape ) {
    case CV_VTNEAR:
        ti.modifier = TM_NEAR;
        ti.size = sizeof( addr32_off );
        break;
    case CV_VTFAR:
        ti.modifier = TM_FAR;
        ti.size = sizeof( addr32_ptr );
        break;
    case CV_VTNEAR32:
        ti.modifier = TM_NEAR;
        ti.size = sizeof( addr48_off );
        break;
    case CV_VTFAR32:
        ti.modifier = TM_FAR;
        ti.size = sizeof( addr48_ptr );
        break;
    default:
        Confused();
        return( DS_ERR|DS_FAIL );
    }
    ds = DoIndirection( ii, &ti, lc, ll );
    if( ds != DS_OK ) return( ds );
    switch( vfshape ) {
    case CV_VTNEAR:
    case CV_VTNEAR32:
        /* since it's a code item, the default addr space is CI_EXECUTION */
        save = ll->e[0].u.addr.mach.offset;
        ds = DCItemLocation( lc, CI_EXECUTION, ll );
        if( ds != DS_OK ) return( ds );
        ll->e[0].u.addr.mach.offset = save;

    }
    return( DS_OK );
}

static dip_status MatchSymLocation( imp_image_handle *ii, imp_sym_handle *is,
                    unsigned idx, location_context *lc, location_list *ll )
{
    char                *name;
    unsigned            len;
    char                *buff;
    char                *start;
    imp_sym_handle      real;
    dip_status          ds;

    /*
        Have to lookup "<scope>::<name>" with given type index to get
        address. Ugh :-(.
    */
    ds = TypeVMGetName( ii, is->handle, &name, &len, NULL );
    if( ds != DS_OK ) return( ds );
    /* name can't be longer than 256 because of CV format */
    buff = __alloca( len + (SCOPE_TOKEN_LEN + 256) );
    start = &buff[SCOPE_TOKEN_LEN+256];
    buff = &start[len];
    memcpy( start, name, len );
    start -= SCOPE_TOKEN_LEN;
    memcpy( start, SCOPE_TOKEN, SCOPE_TOKEN_LEN );
    ds = TypeVMGetName( ii, is->containing_type, &name, &len, NULL );
    if( ds != DS_OK ) return( ds );
    start -= len;
    memcpy( start, name, len );
    ds = SymFindMatchingSym( ii, start, buff-start, idx, &real );
    if( ds != DS_OK ) return( ds );
    return( ImpSymLocation( ii, &real, lc, ll ) );
}

dip_status TypeSymGetAddr( imp_image_handle *ii, imp_sym_handle *is,
                        location_context *lc, location_list *ll )
{
    lf_all              *p;
    numeric_leaf        val;
    dip_status          ds;
    unsigned            idx;
    imp_type_handle     base;
    unsigned long       disp;
    method_info         *minfo;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?