Changeset 937e51d for src/ControlStruct


Ignore:
Timestamp:
Jun 26, 2015, 4:00:26 PM (10 years ago)
Author:
Aaron Moss <a3moss@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, ctor, deferred_resn, demangler, enum, forall-pointer-decay, gc_noraii, jacob/cs343-translation, jenkins-sandbox, master, memory, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, string, with_gc
Children:
0df292b, e0ff3e6
Parents:
eb50842 (diff), 1869adf (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge pointer to pointer to qualified fix into master

Location:
src/ControlStruct
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • src/ControlStruct/ChooseMutator.cc

    reb50842 r937e51d  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue May 19 15:31:39 2015
    13 // Update Count     : 2
     11// Last Modified By : Rob Schluntz
     12// Last Modified On : Wed Jun 03 15:30:20 2015
     13// Update Count     : 5
    1414//
    1515
     
    4444                std::list< Statement * > &stmts = caseStmt->get_statements();
    4545
     46                // the difference between switch and choose is that switch has an implicit fallthrough
     47                // to the next case, whereas choose has an implicit break at the end of the current case.
     48                // thus to transform a choose statement into a switch, we only need to insert breaks at the
     49                // end of any case that doesn't already end in a break and that doesn't end in a fallthru
     50
    4651                if ( insideChoose ) {
    4752                        BranchStmt *posBrk;
  • src/ControlStruct/LabelFixer.cc

    reb50842 r937e51d  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue May 19 15:25:59 2015
    13 // Update Count     : 1
     11// Last Modified By : Rob Schluntz
     12// Last Modified On : Wed Jun 24 16:24:34 2015
     13// Update Count     : 141
    1414//
    1515
     
    1919#include "LabelFixer.h"
    2020#include "MLEMutator.h"
     21#include "SynTree/Expression.h"
    2122#include "SynTree/Statement.h"
    2223#include "SynTree/Declaration.h"
    2324#include "utility.h"
    2425
     26#include <iostream>
     27
    2528namespace ControlStruct {
    2629        LabelFixer::Entry::Entry( Statement *to, Statement *from ) : definition ( to ) {
    27                 if ( from != 0 )
    28                         usage.push_back( from );
    29         }
     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
    3043
    3144        bool LabelFixer::Entry::insideLoop() {
    3245                return ( dynamic_cast< ForStmt * > ( definition ) ||
    33                                  dynamic_cast< WhileStmt * > ( definition )  );
     46                        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                }
    3455        }
    3556
     
    4061
    4162        void LabelFixer::visit( FunctionDecl *functionDecl ) {
    42                 if ( functionDecl->get_statements() != 0 )
    43                         functionDecl->get_statements()->accept( *this );
     63                maybeAccept( functionDecl->get_statements(), *this );
    4464
    4565                MLEMutator mlemut( resolveJumps(), generator );
     
    4767        }
    4868
     69        // prune to at most one label definition for each statement
    4970        void LabelFixer::visit( Statement *stmt ) {
     71                currentStatement = stmt;
    5072                std::list< Label > &labels = stmt->get_labels();
    5173
    5274                if ( ! labels.empty() ) {
     75                        // only remember one label for each statement
    5376                        Label current = setLabelsDef( labels, stmt );
    5477                        labels.clear();
     
    5881
    5982        void LabelFixer::visit( BranchStmt *branchStmt ) {
    60                 visit ( ( Statement * )branchStmt );  // the labels this statement might have
    61 
    62                 Label target;
    63                 if ( (target = branchStmt->get_target()) != "" ) {
     83                visit ( ( Statement * )branchStmt );
     84
     85                // for labeled branches, add an entry to the label table
     86                Label target = branchStmt->get_target();
     87                if ( target != "" ) {
    6488                        setLabelsUsg( target, branchStmt );
    65                 } //else       /* computed goto or normal exit-loop statements */
    66         }
    67 
     89                }
     90        }
     91
     92        void LabelFixer::visit( UntypedExpr *untyped ) {
     93                if ( NameExpr * func = dynamic_cast< NameExpr * >( untyped->get_function() ) ) {
     94                        if ( func->get_name() == "&&" ) {
     95                                NameExpr * arg = dynamic_cast< NameExpr * >( untyped->get_args().front() );
     96                                Label target = arg->get_name();
     97                                assert( target != "" );
     98                                setLabelsUsg( target, untyped );
     99                        } else {
     100                                Visitor::visit( untyped );
     101                        }
     102                }
     103        }
     104
     105
     106        // sets the definition of the labelTable entry to be the provided
     107        // statement for every label in the list parameter. Happens for every kind of statement
    68108        Label LabelFixer::setLabelsDef( std::list< Label > &llabel, Statement *definition ) {
    69109                assert( definition != 0 );
    70                 Entry *entry = new Entry( definition );
    71                 bool used = false;
    72 
    73                 for ( std::list< Label >::iterator i = llabel.begin(); i != llabel.end(); i++ )
    74                         if ( labelTable.find( *i ) == labelTable.end() )
    75                                 { used = true; labelTable[ *i ] = entry; } // undefined and unused
    76                         else
    77                                 if ( labelTable[ *i ]->defined() )
    78                                         throw SemanticError( "Duplicate definition of label: " + *i );
    79                                 else
    80                                         labelTable[ *i ]->set_definition( definition );
    81 
    82                 if ( ! used ) delete entry;
    83 
    84                 return labelTable[ llabel.front() ]->get_label();  // this *must* exist
    85         }
    86 
    87         Label LabelFixer::setLabelsUsg( Label orgValue, Statement *use ) {
     110                assert( llabel.size() > 0 );
     111
     112                Entry * e = new Entry( definition );
     113
     114                for ( std::list< Label >::iterator i = llabel.begin(); i != llabel.end(); i++ ) {
     115                        if ( labelTable.find( *i ) == labelTable.end() ) {
     116                                // all labels on this statement need to use the same entry, so this should only be created once
     117                                // undefined and unused until now, add an entry
     118                                labelTable[ *i ] =  e;
     119                        } else if ( labelTable[ *i ]->defined() ) {
     120                                // defined twice, error
     121                                throw SemanticError( "Duplicate definition of label: " + *i );
     122                        }       else {
     123                                // used previously, but undefined until now -> link with this entry
     124                                Entry * oldEntry = labelTable[ *i ];
     125                                e->add_uses( *oldEntry );
     126                                labelTable[ *i ] = e;
     127                        } // if
     128                } // for
     129
     130                // produce one of the labels attached to this statement to be
     131                // temporarily used as the canonical label
     132                return labelTable[ llabel.front() ]->get_label();
     133        }
     134
     135        // Remember all uses of a label.
     136        template< typename UsageNode >
     137        void LabelFixer::setLabelsUsg( Label orgValue, UsageNode *use ) {
    88138                assert( use != 0 );
    89139
    90                 if ( labelTable.find( orgValue ) != labelTable.end() )
    91                         labelTable[ orgValue ]->add_use( use );         // the label has been defined or used before
    92                 else
     140                if ( labelTable.find( orgValue ) != labelTable.end() ) {
     141                        // the label has been defined or used before
     142                        labelTable[ orgValue ]->add_use( use );
     143                } else {
    93144                        labelTable[ orgValue ] = new Entry( 0, use );
    94 
    95                 return labelTable[ orgValue ]->get_label();
    96         }
    97 
     145                }
     146        }
     147
     148        class LabelGetter : public Visitor {
     149                public:
     150                LabelGetter( Label &label ) : label( label ) {}
     151
     152                virtual void visit( BranchStmt * branchStmt ) {
     153                        label = branchStmt->get_target();
     154                }
     155
     156                virtual void visit( UntypedExpr * untyped ) {
     157                        NameExpr * name = dynamic_cast< NameExpr * >( untyped->get_function() );
     158                        assert( name );
     159                        assert( name->get_name() == "&&" );
     160                        NameExpr * arg = dynamic_cast< NameExpr * >( untyped->get_args().front() );
     161                        assert( arg );
     162                        label = arg->get_name();
     163                }               
     164
     165                private:
     166                        Label &label;
     167        };
     168
     169        class LabelSetter : public Visitor {
     170                public:
     171                LabelSetter( Label label ) : label( label ) {}
     172
     173                virtual void visit( BranchStmt * branchStmt ) {
     174                        branchStmt->set_target( label );
     175                }
     176
     177                virtual void visit( UntypedExpr * untyped ) {
     178                        NameExpr * name = dynamic_cast< NameExpr * >( untyped->get_function() );
     179                        assert( name );
     180                        assert( name->get_name() == "&&" );
     181                        NameExpr * arg = dynamic_cast< NameExpr * >( untyped->get_args().front() );
     182                        assert( arg );
     183                        arg->set_name( label );
     184                }
     185
     186        private:
     187                Label label;
     188        };
     189
     190        // Ultimately builds a table that maps a label to its defining statement.
     191        // In the process,
    98192        std::map<Label, Statement * > *LabelFixer::resolveJumps() throw ( SemanticError ) {
    99193                std::map< Statement *, Entry * > def_us;
    100194
    101                 for ( std::map< Label, Entry *>::iterator i = labelTable.begin(); i != labelTable.end(); i++ ) {
     195                // combine the entries for all labels that target the same location
     196                for ( std::map< Label, Entry *>::iterator i = labelTable.begin(); i != labelTable.end(); ++i ) {
    102197                        Entry *e = i->second;
    103198
    104                         if ( def_us.find ( e->get_definition() ) == def_us.end() )
     199                        if ( def_us.find ( e->get_definition() ) == def_us.end() ) {
    105200                                def_us[ e->get_definition() ] = e;
    106                         else
    107                                 if ( e->used() )
    108                                         def_us[ e->get_definition() ]->add_uses( e->get_uses() );
    109                 }
    110 
    111                 // get rid of labelTable
    112                 for ( std::map< Statement *, Entry * >::iterator i = def_us.begin(); i != def_us.end(); i++ ) {
     201                        } else if ( e->used() ) {
     202                                def_us[ e->get_definition() ]->add_uses( *e );
     203                        }
     204                }
     205
     206                // create a unique label for each target location.
     207                for ( std::map< Statement *, Entry * >::iterator i = def_us.begin(); i != def_us.end(); ++i ) {
    113208                        Statement *to = (*i).first;
    114                         std::list< Statement *> &from = (*i).second->get_uses();
    115                         Label finalLabel = generator->newLabel();
    116                         (*i).second->set_label( finalLabel );
    117 
     209                        Entry * entry = (*i).second;
     210                        std::list< Entry::UsageLoc > &from = entry->get_uses();
     211
     212                        // no label definition found
    118213                        if ( to == 0 ) {
    119                                 BranchStmt *first_use = dynamic_cast<BranchStmt *>(from.back());
    120                                 Label undef("");
    121                                 if ( first_use != 0 )
    122                                         undef = first_use->get_target();
     214                                Label undef;
     215                                LabelGetter getLabel( undef );
     216                                from.back().accept( getLabel );
     217                                // Label undef = getLabel( from.back()->get_target() );
    123218                                throw SemanticError ( "'" + undef + "' label not defined");
    124                         }
     219                        } // if
     220
     221                        // generate a new label, and attach it to its defining statement as the only label on that statement
     222                        Label finalLabel = generator->newLabel( to->get_labels().back() );
     223                        entry->set_label( finalLabel );
    125224
    126225                        to->get_labels().clear();
    127226                        to->get_labels().push_back( finalLabel );
    128227
    129                         for ( std::list< Statement *>::iterator j = from.begin(); j != from.end(); j++ ) {
    130                                 BranchStmt *jumpTo = dynamic_cast< BranchStmt * > ( *j );
    131                                 assert( jumpTo != 0 );
    132                                 jumpTo->set_target( finalLabel );
     228                        // redirect each of the source branch statements to the new target label
     229                        for ( std::list< Entry::UsageLoc >::iterator j = from.begin(); j != from.end(); ++j ) {
     230                                LabelSetter setLabel( finalLabel );
     231                                (*j).accept( setLabel );
     232                                // setLabel( *j, finalLabel );
     233
     234                                // BranchStmt *jump = *j;
     235                                // assert( jump != 0 );
     236                                // jump->set_target( finalLabel );
    133237                        } // for
    134238                } // for
    135239
    136                 // reverse table
     240                // create a table where each label maps to its defining statement
    137241                std::map< Label, Statement * > *ret = new std::map< Label, Statement * >();
    138                 for ( std::map< Statement *, Entry * >::iterator i = def_us.begin(); i != def_us.end(); i++ )
     242                for ( std::map< Statement *, Entry * >::iterator i = def_us.begin(); i != def_us.end(); ++i ) {
    139243                        (*ret)[ (*i).second->get_label() ] = (*i).first;
     244                }
    140245
    141246                return ret;
  • src/ControlStruct/LabelFixer.h

    reb50842 r937e51d  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue May 19 15:31:55 2015
    13 // Update Count     : 3
     11// Last Modified By : Rob Schluntz
     12// Last Modified On : Tue Jun 23 15:47:25 2015
     13// Update Count     : 28
    1414//
    1515
     
    5353                virtual void visit( DeclStmt *stmt ) { visit( (Statement *)stmt ); return Parent::visit( stmt ); }
    5454                virtual void visit( BranchStmt *branchStmt );
     55                virtual void visit( UntypedExpr *untyped );
    5556
    5657                Label setLabelsDef( std::list< Label > &, Statement *definition );
    57                 Label setLabelsUsg( Label, Statement *usage = 0 );
     58                template< typename UsageNode >
     59                void setLabelsUsg( Label, UsageNode *usage = 0 );
    5860
    5961          private:
    6062                class Entry {
    61                   public:
    62                         Entry( Statement *to = 0, Statement *from = 0 );
     63                        public:
     64                        union UsageLoc {
     65                                Statement * stmt;
     66                                Expression * expr;
     67
     68                                void accept( Visitor &visitor );
     69                        };
     70
     71                        Entry( Statement *to ) : definition( to ) {}
     72                        Entry( Statement *to, Statement *from );
     73                        Entry( Statement *to, Expression *from );
    6374                        bool used() { return ( usage.empty() ); }
    6475                        bool defined() { return ( definition != 0 ); }
     
    6677
    6778                        Label get_label() const { return label; }
     79                        void set_label( Label lab ) { label = lab; }
     80
    6881                        Statement *get_definition() const { return definition; }
    69                         std::list< Statement *> &get_uses() { return usage; }
    70 
    71                         void add_use ( Statement *use ) { usage.push_back( use ); }
    72                         void add_uses ( std::list<Statement *> uses ) { usage.insert( usage.end(), uses.begin(), uses.end() ); }
    7382                        void set_definition( Statement *def ) { definition = def; }
    7483
    75                         void set_label( Label lab ) { label = lab; }
    76                         Label gset_label() const { return label; }
     84                        std::list< UsageLoc > &get_uses() { return usage; }
     85                        void add_use( Statement *use ) {
     86                                UsageLoc loc;
     87                                loc.stmt = use;
     88                                usage.push_back( loc );
     89                        }
     90                        void add_use( Expression *use ) {
     91                                UsageLoc loc;
     92                                loc.expr = use;
     93                                usage.push_back( loc );                                 
     94                        }
     95
     96                        void add_uses ( Entry &other ) { usage.insert( usage.end(), other.usage.begin(), usage.end() ); }
    7797                  private:
    7898                        Label label; 
    7999                        Statement *definition;
    80                         std::list<Statement *> usage;
     100                        std::list<UsageLoc> usage;
    81101                };
    82102                 
    83103                std::map < Label, Entry *> labelTable;
    84104                LabelGenerator *generator;
     105                Statement * currentStatement;
    85106        };
    86107} // namespace ControlStruct
  • src/ControlStruct/LabelGenerator.cc

    reb50842 r937e51d  
    1010// Created On       : Mon May 18 07:44:20 2015
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue May 19 15:32:04 2015
    13 // Update Count     : 2
     12// Last Modified On : Tue Jun 23 12:18:34 2015
     13// Update Count     : 13
    1414//
    1515
    1616#include <iostream>
    17 #include <strstream>
     17#include <sstream>
    1818
    1919#include "LabelGenerator.h"
     
    2929        }
    3030
    31         Label LabelGenerator::newLabel() {
    32                 std::ostrstream os;
    33                 os << "__L" << current++ << "__";// << std::ends;
    34                 os.freeze( false );
    35                 std::string ret = std::string (os.str(), os.pcount());
     31        Label LabelGenerator::newLabel( std::string suffix ) {
     32                std::ostringstream os;
     33                os << "__L" << current++ << "__" << suffix;
     34                std::string ret = os.str();
    3635                return Label( ret );
    3736        }
  • src/ControlStruct/LabelGenerator.h

    reb50842 r937e51d  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue May 19 15:33:20 2015
    13 // Update Count     : 3
     11// Last Modified By : Rob Schluntz
     12// Last Modified On : Wed Jun 03 14:16:26 2015
     13// Update Count     : 5
    1414//
    1515
     
    1818
    1919#include "SynTree/SynTree.h"
     20#include <string>
    2021
    2122namespace ControlStruct {
     
    2324          public:
    2425                static LabelGenerator *getGenerator();
    25                 Label newLabel();
     26                Label newLabel(std::string suffix = "");
    2627                void reset() { current = 0; }
    2728                void rewind() { current--; }
  • src/ControlStruct/LabelTypeChecker.cc

    reb50842 r937e51d  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue May 19 15:32:15 2015
    13 // Update Count     : 2
     11// Last Modified By : Rob Schluntz
     12// Last Modified On : Wed Jun 24 16:24:48 2015
     13// Update Count     : 3
    1414//
    1515
     
    2929                NameExpr *fname;
    3030                if ( ((fname = dynamic_cast<NameExpr *>(untypedExpr->get_function())) != 0)
    31                          && fname->get_name() == std::string("LabAddress") )
     31                         && fname->get_name() == std::string("&&") )
    3232                        std::cerr << "Taking the label of an address." << std::endl;
    3333                else {
  • src/ControlStruct/MLEMutator.cc

    reb50842 r937e51d  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue May 19 15:32:26 2015
    13 // Update Count     : 2
     11// Last Modified By : Rob Schluntz
     12// Last Modified On : Thu Jun 04 15:12:33 2015
     13// Update Count     : 173
    1414//
    1515
     
    1919#include "MLEMutator.h"
    2020#include "SynTree/Statement.h"
     21#include "SynTree/Expression.h"
    2122
    2223namespace ControlStruct {
     
    2627        }
    2728
    28         CompoundStmt* MLEMutator::mutate( CompoundStmt *cmpndStmt ) {
    29                 bool labeledBlock = false;
    30                 if ( !((cmpndStmt->get_labels()).empty()) ) {
    31                         labeledBlock = true;
    32                         enclosingBlocks.push_back( Entry( cmpndStmt ) );
    33                 } // if
    34 
    35                 std::list< Statement * > &kids = cmpndStmt->get_kids();
     29        // break labels have to come after the statement they break out of,
     30        // so mutate a statement, then if they inform us through the breakLabel field
     31        // tha they need a place to jump to on a break statement, add the break label
     32        // to the body of statements
     33        void MLEMutator::fixBlock( std::list< Statement * > &kids ) {
    3634                for ( std::list< Statement * >::iterator k = kids.begin(); k != kids.end(); k++ ) {
    3735                        *k = (*k)->acceptMutator(*this);
    3836
    3937                        if ( ! get_breakLabel().empty() ) {
    40                                 std::list< Statement * >::iterator next = k; next++;
     38                                std::list< Statement * >::iterator next = k+1;
    4139                                if ( next == kids.end() ) {
    4240                                        std::list<Label> ls; ls.push_back( get_breakLabel() );
    4341                                        kids.push_back( new NullStmt( ls ) );
    44                                 } else
     42                                } else {
    4543                                        (*next)->get_labels().push_back( get_breakLabel() );
     44                                }
    4645
    4746                                set_breakLabel("");
    4847                        } // if
    4948                } // for
     49        }
     50
     51        CompoundStmt* MLEMutator::mutate( CompoundStmt *cmpndStmt ) {
     52                bool labeledBlock = !(cmpndStmt->get_labels().empty());
     53                if ( labeledBlock ) {
     54                        Label brkLabel = generator->newLabel("blockBreak");
     55                        enclosingBlocks.push_back( Entry( cmpndStmt, brkLabel ) );
     56                } // if
     57
     58                // a child statement may set the break label
     59                // - if they do, attach it to the next statement
     60                std::list< Statement * > &kids = cmpndStmt->get_kids();
     61                fixBlock( kids );
    5062
    5163                if ( labeledBlock ) {
    5264                        assert( ! enclosingBlocks.empty() );
    53                         if ( ! enclosingBlocks.back().get_breakExit().empty() )
    54                                 set_breakLabel( enclosingBlocks.back().get_breakExit() );
     65                        if ( ! enclosingBlocks.back().useBreakExit().empty() ) {
     66                                set_breakLabel( enclosingBlocks.back().useBreakExit() );
     67                        }
    5568                        enclosingBlocks.pop_back();
    5669                } // if
    5770
    58                 //mutateAll( cmpndStmt->get_kids(), *this );
    5971                return cmpndStmt;
    6072        }
    6173
    62         Statement *MLEMutator::mutate( WhileStmt *whileStmt ) {
    63                 enclosingLoops.push_back( Entry( whileStmt ) );
    64                 whileStmt->set_body ( whileStmt->get_body()->acceptMutator( *this ) );
    65 
     74        template< typename LoopClass >
     75        Statement *MLEMutator::handleLoopStmt( LoopClass *loopStmt ) {
     76                // remember this as the most recent enclosing loop, then mutate
     77                // the body of the loop -- this will determine whether brkLabel
     78                // and contLabel are used with branch statements
     79                // and will recursively do the same to nested loops
     80                Label brkLabel = generator->newLabel("loopBreak");
     81                Label contLabel = generator->newLabel("loopContinue");
     82                enclosingLoops.push_back( Entry( loopStmt, brkLabel, contLabel ) );
     83                loopStmt->set_body ( loopStmt->get_body()->acceptMutator( *this ) );
     84
     85                // sanity check that the enclosing loops have been popped correctly
    6686                Entry &e = enclosingLoops.back();
    67                 assert ( e == whileStmt );
    68                 whileStmt->set_body( mutateLoop( whileStmt->get_body(), e ) );
     87                assert ( e == loopStmt );
     88
     89                // this will take the necessary steps to add definitions of the previous
     90                // two labels, if they are used.
     91                loopStmt->set_body( mutateLoop( loopStmt->get_body(), e ) );
    6992                enclosingLoops.pop_back();
    7093
    71                 return whileStmt;
    72         }
    73 
    74         Statement *MLEMutator::mutate( ForStmt *forStmt ) {
    75                 enclosingLoops.push_back( Entry( forStmt ) );
    76                 maybeMutate( forStmt->get_body(), *this );
    77 
    78                 Entry &e = enclosingLoops.back();
    79                 assert ( e == forStmt );
    80                 forStmt->set_body( mutateLoop( forStmt->get_body(), e ) );
    81                 enclosingLoops.pop_back();
    82 
    83                 return forStmt;
     94                return loopStmt;
     95        }
     96
     97        Statement *MLEMutator::mutate( CaseStmt *caseStmt ) {
     98                caseStmt->set_condition( maybeMutate( caseStmt->get_condition(), *this ) );
     99                fixBlock( caseStmt->get_statements() );
     100
     101                return caseStmt;
     102        }
     103
     104        template< typename SwitchClass >
     105        Statement *MLEMutator::handleSwitchStmt( SwitchClass *switchStmt ) {
     106                // generate a label for breaking out of a labeled switch
     107                Label brkLabel = generator->newLabel("switchBreak");
     108                enclosingSwitches.push_back( Entry(switchStmt, brkLabel) );
     109                mutateAll( switchStmt->get_branches(), *this );
     110
     111                Entry &e = enclosingSwitches.back();
     112                assert ( e == switchStmt );
     113
     114                // only generate break label if labeled break is used
     115                if (e.isBreakUsed()) {
     116                        // for the purposes of keeping switch statements uniform (i.e. all statements that are
     117                        // direct children of a switch should be CastStmts), append the exit label + break to the
     118                        // last case statement; create a default case if there are no cases
     119                        std::list< Statement * > &branches = switchStmt->get_branches();
     120                        if ( branches.empty() ) {
     121                                branches.push_back( CaseStmt::makeDefault() );
     122                        }
     123
     124                        if ( CaseStmt * c = dynamic_cast< CaseStmt * >( branches.back() ) ) {
     125                                std::list<Label> temp; temp.push_back( brkLabel );
     126                                c->get_statements().push_back( new BranchStmt( temp, Label(""), BranchStmt::Break ) );
     127                        } else assert(0); // as of this point, all branches of a switch are still CaseStmts
     128                }
     129
     130                assert ( enclosingSwitches.back() == switchStmt );
     131                enclosingSwitches.pop_back();
     132                return switchStmt;
    84133        }
    85134
    86135        Statement *MLEMutator::mutate( BranchStmt *branchStmt ) throw ( SemanticError ) {
     136                std::string originalTarget = branchStmt->get_originalTarget();
     137
    87138                if ( branchStmt->get_type() == BranchStmt::Goto )
    88139                        return branchStmt;
    89140
    90141                // test if continue target is a loop
    91                 if ( branchStmt->get_type() == BranchStmt::Continue && enclosingLoops.empty() )
    92                         throw SemanticError( "'continue' outside a loop" );
     142                if ( branchStmt->get_type() == BranchStmt::Continue) {
     143                        if ( enclosingLoops.empty() ) {
     144                                throw SemanticError( "'continue' outside a loop" );
     145                        } else if ( std::find( enclosingLoops.begin(), enclosingLoops.end(), (*targetTable)[branchStmt->get_target()] ) == enclosingLoops.end() ) {
     146                                throw SemanticError( "'continue' target label must be an enclosing loop: " + originalTarget );
     147                        }
     148                }
    93149
    94150                if ( branchStmt->get_type() == BranchStmt::Break && (enclosingLoops.empty() && enclosingSwitches.empty() && enclosingBlocks.empty() ) )
     
    98154
    99155                if ( targetTable->find( branchStmt->get_target() ) == targetTable->end() )
    100                         throw SemanticError("The label defined in the exit loop statement does not exist." );  // shouldn't happen (since that's already checked)
     156                        throw SemanticError("The label defined in the exit loop statement does not exist: " + originalTarget );  // shouldn't happen (since that's already checked)
    101157
    102158                std::list< Entry >::iterator check;
     
    106162                                // neither in loop nor in block, checking if in switch/choose
    107163                                if ( (check = std::find( enclosingSwitches.begin(), enclosingSwitches.end(), (*targetTable)[branchStmt->get_target()] )) == enclosingSwitches.end() )
    108                                         throw SemanticError("The target specified in the exit loop statement does not correspond to an enclosing loop.");
    109 
     164                                        throw SemanticError("The target specified in the exit loop statement does not correspond to an enclosing control structure: " + originalTarget );
     165
     166                // what about exiting innermost block or switch???
    110167                if ( enclosingLoops.back() == (*check) )
    111168                        return branchStmt;                              // exit the innermost loop (labels unnecessary)
    112169
    113                 Label newLabel;
     170                // branch error checks, get the appropriate label name and create a goto
     171                Label exitLabel;
    114172                switch ( branchStmt->get_type() ) {
    115173                  case BranchStmt::Break:
    116                         if ( check->get_breakExit() != "" )
    117                                 newLabel = check->get_breakExit();
    118                         else {
    119                                 newLabel = generator->newLabel();
    120                                 check->set_breakExit( newLabel );
    121                         } // if
    122                         break;
     174                                assert( check->useBreakExit() != "");
     175                                exitLabel = check->useBreakExit();
     176                                break;
    123177                  case BranchStmt::Continue:
    124                         if ( check->get_contExit() != "" )
    125                                 newLabel = check->get_contExit();
    126                         else {
    127                                 newLabel = generator->newLabel();
    128                                 check->set_contExit( newLabel );
    129                         } // if
    130                         break;
     178                                assert( check->useContExit() != "");
     179                                exitLabel = check->useContExit();
     180                                break;
    131181                  default:
    132                         return 0;                                       // shouldn't be here
     182                                assert(0);                                      // shouldn't be here
    133183                } // switch
    134184
    135                 return new BranchStmt( std::list<Label>(), newLabel, BranchStmt::Goto );
    136         }
    137 
    138 
    139         Statement *MLEMutator::mutate( SwitchStmt *switchStmt ) {
    140                 Label brkLabel = generator->newLabel();
    141                 enclosingSwitches.push_back( Entry(switchStmt, "", brkLabel) );
    142                 mutateAll( switchStmt->get_branches(), *this ); {
    143                         // check if this is necessary (if there is a break to this point, otherwise do not generate
    144                         std::list<Label> temp; temp.push_back( brkLabel );
    145                         switchStmt->get_branches().push_back( new BranchStmt( temp, Label(""), BranchStmt::Break ) );
    146                 }
    147                 assert ( enclosingSwitches.back() == switchStmt );
    148                 enclosingSwitches.pop_back();
    149                 return switchStmt;
    150         }
    151 
    152         Statement *MLEMutator::mutate( ChooseStmt *switchStmt ) {
    153                 Label brkLabel = generator->newLabel();
    154                 enclosingSwitches.push_back( Entry(switchStmt,"", brkLabel) );
    155                 mutateAll( switchStmt->get_branches(), *this ); {
    156                         // check if this is necessary (if there is a break to this point, otherwise do not generate
    157                         std::list<Label> temp; temp.push_back( brkLabel );
    158                         switchStmt->get_branches().push_back( new BranchStmt( temp, Label(""), BranchStmt::Break ) );
    159                 }
    160                 assert ( enclosingSwitches.back() == switchStmt );
    161                 enclosingSwitches.pop_back();
    162                 return switchStmt;
     185                return new BranchStmt( std::list<Label>(), exitLabel, BranchStmt::Goto );
    163186        }
    164187
    165188        Statement *MLEMutator::mutateLoop( Statement *bodyLoop, Entry &e ) {
     189                // ensure loop body is a block
    166190                CompoundStmt *newBody;
    167191                if ( ! (newBody = dynamic_cast<CompoundStmt *>( bodyLoop )) ) {
     
    170194                } // if
    171195
    172                 Label endLabel = e.get_contExit();
    173 
    174                 if ( e.get_breakExit() != "" ) {
    175                         if ( endLabel == "" ) endLabel = generator->newLabel();
    176                         // check for whether this label is used or not, so as to not generate extraneous gotos
    177                         if (e.breakExitUsed)
    178                                 newBody->get_kids().push_back( new BranchStmt( std::list< Label >(), endLabel, BranchStmt::Goto ) );
    179                         // xxx
    180                         //std::list< Label > ls; ls.push_back( e.get_breakExit() );
    181                         set_breakLabel( e.get_breakExit() );
    182                         //newBody->get_kids().push_back( new BranchStmt( ls, "", BranchStmt::Break ) );
    183                 } // if
    184 
    185                 if ( e.get_breakExit() != "" || e.get_contExit() != "" ) {
    186                         if (dynamic_cast< NullStmt *>( newBody->get_kids().back() ))
    187                                 newBody->get_kids().back()->get_labels().push_back( endLabel );
    188                         else {
    189                                 std::list < Label > ls; ls.push_back( endLabel );
    190                                 newBody->get_kids().push_back( new NullStmt( ls ) );
    191                         } // if
    192                 } // if
     196                // only generate these when needed
     197
     198                if ( e.isContUsed() ) {
     199                        // continue label goes in the body as the last statement
     200                        std::list< Label > labels; labels.push_back( e.useContExit() );
     201                        newBody->get_kids().push_back( new NullStmt( labels ) );                       
     202                }
     203
     204                if ( e.isBreakUsed() ) {
     205                        // break label goes after the loop -- it'll get set by the
     206                        // outer mutator if we do this
     207                        set_breakLabel( e.useBreakExit() );                     
     208                }
    193209
    194210                return newBody;
    195211        }
    196212
    197         //*** Entry's methods
    198         void MLEMutator::Entry::set_contExit( Label l ) {
    199                 assert ( contExit == "" || contExit == l );
    200                 contExit = l;
    201         }
    202 
    203         void MLEMutator::Entry::set_breakExit( Label l ) {
    204                 assert ( breakExit == "" || breakExit == l );
    205                 breakExit = l;
    206         }
     213        Statement *MLEMutator::mutate( WhileStmt *whileStmt ) {
     214                return handleLoopStmt( whileStmt );
     215        }
     216
     217        Statement *MLEMutator::mutate( ForStmt *forStmt ) {
     218                return handleLoopStmt( forStmt );
     219        }
     220
     221        Statement *MLEMutator::mutate( SwitchStmt *switchStmt ) {
     222                return handleSwitchStmt( switchStmt );
     223        }
     224
     225        Statement *MLEMutator::mutate( ChooseStmt *switchStmt ) {
     226                return handleSwitchStmt( switchStmt );         
     227        }
     228
    207229} // namespace ControlStruct
    208230
  • src/ControlStruct/MLEMutator.h

    reb50842 r937e51d  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue May 19 15:32:39 2015
    13 // Update Count     : 3
     11// Last Modified By : Rob Schluntz
     12// Last Modified On : Wed Jun 03 15:06:36 2015
     13// Update Count     : 25
    1414//
    1515
     
    3838                Statement *mutate( BranchStmt *branchStmt ) throw ( SemanticError );
    3939
     40                Statement *mutate( CaseStmt *caseStmt );
    4041                Statement *mutate( SwitchStmt *switchStmt );
    4142                Statement *mutate( ChooseStmt *switchStmt );
     
    4849                class Entry {
    4950                  public:
    50                         explicit Entry( Statement *_loop = 0, Label _contExit = Label(""), Label _breakExit = Label("") ) :
    51                                 loop( _loop ), contExit( _contExit ), breakExit( _breakExit ), contExitUsed( false ), breakExitUsed( false ) {}
     51                        explicit Entry( Statement *_loop, Label _breakExit, Label _contExit = Label("") ) :
     52                                loop( _loop ), breakExit( _breakExit ), contExit( _contExit ), breakUsed(false), contUsed(false) {}
    5253
    5354                        bool operator==( const Statement *stmt ) { return ( loop == stmt ); }
     
    5859                        Statement *get_loop() const { return loop; }
    5960
    60                         Label get_contExit() const { return contExit; }
    61                         void set_contExit( Label );
     61                        Label useContExit() { contUsed = true; return contExit; }
     62                        Label useBreakExit() { breakUsed = true; return breakExit; }
    6263
    63                         Label get_breakExit() const { return breakExit; }
    64                         void set_breakExit( Label );
     64                        bool isContUsed() const { return contUsed; }
     65                        bool isBreakUsed() const { return breakUsed; }
    6566
    6667                  private:
    6768                        Statement *loop;
    68                         Label contExit, breakExit;
    69                   public: // hack, provide proper [sg]etters
    70                         bool contExitUsed, breakExitUsed;
     69                        Label breakExit, contExit;
     70                        bool breakUsed, contUsed;
    7171                };
    7272
     
    7575                Label breakLabel;
    7676                LabelGenerator *generator;
     77
     78                template< typename LoopClass >
     79                Statement *handleLoopStmt( LoopClass *loopStmt );
     80
     81                template< typename SwitchClass >
     82                Statement *handleSwitchStmt( SwitchClass *switchStmt );
     83
     84                void fixBlock( std::list< Statement * > &kids );
    7785        };
    7886} // namespace ControlStruct
  • src/ControlStruct/Mutate.cc

    reb50842 r937e51d  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue May 19 15:32:52 2015
    13 // Update Count     : 2
     11// Last Modified By : Rob Schluntz
     12// Last Modified On : Wed Jun 03 23:08:43 2015
     13// Update Count     : 5
    1414//
    1515
     
    3737        void mutate( std::list< Declaration * > translationUnit ) {
    3838                // ForExprMutator formut;
     39
     40                // normalizes label definitions and generates multi-level
     41                // exit labels
    3942                LabelFixer lfix;
     43
     44                // transform choose statements into switch statements
    4045                ChooseMutator chmut;
     46
     47                // expand case ranges and turn fallthru into a null statement
    4148                CaseRangeMutator ranges;  // has to run after ChooseMutator
     49
    4250                //ExceptMutator exc;
    4351                // LabelTypeChecker lbl;
  • src/ControlStruct/module.mk

    reb50842 r937e51d  
     1######################### -*- Mode: Makefile-Gmake -*- ########################
     2##
     3## Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
     4##
     5## The contents of this file are covered under the licence agreement in the
     6## file "LICENCE" distributed with Cforall.
     7##
     8## module.mk --
     9##
     10## Author           : Richard C. Bilson
     11## Created On       : Mon Jun  1 17:49:17 2015
     12## Last Modified By : Peter A. Buhr
     13## Last Modified On : Mon Jun  1 17:51:45 2015
     14## Update Count     : 1
     15###############################################################################
     16
    117SRC +=  ControlStruct/LabelGenerator.cc \
    2         ControlStruct/LabelFixer.cc \
     18        ControlStruct/LabelFixer.cc \
    319        ControlStruct/MLEMutator.cc \
    420        ControlStruct/CaseRangeMutator.cc \
     
    622        ControlStruct/ChooseMutator.cc \
    723        ControlStruct/ForExprMutator.cc \
    8         ControlStruct/LabelTypeChecker.cc \
    9         $(NULL)
     24        ControlStruct/LabelTypeChecker.cc
    1025
Note: See TracChangeset for help on using the changeset viewer.