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 + -
显示快捷键?