Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ControlStruct/LabelFixer.cc

    re766208 r0a0a65b  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Rob Schluntz
    12 // Last Modified On : Tue Jul 28 13:32:43 2015
    13 // Update Count     : 156
     12// Last Modified On : Wed Jul 08 12:36:46 2015
     13// Update Count     : 145
    1414//
    1515
     
    2727
    2828namespace ControlStruct {
     29        LabelFixer::Entry::Entry( Statement *to, Statement *from ) : definition ( to ) {
     30                if ( from != 0 ) {
     31                        UsageLoc loc; loc.stmt = from;
     32                        usage.push_back( loc );
     33                }
     34        }
     35
     36        LabelFixer::Entry::Entry( Statement *to, Expression *from ) : definition ( to ) {
     37                if ( from != 0 ) {
     38                        UsageLoc loc; loc.expr = from;
     39                        usage.push_back( loc );
     40                }
     41        }
     42
     43
    2944        bool LabelFixer::Entry::insideLoop() {
    3045                return ( dynamic_cast< ForStmt * > ( definition ) ||
    3146                        dynamic_cast< WhileStmt * > ( definition )  );
     47        }
     48
     49        void LabelFixer::Entry::UsageLoc::accept( Visitor & visitor ) {
     50                if ( dynamic_cast< Statement * >( stmt ) ) {
     51                        stmt->accept( visitor );
     52                } else {
     53                        expr->accept( visitor );
     54                }
    3255        }
    3356
     
    5477        // prune to at most one label definition for each statement
    5578        void LabelFixer::visit( Statement *stmt ) {
     79                currentStatement = stmt;
    5680                std::list< Label > &labels = stmt->get_labels();
    5781
     
    5983                        // only remember one label for each statement
    6084                        Label current = setLabelsDef( labels, stmt );
     85                        labels.clear();
     86                        labels.push_front( current );
    6187                } // if
    6288        }
     
    104130                        }       else {
    105131                                // used previously, but undefined until now -> link with this entry
    106                                 delete labelTable[ *i ];
     132                                Entry * oldEntry = labelTable[ *i ];
     133                                e->add_uses( *oldEntry );
    107134                                labelTable[ *i ] = e;
    108135                        } // if
     
    114141        }
    115142
    116         // A label was used, add it ot the table if it isn't already there
     143        // Remember all uses of a label.
    117144        template< typename UsageNode >
    118145        void LabelFixer::setLabelsUsg( Label orgValue, UsageNode *use ) {
    119146                assert( use != 0 );
    120147
    121                 // add label with an unknown origin
    122                 if ( labelTable.find( orgValue ) == labelTable.end() ) {
    123                         labelTable[ orgValue ] = new Entry( 0 );
    124                 }
    125         }
    126 
    127         // Builds a table that maps a label to its defining statement.
     148                if ( labelTable.find( orgValue ) != labelTable.end() ) {
     149                        // the label has been defined or used before
     150                        labelTable[ orgValue ]->add_use( use );
     151                } else {
     152                        labelTable[ orgValue ] = new Entry( 0, use );
     153                }
     154        }
     155
     156        class LabelGetter : public Visitor {
     157                public:
     158                LabelGetter( Label &label ) : label( label ) {}
     159
     160                virtual void visit( BranchStmt * branchStmt ) {
     161                        label = branchStmt->get_target();
     162                }
     163
     164                virtual void visit( UntypedExpr * untyped ) {
     165                        NameExpr * name = dynamic_cast< NameExpr * >( untyped->get_function() );
     166                        assert( name );
     167                        assert( name->get_name() == "&&" );
     168                        NameExpr * arg = dynamic_cast< NameExpr * >( untyped->get_args().front() );
     169                        assert( arg );
     170                        label = arg->get_name();
     171                }               
     172
     173                private:
     174                        Label &label;
     175        };
     176
     177        class LabelSetter : public Visitor {
     178                public:
     179                LabelSetter( Label label ) : label( label ) {}
     180
     181                virtual void visit( BranchStmt * branchStmt ) {
     182                        branchStmt->set_target( label );
     183                }
     184
     185                virtual void visit( UntypedExpr * untyped ) {
     186                        NameExpr * name = dynamic_cast< NameExpr * >( untyped->get_function() );
     187                        assert( name );
     188                        assert( name->get_name() == "&&" );
     189                        NameExpr * arg = dynamic_cast< NameExpr * >( untyped->get_args().front() );
     190                        assert( arg );
     191                        arg->set_name( label );
     192                }
     193
     194        private:
     195                Label label;
     196        };
     197
     198        // Ultimately builds a table that maps a label to its defining statement.
     199        // In the process,
    128200        std::map<Label, Statement * > *LabelFixer::resolveJumps() throw ( SemanticError ) {
     201                std::map< Statement *, Entry * > def_us;
     202
     203                // combine the entries for all labels that target the same location
     204                for ( std::map< Label, Entry *>::iterator i = labelTable.begin(); i != labelTable.end(); ++i ) {
     205                        Entry *e = i->second;
     206
     207                        if ( def_us.find ( e->get_definition() ) == def_us.end() ) {
     208                                def_us[ e->get_definition() ] = e;
     209                        } else if ( e->used() ) {
     210                                def_us[ e->get_definition() ]->add_uses( *e );
     211                        }
     212                }
     213
     214                // create a unique label for each target location.
     215                for ( std::map< Statement *, Entry * >::iterator i = def_us.begin(); i != def_us.end(); ++i ) {
     216                        Statement *to = (*i).first;
     217                        Entry * entry = (*i).second;
     218                        std::list< Entry::UsageLoc > &from = entry->get_uses();
     219
     220                        // no label definition found
     221                        if ( to == 0 ) {
     222                                Label undef;
     223                                LabelGetter getLabel( undef );
     224                                from.back().accept( getLabel );
     225                                // Label undef = getLabel( from.back()->get_target() );
     226                                throw SemanticError ( "'" + undef + "' label not defined");
     227                        } // if
     228
     229                        // generate a new label, and attach it to its defining statement as the only label on that statement
     230                        Label finalLabel = generator->newLabel( to->get_labels().back() );
     231                        entry->set_label( finalLabel );
     232
     233                        to->get_labels().clear();
     234                        to->get_labels().push_back( finalLabel );
     235
     236                        // redirect each of the source branch statements to the new target label
     237                        for ( std::list< Entry::UsageLoc >::iterator j = from.begin(); j != from.end(); ++j ) {
     238                                LabelSetter setLabel( finalLabel );
     239                                (*j).accept( setLabel );
     240                                // setLabel( *j, finalLabel );
     241
     242                                // BranchStmt *jump = *j;
     243                                // assert( jump != 0 );
     244                                // jump->set_target( finalLabel );
     245                        } // for
     246                } // for
     247
     248                // create a table where each label maps to its defining statement
    129249                std::map< Label, Statement * > *ret = new std::map< Label, Statement * >();
    130                 for ( std::map< Label, Entry * >::iterator i = labelTable.begin(); i != labelTable.end(); ++i ) {
    131                         if ( ! i->second->defined() ) {
    132                                 throw SemanticError( "Use of undefined label: " + i->first );
    133                         }
    134                         (*ret)[ i->first ] = i->second->get_definition();
     250                for ( std::map< Statement *, Entry * >::iterator i = def_us.begin(); i != def_us.end(); ++i ) {
     251                        (*ret)[ (*i).second->get_label() ] = (*i).first;
    135252                }
    136253
Note: See TracChangeset for help on using the changeset viewer.