📄 cgen2.c
字号:
/****************************************************************************
*
* 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 + -