cpragx86.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,054 行 · 第 1/3 页
C
1,054 行
/****************************************************************************
*
* 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: Pragmas specific to x86 targets.
*
****************************************************************************/
#include "cvars.h"
#include "cgswitch.h"
#include "pragdefn.h"
#include "pdefn2.h"
#include "asminlin.h"
#include "asmstmt.h"
extern struct aux_info *GetLangInfo( type_modifiers flags );
extern TREEPTR CurFuncNode;
static int AsmFuncNum;
static hw_reg_set AsmRegsSaved = HW_D( HW_FULL );
static struct aux_info AuxInfo;
#if _CPU == 386
static hw_reg_set STOSBParms[] = {
HW_D( HW_EAX ), HW_D( HW_EDX ), HW_D( HW_ECX ),
HW_D( HW_EMPTY )
};
#endif
static struct {
unsigned f_near : 1;
unsigned f_routine_pops : 1;
unsigned f_caller_return : 1;
unsigned f_8087_returns : 1;
} AuxInfoFlg;
void PragmaAuxInit( void )
/************************/
{
PragmaAuxInfoInit( CompFlags.use_stdcall_at_number );
#if _CPU == 386
HW_CTurnOff( AsmRegsSaved, HW_EAX );
HW_CTurnOff( AsmRegsSaved, HW_EBX );
HW_CTurnOff( AsmRegsSaved, HW_ECX );
HW_CTurnOff( AsmRegsSaved, HW_EDX );
HW_CTurnOff( AsmRegsSaved, HW_ESI );
HW_CTurnOff( AsmRegsSaved, HW_EDI );
#else
HW_CTurnOff( AsmRegsSaved, HW_ABCD );
HW_CTurnOff( AsmRegsSaved, HW_SI );
HW_CTurnOff( AsmRegsSaved, HW_DI );
HW_CTurnOff( AsmRegsSaved, HW_ES );
#endif
#if _CPU == 386
/* these are internal, and will never be pointed to by
an aux_entry, so we don't have to worry about them
or their fields being freed */
STOSBInfo = WatcallInfo;
STOSBInfo.cclass = NO_FLOAT_REG_RETURNS |
NO_STRUCT_REG_RETURNS |
SPECIAL_STRUCT_RETURN;
STOSBInfo.parms = STOSBParms;
STOSBInfo.objname = "*";
#endif
}
void PragmaInit( void )
/*********************/
{
int cpu;
int fpu;
int use32;
#if _CPU == 386
use32 = 1;
cpu = 3;
#else
use32 = 0;
cpu = 0;
#endif
AsmFuncNum = 0;
switch( GET_CPU( ProcRevision ) ) {
case CPU_86: cpu = 0; break;
case CPU_186: cpu = 1; break;
case CPU_286: cpu = 2; break;
case CPU_386: cpu = 3; break;
case CPU_486: cpu = 4; break;
case CPU_586: cpu = 5; break;
case CPU_686: cpu = 6; break;
}
switch( GET_FPU( ProcRevision ) ) {
case FPU_NONE: fpu = 0; break;
default: fpu = 1; break;
}
AsmInit( cpu, fpu, use32, 1 );
HeadLibs = NULL;
}
static void InitAuxInfo( void )
/*****************************/
{
CurrAlias = NULL;
CurrInfo = NULL;
CurrEntry = NULL;
memset( &AuxInfo, 0, sizeof( AuxInfo ) );
AuxInfoFlg.f_near = 0;
AuxInfoFlg.f_routine_pops = 0;
AuxInfoFlg.f_caller_return = 0;
AuxInfoFlg.f_8087_returns = 0;
}
static void CopyAuxInfo( void )
/*****************************/
{
hw_reg_set default_flt_n_seg;
hw_reg_set flt_n_seg;
if( CurrEntry == NULL ) {
// Redefining a built-in calling convention
} else {
CurrInfo = (struct aux_info *)CMemAlloc( sizeof( struct aux_info ) );
*CurrInfo = *CurrAlias;
}
if( AuxInfo.code != NULL ) {
CurrInfo->code = AuxInfo.code;
}
if( AuxInfoFlg.f_near ) {
CurrInfo->cclass &= ~FAR;
}
if( AuxInfoFlg.f_routine_pops ) {
CurrInfo->cclass &= ~CALLER_POPS;
}
if( AuxInfoFlg.f_caller_return ) {
CurrInfo->cclass &= ~ROUTINE_RETURN;
}
if( AuxInfoFlg.f_8087_returns ) {
CurrInfo->cclass &= ~NO_8087_RETURNS;
}
CurrInfo->cclass |= AuxInfo.cclass;
CurrInfo->flags |= AuxInfo.flags;
if( AuxInfo.objname != NULL )
CurrInfo->objname = AuxInfo.objname;
if( AuxInfo.cclass & SPECIAL_RETURN )
CurrInfo->returns = AuxInfo.returns;
if( AuxInfo.cclass & SPECIAL_STRUCT_RETURN )
CurrInfo->streturn = AuxInfo.streturn;
if( AuxInfo.parms != NULL )
CurrInfo->parms = AuxInfo.parms;
if( !HW_CEqual( AuxInfo.save, HW_EMPTY ) ) {
HW_CTurnOn( CurrInfo->save, HW_FULL );
if( !( AuxInfo.cclass & MODIFY_EXACT ) && !CompFlags.save_restore_segregs ) {
HW_Asgn( default_flt_n_seg, WatcallInfo.save );
HW_CAsgn( flt_n_seg, HW_FLTS );
HW_CTurnOn( flt_n_seg, HW_SEGS );
HW_TurnOff( CurrInfo->save, flt_n_seg );
HW_OnlyOn( default_flt_n_seg, flt_n_seg );
HW_TurnOn( CurrInfo->save, default_flt_n_seg );
}
HW_TurnOff( CurrInfo->save, AuxInfo.save );
}
}
static void AdvanceToken( void )
/******************************/
{
CMemFree( SavedId );
SavedId = NULL;
CurToken = LAToken;
}
static int GetAliasInfo( void )
/*****************************/
{
int isfar16;
if( CurToken != T_LEFT_PAREN ) // #pragma aux symbol .....
return( 1 );
NextToken();
if( CurToken != T_ID ) // error
return( 0 );
LookAhead();
if( LAToken == T_RIGHT_PAREN ) { // #pragma aux (alias) symbol .....
PragCurrAlias( SavedId );
AdvanceToken();
NextToken();
return( 1 );
} else if( LAToken == T_COMMA ) { // #pragma aux (symbol, alias)
HashValue = SavedHash;
SetCurrInfo( SavedId );
AdvanceToken();
NextToken();
if( CurToken != T_ID ) // error
return( 0 );
isfar16 = PragRecog( "far16" );
if( CurToken == T_ID ) {
PragCurrAlias( Buffer );
NextToken();
}
if( CurToken == T_RIGHT_PAREN )
NextToken();
if( isfar16 )
AuxInfo.flags |= AUX_FLAG_FAR16;
CopyAuxInfo();
PragEnding();
return( 0 ); /* process no more! */
} else { // error
AdvanceToken();
return( 0 ); // shut up the compiler
}
}
typedef enum {
FIXWORD_NONE,
FIXWORD_FLOAT,
FIXWORD_SEGMENT,
FIXWORD_OFFSET,
FIXWORD_RELOFF
} fix_words;
local fix_words FixupKeyword( void )
/**********************************/
{
if( CurToken == T_FLOAT ) {
NextToken(); /* 20-jun-92 */
return( FIXWORD_FLOAT );
}
if( PragRecog( "seg" ) ) return( FIXWORD_SEGMENT );
if( PragRecog( "offset" ) ) return( FIXWORD_OFFSET );
if( PragRecog( "reloff" ) ) return( FIXWORD_RELOFF );
return( FIXWORD_NONE );
}
enum sym_state AsmQueryExternal( char *name )
/*******************************************/
{
SYM_HANDLE sym_handle;
SYM_ENTRY sym;
sym_handle = SymLook( CalcHash( name, strlen( name ) ), name );
if( sym_handle == 0 )
return( SYM_UNDEFINED );
SymGet( &sym, sym_handle );
if( !(sym.flags & SYM_REFERENCED) ) {
sym.flags |= SYM_REFERENCED;
SymReplace( &sym, sym_handle );
}
switch( sym.stg_class ) {
case SC_AUTO:
case SC_REGISTER:
return( SYM_STACK );
}
return( SYM_EXTERNAL );
}
#if _CPU == 8086
#define SYM_INT SYM_INT2
#define SYM_FFAR SYM_FAR2
#define SYM_FNEAR SYM_NEAR2
#define SYM_DFAR SYM_INT4
#define SYM_DNEAR SYM_INT2
#else
#define SYM_INT SYM_INT4
#define SYM_FFAR SYM_FAR4
#define SYM_FNEAR SYM_NEAR2
#define SYM_DFAR SYM_INT6
#define SYM_DNEAR SYM_INT4
#endif
static int AsmCodePtrType( type_modifiers flags )
/***********************************************/
{
if( flags & FLAG_FAR ) {
return( SYM_FFAR );
} else if( flags & FLAG_NEAR ) {
return( SYM_FNEAR );
} else if( TargetSwitches & BIG_CODE ) {
return( SYM_FFAR );
} else {
return( SYM_FNEAR );
}
}
static int AsmPtrType( TYPEPTR typ, type_modifiers flags )
/********************************************************/
{
SKIP_TYPEDEFS( typ );
if( typ->decl_type == TYPE_FUNCTION ) {
return( AsmCodePtrType( flags ) );
} else if( flags & (FLAG_FAR|FLAG_HUGE) ) {
return( SYM_DFAR );
} else if( flags & FLAG_NEAR ) {
return( SYM_DNEAR );
} else if( TargetSwitches & BIG_DATA ) {
return( SYM_DFAR );
} else {
return( SYM_DNEAR );
}
}
/* matches enum DataType in ctypes.h */
static enum sym_type AsmDataType[TYPE_LAST_ENTRY] = {
SYM_INT1, /* TYPE_CHAR,*/
SYM_INT1, /* TYPE_UCHAR,*/
SYM_INT2, /* TYPE_SHORT,*/
SYM_INT2, /* TYPE_USHORT,*/
SYM_INT, /* TYPE_INT,*/
SYM_INT, /* TYPE_UINT,*/
SYM_INT4, /* TYPE_LONG,*/
SYM_INT4, /* TYPE_ULONG,*/
SYM_INT8, /* TYPE_LONG64,*/
SYM_INT8, /* TYPE_ULONG64,*/
SYM_FLOAT4, /* TYPE_FLOAT,*/
SYM_FLOAT8, /* TYPE_DOUBLE,*/
SYM_FLOAT10, /* TYPE_LONG_DOUBLE */
SYM_FLOAT4, /* TYPE_FIMAGINARY, */
SYM_FLOAT8, /* TYPE_DIMAGINARY, */
SYM_FLOAT10, /* TYPE_LDIMAGINARY, */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?