cgbkmain.c

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

C
1,832
字号
/****************************************************************************
*
*                            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 control for C++.
*
****************************************************************************/


#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 "cgaux.h"
#include "cginfo.h"
#include "ring.h"
#include "conpool.h"
#include "stringl.h"
#include "rtfuncod.h"
#include "carve.h"
#include "label.h"
#include "vstk.h"
#include "context.h"
#include "name.h"
#include "ctexcept.h"
#include "symdbg.h"
#include "dwarfdbg.h"
#include "callgrph.h"
#include "cdopt.h"
#include "initdefs.h"
#include "stats.h"
#include "specfuns.h"
#include "objmodel.h"
#include "extrf.h"
#include "fmtsym.h"
#include "floatsup.h"
#include "rtti.h"

#ifndef NDEBUG
#include "pragdefn.h"
#endif



#define ST_backwards_beg( h, i )        \
    {                                   \
        SE* __HDR = h;                  \
        SE* __PRV = NULL;               \
        for( i = __HDR; __PRV != __HDR; i = __PRV ) {  \
            __PRV = i->base.prev;

#define ST_backwards_end                \
        }                               \
    }

#define ST_backwards_prev( p )          \
            __PRV = p

#define ST_backwards_setsv( s )         \
            __PRV = (s)->set_sv.se;     \
            if( __PRV == NULL ) {       \
                __PRV = __HDR;          \
            }

#define IC_PARM_STACK_SIZE      (16)
#define IC_PARM_PUSH_PTR( p )           \
        DbgAssert( ic_sp < IC_PARM_STACK_SIZE ); \
        ic_parms[ic_sp++].pvalue = p;
#define IC_PARM_PUSH_INT( i )           \
        DbgAssert( ic_sp < IC_PARM_STACK_SIZE ); \
        ic_parms[ic_sp++].ivalue = i;
#define IC_PARM_POP_PTR( p )            \
        DbgAssert( ic_sp != 0 ); \
        p = ic_parms[--ic_sp].pvalue;
#define IC_PARM_POP_INT( i )            \
        DbgAssert( ic_sp != 0 ); \
        i = ic_parms[--ic_sp].ivalue;
#define IC_PARM_DONE                    \
        DbgAssert( ic_sp == 0 );        \
        ic_sp = 0;

#ifndef NDEBUG
    #include <stdio.h>
    #include "dbg.h"
    #define dump_label( ins ) if( PragDbgToggle.dump_labels ) ins
#else
    #define dump_label( ins )
#endif


#define TY_VOID TY_INTEGER


static VSTK_CTL stack_labs_cs;      // stack: labels (control)
static VSTK_CTL stack_goto_near;    // stack: gotos (near)

static unsigned max_inline_depth;   // maximum depth of inlining
static unsigned depth_inline;       // depth of inlining
static SYMBOL statics;              // static symbols (freed at file end)
static SYMBOL autos;                // automatic variables for procedure
static carve_t carveTRY_IMPL;       // allocations for TRY_IMPL
static carve_t carveSTAB_OBJ;       // allocations for STAB_OBJ
static SCOPE scope_exit;            // scope exited by IC_SCOPE_EXIT
static CGFILE *data_file;           // data file
static STAB_OBJ* state_tables_obj;  // state tables for objects
static boolean sig_thunk_genned;    // TRUE ==> significant thunk genned

static SYMBOL thisSym;              // model for 'this' symbol
static SYMBOL cdtorSym;             // model for cdtor extra parm

static TRY_IMPL* fun_try_impls;     // function try implementations
// static SYMBOL new_ctor_ptr;         // contains ptr to new'ed area

ExtraRptCtr( ctr_ic_codes );        // number of IC codes
ExtraRptCtr( ctr_inlines );         // number of inlines
ExtraRptCtr( ctr_funcs );           // number of functions

CGBK_INFO CgbkInfo;                 // useful information


static void cgResetThis(        // RESET THIS, IF REQUIRED
    target_offset_t offset )    // - offset of object just CTOR'ed/DTOR'ed
{
    SYMBOL sym;                 // - symbol for " this"
    SYMBOL ref;                 // - not used: bound reference
    target_offset_t offset_ref; // - not used: offset from bound reference
    cg_name expr;               // - expression

    if( ! IbpReference( NULL, &sym, &ref, &offset_ref ) ) {
        expr = CgExprPop();
        if( offset > 0 ) {
           expr = CGBinary( O_MINUS, expr, CgOffset( offset ), T_POINTER );
        }
        expr = CGLVAssign( CgSymbol( sym ), expr, T_POINTER );
        CgExprPush( expr, T_POINTER );
    }
}


unsigned CgNonThunkDepth(       // COMPUTE INLINE DEPTH WITHOUT THUNKS
    FN_CTL* fctl )              // - current function
{
    unsigned real_depth;        // - depth without inlines

    real_depth = depth_inline;
    if( real_depth > 0 ) {
        for( ; ; ) {
            fctl = FnCtlPrev( fctl );
            if( fctl == NULL ) break;
            if( SymIsThunk( fctl->func ) ) {
                -- real_depth;
            }
        }
    }
    return real_depth;
}

#if 0
static void push_optional_expr( // PUSH EXPRESSION IF NOT EMPTY
    cg_name expr,               // - NULL or expression
    cg_type type )              // - type, when non-null
{
    if( expr != NULL ) {
        CgExprPush( expr, type );
    }
}
#endif


#if 0
static void push_reqd_expr(     // PUSH REQUIRED EXPRESSION ON STACK
    cg_name expr,               // - expression to be pushed
    cg_type type )              // - type
{
    if( expr == NULL ) {
        CgPushGarbage();
    } else {
        CgExprPush( expr, type );
    }
}
#endif


static TRY_IMPL* tryImpl(       // FIND/ALLOCATE A TRY IMPLEMENTATION
    SYMBOL sym )                // - try variable
{
#if _CPU == _AXP
    #define JMPBUF_SIZE ( 24 * TARGET_DOUBLE )
#elif _INTEL_CPU
    #define JMPBUF_SIZE ( 13 * TARGET_INT )
#else
    #error bad target
#endif
    TRY_IMPL* try_impl;         // - try implementation
    TRY_IMPL* curr;             // - current try implementation

    sym = SymTrans( sym );
    try_impl = NULL;
    RingIterBeg( fun_try_impls, curr ) {
        if( curr->try_sym == sym ) {
            try_impl = curr;
            break;
        }
    } RingIterEnd( curr )
    if( try_impl == NULL ) {
        try_impl = RingCarveAlloc( carveTRY_IMPL, &fun_try_impls );
        try_impl->try_sym = sym;
        AutoRelRegister( try_impl->try_sym, &try_impl->offset_var );
        try_impl->jmp_sym = CgVarRw( JMPBUF_SIZE, SC_AUTO );
        AutoRelRegister( try_impl->jmp_sym, &try_impl->offset_jmpbuf );
    }
    return try_impl;
}


static void freeTryImpls(       // FREE TRY IMPLEMENTATIONS
    void )
{
    RingCarveFree( carveTRY_IMPL, &fun_try_impls );
}


static SE* stateTableTryBlk(    // GET CURRENT STATE TABLE TRY BLOCK
    TRY_IMPL* try_impl )        // - try implementation
{
    SE* try_blk;                // - last try block
    SE* curr;                   // - current state entry

    try_blk = NULL;
    ST_backwards_beg( FstabActualPosn(), curr ) {
        if( ( curr->base.se_type == DTC_TRY )
          &&( curr->try_blk.try_impl == try_impl ) ) {
            try_blk = curr;
            break;
        }
    } ST_backwards_end
    DbgVerify( try_blk != NULL, "stateTableTryBlk -- none" );
    return try_blk;
}


static void undefine_string_const(  // UN-DEFINE A STRING CONSTANT
    STRING_CONSTANT str )           // - the constant
{
    if( str->cg_handle != NULL ) {
        BEFreeBack( (back_handle)str->cg_handle );
        str->cg_handle = NULL;
    }
}


static SYMBOL transThisSym(     // TRANSLATE TO "this_sym" WHEN NULL
    SYMBOL sym,                 // - input symbol
    FN_CTL *fctl )              // - current function control pointer
{
    if( sym == NULL
     && ! SymIsStatic( fctl->func ) ) {
        sym = fctl->this_sym;
    }
    return sym;
}


static void funcDebugInfo(      // DEFINE FUNCTION DEBUGGING INFORMATION
    FN_CTL *fctl )              // - current function control pointer
{
    if( fctl->debug_info && ( GenSwitches & DBG_LOCALS ) ){
        if( SymIsClassMember( fctl->func ) ) {
            SYMBOL this_sym;
            this_sym = transThisSym( NULL, fctl );
            if( GenSwitches & DBG_DF ){
                DwarfDebugMemberFunc( fctl->func, this_sym );
            }else{
                SymbolicDebugMemberFunc( fctl->func, this_sym );
            }
        }else if( SymIsNameSpaceMember( fctl->func ) ){
            if( GenSwitches & DBG_DF ){
                DwarfDebugNameSpaceEnclosed( fctl->func );
            }
        }
    }
}


#define flushOverInitialization( __fc ) \
        CgioReadICUntilOpcode( __fc, IC_INIT_DONE )


static SYMBOL finalAlias(       // CHECK FOR ANONYMOUS UNION ALIASING
    SYMBOL sym )                // - the symbol
{
    SYMBOL check;

    check = SymIsAnonymous( sym );
    if( check != NULL ) {
        sym = check;
    }
    return( sym );
}


static void cgDtorThisOffset(   // DESTRUCT (*this)+offset
    FN_CTL* fctl,               // - file information
    SYMBOL dtor,                // - DTOR to be used
    target_offset_t offset,     // - offset
    unsigned cdtor )            // - CDTOR value to be used
{
    SYMBOL this_sym;            // - symbol for "this"
    SYMBOL refd_sym;            // - symbol bound to "this"
    target_offset_t refd_off;   // - offset from "refd_sym"
    cg_name expr;               // - generated expression

    if( IbpReference( NULL, &this_sym, &refd_sym, &refd_off ) ) {
        CgDone( CgDestructSymOffset( fctl
                                   , dtor
                                   , refd_sym
                                   , offset + refd_off
                                   , cdtor )
              , T_POINTER );
    } else {
        expr = CgFetchSymbolAddOffset( this_sym, offset );
        expr = CgDestructExpr( dtor, expr, cdtor );
        CgExprPush( expr, T_POINTER );
        cgResetThis( offset );
        CgDone( CgExprPop(), T_POINTER );
    }
}


static void emitDtorComponent(  // EMIT CODE TO DESTRUCT COMPONENT
    FN_CTL* fctl,               // - file information
    SE* se,                     // - component entry
    unsigned cdtor )            // - CDTOR parameter
{
    if( ! fctl->ctor_complete ) {
        FstabSetDtorState( se, fctl );
        cgDtorThisOffset( fctl
                        , se->component.dtor
                        , se->component.offset

⌨️ 快捷键说明

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