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 + -
显示快捷键?