addrfold.c

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

C
681
字号
/****************************************************************************
*
*                            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 <stdlib.h>
#include "standard.h"
#include "coderep.h"
#include "opcodes.h"
#include "cgdefs.h"
#include "model.h"
#include "addrname.h"
#include "procdef.h"
#include "sysmacro.h"
#include "zoiks.h"
#include "freelist.h"
#include "cfloat.h"

#include "addrfold.h"

extern  type_class_def  TypeClass(type_def*);
extern  void            AddrFree(an);
extern  instruction     *MakeUnary(opcode_defs,name*,name*,type_class_def);
extern  name            *STempOffset(name*,type_length,type_class_def,type_length);
extern  void            AddIns(instruction*);
extern  name            *AllocIndex(name*,name*,type_length,type_class_def);
extern  name            *ScaleIndex(name*,name*,type_length,type_class_def,type_length,int,i_flags);
extern  void            FPSetStack(name*);
extern  cg_type         NamePtrType(name*);
extern  name            *AllocIntConst(int);
extern  name            *AllocS32Const(signed_32);
extern  name            *SAllocMemory(pointer,type_length,cg_class,type_class_def,type_length);
extern  name            *AllocTemp(type_class_def);
extern  name            *AllocMemory(pointer,type_length,cg_class,type_class_def);
extern  instruction     *MakeBinary(opcode_defs,name*,name*,name*,type_class_def);
extern  name            *TempOffset(name*,type_length,type_class_def);
extern  void            BGDone(an);
extern  void            CheckPointer(an );
extern  name            *LoadTemp(name *,type_class_def);
extern  name            *LoadAddress(name*,name*,type_def*);
extern  void            Convert(an ,type_class_def );
extern  an              NewAddrName(void);
extern  bool            PointLess(an ,an );
extern  void            InsToAddr(an );
extern  name            *MaybeTemp(name *,type_class_def );
extern  void            MoveAddress(an ,an );
extern  i_flags         AlignmentToFlags( type_length );

static  void    LoadTempInt( an addr );

typedef enum {
        /* actions which require further actions*/

        UNEXPECTED,     /* unexpected mode -- two addresses*/
        TEMP_L,         /* move value of left into temp*/
        TEMP_R,         /* move value of right into temp*/
#if WORD_SIZE == 2
        SHRNK_L,        /* convert left from I4 to I2*/
        SHRNK_R,        /* convert left from I4 to I2*/
#endif
        XPAND_L,        /* expand left from I2 to I4*/
        XPAND_R,        /* expand right from I2 to I4*/
#if WORD_SIZE == 2
        XP_LC,          /* expand left & move constant*/
        XP_RC,          /* expand right & move constant*/
#endif

        /* actions which result in a finished address*/

        IL,             /* index by left temporary*/
        IR,             /* index by right temporary*/
        ADD_LA,         /* add right constant to left address*/
        ADD_RA,         /* add left constant to right address*/
        ADD_LI,         /* add right index to left*/
        ADD_RI,         /* add left index to right*/
        ADD_I,          /* add integers, creating*/
        CODE            /* generate normal code*/
} mode_action;

#if WORD_SIZE == 2
    #define CL_VALUE            CL_VALUE2
#else
    #define CL_VALUE            CL_VALUE4
#endif

#define ___     UNEXPECTED

#define _HaveMode( action )     ( (action) >= IL )

static  mode_action     AddTable[][9] = {
/***************************************/
/*                       left argument*/
#if WORD_SIZE == 2
/* &g+C  &g+C[I] &t+C    &t+C[I] &X->C   TI2+C   I2      I4      C2*/
{___,    ___,    ___,    ___,    ___,    IL,     TEMP_L, SHRNK_L,ADD_RA},//&g+C
{___,    ___,    ___,    ___,    ___,    ADD_RI, ADD_RI, SHRNK_L,ADD_RA},//&g+Ci
{___,    ___,    ___,    ___,    ___,    IL,     TEMP_L, SHRNK_L,ADD_RA},//&t+C
{___,    ___,    ___,    ___,    ___,    ADD_RI, ADD_RI, SHRNK_L,ADD_RA},//&t+Ci
{___,    ___,    ___,    ___,    ___,    ADD_RI, ADD_RI, SHRNK_L,ADD_RA},//&X->C
{IR,     ADD_LI, IR,     ADD_LI, ADD_LI, ADD_I,  ADD_I,  XPAND_R,ADD_RA},//TI2+C
{TEMP_R, ADD_LI, TEMP_R, ADD_LI, ADD_LI, ADD_I,  CODE,   XPAND_R,TEMP_R},//I2
{SHRNK_R,SHRNK_R,SHRNK_R,SHRNK_R,SHRNK_R,XPAND_L,XPAND_L,CODE,   CODE},  //I4
{ADD_LA, ADD_LA, ADD_LA, ADD_LA, ADD_LA, ADD_LA, TEMP_L, CODE,   ADD_LA} //C2
#else
/* &g+C  &g+C[I] &t+C    &t+C[I] &X->C   TI4+C   I4      I2      C2*/
{___,    ___,    ___,    ___,    ___,    IL,     TEMP_L, XPAND_L,ADD_RA},//&g+C
{___,    ___,    ___,    ___,    ___,    ADD_RI, ADD_RI, XPAND_L,ADD_RA},//&g+Ci
{___,    ___,    ___,    ___,    ___,    IL,     TEMP_L, XPAND_L,ADD_RA},//&t+C
{___,    ___,    ___,    ___,    ___,    ADD_RI, ADD_RI, XPAND_L,ADD_RA},//&t+Ci
{___,    ___,    ___,    ___,    ___,    ADD_RI, ADD_RI, XPAND_L,ADD_RA},//&X->C
{IR,     ADD_LI, IR,     ADD_LI, ADD_LI, ADD_I,  ADD_I,  XPAND_L,ADD_RA},//TI4+C
{TEMP_R, ADD_LI, TEMP_R, ADD_LI, ADD_LI, ADD_I,  CODE,   CODE,   TEMP_R},//I4
{XPAND_R,XPAND_R,XPAND_R,XPAND_R,XPAND_R,XPAND_R,CODE,   CODE,   CODE},  //I2
{ADD_LA, ADD_LA, ADD_LA, ADD_LA, ADD_LA, ADD_LA, TEMP_L, CODE,   ADD_LA} //C2
#endif
};

/*
 * This is a kludge. I was too lazy to rearrange row and column in the
 * tables so I just used this table to map CL constants onto the tables
 */

static  byte    Idx[] = {
        0,        /* CL_ADDR_GLOBAL */
        2,        /* CL_ADDR_TEMP */
        4,        /* CL_POINTER */
#if WORD_SIZE == 2
        6,        /* CL_VALUE2 */
        7,        /* CL_VALUE4 */
#else
        7,        /* CL_VALUE2 */
        6,        /* CL_VALUE4 */
#endif
        8,        /* CL_CONS2 */
#if WORD_SIZE == 2
        0xFF,     /* CL_CONS4 */
#else
        8,        /* CL_CONS4 */
#endif
        1,        /* CL_GLOBAL_INDEX */
        3,        /* CL_TEMP_INDEX */
        5         /* CL_TEMP_OFFSET */
};

extern  name    *Points( an addr, type_def *tipe ) {
/**************************************************/

    type_class_def      class;
    type_length         size;
    name                *result;
    i_flags             flags;

    CheckPointer( addr );
    if( addr->format != NF_ADDR && addr->format != NF_CONS ) {
        _Zoiks( ZOIKS_024 );
    }
    class = TypeClass( tipe );
    size = tipe->length;
    if( addr->base != NULL ) {
        flags = X_FAKE_BASE;
    } else {
        flags = EMPTY;
    }
    if( addr->flags & VOLATILE ) {
        flags |= X_VOLATILE;
    }
    if( addr->flags & CONSTANT ) {
        flags |= X_CONSTANT;
    }
    if( addr->alignment != 0 ) {
        flags |= AlignmentToFlags( addr->alignment );
    }
    switch( addr->class ) {
    case CL_ADDR_GLOBAL:
        if( addr->u.name->v.offset == addr->offset
          && addr->u.name->n.name_class == class
          && addr->u.name->n.size == size ) {
            result = addr->u.name;
        } else {
            result = SAllocMemory( addr->u.name->v.symbol,
                                   addr->offset,
                                   addr->u.name->m.memory_type,
                                   class, size );
        }
        if( addr->alignment != 0 ) {
            // NOTE: This means all references to a memory operand must
            // have the same alignment in a function (be conservative)
            result->m.alignment = addr->alignment;
        }
        break;
    case CL_ADDR_TEMP:
        if( addr->u.name->v.offset == addr->offset
          && addr->u.name->n.name_class == class
          && addr->u.name->n.size == size ) {
            result = addr->u.name;
        } else {
            result = STempOffset( addr->u.name, addr->offset, class, size );
        }
        break;
    case CL_POINTER:
        result = ScaleIndex( addr->index, addr->base, addr->offset, class,
                             size, 0, flags );
        break;
    case CL_GLOBAL_INDEX:
    case CL_TEMP_INDEX:
        result = ScaleIndex( addr->index, addr->u.name, addr->offset,
                             class, size, 0, flags & ~X_FAKE_BASE );
        break;
    case CL_TEMP_OFFSET:
        result = ScaleIndex( addr->u.name, addr->base, addr->offset, class,
                              size, 0, flags );
        break;
    case CL_CONS2:
#if WORD_SIZE != 2
    case CL_CONS4:
#endif
        addr->u.name = AllocIntConst( addr->offset );
        addr->class = CL_VALUE;
        LoadTempInt( addr );
        result = ScaleIndex( addr->u.name, addr->base, 0,
                             class, size, 0, flags );
        break;
    default:
        LoadTempInt( addr );
        result = ScaleIndex( addr->u.name, addr->base, 0,
                             class, size, 0, flags );
        break;
    }
    if( addr->flags & VOLATILE ) {
        if( result->n.class != N_INDEXED ) {
            result->v.usage |= ( VAR_VOLATILE | USE_MEMORY | NEEDS_MEMORY );
        }
    }
    if( addr->flags & CONSTANT ) {
        if( result->n.class != N_INDEXED ) {
            result->v.usage |= VAR_CONSTANT;
        }
    }
    return( result );
}


extern  an      AddrName( name *op, type_def *tipe ) {
/******************************************************/

    an  addr;

    addr = NewAddrName();
    addr->tipe = tipe;
    addr->u.name = op;
    if( op->n.class == N_CONSTANT && op->c.const_type == CONS_ABSOLUTE ) {
        addr->format = NF_CONS;
        if( CFIsI16( op->c.value ) && tipe->length <= WORD_SIZE ) {
            addr->class = CL_CONS2;
            addr->offset = CFCnvF16( op->c.value );
        } else {
            addr->class = CL_VALUE4;
            addr->offset = 0;
            #if WORD_SIZE >= 4
                if( CFIsI32( op->c.value ) ) {
                    addr->class = CL_CONS4;
                    addr->offset = CFCnvF32( op->c.value );
                }
            #endif
        }
    } else {
        if( tipe->attr & TYPE_POINTER ) {
            addr->u.name = op;
            addr->format = NF_NAME;
        } else if( tipe->length == WORD_SIZE ) {
            addr->u.name = op;
            addr->format = NF_ADDR;
            if( op->n.class == N_TEMP ) {
                addr->class = CL_TEMP_OFFSET;
            } else {
                addr->class = CL_VALUE;
            }
#if WORD_SIZE == 2
        } else if( tipe->length == 4 ) {
            addr->u.name = op;
            addr->format = NF_ADDR;
            addr->class = CL_VALUE4;
#endif
        } else {
            addr->format = NF_NAME;
        }
    }
    return( addr );
}


static  void    FixIndexClass( an addr ) {
/***********************************/

    if( addr->u.name->n.class == N_TEMP ) {
        addr->class = CL_TEMP_INDEX;
    } else {
        addr->class = CL_GLOBAL_INDEX;
    }
}


static  void    LoadTempInt( an addr ) {
/**************************************/

    addr->u.name = LoadTemp( addr->u.name, TypeClass( addr->tipe ) );
    addr->index = NULL;
    addr->offset = 0;
    if( addr->class == CL_VALUE ) {
        addr->class = CL_TEMP_OFFSET;
    }
}


⌨️ 快捷键说明

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