cgfront.c

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

C
938
字号
/****************************************************************************
*
*                            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 "plusplus.h"

#include <limits.h>

#include "errdefns.h"
#include "preproc.h"
#include "cgfront.h"
#include "memmgr.h"
#include "codegen.h"
#include "toggle.h"
#include "label.h"
#include "cgsegid.h"
#include "initdefs.h"
#include "pcheader.h"
#include "objmodel.h"
#include "stats.h"
#include "fnbody.h"
#include "tgtenv.h"
#ifndef NDEBUG
#include "pragdefn.h"
#endif

#define CS_LABEL_BLOCK  4       // number of CS labels to allocate at a time

static CGFILE *dataCGFILE;      // file for data
static CGFILE *codeCGFILE;      // file for code
static CGFILE **emitDataCGFILE; // points to dataCGFILE or codeCGFILE

static CGINTER ins_def_seg      // IC_DEF_SEG instruction
       = { 0, IC_DEF_SEG };
static CGINTER ins_init_beg     // IC_INIT_BEG instruction
       = { 0, IC_INIT_BEG };
static CGINTER ins_init_done    // IC_INIT_DONE instruction
       = { 0, IC_INIT_DONE };
static CGINTER ins_init_test    // IC_INIT_TEST instruction
       = { 0, IC_INIT_TEST };

static struct {                  // FLAGS FOR CGFRONT
    unsigned init_data_beg   :1; // - init-data-beg required
    unsigned init_data_end   :1; // - init-data-end required
} flags;

#ifndef NDEBUG
static void cgfront_debug(      // DEBUGGING ROUTINE
    char *str )                 // - prefix
{
    if( PragDbgToggle.dump_emit_ic ) {
        printf( "%s\n", str );
    }
}

#define dump_label( inst ) if( PragDbgToggle.dump_labels ) inst
#else
#define cgfront_debug( str )
#define dump_label( inst )
#endif


// function macros
#ifndef NDEBUG
static void cgWriteIC( CGFILE *f, CGINTER *i )
{
    CgioWriteIC( f, i );
}
#else
#define cgWriteIC( f, i )       CgioWriteIC( f, i );
#endif


SYMBOL CgFrontCurrentFunction(  // GET CURRENT FUNCTION BEING GENERATED
    void )
{
    SYMBOL curr;                // - current function

    if( codeCGFILE == NULL ) {
        curr = NULL;
    } else {
        curr = codeCGFILE->symbol;
    }
    return curr;
}


void CgFrontResumeFunction(     // RESUME A FUNCTION
    SYMBOL func )               // - function being resumed
{
    if( func != NULL ) {
        codeCGFILE = CgioLocateFile( func );
    }
}


static CGFILE_GEN *getGenData(  // GET PTR TO GENERATION DATA
    void )
{
    CGFILE *stat_file;          // - file for statistics

    if( codeCGFILE == NULL ) {
        stat_file = dataCGFILE;
    } else {
        stat_file = codeCGFILE;
    }
    return( stat_file->gen );
}


static void cgEmitData(         // EMIT AN INSTRUCTION TO DATA FILE
    CGINTER *instruction )      // - instruction to be emitted
{
    CGFILE *emit_file;          // - file for emit

    emit_file = *emitDataCGFILE;
    if( flags.init_data_beg ) {
        cgWriteIC( emit_file, &ins_init_beg );
        flags.init_data_beg = FALSE;
        flags.init_data_end = TRUE;
    }
    cgWriteIC( emit_file, instruction );
}


static void cgEmitIns(          // EMIT AN INSTRUCTION TO CODE FILE
    CGFILE_GEN *gen,            // - generation data
    CGINTER *instruction )      // - instruction to be emitted
{
    if( gen->emit_init_beg ) {
        ins_init_beg.value.pvalue = gen->init_sym;
        cgWriteIC( codeCGFILE, &ins_init_beg );
        gen->emit_init_beg = FALSE;
        gen->emit_init_end = TRUE;
    }
    cgWriteIC( codeCGFILE, instruction );
}


void CgFrontStatInit(           // START OF STATIC-INIT TEST IN FUNCTION
    void )
{
    CGFILE_GEN *gen;            // - generation data

    if( emitDataCGFILE == &codeCGFILE ) {
        gen = getGenData();
        ins_init_done.value.pvalue = gen->init_sym;
        cgWriteIC( codeCGFILE, &ins_init_done );
        ins_init_test.value.pvalue = gen->init_sym;
        cgWriteIC( codeCGFILE, &ins_init_test );
        flags.init_data_beg = FALSE;
        flags.init_data_end = TRUE;
    }
}


void CgFrontFuncInitFlags(      // GENERATE INIT FLAGS FOR FUNCTION
    SYMBOL var )                // - NULL OR FLAGS VARIABLE
{
    if( var != NULL ) {
        ins_init_beg.value.pvalue = var;
        ins_init_done.value.pvalue = var;
        CgSegIdData( var, SI_ALL_ZERO );
        cgWriteIC( codeCGFILE, &ins_init_beg );
        emitDataCGFILE = &codeCGFILE;
        DgSymbol( var );
        cgWriteIC( codeCGFILE, &ins_init_done );
        emitDataCGFILE = &dataCGFILE;
    }
}


static void cgEmitCodeUint(     // EMIT INSTRUCTION TO CODE FILE WITH UINT PARM
    CGFILE_GEN *gen,            // - generation data
    unsigned opcode,            // - opcode
    unsigned value )            // - value
{
    CGINTER ins;                // - instruction

    ins.opcode = opcode;
    ins.value.uvalue = value;
    cgEmitIns( gen, &ins );
}


static void cgEmitCodePtr(      // EMIT INSTRUCTION TO CODE FILE WITH PTR PARM
    CGFILE_GEN *gen,            // - generation data
    unsigned opcode,            // - opcode
    void *value )               // - value
{
    CGINTER ins;                // - instruction

    ins.opcode = opcode;
    ins.value.pvalue = value;
    cgEmitIns( gen, &ins );
}


static void emitSetType(        // GENERATE TYPE IF REQ'D
    CGFILE_GEN *gen )           // - generation data
{
    if( gen->curr_type != gen->emit_type && gen->curr_type != NULL ) {
        gen->emit_type = gen->curr_type;
        cgEmitCodePtr( gen, IC_SET_TYPE, gen->curr_type );
    }
}


void CgSetTypeExact(            // SET EXACT TYPE FOR GENERATION
    TYPE type )                 // - the type
{
    CGFILE_GEN *gen;            // - generation data

    gen = getGenData();
    gen->curr_type = type;
}


void CgFrontResultBoolean(      // SET RESULTANT TYPE TO BE BOOLEAN
    void )
{
    CGFILE_GEN *gen;            // - generation data

    gen = getGenData();
    gen->emit_type = GetBasicType( TYP_BOOL );
    gen->curr_type = gen->emit_type;
}


void CgSetType(                 // SET NORMAL TYPE FOR GENERATION
    TYPE type )                 // - the type
{
    if( OMR_CLASS_REF == ObjModelArgument( type ) ) {
        type = MakeReferenceTo( type );
    }
    CgSetTypeExact( type );
}


static void emitSourcePosn(     // GENERATE DEBUG POSITION IF REQ'D
    CGFILE_GEN *gen,            // - generation data
    TOKEN_LOCN *srcposn )       // - source position
{
    DbgAssert( srcposn != NULL );
    if( srcposn->src_file != NULL ) {
        if( gen->emit_line_no.src_file != srcposn->src_file ) {
            cgEmitCodePtr( gen, IC_DBG_SRCFILE, srcposn->src_file );
            cgEmitCodeUint( gen, IC_DBG_LINE, srcposn->line );
            gen->emit_line_no.src_file = srcposn->src_file;
            gen->emit_line_no.line = srcposn->line;
        } else if( gen->emit_line_no.line != srcposn->line ) {
            cgEmitCodeUint( gen, IC_DBG_LINE, srcposn->line );
            gen->emit_line_no.line = srcposn->line;
        }
    }
}


static void cgEmit(             // EMIT INSTRUCTION TO CODE FILE, IF REQUIRED
    CGFILE_GEN *gen,            // - generation data
    CGINTER *instruction )      // - instruction to be emitted
{
    emitSetType( gen );
    switch( instruction->opcode ) {
    case IC_INIT_DONE :
    case IC_FUNCTION_OPEN :
        gen->curr_type = NULL;
        break;
    }
    cgEmitIns( gen, instruction );
}


void CgFrontDbgLine(            // SET LINE FOR DEBUGGING
    TOKEN_LOCN* posn )          // - source file position
{
    CGFILE_GEN *gen;            // - generation data

    gen = getGenData();
    emitSourcePosn( gen, posn );
#ifndef NDEBUG
    if( PragDbgToggle.dump_tokens || PragDbgToggle.dump_emit_ic ) {
        printf( "CgFrontDbgLine: %d\n", posn->line );
    }
#endif
}


CGFILE_INS CgFrontLastIns(      // RETURN LOCATION OF LAST WRITTEN CODE IC
    void )
{
    return CgioLastWrite( codeCGFILE );
}


void CgFrontCode(               // EMIT TO CODE SEGMENT
    int opcode )                // - intermediate code
{
    CGINTER ins;                // - instruction

    ins.opcode = opcode;
    ins.value.ivalue = 0;
    cgEmit( getGenData(), &ins );
}


void CgFrontCodeInt(            // EMIT (code,int) TO CODE SEGMENT
    int opcode,                 // - opcode
    int value )                 // - value
{
    CGINTER ins;                // - instruction

    ins.opcode = opcode;
    ins.value.ivalue = value;
    cgEmit( getGenData(), &ins );
}


void CgFrontCodeUint(           // EMIT (code,unsigned) TO CODE SEGMENT
    int opcode,                 // - opcode
    unsigned value )            // - value
{
    CGINTER ins;                // - instruction

    ins.opcode = opcode;
    ins.value.uvalue = value;
    cgEmit( getGenData(), &ins );
}


void CgFrontCodePtr(            // EMIT (code,ptr) TO CODE SEGMENT
    int opcode,                 // - opcode
    void *value )               // - value
{
    CGINTER ins;                // - instruction

    ins.opcode = opcode;
    ins.value.pvalue = value;
    cgEmit( getGenData(), &ins );
}


void CgFrontData(               // EMIT TO DATA SEGMENT
    int opcode )                // - intermediate code
{
    CGINTER ins;                // - instruction

    ins.opcode = opcode;
    ins.value.ivalue = 0;
    cgEmitData( &ins );
}


void CgFrontDataInt(            // EMIT (code,int) TO DATA SEGMENT
    int opcode,                 // - opcode
    int value )                 // - value
{
    CGINTER ins;                // - instruction

    ins.opcode = opcode;
    ins.value.ivalue = value;
    cgEmitData( &ins );
}


void CgFrontDataUint(           // EMIT (code,unsigned) TO DATA SEGMENT
    int opcode,                 // - opcode
    unsigned value )            // - value
{
    CGINTER ins;                // - instruction

    ins.opcode = opcode;
    ins.value.uvalue = value;
    cgEmitData( &ins );
}


void CgFrontDataPtr(            // EMIT (code,ptr) TO DATA SEGMENT
    int opcode,                 // - opcode
    void *value )               // - value
{
    CGINTER ins;                // - instruction

    ins.opcode = opcode;
    ins.value.pvalue = value;
    cgEmitData( &ins );
}

static void cgSetupSegment(     // SET UP DATA SEGMENT, EMIT INSTRUCTION
    unsigned seg_number )       // - segment number
{
    if( seg_number != ins_def_seg.value.ivalue ) {
        ins_def_seg.value.uvalue = seg_number;
        cgEmitData( &ins_def_seg );
    }
}


void CgFrontFiniRef(            // EMIT TO FINI-REF SEGMENT
    void )
{
    cgSetupSegment( SEG_FINI_REF );
}


void CgFrontInitRef(            // EMIT TO INIT-REF SEGMENT
    void )
{
    cgSetupSegment( SEG_INIT_REF );
}


void CgFrontZapPtr(             // ZAP A WRITTEN RECORD (PTR OPERAND)
    CGFILE_INS location,        // - location to be zapped
    int opcode,                 // - opcode
    void *operand )             // - operand
{
    CGINTER ins;                // - instruction

    ins.opcode = opcode;
    ins.value.pvalue = operand;
    CgioRewriteRecord( location, &ins );
}


void CgFrontZapUint(            // ZAP A WRITTEN RECORD (UNSIGNED OPERAND)
    CGFILE_INS location,        // - location to be zapped
    int opcode,                 // - opcode
    unsigned operand )          // - operand
{
    CGINTER ins;                // - instruction

    ins.opcode = opcode;
    ins.value.uvalue = operand;
    CgioRewriteRecord( location, &ins );
}


void *CgFrontSwitchFile(        // SWITCH VIRTUAL FUNCTION FILES
    void *symbol )              // - symbol for opened file
{

⌨️ 快捷键说明

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