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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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
Note: See TracChangeset for help on using the changeset viewer.