wattype.c

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

C
1,874
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  Watcom debugging information type support.
*
****************************************************************************/


#include "dipwat.h"
#include "wattype.h"
#include <string.h>
#include "walloca.h"


extern void             *InfoLoad(imp_image_handle *, imp_mod_handle, unsigned, unsigned, void (*)() );
extern void             InfoSpecUnlock( void * );
extern void             InfoSpecLock( void * );
extern unsigned int     InfoSize(imp_image_handle *,imp_mod_handle,unsigned, unsigned );
extern byte             *GetIndex( byte *, unsigned * );
extern byte             *SkipLocation( loc_expr );
extern location_info    InfoLocation( loc_expr );
extern void             LocationAdd( location_list *, long );
extern void             LocationTrunc( location_list *, unsigned );
extern void             LocationCreate( location_list *, location_type, void * );
extern dip_status       EvalLocation( imp_image_handle *, location_context *, loc_expr, location_list * );
extern void             PushBaseLocation( location_list * );
extern byte             *GetAddress( imp_image_handle *, byte *, address *, int );
extern type_kind        GblTypeClassify( unsigned );
extern dip_status       SymHdl2LclInfo( imp_image_handle *, imp_sym_handle *, sym_info * );
extern search_result    LookupLclAddr( imp_image_handle *, address, imp_sym_handle * );

#define NEXT_TYPE( p )  ((p) + *(p))

typedef struct typeinfo {
    byte                *start;
    byte                *end;
    unsigned            entry;
    imp_mod_handle      im;
    struct typeinfo     *prev;
} typeinfo;

static typeinfo *Type;

static void PushLoad( typeinfo *new )
{
    new->prev = Type;
    new->start = NULL;
    Type = new;
}

static void FreeLoad( void )
{
    if( Type->start != NULL ) {
        InfoSpecUnlock( Type->start );
        Type->start = NULL;
    }
}

static void PopLoad( void )
{
    FreeLoad();
    Type = Type->prev;
}

void KillTypeLoadStack( void )
{
    Type = NULL;
}

static dip_status LoadType( imp_image_handle *ii, imp_mod_handle im,
                                unsigned entry )
{
    FreeLoad();
    Type->start = InfoLoad( ii, im, DMND_TYPES, entry, NULL );
    if( Type->start == NULL ) {
        return( DS_FAIL );
    }
    Type->end = Type->start + InfoSize( ii, im, DMND_TYPES, entry );
    Type->entry = entry;
    Type->im = im;
    return( DS_OK );
}

static byte *NamePtr( byte *p )
{
    unsigned    index;

    switch( p[1] ) {
    case NAME_TYPE+TYPE_SCALAR:
        p += 3;
        break;
    case NAME_TYPE+TYPE_SCOPE:
        p += 2;
        break;
    case NAME_TYPE+TYPE_NAME:
        p = GetIndex( p + 2, &index );
        p = GetIndex( p, &index );
        break;
    case ENUM_TYPE+ENUM_CONST_BYTE:
        p += 3;
        break;
    case ENUM_TYPE+ENUM_CONST_WORD:
        p += 4;
        break;
    case ENUM_TYPE+ENUM_CONST_LONG:
        p += 6;
        break;
    case ENUM_TYPE+ENUM_CONST_I64:
        p += 10;
        break;
    case STRUCT_TYPE+ST_BIT_BYTE:
        p += 2;
        /* fall through */
    case STRUCT_TYPE+ST_FIELD_BYTE:
        p += 3;
        p = GetIndex( p, &index );
        break;
    case STRUCT_TYPE+ST_BIT_WORD:
        p += 2;
        /* fall through */
    case STRUCT_TYPE+ST_FIELD_WORD:
        p += 4;
        p = GetIndex( p, &index );
        break;
    case STRUCT_TYPE+ST_BIT_LONG:
        p += 2;
        /* fall through */
    case STRUCT_TYPE+ST_FIELD_LONG:
        p += 6;
        p = GetIndex( p, &index );
        break;
    case STRUCT_TYPE+ST_FIELD_LOC:
        p = SkipLocation( p + 3 );
        p = GetIndex( p, &index );
        break;
    case STRUCT_TYPE+ST_BIT_LOC:
        p = SkipLocation( p + 3 ) + 2;
        p = GetIndex( p, &index );
        break;
    default:
        p += *p;
        break;
    }
    return( p );
}

static byte *BaseTypePtr( byte *p )
{
    byte        kind;
    byte        subkind;
    unsigned    index;

    kind = p[1];
    subkind = kind & SUBCLASS_MASK;
    switch( kind & CLASS_MASK ) {
    case NAME_TYPE:
        if( subkind == TYPE_NAME ) {
            p = GetIndex( p, &index );
            return( p );
        }
        break;
    case ARRAY_TYPE:
        {
            static const byte Incr[] = { 3, 4, 6, 0, 8, 10 };

            if( subkind == ARRAY_TYPE_INDEX ) {
                p = GetIndex( p + 2, &index );
            } else {
                p += Incr[ subkind ];
            }
        }
        return( p );
    case SUBRANGE_TYPE:
        {
            static const byte Incr[] = { 4, 6, 10 };

            p += Incr[ subkind ];
        }
        return( p );
    case POINTER_TYPE:
        return( p + 2 );
    case STRUCT_TYPE:
        switch( subkind ) {
        case STRUCT_LIST:
            return( NULL );
        case ST_BIT_BYTE:
            p += 2;
            /* fall through */
        case ST_FIELD_BYTE:
            p += 3;
            break;
        case ST_BIT_WORD:
            p += 2;
            /* fall through */
        case ST_FIELD_WORD:
            p += 4;
            break;
        case ST_BIT_LONG:
            p += 2;
            /* fall through */
        case ST_FIELD_LONG:
            p += 6;
            break;
        case ST_FIELD_LOC:
            p = SkipLocation( p + 3 );
            break;
        case ST_BIT_LOC:
            p = SkipLocation( p + 3 ) + 2;
            break;
        case ST_INHERIT:
            p = SkipLocation( p + 2 );
            break;
        }
        return( p );
     case PROC_TYPE:
         return( p + 2 );
    }
    return( NULL );
}

static unsigned long GetScalar( address addr, unsigned scalar )
{
    location_list       src_ll;
    location_list       dst_ll;
    union {
        unsigned_8      u8;
        signed_8        s8;
        unsigned_16     u16;
        signed_16       s16;
        unsigned_32     u32;
        signed_32       s32;
    }                   tmp;

    LocationCreate( &src_ll, LT_ADDR, &addr );
    LocationCreate( &dst_ll, LT_INTERNAL, &tmp );
    DCAssignLocation( &dst_ll, &src_ll, (scalar & SCLR_LEN_MASK) + 1 );
    switch( scalar ) {
    case SCLR_UNSIGNED + 0:
        return( tmp.u8 );
    case SCLR_UNSIGNED + 1:
        return( tmp.u16 );
    case SCLR_UNSIGNED + 3:
        return( tmp.u32 );
    case SCLR_INTEGER  + 0:
        return( tmp.s8 );
    case SCLR_INTEGER  + 1:
        return( tmp.s16 );
    case SCLR_INTEGER  + 3:
        return( tmp.s32 );
    }
    return( 0 );
}

#define TYPE_CACHE_SIZE 64              // must be power of 2

typedef struct {
    imp_image_handle    *ii;
    imp_mod_handle      im;
    unsigned            index;
    struct type_pos     t;
} type_cache;

static type_cache       TypeCache[TYPE_CACHE_SIZE];
static int              TypeCacheRover;

static dip_status FindTypeCache( imp_image_handle *ii, imp_mod_handle im,
                        unsigned index, imp_type_handle *it )
{
    int         i;
    type_cache  *cache;

    for( i = 0; i < TYPE_CACHE_SIZE; ++i ) {
        cache = &TypeCache[ i ];
        if( cache->ii == ii && cache->im == im && cache->index == index ) {
            it->im = im;
            it->f.all = 0;
            it->t.entry = cache->t.entry;
            it->t.offset = cache->t.offset;
            return( LoadType( ii, im, it->t.entry ) );
        }
    }
    return( DS_FAIL );
}


static void SetTypeCache( imp_image_handle *ii, imp_mod_handle im,
                        unsigned index, imp_type_handle *it )
{
    type_cache  *cache;

    cache = &TypeCache[ TypeCacheRover++ ];
    TypeCacheRover &= (TYPE_CACHE_SIZE-1);
    cache->ii = ii;
    cache->im = im;
    cache->index = index;
    cache->t.entry = it->t.entry;
    cache->t.offset = it->t.offset;
}


void ClearTypeCache( imp_image_handle *ii )
{
    int         i;

    for( i = 0; i < TYPE_CACHE_SIZE; ++i ) {
        if( TypeCache[i].ii == ii ) TypeCache[i].ii = NULL;
    }
}


static dip_status FindRawTypeHandle( imp_image_handle *ii, imp_mod_handle im,
                unsigned index, imp_type_handle *it )
{
    byte        *p;
    byte        kind;
    unsigned    entry;
    unsigned    count;

    if( index == 0 ) return( DS_FAIL );
    if( FindTypeCache( ii, im, index, it ) == DS_OK ) {
        return( DS_OK );
    }
    entry = 0;
    count = index;
    for( ;; ) {
        if( LoadType( ii, im, entry ) != DS_OK ) break;
        for( p = Type->start; p < Type->end; p = NEXT_TYPE( p ) ) {
            kind = *(p+1);
            switch( kind & CLASS_MASK ) {
            case ENUM_TYPE :
                if( (kind & SUBCLASS_MASK) == ENUM_LIST ) {
                    --count;
                }
                break;
            case STRUCT_TYPE :
                if( (kind & SUBCLASS_MASK) == STRUCT_LIST ) {
                    --count;
                }
                break;
            case NAME_TYPE:
                switch( kind & SUBCLASS_MASK ) {
                case TYPE_CUE_TABLE:
                    break;
                case TYPE_EOF:
                    FreeLoad();
                    return( DS_FAIL );
                default:
                    --count;
                    break;
                }
                break;
            default :
                --count;
            }
            if( count == 0 ) {
                it->im = im;
                it->f.all = 0;
                it->t.entry = entry;
                it->t.offset = p - Type->start;
                SetTypeCache( ii, im, index, it );
                return( DS_OK );
            }
        }
        ++entry;
    }
    return( DS_FAIL );
}

static int CharName( char *name, unsigned len )
{
    if( len > 4 ) {
        name += len - 5;
        if( name[0] != ' ' ) return( 0 );
        ++name;
    }
    if( memcmp( name, "char", 4 ) == 0 ) return( 1 );
    return( 0 );
}


static byte GetRealTypeHandle( imp_image_handle *ii, imp_type_handle *it )
{
    byte        *p;
    byte        *start;
    unsigned    index;
    byte        is_char;
    unsigned    len;

    it->f.s.chr = 0;
    is_char = 1;
    for( ;; ) {
        p = Type->start + it->t.offset;
        if( p[1] != NAME_TYPE+TYPE_NAME ) {
            if( is_char
             && p[0] >= 7
             && p[1] == NAME_TYPE+TYPE_SCALAR
             && CharName( &p[3], p[0] - 3 ) ) {
                it->f.s.chr = 1;
            }
            return( p[1] );
        }
        len = p[0];
        start = p;
        p = GetIndex( p + 2, &index ); /* scope index */
        p = GetIndex( p, &index );
        len -= (p - start);
        if( !(is_char && len >= 4 && CharName( p, len )) ) {
            is_char = 0;
        }
        if( FindRawTypeHandle( ii, it->im, index, it ) != DS_OK ) return( NO_TYPE );
        if( is_char ) it->f.s.chr = 1;
        is_char = 0;
    }
}

static dip_status DoFindTypeHandle( imp_image_handle *ii, imp_mod_handle im,
                unsigned index, imp_type_handle *it )
{
    byte                type;
    byte                *p;
    imp_type_handle     base;
    dip_status          ret;

    ret = FindRawTypeHandle( ii, im, index, it );
    if( ret != DS_OK ) return( ret );
    type = GetRealTypeHandle( ii, it );
    switch( type & CLASS_MASK ) {
    case NO_TYPE:
        return( DS_FAIL );
    case ARRAY_TYPE:
        if( stricmp( ImpInterface.mod_src_lang( ii, im ), "fortran" ) == 0 ) {
            it->f.s.col_major = 1;
            it->f.s.array_ss = 0;
            base = *it;
            for( ;; ) {
                p = Type->start + base.t.offset;
                if( (p[1] & CLASS_MASK) != ARRAY_TYPE ) break;
                p = BaseTypePtr( p );
                GetIndex( p, &index );
                FindRawTypeHandle( ii, base.im, index, &base );
                it->f.s.array_ss++;
            }
        }
        break;
    }
    return( DS_OK );

⌨️ 快捷键说明

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