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 + -
显示快捷键?