cgbksvar.c

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

C
762
字号
/****************************************************************************
*
*                            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:  Back-end support for state-variable version.
*
****************************************************************************/

#include "plusplus.h"

#include <float.h>

#include "cgfront.h"
#include "cgback.h"
#include "memmgr.h"
#include "errdefns.h"
#include "codegen.h"
#include "cgbackut.h"
#include "ring.h"
#include "initdefs.h"

#ifndef NDEBUG
    #include <stdio.h>
    #include "dbg.h"
    #include "toggle.h"
    #include "pragdefn.h"
#endif

//**********************************************************************
// Static Data
//**********************************************************************

static carve_t carveSE_SYM_AUTO;    // allocations for SE_SYM_AUTO
static carve_t carveSE_SYM_STATIC;  // allocations for SE_SYM_STATIC
static carve_t carveSE_SUBOBJ;      // allocations for SE_SUBOBJ
static carve_t carveSE_TRY;         // allocations for SE_TRY
static carve_t carveSE_CATCH;       // allocations for SE_CATCH
static carve_t carveSE_FN_EXC;      // allocations for SE_FN_EXC
static carve_t carveSE_SET_SV;      // allocations for SE_SET_SV
static carve_t carveSE_TEST_FLAG;   // allocations for SE_TEST_FLAG
static carve_t carveSE_COMPONENT;   // allocations for SE_COMPONENT
static carve_t carveSE_ARRAY_INIT;  // allocations for SE_ARRAY_INIT
static carve_t carveSE_DLT_1;       // allocations for SE_DLT_1
static carve_t carveSE_DLT_2;       // allocations for SE_DLT_2
static carve_t carveSE_DLT_1_ARRAY; // allocations for SE_DLT_1_ARRAY
static carve_t carveSE_DLT_2_ARRAY; // allocations for SE_DLT_2_ARRAY
static carve_t carveSE_CTOR_TEST;   // allocations for SE_CTOR_TEST
static carve_t carveSTAB_DEFN;      // allocations for STAB_DEFN
static carve_t carveSTAB_CTL;       // allocations for STAB_CTL


//**********************************************************************
// internal support
//**********************************************************************

#define carver_DTC_ARRAY        NULL
#define carver_DTC_SYM_AUTO     &carveSE_SYM_AUTO
#define carver_DTC_SYM_STATIC   &carveSE_SYM_STATIC
#define carver_DTC_SUBOBJ       &carveSE_SUBOBJ
#define carver_DTC_TEST_FLAG    &carveSE_TEST_FLAG
#define carver_DTC_COMP_VBASE   &carveSE_COMPONENT
#define carver_DTC_COMP_DBASE   &carveSE_COMPONENT
#define carver_DTC_COMP_MEMB    &carveSE_COMPONENT
#define carver_DTC_ACTUAL_VBASE &carveSE_COMPONENT
#define carver_DTC_ACTUAL_DBASE &carveSE_COMPONENT
#define carver_DTC_TRY          &carveSE_TRY
#define carver_DTC_CATCH        &carveSE_CATCH
#define carver_DTC_FN_EXC       &carveSE_FN_EXC
#define carver_DTC_SET_SV       &carveSE_SET_SV
#define carver_DTC_ARRAY_INIT   &carveSE_ARRAY_INIT
#define carver_DTC_DLT_1        &carveSE_DLT_1
#define carver_DTC_DLT_2        &carveSE_DLT_2
#define carver_DTC_DLT_1_ARRAY  &carveSE_DLT_1_ARRAY
#define carver_DTC_DLT_2_ARRAY  &carveSE_DLT_2_ARRAY
#define carver_DTC_CTOR_TEST    &carveSE_CTOR_TEST

static carve_t* seCarvers[] = {
    #define DTC_DEF( a ) carver_ ## a
    #define DTC_MRK( a )
    #define DTC_VAL( a, b ) DTC_DEF( a )
    DTC_DEFS
    #undef  DTC_DEF
    #undef  DTC_MRK
    #undef  DTC_VAL
};


#ifndef NDEBUG
static carve_t seCarver(        // GET CARVER FOR AN SE TYPE
    uint_8 se_type )            // - code for entry
{
    DbgVerify( se_type < MAX_DTC_DEF, "seCarver -- BAD DTC_..." );
    DbgVerify( se_type != DTC_ARRAY,  "seCarver -- BAD DTC_..." );
    return *seCarvers[ se_type ];
}
#else
    #define seCarver(a) *seCarvers[a]
#endif


static void seFree(             // FREE AN SE ENTRY
    SE* se )                    // - entry
{
    CarveFree( seCarver( se->base.se_type ), se );
}


static void pruneSE(            // PRUNE STATE ENTRY
    SE** a_stab,                // - addr[ state table pointer ]
    SE* se )                    // - entry to be removed
{
    SE* prev                    // - previous entry
        = se->base.prev;
    SE* next                    // - next entry
        = se->base.next;

    RingPrune( a_stab, se );
#ifndef NDEBUG
    if( PragDbgToggle.dump_stab ) {
        printf( "State Table[%x] removed: %x\n", a_stab, se );
        DbgDumpStateEntry( se );
    }
#endif
    next->base.prev = prev;
    prev->base.next = next;
    seFree( se );
}


static boolean sameSE(          // DETERMINE IF SAME STATE ENTRY
    SE* se,                     // - state entry to be added
    SE* state_table )           // - state table
{
    SE* last;                   // - last state entry in table
    boolean retn;               // - TRUE ==> same entry

    last = state_table;
    if( last == NULL ) {
        retn = FALSE;
    } else {
        if( last->base.se_type == DTC_CTOR_TEST ) {
            last = last->base.prev;
        }
        if( last->base.se_type == se->base.se_type ) {
            switch( se->base.se_type ) {
              case DTC_SET_SV :
                last->set_sv.se = se->set_sv.se;
// check for SET_SV to previous
#ifndef NDEBUG
                if( PragDbgToggle.dump_stab ) {
                    printf( "State Table replacement %x\n", se );
                    DbgDumpStateEntry( last );
                }
#endif
                retn = TRUE;
                break;
              case DTC_TEST_FLAG :
                if(  last->test_flag.index    == se->test_flag.index
                  && last->test_flag.se_true  == se->test_flag.se_true
                  && last->test_flag.se_false == se->test_flag.se_false ) {
                    retn = TRUE;
                } else {
                    retn = FALSE;
                }
                break;
              default :
                retn = FALSE;
                break;
            }
        } else {
            retn = FALSE;
        }
    }
    return retn;
}



static SE* stateTableAddSe(     // ADD TO STATE TABLE
    SE* se,                     // - state entry
    SE** a_stab )               // - addr[ state table pointer ]
{
    SE* next;                   // - next in doubly linked ring
    SE* state_table;            // - end of state table
    unsigned state_var;         // - value of state variable

    state_table = *a_stab;
    if( sameSE( se, state_table ) ) {
        seFree( se );
        se = state_table;
    } else {
        if( se->base.se_type == DTC_TEST_FLAG
         && NULL != state_table
         && state_table->base.se_type == DTC_SET_SV ) {
            pruneSE( a_stab, *a_stab );
            state_table = *a_stab;
        }
        if( NULL == state_table ) {
            state_var = 0;
        } else {
            state_var = state_table->base.state_var;
        }
        if( se->base.gen ) {
            ++ state_var;
        }
        se->base.state_var = state_var;
        RingAppend( a_stab, se );
        next = se->base.next;
        se->base.prev = next->base.prev;
        next->base.prev = se;
#ifndef NDEBUG
        if( PragDbgToggle.dump_stab ) {
            printf( "State Table[%x] added: %x\n", a_stab, se );
            DbgDumpStateEntry( se );
        }
#endif
    }
    return se;
}


//**********************************************************************
// STAB_DEFN Support
//**********************************************************************

STAB_DEFN* StabDefnInit(        // INITIALIZE STAB_DEFN
    STAB_DEFN* defn,            // - definition
    unsigned kind )             // - kind of table
{
    defn->kind = kind;
    defn->state_table = NULL;
    defn->ro = NULL;
    return defn;
}


STAB_DEFN* StabDefnAllocate(    // ALLOCATE STAB_DEFN
    unsigned kind )             // - kind of table
{
    return StabDefnInit( CarveAlloc( carveSTAB_DEFN ), kind );
}


void StabDefnFree(              // FREE AN STAB_DEFN
    STAB_DEFN* defn )           // - entry to be freed
{
    CarveFree( carveSTAB_DEFN, defn );
}


SE* StabDefnAddSe(              // ADD STATE ENTRY TO STATE TABLE
    SE* se,                     // - entry to be added
    STAB_DEFN* defn )           // - state table definition
{
    return stateTableAddSe( se, &defn->state_table );
}


void StabDefnFreeStateTable(    // FREE A STATE TABLE
    STAB_DEFN* defn )           // - definition for state table
{
    SE* se;                     // - current state entry

    if( NULL != defn ) {
        RingIterBegSafe( defn->state_table, se ) {
            seFree( se );
        } RingIterEndSafe( se )
    }
}


static void stabDefnRemove(     // REMOVE TOP ENTRY
    STAB_DEFN* defn )           // - definition for state table
{
    pruneSE( &defn->state_table, defn->state_table );
}



//**********************************************************************
// STAB_CTL Support
//**********************************************************************

STAB_CTL* StabCtlInit(          // INITIALIZE STAB_CTL
    STAB_CTL* stab,             // - control info: instance
    STAB_DEFN* defn )           // - control information: definition
{
    stab->rw = NULL;
    stab->defn = defn;
    return stab;
}


SE* StateTableCurrPosn(         // GET STATE ENTRY FOR CURRENT POSITION
    STAB_CTL* sctl )            // - control info
{
    SE* curr_posn;              // - current position

    if( sctl->defn == NULL ) {
        curr_posn = NULL;
    } else {
        curr_posn = SeSetSvPosition( sctl->defn->state_table );
    }
    return curr_posn;
}


SE* StateTableActualPosn(       // GET (UN-OPTIMIZED) CURRENT STATE ENTRY
    STAB_CTL* sctl )            // - control info
{
    return sctl->defn->state_table;
}


SE* StabCtlPrecedes(            // GET PRECEDING ENTRY OR NULL
    STAB_CTL* sctl,             // - control info
    SE* se )                    // - state entry
{
    se = se->base.prev;
    if( se == sctl->defn->state_table ) {
        se = NULL;
    }
    return se;
}


SE* StabCtlPrevious(            // GET PREVIOUS ENTRY OR NULL
    STAB_CTL* sctl,             // - control info
    SE* se )                    // - state entry
{
    return SeSetSvPosition( StabCtlPrecedes( sctl, se ) );
}


static void pruneFixUp(         // FIX-UP PTR. TO ENTRY, FOR PRUNING
    SE** a_se )                 // - addr[ SE ptr ]
{
    SE* se;                     // - entry
    STATE_VAR state_var;        // - state value

    se = *a_se;
    if( se != NULL && ! se->base.gen ) {
        state_var = se->base.state_var;
        if( 0 == state_var ) {
            se = NULL;
        } else {
            for( ; ; ) {
                se = se->base.prev;
                if( se->base.state_var == state_var ) {
                    if( se->base.gen ) break;
                }
            }
        }
        *a_se = se;
    }
}


void StabCtlPrune(              // PRUNE UN-GENNED ENTRIES UP TO AN ENTRY

⌨️ 快捷键说明

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