upscan.c

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

C
1,377
字号
/****************************************************************************
*
*                            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:  Upscan phase of expression handling.
*
****************************************************************************/


#include "ftnstd.h"
#include "opr.h"
#include "optr.h"
#include "opn.h"
#include "errcod.h"
#include "astype.h"
#include "iflookup.h"
#include "global.h"
#include "cpopt.h"
#include "prmcodes.h"
#include "recog.h"
#include "emitobj.h"
#include "types.h"
#include "ferror.h"
#include "insert.h"
#include "utility.h"

extern  void            DetSubList(void);
extern  void            DetCallList(void);
extern  void            DetSStr(void);
extern  void            MarkIFUsed(IFF);
extern  void            GMakeCplx(void);
extern  void            GMakeDCplx(void);
extern  void            GMakeXCplx(void);
extern  void            GArg(void);
extern  void            GILCnvTo(TYPE,uint);
extern  void            CnvTo(itnode*,TYPE,uint);
extern  void            UpdateNode(itnode *,itnode *);
extern  void            BackTrack(void);
extern  void            MoveDown(void);
extern  void            KillOpnOpr(void);
extern  void            AdvError(int);
extern  void            EndExpr(void);
extern  sym_id          STConst(void *,TYPE,uint);
extern  sym_id          STLit(byte *,int);
extern  byte            ParmCode(itnode *);
extern  void            FiniCat(void);
extern  void            CatBack(void);
extern  void            CatAxeParens(void);
extern  void            CatOpn(void);
extern  void            ChkCatOpn(void);
extern  void            CatParen(void);
extern  void            ParenCat(void);
extern  void            ProcList(itnode *);
extern  void            GIChar(void);
extern  void            GModulus(void);
extern  void            GCharLen(void);
extern  void            GImag(void);
extern  void            GMax(int);
extern  void            GMin(int);
extern  void            GConjg(void);
extern  void            GDProd(void);
extern  void            GXProd(void);
extern  void            GSign(void);
extern  void            GBitTest(void);
extern  void            GBitSet(void);
extern  void            GBitClear(void);
extern  void            GBitOr(void);
extern  void            GBitAnd(void);
extern  void            GBitNot(void);
extern  void            GBitExclOr(void);
extern  void            GBitChange(void);
extern  void            GBitLShift(void);
extern  void            GBitRShift(void);
extern  void            GMod(void);
extern  void            GAbs(void);
extern  void            GASin(void);
extern  void            GACos(void);
extern  void            GATan(void);
extern  void            GATan2(void);
extern  void            GLog(void);
extern  void            GLog10(void);
extern  void            GCos(void);
extern  void            GSin(void);
extern  void            GTan(void);
extern  void            GSinh(void);
extern  void            GCosh(void);
extern  void            GTanh(void);
extern  void            GSqrt(void);
extern  void            GExp(void);
extern  void            GVolatile(void);
extern  void            GLoc(void);
extern  void            GAllocated(void);
extern  sym_id          FindStruct(char *,int);
extern  void            SetDefinedStatus(void);

extern  void            (* const __FAR GenOprTable[])(TYPE, TYPE, OPTR);
extern  void            (* const __FAR ConstTable[])(TYPE, TYPE, OPTR);

#ifdef pick
#undef pick
#endif
#define pick(id,opr_index,proc_index) proc_index,

static const OPTR __FAR OprNum[] = {
#include "oprdefn.h"
};

// Constants below used in UPSCAN for operator sequence table and are
// modified (along with UPSCAN) if operators are added/deleted/modified

//  dimensions of operator sequence table

#define OPR_CLASSES             18
#define OPR_SEQ_MAT_SIZE        (OPR_CLASSES*OPR_CLASSES-1)     //  base 0
#define OPR_SEQ_MAT_COLS        OPR_CLASSES

enum {
    OPRI_PHI,         //  null operator
    OPRI_TRM,         //  start/terminate symbol
    OPRI_FBR,         //  function/array bracket
    OPRI_LBR,         //  (
    OPRI_COM,         //  ,
    OPRI_COL,         //  :
    OPRI_EQU,         //  =
    OPRI_EQV_NEQV,    //  .EQV., .NEQV.
    OPRI_OR,          //  .OR.
    OPRI_AND,         //  .AND.
    OPRI_NOT,         //  .NOT.
    OPRI_REL,         //  .EQ.,.NE.,.LT.,.GE.,.LE.,.GT.
    OPRI_PLS_MIN,     //  +,-
    OPRI_MUL_DIV,     //  *,/
    OPRI_EXP,         //  **
    OPRI_CAT,         //  //
    OPRI_RBR,         //  )
    OPRI_FLD          //  %,.
};

#undef pick
#define pick(id,proc) id,

typedef enum {
#include "rtntable.h"
} move;

static  const move    __FAR OprSeqMat[] = {
//                                                                       |o   /
//                                                                       |p  /
//                                                                       |r /
//                                                                       |2/
// phi |- [   (   ,   :   =   eqv OR  AND NOT rel +-  */  **  //  )   %  |/opr1
//                                                                       *-----
  MO, BT, BT, BT, BT, BT, BT, BT, BT, BT, BT, BT, BT, BT, BT, BT, BT, GO, // phi
  MO, EE, CA, RP, BS, BS, GO, GO, GO, GO, GO, GO, GO, GO, GO, FC, BB, GO, // |-
  MO, BB, CA, RP, PA, LC, BE, GO, GO, GO, GO, GO, GO, GO, GO, FC, PA, GO, // [
  MO, BB, CA, RP, BT, GC, BE, GO, GO, GO, GO, GO, GO, GO, GO, CR, PE, GO, // (
  MO, BS, CA, RP, PA, BS, BE, GO, GO, GO, GO, GO, GO, GO, GO, FC, PA, GO, // ,
  MO, BS, CA, RP, BS, BS, BE, BC, BC, BC, BC, BC, GO, GO, GO, BC, HC, GO, // :
  MO, EV, CA, RP, BS, BS, GO, GO, GO, GO, GO, GO, GO, GO, GO, CB, BB, GO, // =
  MO, BT, CA, RP, BT, BC, BE, BT, GO, GO, GO, GO, GO, GO, GO, FC, BT, GO, // eqv
  MO, BT, CA, RP, BT, BC, BE, BT, GO, GO, GO, GO, GO, GO, GO, FC, BT, GO, // OR
  MO, BT, CA, RP, BT, BC, BE, BT, BT, GO, GO, GO, GO, GO, GO, FC, BT, GO, // AND
  MO, BT, CA, RP, BT, BC, BE, BT, BT, BT, BS, GO, GO, GO, GO, FC, BT, GO, // NOT
  MO, BT, CA, RP, BT, BC, BE, BT, BT, BT, BS, BR, GO, GO, GO, FC, BT, GO, // rel
  MO, BT, CA, RP, BT, BT, BE, BT, BT, BT, BS, BT, BT, GO, GO, CO, BT, GO, // +-
  MO, BT, CA, RP, BT, BT, BE, BT, BT, BT, BS, BT, BT, BT, GO, CO, BT, GO, // */
  MO, BT, CA, RP, BT, BT, BE, BT, BT, BT, BS, BT, BT, BT, GO, CO, BT, GO, // **
  MO, CO, CA, RP, CO, BC, BE, CO, CO, CO, CO, CO, GO, GO, GO, CO, CP, GO, // //
  MO, BT, BS, BS, BT, BT, BT, BT, BT, BT, BS, KO, BT, BT, BT, PC, BT, BT, // )
  MO, EV, CA, EV, EV, EV, EV, EV, EV, EV, EV, EV, EV, EV, EV, CO, EV, GO  // %
};

// Notes:
//        |-      -- start/terminal operator
//        [       -- function/array bracket
//        eqv     -- .EQV.,  .NEQV.
//        rel     -- .LT., .GT., .EQ., .NE., .LE., .GE.
//
//        operator1 is in row, operator2 is in column  ( e.g. op1 * op2 )

//
// LegalOprs -- specifies which operators are legal given the operand
//
// --------------------------------------------------------------------+
//   15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0    |
//                                                                     |
//   //  **   /   *   -   +   r   .   P   =   %   n   a   o   n   e    |
//                            e       H           o   n   r   e   q    |
//                            l       I           t   d       q   v    |
//                                                            v        |
// --------------------------------------------------------------------+
// NOTES : PHI -- not used
//       : rel -- relational operators

#define CT      0x8000          // //
#define RL      0x0200          // .EQ. .NE. .GT. .LT. .GE. .LE.
#define LG      0x000F          // .AND. .OR. .EQV. .NEQV. .XOR.
#define AR      0x7C40          // +, -, *, /, **, =
#define EQ      0x0040          // =
#define NONE    0x0000          // none allowed
#define NOT     0x0010          // .NOT.
#define PLMIN   0x0C00          // +, -
#define IPLMIN  0x0C10          // integer +, -, .NOT.
#define CHAR    (CT+RL+EQ)      // legal character-character ops
#define LOG     (LG+EQ)         // legal logical-logical ops
#define NUMOP   (AR+RL)         // legal number-number ops
#define INUMOP  (LG+AR+RL)      // legal integer-integer ops
#define FLDOP   0x0120          // field selection
#define FLDEQ   0x0160          // field selection, .EQ.

#define LEGALOPR_TAB_ROWS       13
#define LEGALOPR_TAB_COLS       13
#define LEGALOPR_TAB_SIZE       169

static  const unsigned_16     __FAR LegalOprsB[] = { /*                                |
                                                                                       |
 opnd1  (binary)                                                                       | opnd2
                                                                                       |
log1 log4  int1   int2   int4   real   dble   xtnd   cmplx  dcmplx xcmplex char struct |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
                                                                                               
LOG,  LOG,  NONE,  NONE,  NONE,  NONE,  NONE,  NONE,  NONE,  NONE,  NONE,  NONE, FLDOP, // log*1
LOG,  LOG,  NONE,  NONE,  NONE,  NONE,  NONE,  NONE,  NONE,  NONE,  NONE,  NONE, FLDOP, // log*4
NONE, NONE, INUMOP,INUMOP,INUMOP,NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NONE, FLDOP, // int*1
NONE, NONE, INUMOP,INUMOP,INUMOP,NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NONE, FLDOP, // int*2
NONE, NONE, INUMOP,INUMOP,INUMOP,NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NONE, FLDOP, // int*4
NONE, NONE, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NONE, FLDOP, // real
NONE, NONE, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NONE, FLDOP, // double
NONE, NONE, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NONE, FLDOP, // extend
NONE, NONE, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NONE, FLDOP, // complex
NONE, NONE, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NONE, FLDOP, // dcomplex
NONE, NONE, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NUMOP, NONE, FLDOP, // xcomplex
NONE, NONE, NONE,  NONE,  NONE,  NONE,  NONE,  NONE,  NONE,  NONE,  NONE,  CHAR, FLDOP, // character
NONE, NONE, NONE,  NONE,  NONE,  NONE,  NONE,  NONE,  NONE,  NONE,  NONE,  NONE, FLDEQ  // structure
};


static  const unsigned_16     __FAR LegalOprsU[] = { /*

 opnd2 (unary)

log1 log4  int1   int2   int4   real   dble   xtnd   cmplx  dcmplx xcmplex char struct
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/

NOT, NOT, IPLMIN,IPLMIN,IPLMIN, PLMIN, PLMIN, PLMIN, PLMIN, PLMIN, PLMIN,  NONE,  NONE
};


#undef pick
#define pick(id,opr_index,proc_index) opr_index,

static const byte __FAR OprIndex[] = {
#include "oprdefn.h"
};


static  bool    SimpleScript( itnode *op ) {
//==========================================

    if( ( op->opn.us & USOPN_WHERE ) != 0 )
        return( FALSE );
    switch( op->opn.us & USOPN_WHAT ) {
    case USOPN_NNL:
    case USOPN_CON:
    case USOPN_NONE:
        return( TRUE );
    }
    return( FALSE );
}


static  int     SameScripts( itnode *op1, itnode *op2 ) {
//=======================================================

    if( !SimpleScript( op1 ) ) return( 0 );
    if( ( op1->opn.us & USOPN_WHAT ) == USOPN_NONE ) {
        if( ( op2->opn.us & USOPN_WHAT ) == USOPN_CON ) {
            return( ITIntValue( op2 ) );
        } else {
            return( 0 );
        }
    }
    if( ( op1->opn.us & USOPN_WHAT ) != ( op2->opn.us & USOPN_WHAT ) ) {
        return( 0 );
    }
    if( ( op1->opn.us & USOPN_WHAT ) == USOPN_NNL ) {
        if( op1->sym_ptr == op2->sym_ptr ) {
            return( 1 );
        }
    } else if( ( op1->opn.us & USOPN_WHAT ) == USOPN_CON ) {
        return( ITIntValue( op2 ) - ITIntValue( op1 ) + 1 );
    }
    return( 0 );
}


bool    OptimalChSize( uint size ) {
//==================================

    return( ( size == 1 ) || ( size == 2 ) || ( size == 4 ) );
}


static  void    EvalOpn( void ) {
//===============================

// Evaluate operand.

    if( CITNode->opn.us == USOPN_CON ) {
        AddConst( CITNode );
    }
    PushOpn( CITNode );
}


static  void    ParenExpr( void ) {
//=================================

// Finish off evaluation of a parenthesized expression.

    // don't evaluate constants enclosed in parentheses
    // so that they can be folded. Consider: (3+4)+5
    if( CITNode->opn.us != USOPN_CON ) {
        // Consider: CHARACTER A

⌨️ 快捷键说明

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