cpragx86.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,416 行 · 第 1/3 页

C
1,416
字号
/****************************************************************************
*
*                            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:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include "plusplus.h"
#include "preproc.h"
#include "name.h"
#include "memmgr.h"
#include "errdefns.h"
#include "cgdata.h"
#include "pragdefn.h"
#include "pdefn2.h"
#include "asminlin.h"
#include "fnovload.h"
#include "cgswitch.h"
#include "initdefs.h"
#include "cginlibs.h"
#include "cginimps.h"
#include "asmstmt.h"
#include "pcheader.h"


static int      GetAliasInfo();
static byte_seq *AuxCodeDup( byte_seq *code );
static int      GetByteSeq( void );

static  hw_reg_set      asmRegsSaved = { HW_D( HW_FULL ) };

#define WCPP_ASM     // enable assembler

static void pragmaInit(         // INITIALIZATION FOR PRAGMAS
    INITFINI* defn )            // - definition
{
    defn = defn;
    PragInit();

    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

    SetAuxDefaultInfo();
}


static void freeInfo( AUX_INFO *info )
{
    if( info->code != NULL ) {
        CMemFree( info->code );
        info->code = NULL;
    }
    if( !IsAuxParmsBuiltIn( info->parms ) ) {
        CMemFree( info->parms );
        info->parms = NULL;
    }
    if( info->objname != NULL ) {
        CMemFree( info->objname );
        info->objname = NULL;
    }
}


static void pragmaFini(         // FINISH PRAGMAS
    INITFINI* defn )            // - definition
{
    register struct aux_entry *next;
    register void             *junk;

    defn = defn;
    next = AuxList;
    while( next != NULL ) {
        junk = next;
        if( next->info != NULL ) {
            if( next->info->use != 1 ) {
                next->info->use--;
            } else {
                freeInfo( next->info );
#ifndef NDEBUG
                if( IsAuxInfoBuiltIn( next->info ) ) {
                    CFatal( "freeing a static calling convention info" );
                }
#endif
                if( !IsAuxInfoBuiltIn( next->info ) ) {
                    CMemFree( next->info );
                }
            }
        }
        next = next->next;
        CMemFree( junk );
    }
    freeInfo( &DefaultInfo );
    freeInfo( &CdeclInfo );
    freeInfo( &PascalInfo );
    freeInfo( &SyscallInfo );
    freeInfo( &OptlinkInfo );
    freeInfo( &StdcallInfo );
    freeInfo( &FastcallInfo );
#if _CPU == 386
    freeInfo( &Far16CdeclInfo );
    freeInfo( &Far16PascalInfo );
#endif
    freeInfo( &WatcallInfo );
    freeInfo( &FortranInfo );
    //CMemFreePtr( &FortranInfo.objname );
    AuxList = NULL;
    CgInfoFreeLibs();
    CgInfoFreeImports();
    CgInfoFreeImportsS();
}


INITDEFN( pragmas, pragmaInit, pragmaFini )


static void assemblerInit(      // INITIALIZATION OF ASSEMBLER
    INITFINI* defn )            // - definition
{
    int         cpu;
    int         fpu;
    int         use32;

    defn = defn;
#if _CPU == 386
    use32 = 1;
    cpu = 3;
#else
    use32 = 0;
    cpu = 0;
#endif
    switch( GET_CPU( CpuSwitches ) ) {
      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( CpuSwitches ) ) {
    case FPU_NONE:      fpu = 0; break;
    default:            fpu = 1; break;
    }
    AsmInit( cpu, fpu, use32, 1 );
}


INITDEFN( assembler, assemblerInit, InitFiniStub )


static void AuxCopy(           // COPY AUX STRUCTURE
    AUX_INFO *to,               // - destination
    AUX_INFO *from )            // - source
{
    freeAuxInfo( to );
    *to = *from;
    to->parms = AuxParmDup( from->parms );
    to->objname = AuxObjnameDup( from->objname );
    to->code = AuxCodeDup( from->code );
}

static boolean GetAliasInfo(
    void )
{
    char buff[256];
    boolean isfar16;
    boolean retn;

    CurrAlias = &DefaultInfo;
    if( CurToken != T_LEFT_PAREN ) {
        retn = TRUE;
    } else {
        NextToken();
        if( ! PragIdCurToken() ) {
            retn = FALSE;
        } else {
            PragCurrAlias();
            strcpy( buff, Buffer );
            NextToken();
            if( CurToken == T_RIGHT_PAREN ) {
                NextToken();
                retn = TRUE;
            } else if( CurToken == T_COMMA ) {
                NextToken();
                if( ! PragIdCurToken() ) {
                    retn = FALSE;
                } else {
                    isfar16 = PragRecog( "far16" );
                    CreateAux( buff );
                    PragCurrAlias();
                    NextToken();
                    if( CurToken == T_RIGHT_PAREN ) {
                        AuxCopy( CurrInfo, CurrAlias );
                        NextToken();
                    }
                    if( isfar16 ) {
                        CurrInfo->flags |= AUX_FLAG_FAR16;
                    }
                    PragEnding( TRUE );
                    retn = FALSE;
                }
            }
        }
    }
    return retn;
}

static void GetParmInfo(
    void )
    {
    struct {
        unsigned f_pop           : 1;
        unsigned f_reverse       : 1;
        unsigned f_loadds        : 1;
        unsigned f_nomemory      : 1;
        unsigned f_list          : 1;
    } have;

    have.f_pop           = 0;
    have.f_reverse       = 0;
    have.f_loadds        = 0;
    have.f_nomemory      = 0;
    have.f_list          = 0;
    for( ;; ) {
        if( !have.f_pop && PragRecog( "caller" ) ) {
            CurrInfo->cclass |= CALLER_POPS;
            have.f_pop = 1;
        } else if( !have.f_pop && PragRecog( "routine" ) ) {
            CurrInfo->cclass &= ~ CALLER_POPS;
            have.f_pop = 1;
        } else if( !have.f_reverse && PragRecog( "reverse" ) ) {
            CurrInfo->cclass |= REVERSE_PARMS;
            have.f_reverse = 1;
        } else if( !have.f_nomemory && PragRecog( "nomemory" ) ) {
            CurrInfo->cclass |= NO_MEMORY_READ;
            have.f_nomemory = 1;
        } else if( !have.f_loadds && PragRecog( "loadds" ) ) {
            CurrInfo->cclass |= LOAD_DS_ON_CALL;
            have.f_loadds = 1;
        } else if( !have.f_list && PragSet() != T_NULL ) {
            PragManyRegSets();
            have.f_list = 1;
        } else {
            break;
        }
    }
}

static void GetSTRetInfo(
    void )
{
    struct {
        unsigned f_float        : 1;
        unsigned f_struct       : 1;
        unsigned f_allocs       : 1;
        unsigned f_list         : 1;
    } have;

    have.f_float  = 0;
    have.f_struct = 0;
    have.f_allocs = 0;
    have.f_list   = 0;
    for( ;; ) {
        if( !have.f_float && PragRecog( "float" ) ) {
            have.f_float = 1;
            CurrInfo->cclass |= NO_FLOAT_REG_RETURNS;
        } else if( !have.f_struct && PragRecog( "struct" ) ) {
            have.f_struct = 1;
            CurrInfo->cclass |= NO_STRUCT_REG_RETURNS;
        } else if( !have.f_allocs && PragRecog( "routine" ) ) {
            have.f_allocs = 1;
            CurrInfo->cclass |= ROUTINE_RETURN;
        } else if( !have.f_allocs && PragRecog( "caller" ) ) {
            have.f_allocs = 1;
            CurrInfo->cclass &= ~ROUTINE_RETURN;
        } else if( !have.f_list && PragSet() != T_NULL ) {
            have.f_list = 1;
            CurrInfo->cclass |= SPECIAL_STRUCT_RETURN;
            CurrInfo->streturn = PragRegList();
        } else {
            break;
        }
    }
}

static void GetRetInfo(
    void )
{
    struct {
        unsigned f_no8087        : 1;
        unsigned f_list          : 1;
        unsigned f_struct        : 1;
    } have;

    have.f_no8087  = 0;
    have.f_list    = 0;
    have.f_struct  = 0;
    CurrInfo->cclass &= ~ NO_8087_RETURNS;
    for( ;; ) {
        if( !have.f_no8087 && PragRecog( "no8087" ) ) {
            have.f_no8087 = 1;
            HW_CTurnOff( CurrInfo->returns, HW_FLTS );
            CurrInfo->cclass |= NO_8087_RETURNS;
        } else if( !have.f_list && PragSet() != T_NULL ) {
            have.f_list = 1;
            CurrInfo->cclass |= SPECIAL_RETURN;
            CurrInfo->returns = PragRegList();
        } else if( !have.f_struct && PragRecog( "struct" ) ) {
            have.f_struct = 1;
            GetSTRetInfo();
        } else {
            break;
        }
    }
}

static void GetSaveInfo(
    void )
{
    hw_reg_set      modlist;
    hw_reg_set      default_flt_n_seg;
    hw_reg_set      flt_n_seg;

    struct {
        unsigned f_exact        : 1;
        unsigned f_nomemory     : 1;
        unsigned f_list         : 1;
    } have;

    have.f_exact    = 0;
    have.f_nomemory = 0;
    have.f_list     = 0;
    for( ;; ) {
        if( !have.f_exact && PragRecog( "exact" ) ) {
            CurrInfo->cclass |= MODIFY_EXACT;
            have.f_exact = 1;
        } else if( !have.f_nomemory && PragRecog( "nomemory" ) ) {
            CurrInfo->cclass |= NO_MEMORY_CHANGED;
            have.f_nomemory = 1;
        } else if( !have.f_list && PragSet() != T_NULL ) {
            modlist = PragRegList();
            have.f_list = 1;
        } else {
            break;
        }
    }
    if( have.f_list ) {
        HW_Asgn( default_flt_n_seg, DefaultInfo.save );
        HW_CTurnOn( CurrInfo->save, HW_FULL );
        if( !have.f_exact && !CompFlags.save_restore_segregs ) {
            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, modlist );
    }
}

static void doPragAux(                   // #PRAGMA AUX ...
    void )
{
    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( !PragIdCurToken() ) return;
    SetCurrInfo();
    NextToken();
    AuxCopy( 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;
    for( ;; ) {
        if( !have.f_call && CurToken == T_EQUAL ) {
            have.uses_auto = GetByteSeq();
            have.f_call = 1;
        } else if( !have.f_call && PragRecog( "far" ) ) {
            CurrInfo->cclass |= FAR;
            have.f_call = 1;
        } else if( !have.f_call && PragRecog( "near" ) ) {
            CurrInfo->cclass &= ~FAR;
            have.f_call = 1;
        } else if( !have.f_loadds && PragRecog( "loadds" ) ) {
            CurrInfo->cclass |= LOAD_DS_ON_ENTRY;
            have.f_loadds = 1;
        } else if( !have.f_export && PragRecog( "export" ) ) {
            CurrInfo->cclass |= 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->cclass |= 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->cclass |= GENERATE_STACK_FRAME;
            have.f_frame = 1;
        } else {
            break;
        }
    }
    if( have.uses_auto ) {
        AsmSysUsesAuto();
    }
    PragEnding( TRUE );
}

void PragAux(                   // #PRAGMA AUX ...
    void )
{
    PPState = PPS_EOL;

⌨️ 快捷键说明

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