cantype.h
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C头文件 代码 · 共 340 行
H
340 行
/****************************************************************************
*
* 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: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#ifndef CANTYPE_H
#define CANTYPE_H 1
typedef uint_32 bitsize; /* type for sizes of types in bits */
typedef uint_16 type_handle; /* type for referencing other types */
#define CANT_NULL ((type_handle)0)/* unused handle */
typedef struct cantype cantype;
typedef struct enum_const enum_const;
typedef struct struct_field struct_field;
typedef struct proc_parm proc_parm;
#include <stddef.h>
#include <watcom.h>
#include "canaddr.h"
#include "namemgr.h"
/*
The following struct represents a type. Each cantype is a node in the
complete type graph for an object file.
See the note about CanTMunge for details as to when all of these fields
are valid.
*/
struct cantype {
type_handle hdl; /* type handle for this type */
/*
There are arrays that depend on the ordering of this enum.
*/
enum cantype_class {
CANT_RESERVED,
CANT_INTEGER,
CANT_REAL,
CANT_VOID,
CANT_COMPLEX,
CANT_TYPEDEF,
CANT_SUBRANGE,
CANT_ARRAY,
CANT_ARRAY_ZERO,
CANT_ARRAY_DESC,
CANT_POINTER,
CANT_ENUM,
CANT_STRUCT,
CANT_PROCEDURE,
CANT_CHARBLOCK,
CANT_CHARBLOCK_IND
} class; /* class of this type */
uint_8 sgned :1; /* for integer types */
uint_8 busy :1; /* can be used while exploring type graph */
bitsize size; /* size of this type in bits */
uint_32 extra; /* an extra field for use by parser or
generator in any manner it wishes */
union {
/*
The following types have no extra data:
CANT_INTEGER, CANT_VOID, CANT_REAL, CANT_COMPLEX
*/
/*
CANT_TYPEDEF: Attach a new name to an existing type
*/
struct {
type_handle type; /* type of this name */
name_handle name; /* name of this type */
enum {
CANT_SCOPE_NULL = 0,
CANT_SCOPE_STRUCT, /* i.e., "struct name" */
CANT_SCOPE_UNION,
CANT_SCOPE_ENUM
} scope; /* scope of this typedef */
} typdef;
/*
CANT_SUBRANGE: Subrange of CANT_INTEGER, CANT_ENUM, or CANT_SUBRANGE
*/
struct {
type_handle base_type;
uint_32 low;
uint_32 high;
} subrng;
/*
CANT_ARRAY: Array -- bounds are determined by another type (known at
compile time)
NOTE: in each of these array types the base_type is the first structure
element. DON'T CHANGE THIS!
*/
struct {
type_handle base_type; /* base type of the array */
type_handle index_type; /* CANT_SUBRANGE type of indicies */
} array;
/*
CANT_ARRAY_ZERO: Array -- bounds are of form 0..high (Use for C Arrays)
*/
struct {
type_handle base_type;
uint_32 high;
} arrayz;
/*
CANT_ARRAY_DESC: Array -- bounds not known at compile-time
*/
struct {
type_handle base_type;
type_handle lo_type; /* data type of low bound */
type_handle hi_type; /* data type of high bound */
addr_handle bounds; /* memory that contains struct with low
and high bounds in that order */
} arrayd;
/*
CANT_POINTER: pointer types
*/
struct {
type_handle base_type; /* type pointed to */
enum { /* attributes for pointer */
CANT_PTR_FAR = 0x01,
CANT_PTR_HUGE = 0x02,
CANT_PTR_DEREF = 0x04,
CANT_PTR_386 = 0x08
} class;
} pointr;
/*
CANT_ENUM: enumerated constants of type CANT_INTEGER, or CANT_SUBRANGE
*/
struct {
type_handle base_type; /* base data type */
uint_16 num_consts; /* number of consts in array */
struct enum_const {
name_handle name;
uint_32 value;
} *consts;
} enumr;
/*
CANT_STRUCT: structures and unions
*/
struct {
uint_16 num_fields;
struct struct_field {
uint_32 bit_offset;
type_handle type;
name_handle name;
uint_8 bitfield : 1;
} *fields;
} strct;
/*
CANT_PROCEDURE: procedure return and parameter types
parms[0] is leftmost parameter
parms[1] is next parm
...
parms[num_parms-1] is rightmost parameter
*/
struct {
type_handle ret_type; /* return type of procedure */
enum {
CANT_PROC_FAR = 0x01, /* __far procedure bit field */
CANT_PROC_386 = 0x02 /* 386 procedure */
} class;
uint_8 num_parms; /* number of parameters */
struct proc_parm {
type_handle type;
} *parms;
} proc;
/*
CANT_CHARBLOCK: FORTRAN character block type
*/
struct {
uint_32 length; /* length of character block */
} charb;
/*
CANT_CHARBLOCK_IND: FORTRAN character block type
*/
struct {
addr_handle length; /* location of variable length value */
type_handle length_type;/* data type of length */
} charbi;
} d;
};
/*
In my (DJG) opinion, the CHARBLOCK_IND and ARRAY_DESC types are implemented
improperly. There should be no addr_handles in the type graph. It would
be more appropriate if a CHARBLOCK_IND were simply:
struct {
type_handle length_type;
} charbi;
Then there can be a CANS_(MEM_LOC|BP_OFFSET|REGISTER) that has the
type_handle of this CHARBLOCK_IND.
If WATCOM and Microsoft DBI were handled this way then we could do proper
translation of Fortran programs...
*/
void CanTInit( void );
void CanTFini( void );
/*
The following functions are used to construct the graph
*/
type_handle CanTReserve( void );
void CanTReUse( type_handle hdl );
type_handle CanTInteger( bitsize size, int sgned );
type_handle CanTReal( bitsize size );
type_handle CanTComplex( bitsize size );
type_handle CanTVoid( void );
type_handle CanTTypeDef( type_handle base_type, name_handle name, uint_8 scope);
type_handle CanTSubRange( type_handle base_type, uint_32 lo, uint_32 hi );
type_handle CanTArray( type_handle base_type, type_handle index_type );
type_handle CanTArrayZ( type_handle base_type, uint_32 high );
type_handle CanTArrayD( type_handle base_type, type_handle lo_type,
type_handle hi_type, addr_handle bounds );
type_handle CanTPointer( type_handle base_type, uint_8 class );
cantype * CanTEnum( type_handle base_type, uint_16 num_consts );
cantype * CanTStruct( uint_16 num_fields );
cantype * CanTProcedure( type_handle ret_type,uint_8 class, uint_8 num_parms);
type_handle CanTCharB( uint_32 length );
type_handle CanTCharBI( type_handle length_type, addr_handle length );
type_handle CanTDupSize( type_handle type_hdl, bitsize newsize );
/*
CanTGraph must be called with the type returned from CanTStruct,
CanTProcedure, and CanTEnum after the fields/parms have been initialized.
*/
void CanTGraph( cantype *type );
/*
The following functions are used to traverse the graph.
*/
cantype * CanTFind( type_handle hdl );
int CanTWalk( void *parm, int (*func)( void *type, void *parm ) );
cantype * CanTElimTypeDef( type_handle start_hdl );
/*
When the graph is first constructed not all nodes are complete. So
CanTMunge is used to complete the nodes of the graph. CanTMunge
has the following post condition:
for each node T in the graph {
T->sized == 1; ( hence T->size is valid )
switch( T->class ) {
case CANT_SUBRANGE:
T->sgned is set according to T->d.subrng.base_type;
if( T->sgned ) {
T->d.subrng.low && T->d.subrng.high are sign extended
from T->size bits to full int_32s.
}
break;
case CANT_ARRAY:
switch( T->d.array.index_type ) {
case CANT_INTEGER:
num_elms = 1 << index_type->size;
break;
case CANT_ENUM:
num_elms = highest value in ENUM - lowest value in ENUM + 1;
break;
case CANT_SUBRANGE:
num_elms = SUBRANGE high - SUBRANGE low + 1;
break;
}
T->size = size of base_type * num_elms;
break;
case CANT_ENUM:
T->sgned is set according to T->d.enumr.base_type;
if( T->sgned ) {
for each constant C in T->d.enumr.consts {
C->value is signed extended from T->size bits to int_32s
}
}
The list of constants C is sorted in increasing order by value.
break;
case CANT_STRUCT:
T->size is set to the maximum of the set of
{ F->bit_offset + sizeof F->type where F is any field of T }
The list of fields F is sorted in increasing order by bit_offset,
and for identical bit_offsets fields are sorted in order by
increasing size.
break;
}
}
Basically this post condition guarantees that the graph is cohesive and
useful for generating debugging information from. There is no guarantee
that any of these conditions are met prior to a call to CanTMunge.
CanTMunge assumes that the graph is complete. i.e., there are no missing
nodes. (Such as the base_type for a TYPEDEF.)
The debugging parser should call CanTMunge as its last action when
building the type graph.
*/
void CanTMunge( void );
#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?