fcgmain.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 436 行

C
436
字号
/****************************************************************************
*
*                            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 interpreter (code generation phase)
*
****************************************************************************/


#include "ftnstd.h"
#include "global.h"
#include "cgdefs.h"
#include "cg.h"
#include "cgaux.h"
#include "cgswitch.h"
#include "fcodes.h"
#include "cpopt.h"
#include "fcgbls.h"
#include "progsw.h"
#include "cgflags.h"
#include "wf77segs.h"
#include "wf77labe.h"
#include "compcfg.h"
#include "emitobj.h"

#include <stdarg.h>

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

extern  cg_init_info    BEInit(cg_switches,cg_target_switches,uint,proc_revision);
extern  void            BEStart(void);
extern  void            BEStop(void);
extern  void            BEFini(void);
extern  segment_id      BESetSeg(segment_id);
extern  void            BEFreeBack(back_handle);

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

extern  void            InitSegs(void);
extern  void            AllocSegs(void);
extern  void            FiniSegs(void);
extern  void            DefTypes(void);
extern  void            DefStructs(void);
extern  void            FreeGlobalSegs(void);
extern  void            InitStack(void);
extern  void            InitRtRtns(void);
extern  void            FreeRtRtns(void);
extern  void            InitInlinePragmas(void);
extern  void            FreeInlinePragmas(void);
extern  void            InitLabels(void);
extern  void            FiniLabels(uint);
extern  void            FreeGlobalData(void);
extern  void            FreeUsedBacks(bool);
extern  void            InitTmps(void);
extern  void            FiniTmps(void);
extern  void            InitSubSegs(void);
extern  char            *GetFullSrcName(void);

extern  void            (* __FAR FCJmpTab[])(void);

unsigned_8              CGFlags = { 0 };


static  void    CGProgFini( void ) {
//============================

// Finalize code generator.

    if( CGFlags & CG_INIT ) {
        FreeGlobalData();
        FiniSegs();
        BEStop();
    }
    BEFini();
}


void    CGGenSub( void ) {
//==================

// Finalize code generator after compiling a subprogram.

    InitStack();
    if( ( CGFlags & CG_STARTED ) == 0 ) {
        CGStart();
    }
    if( CGFlags & CG_INIT ) {
        if( ( ProgSw & PS_ERROR ) == 0 ) {
            InitSubSegs();
            InitLabels();
            InitRtRtns();
            InitInlinePragmas();
            InitFCode();
            InitTmps();
            DefStructs();
            FCTablePtr = FCJmpTab;
            FCodeSequence();
            FreeRtRtns();
            FreeInlinePragmas();
            if( NumSubProgs == 0 ) {
                CGProgFini();
            }
        }
    }
}


#if _CPU == 386
  #define TARG_SWITCHES (USE_32)
#elif _CPU == 8086
  #define TARG_SWITCHES 0
#elif _CPU == _AXP
  #define TARG_SWITCHES 0
#elif _CPU == _PPC
  #define TARG_SWITCHES 0
#else
  #error no target specified
#endif

static  void    CGStart( void ) {
//=========================

// Initialize code generator.

    cg_switches         cg_opts;
    cg_target_switches  cg_target;
    int                 space_time;
    cg_init_info        info;
    proc_revision       cpu;

    cpu = 0;
    cg_opts = FORTRAN_ALIASING|RELAX_ALIAS;
#if COMP_CFG_CG_FPE
    if( !( OZOpts & OZOPT_O_LOOP_INVAR ) ) {
        cg_opts |= ENABLE_FP_EXCEPTIONS;
    }
#endif
    cg_target = TARG_SWITCHES;

#if _CPU == _AXP || _CPU == _PPC
    if( CGOpts & CGOPT_GENASM ) {
        cg_target |= ASM_OUTPUT;
    }
    if( CGOpts & CGOPT_LOGOWL ) {
        cg_target |= OWL_LOGGING;
    }
#endif
    if( CGOpts & CGOPT_ECHOAPI ) {
        cg_opts |= ECHO_API_CALLS;
    }

#if _CPU == 386 || _CPU == 8086
    if( CGOpts & CGOPT_CONST_CODE ) {
        cg_target |= CONST_IN_CODE;
    }
#endif
#if _CPU == 386
    if( OZOpts & OZOPT_O_BASE_PTR ) {
        cg_opts |= MEMORY_LOW_FAILS;
    }
#endif
    if( OZOpts & OZOPT_O_SUPER_OPTIMAL ) {
        cg_opts |= SUPER_OPTIMAL;
    }
    if( OZOpts & OZOPT_O_FLOW_REG_SAVES ) {
        cg_opts |= FLOW_REG_SAVES;
    }
    if( OZOpts & OZOPT_O_BRANCH_PREDICTION ) {
        cg_opts |= BRANCH_PREDICTION;
    }
    if( OZOpts & OZOPT_O_CALL_RET ) {
        cg_target |= NO_CALL_RET_TRANSFORM;
    }
    if( OZOpts & OZOPT_O_LOOP ) {
        cg_opts |= LOOP_OPTIMIZATION;
    }
    if( OZOpts & OZOPT_O_UNROLL ) {
        cg_opts |= LOOP_OPTIMIZATION | LOOP_UNROLLING;
    }
    if( OZOpts & OZOPT_O_MATH ) {
        cg_target |= I_MATH_INLINE;
    }
    if( OZOpts & OZOPT_O_DISABLE ) {
        cg_opts |= NO_OPTIMIZATION;
    }
#if _CPU == 386 || _CPU == 8086
    if( OZOpts & OZOPT_O_FRAME ) {
        cg_target |= NEED_STACK_FRAME;
    }
#endif
    if( OZOpts & OZOPT_O_INSSCHED ) {
        cg_opts |= INS_SCHEDULING;
    }
    if( OZOpts & OZOPT_O_NUMERIC ) {
        cg_opts |= FP_UNSTABLE_OPTIMIZATION;
    }
    space_time = 50;
    if( OZOpts & OZOPT_O_SPACE ) {
        space_time = 100;
    }
    if( OZOpts & OZOPT_O_TIME ) {
        space_time = 0;
    }
#if _CPU == 386 || _CPU == 8086
    if( _FloatingDS( CGOpts ) ) {
        cg_target |= FLOATING_DS;
    }
    if( _FloatingES( CGOpts ) ) {
        cg_target |= FLOATING_ES;
    }
#endif
#if _CPU == 8086
    if( CGOpts & CGOPT_SS_FLOATS ) {
        cg_target |= FLOATING_SS;
    }
    if( CGOpts & CGOPT_WINDOWS ) {
        cg_target |= WINDOWS | CHEAP_WINDOWS;
    }
#elif _CPU == 386
    if( CGOpts & CGOPT_EZ_OMF ) {
        cg_target |= EZ_OMF;
    }
    if( CGOpts & CGOPT_STACK_GROW ) {
        cg_target |= GROW_STACK;
    }
#endif
#if _CPU == 386 || _CPU == 8086
#if _CPU == 8086
    if( CPUOpts & (CPUOPT_80386 | CPUOPT_80486 | CPUOPT_80586) ) {
#endif
        if( _FloatingFS( CGOpts ) ) {
            cg_target |= FLOATING_FS;
        }
        if( _FloatingGS( CGOpts ) ) {
            cg_target |= FLOATING_GS;
        }
#if _CPU == 8086
    }
#endif
#endif

    // set memory model

#if _CPU == 8086
    if( CGOpts & CGOPT_M_HUGE ) {
        cg_target |= BIG_CODE | BIG_DATA;
    }
#elif _CPU == 386
    if( CGOpts & CGOPT_M_FLAT ) {
        cg_target |= FLAT_MODEL;
    }
    if( CGOpts & CGOPT_M_COMPACT ) {
        cg_target |= BIG_DATA | CHEAP_POINTER;
    }
#elif _CPU == _AXP || _CPU == _PPC
        cg_target |= CHEAP_POINTER;
#else
  #error Unknown Platform
#endif

#if _CPU == 386 || _CPU == 8086
    if( CGOpts & CGOPT_M_MEDIUM ) {
        cg_target |= BIG_CODE | CHEAP_POINTER;
    }
    if( CGOpts & CGOPT_M_LARGE ) {
        cg_target |= BIG_CODE | BIG_DATA | CHEAP_POINTER;
    }

    // set CPU type

#if _CPU == 8086
    if( CPUOpts & CPUOPT_8086 ) {
        SET_CPU( cpu, CPU_86 );
    }
    if( CPUOpts & CPUOPT_80186 ) {
        SET_CPU( cpu, CPU_186 );
    }
    if( CPUOpts & CPUOPT_80286 ) {
        SET_CPU( cpu, CPU_286 );
    }
#endif
    if( CPUOpts & CPUOPT_80386 ) {
        SET_CPU( cpu, CPU_386 );
    }
    if( CPUOpts & CPUOPT_80486 ) {
        SET_CPU( cpu, CPU_486 );
    }
    if( CPUOpts & CPUOPT_80586 ) {
        SET_CPU( cpu, CPU_586 );
    }
    if( CPUOpts & CPUOPT_80686 ) {
        SET_CPU( cpu, CPU_686 );
    }

    // set floating-point model

    SET_FPU( cpu, FPU_NONE );   // floating-point calls
    if( CPUOpts & CPUOPT_FPI ) {
        SET_FPU_EMU( cpu );
    }
    if( CPUOpts & CPUOPT_FPI87 ) {
        SET_FPU_INLINE( cpu );
    }

    // Set Floating-point level

    if( CPUOpts & CPUOPT_FP287 ) {
        SET_FPU_LEVEL( cpu, FPU_87 );
    } else if( CPUOpts & CPUOPT_FP387 ) {
        SET_FPU_LEVEL( cpu, FPU_387 );
    } else if( CPUOpts & CPUOPT_FP5 ) {
        SET_FPU_LEVEL( cpu, FPU_586 );
    } else if( CPUOpts & CPUOPT_FP6 ) {
        SET_FPU_LEVEL( cpu, FPU_686 );
    } else if( CPUOpts & (CPUOPT_FPI | CPUOPT_FPI87) ) {
        // no level specified; use default
        #if _CPU == 386
            SET_FPU_LEVEL( cpu, FPU_387 );
        #else
            SET_FPU_LEVEL( cpu, FPU_87 );
        #endif
    }

    if( CPUOpts & CPUOPT_FPD ) {
        cg_target |= P5_DIVIDE_CHECK;
    }
#endif

    if( CGOpts & CGOPT_DB_LINE ) {
        cg_opts |= NUMBERS;
    }
    if( CGOpts & CGOPT_DB_LOCALS ) {
        cg_opts |= DBG_TYPES | DBG_LOCALS | NUMBERS | NO_OPTIMIZATION;
    }
    if( CGOpts & CGOPT_DI_CV ) {
        cg_opts |= DBG_CV;
    } else if( CGOpts & CGOPT_DI_DWARF ) {
        cg_opts |= DBG_DF;
    }
    info = BEInit( cg_opts, cg_target, space_time, cpu );

    if( info.success != 0 ) {
        if( ( info.version.target == II_TARG_STUB ) ||
            ( info.version.target == II_TARG_CHECK ) ) {
            InitCG();
#if _CPU == 8086
        } else if( info.version.target == II_TARG_8086 ) {
            InitCG();
#elif _CPU == 386
        } else if( info.version.target == II_TARG_80386 ) {
            InitCG();
#elif _CPU == _AXP
        } else if( info.version.target == II_TARG_AXP ) {
            InitCG();
#elif _CPU == _PPC
        } else if( info.version.target == II_TARG_PPC ) {
            InitCG();
#else
  #error no target specified
#endif
        }
    }
    CGFlags |= CG_STARTED;
#if _CPU == 386 || _CPU == 8086
    if( GET_FPU( cpu ) > FPU_NONE ) {
        CGFlags |= CG_FP_MODEL_80x87;
    }
#endif
}


static  void    InitCG( void ) {
//========================

// Initialize code generator.

    CGFlags |= CG_INIT;
    InitSegs();
    BEStart();
    DefTypes();
    AllocSegs();
}


void    FCodeSequence( void ) {
//=======================

// Interpret an F-Code sequence.

    FCODE   f_code;

    for(;;) {
        f_code = GetFCode();
        if( f_code == FC_END_OF_SEQUENCE )
            break;
        FCTablePtr[ f_code ]();
    }
}


void    CGPurge( void ) {
//=================

// Free up unallocated memory if code generator gave a fatal error.

    FiniLabels( 0 );
    FiniLabels( FORMAT_LABEL );
    FiniTmps();
    FreeUsedBacks( FALSE );
    FreeGlobalSegs();
    FreeRtRtns();
    FreeInlinePragmas();
}

⌨️ 快捷键说明

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