示例#1
0
void    FCPush( void ) {
//================

// Process PUSH F-Code.

    sym_id      sym;

    sym = GetPtr();
    if( TypeCmplx( sym->ns.typ ) ) {
        PushComplex( sym );
    } else {
        XPush( SymAddr( sym ) );
    }
}
示例#2
0
void            TDStmtFini( void ) {
//============================

// Target dependent statement finalization.

    if( StmtProc == PR_ASNMNT ) {
        if( TypeCmplx( ResultType ) ) {
            EmitOp( FC_CMPLX_EXPR_DONE );
        } else {
            EmitOp( FC_EXPR_DONE );
        }
    }
    if( StmtSw & SS_SF_REFERENCED ) {
        EmitOp( FC_SF_REFERENCED );
    }
    EmitOp( FC_STMT_DONE );
}
示例#3
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 );
}
示例#4
0
void    FCSFCall( void ) {
//==================

// Call a statement function.

    sym_id      sf;
    sym_id      sf_arg;
    sym_id      tmp;
    cg_type     sf_type;
    cg_name     arg_list;
    cg_name     value;
    cg_cmplx    z;
    obj_ptr     curr_obj;

    sf = GetPtr();
    arg_list = NULL;
    value = NULL;
    sf_type = 0;
    for(;;) {
        sf_arg = GetPtr();
        if( sf_arg == NULL ) break;
        if( sf_arg->u.ns.u1.s.typ == FT_CHAR ) {
            value = Concat( 1, CGFEName( sf_arg, TY_CHAR ) );
        } else {
            sf_type = F772CGType( sf_arg );
            if( TypeCmplx( sf_arg->u.ns.u1.s.typ ) ) {
                XPopCmplx( &z, sf_type );
                sf_type = CmplxBaseType( sf_type );
                value = ImagPtr( SymAddr( sf_arg ), sf_type );
                CGTrash( CGAssign( value, z.imagpart, sf_type ) );
                value = CGFEName( sf_arg, sf_type );
                value = CGAssign( value, z.realpart, sf_type );
            } else {
                value = CGFEName( sf_arg, sf_type );
                value = CGAssign( value, XPopValue( sf_type ), sf_type );
            }
        }
        if( arg_list == NULL ) {
            arg_list = value;
        } else {
            arg_list = CGBinary( O_COMMA, arg_list, value, TY_DEFAULT );
        }
    }
    if( sf->u.ns.u1.s.typ == FT_CHAR ) {
        tmp = GetPtr();
        value = CGUnary( O_POINTS, CGFEName( tmp, TY_CHAR ), TY_CHAR );
        value = CGAssign( CGFEName( sf, TY_CHAR ), value, TY_CHAR );
        if( arg_list == NULL ) {
            arg_list = value;
        } else {
            arg_list = CGBinary( O_COMMA, arg_list, value, TY_DEFAULT );
        }
        value = CGFEName( tmp, TY_CHAR );
    } else {
        sf_type = F772CGType( sf );
        if( !(OZOpts & OZOPT_O_INLINE) ) {
            value = CGUnary( O_POINTS, CGFEName( sf, sf_type ), sf_type );
        }
    }
    if( OZOpts & OZOPT_O_INLINE ) {
        if( arg_list != NULL ) {
            CGTrash( arg_list );
        }
        curr_obj = FCodeSeek( sf->u.ns.si.sf.u.sequence );
        GetObjPtr();
        FCodeSequence();
        FCodeSeek( curr_obj );
        if( sf->u.ns.u1.s.typ == FT_CHAR ) {
            CGTrash( XPop() );
            XPush( value );
        } else if( TypeCmplx( sf->u.ns.u1.s.typ ) ) {
            XPopCmplx( &z, sf_type );
            sf_type = CmplxBaseType( sf_type );
            XPush( TmpVal( MkTmp( z.imagpart, sf_type ), sf_type ) );
            XPush( TmpVal( MkTmp( z.realpart, sf_type ), sf_type ) );
        } else {
            XPush( TmpVal( MkTmp( XPopValue( sf_type ), sf_type ), sf_type ) );
        }
    } else {
        value = CGWarp( arg_list, GetLabel( sf->u.ns.si.sf.u.location ), value );
        // consider: y = f( a, f( b, c, d ), e )
        // make sure that inner reference to f gets evaluated before we assign
        // arguments for outer reference
        value = CGEval( value );
        if( TypeCmplx( sf->u.ns.u1.s.typ ) ) {
            SplitCmplx( TmpPtr( MkTmp( value, sf_type ), sf_type ), sf_type );
        } else {
            XPush( value );
        }
        RefStmtFunc( sf );
    }
}
示例#5
0
cg_name SymIndex( sym_id sym, cg_name i ) {
//=========================================

// Get address of symbol plus an index.
// Merges offset of symbols in common or equivalence with index so that
// we don't get two run-time calls for huge pointer arithmetic.

    sym_id      leader;
    cg_name     addr;
    signed_32   offset;
    com_eq      *ce_ext;
    cg_type     p_type;
    bool        data_reference;

    data_reference = TRUE;
    if( ( sym->ns.flags & SY_CLASS ) == SY_SUBPROGRAM ) {
        if( ( sym->ns.flags & SY_SUBPROG_TYPE ) == SY_STMT_FUNC ) {
            addr = CGFEName( sym, F772CGType( sym ) );
        } else {
            addr = CGFEName( sym, TY_CODE_PTR );
            if( sym->ns.flags & SY_SUB_PARM ) {
                addr = CGUnary( O_POINTS, addr, TY_CODE_PTR );
            }
            data_reference = FALSE;
        }
    } else if( sym->ns.flags & SY_PS_ENTRY ) {
        // it's the shadow symbol for function return value
        if( CommonEntry == NULL ) {
            if( sym->ns.typ == FT_CHAR ) {
                if( Options & OPT_DESCRIPTOR ) {
                    addr = CGFEName( ReturnValue, F772CGType( sym ) );
                    addr = CGUnary( O_POINTS, addr, TY_POINTER );
                } else {
                    addr = SubAltSCB( sym->ns.si.ms.sym );
                }
            } else {
                addr = CGFEName( ReturnValue, F772CGType( sym ) );
            }
        } else {
            if( (sym->ns.typ == FT_CHAR) && !(Options & OPT_DESCRIPTOR) ) {
                addr = SubAltSCB( CommonEntry );
            } else {
                addr = CGUnary( O_POINTS, CGFEName( ReturnValue, TY_POINTER ),
                                TY_POINTER );
            }
        }
    } else if( sym->ns.flags & SY_SUB_PARM ) {
        // subprogram argument
        if( sym->ns.flags & SY_SUBSCRIPTED ) {
            p_type = ArrayPtrType( sym );
            if( sym->ns.typ == FT_CHAR ) {
                addr = CGUnary( O_POINTS, CGFEName( sym, p_type ), p_type );
                if( !(sym->ns.flags & SY_VALUE_PARM) ) {
                    if( Options & OPT_DESCRIPTOR ) {
                        addr = SCBPointer( addr );
                    }
                }
            } else {
                addr = CGUnary( O_POINTS, CGFEName( sym, p_type ), p_type );
            }
        } else {
            p_type = TY_POINTER;
            if( sym->ns.typ == FT_CHAR ) {
                if( SCBRequired( sym ) ) {
                    addr = VarAltSCB( sym );
                } else {
                    addr = CGUnary( O_POINTS, CGFEName( sym, p_type ), p_type );
                }
            } else if( sym->ns.flags & SY_VALUE_PARM ) {
                p_type = F772CGType( sym );
                if( TypeCmplx( sym->ns.typ ) ) {
                    p_type = CmplxBaseType( p_type );
                    addr = CGFEName( sym, p_type );
                    XPush( CGUnary( O_POINTS,
                                    CGFEName( FindArgShadow( sym ), p_type ),
                                    p_type ) );
                    addr = CGUnary( O_POINTS, addr, p_type );
                } else {
                    addr = CGFEName( sym, p_type );
                }
            } else {
                addr = CGUnary( O_POINTS, CGFEName( sym, p_type ), p_type );
            }
        }
    } else if( sym->ns.flags & SY_IN_EQUIV ) {
        leader = sym;
        offset = 0;
        for(;;) {
            if( leader->ns.si.va.vi.ec_ext->ec_flags & LEADER ) break;
            offset += leader->ns.si.va.vi.ec_ext->offset;
            leader = leader->ns.si.va.vi.ec_ext->link_eqv;
        }
        if( leader->ns.si.va.vi.ec_ext->ec_flags & MEMBER_IN_COMMON ) {
            addr = CGFEName( leader->ns.si.va.vi.ec_ext->com_blk,
                             F772CGType( sym ) );
            offset += leader->ns.si.va.vi.ec_ext->offset;
        } else {
            sym_id      shadow;

            shadow = FindEqSetShadow( leader );
            if( shadow != NULL ) {
                addr = CGFEName( shadow, shadow->ns.si.ms.cg_typ );
                offset -= leader->ns.si.va.vi.ec_ext->low;
            } else if( (leader->ns.typ == FT_CHAR) &&
                       !(leader->ns.flags & SY_SUBSCRIPTED) ) {
                addr = CGBackName( leader->ns.si.va.bck_hdl, F772CGType( sym ) );
            } else {
                addr = CGFEName( leader, F772CGType( sym ) );
            }
        }
        if( i != NULL ) {
            i = CGBinary( O_PLUS, i, CGInteger( offset, TY_INT_4 ), TY_INT_4 );
        } else {
            i = CGInteger( offset, TY_INT_4 );
        }
        addr = CGBinary( O_PLUS, addr, i, SymPtrType( sym ) );
        if( (sym->ns.typ == FT_CHAR) && !(sym->ns.flags & SY_SUBSCRIPTED) ) {
            // tell code generator where storage pointed to by SCB is located
            addr = CGBinary( O_COMMA, addr,
                             CGFEName( sym, F772CGType( sym ) ), TY_DEFAULT );
        }
        i = NULL;
    } else if( ( sym->ns.typ == FT_CHAR ) &&
               ( ( sym->ns.flags & SY_SUBSCRIPTED ) == 0 ) ) {
        // character variable, address of scb
        addr = CGFEName( sym, F772CGType( sym ) );
    } else if( sym->ns.flags & SY_IN_COMMON ) {
        ce_ext = sym->ns.si.va.vi.ec_ext;
        if( i != NULL ) {
            i = CGBinary( O_PLUS, i, CGInteger( ce_ext->offset, TY_INT_4 ),
                          TY_INT_4 );
        } else {
            i = CGInteger( ce_ext->offset, TY_INT_4 );
        }
        addr = CGBinary( O_PLUS, CGFEName( ce_ext->com_blk, F772CGType( sym ) ),
                         i, SymPtrType( sym ) );
        i = NULL;
    } else {
        addr = CGFEName( sym, F772CGType( sym ) );
        if( ( sym->ns.flags & SY_SUBSCRIPTED ) && _Allocatable( sym ) ) {
            addr = CGUnary( O_POINTS, addr, ArrayPtrType( sym ) );
        }
    }
    if( i != NULL ) {
        addr = CGBinary( O_PLUS, addr, i, SymPtrType( sym ) );
    }
    if( ( OZOpts & OZOPT_O_VOLATILE ) && data_reference &&
        ( ( sym->ns.typ >= FT_REAL ) && ( sym->ns.typ <= FT_XCOMPLEX ) ) ) {
        addr = CGVolatile( addr );
    } else if( sym->ns.xflags & SY_VOLATILE ) {
        addr = CGVolatile( addr );
    }
    return( addr );
}
示例#6
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 );
    }
}
示例#7
0
void    RelOp( TYPE typ1, TYPE typ2, OPTR optr ) {
//================================================

// Generate code for a relational operator.

    bool        flip;
    bool        associative;
    bool        char_1_cmp;
    uint        i;
    uint        j;
    OPR         opr_code;
    FCODE       op_code;

    optr = optr;
    // must check for "flip" before we call "CharLength" since they may
    // call "PushOpn"
    flip = FALSE;
    if( ( ( CITNode->opn.us & USOPN_WHERE ) == USOPN_SAFE ) &&
        ( ( CITNode->link->opn.us & USOPN_WHERE ) != USOPN_SAFE ) ) {
        flip = TRUE;
    }
    // must do "CITNode->link" first to get operands in the right order
    i = CharLength( CITNode->link );
    j = CharLength( CITNode );
    opr_code = CITNode->link->opr;
    if( ( opr_code == OPR_EQ ) || ( opr_code == OPR_NE ) ) {
        char_1_cmp = OptimalChSize( i ) && OptimalChSize( j ) && ( i == j );
        associative = TRUE;
    } else {
        char_1_cmp = (i == 1 ) && ( j == 1 );
        associative = FALSE;
    }
    PushOpn( CITNode->link );
    PushOpn( CITNode );
    op_code = opr_code - OPR_FIRST_RELOP;
    if( TypeCmplx( typ1 ) && TypeCmplx( typ2 ) ) {
        op_code += FC_CC_RELOPS;
    } else if( TypeCmplx( typ1 ) ) {
        if( flip ) {
            op_code += FC_XC_RELOPS;
        } else {
            op_code += FC_CX_RELOPS;
        }
    } else if( TypeCmplx( typ2 ) ) {
        if( flip ) {
            op_code += FC_CX_RELOPS;
        } else {
            op_code += FC_XC_RELOPS;
        }
    } else {
        if( flip && !associative ) {
            EmitOp( FC_FLIP );
        }
        if( typ1 == TY_CHAR ) {
            if( char_1_cmp ) {
                op_code += FC_CHAR_1_RELOPS;
            } else {
                op_code += FC_CHAR_RELOPS;
            }
        } else {
            op_code += FC_RELOPS;
        }
    }
    EmitOp( op_code );
    if( char_1_cmp ) {
        if( associative ) {
            DumpType( MapTypes( TY_INTEGER, i ), i );
        } else {
            // Assert: comparing CHARACTER*1 with LT, LE, GT, or GE
            // Consider: CHARACTER A/'a'/
            //           IF( A .lt. CHAR(159) ) PRINT *, 'OK'
            // we must generate an unsigned comparison
            DumpType( MapTypes( TY_LOGICAL, i ), i );
        }
        if( flip && associative ) {
            GenChar1Op( CITNode->link );
            GenChar1Op( CITNode );
        } else {
            GenChar1Op( CITNode );
            GenChar1Op( CITNode->link );
        }
    } else if( typ1 != TY_CHAR ) {
        if( flip && associative ) {
            GenTypes( CITNode->link, CITNode );
        } else {
            GenTypes( CITNode, CITNode->link );
        }
    }
}