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