Changeset 937e51d for src/ControlStruct/MLEMutator.cc
- Timestamp:
- Jun 26, 2015, 4:00:26 PM (10 years ago)
- 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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ControlStruct/MLEMutator.cc
reb50842 r937e51d 9 9 // Author : Rodolfo G. Esteves 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Peter A. Buhr12 // Last Modified On : T ue May 19 15:32:26201513 // Update Count : 211 // Last Modified By : Rob Schluntz 12 // Last Modified On : Thu Jun 04 15:12:33 2015 13 // Update Count : 173 14 14 // 15 15 … … 19 19 #include "MLEMutator.h" 20 20 #include "SynTree/Statement.h" 21 #include "SynTree/Expression.h" 21 22 22 23 namespace ControlStruct { … … 26 27 } 27 28 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 ) { 36 34 for ( std::list< Statement * >::iterator k = kids.begin(); k != kids.end(); k++ ) { 37 35 *k = (*k)->acceptMutator(*this); 38 36 39 37 if ( ! get_breakLabel().empty() ) { 40 std::list< Statement * >::iterator next = k ; next++;38 std::list< Statement * >::iterator next = k+1; 41 39 if ( next == kids.end() ) { 42 40 std::list<Label> ls; ls.push_back( get_breakLabel() ); 43 41 kids.push_back( new NullStmt( ls ) ); 44 } else 42 } else { 45 43 (*next)->get_labels().push_back( get_breakLabel() ); 44 } 46 45 47 46 set_breakLabel(""); 48 47 } // if 49 48 } // 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 ); 50 62 51 63 if ( labeledBlock ) { 52 64 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 } 55 68 enclosingBlocks.pop_back(); 56 69 } // if 57 70 58 //mutateAll( cmpndStmt->get_kids(), *this );59 71 return cmpndStmt; 60 72 } 61 73 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 66 86 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 ) ); 69 92 enclosingLoops.pop_back(); 70 93 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; 84 133 } 85 134 86 135 Statement *MLEMutator::mutate( BranchStmt *branchStmt ) throw ( SemanticError ) { 136 std::string originalTarget = branchStmt->get_originalTarget(); 137 87 138 if ( branchStmt->get_type() == BranchStmt::Goto ) 88 139 return branchStmt; 89 140 90 141 // 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 } 93 149 94 150 if ( branchStmt->get_type() == BranchStmt::Break && (enclosingLoops.empty() && enclosingSwitches.empty() && enclosingBlocks.empty() ) ) … … 98 154 99 155 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) 101 157 102 158 std::list< Entry >::iterator check; … … 106 162 // neither in loop nor in block, checking if in switch/choose 107 163 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??? 110 167 if ( enclosingLoops.back() == (*check) ) 111 168 return branchStmt; // exit the innermost loop (labels unnecessary) 112 169 113 Label newLabel; 170 // branch error checks, get the appropriate label name and create a goto 171 Label exitLabel; 114 172 switch ( branchStmt->get_type() ) { 115 173 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; 123 177 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; 131 181 default: 132 return 0; // shouldn't be here182 assert(0); // shouldn't be here 133 183 } // switch 134 184 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 ); 163 186 } 164 187 165 188 Statement *MLEMutator::mutateLoop( Statement *bodyLoop, Entry &e ) { 189 // ensure loop body is a block 166 190 CompoundStmt *newBody; 167 191 if ( ! (newBody = dynamic_cast<CompoundStmt *>( bodyLoop )) ) { … … 170 194 } // if 171 195 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 } 193 209 194 210 return newBody; 195 211 } 196 212 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 207 229 } // namespace ControlStruct 208 230
Note:
See TracChangeset
for help on using the changeset viewer.