analnode.c
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 2,101 行 · 第 1/5 页
C
2,101 行
/****************************************************************************
*
* 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: WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
* DESCRIBE IT HERE!
*
****************************************************************************/
#include "plusplus.h"
#include <stdarg.h>
#include "cgfront.h"
#include "fold.h"
#include "errdefns.h"
#include "fnovload.h"
#include "fnbody.h"
#include "objmodel.h"
#include "typesig.h"
#include "conpool.h"
#include "utility.h"
static PTREE set_meaningful_side_effects( // SET MEANINGFUL, SIDE_EFFECTS
PTREE node ) // - node
{
if( node->op == PT_UNARY ) {
node->flags |= PTreeEffFlags( node->u.subtree[0] );
} else if( node->op == PT_BINARY ) {
node->flags |= PTreeEffFlags( node->u.subtree[1] )
| PTreeEffFlags( node->u.subtree[0] );
}
return node;
}
#ifndef NDEBUG
boolean NodeIsUnaryOp( // TEST IF UNARY OPERATION OF GIVEN TYPE
PTREE node, // - node
CGOP operation ) // - operation
{
DbgVerify( (node->cgop == operation) ? (node->op==PT_UNARY) : 1
, "NodeIsUnaryOp -- node/operator mismatch" );
return ___NodeIsOp( node, operation );
}
boolean NodeIsBinaryOp( // TEST IF BINARY OPERATION OF GIVEN TYPE
PTREE node, // - node
CGOP operation ) // - operation
{
DbgVerify( (node->cgop == operation) ? (node->op==PT_BINARY) : 1
, "NodeIsBinaryOp -- node/operator mismatch" );
return ___NodeIsOp( node, operation );
}
#endif
PTREE NodeBinary( // MAKE A BINARY NODE
CGOP op, // - operator
PTREE left, // - left operand
PTREE right ) // - right operand
{
return set_meaningful_side_effects( PTreeBinary( op, left, right ) );
}
PTREE NodeUnary( // MAKE A UNARY NODE
CGOP op, // - operator
PTREE expr ) // - operand
{
return set_meaningful_side_effects( PTreeUnary( op, expr ) );
}
PTREE NodeUnaryCopy( // MAKE A UNARY NODE, COPY ATTRIBUTES
CGOP op, // - operator
PTREE expr ) // - operand
{
PTREE node; // - new node
node = NodeUnary( op, expr );
node->type = expr->type;
node->flags = expr->flags;
node->flags &= ~PTF_NEVER_PROPPED;
node = PTreeCopySrcLocation( node, expr );
return node;
}
static PTREE nodeCommaPropogate(// PROPOGATE DATA FOR COMMA OPERATOR
PTREE node ) // - CO_COMMA node
{
PTREE right; // - right operand
right = node->u.subtree[1];
node = PTreeCopySrcLocation( node, right );
node->type = right->type;
node->flags = right->flags;
return set_meaningful_side_effects( node );
}
void NodeUnduplicate( // UNDUPLICATE A NODE
PTREE node ) // - node to be undupicated
{
PTREE partner; // - partner node
PTREE subtree; // - duplicated node
PTD* deced; // - decoration on node to be undupicated
DbgAssert( node->op == PT_DUP_EXPR );
subtree = node->u.dup.subtree[0];
if( subtree != NULL ) {
node->u.dup.subtree[0] = NULL;
partner = node->u.dup.node;
deced = partner->decor;
PTreeAssign( partner, subtree );
subtree->op = PT_ERROR;
PtdInsert( partner, deced );
PTreeFree( subtree );
}
}
static PTREE fixupTraverse( // CLEANUP before freeing
PTREE node ) // - current node
{
switch( node->op ) {
case PT_DUP_EXPR:
NodeUnduplicate( node );
break;
case PT_SYMBOL:
NodeFreeSearchResult( node );
break;
}
return node;
}
// Algorithm follows CO_COMMA nodes to the right, linking to the parent
// using u.subtree[1]. The original node is marked by setting the
// u.subtree[1] field to NULL.
//
// The rightmost node is then deleted, with at most two subtrees left
// unlinked. These nodes are linked into the tree as follows:
// - two subtrees: last CO_COMMA node points to a new CO_COMMA node
// connecting the subtrees
// - one subtree: last CO_COMMA node points at node
// - no subtrees: last CO_COMMA is replaced by the subtree
//
// The CO_COMMA nodes are reversed linked to restore a proper parse tree. As
// each node is unlinked, the node has a type and flags propogated from the
// daughter subtrees.
//
// BEFORE: AFTER: - ',' nodes are optional |
// - exp-a, exp-b may be NULL, |
// , , in which case the tree |
// / \ / \ collapses |
// / \ / \ |
// exp-1 , exp-1 , |
// / \ / \ |
// / \ / \ |
// exp-2 . exp-2 . |
// . . |
// , , |
// / \ / \ |
// / \ / \ |
// exp-n node exp-n , |
// / \ / \ |
// / \ / \ |
// exp-a exp-b exp-a exp-b |
// |
PTREE NodePruneTop( // PRUNE TOP OPERAND NODE
PTREE curr ) // - expression
{
PTREE last; // - last node
PTREE next; // - next node
PTREE dlt; // - a node to be deleted
if( curr == NULL ) return curr;
last = NULL;
while( NodeIsBinaryOp( curr, CO_COMMA ) ) {
next = curr->u.subtree[1];
curr->u.subtree[1] = last;
last = curr;
curr = next;
}
if( curr != NULL ) {
switch( curr->op ) {
case PT_DUP_EXPR :
dlt = fixupTraverse( curr );
break;
case PT_ERROR :
case PT_STRING_CONSTANT :
case PT_INT_CONSTANT :
case PT_FLOATING_CONSTANT :
case PT_TYPE :
case PT_ID :
case PT_SYMBOL :
dlt = curr;
curr = NULL;
break;
case PT_UNARY :
dlt = curr;
curr = curr->u.subtree[0];
break;
case PT_BINARY :
if( curr->u.subtree[0] == NULL ) {
dlt = curr;
curr = curr->u.subtree[1];
} else if( curr->u.subtree[1] == NULL ) {
dlt = curr;
curr = curr->u.subtree[0];
} else {
curr->cgop = CO_COMMA;
curr = nodeCommaPropogate( curr );
dlt = NULL;
}
break;
}
PTreeFree( dlt );
}
if( last != NULL ) {
if( curr == NULL ) {
next = last->u.subtree[1];
curr = last->u.subtree[0];
PTreeFree( last );
last = next;
}
while( last != NULL ) {
next = last->u.subtree[1];
last->u.subtree[1] = curr;
curr = last;
curr = nodeCommaPropogate( curr );
last = next;
}
}
return curr;
}
static PTREE pruneSubtree( // PRUNE A SUBTREE (KEEP COMMA'D EXPR'S)
PTREE expr, // - expression
PTREE *subtree ) // - ref[ subtree of expression ]
{
PTREE dlt; // - subtree to be pruned (with commas)
PTREE *ref; // - ref[ actual tree to be pruned ]
ref = PTreeRef( subtree );
dlt = *subtree;
NodeFreeDupedExpr( *ref );
*subtree = NULL;
if( subtree != ref ) {
*ref = expr;
expr = dlt;
}
return expr;
}
PTREE NodePruneLeft( // PRUNE LEFT OPERAND
PTREE expr ) // - expression
{
return pruneSubtree( expr, &expr->u.subtree[0] );
}
PTREE NodePruneRight( // PRUNE RIGHT OPERAND
PTREE expr ) // - expression
{
return pruneSubtree( expr, &expr->u.subtree[1] );
}
PTREE NodePruneLeftTop( // PRUNE LEFT, THEN TOP
PTREE expr ) // - expression to be pruned
{
return NodePruneTop( NodePruneLeft( expr ) );
}
// This routine should be called to free a tree when the tree can
// contain PT_DUP_EXPR nodes whose partner is not in the tree to be
// freed. This is because PTreeFreeSubtrees will free the duplicated
// expression before encountering the PT_DUP_EXPR node.
// (notice the use of a prefix traversal to handle the case of cleaning
// up dup nodes that duplicate subtrees with dup nodes in them)
//
void NodeFreeDupedExpr( // FREE AN EXPRESSION WITH DUPLICATES
PTREE expr ) // - expression to be freed
{
PTreeFreeSubtrees( PTreeTraversePrefix( expr, &fixupTraverse ) );
}
PTREE NodeReplace( // REPLACE EXPRESSION WITH ANOTHER
PTREE old, // - expression to be replaced
PTREE replace ) // - replacement expression
{
PTREE *ref; // - reference[ rightmost CO_COMMA operand ]
if( old != NULL ) {
old = PTreeCopySrcLocation( old, replace );
ref = PTreeRef( &old );
NodeFreeDupedExpr( *ref );
*ref = replace;
replace = old;
}
return replace;
}
PTREE NodeReplaceTop( // REPLACE TOP EXPRESSION WITH ANOTHER
PTREE old, // - expression to be replaced
PTREE replace ) // - replacement expression
{
if( old != NULL ) {
old = PTreeCopySrcLocation( old, replace );
old = NodePruneTop( old );
replace = NodeComma( old, replace );
}
return replace;
}
static PTREE nodeMakeConvert( // MAKE A CONVERSION NODE
TYPE type, // - type for conversion
PTREE expr ) // - expression to be converted
{
#if 0
#define PTF_CONVERT ( PTF_SIDE_EFF \
| PTF_MEANINGFUL \
| PTF_MEMORY_EXACT \
| PTF_PTR_NONZERO )
PTREE orig; // - original node
PTREE cast; // - cast node
PTF_FLAG flags; // - flags for cast node
orig = expr;
cast = PTreeType( type );
cast = PTreeCopySrcLocation( cast, orig );
expr = NodeBinary( CO_CONVERT, cast, orig );
expr = PTreeCopySrcLocation( expr, orig );
expr = NodeSetType( expr, type, orig->flags & PTF_CONVERT );
if( flags & PTF_MEMORY_EXACT ) {
TYPE t_conv = TypedefModifierRemoveOnly( NodeType( expr ) );
TYPE t_orig = TypedefModifierRemoveOnly( NodeType( orig ) );
if( t_conv != t_orig ) {
t_conv = TypeReferenced( t_conv );
t_orig = TypeReferenced( t_orig );
if( t_conv != t_orig ) {
expr->flags &= ~ PTF_MEMORY_EXACT;
}
}
}
expr = FoldBinary( expr );
return expr;
#undef PTF_CONVERT
#else
PTREE orig = expr;
expr = AddCastNode( expr, type );
if( expr->flags & PTF_MEMORY_EXACT ) {
TYPE t_conv = TypedefModifierRemoveOnly( NodeType( expr ) );
TYPE t_orig = TypedefModifierRemoveOnly( NodeType( orig ) );
if( t_conv != t_orig ) {
t_conv = TypeReferenced( t_conv );
t_orig = TypeReferenced( t_orig );
if( t_conv != t_orig ) {
expr->flags &= ~ PTF_MEMORY_EXACT;
}
}
}
expr = FoldBinary( expr );
return expr;
#endif
}
PTREE NodeConvert( // MAKE A CONVERSION NODE IF REQ'D
TYPE type, // - type for conversion
PTREE expr ) // - expression to be converted
{
if( ( ! TypesIdentical( NodeType( expr ), type )
||( ( expr->flags & PTF_LVALUE )
&&( NULL == TypeReference( type ) ) ) ) ) {
expr = nodeMakeConvert( type, expr );
}
return expr;
}
PTREE NodeConvertFlags( // MAKE A CONVERSION NODE WITH FLAGS, IF REQ'D
TYPE type, // - type for conversion
PTREE expr, // - expression to be converted
PTF_FLAG flags ) // - flags to be added
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?