cgen.c

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

C
2,041
字号
/****************************************************************************
*
*                            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:  Interface to Optimizing code generator.
*
****************************************************************************/


#include "cvars.h"
#include "cg.h"
#include "cgdefs.h"
#include "cgswitch.h"
#include "pragdefn.h"
#include "cgdllcli.h"
#define BY_CLI
#include "cgprotos.h"
#include "feprotos.h"

local void      FreeExtVars( void );
local void      FreeGblVars( SYM_HANDLE sym_handle );
local void      FreeLocalVars( SYM_HANDLE sym_list );
static void     FreeTrySymBackInfo( void );
static void     FreeTryTableBackHandles( void );
static void     FreeTrySymBackInfo( void );
local int       CodePtrType( type_modifiers flags );
local int       DoFuncDefn( SYM_HANDLE funcsym_handle );
static void     CallTryFini( void );
local void      EmitSyms( void );
local void      Emit1String( STR_HANDLE str_handle );
local void      EmitLiteral( STR_HANDLE strlit );
local void      EmitCS_Strings( void );
local void      FreeStrings( void );
local void      CDoAutoDecl( SYM_HANDLE sym_handle );
local void      CDoParmDecl( SYMPTR sym, SYM_HANDLE sym_handle );
local void      ParmReverse( SYM_HANDLE sym_handle );
#ifdef __SEH__
static void     GenerateTryBlock( TREEPTR tree );
#endif

static  struct  local_vars {
    struct local_vars       *next;
    SYM_HANDLE              sym_list;
} *LocalVarList;

extern  SYM_LISTS       *SymListHeads;

#ifdef __SEH__
#include "tryblock.h"

static  int             TryRefno;

static struct  try_table_back_handles {
    struct try_table_back_handles   *next;
    back_handle                     try_table_back_handle;
} *TryTableBackHandles;
#endif

#define PushCGName(name)        cgnames[index++] = name
#define PopCGName()             cgnames[--index]

static label_handle     *CGLabelHandles;
static TREEPTR          FirstNode;
static TREEPTR          LastNode;
static OPNODE           *FuncNodePtr;
static int              Refno;
static temp_handle      SSVar;
static SYM_HANDLE       Saved_CurFunc;

extern  int             LabelIndex;
static  int             InLineDepth;

struct func_save {
    SYMPTR          func;
    SYM_HANDLE      func_handle;
    OPNODE          *funcnode;
    label_handle    *cglabel_handles;
    int             labelindex;
};

/* matches table of type in ctypes.h */
static  char    CGDataType[TYPE_LAST_ENTRY] = {
    T_INT_1,        /* TYPE_CHAR */
    T_UINT_1,       /* TYPE_UCHAR */
    T_INT_2,        /* TYPE_SHORT */
    T_UINT_2,       /* TYPE_USHORT */
    T_INTEGER,      /* TYPE_INT */
    TY_UNSIGNED,    /* TYPE_UINT */
    T_INT_4,        /* TYPE_LONG */
    T_UINT_4,       /* TYPE_ULONG */
    T_INT_8,        /* TYPE_LONG64*/
    T_UINT_8,       /* TYPE_ULONG64 */
    T_SINGLE,       /* TYPE_FLOAT */
    TY_DOUBLE,      /* TYPE_DOUBLE */
    T_LONG_DOUBLE,  /* TYPE_LONG_DOUBLE */
    T_FLOAT,        /* TYPE_FIMAGINARY */
    T_DOUBLE,       /* TYPE_DIMAGINARY */
    T_LONG_DOUBLE,  /* TYPE_LDIMAGINARY */
    T_UINT_1,       /* TYPE_BOOL */
    T_POINTER,      /* TYPE_POINTER */
    T_POINTER,      /* TYPE_ARRAY */
    T_POINTER,      /* TYPE_STRUCT */
    T_POINTER,      /* TYPE_UNION */
    TY_DEFAULT,     /* TYPE_FUNCTION */
    TY_DEFAULT,     /* TYPE_FIELD */
    T_INTEGER,      /* TYPE_VOID */
    T_INTEGER,      /* TYPE_ENUM */
    T_INTEGER,      /* TYPE_TYPEDEF */
    T_INTEGER,      /* TYPE_UFIELD unsigned bit field */
    T_INTEGER,      /* TYPE_DOT_DOT_DOT  for the ... in prototypes */
    T_INTEGER,      /* TYPE_PLAIN_CHAR */
    T_INTEGER,      /* TYPE_WCHAR L'c' - a wide character constant */
    T_POINTER,      /* TYPE_FCOMPLEX */
    T_POINTER,      /* TYPE_DCOMPLEX */
    T_POINTER,      /* TYPE_LDCOMPLEX */
};

static  char    CGOperator[] = {
    O_PLUS,         //      OPR_ADD,        // +
    O_MINUS,        //      OPR_SUB,        // -
    O_TIMES,        //      OPR_MUL,        // *
    O_DIV,          //      OPR_DIV,        // /
    O_UMINUS,       //      OPR_NEG,        // negate
    0,              //      OPR_CMP,        // compare
    O_MOD,          //      OPR_MOD,        // %
    O_COMPLEMENT,   //      OPR_COM,        // ~
    O_FLOW_NOT,     //      OPR_NOT,        // !
    O_OR,           //      OPR_OR,         // |
    O_AND,          //      OPR_AND,        // &
    O_XOR,          //      OPR_XOR,        // ^
    O_RSHIFT,       //      OPR_RSHIFT,     // >>
    O_LSHIFT,       //      OPR_LSHIFT,     // <<
    O_GETS,         //      OPR_EQUALS,     // lvalue = rvalue
    O_OR,           //      OPR_OR_EQUAL,   // |=
    O_AND,          //      OPR_AND_EQUAL,  // &=
    O_XOR,          //      OPR_XOR_EQUAL,  // ^=
    O_RSHIFT,       //      OPR_RSHIFT_EQUAL,// >>=
    O_LSHIFT,       //      OPR_LSHIFT_EQUAL,// <<=
    O_PLUS,         //      OPR_PLUS_EQUAL, // +=
    O_MINUS,        //      OPR_MINUS_EQUAL,// -=
    O_TIMES,        //      OPR_TIMES_EQUAL,// *=
    O_DIV,          //      OPR_DIV_EQUAL,  // /=
    O_MOD,          //      OPR_MOD_EQUAL,  // %=
    0,              //      OPR_QUESTION,   // ?
    0,              //      OPR_COLON,      // :
    O_FLOW_OR,      //      OPR_OR_OR,      // ||
    O_FLOW_AND,     //      OPR_AND_AND,    // &&
    O_POINTS,       //      OPR_POINTS,     // *ptr
    0,              //      OPR_UNUSED1,    // spare
    0,              //      OPR_UNUSED2,    // spare
    O_PLUS,         //      OPR_POSTINC,    // lvalue++
    O_MINUS,        //      OPR_POSTDEC,    // lvalue--
    O_CONVERT,      //      OPR_CONVERT,    // do conversion
};

static  char    CC2CGOp[] = { O_EQ, O_NE, O_LT, O_LE, O_GT, O_GE };

#ifdef HEAP_SIZE_STAT

#include <malloc.h>

struct heap_stat {
    int     free;
    int     used;
};

static int heap_size( struct heap_stat *stat )
{
    struct _heapinfo    h_info;
    int                 heap_status;

    h_info._pentry = NULL;
    stat->free = 0;
    stat->used = 0;
    for( ;; ) {
        heap_status = _heapwalk( &h_info );
        if( heap_status != _HEAPOK ) break;
        if( h_info._useflag ) {
            stat->used += h_info._size;
        } else {
            stat->free += h_info._size;
        }
    }
    return( heap_status );
}
#endif

static void StartFunction( OPNODE *node )
{
    FuncNodePtr = node;
    if( InLineDepth == 0 ) {
        LocalVarList = NULL;
    }

    FuncNodePtr->func.flags |=  FUNC_INUSE;
    DoFuncDefn( node->func.sym_handle );
}

static void DefineLabels( OPNODE *node )
{
    int         i;

    LabelIndex = node->label_count;
    if( LabelIndex != 0 ) {
        CGLabelHandles = (label_handle *)CMemAlloc( (LabelIndex + 1) *
                                                sizeof(label_handle) );
        for( i = 1; i <= LabelIndex; i++ ) {
            CGLabelHandles[i] = BENewLabel();
        }
    }
}

static struct local_vars *ReleaseVars( SYM_HANDLE sym_list,
                                struct local_vars *local_var_list )
{
    struct local_vars *local_entry;

    local_entry = (struct local_vars *)
                    CMemAlloc( sizeof( struct local_vars ) );
    local_entry->next = local_var_list;
    local_entry->sym_list = sym_list;
    return( local_entry );
}

static void RelLocalVars( struct local_vars *local_var_list ) /* 12-mar-92 */
{
    struct local_vars   *local_entry;

    while( local_var_list != NULL ) {
        FreeLocalVars( local_var_list->sym_list );
        local_entry = local_var_list;
        local_var_list = local_var_list->next;
        CMemFree( local_entry );
    }
}

static cg_type ReturnType( cg_type type )
{
    if( CompFlags.returns_promoted && (InLineDepth == 0) ) {
        type = FEParmType( NULL, NULL, type );
    }
    return( type );
}

static void EndFunction( OPNODE *node )
{
    int         i;
    cg_name     name;
    cg_type     dtype;
    SYM_ENTRY   sym;

    if( LabelIndex != 0 ) {
        for( i = 1; i <= LabelIndex; i++ ) {
            BEFiniLabel( CGLabelHandles[i] );
        }
        CMemFree( CGLabelHandles );     // free labels for the function
        CGLabelHandles = NULL;
    }
#ifdef __SEH__
    if( FuncNodePtr->func.flags & FUNC_USES_SEH ) {
        CallTryFini();          // generate call to __TryFini
        FreeTrySymBackInfo();
    }
#endif
    if( node->sym_handle == 0 ) {
        dtype = CGenType( CurFunc->sym_type->object );
        CGReturn( NULL, dtype );
    } else {                            // return value
        SymGet( &sym, node->sym_handle );
        dtype = CGenType( sym.sym_type );
        name = CGTempName( sym.info.return_var, dtype );
        name = CGUnary( O_POINTS, name, dtype );
        CGReturn( name, ReturnType( dtype ) );
    }
    FreeLocalVars( CurFunc->u.func.parms );
    FreeLocalVars( CurFunc->u.func.locals );
    if( InLineDepth == 0 ) {
        RelLocalVars( LocalVarList );
    }
    if( GenSwitches & DBG_LOCALS ) {
        if( InLineDepth != 0 ) {
            DBEndBlock();
        }
    }
    FuncNodePtr->func.flags &= ~FUNC_INUSE;
}

static void ReturnExpression( OPNODE *node, cg_name expr )
{
    cg_name     name;
    cg_type     dtype;
    SYM_ENTRY   sym;

    SymGet( &sym, node->sym_handle );
    dtype = CGenType( sym.sym_type );
    name = CGTempName( sym.info.return_var, dtype );
    CGDone( CGAssign( name, expr, dtype ) );
}

static cg_type DataPointerType( OPNODE *node )
{
#if ( _CPU == 8086 ) || ( _CPU == 386 )
    cg_type     dtype;

    if( Far16Pointer( node->flags ) ) {
        dtype = T_POINTER;
    } else if( node->flags & OPFLAG_NEARPTR ) {
        dtype = T_NEAR_POINTER;
    } else if( node->flags & OPFLAG_FARPTR ) {
        dtype = T_LONG_POINTER;
    } else if( node->flags & OPFLAG_HUGEPTR ) {
        dtype = T_HUGE_POINTER;
    } else {
        dtype = T_POINTER;
    }
    return( dtype );
#else
    node;
    return( T_POINTER );
#endif
}


local cg_name ForceVolatileFloat( cg_name name, TYPEPTR typ ) /* 05-sep-92 */
{
    if( CompFlags.op_switch_used ) {
        if( typ->decl_type == TYPE_FLOAT  ||
            typ->decl_type == TYPE_DOUBLE ) {
            name = CGVolatile( name );
        }
    }
    return( name );
}


static cg_name PushSymSeg( OPNODE *node )
{
    cg_name     segname;
    SYMPTR      sym;
    SYM_HANDLE  sym_handle;

    sym_handle = node->sym_handle;
    if( sym_handle == 0 ) {         /* 30-nov-91 */
        segname = CGInteger( 0, TY_UNSIGNED );
    } else {
        if( sym_handle == Sym_CS ) { /* 23-jan-92 */
            segname = CGFEName(  CurFuncHandle, T_LONG_CODE_PTR );
        } else if( sym_handle == Sym_SS ) { /* 13-dec-92 */
            if( SSVar == NULL ) {
                SSVar = CGTemp( T_UINT_2 );
            }
            segname = CGTempName( SSVar, T_UINT_2 );
        } else {
            sym = SymGetPtr( sym_handle );
            segname = CGFEName( sym_handle, T_UINT_2 );
        }
    }
    return( segname );
}

#ifdef __SEH__
static cg_name TryFieldAddr( unsigned offset )
{
    cg_name     name;

    name = CGFEName( TrySymHandle, TryRefno );
    name = CGBinary( O_PLUS,
                     name,
                     CGInteger( offset, TY_UNSIGNED ),
                     T_POINTER );
    name = CGVolatile( name );
    return( name );
}

static cg_name TryExceptionInfoAddr( void )
{
    cg_name     name;

    name = TryFieldAddr( offsetof( struct try_block, exception_info ) );
//    name = CGUnary( O_POINTS, name, T_POINTER );
//    name = CGUnary( O_POINTS, name, T_POINTER );
    return( name );
}

static void SetTryTable( back_handle except_table )
{
    cg_name     name;

⌨️ 快捷键说明

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