Example #1
0
void    FieldOp( TYPE typ1, TYPE typ2, OPTR op ) {
//================================================

// Generate code for a field selection operator.

    typ1 = typ1; op = op;
    PushOpn( CITNode->link );
    PushOpn( CITNode );
    if( CITNode->opn.us & USOPN_FLD ) {
        // sub-field reference
        EmitOp( FC_ADD );
        DumpTypes( FT_INTEGER, TypeSize( FT_INTEGER ),
                   FT_INTEGER, TypeSize( FT_INTEGER ) );
    } else {
        EmitOp( FC_FIELD_OP );
        OutPtr( CITNode->sym_ptr );
        if( ( StmtSw & SS_DATA_INIT ) == 0 ) {
            if( typ2 == FT_CHAR ) {
                if( ( CITNode->link->opn.us & USOPN_WHAT ) != USOPN_ARR ) {
                    if( ( ( CITNode->link->opn.us & USOPN_WHAT ) != USOPN_NWL ) &&
                        ( ( CITNode->link->opn.us & USOPN_WHAT ) != USOPN_ASS ) ) {
                        GFieldSCB( CITNode->link->size );
                    }
                    EmitOp( FC_MAKE_SCB );
                    OutPtr( GTempString( 0 ) );
                }
            }
        } else {
            OutPtr( CITNode->link->sym_ptr );
        }
    }
}
Example #2
0
void    GArg( void ) {
//==============

// Generate an argument for subprogram, subscript, or substring.

    if( (CITNode->opn.us & USOPN_WHERE) == USOPN_SAFE ) {
        if( (CITNode->opn.us & USOPN_FLD) &&
            ((CITNode->opn.us & USOPN_WHAT) == USOPN_ARR) &&
            (CITNode->typ == FT_CHAR) ) {
            EmitOp( FC_PASS_FIELD_CHAR_ARRAY );
            OutPtr( CITNode->value.st.field_id );
            OutPtr( GTempString( 0 ) );
        }
        return;
    }
    if( (CITNode->opn.us & USOPN_WHAT) == USOPN_SSR ) {
        EmitOp( FC_PUSH_SCB_LEN );
    } else if( (CITNode->opn.us & USOPN_WHAT) == USOPN_CON ) {
        PushOpn( CITNode );
    } else if( (CITNode->opn.us & USOPN_WHAT) == USOPN_ARR ) {
        PushOpn( CITNode );
        if( CITNode->typ == FT_CHAR ) {
            EmitOp( FC_PASS_CHAR_ARRAY );
            SymRef( CITNode );
            OutPtr( GTempString( 0 ) );
        }
    } else {
        PushOpn( CITNode );
    }
}
Example #3
0
void    AsgnChar( void ) {
//========================

// Perform character assignment.

    itnode      *save_cit;
    uint        num_args;
    uint        i;
    uint        j;

    save_cit = CITNode;
    AdvanceITPtr();
    num_args = AsgnCat();
    i = SrcChar( CITNode );
    j = TargChar( save_cit );
    if( ( num_args == 1 ) && ( i > 0 ) && ( j > 0 ) ) {
        if( OptimalChSize( i ) && OptimalChSize( j ) && ( i == j ) ) {
            PushOpn( save_cit );
            EmitOp( FC_CHAR_1_MOVE );
            DumpType( MapTypes( FT_INTEGER, i ), i );
            GenChar1Op( CITNode );
            if( ( CITNode->opn.us & USOPN_WHAT ) == USOPN_CON ) {
                CITNode->sym_ptr->u.lt.flags &= ~LT_SCB_TMP_REFERENCE;
            }
            CITNode = save_cit;
        } else {
#if ( _CPU == 386 || _CPU == 8086 )
            if( j < i ) {
                i = j;
            }
            CITNode = save_cit;
            PushOpn( CITNode );
            EmitOp( FC_CHAR_N_MOVE );
            OutInt( i );
            OutInt( j );
#else
            CatArgs( num_args );
            CITNode = save_cit;
            PushOpn( CITNode );
            EmitOp( FC_CAT );
            OutU16( (uint_16)num_args );
#endif
        }
    } else {
        CatArgs( num_args );
        CITNode = save_cit;
        PushOpn( CITNode );
        EmitOp( FC_CAT );
        OutU16( (uint_16)num_args );
    }
}
Example #4
0
void    GFiniSS( itnode *sym_node, itnode *ss_node ) {
//====================================================

// Finish a substring operation.

    if( sym_node->opn.us & USOPN_FLD ) {
        PushOpn( sym_node );
        EmitOp( FC_FIELD_SUBSTRING );
        OutPtr( sym_node->sym_ptr );
        if( sym_node->opn.us & USOPN_SS1 ) { // length known at compile-time
            OutInt( sym_node->value.st.ss_size );
        } else {
            OutInt( 0 ); // we don't know the length
        }
    } else {
        EmitOp( FC_SUBSTRING );
        if( sym_node->opn.us & USOPN_SS1 ) { // length known at compile-time
            OutPtr( NULL );
        } else {
            SymRef( sym_node ); // in case we need the length of SCB if
        }                       // character*(*) and no upper bound specified
    }
    GenTypes( ss_node, ss_node->link );
    if( (sym_node->opn.us & USOPN_FLD) == 0 ) {
        if( sym_node->opn.us & USOPN_SS1 ) { // length known at compile-time
            OutInt( sym_node->value.st.ss_size );
        }
        if( (StmtSw & SS_DATA_INIT) == 0 ) {
            sym_node->value.st.ss_id = sym_node->sym_ptr;
            sym_node->sym_ptr = GTempString( 0 );
            OutPtr( sym_node->sym_ptr );
            sym_node->opn.us |= USOPN_ASY;
        }
    }
}
Example #5
0
void            GForceHiBound( int ss, sym_id sym ) {
//=======================================================

// Generate code to fill in ADV subscript element (hi bound).
// The hi bound is constant and the low bound is not.
// We have to force the filling in of the high bound so that the number of
// of elements gets computed.
//
// Scenario:   SUBROUTINE SAM( A, J )
//             DIMENSION A(J:3)
//
// GInitADV() fills in the lo bound and # of elements in the dimension at
// compile-time. The lo bound is unknown so the ADV does not contain the
// correct information. The lo bound gets filled in at run-time but
// since the hi bound is not dumped into the ADV at compile time we
// must fill it in at run-time and compute the correct number of elements
// in the dimension.

    AddConst( CITNode );
    PushOpn( CITNode );
    EmitOp( FC_ADV_FILL_HI );
    OutPtr( sym );
    OutU16( (uint_16)ss );
    GenType( CITNode );
}
Example #6
0
void    GInitSS( itnode *itptr ) {
//================================

// Start a substring operation.

    PushOpn( itptr );
}
Example #7
0
void    GEndSubScr( itnode *arr ) {
//=================================

// Finish off a subscripting operation.

    itnode      *arg;
    int         dim_cnt;

    if( arr->opn.us & USOPN_FLD ) {
        PushOpn( arr );
        EmitOp( FC_FIELD_SUBSCRIPT );
        OutPtr( arr->sym_ptr );
        dim_cnt = _DimCount( arr->sym_ptr->u.fd.dim_ext->dim_flags );
    } else {
        EmitOp( FC_SUBSCRIPT );
        OutPtr( arr->sym_ptr );
        dim_cnt = _DimCount( arr->sym_ptr->u.ns.si.va.u.dim_ext->dim_flags );
    }
    arg = arr->list;
    while( dim_cnt-- > 0 ) {
        GenType( arg );
        arg = arg->link;
    }
    if( ( arr->opn.us & USOPN_FLD ) == 0 ) {
        if( ( StmtSw & SS_DATA_INIT ) == 0 ) {
            if( arr->sym_ptr->u.ns.u1.s.typ == FT_CHAR ) {
                OutPtr( GTempString( 0 ) );
            }
        }
    }
    SetOpn( arr, USOPN_SAFE );
}
Example #8
0
static  void    ParenExpr( void ) {
//=================================

// Finish off evaluation of a parenthesized expression.

    // don't evaluate constants enclosed in parentheses
    // so that they can be folded. Consider: (3+4)+5
    if( CITNode->opn.us != USOPN_CON ) {
        // Consider: CHARACTER A
        //           IF( ('9') .NE. (A) ) CONTINUE
        // make sure that we can optimize the character operation
        if( CITNode->opn.us == USOPN_NNL ) {
            if( CITNode->typ == FT_CHAR ) {
                int     ch_size;

                ch_size = CITNode->size;
                if( OptimalChSize( ch_size ) ) {
                    CITNode->value.st.ss_size = ch_size;
                    CITNode->opn.us |= USOPN_SS1;
                }
            }
        }
        PushOpn( CITNode );
        GParenExpr();
    }
    BackTrack();
}
Example #9
0
void            FiniCat( void ) {
//=========================

// Finish concatenation.

    int         num;
    sym_id      result;
    int         size;

    // Make sure we don't PushOpn() a constant expression
    // in case it's for a PARAMETER constant
    if( CITNode->opn.us == USOPN_CON ) {
        FoldCatSequence( CITNode );
        if( AError ) return;
    } else {
        GenCatOpn();
    }
    num = ScanCat( &size );
    if( num != 1 ) {
        PushOpn( CITNode );
        result = GStartCat( num, size );
        CatArgs( num );
        CITNode->size = size;
        GStopCat( num, result );
    }
}
Example #10
0
void    GPassAddr( FCODE routine ) {
//==================================

// Pass the address of CITNode on the stack and emit fcode for routine.

    PushOpn( CITNode );
    EmitOp( routine );
}
Example #11
0
void    GIOItem( void ) {
//=================

// Generate code to process an i/o list item.

    PushOpn( CITNode );
    GIORoutine( CITNode->typ, CITNode->size );
}
Example #12
0
static  void    GenCatOpn( void ) {
//===========================

    if( CITNode->opn.us != USOPN_CON ) {
        ChkConstCatOpn( CITNode->link );
        PushOpn( CITNode );
    }
}
Example #13
0
void    GIntlSet( void ) {
//==================

// Set internal file pointer to character variable.

    PushOpn( CITNode );
    EmitOp( FC_SET_INTL );
}
Example #14
0
void    GCallWithArgs( void ) {
//=======================

// Generate a CALL with arguments.

    PushOpn( CITNode );
    FinishCALL( CITNode );
}
Example #15
0
void    EmExprDone( void ) {
//====================

// Finish expression processing.

    if( ASType & AST_CCR ) {    // i.e. IF( .TRUE. )THEN
        PushOpn( CITNode );
    }
}
Example #16
0
static  void    DoExpr( void ) {
//========================

// Evaluate a DO expression (e1, e2 or e3 ).

    EatDoParm();
    PushOpn( CITNode );
    AdvanceITPtr();
}
Example #17
0
void    GRetIdx( void ) {
//=================

// Generate an alternate return.

    PushOpn( CITNode );
    EmitOp( FC_ASSIGN_ALT_RET );
    GenType( CITNode );
}
Example #18
0
static  void    ChkConstCatOpn( itnode *cat_opn ) {
//=================================================

    if( cat_opn->opn.us == USOPN_CON ) {
        FoldCatSequence( cat_opn );
        if( !AError ) {
            PushOpn( cat_opn );
        }
    }
}
Example #19
0
static  void    EvalOpn( void ) {
//===============================

// Evaluate operand.

    if( CITNode->opn.us == USOPN_CON ) {
        AddConst( CITNode );
    }
    PushOpn( CITNode );
}
Example #20
0
void    GFmtExprSet( void ) {
//=====================

// Pass the label identifying encoded format string.
// Called when using
//        PRINT <character expression>, ...

    PushOpn( CITNode );
    EmitOp( FC_FMT_SCAN );
    ChkExtendFmt();
}
Example #21
0
void            GSLoBound( int ss, sym_id sym ) {
//===================================================

// Generate code to fill in ADV subscript element (lo bound).

    PushOpn( CITNode );
    EmitOp( FC_ADV_FILL_LO );
    OutPtr( sym );
    OutU16( (uint_16)ss );
    GenType( CITNode );
}
Example #22
0
void    GPassValue( FCODE rtn ) {
//===============================

// Pass the value of CITNode on the stack and emit fcode for routine.

    PushOpn( CITNode );
    EmitOp( rtn );
    if( ( rtn == FC_SET_UNIT ) || ( rtn == FC_SET_REC ) ||
        ( rtn == FC_SET_RECL ) || ( rtn == FC_SET_BLOCKSIZE ) ) {
        GenType( CITNode );
    }
}
Example #23
0
void    GIOStruct( sym_id sd ) {
//==============================

// Generate code to do structure i/o.

    PushOpn( CITNode );
    if( StmtProc == PR_READ ) {
        EmitOp( FC_INPUT_STRUCT );
    } else {
        EmitOp( FC_OUTPUT_STRUCT );
    }
    OutPtr( sd ); // structure definition
}
Example #24
0
void            GSHiBoundLo1( int ss, sym_id sym ) {
//======================================================

// Generate code to fill in ADV subscript element (hi bound).
// Set the low bound to 1.

    // push high bound value
    PushOpn( CITNode );
    EmitOp( FC_ADV_FILL_HI_LO_1 );
    // general information
    OutPtr( sym );
    OutU16( (uint_16)ss );
    GenType( CITNode );
}
Example #25
0
void    LogOp( TYPE typ1, TYPE typ2, OPTR op ) {
//==============================================

// Generate code for a relational operator.

    bool        flip;

    op -= OPTR_FIRST_LOGOP;
    flip = FALSE;
    if( ( ( CITNode->opn.us & USOPN_WHERE ) == USOPN_SAFE ) &&
        ( ( CITNode->link->opn.us & USOPN_WHERE ) != USOPN_SAFE ) ) {
        flip = TRUE;
    }
    PushOpn( CITNode->link );
    if( typ1 == TY_NO_TYPE ) {  // unary
        if( _IsTypeInteger( typ2 ) ) {
            EmitOp( FC_BIT_NOT );
        } else {
            EmitOp( FC_NOT );
        }
        GenType( CITNode->link );
        SetOpn( CITNode, USOPN_SAFE );
    } else {
        PushOpn( CITNode );
        if( _IsTypeInteger( typ2 ) ) {
            EmitOp( FC_BITOPS + op );
        } else {
            EmitOp( FC_LOGOPS + op );
        }
        if( flip ) {
            GenTypes( CITNode->link, CITNode );
        } else {
            GenTypes( CITNode, CITNode->link );
        }
    }
}
Example #26
0
void    ExpOp( TYPE typ1, TYPE typ2, OPTR opr ) {
//===============================================

// Generate code to perform exponentiation.

    if( UnaryMul( typ1, typ2 ) ) {
        PushOpn( CITNode );
        EmitOp( FC_UNARY_MUL );
        GenType( CITNode );
        OutU16( ITIntValue( CITNode->link ) );
        SetOpn( CITNode, USOPN_SAFE );
    } else {
        BinOp( typ1, typ2, opr );
    }
}
Example #27
0
void    GStopCat( uint num_args, sym_id result ) {
//===============================================

// Finish concatenation into a temporary.

    /* unused parameters */ (void)result;

    CITNode->sym_ptr = GTempString( CITNode->size );
    CITNode->opn.us = USOPN_VAL;
    // Push the address of a static SCB so that we can modify its
    // length to correspond to the length concatenated so that
    //      CHARACTER*5 WORD
    //      PRINT,LEN('1'//WORD(1:3))
    // prints 4 and not 6. The static SCB in this case initially
    // contains the length 6 ( len('1') + len(word) ) since generally
    // we don't know the length concatenated at compile time if WORD
    // was indexed as WORD(I:J).
    PushOpn( CITNode );
    EmitOp( FC_CAT );
    OutU16( (uint_16)( num_args | CAT_TEMP ) ); // indicate concatenating into a static temp
}
Example #28
0
static void Unary( TYPE typ, OPTR opr ) {
//=======================================

// Generate code for unary plus or unary minus.

    PushOpn( CITNode->link );
    if( opr == OPTR_SUB ) {             // unary minus
        if( TypeCmplx( typ ) ) {
            EmitOp( FC_CUMINUS );
        } else {
            EmitOp( FC_UMINUS );
        }
        GenType( CITNode->link );
    } else if( ( _IsTypeInteger( CITNode->link->typ ) ) &&
               ( CITNode->link->size < sizeof( intstar4 ) ) ) {
        // convert INTEGER*1 or INTEGER*2 to INTEGER*4
        EmitOp( FC_CONVERT );
        DumpTypes( CITNode->link->typ, CITNode->link->size, FT_INTEGER, sizeof( intstar4 ) );
    }
    SetOpn( CITNode, USOPN_SAFE );
}
Example #29
0
static  void    DoLoop( TYPE do_type ) {
//=====================================

// Generate code for DO statement or implied-DO.

    do_entry    *doptr;
    uint        do_size;
    intstar4    incr;
    intstar4    limit;
    sym_id      loop_ctrl;
    TYPE        e1_type;
    uint        e1_size;
    itnode      *e2_node;
    itnode      *e3_node;
    bool        e2_const;

    doptr = CSHead->cs_info.do_parms;
    do_size = CITNode->sym_ptr->u.ns.xt.size;
    doptr->do_parm = CITNode->sym_ptr;          // save ptr to do variable
    AdvanceITPtr();                             // bump past the '='
    EatDoParm();                                // process e1
    PushOpn( CITNode );
    e1_type = CITNode->typ;
    e1_size = CITNode->size;
    AdvanceITPtr();
    if( ReqComma() ) {
        EatDoParm();                            // process e2
        e2_const = CITNode->opn.us == USOPN_CON;
        PushOpn( CITNode );
        e2_node = CITNode;
        AdvanceITPtr();
        e3_node = NULL;
        if( RecComma() ) {
            EatDoParm();                        // process e3
            e3_node = CITNode;
            if( !AError ) {
                if( (CITNode->opn.us == USOPN_CON) && _IsTypeInteger( do_type ) ) {
                    incr = GetIntValue( CITNode );
                    doptr->incr_value = incr;
                    doptr->increment = NULL;
                    if( (OZOpts & OZOPT_O_FASTDO) == 0 ) {
                        if( e2_const ) {
                            limit = GetIntValue( e2_node );
                            if( NeedIncrement( limit, incr, do_type ) ) {
                                PushOpn( CITNode );
                                doptr->increment = StaticAlloc( do_size, do_type );
                            }
                        } else {
                            PushOpn( CITNode );
                            doptr->increment = StaticAlloc( do_size, do_type );
                        }
                    }
                } else {
                    PushOpn( CITNode );
                    doptr->increment = StaticAlloc( do_size, do_type );
                }
                AdvanceITPtr();
            }
        } else {
            if( _IsTypeInteger( do_type ) ) {
                doptr->increment = NULL;
                doptr->incr_value = 1;
                if( (OZOpts & OZOPT_O_FASTDO) == 0 ) {
                    if( e2_const ) {
                        limit = GetIntValue( e2_node );
                        if( NeedIncrement( limit, 1, do_type ) ) {
                            PushConst( 1 );
                            doptr->increment = StaticAlloc( do_size, do_type );
                        }
                    } else {
                        PushConst( 1 );
                        doptr->increment = StaticAlloc( do_size, do_type );
                    }
                }
            } else {
                PushConst( 1 );
                doptr->increment = StaticAlloc( do_size, do_type );
            }
        }
        EmitOp( FC_DO_BEGIN );
        OutPtr( doptr->do_parm );
        OutPtr( doptr->increment );
        if( doptr->increment == NULL ) { // INTEGER do-loop with constant incr
            loop_ctrl = StaticAlloc( do_size, do_type );
            OutConst32( doptr->incr_value );
            OutPtr( loop_ctrl );
        } else {
            if( _IsTypeInteger( do_type ) ) {
                loop_ctrl = StaticAlloc( do_size, do_type );
            } else {
                loop_ctrl = StaticAlloc( sizeof( intstar4 ), FT_INTEGER );
            }
            doptr->iteration = loop_ctrl;
            OutPtr( loop_ctrl );
            if( e3_node == NULL ) {
                DumpType( FT_INTEGER, TypeSize( FT_INTEGER ) );
            } else {
                GenType( e3_node );
            }
        }
        GenType( e2_node );
        DumpType( e1_type, e1_size );
        OutU16( CSHead->branch );
        OutU16( CSHead->bottom );
    }
}
Example #30
0
static void Binary( TYPE typ1, TYPE typ2, OPTR opr ) {
//====================================================

// Generate code for binary operations.

    bool    flip;
    bool    associative;
    FCODE   op_code;

    associative = FALSE;
    if( ( opr == OPTR_ADD ) || ( opr == OPTR_MUL ) ) {
        associative = TRUE;
    }
    flip = FALSE;
    if( ( ( CITNode->opn.us & USOPN_WHERE ) == USOPN_SAFE ) &&
        ( ( CITNode->link->opn.us & USOPN_WHERE ) != USOPN_SAFE ) ) {
        flip = TRUE;
    }
    op_code = opr - OPTR_FIRST_ARITHOP;
    PushOpn( CITNode->link );
    PushOpn( CITNode );
    if( TypeCmplx( typ1 ) && TypeCmplx( typ2 ) ) {
        op_code += FC_CC_BINOPS;
        if( flip && !associative ) {
            EmitOp( FC_CMPLX_FLIP );
        }
    } else if( TypeCmplx( typ1 ) ) {
        if( flip ) {
            if( associative ) {
                op_code += FC_XC_BINOPS;
            } else {
                EmitOp( FC_XC_FLIP );
                op_code += FC_CX_BINOPS;
            }
        } else {
            op_code += FC_CX_BINOPS;
        }
    } else if( TypeCmplx( typ2 ) ) {
        if( flip ) {
            if( associative ) {
                op_code += FC_CX_BINOPS;
            } else {
                EmitOp( FC_CX_FLIP );
                op_code += FC_XC_BINOPS;
            }
        } else {
            op_code += FC_XC_BINOPS;
        }
    } else {
        op_code += FC_BINOPS;
        if( flip && !associative ) {
            EmitOp( FC_FLIP );
        }
    }
    EmitOp( op_code );
    if( flip && associative ) {
        GenTypes( CITNode->link, CITNode );
    } else {
        GenTypes( CITNode, CITNode->link );
    }
}