cantype.c

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

C
692
字号
/****************************************************************************
*
*                            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!
*
****************************************************************************/


#include <string.h>
#include <stdlib.h>
#include "womp.h"
#include "genutil.h"
#include "myassert.h"
#include "memutil.h"
#include "cantype.h"
#include "namemgr.h"
#include "array.h"

STATIC array_hdr    *cantArr;
STATIC type_handle  nextHdl;
STATIC type_handle  reUseHdl;

#define validHdl( hdl )         ( (hdl) < nextHdl )

void CanTInit( void ) {
/*******************/

    cantArr = ArrCreate( sizeof( cantype ), NULL );
    reUseHdl = CANT_NULL;
    nextHdl = CANT_NULL;
    CanTReserve();
}

STATIC int freeElm( void *_node, void *parm ) {

    cantype *node = _node;
    parm = parm;
    switch( node->class ) {
    case CANT_ENUM:
        if( node->d.enumr.consts != NULL ) {
            MemFree( node->d.enumr.consts );
        }
        break;
    case CANT_STRUCT:
        if( node->d.strct.fields != NULL ) {
            MemFree( node->d.strct.fields );
        }
        break;
    case CANT_PROCEDURE:
        if( node->d.proc.parms != NULL ) {
            MemFree( node->d.proc.parms );
        }
        break;
    case CANT_ARRAY_DESC:
        CanADestroyHdl( node->d.arrayd.bounds );
        break;
    case CANT_CHARBLOCK_IND:
        CanADestroyHdl( node->d.charbi.length );
        break;
    }
    return( 0 );
}

void CanTFini( void ) {
/*******************/
    ArrWalk( cantArr, NULL, freeElm );
    ArrDestroy( cantArr );
}

cantype *CanTFind( type_handle hdl ) {
/**********************************/
/**/myassert( validHdl( hdl ) );
    return( (cantype *)ArrAccess( cantArr, (size_t)hdl ) );
}

STATIC cantype *newNode( uint_8 class ) {

    cantype *type;

    if( reUseHdl != CANT_NULL ) {
        type = (cantype *)ArrAccess( cantArr, (size_t)reUseHdl );
        type->hdl = reUseHdl;
        reUseHdl = CANT_NULL;
    } else {
        type = (cantype *)ArrNewElm( cantArr, (size_t)nextHdl );
        type->hdl = nextHdl;
        ++nextHdl;
    }
/**/myassert( nextHdl != CANT_NULL );   /* FIXME overflow */
    type->class = class;
    return( type );
}

type_handle CanTReserve( void ) {
/*****************************/
    cantype *type;

    type = newNode( CANT_RESERVED );
    return( type->hdl );
}

void CanTReUse( type_handle hdl ) {
/*******************************/
/**/myassert( reUseHdl == CANT_NULL );
    reUseHdl = hdl;
}

#ifndef NDEBUG
STATIC int isOrdinalType( type_handle hdl ) {

    cantype *type;

/**/myassert( validHdl( hdl ) );
    if( hdl == CANT_NULL ) {
        return( 0 );
    }
    type = CanTFind( hdl );
/**/myassert( type != NULL );
    switch( type->class ) {
    case CANT_INTEGER:
    case CANT_SUBRANGE:
    case CANT_ENUM:
        return( 1 );
    }
    return( 0 );
}
#endif

STATIC type_handle newScalar( bitsize size, uint_8 class ) {

    cantype *type;

    type = newNode( class );
    type->size = size;
    return( type->hdl );
}

type_handle CanTInteger( bitsize size, int sgned ) {
/************************************************/

    cantype *type;

    type = newNode( CANT_INTEGER );
    type->size = size;
    type->sgned = sgned;
    return( type->hdl );
}

type_handle CanTReal( bitsize size ) {
/**********************************/

    return( newScalar( size, CANT_REAL ) );
}

type_handle CanTComplex( bitsize size ) {
/*************************************/

    return( newScalar( size, CANT_COMPLEX ) );
}

type_handle CanTVoid( void ) {
/**************************/

    return( newScalar( 0, CANT_VOID ) );
}

type_handle CanTTypeDef( type_handle base_type, name_handle name,
    uint_8 scope ) {
/****************************************************************/
    cantype *type;
    cantype *base;

/**/myassert( validHdl( base_type ) );

    type = newNode( CANT_TYPEDEF );
    type->d.typdef.type = base_type;
    type->d.typdef.name = name;
    type->d.typdef.scope = scope;
    base = CanTFind( base_type );
    type->size = base->size;
    return( type->hdl );
}

STATIC int_32 signExtend( bitsize size, uint_32 field ) {
/*
    Field is a signed number of size bits.  Return field sign extended to
    32 bits
*/
    uint_32 mask;

    switch( size ) {        /* these are the common cases */
    case  8:    return( (int_8)field );
    case 16:    return( (int_16)field );
    case 32:    return( (int_32)field );
    }
                            /* now handle special cases */
/**/myassert( size < 32 );
    mask = ~(0UL) << ( size - 1 );  /* turn on all sign bits */

    /* An assumption we will make for speed is that if any bit in field&mask
       is on then field is negative.  This assertion just ensures that this
       assumption is valid. */
/**/myassert( ( ( field & mask ) != 0 ) ==
        ( ( field & ( 1 << ( size - 1 ) ) ) != 0 ) );

    return( ( field & mask ) ?
        ( field | mask )
        : field );
}

type_handle CanTSubRange( type_handle base_type, uint_32 low, uint_32 high ) {
/**************************************************************************/
    cantype *type;
    cantype *base;

/**/myassert( validHdl( base_type ) );
    base = CanTFind( base_type );
/**/myassert(   base->class == CANT_INTEGER ||
                base->class == CANT_ENUM ||
                base->class == CANT_SUBRANGE );
    type = newNode( CANT_SUBRANGE );
    type->d.subrng.base_type = base_type;
    type->size = base->size;
    type->sgned = base->sgned;
    if( type->sgned ) {
        type->d.subrng.low = signExtend( type->size, low );
        type->d.subrng.high = signExtend( type->size, high );
    } else {
        type->d.subrng.low = low;
        type->d.subrng.high = high;
    }
    return( type->hdl );
}

STATIC unsigned log2( uint_32 num ) {

    unsigned log2;

    log2 = 0;
    for(;;) {
        num >>= 1;
        if( num == 0 ) break;
        ++log2;
    }
    return( log2 );
}

type_handle CanTArray( type_handle base_hdl, type_handle idx_hdl ) {
/****************************************************************/
    cantype *type;
    cantype *idx_type;
    uint_32 num_elm;
    bitsize base_size;
    cantype *base_type;

/**/myassert( validHdl( idx_hdl ) && isOrdinalType( idx_hdl ) &&
        validHdl( base_hdl ) );
    type = newNode( CANT_ARRAY );
    type->d.array.index_type = idx_hdl;
    type->d.array.base_type = base_hdl;
    idx_type = CanTFind( idx_hdl );
/**/myassert( idx_type != NULL );
    switch( idx_type->class ) {
    case CANT_INTEGER:
        num_elm = 1 << idx_type->size;
        break;
    case CANT_ENUM:
        {
            /* this assumes the constants have been sorted by CanTGraph() */
            enum_const  *low;
            enum_const  *high;

            low = idx_type->d.enumr.consts;
            high = low + idx_type->d.enumr.num_consts - 1;
            if( idx_type->sgned ) {
                num_elm = (int_32)high->value - (int_32)low->value;
            } else {
                num_elm = high->value - low->value;
            }
            ++num_elm;  /* add 1 */
        }
        break;
    case CANT_SUBRANGE:
        if( idx_type->sgned ) {
            num_elm = (int_32)( idx_type->d.subrng.high ) -
                        (int_32)( idx_type->d.subrng.low );
        } else {
            num_elm = ( idx_type->d.subrng.high ) -
                        ( idx_type->d.subrng.low );
        }
        ++num_elm;  /* add 1 */
        break;
    }
    base_type = CanTFind( base_hdl );
    base_size = base_type->size;
    /* FIXME - this is a bad heuristic! */
    if( log2( num_elm ) + log2( base_size ) >= 32 ) {
        Fatal( MSG_ARRAY_TOO_LARGE, num_elm, base_size );
    }
    type->size = num_elm * base_size;
    return( type->hdl );
}

type_handle CanTArrayZ( type_handle base_hdl, uint_32 high ) {
/***********************************************************/

    cantype *type;
    cantype *base_type;
    bitsize base_size;

/**/myassert( validHdl( base_hdl ) );
    type = newNode( CANT_ARRAY_ZERO );
    type->d.arrayz.base_type = base_hdl;
    type->d.arrayz.high = high;
    base_type = CanTFind( base_hdl );
    base_size = base_type->size;
    if( log2( high ) + log2( base_size ) >= 32 ) {
        Fatal( MSG_ARRAY_TOO_LARGE, high, base_size );
    }
    type->size = ( high + 1 ) * base_size;
    return( type->hdl );
}

⌨️ 快捷键说明

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