fccall.c

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

C
999
字号
/****************************************************************************
*
*                            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:  F-Code processor for subroutine calls.
*
****************************************************************************/


#include "ftnstd.h"
#include "global.h"
#include "wf77defs.h"
#include "wf77aux.h"
#include "wf77cg.h"
#include "tmpdefs.h"
#include "cpopt.h"
#include "fcgbls.h"
#include "iflookup.h"
#include "rtconst.h"
#include "prmcodes.h"
#include "fmemmgr.h"
#include "emitobj.h"
#include "fctypes.h"

//=================== Back End Code Generation Routines ====================

extern  void            CGProcDecl(pointer,cg_type);
extern  void            CGReturn(cg_name,cg_type);
extern  cg_name         CGUnary(cg_op,cg_name,cg_type);
extern  cg_name         CGBinary(cg_op,cg_name,cg_name,cg_type);
extern  cg_name         CGAssign(cg_name,cg_name,cg_type);
extern  cg_name         CGLVAssign(cg_name,cg_name,cg_type);
extern  cg_name         CGIndex(cg_name,cg_name,cg_type,cg_type);
extern  cg_name         CGInteger(signed_32,cg_type);
extern  cg_name         CGFEName(sym_handle,cg_type);
extern  cg_name         CGBackName(back_handle,cg_type);
extern  call_handle     CGInitCall(cg_name,cg_type,sym_handle);
extern  void            CGAddParm(call_handle,cg_name,cg_type);
extern  cg_name         CGCall(call_handle);
extern  cg_name         CGEval(cg_name);
extern  sel_handle      CGSelInit( void );
extern  void            CGSelCase(sel_handle,label_handle,signed_32);
extern  void            CGSelOther(sel_handle,label_handle);
extern  void            CGControl(cg_op,cg_name,label_handle);
extern  void            CGSelect(sel_handle,cg_name);
extern  void            CGDone(cg_name);
extern  void            CGTrash(cg_name);
extern  cg_type         CGType(cg_name);
extern  segment_id      BESetSeg(segment_id);
extern  void            BEFlushSeg(segment_id);
extern  label_handle    BENewLabel(void);
extern  void            BEFiniLabel(label_handle);
extern  unsigned long   BETypeLength(cg_type);
extern  void            DGLabel(back_handle);
extern  void            DBModSym(sym_handle,cg_type);
extern  unsigned long   DGSeek(unsigned long);
extern  unsigned long   DGTell(void);
extern  cg_name         CGTempName(temp_handle,cg_type);

//=========================================================================

extern  void            GenLocalSyms(void);
extern  void            GenLocalDbgInfo(void);
extern  void            FreeLocalBacks(bool);
extern  void            FreeGlobalBacks(void);
extern  void            XPush(cg_name);
extern  cg_name         XPop(void);
extern  void            XPopCmplx(cg_cmplx *,cg_type);
extern  cg_name         GetTypedValue(void);
extern  label_handle    GetLabel(int);
extern  label_handle    GetStmtLabel(sym_id);
extern  void            MakeSCB(sym_id,cg_name);
extern  pointer         FEBack(sym_id);
extern  void            SubCodeSeg(void);
extern  void            FiniLabels(int);
extern  void            DefineEntryPoint(entry_pt *);
extern  bool            InArgList(entry_pt *,sym_id);
extern  void            SplitCmplx(cg_name,cg_type);
extern  tmp_handle      AllocTmp(cg_type);
extern  tmp_handle      MkTmp(cg_name,cg_type);
extern  cg_name         TmpPtr(tmp_handle,cg_type);
extern  void            RefStmtLabel(sym_id);
extern  void            DoneLabel(label_id);
extern  cg_name         CmplxAddr(cg_name,cg_name);
extern  aux_info        *AuxLookup(sym_id);
extern  cg_name         SCBPointer(cg_name);
extern  cg_name         SCBPtrAddr(cg_name);
extern  cg_name         SCBLength(cg_name);
extern  cg_name         SCBLenAddr(cg_name);
extern  cg_name         ArrayEltSize(sym_id);
extern  cg_name         FieldArrayEltSize(sym_id);
extern  call_handle     InitCall(RTCODE);
extern  bool            IntType(PTYPE);
extern  void            FiniTmps(void);
extern  void            CloneCGName(cg_name,cg_name *,cg_name *);
extern  sym_id          FindArgShadow(sym_id);
extern  bool            ForceStatic(unsigned_16);
extern  bool            SCBRequired(sym_id);

extern  aux_info        FortranInfo;
extern  back_handle     TraceEntry;
extern  segment_id      CurrCodeSegId;


cg_type SPType( sym_id sym ) {
//============================

// Return subprogram cg type.

    if( (sym->ns.flags & SY_SUBPROG_TYPE) == SY_PROGRAM ) return( T_INTEGER );
    if( (sym->ns.flags & SY_SUBPROG_TYPE) == SY_SUBROUTINE ) return( T_INTEGER );
    // must be a function
    if( sym->ns.typ == TY_CHAR ) return( T_INTEGER );
    return( F772CGType( sym ) );
}


static  cg_type    CommonEntryType( void ) {
//====================================

// Generate return value for common entry point.

    return( T_INTEGER );
}


void    FCPrologue( void ) {
//====================

// Start a subprogram.

    sym_id              sym;
    entry_pt            *ep;
    int                 ep_count;
    sel_handle          sel;
    label_handle        main_entry_label;
    unsigned_16         sp_type;

    --NumSubProgs;
    sym = GetPtr();
    sp_type = sym->ns.flags & SY_SUBPROG_TYPE;
    SubCodeSeg();
    BESetSeg( WF77_LDATA );
    DGSeek( LDSegOffset );
    if( sp_type == SY_BLOCK_DATA ) {
        if( ( sym->ns.flags & SY_UNNAMED ) == 0 ) {
            DGLabel( FEBack( sym ) );
        }
    } else {
        if( CommonEntry == NULL ) {
            CGProcDecl( sym, SPType( sym ) );
        } else {
            CGProcDecl( CommonEntry, CommonEntryType() );
        }
        if( CGOpts & CGOPT_DB_LOCALS ) {
            DBModSym( sym, T_DEFAULT );
        }
    }
    GenLocalSyms();
    if( CGOpts & CGOPT_DB_LOCALS ) {
        if( sp_type != SY_BLOCK_DATA ) {
            GenLocalDbgInfo();
        }
    }
    if( sp_type != SY_BLOCK_DATA ) {
        GenTraceback();
    }
    if( CommonEntry != NULL ) {
        sel = CGSelInit();
        ep_count = 1;
        ep = Entries->link;
        while( ep != NULL ) {
            CGSelCase( sel, GetLabel( ep->id->ns.si.sp.entry ), ep_count );
            ep_count++;
            ep = ep->link;
        }
        main_entry_label = BENewLabel();
        CGSelOther( sel, main_entry_label );
        CGSelect( sel, CGUnary( O_POINTS, CGFEName( EPValue, T_INTEGER ),
                                T_INTEGER ) );
        CGControl( O_LABEL, NULL, main_entry_label );
        BEFiniLabel( main_entry_label );
    }
    BESetSeg( WF77_LDATA );
    LDSegOffset = DGTell();
}


static  void    GenTraceback( void ) {
//==============================

    call_handle         handle;

    if( Options & OPT_TRACE ) {
        handle = InitCall( RT_SET_MODULE );
        CGAddParm( handle, CGBackName( TraceEntry, T_POINTER ), T_POINTER );
        CGDone( CGCall( handle ) );
    }
}


void    FCEpilogue( void ) {
//====================

// End a subprogram.

    sym_id      sym;
    unsigned_16 sp_type;

    sym = GetPtr();
    sp_type = sym->ns.flags & SY_SUBPROG_TYPE;
    if( sp_type != SY_BLOCK_DATA ) {
        GenTraceback();
    }
    if( StNumbers.wild_goto ) {
        DoneLabel( StNumbers.branches );
    }
    FiniLabels( 0 );
    FiniTmps();
    if( ( sym->ns.flags & SY_SUBPROG_TYPE ) == SY_PROGRAM ) {
        CGReturn( NULL, T_INTEGER );
    } else if( sp_type != SY_BLOCK_DATA ) {
        if( CommonEntry == NULL ) {
            GenReturnValue( sym );
        } else {
            GenCommonReturnValue();
            DefineEntries();
        }
    }
    BEFlushSeg( CurrCodeSegId );
    FreeLocalBacks( TRUE );
    FreeGlobalBacks();
}


bool    ChkForAltRets( entry_pt *ep ) {
//=====================================

// Check to see if the specified entry point has an alternate return.

    parameter   *args;

    args = ep->parms;
    for(;;) {
        if( args == NULL ) break;
        if( args->flags & ARG_STMTNO ) return( TRUE );
        args = args->link;
    }
    return( FALSE );
}


bool    EntryWithAltRets( void ) {
//==========================

// Check to see if there's at least one entry with an alternate return.

    entry_pt    *ep;

    ep = Entries;
    while( ep != NULL ) {
        if( ChkForAltRets( ep ) ) return( TRUE );
        ep = ep->link;
    }
    return( FALSE );
}


static  void    GenReturnValue( sym_id sym ) {
//============================================

// Generate return value.

    cg_type     typ;

    typ = SPType( sym );
    if( ( sym->ns.flags & SY_SUBPROG_TYPE ) == SY_SUBROUTINE ) {
        if( !EntryWithAltRets() ) {
            CGReturn( NULL, T_INTEGER );
            return;
        }
    } else { // must be a function
        if( sym->ns.typ == TY_CHAR ) {
            CGReturn( NULL, T_INTEGER );
            return;
        }
    }
    CGReturn( CGUnary( O_POINTS, CGFEName( ReturnValue, typ ), typ ), typ );
}


static  void    GenCommonReturnValue( void ) {
//======================================

// Generate return value for common entry point.

    if( EntryWithAltRets() ) {
        CGReturn( CGUnary( O_POINTS, CGFEName( ReturnValue, T_INTEGER ),
                           T_INTEGER ), T_INTEGER );
    } else {
        CGReturn( NULL, T_INTEGER );
    }
}


static  void    DefineEntries( void ) {
//===============================

// Define entry points into subprogram.

    entry_pt    *ep;

⌨️ 快捷键说明

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