Example #1
0
extern  an      BGStopInline( call_handle handle, type_def *tipe ) {
/******************************************************************/

    // works if we're in the middle of a conditional???

    label_handle    lbl;
    inline_stack    *junk;
    an              retv;

    if( HaveCurrBlock == FALSE ) {
        EnLink( AskForNewLabel(), TRUE );
        HaveCurrBlock = TRUE;
    }
    lbl = AskForNewLabel();
    GenBlock( JUMP, 1 );
    AddTarget( lbl, FALSE );
    EnLink( lbl, TRUE );
    InlineStack->tipe = tipe;
    FEGenProc( InlineStack->proc_sym, handle );
    retv = InlineStack->addr;
    junk = InlineStack;
    InlineStack = InlineStack->next;
    CGFree( junk );
    return( retv );
}
Example #2
0
static  an      FlowOut( an node, type_def *tipe ) {
/**************************************************/

    name                *temp;
    label_handle        lbl;

    lbl = AskForNewLabel();
    temp = BGGlobalTemp( tipe );
    AddIns( MakeMove( AllocIntConst( FETrue() ), temp, temp->n.type_class ) );
    *(node->u.b.t) = CurrBlock->label;
    GenBlock( BLK_JUMP, 1 );
    AddTarget( lbl, false );
    EnLink( AskForNewLabel(), true );
    AddIns( MakeMove( AllocIntConst( 0 ), temp, temp->n.type_class ) );
    *(node->u.b.f) = CurrBlock->label;
    GenBlock( BLK_JUMP, 1 );
    AddTarget( lbl, false );
    EnLink( lbl, true );
    NamesCrossBlocks();
    AddrFree( node );
    return( AddrName( temp, tipe ) );
}
Example #3
0
void    BGProcDecl( cg_sym_handle sym, type_def *tipe )
/*****************************************************/
{
    hw_reg_set          reg;
    name                *temp;
    type_class_def      type_class;
    segment_id          old_segid;
    label_handle        lbl;

    SaveTargetModel = TargetModel;
    type_class = AddCallBlock( sym, tipe );
    if( tipe != TypeNone ) {
        if( type_class == XX ) {
            if( CurrProc->state.attr & ROUTINE_ALLOCS_RETURN ) {
                old_segid = SetOP( AskBackSeg() );
                lbl = AskForNewLabel();
                DataLabel( lbl );
                DGUBytes( tipe->length );
                CurrProc->targ.return_points = (name *)SAllocMemory( lbl, 0, CG_LBL, TypeClass( tipe ), tipe->length );
                SetOP( old_segid );
            } else {
                reg = CurrProc->state.return_reg;
                if( HW_CEqual( reg, HW_EMPTY ) ) {
                    temp = DoParmDecl( NULL, TypeInteger, HW_EMPTY );
                } else {
                    temp = AllocTemp( WD );
                    temp->v.usage |= USE_IN_ANOTHER_BLOCK;
                    AddIns( MakeMove( AllocRegName( reg ), temp, WD ) );
                    HW_TurnOn( CurrProc->state.parm.used, reg );
                }
                CurrProc->targ.return_points = temp;
            }
        }
    }
    if( CurrProc->state.attr & ROUTINE_FARSS ) {
        TargetModel |= FLOATING_SS;
    }
}
Example #4
0
static  void    DoBinarySearch( an node, select_list *list, type_def *tipe,
                               int lo, int hi, label_handle other,
                               signed_32 lobound, signed_32 hibound,
                               bool have_lobound, bool have_hibound )
/*************************************************************************/
{
    int                 num;
    int                 mid;
    select_list         *mid_list;
    an                  cmp;
    label_handle        lt;

    mid = lo + ( hi - lo ) / 2;
    mid_list = list;
    for( num = mid; num > 0; --num ) {
        mid_list = mid_list->next;
    }
    if( lo == hi ) {
        if( have_lobound && lobound == mid_list->low
         && have_hibound && hibound == mid_list->high ) {
             BGControl( O_GOTO, NULL, mid_list->label );
             return;
        } else if( mid_list->low == mid_list->high ) {
            cmp = BGCompare( O_EQ, BGDuplicate( node ),
                             BGInteger( mid_list->low, tipe ), NULL, tipe );
            BGControl( O_IF_TRUE, cmp, mid_list->label );
            BGControl( O_GOTO, NULL, other );
            return;
        }
    }
    if( hi == mid + 1 && mid_list->next->low == mid_list->next->high ) {
        /* a linear sequence for three different non-sequential cases where
           c1<c2<c3, looks like:
        if( a == c3 ) goto l3;
        if( a == c2 ) goto l2;
        if( a != c1 ) goto default;
        l1: ...

           a binary sequence for these three cases looks like:
        if( a < c2 goto lt;    \
        if( a <= c2 ) goto l2; /only one cmp ins on x86
        if( a == c3 ) goto l3;
        goto default;
        lt:
        if ( a != c1 ) goto default;
        l1: ...

        Advantage of the linear search:
        * 3 goto's instead of 5, resulting in smaller code.
        Advantage of the binary search:
        * Execution time for all the cases is more balanced. which one is
          really faster depends a lot on the CPU's branch prediction and
          other things that are very hard to measure here.

        Using a linear search here for <= 3 cases to save on code size
        with negligible performance loss or gain.
        */
        mid_list = mid_list->next;
        cmp = BGCompare( O_EQ, BGDuplicate( node ),
                         BGInteger( mid_list->low, tipe ), NULL, tipe );
        BGControl( O_IF_TRUE, cmp, mid_list->label );
        /* Because we only compared for equality, it is only possible to
           decrease the upper bound if it was already set and equal to
           the value we are comparing to. Otherwise the incoming value
           may still be higher, where the inner call may produce an
           unconditional O_GOTO to a specific case label!
        */
        if( have_hibound && hibound == mid_list->low )
            hibound--;
        DoBinarySearch( node, list, tipe, lo, mid, other,
                        lobound, hibound, have_lobound, have_hibound );
        return;
    }
    lt = AskForNewLabel();
    if( !have_lobound || SelCompare( lobound, mid_list->low ) < 0 ) {
        if( have_hibound && SelCompare( hibound, mid_list->low ) < 0 ) {
            BGControl( O_GOTO, NULL, lt );
        } else {
            cmp = BGCompare( O_LT, BGDuplicate( node ),
                             BGInteger( mid_list->low, tipe ), NULL, tipe );
            BGControl( O_IF_TRUE, cmp, lt );
        }
    }
    if( !have_lobound || SelCompare( lobound, mid_list->high ) <= 0 ) {
        if( have_hibound && SelCompare( hibound, mid_list->high ) <= 0 ) {
            BGControl( O_GOTO, NULL, mid_list->label );
        } else {
            cmp = BGCompare( O_LE, BGDuplicate( node ),
                             BGInteger( mid_list->high, tipe ), NULL, tipe );
            BGControl( O_IF_TRUE, cmp, mid_list->label );
        }
    }
    if( mid < hi ) {
        DoBinarySearch( node, list, tipe, mid+1, hi, other,
                        mid_list->high+1, hibound, true, have_hibound );
    } else if( other != NULL ) {
        BGControl( O_GOTO, NULL, other );
    }
    BGControl( O_LABEL, NULL, lt );
    if( lo < mid ) {
        DoBinarySearch( node, list, tipe, lo, mid-1, other,
                        lobound, mid_list->low-1, have_lobound, true );
    } else if( other != NULL ) {
        BGControl( O_GOTO, NULL, other );
    }
}
Example #5
0
extern  bool            CreateBreak( void )
/*****************************************/
{
    block       *blk;
    block       *break_blk;
    block       *back_break_blk;
    block       *exit_blk;
    block_edge  *edge;
    block_edge  *next_edge;
    block_num   targets;
    int         pending;
    edge_list   *exit_edge;

    if( HeadBlock == NULL ) {
        return( false );
    }
    if( _IsntModel( FORTRAN_ALIASING ) ) {
        return( false );
    }
    if( !FixReturns() ) {
        return( false );
    }
    FixEdges();

/*
    Run through the blocks and find a place (break_blk) where no previous
    blocks are branched to from later blocks. IE: there are no backward branches
    around break_blk.
*/
    _MarkBlkAllUnVisited();
    break_blk = NULL;
    back_break_blk = NULL;
    pending = 0;
    BranchOuts = NULL;
    for( blk = HeadBlock; blk != NULL; blk = blk->next_block ) {
        if( AskIfReachedLabel( blk->label ) && blk != HeadBlock )
            break;
        if( (blk->edge[0].flags & BLOCK_LABEL_DIES) == 0 && blk != HeadBlock ) {
            _MarkBlkVisited( blk );
            ++pending;
        } else if( pending == 0 ) {
            break_blk = blk;
        }
        edge = &blk->edge[0];
        for( targets = blk->targets; targets > 0; --targets ) {
            if( edge->flags & DEST_IS_BLOCK ) {
                if( edge->flags & DEST_LABEL_DIES ) {
                    if( _IsBlkVisited( edge->destination.u.blk ) ) {
                        _MarkBlkUnVisited( edge->destination.u.blk );
                        if( --pending == 0 ) {
                            back_break_blk = blk->next_block;
                        }
                    }
                }
            }
            ++edge;
        }
    }
    /* clean up the BLOCK_VISITED flags */
    _MarkBlkAllUnVisited();
    if( back_break_blk != NULL ) {
        break_blk = back_break_blk; /* always better to break on a back edge */
    }
    if( break_blk == NULL ) {
        break_blk = HeadBlock;
    }
    if( break_blk == HeadBlock ) {
        break_blk = break_blk->next_block;
    }
    if( break_blk == NULL ) {
        UnFixEdges();
        return( false );
    }

/*
    create a new block and link it after break_blk. Point Break to the rest
    of the blocks and unhook them from the block list.
*/
    Break = break_blk;
    Curr = CurrBlock;
    Tail = BlockList;
    exit_blk = NewBlock( NULL, false );
    exit_blk->gen_id = BlockList->gen_id + 1;
    exit_blk->id = BlockList->id + 1;
    exit_blk->ins.hd.line_num = 0;
    BlockList = exit_blk;
    exit_blk->prev_block = break_blk->prev_block;
    exit_blk->next_block = NULL;
    _SetBlkAttr( exit_blk, BLK_UNKNOWN_DESTINATION );
    break_blk->prev_block->next_block = exit_blk;
    break_blk->prev_block = NULL;

/*
    run throuch all the blocks before break_blk, and create a 'BranchOut' for
    and edge that goes to a block after break_blk
*/
    for( blk = HeadBlock; blk != NULL; blk = blk->next_block ) {
        edge = &blk->edge[0];
        for( targets = blk->targets; targets > 0; --targets ) {
            if( (edge->flags & DEST_IS_BLOCK) == 0 || edge->destination.u.blk->gen_id >= break_blk->gen_id ) {
                exit_edge = CGAlloc( sizeof( edge_list ) );
                exit_edge->edge = edge;
                exit_edge->next = BranchOuts;
                exit_edge->gen_id = blk->gen_id;
                BranchOuts = exit_edge;
            }
            ++edge;
        }
    }

/*
    now, point all 'BranchOuts' at the new 'exit' block, saving their original
    labels in the 'lbl' field of the exit_list
*/

    for( exit_edge = BranchOuts; exit_edge != NULL; exit_edge = exit_edge->next ) {
        edge = exit_edge->edge;
        if( edge->flags & DEST_IS_BLOCK ) {
            exit_edge->lbl = edge->destination.u.blk->label;
            RemoveInputEdge( edge );
        } else {
            exit_edge->lbl = edge->destination.u.lbl;
        }
        edge->destination.u.blk = exit_blk;
        edge->flags |= DEST_IS_BLOCK;
        edge->next_source = exit_blk->input_edges;
        exit_blk->input_edges = edge;
        exit_blk->inputs++;
    }

    if( exit_blk->inputs == 0 ) {
        BlockList = exit_blk->prev_block;
        BlockList->next_block = NULL;
        exit_blk->prev_block = NULL;
        FreeABlock( exit_blk );
    }

    _MarkBlkAttr( HeadBlock, BLK_BIG_LABEL );
    HaveBreak = true;
/*
    change any branches to HeadBlock from a block after break_blk into
    a label (~DEST_IS_BLOCK) branch.
*/
    for( edge = HeadBlock->input_edges; edge != NULL; edge = next_edge ) {
        next_edge = edge->next_source;
        if( edge->source->gen_id >= break_blk->gen_id ) {
            RemoveInputEdge( edge );
            edge->destination.u.lbl = edge->destination.u.blk->label;
            edge->flags &= ~DEST_IS_BLOCK;
        }
    }
/*
    Now, set up a new HeadBlock, and redirect all unknowns branches to it.
    Known branches may still go to the old HeadBlock. This is so that
    HeadBlock will not be a loop header. The loop optimizer will
    screw up if it is.
*/
    blk = NewBlock( NULL, false );
    blk->input_edges = NULL;
    blk->inputs = 0;
    blk->label = HeadBlock->label;
    blk->ins.hd.line_num = HeadBlock->ins.hd.line_num;
    HeadBlock->ins.hd.line_num = 0;
    blk->gen_id = 0;
    blk->id = 0;
    HeadBlock->label = AskForNewLabel();
    blk->targets = 1;
    _SetBlkAttr( blk, BLK_BIG_LABEL | BLK_JUMP );
    _MarkBlkAttrNot( HeadBlock, BLK_BIG_LABEL );
    edge = &blk->edge[0];
    edge->flags = DEST_IS_BLOCK;
    edge->destination.u.blk = HeadBlock;
    edge->source = blk;
    edge->next_source = HeadBlock->input_edges;
    HeadBlock->input_edges = edge;
    HeadBlock->inputs++;
    HeadBlock->prev_block = blk;
    blk->prev_block = NULL;
    blk->next_block = HeadBlock;
    HeadBlock = blk;
    return( true );
}