dftype.c

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

C
1,391
字号
/****************************************************************************
*
*                            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:  Type handle support for DWARF DIP.
*
****************************************************************************/


#include <stddef.h>
#include <string.h>
#include <limits.h>
#include "dfdip.h"
#include "dfld.h"
#include "dfmod.h"
#include "dfmodinf.h"
#include "dfloc.h"
#include "dfclean.h"

typedef struct {
    dr_handle curr;
    int       skip;
} array_wlk_skip; /* and jump */

static int ArrayIndexSkip( dr_handle index, int pos, void *_df )
{
    array_wlk_skip *df = _df;
    pos = pos;
    if( df->skip == 0 ){
        df->curr = index;
        return( FALSE );
    }
    df->skip--;
    return( TRUE );
}

static DRWLKBLK ArrayWlkNext[DR_WLKBLK_ARRSIB] = {
    ArrayIndexSkip,
    ArrayIndexSkip,
    NULL
};

static dr_handle GetArrayDim( dr_handle index, int skip  ){
// Get current or next dim handle
    array_wlk_skip df;

    df.skip = skip;
    if( !DRWalkArraySibs( index, ArrayWlkNext, &df ) ){
      index = df.curr;
    }else{
      index = NULL;
    }
    return( index );
}

static int  GetStrLen( imp_image_handle *ii,
                        dr_handle dr_sym,
                        location_context *lc,
                        dr_typeinfo  *ret ){
//  Find value of scalar
    uint_32         seg;
    location_list   src;
    location_list   dst;
    im_idx          imx;
    union{
        long  l;
        short s;
        char  c;
    }val;
    int             idx_size;

    imx = DwarfModIdx( ii, dr_sym );
    if( imx == INVALID_IMX ){
        return( FALSE );
    }
    if( ii->mod_map[imx].is_segment == FALSE ){
        seg = SEG_DATA; // if flat hoke segment
    }else{
        EvalSeg( ii, dr_sym, &seg );
    }
    if( EvalLocation( ii, lc, dr_sym, seg, &src ) != DS_OK ){
        return( FALSE );
    }
    idx_size = ret->size;
    if( idx_size == 0 ){
        idx_size = ii->mod_map[imx].addr_size;
    }
    LocationCreate( &dst, LT_INTERNAL, &val );
    if( DCAssignLocation( &dst, &src, idx_size ) != DS_OK ){
        return( FALSE );
    }
    switch( idx_size ){
    case 1:
        ret->size = val.c;
        break;
    case 2:
        ret->size = val.s;
        break;
    case 4:
        ret->size = val.l;
        break;
    }
    return( TRUE );
}

/***********************/
/* Walk array dims     */
/***********************/
typedef struct{
    int_32           low;
    uint_32          count;
    imp_image_handle *ii;
    imp_type_handle  *it;
    location_context *lc;
    uint_32          num_elts;
    int              dim;
    int              cont;
}array_wlk_wlk;

static int ArraySubRange( dr_handle tsub, int index, void *df );
static int ArrayEnumType( dr_handle tenu, int index, void *df );
static DRWLKBLK ArrayWlk[DR_WLKBLK_ARRSIB] = {
    ArraySubRange,
    ArrayEnumType,
    NULL
};

static void GetArraySize( imp_image_handle *ii,
                          imp_type_handle  *it,
                          location_context *lc ){
//Calculate size of array starting at it->array.index;
    dr_handle     dim;
    array_wlk_wlk df;
    uint_32       base_stride;

    df.ii = ii;
    df.it = it;
    df.lc = lc;
    df.count = 1;
    df.dim = 0;
    df.cont = FALSE;
    DRWalkArraySibs( it->array.index, ArrayWlk, &df );
    it->array.num_elts = df.count;
    it->array.low = df.low;
    df.cont = TRUE;
    dim = GetArrayDim( it->array.index, 1 );
    if( dim != NULL ){
        DRWalkArraySibs( dim, ArrayWlk, &df );
    }
    it->array.dims = df.dim;
    it->typeinfo.size = df.count * it->array.base_stride;
    if( !it->array.column_major ){
        base_stride = it->typeinfo.size;
        base_stride /= it->array.num_elts;
        it->array.base_stride = base_stride;
    }
    it->array.is_set = TRUE;
    it->array.is_based = FALSE;
}

static void GetArraySubSize( imp_image_handle *ii,
                          imp_type_handle  *it,
                          location_context *lc ){
// Calc array size one in from previous dim
    array_wlk_wlk df;
    uint_32         new_size;
    uint_32         base_stride;

    df.ii = ii;
    df.it = it;
    df.lc = lc;
    df.count = 1;
    df.dim = 0;
    df.cont = FALSE;
    DRWalkArraySibs( it->array.index, ArrayWlk, &df );
    new_size = it->typeinfo.size;
    new_size /= it->array.num_elts;
    if( it->array.column_major ){
        base_stride = it->array.base_stride;
        base_stride *= it->array.num_elts;
        it->array.base_stride = base_stride;
    }else{
        base_stride = it->typeinfo.size;
        base_stride /= df.count;
        it->array.base_stride = base_stride;
    }
    it->typeinfo.size = new_size;
    it->array.num_elts = df.count;
    it->array.low = df.low;
    --it->array.dims;
    it->array.is_set = TRUE;
    it->array.is_based = FALSE;
}

static void InitTypeHandle( imp_image_handle *ii,
                            imp_type_handle  *it,
                            location_context *lc  ){
/***********************************************************************/
//Set type handle to the base state
//If array poise at first index
    imp_type_handle sub;
    dr_array_info   info;
    dr_handle       btype;
    dr_array_stat   stat;
    uint_32         base_stride;

    if( it->state == DF_NOT ) {
        DRSetDebug( ii->dwarf->handle ); /* must do at each call into dwarf */
        DRGetTypeInfo( it->type, &it->typeinfo );
        it->state = DF_SET;
        it->sub_array = FALSE;
        if( it->typeinfo.kind == DR_TYPEK_ARRAY ){
            if( it->typeinfo.size == 0 ){
                btype =  DRSkipTypeChain( it->type ); /* skip modifiers and typedefs */
                stat = DRGetArrayInfo( btype, &info );
                if( stat & DR_ARRAY_STRIDE_SIZE ){
                    base_stride = info.stride_size/8;
                }else{
                    btype = DRGetTypeAT( btype );    /* get base type */
                    sub.type = btype;
                    sub.imx = it->imx;
                    sub.state = DF_NOT;
                    InitTypeHandle( ii, &sub, lc );
                    base_stride = sub.typeinfo.size;
                }
                it->array.base_stride = base_stride;
                it->array.column_major = 0; /* 1 for fortran */
                if( stat & DR_ARRAY_ORDERING ){
                    if( info.ordering == DW_ORD_col_major ){
                        it->array.column_major = 1;
                    }
                }else if( ii->mod_map[it->imx].lang == DR_LANG_FORTRAN ){
                    it->array.column_major = 1;
                }
                if( info.child == NULL ){ // set info now
                    it->array.dims = 1;
                    it->array.low = 0;
                    it->array.index = 0;
                    if( stat & DR_ARRAY_COUNT ){
                        if( info.count == 0 ){ // ie  char (*x)[]
                            info.count = 1;
                        }
                        it->typeinfo.size = info.count * it->array.base_stride;
                        it->array.num_elts= info.count;
                    }else{
                        it->typeinfo.size =  it->array.base_stride;
                    }
                    if( !it->array.column_major ){
                        base_stride = it->typeinfo.size;
                        base_stride /= it->array.num_elts;
                        it->array.base_stride = base_stride;
                    }
                    it->array.is_set = TRUE;
                    it->array.is_based = FALSE;
                    it->sub_array = FALSE;
                }else{
                    it->sub_array = TRUE;
                    it->array.is_set = FALSE;
                    it->array.index = GetArrayDim( info.child, 0 );
                }
            }
        }else if( it->typeinfo.kind == DR_TYPEK_STRING ){
            if( DRStringLengthAT( it->type ) != NULL ){
                if( !GetStrLen( ii, it->type, lc, &it->typeinfo ) ){
                    it->typeinfo.size = 1;
                }
            }
        }
    }
    if( it->typeinfo.kind == DR_TYPEK_ARRAY ){
        if( it->array.is_set == FALSE ){
            GetArraySize( ii, it, lc );
        }else if( it->array.is_based ){
            GetArraySubSize( ii, it, lc );
        }
    }
}

struct mod_type{
    imp_image_handle *ii;
    im_idx          imx;
    IMP_TYPE_WKR    *wk;
    imp_type_handle *it;
    void            *d;
    walk_result     wr;
};

static int AType( dr_handle type, void *_typ_wlk, dr_search_context *cont ) {
/***************************************************************************/
    struct mod_type *typ_wlk = _typ_wlk;
    int             ret;
    imp_type_handle *it;
    dr_dbg_handle  saved;

    cont = cont;
    ret = TRUE;
    it = typ_wlk->it;
    it->imx = typ_wlk->imx;
    it->state = DF_NOT;
    it->type = type;
    saved = DRGetDebug();
    typ_wlk->wr = typ_wlk->wk( typ_wlk->ii, it, typ_wlk->d );
    DRSetDebug( saved );
    if( typ_wlk->wr != WR_CONTINUE ){
        ret = FALSE;
    }
    return( ret );
}

walk_result     DIPENTRY DIPImpWalkTypeList( imp_image_handle *ii,
                    imp_mod_handle im, IMP_TYPE_WKR *wk, imp_type_handle *it,
                    void *d )
{
    im_idx          imx;
    dr_handle       cu_tag;
    struct mod_type typ_wlk;

    DRSetDebug( ii->dwarf->handle ); /* must do at each interface */
    imx = IM2IMX( im );
    cu_tag = ii->mod_map[imx].cu_tag;
    typ_wlk.ii = ii;
    typ_wlk.imx = imx;
    typ_wlk.wk = wk;
    typ_wlk.it  = it;
    typ_wlk.d   = d;
    DRWalkModTypes( cu_tag, AType, &typ_wlk );
    return( typ_wlk.wr );
}

imp_mod_handle  DIPENTRY DIPImpTypeMod( imp_image_handle *ii,
                                imp_type_handle *it )
{
    /*
        Return the module that the type handle comes from.
    */
    ii = ii;
    return( IMX2IM( it->imx ) );
}

extern void MapImpTypeInfo( dr_typeinfo *typeinfo, type_info *ti )
{
    /*
        Map dwarf info to dip imp
    */
    type_kind   kind;

    ti->modifier = TM_NONE;
    switch( typeinfo->kind ){
    case DR_TYPEK_NONE:
        kind = TK_NONE;
        break;
    case DR_TYPEK_DATA:
        kind = TK_DATA;
        break;
    case DR_TYPEK_CODE:
        kind = TK_CODE;
        break;
    case DR_TYPEK_ADDRESS:
        kind = TK_ADDRESS;
        break;
    case DR_TYPEK_VOID:
        kind = TK_VOID;
        break;
    case DR_TYPEK_BOOL:
        kind = TK_BOOL;
        break;
    case DR_TYPEK_ENUM:
        kind = TK_ENUM;
        break;
    case DR_TYPEK_CHAR:
        kind = TK_CHAR;
        break;
    case DR_TYPEK_INTEGER:
        kind = TK_INTEGER;
        break;
    case DR_TYPEK_REAL:
        kind = TK_REAL;
        break;
    case DR_TYPEK_COMPLEX:
        kind = TK_COMPLEX;
        break;
    case DR_TYPEK_STRING:
        kind = TK_STRING;
        break;
    case DR_TYPEK_POINTER:
        kind = TK_POINTER;
        break;
    case DR_TYPEK_REF:
        kind = TK_POINTER;
        break;
    case DR_TYPEK_STRUCT:
    case DR_TYPEK_UNION:
    case DR_TYPEK_CLASS:
        kind = TK_STRUCT;
        break;
    case DR_TYPEK_ARRAY:
        kind = TK_ARRAY;
        break;
    case DR_TYPEK_FUNCTION:
        kind = TK_FUNCTION;
        break;
    }
    ti->kind = kind;
    ti->size = typeinfo->size;
    ti->modifier = TM_NONE;
    switch( typeinfo->mclass ){
    case DR_MOD_BASE:
        if( (ti->kind == TK_INTEGER) || (ti->kind == TK_CHAR)) {
            if( typeinfo->modifier.sign ) {
                ti->modifier = TM_SIGNED;
            } else {
                ti->modifier = TM_UNSIGNED;
            }
        }
        break;
    case DR_MOD_ADDR:
        switch( typeinfo->modifier.ptr ){
        case DR_PTR_none:
            ti->modifier = TM_NEAR;
            break;
        case DR_PTR_near16:
        case DR_PTR_near32:
            ti->modifier = TM_NEAR;
            break;
        case DR_PTR_far16:
        case DR_PTR_far32:
            ti->modifier = TM_FAR;
            break;
        case DR_PTR_huge16:
            ti->modifier = TM_HUGE;
            break;
        }
        if( typeinfo->kind == DR_TYPEK_REF ){
            ti->modifier |= TM_FLAG_DEREF;
        }
        break;
    }
}

dip_status      DIPENTRY DIPImpTypeInfo( imp_image_handle *ii,
                imp_type_handle *it, location_context *lc, type_info *ti )
{

⌨️ 快捷键说明

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