tree.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 2,199 行 · 第 1/5 页
C
2,199 行
/****************************************************************************
*
* 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: Functions to manipulate the expression tree.
*
****************************************************************************/
#include "standard.h"
#include "sysmacro.h"
#include "coderep.h"
#include "addrname.h"
#include "model.h"
#include "cgdefs.h"
#include "procdef.h"
#include "tree.h"
#include "hostsys.h"
#include "zoiks.h"
#include "opcodes.h"
#include "freelist.h"
#include "cfloat.h"
#include "targsys.h"
#include "cgaux.h"
#define BY_CG
#include "feprotos.h"
#include "cgprotos.h"
#ifndef NDEBUG
#include "echoapi.h"
#endif
#include "addrfold.h"
#include "bgcall.h"
#include "bldcall.h"
#include "bldins.h"
#include "blips.h"
#include "data.h"
#include "display.h"
#include "foldins.h"
#include "inline.h"
#include "makeaddr.h"
#include "namelist.h"
#include "optask.h"
#include "patch.h"
#include "rgtbl.h"
#include "stack.h"
#include "treeprot.h"
#include "treeconv.h"
#include "treefold.h"
#include "typemap.h"
#include "types.h"
#include "i64.h"
#if _TARGET & ( _TARG_80386 | _TARG_IAPX86 )
#include "i86segs.h"
#endif
static void FreeTreeNode( tn node );
static void Control( cg_op op, tn node, label_handle lbl, bool gen );
static pointer TreeFrl;
static type_class_def BinMat[] = {
/*********************************
What is the result type of a binary operation
*/
/* U1 I1 U2 I2 U4 I4 U8 I8 CP PT FS FD FL*/
U1,U1,U2,I2,U4,I4,U8,I8,CP,PT,FS,FD,FL,/* U1*/
U1,I1,U2,I2,U4,I4,U8,I8,CP,PT,FS,FD,FL,/* I1*/
U2,U2,U2,U2,U4,I4,U8,I8,CP,PT,FS,FD,FL,/* U2*/
I2,I2,U2,I2,U4,I4,U8,I8,CP,PT,FS,FD,FL,/* I2*/
U4,U4,U4,U4,U4,U4,U8,I8,CP,PT,FS,FD,FL,/* U4*/
I4,I4,I4,I4,U4,I4,U8,I8,CP,PT,FS,FD,FL,/* I4*/
U8,U8,U8,U8,U8,U8,U8,U8,CP,PT,FD,FD,FL,/* U8*/
I8,I8,I8,I8,I8,I8,U8,I8,CP,PT,FD,FD,FL,/* I8*/
CP,CP,CP,CP,CP,CP,CP,CP,CP,PT,ER,ER,ER,/* CP*/
PT,PT,PT,PT,PT,PT,PT,PT,PT,PT,ER,ER,ER,/* PT*/
FS,FS,FS,FS,FS,FS,FD,FD,ER,ER,FS,FD,FL,/* FS*/
FD,FD,FD,FD,FD,FD,FD,FD,ER,ER,FD,FD,FL,/* FD*/
FL,FL,FL,FL,FL,FL,FL,FL,ER,ER,FL,FL,FL /* FL*/
};
static type_class_def SubMat[] = {
/*********************************
what is the result type of a subtraction
*/
/* U1 I1 U2 I2 U4 I4 U8 I8 CP PT FS FD FL*/
U1,U1,U2,I2,U4,I4,U8,I8,CP,PT,FS,FD,FL,/* U1*/
U1,I1,U2,I2,U4,I4,U8,I8,CP,PT,FS,FD,FL,/* I1*/
U2,U2,U2,U2,U4,I4,U8,I8,CP,PT,FS,FD,FL,/* U2*/
I2,I2,U2,I2,U4,I4,U8,I8,CP,PT,FS,FD,FL,/* I2*/
U4,U4,U4,U4,U4,U4,U8,I8,CP,PT,FS,FD,FL,/* U4*/
I4,I4,I4,I4,U4,I4,U8,I8,CP,PT,FS,FD,FL,/* I4*/
U8,U8,U8,U8,U8,U8,U8,U8,CP,PT,FD,FD,FL,/* U8*/
I8,I8,I8,I8,I8,I8,U8,I8,CP,PT,FD,FD,FL,/* I8*/
CP,CP,CP,CP,CP,CP,CP,CP,XX,PT,ER,ER,ER,/* CP*/
PT,PT,PT,PT,PT,PT,PT,PT,PT,XX,ER,ER,ER,/* PT*/
FS,FS,FS,FS,FS,FS,FD,FD,ER,ER,FS,FD,FL,/* FS*/
FD,FD,FD,FD,FD,FD,FD,FD,ER,ER,FD,FD,FL,/* FD*/
FL,FL,FL,FL,FL,FL,FL,FL,ER,ER,FL,FL,FL,/* FL*/
};
/*
Routines TGxxxx build up the expression trees. TNxxx tear them down.
*/
static tn NewTreeNode( void )
/******************************
gimme a new tree node
*/
{
tn new;
new = AllocFrl( &TreeFrl, sizeof( either_tree_node ) );
new->base = NULL;
new->alignment = 0;
#ifndef NDEBUG
new->useinfo.hdltype = NO_HANDLE;
new->useinfo.used = 0;
#endif
return( new );
}
extern tn TGLeaf( an addr )
/****************************
create a leaf node for "addr"
*/
{
tn node;
node = NewTreeNode();
node->op = O_NOP;
node->u.addr = addr;
node->rite = NULL;
node->kids = 0;
node->flags = TF_USED;
node->tipe = addr->tipe;
node->class = TN_LEAF;
if( addr->format == NF_BOOL ) {
node->tipe = TypeBoolean;
} else if( addr->format == NF_CONS ) {
node->class = TN_CONS;
node->u.name = addr->u.name;
BGDone( addr );
}
return( node );
}
extern btn TGBitMask( tn left, byte start, byte len, type_def *tipe )
/*********************************************************************
return a tree node for bits "start" for "len" selected from "left"
whose type is "tipe". Takes and yields an lvalue.
*/
{
btn new;
new = (btn)NewTreeNode();
new->u.left = left;
new->tipe = tipe;
new->flags = TF_USED;
#if _TARGET & _TARG_370
new->start = tipe->length*8 - start - len;
#else
new->start = start;
#endif
new->len = len;
new->is_signed = FALSE;
new->kids = left->kids + 1;
new->class = TN_BIT_LVALUE;
#ifndef NDEBUG
new->useinfo.hdltype = NO_HANDLE;
new->useinfo.used = 0;
#endif
return( new );
}
extern tn TGNode( tn_class class, cg_op op,
tn left, tn rite, type_def *tipe )
/*********************************************
create a general node
*/
{
tn node;
node = NewTreeNode();
node->class = class;
node->op = op;
node->u.left = left;
node->rite = rite;
node->tipe = tipe;
node->flags = TF_USED;
node->kids = 0;
if( rite != NULL && class != TN_PARM ) {
node->kids += rite->kids + 1;
}
if( left != NULL ) {
node->kids += left->kids + 1;
node->flags |= TF_HAS_LEFT;
}
return( node );
}
extern tn TGWarp( tn before, label_handle label, tn after )
/************************************************************
evaluate "before", call label "label" and yield value "after".
*/
{
tn result;
result = TGNode( TN_COLON, O_NOP, NULL, before, after->tipe );
result->u.handle = label;
result = TGNode( TN_WARP, O_NOP, result, after, after->tipe );
return( result );
}
extern tn TGHandle( void *ptr )
/********************************
make a handle node - this is a leaf which holds a ptr
*/
{
tn node;
node = NewTreeNode();
node->tipe = TypeAddress( T_DEFAULT );
node->class = TN_HANDLE;
node->op = O_NOP;
node->u.handle = ptr;
return( node );
}
extern tn TGCallback( cg_callback rtn, callback_handle ptr )
/*************************************************************
make a special callback node which will be used to communicate with
the front end
*/
{
tn node;
node = TGNode( TN_CALLBACK, O_NOP, NULL, TGHandle( ptr ), TypeAddress( T_DEFAULT ) );
node->u.handle = TGHandle( rtn );
return( node );
}
static type_def *ResultType( tn left, tn rite, type_def *tipe,
type_class_def *mat, bool demote_const )
/*****************************************************************
What is the resulting type of "left" op "rite" given that the front
end says it should be "tipe" (T_DEFAULT if its not sure).
"demote_const" is true if we are allowed to do demotion of type even
if the front end said it wanted a different type. For example if
the front end says do ( (char)i & 3 ) as an integer, we know better.
*/
{
tn temp;
type_def *ltipe;
type_def *rtipe;
#if _TARGET & 0
if( tipe->length < WORD_SIZE ) {
if( tipe->attr & TYPE_SIGNED ) {
return( TypeAddress( T_INTEGER ) );
}
return( TypeAddress( T_UNSIGNED ) );
}
#endif
if( !demote_const && tipe->refno != T_DEFAULT ) return( tipe );
if( left->class == TN_CONS ) {
temp = left;
left = rite;
rite = temp;
}
ltipe = left->tipe;
if( ltipe == TypeBoolean ) {
ltipe = TypeInteger;
}
rtipe = rite->tipe;
if( rtipe == TypeBoolean ) {
rtipe = TypeInteger;
}
if( tipe->refno == T_DEFAULT ) {
return( ClassType( mat[ TypeClass(ltipe)*XX + TypeClass(rtipe) ] ));
}
#if _TARGET & 0
return( tipe );
#else
if( left->tipe->length >= tipe->length ) return( tipe );
if( rite->class != TN_CONS ) return( tipe );
if( left->tipe->attr & TYPE_FLOAT ) return( tipe );
if( rite->tipe->attr & TYPE_FLOAT ) return( tipe );
if( tipe->length > TypeClassSize[ U4 ] ) return( tipe );
if( left->tipe->attr & TYPE_SIGNED ) {
if( !CFSignedSize( rite->u.name->c.value, left->tipe->length ) ) {
return( tipe );
}
if( rite->u.name->c.int_value < 0 ) return( tipe );
if( !( tipe->attr & TYPE_SIGNED ) ) return( tipe );
} else {
if( !CFUnSignedSize( rite->u.name->c.value, left->tipe->length ) ) {
return( tipe );
}
}
return( left->tipe );
#endif
}
#if _TARGET & ( _TARG_80386 | _TARG_IAPX86 )
static bool RHSLongPointer( tn rite )
{
if( rite->class == TN_LEAF && rite->u.addr->format == NF_ADDR ) {
switch( rite->u.addr->class ) {
case CL_ADDR_GLOBAL:
case CL_ADDR_TEMP:
return( TRUE );
default:
break;
}
} else {
switch( rite->tipe->refno ) {
case T_LONG_POINTER:
case T_HUGE_POINTER:
case T_LONG_CODE_PTR:
return( TRUE );
break;
}
}
return( FALSE );
}
#endif
extern tn TGCompare( cg_op op, tn left, tn rite, type_def *tipe )
/***********************************************************************
build a relational operator node
*/
{
tn new;
tn_btn left_tn_btn;
bool can_demote;
can_demote = TRUE;
#if _TARGET & _TARG_AXP
// FIXME: bad assumption being covered here
if( tipe->length < 4 ) {
tipe = TypeAddress( T_INTEGER );
can_demote = FALSE;
}
#endif
if( ( left->tipe == rite->tipe )
&& ( left->tipe != TypeBoolean )
&& ( ( left->tipe->attr & ~TYPE_SIGNED ) == ( tipe->attr & ~TYPE_SIGNED ) ) ) {
tipe = left->tipe;
} else {
tipe = ResultType( left, rite, tipe, BinMat, can_demote );
}
left = TGConvert( left, tipe );
rite = TGConvert( rite, tipe );
new = FoldCompare( op, left, rite, tipe );
if( new != NULL ) return( new );
left_tn_btn.t = left;
new = FoldBitCompare( op, left_tn_btn, rite );
if( new != NULL ) return( new );
new = FoldPostGetsCompare( op, left, rite, tipe );
if( new != NULL ) return( new );
new = TGNode( TN_COMPARE, op, left, rite, TypeBoolean );
return( new );
}
static an Int( unsigned_32 num )
/*********************************
return an address name for an integer
*/
{
return( BGInteger( num, TypeInteger ) );
}
static an Int64( unsigned_64 num )
/***********************************
return an address name for a 64-bit integer
*/
{
return( BGInt64( num, TypeLongLongInteger ) );
}
extern unsigned_32 Mask( btn node )
/**************************************
return a mask of 1's in the positions a bit field occupies.
*/
{
unsigned_32 mask;
uint len;
unsigned_32 bit;
len = node->len;
mask = 0;
bit = (unsigned_32)1 << node->start;
for( ;; ) {
mask |= bit;
bit <<= 1;
if( --len == 0 ) break;
}
return( mask );
}
static unsigned_64 Mask64( btn node )
/****************************************
like Mask(), only 64-bit
*/
{
unsigned_64 mask;
uint len;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?