⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cgen2.c

📁 Open Watcom 的 C 编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/****************************************************************************
*
*                            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 "standard.h"
#include "cgprotos.h"
#include "cgdllcli.h"
#include <stdarg.h>
#include <malloc.h>

extern  void    InitExpressCode(int,int);
    extern      void    GenNewProc(cg_sym_handle);
extern  TREEPTR GenExpressCode(TREEPTR,int,TREEPTR);
extern  void    EmptyQueue(void);
extern  int     StartWCG();

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 );
extern int      PtrType( TYPEPTR typ, int flags );
local int       CodePtrType( int 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      DoAutoDecl( SYM_HANDLE sym_handle );
local void      DoParmDecl( 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[] = {
        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_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 */
/*
  I can't see how these were ever generated.  They're also not
  in the same order as the table in ctypes.h, which is very important.
*/
#if 0
        T_INTEGER,      /* TYPE_UNUSED (a unref'd function) */
        T_INTEGER,      /* TYPE_WCHAR L'c' - a wide character constant */
        T_POINTER,      /* TYPE_REF C++ reference */
        T_INTEGER       /* TYPE_CLASS  C++ class */
#endif
        T_INTEGER,      /* TYPE_WCHAR L'c' - a wide character constant */
        T_LONG_DOUBLE,  /* TYPE_LONG_DOUBLE */
        T_POINTER,      /* TYPE_FCOMPLEX */
        T_POINTER,      /* TYPE_DCOMPLEX */
        T_POINTER,      /* TYPE_LDCOMPLEX */
        T_FLOAT,        /* TYPE_FIMAGINARY */
        T_DOUBLE,       /* TYPE_DIMAGINARY */
        T_LONG_DOUBLE,  /* TYPE_LDIMAGINARY */
        T_UINT_1,       /* TYPE_BOOL */
        T_INTEGER,      /* TYPE_UNUSED */
  };

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
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 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 );
        if( CompFlags. returns_promoted ) {
            dtype = FEParmType( NULL, NULL, dtype );
        }
        CGReturn( name, 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 _MACHINE == _PC
    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 );
}

⌨️ 快捷键说明

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