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