cfeinfo.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,344 行 · 第 1/3 页
C
1,344 行
/****************************************************************************
*
* 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: Callback functions invoked from cg - communicate
* auxiliary information to the backend.
*
****************************************************************************/
#include "cvars.h"
#include <ctype.h>
#include "cg.h"
#include "cgswitch.h"
#include "pragdefn.h"
#include "pdefn2.h"
#include "iopath.h"
#include "compcfg.h"
#include <sys/stat.h>
#include "autodept.h"
#include "langenv.h"
#define BY_CLI
#include "feprotos.h"
#define TRUNC_SYMBOL_HASH_LEN 4
#define TRUNC_SYMBOL_LEN_WARN 120
static unsigned char VarFuncWeights[] = {
//a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y,z
0, 0,13, 0, 2, 1, 0, 0, 0, 0, 0,12, 0,14, 4,10, 0, 0, 6, 0, 0, 0, 0, 0, 0,0
};
static char *VarParmFuncs[] = {
/* functions with var parm lists */
"", // 0
"", // 1
"", // 2
"", // 3
"", // 4
"", // 5
"", // 6
"", // 7
"fscanf", // 8
"fprintf", // 9
"execle", // 10
"execlpe", // 11
"scanf", // 12
"sscanf", // 13
"sprintf", // 14
"spawnle", // 15
"spawnlpe", // 16
"printf", // 17
"execlp", // 18
"execl", // 19
"cscanf", // 20
"cprintf", // 21
"open", // 22
"spawnlp", // 23
"spawnl", // 24
"sopen", // 25
"", // 26
"", // 27
"", // 28
"", // 29
"", // 30
"", // 31
};
#ifdef __SEH__
#if _CPU == 386
hw_reg_set TryParms[] = {
HW_D( HW_EAX ),
HW_D( HW_EMPTY )
};
#else
hw_reg_set TryParms[] = {
HW_D( HW_EMPTY )
};
#endif
#endif
/*
// does the specified symbol take variable parameters? manual search.
*/
int VarParm( SYMPTR sym )
{
TYPEPTR *parm;
TYPEPTR typ;
TYPEPTR fn_typ;
if( sym == NULL )
return( 0 );
if( sym->flags & SYM_FUNCTION ) {
fn_typ = sym->sym_type;
SKIP_TYPEDEFS( fn_typ );
parm = fn_typ->u.fn.parms;
if( parm != NULL ) {
for( ; (typ = *parm); ++parm ) {
if( typ->decl_type == TYPE_DOT_DOT_DOT ) {
return( 1 );
}
}
}
}
return( 0 );
}
/*
// does the specified symbol take variable args? hash calc'ed
//
*/
int VarFunc( SYMPTR sym )
{
int hash;
int len;
char *p;
if( sym == NULL )
return( 0 );
if( sym->flags & SYM_FUNCTION ) {
p = sym->name;
len = strlen( p );
hash = (len + VarFuncWeights[ p[0] - 'a' ]
+ VarFuncWeights[ p[len-1] -'a' ]) & 31;
if( strcmp( p, VarParmFuncs[ hash ] ) == 0 )
return( 1 );
return( VarParm( sym ) );
}
return( 0 );
}
#if ( _CPU == 8086 ) || ( _CPU == 386 )
static struct inline_funcs *Flat( struct inline_funcs *ifunc )
{
#if _CPU == 386
extern byte_seq * FlatAlternates[];
byte_seq ** p;
if( TargetSwitches & FLAT_MODEL ) {
for( p = FlatAlternates; p[0] != NULL; p += 2 ) {
if( p[0] == ifunc->code ) {
ifunc->code = p[1];
return( ifunc );
}
}
}
#endif
return( ifunc );
}
struct inline_funcs *IF_Lookup( char *name )
{
struct inline_funcs *ifunc;
if( GET_FPU( ProcRevision ) > FPU_NONE ) {
ifunc = _8087_Functions;
while( ifunc->name ) {
if( strcmp( ifunc->name, name ) == 0 )
return( Flat( ifunc ) );
++ifunc;
}
}
if( OptSize == 100 ) { /* if /os specified */
ifunc = SInline_Functions;
if( TargetSwitches & BIG_DATA ) {
#if _CPU == 8086
if( TargetSwitches & FLOATING_DS ) {
ifunc = ZF_Data_Functions;
} else {
ifunc = ZP_Data_Functions;
}
#else
ifunc = SBigData_Functions;
#endif
}
while( ifunc->name ) {
if( strcmp( ifunc->name, name ) == 0 )
return( Flat( ifunc ) );
++ifunc;
}
}
#if _CPU == 386
if( TargetSwitches & FLAT_MODEL ) {
ifunc = Flat_Functions;
while( ifunc->name ) {
if( strcmp( ifunc->name, name ) == 0 )
return( ifunc );
++ifunc;
}
}
#endif
ifunc = Inline_Functions;
if( TargetSwitches & BIG_DATA ) {
#if _CPU == 8086
if( TargetSwitches & FLOATING_DS ) {
ifunc = DF_Data_Functions;
} else {
ifunc = DP_Data_Functions;
}
#else
ifunc = BigData_Functions;
#endif
}
while( ifunc->name ) {
if( strcmp( ifunc->name, name ) == 0 )
return( Flat( ifunc ) );
++ifunc;
}
ifunc = Common_Functions;
while( ifunc->name ) {
if( strcmp( ifunc->name, name ) == 0 )
return( Flat( ifunc ) );
++ifunc;
}
return( NULL );
}
#endif
struct aux_info *GetLangInfo( type_modifiers flags )
{
switch( flags & FLAG_LANGUAGES ) {
case LANG_WATCALL:
return( &WatcallInfo );
case LANG_CDECL:
return( &CdeclInfo );
case LANG_PASCAL:
return( &PascalInfo );
case LANG_FORTRAN:
return( &FortranInfo );
case LANG_SYSCALL:
return( &SyscallInfo );
case LANG_STDCALL:
return( &StdcallInfo );
case LANG_FASTCALL:
return( &FastcallInfo );
case LANG_OPTLINK:
return( &OptlinkInfo );
default:
return( &DefaultInfo );
}
}
/*
// return language specific info
*/
static struct aux_info *LangInfo( type_modifiers flags, struct aux_info *inf )
{
if( inf != &DefaultInfo )
return( inf );
return( GetLangInfo( flags ) );
}
int ParmsToBeReversed( int flags, struct aux_info *inf )
{
#ifdef REVERSE
inf = LangInfo( flags, inf );
if( inf != NULL ) {
if( inf->cclass & REVERSE_PARMS ) {
return( 1 );
}
}
#else
flags = flags;
inf = inf;
#endif
return( 0 );
}
struct aux_info *InfoLookup( SYMPTR sym )
{
char *name;
struct aux_info *inf;
struct aux_entry *ent;
name = sym->name;
inf = &DefaultInfo; /* assume default */
if( name == NULL )
return( inf ); /* 01-jun-90 */
ent = AuxLookup( name );
if( ent != NULL )
inf = ent->info;
if( ( ent == NULL ) || (sym->flags & SYM_INTRINSIC) ) {
if( sym->flags & SYM_DEFINED )
return( inf );
if( !(sym->flags & SYM_INTRINSIC) ) {
if( memcmp( name, "_inline_", 8 ) != 0 )
return( inf );
name += 8;
}
#if ( _CPU == 8086 ) || ( _CPU == 386 )
{
struct inline_funcs *ifunc;
ifunc = IF_Lookup( name );
if( ifunc == NULL )
return( inf );
#if ( _CPU == 8086 )
if( HW_CEqual( ifunc->returns, HW_DX_AX )
|| HW_CEqual( ifunc->returns, HW_DS_SI )
|| HW_CEqual( ifunc->returns, HW_ES_DI )
|| HW_CEqual( ifunc->returns, HW_CX_DI ) ) {
if( SizeOfArg( sym->sym_type->object ) != 4 ) {
#else
if( HW_CEqual( ifunc->returns, HW_DX_AX )
|| HW_CEqual( ifunc->returns, HW_DS_ESI )
|| HW_CEqual( ifunc->returns, HW_ES_EDI )
|| HW_CEqual( ifunc->returns, HW_CX_DI ) ) {
if( SizeOfArg( sym->sym_type->object ) != 6 ) {
#endif
return( inf );
}
}
inf = &InlineInfo;
inf->cclass = (WatcallInfo.cclass & FAR) | MODIFY_EXACT;
if( (sym->flags & SYM_INTRINSIC) && ( ent != NULL ) )
inf->cclass |= ent->info->cclass;
inf->code = ifunc->code;
inf->parms = ifunc->parms;
inf->returns = ifunc->returns;
#if ( _CPU == 8086 )
if( !HW_CEqual( inf->returns, HW_AX )
&& !HW_CEqual( inf->returns, HW_EMPTY ) ) {
#else
if( !HW_CEqual( inf->returns, HW_EAX )
&& !HW_CEqual( inf->returns, HW_EMPTY ) ) {
#endif
inf->cclass |= SPECIAL_RETURN;
}
HW_CAsgn( inf->streturn, HW_EMPTY );
inf->save = ifunc->save;
inf->objname = WatcallInfo.objname; /* 26-jan-93 */
inf->use = 1;
}
#endif
}
return( inf );
}
struct aux_info *FindInfo( SYM_ENTRY *sym, SYM_HANDLE sym_handle )
{
SYM_ENTRY sym_typedef;
struct aux_entry *ent;
TYPEPTR typ;
struct aux_info *inf;
inf = &DefaultInfo; /* assume default */
if( sym_handle == 0 )
return( inf );
SymGet( sym, sym_handle );
#if _CPU == 386
if( (sym_handle == SymSTOSB) || (sym_handle == SymSTOSD) ) {
return( &STOSBInfo );
} else if( sym_handle == SymFinally ) {
static byte_seq FinallyCode = { 1, { 0xc3 } }; /* ret */
InlineInfo = WatcallInfo;
InlineInfo.code = &FinallyCode;
return( &InlineInfo );
} else if( sym_handle == SymTryFini ) {
static hw_reg_set TryFiniParms[] = {
HW_D( HW_EAX ),
HW_D( HW_EMPTY )
};
static byte_seq TryFiniCode = {
6, { 0x64, 0xA3, 0, 0, 0, 0 }
}; /* mov fs:[0],eax */
InlineInfo = WatcallInfo;
InlineInfo.parms = TryFiniParms;
InlineInfo.code = &TryFiniCode;
return( &InlineInfo );
}
#endif
if( !(sym->flags & SYM_TEMP) ) {
/* not an indirect func call*/
inf = InfoLookup( sym );
}
if( inf == &DefaultInfo ) {
typ = SkipDummyTypedef( sym->sym_type );
if( typ->decl_type == TYPE_TYPEDEF ) {
SymGet( &sym_typedef, typ->u.typedefn );
if( sym_typedef.name != NULL ) {
ent = AuxLookup( sym_typedef.name );
if( ent != NULL ) {
inf = ent->info;
}
}
}
}
#if _CPU == 386
if( ( inf->flags & AUX_FLAG_FAR16 )
|| ( sym->attrib & FLAG_FAR16 ) ) {
if( ( (sym->attrib & FLAG_LANGUAGES) == LANG_PASCAL )
|| ( inf->cclass & REVERSE_PARMS ) ) {
return( &Far16PascalInfo );
} else {
return( &Far16CdeclInfo );
}
}
#endif
return( inf );
}
int FunctionAborts( SYM_ENTRY *sym, SYM_HANDLE sym_handle ) /* 09-apr-93 */
{
struct aux_entry *ent;
if( sym_handle != 0 ) { /* 19-apr-93 */
SymGet( sym, sym_handle );
ent = AuxLookup( SymName( sym, sym_handle ) );
if( ent != NULL ) {
if( ent->info->cclass & SUICIDAL ) {
return( 1 );
}
}
}
return( 0 );
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?