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

📄 cprag86.c

📁 Open Watcom 的 C 编译器源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/****************************************************************************
*
*                            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"

local   void    GetParmInfo( void );
local   void    GetRetInfo( void );
local   void    GetSTRetInfo( void );
local   void    GetSaveInfo( void );
local   int     GetByteSeq( void );

extern  TREEPTR     CurFuncNode;

static  int             AsmFuncNum;
static  hw_reg_set      AsmRegsSaved = { HW_D( HW_FULL ) };
static  hw_reg_set      StackParms[] = { HW_D( HW_EMPTY ) };
#if _CPU == 386
static  hw_reg_set      OptlinkParms[] = { HW_D( HW_FLTS ),HW_D( HW_EMPTY )};
#endif

void PragmaInit()
{
    call_class  call_type;
    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 );

    PragInit();

    HeadLibs = NULL;

    /* predefine "cdecl" and "pascal" pragmas  18-aug-90 */

    call_type = ( DefaultInfo.class & FAR );
    CdeclInfo.class =  call_type |
                       CALLER_POPS |
                       NO_FLOAT_REG_RETURNS |
                       NO_STRUCT_REG_RETURNS |
                       ROUTINE_RETURN |
#if _CPU == 8086
                       LOAD_DS_ON_CALL |
#endif
                       SPECIAL_STRUCT_RETURN;
    CdeclInfo.objname = CStrSave( "_*" );
    CdeclInfo.parms = (hw_reg_set *)CMemAlloc( sizeof( StackParms ) );
    memcpy( CdeclInfo.parms, StackParms, sizeof( StackParms ) );
    HW_CAsgn( CdeclInfo.returns, HW_EMPTY );

    PascalInfo.class = call_type |
                       REVERSE_PARMS |
                       NO_FLOAT_REG_RETURNS |
                       NO_STRUCT_REG_RETURNS |
/*                         ROUTINE_RETURN |             JFD Nov-15-91 */
                       SPECIAL_STRUCT_RETURN;
    PascalInfo.parms = (hw_reg_set *)CMemAlloc( sizeof( StackParms ) );
    memcpy( PascalInfo.parms, StackParms, sizeof( StackParms ) );
    PascalInfo.objname = CStrSave( "^" );
    HW_CAsgn( PascalInfo.returns, HW_EMPTY );

    FortranInfo.objname = CStrSave( "^" );

    StdcallInfo.class =  call_type |
                         // NO_FLOAT_REG_RETURNS | BBB - Jan-31-94
                         // NO_STRUCT_REG_RETURNS |
                         // ROUTINE_RETURN;
                         SPECIAL_STRUCT_RETURN;
    StdcallInfo.objname = CStrSave( "_*" );
    StdcallInfo.parms = (hw_reg_set *)CMemAlloc( sizeof( StackParms ) );
    memcpy( StdcallInfo.parms, StackParms, sizeof( StackParms ) );
    HW_CAsgn( StdcallInfo.returns, HW_EMPTY );

    OptlinkInfo.class =  call_type |
                         CALLER_POPS  |
#ifdef PARMS_STACK_RESERVE
                         PARMS_STACK_RESERVE |
#endif
                         NO_STRUCT_REG_RETURNS |
                         SPECIAL_STRUCT_RETURN;
    OptlinkInfo.objname = CStrSave( "*" );
#if _CPU == 386
    HW_CTurnOn( OptlinkParms[0], HW_EAX );
    HW_CTurnOn( OptlinkParms[0], HW_ECX );
    HW_CTurnOn( OptlinkParms[0], HW_EDX );
    OptlinkInfo.parms = (hw_reg_set *)CMemAlloc( sizeof( OptlinkParms ) );
    memcpy( OptlinkInfo.parms, OptlinkParms, sizeof( OptlinkParms ) );
#else
    OptlinkInfo.parms = (hw_reg_set *)CMemAlloc( sizeof( StackParms ) );
    memcpy( OptlinkInfo.parms, StackParms, sizeof( StackParms ) );
#endif
    HW_CAsgn( OptlinkInfo.returns, HW_FLTS );

    SyscallInfo.parms = (hw_reg_set *)CMemAlloc( sizeof( StackParms ) );
    memcpy( SyscallInfo.parms, StackParms, sizeof( StackParms ) );
    SyscallInfo.objname = CStrSave( "*" );
    SyscallInfo.class = CALLER_POPS |
                        NO_STRUCT_REG_RETURNS |
                        SPECIAL_STRUCT_RETURN;

#if _CPU == 386
    HW_CAsgn( CdeclInfo.streturn, HW_EAX );
    HW_CTurnOff( CdeclInfo.save, HW_EAX );
/*  HW_CTurnOff( CdeclInfo.save, HW_EBX ); AFS Nov-21-94 */
    HW_CTurnOff( CdeclInfo.save, HW_ECX );
    HW_CTurnOff( CdeclInfo.save, HW_EDX );

/*  HW_CAsgn( PascalInfo.streturn, HW_EAX ); JFD Nov-15-91 */
    HW_CTurnOff( PascalInfo.save, HW_EAX );
    HW_CTurnOff( PascalInfo.save, HW_EBX );
    HW_CTurnOff( PascalInfo.save, HW_ECX );
    HW_CTurnOff( PascalInfo.save, HW_EDX );

/*  HW_CAsgn( StdcallInfo.streturn, HW_EAX ); BBB Jan-31-94 */
    HW_CTurnOff( StdcallInfo.save, HW_EAX );
/*  HW_CTurnOff( StdcallInfo.save, HW_EBX );  CGE Jan-25-93 */
    HW_CTurnOff( StdcallInfo.save, HW_ECX );
    HW_CTurnOff( StdcallInfo.save, HW_EDX );

    HW_CTurnOff( SyscallInfo.save, HW_EAX );
    HW_CTurnOn ( SyscallInfo.save, HW_EBX );
    HW_CTurnOff( SyscallInfo.save, HW_ECX );
    HW_CTurnOff( SyscallInfo.save, HW_EDX );
    HW_CAsgn( SyscallInfo.streturn, HW_EMPTY );


    HW_CAsgn( OptlinkInfo.streturn, HW_EMPTY );
    HW_CTurnOff( OptlinkInfo.save, HW_EAX );
    HW_CTurnOff( OptlinkInfo.save, HW_ECX );
    HW_CTurnOff( OptlinkInfo.save, HW_EDX );

    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_CAsgn( CdeclInfo.streturn, HW_AX );
    HW_CTurnOff( CdeclInfo.save, HW_ABCD );
    HW_CTurnOff( CdeclInfo.save, HW_ES );

    HW_CTurnOff( PascalInfo.save, HW_ABCD );
    HW_CTurnOff( PascalInfo.save, HW_ES );

    HW_CAsgn( StdcallInfo.streturn, HW_AX );
    HW_CTurnOff( StdcallInfo.save, HW_ABCD );
    HW_CTurnOff( StdcallInfo.save, HW_ES );

    /* roughly like pascal */
    HW_CTurnOff( SyscallInfo.save, HW_ABCD );
    HW_CTurnOff( SyscallInfo.save, HW_ES );

    /* roughly like pascal */
    HW_CTurnOff( OptlinkInfo.save, HW_ABCD );
    HW_CTurnOff( OptlinkInfo.save, HW_ES );

    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 */

        static hw_reg_set STOSBParms[] = { HW_D( HW_EAX ),
                                           HW_D( HW_EDX ),
                                           HW_D( HW_ECX ),
                                           HW_D( HW_EMPTY ) };

        call_type = NO_FLOAT_REG_RETURNS | NO_STRUCT_REG_RETURNS
                  | SPECIAL_STRUCT_RETURN;

        STOSBInfo = DefaultInfo;
        STOSBInfo.class = call_type;
        STOSBInfo.parms = STOSBParms;
        STOSBInfo.objname = "*";


        /*
         * These are not freed when we shut down so we can't just point at the
         * CdeclInfo parms etc. Do not call FreeInfo on these. BBB
         */

        Far16CdeclInfo = CdeclInfo;
        Far16CdeclInfo.class |= FAR16_CALL;
        // __far16 __cdecl depends on EBX being trashed in __cdecl
        // but NT 386 __cdecl preserves EBX
        HW_CTurnOff( Far16CdeclInfo.save, HW_EBX );

        Far16PascalInfo = PascalInfo;
        Far16PascalInfo.class |= FAR16_CALL;

    #if 0
        Far16CdeclInfo = DefaultInfo;
        Far16CdeclInfo.class = call_type | ROUTINE_RETURN | FAR16_CALL;
        Far16CdeclInfo.objname = "_*";
        Far16CdeclInfo.parms = CdeclInfo.parms;         // BBB - March 23, 1994
        Far16CdeclInfo.save = CdeclInfo.save;           // BBB - March 23, 1994

        Far16PascalInfo = DefaultInfo;
        Far16PascalInfo.class = call_type | REVERSE_PARMS | FAR16_CALL;
        Far16PascalInfo.objname = "^";
        Far16PascalInfo.parms = PascalInfo.parms;       // BBB - March 23, 1994
        Far16PascalInfo.save = PascalInfo.save;         // BBB - March 23, 1994
    #endif
    }
    #endif
}


static int GetAliasInfo()
{
    int         isfar16;
    auto char   buff[256];

    CurrAlias = &DefaultInfo;
    if( CurToken != T_LEFT_PAREN ) return( 1 );
    NextToken();
    if( CurToken != T_ID ) return( 0 );
    PragCurrAlias();
    strcpy( buff, Buffer );
    NextToken();
    if( CurToken == T_RIGHT_PAREN ) {
        NextToken();
        return( 1 );
    } else if( CurToken == T_COMMA ) {
        NextToken();
        if( CurToken != T_ID ) return( 0 );
        isfar16 = PragRecog( "far16" );
        CreateAux( buff );
        PragCurrAlias();
        NextToken();
        if( CurToken == T_RIGHT_PAREN ) {
            *CurrInfo = *CurrAlias;
            NextToken();
        }
        if( isfar16 ) {
            CurrInfo->flags |= AUX_FLAG_FAR16;
        }
        PragEnding();
        return( 0 ); /* process no more! */
    } else {
        return( 0 ); // shut up the compiler
    }
}


void PragAux()
{
    struct {
        unsigned f_call   : 1;
        unsigned f_loadds : 1;
        unsigned f_export : 1;
        unsigned f_parm   : 1;
        unsigned f_value  : 1;
        unsigned f_modify : 1;
        unsigned f_frame  : 1;
        unsigned uses_auto: 1;
    } have;

    if( !GetAliasInfo() ) return;
    CurrEntry = NULL;
    if( CurToken != T_ID ) return;
    SetCurrInfo();
    NextToken();
    *CurrInfo = *CurrAlias;
    PragObjNameInfo();
    have.f_call   = 0;
    have.f_loadds = 0;
    have.f_export = 0;
    have.f_parm   = 0;
    have.f_value  = 0;
    have.f_modify = 0;
    have.f_frame = 0;
    have.uses_auto = 0; /* BBB - Jan 26, 1994 */
    for( ;; ) {
        if( !have.f_call && CurToken == T_EQUAL ) {
            have.uses_auto = GetByteSeq();
            have.f_call = 1;
        } else if( !have.f_call && PragRecog( "far" ) ) {
            CurrInfo->class |= FAR;
            have.f_call = 1;
        } else if( !have.f_call && PragRecog( "near" ) ) {
            CurrInfo->class &= ~FAR;
            have.f_call = 1;
        } else if( !have.f_loadds && PragRecog( "loadds" ) ) {
            CurrInfo->class |= LOAD_DS_ON_ENTRY;
            have.f_loadds = 1;
        } else if( !have.f_export && PragRecog( "export" ) ) {
            CurrInfo->class |= DLL_EXPORT;
            have.f_export = 1;
        } else if( !have.f_parm && PragRecog( "parm" ) ) {
            GetParmInfo();
            have.f_parm = 1;
        } else if( !have.f_value && PragRecog( "value" ) ) {
            GetRetInfo();
            have.f_value = 1;
        } else if( !have.f_value && PragRecog( "aborts" ) ) {
            CurrInfo->class |= SUICIDAL;
            have.f_value = 1;
        } else if( !have.f_modify && PragRecog( "modify" ) ) {
            GetSaveInfo();
            have.f_modify = 1;
        } else if( !have.f_frame && PragRecog( "frame" ) ) {
            CurrInfo->class |= GENERATE_STACK_FRAME;
            have.f_frame = 1;
        } else {
            break;
        }
    }
    if( have.uses_auto ) {
        /*
           We want to force the calling routine to set up a [E]BP frame
           for the use of this pragma. This is done by saying the pragma
           modifies the [E]SP register. A kludge, but it works.
        */
        HW_CTurnOff( CurrInfo->save, HW_SP );
    }
    PragEnding();
}

typedef enum {
        FIXWORD_NONE,
        FIXWORD_FLOAT,
        FIXWORD_SEGMENT,
        FIXWORD_OFFSET,
        FIXWORD_RELOFF
} fix_words;

local fix_words FixupKeyword()
{

⌨️ 快捷键说明

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