cg.c

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

C
953
字号
/****************************************************************************
*
*                            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 <stdarg.h>
#include "standard.h"
#include "cg.h"
#include "bckdef.h"
#include "cgdefs.h"
#include "typclass.h"
#include "typedef.h"
#include "cfloat.h"
#include "cgaux.h"
#include "model.h"
#include "hostsys.h"
#include "cgstub.h"
#include "feprotos.h"

#include "stubdata.h"

extern  int             TempId;

extern  void            DumpTree(n *);
extern  type_def        *TypeAddress(cg_type);
extern  char            *CopyStr(char*,char*);

extern  char            *ACopyOf(char *);
extern  void            VerTipe(cg_type ,cg_type *);
extern  n               *Binary(cg_op ,n *,n *,cg_type );
extern  char            *Tipe(cg_type );
extern  void            VerLabel(l *);
extern  char            *Label(l *);
extern  void            Action(char *,... );
extern  void            NoDanglers(void);
extern  n               *NewNode(nclass ,cg_type );
extern  void            Code(char *,... );
extern  void            VerAuto(a *);
extern  void            VerNode(n *);
extern  char            *Name(pointer );
extern  char            *Op(cg_op );
extern  void            NotDefault(cg_type );
extern  void            CGError(char *,... );
extern  void            VerBack(b *);
extern  char            *LToS(signed_32 );
extern  void            DumpT(n *);
extern  void            VerOp(cg_op ,cg_op *);
extern  void            Find(char *,pointer *,pointer );
extern  n               *Unary(cg_op ,n *,cg_type );
extern  void            CRefLabel(l *lb);
extern  void            CDefLabel(l *lb);
extern  void            DRefLabel(l *lb);
extern  void            DDefLabel(l *lb);
extern  pointer         LkAddBack(sym_handle,pointer);
extern  pointer         CGAlloc( unsigned size );
extern  pointer         DoCGAlloc( unsigned size, pointer ra );
extern  void            CGFree( pointer chunk );
extern  void            CGFreeSize( pointer chunk, int size );
extern  unsigned_32     BETypeLength( cg_type );

/********************************************************************/
/* Handle feedback for auto locations                               */
/********************************************************************/


typedef struct auto_locn AUTO_LOCN;
struct auto_locn {
    AUTO_LOCN* next;
    sym s;
    unsigned offset;
};

#define AUTO_PACK 4

static AUTO_LOCN*auto_locations;
static unsigned next_auto_offset;

static void addAutoLocn( sym s, cg_type type )
{
    AUTO_LOCN* curr;

    curr = CGAlloc( sizeof( AUTO_LOCN ) );
    curr->s = s;
    curr->offset = next_auto_offset;
    curr->next = auto_locations;
    auto_locations = curr;
    next_auto_offset += ( BETypeLength( type ) + AUTO_PACK - 1 )
                      & ( - AUTO_PACK );
}


static void dumpAutoLocn( void )
{
    AUTO_LOCN* curr;

    if( auto_locations ) {
        for( ; ; ) {
            curr = auto_locations;
            if( ! curr ) break;
            auto_locations = curr->next;
            if( ((pointer)TEMP_LOC_YES) == FEAuxInfo( curr->s, TEMP_LOC_NAME ) ) {
                Action( "TEMP_LOC_TELL offset=%h symbol=%s%n"
                      , curr->offset
                      , Name( curr->s ) );
                FEAuxInfo( (sym_handle)curr->offset, TEMP_LOC_TELL );
            }
            CGFree( curr );
        }
        Action( "%n" );
    }
}

#undef AUTO_PACK


/********************************************************************/
/* end of auto locations                                            */
/********************************************************************/


/* verification */
extern  void    CGDone( n *nd ) {
/*******************************/

//  CGError( "OOPS!" );
    Action( "CGDone( %t )%n%n", nd );
    VerNode( nd );
    DumpTree( nd );
    NoDanglers();
}

extern  void    CGTrash( n *nd ) {
/********************************/

    Action( "CGTrash( %t )%n%n", nd );
    VerNode( nd );
    DumpT( nd );
}

static  int     EvalNo = { 0 };
extern  n       *CGEval( n *nd ) {
/********************************/

    n           *new;
    char        buff[80];
    char        *endptr;

    Action( "CGEval( %t )", nd );
    VerNode( nd );
    endptr = CopyStr( "[eval", buff );
    endptr = CopyStr( LToS( ++EvalNo ), endptr );
    endptr = CopyStr( "]", endptr );
    new = NewNode( LEAF, nd->t );
    new->l = (n *)ACopyOf( buff );
    DumpTree( nd );
    Code( "evaluate ===> %s%n", new->l );
    Action( " -> %t%n%n", new );
    return( new );
}

extern  n       *CGVolatile( n *nd ) {
/************************************/

    Action( "CGVolatile( %t ) -> %t%n", nd, nd );
    VerNode( nd );
    return( nd );
}

extern  n       *CGAttr( n *nd, cg_sym_attr attr ) {
/**************************************************/

    Action( "CGAttr( %t, %l ) -> %t%n", nd, attr, nd );
    VerNode( nd );
    // should check the attr?
    return( nd );
}

static  int     DupNo = { 0 };
static  n       *CGDuplicateArray[ 2 ];
extern  n       **CGDuplicate( n *nd ) {
/************************************/

    n           *new1;
    n           *new2;
    char        buff[80];
    char        *endptr;

    Action( "CGDuplicate( %t )", nd );
    VerNode( nd );
    endptr = CopyStr( "[dup", buff );
    endptr = CopyStr( LToS( ++DupNo ), endptr );
    endptr = CopyStr( "]", endptr );
    new1 = NewNode( LEAF, nd->t );
    new1->l = (n *)ACopyOf( buff );
    endptr = CopyStr( "[dup", buff );
    endptr = CopyStr( LToS( ++DupNo ), endptr );
    endptr = CopyStr( "]", endptr );
    new2 = NewNode( LEAF, nd->t );
    new2->l = (n *)ACopyOf( buff );
    DumpT( nd );
    Code( "duplicate ===> %s %s%n", new1->l, new2->l );
    CGDuplicateArray[ 0 ] = new1;
    CGDuplicateArray[ 1 ] = new2;
    Action( " -> %t %t%n", new1, new2 );
    return( CGDuplicateArray );
}

static int inlineTypeEquivalent( cg_type t1, cg_type t2 )
{
    return TypeAddress( t1 )->refno == TypeAddress( t2 )->refno;
}

extern  void    CGProcDecl( sym s, cg_type t ) {
/**********************************************/

    b   *bk;
    Action( "%n==================================================%n" );
    Action( "CGProcDecl" );
    Action( "( %s, %s )", Name(s), Tipe(t) );
    Attrs(s);
    CClass(s);
    bk = FEBack(s);
    VerBack(bk);
    Code( "Routine %s%n", Name(s) );
    if( Inlines ) {
#if 0
        if( Inlines->t != t ) {
#else
        if( ! inlineTypeEquivalent( Inlines->t, t ) ) {
#endif
            CGError( "Declared type of inline '%s' does not match", Name(s) );
        }
        if( Inlines->h != s ) {
            char name[80];
            CopyStr( Name(Inlines->h), name );
            CGError( "Expecting inline for '%s', got '%s'", name, Name(s) );
        }
    } else {
        DDefLabel( bk->lp );
        InProc = s;
    }
}

extern  void    CGParmDecl(  sym s,  cg_type  t ) {
/*************************************************/

    ip  *iparm;
    int i;

    addAutoLocn( s, t );
    Action( "CGParmDecl" );
    Action( "( %s, %s )", Name(s), Tipe(t) );
    Attrs(s);
    Code( "Parm %s%n", Name(s) );
    if( Inlines ) {
        Inlines->d++;
        if( Inlines->d > Inlines->c ) {
            CGError( "Too many parameters for inline '%s'", Name(Inlines->h) );
        }
        iparm = Inlines->p;
        for( i = 1; i < Inlines->d; ++i ) {
            iparm = iparm->n;
        }
#if 0
        if( iparm->t != t ) {
#else
        if( ! inlineTypeEquivalent( iparm->t, t ) ) {
#endif
            CGError( "Type of parm %d to inline '%s' does not match",
                      Inlines->d, Name(Inlines->h) );
        }
    }
}

extern  void    CGAutoDecl( sym s, cg_type t ) {
/**********************************************/

    addAutoLocn( s, t );
    Action( "CGAutoDecl" );
    Action( "( %s, %s )", Name(s), Tipe(t) );
    Attrs(s);
    Code( "Auto %s%n", Name(s) );
}

extern  label_handle CGLastParm() {
/*********************************/

    Action( "CGLastParm()%n" );
    return( NULL );
}

extern  void    Attrs( sym s ) {
/******************************/

    fe_attr     a;
    Action( "\n----" );
    a = FEAttr( s );
    if( a & FE_PROC ) Action( " FE_PROC" );
    if( a & FE_STATIC ) Action( " FE_STATIC" );
    if( a & FE_GLOBAL ) Action( " FE_GLOBAL" );
    if( a & FE_IMPORT ) Action( " FE_IMPORT" );
    if( a & FE_CONSTANT ) Action( " FE_CONSTANT" );
    if( a & FE_MEMORY ) Action( " FE_MEMORY" );
    if( a & FE_VISIBLE ) Action( " FE_VISIBLE" );
    if( a & FE_NOALIAS ) Action( " FE_NOALIAS" );
    if( a & FE_UNIQUE ) Action( " FE_UNIQUE" );
    if( a & FE_COMMON ) Action( " FE_COMMON" );
    if( a & FE_ADDR_TAKEN ) Action( " FE_ADDR_TAKEN" );
    if( a & FE_VOLATILE ) Action( " FE_VOLATILE" );
    Action( " seg id %d%n", FESegID( s ) );
}

extern  void    DumpCClass( call_class c ) {
/******************************************/

#if _TARGET & ( _TARG_IAPX86 | _TARG_80386 )
    if( c & FAR ) Action( "FAR " );
    if( c & ROUTINE_RETURN ) Action( "ROUTINE_RETURN " );
    if( c & SPECIAL_RETURN ) Action( "SPECIAL_RETURN " );
#endif
    if( c & CALLER_POPS ) Action( "CALLER_POPS " );
    if( c & NO_MEMORY_CHANGED ) Action( "NO_MEMORY_CHANGED " );
    if( c & NO_MEMORY_READ ) Action( "NO_MEMORY_READ " );
    if( c & SUICIDAL ) Action( "SUICIDAL " );
}

extern  void    CClass( sym  s ) {
/********************************/

    call_class  *pc;

    pc = FEAuxInfo( FEAuxInfo( s, AUX_LOOKUP ), CALL_CLASS );
    DumpCClass( *pc );
    Action( "%n" );
}

extern  void    CG3WayControl( n *e, l *lt, l *eq, l *gt ) {
/**********************************************************/

    Action( "CG3WayControl" );
    Action( "( %s, ", Label(lt) );
    Action( "%s, ", Label( eq ) );
    Action( "%s )%n", Label( gt ) );
    Code( "IF_ARITH %s", Label( lt ) );
    Code( " %s", Label( eq ) );
    Code( " %s ", Label( gt ) );
    CRefLabel( lt );
    CRefLabel( eq );
    CRefLabel( gt );
    VerNode( e );
    DumpTree( e );
    NoDanglers();
}
extern  void    CGControl( cg_op o, n *e, l  *lb ) {
/**************************************************/

    Action( "CGControl" );
    VerCGCtrl( TRUE, o, e, lb );
}
extern  void    VerCGCtrl( bool ver, cg_op o, n *e, l *lb ) {
/***********************************************************/

    if( ver ) {
        VerOp( o, ControlOps );
    }
    if( o == O_IF_TRUE || o == O_IF_FALSE ) {
        VerNode( e );
    } else if( e != NULL ) {
        CGError( "3rd Parm to CGControl must be NULL if 2nd parm !== O_IF_ ... " );
    }
    if( o != O_LABEL_RETURN ) {
        Action( "( %s, %t, %s )%n", Op(o), e, Label(lb) );
        Code( "%s %s  ", Op(o), Label(lb) );
    } else {
        Action( "( %s, %t, NULL )%n", Op(o), e );
        Code( "%s%n", Op(o) );
    }
    if( e != NULL ) {
        DumpTree( e );
    } else {
        Code( "%n" );
    }
    switch( o ) {
    case O_GOTO:
    case O_IF_TRUE:
    case O_IF_FALSE:
    case O_INVOKE_LABEL:
        CRefLabel( lb );
        break;
    case O_LABEL:
        CDefLabel( lb );
        break;
    }
    Action( "%n" );
    NoDanglers();
}
extern  n       *CGCompare( cg_op o, n *l, n *r, cg_type t ) {
/************************************************************/

    n   *new;

    Action( "CGCompare" );
    VerNode(l);
    VerNode(r);
    VerOp(o,CompareOps);
    Action( "( %s, %t, %t, %s )", Op(o), l, r, Tipe( t ) );
    new = Binary(o,l,r,T_BOOLEAN);
    Action( " -> %t%n", new );
    return( new );
}
extern  n       *CGFlow( cg_op o, n *l, n *r ) {
/**********************************************/

    n   *new;

    Action( "CGFlow" );
    VerNode(l);
    if( o != O_FLOW_NOT ) {
        VerNode(r);
    } else if( r != NULL ) {
        CGError( "3rd Parm to CGFlow( O_FLOW_NOT, ... must be null" );
    }
    VerOp(o,FlowOps);
    Action( "( %s, %t, %t )", Op(o), l, r );
    new = Binary(o,l,r,T_BOOLEAN);
    Action( " -> %t%n", new );
    return( new );
}
extern  sh      *CGSelInit() {
/****************************/

    sh  *s;

    Action( "CGSelInit()" );
    s=CGAlloc(sizeof(sh));
    s->o=NULL;
    s->r=NULL;
    s->i=++SelId;
    Action( " -> %d%n", SelId );
    return(s);
}
extern  void    CGSelCase( sh *s, l *lb, signed_32 v ) {
/******************************************************/

    Action( "CGSelCase" );
    Action( "( %d, %l, %s )%n", s->i, v, Label( lb ) );
    CRefLabel( lb );
    SelRange(s,v,v,lb);
}
extern  void    CGSelRange( sh *s, signed_32 lo, signed_32 hi, l *lb ) {

⌨️ 快捷键说明

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