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 + -
显示快捷键?