Changeset 27de955
- Timestamp:
- Jun 3, 2015, 3:19:29 PM (9 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:
- 4162aea9
- Parents:
- 954463b8
- Location:
- src/ControlStruct
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ControlStruct/LabelGenerator.cc
r954463b8 r27de955 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 : Tue May 19 15:32:04201513 // Update Count : 211 // Last Modified By : Rob Schluntz 12 // Last Modified On : Wed Jun 03 14:23:26 2015 13 // Update Count : 9 14 14 // 15 15 … … 29 29 } 30 30 31 Label LabelGenerator::newLabel( ) {31 Label LabelGenerator::newLabel(std::string suffix) { 32 32 std::ostrstream os; 33 os << "__L" << current++ << "__" ;// << std::ends;33 os << "__L" << current++ << "__" << suffix; 34 34 os.freeze( false ); 35 35 std::string ret = std::string (os.str(), os.pcount()); -
src/ControlStruct/LabelGenerator.h
r954463b8 r27de955 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 : Tue May 19 15:33:20201513 // Update Count : 311 // Last Modified By : Rob Schluntz 12 // Last Modified On : Wed Jun 03 14:16:26 2015 13 // Update Count : 5 14 14 // 15 15 … … 18 18 19 19 #include "SynTree/SynTree.h" 20 #include <string> 20 21 21 22 namespace ControlStruct { … … 23 24 public: 24 25 static LabelGenerator *getGenerator(); 25 Label newLabel( );26 Label newLabel(std::string suffix = ""); 26 27 void reset() { current = 0; } 27 28 void rewind() { current--; } -
src/ControlStruct/MLEMutator.cc
r954463b8 r27de955 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Rob Schluntz 12 // Last Modified On : Tue Jun 02 13:43:01201513 // Update Count : 9212 // Last Modified On : Wed Jun 03 15:09:27 2015 13 // Update Count : 170 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 // a child statement may set the break label 36 // - if they do, attach it to the next statement 37 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 ) { 38 34 for ( std::list< Statement * >::iterator k = kids.begin(); k != kids.end(); k++ ) { 39 35 *k = (*k)->acceptMutator(*this); … … 51 47 } // if 52 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(); 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 ); 53 62 54 63 if ( labeledBlock ) { 55 64 assert( ! enclosingBlocks.empty() ); 56 if ( ! enclosingBlocks.back(). get_breakExit().empty() ) {57 set_breakLabel( enclosingBlocks.back(). get_breakExit() );65 if ( ! enclosingBlocks.back().useBreakExit().empty() ) { 66 set_breakLabel( enclosingBlocks.back().useBreakExit() ); 58 67 } 59 68 enclosingBlocks.pop_back(); … … 63 72 } 64 73 65 Statement *MLEMutator::mutate( WhileStmt *whileStmt ) { 66 enclosingLoops.push_back( Entry( whileStmt ) ); 67 whileStmt->set_body ( whileStmt->get_body()->acceptMutator( *this ) ); 68 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 do SOMETHING with branch statements 78 // and will recursively do the same to nested loops 79 Label brkLabel = generator->newLabel("loopBreak"); 80 Label contLabel = generator->newLabel("loopContinue"); 81 enclosingLoops.push_back( Entry( loopStmt, brkLabel, contLabel ) ); 82 loopStmt->set_body ( loopStmt->get_body()->acceptMutator( *this ) ); 83 84 // sanity check that the enclosing loops have been popped correctly 69 85 Entry &e = enclosingLoops.back(); 70 assert ( e == whileStmt ); 71 whileStmt->set_body( mutateLoop( whileStmt->get_body(), e ) ); 86 assert ( e == loopStmt ); 87 88 // generate labels as needed 89 loopStmt->set_body( mutateLoop( loopStmt->get_body(), e ) ); 72 90 enclosingLoops.pop_back(); 73 91 74 return whileStmt; 75 } 76 77 Statement *MLEMutator::mutate( ForStmt *forStmt ) { 78 enclosingLoops.push_back( Entry( forStmt ) ); 79 forStmt->set_body( maybeMutate( forStmt->get_body(), *this ) ); 80 81 Entry &e = enclosingLoops.back(); 82 assert ( e == forStmt ); 83 forStmt->set_body( mutateLoop( forStmt->get_body(), e ) ); 84 enclosingLoops.pop_back(); 85 86 return forStmt; 92 return loopStmt; 93 } 94 95 Statement *MLEMutator::mutate( CaseStmt *caseStmt ) { 96 caseStmt->set_condition( maybeMutate( caseStmt->get_condition(), *this ) ); 97 fixBlock( caseStmt->get_statements() ); 98 99 return caseStmt; 100 } 101 102 template< typename SwitchClass > 103 Statement *MLEMutator::handleSwitchStmt( SwitchClass *switchStmt ) { 104 // generate a label for breaking out of a labeled switch 105 Label brkLabel = generator->newLabel("switchBreak"); 106 enclosingSwitches.push_back( Entry(switchStmt, brkLabel) ); 107 mutateAll( switchStmt->get_branches(), *this ); 108 109 Entry &e = enclosingSwitches.back(); 110 assert ( e == switchStmt ); 111 112 // only generate break label if labeled break is used 113 if (e.isBreakUsed()) { 114 // for the purposes of keeping switch statements uniform (i.e. all statements that are 115 // direct children of a switch should be CastStmts), append the exit label + break to the 116 // last case statement; create a default case if there are no cases 117 std::list< Statement * > &branches = switchStmt->get_branches(); 118 if ( branches.empty() ) { 119 branches.push_back( CaseStmt::makeDefault() ); 120 } 121 122 if ( CaseStmt * c = dynamic_cast< CaseStmt * >( branches.back() ) ) { 123 std::list<Label> temp; temp.push_back( brkLabel ); 124 c->get_statements().push_back( new BranchStmt( temp, Label(""), BranchStmt::Break ) ); 125 } else assert(0); // as of this point, all branches of a switch are still CaseStmts 126 } 127 128 assert ( enclosingSwitches.back() == switchStmt ); 129 enclosingSwitches.pop_back(); 130 return switchStmt; 87 131 } 88 132 … … 118 162 throw SemanticError("The target specified in the exit loop statement does not correspond to an enclosing control structure: " + originalTarget ); 119 163 164 // what about exiting innermost block or switch??? 120 165 if ( enclosingLoops.back() == (*check) ) 121 166 return branchStmt; // exit the innermost loop (labels unnecessary) 122 167 123 Label newLabel; 168 // branch error checks, get the appropriate label name and create a goto 169 Label exitLabel; 124 170 switch ( branchStmt->get_type() ) { 125 171 case BranchStmt::Break: 126 if ( check->get_breakExit() != "" ) { 127 newLabel = check->get_breakExit(); 128 } else { 129 newLabel = generator->newLabel(); 130 check->set_breakExit( newLabel ); 131 } // if 172 assert( check->useBreakExit() != ""); 173 exitLabel = check->useBreakExit(); 132 174 break; 133 175 case BranchStmt::Continue: 134 if ( check->get_contExit() != "" ) { 135 newLabel = check->get_contExit(); 136 } else { 137 newLabel = generator->newLabel(); 138 check->set_contExit( newLabel ); 139 } // if 176 assert( check->useContExit() != ""); 177 exitLabel = check->useContExit(); 140 178 break; 141 179 default: 142 return 0; // shouldn't be here180 assert(0); // shouldn't be here 143 181 } // switch 144 182 145 return new BranchStmt( std::list<Label>(), newLabel, BranchStmt::Goto ); 146 } 147 148 template< typename SwitchClass > 149 Statement *handleSwitchStmt( SwitchClass *switchStmt, MLEMutator &mutator ) { 150 // set up some aliases so that the rest of the code isn't messy 151 typedef MLEMutator::Entry Entry; 152 LabelGenerator *generator = mutator.generator; 153 std::list< Entry > &enclosingSwitches = mutator.enclosingSwitches; 154 155 Label brkLabel = generator->newLabel(); 156 enclosingSwitches.push_back( Entry(switchStmt, "", brkLabel) ); 157 mutateAll( switchStmt->get_branches(), mutator ); 158 { 159 // check if this is necessary (if there is a break to this point, otherwise do not generate 160 161 // for the purposes of keeping switch statements uniform (i.e. all statements that are 162 // direct children of a switch should be CastStmts), append the exit label + break to the 163 // last case statement; create a default case if there are no cases 164 std::list< Statement * > &branches = switchStmt->get_branches(); 165 if ( branches.empty() ) { 166 branches.push_back( CaseStmt::makeDefault() ); 167 } 168 169 if ( CaseStmt * c = dynamic_cast< CaseStmt * >( branches.back() ) ) { 170 std::list<Label> temp; temp.push_back( brkLabel ); 171 c->get_statements().push_back( new BranchStmt( temp, Label(""), BranchStmt::Break ) ); 172 } else assert(0); 173 } 174 assert ( enclosingSwitches.back() == switchStmt ); 175 enclosingSwitches.pop_back(); 176 return switchStmt; 177 } 178 179 Statement *MLEMutator::mutate( SwitchStmt *switchStmt ) { 180 return handleSwitchStmt( switchStmt, *this ); 181 } 182 183 Statement *MLEMutator::mutate( ChooseStmt *switchStmt ) { 184 return handleSwitchStmt( switchStmt, *this ); 183 return new BranchStmt( std::list<Label>(), exitLabel, BranchStmt::Goto ); 185 184 } 186 185 … … 193 192 } // if 194 193 195 Label endLabel = e.get_contExit(); 196 197 if ( e.get_breakExit() != "" ) { 198 if ( endLabel == "" ) endLabel = generator->newLabel(); 199 // check for whether this label is used or not, so as to not generate extraneous gotos 200 if (e.breakExitUsed) 201 newBody->get_kids().push_back( new BranchStmt( std::list< Label >(), endLabel, BranchStmt::Goto ) ); 202 // xxx 203 //std::list< Label > ls; ls.push_back( e.get_breakExit() ); 204 set_breakLabel( e.get_breakExit() ); 205 //newBody->get_kids().push_back( new BranchStmt( ls, "", BranchStmt::Break ) ); 206 } // if 207 208 if ( e.get_breakExit() != "" || e.get_contExit() != "" ) { 209 if (dynamic_cast< NullStmt *>( newBody->get_kids().back() )) 210 newBody->get_kids().back()->get_labels().push_back( endLabel ); 211 else { 212 std::list < Label > ls; ls.push_back( endLabel ); 213 newBody->get_kids().push_back( new NullStmt( ls ) ); 214 } // if 215 } // if 194 // only generate these when needed 195 196 if ( e.isContUsed() ) { 197 // continue label goes in the body as the last statement 198 std::list< Label > labels; labels.push_back( e.useContExit() ); 199 newBody->get_kids().push_back( new NullStmt( labels ) ); 200 } 201 202 if ( e.isBreakUsed() ) { 203 // break label goes after the loop -- it'll get set by the 204 // outer mutator if we do this 205 set_breakLabel( e.useBreakExit() ); 206 } 216 207 217 208 return newBody; 218 209 } 219 210 220 //*** Entry's methods - ensure these labels can be set at most once 221 void MLEMutator::Entry::set_contExit( Label l ) { 222 assert ( contExit == "" || contExit == l ); 223 contExit = l; 224 } 225 226 void MLEMutator::Entry::set_breakExit( Label l ) { 227 assert ( breakExit == "" || breakExit == l ); 228 breakExit = l; 229 } 211 Statement *MLEMutator::mutate( WhileStmt *whileStmt ) { 212 return handleLoopStmt( whileStmt ); 213 } 214 215 Statement *MLEMutator::mutate( ForStmt *forStmt ) { 216 return handleLoopStmt( forStmt ); 217 } 218 219 Statement *MLEMutator::mutate( SwitchStmt *switchStmt ) { 220 return handleSwitchStmt( switchStmt ); 221 } 222 223 Statement *MLEMutator::mutate( ChooseStmt *switchStmt ) { 224 return handleSwitchStmt( switchStmt ); 225 } 226 230 227 } // namespace ControlStruct 231 228 -
src/ControlStruct/MLEMutator.h
r954463b8 r27de955 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Rob Schluntz 12 // Last Modified On : Tue May 26 15:04:21201513 // Update Count : 712 // Last Modified On : Wed Jun 03 15:06:36 2015 13 // Update Count : 25 14 14 // 15 15 … … 38 38 Statement *mutate( BranchStmt *branchStmt ) throw ( SemanticError ); 39 39 40 Statement *mutate( CaseStmt *caseStmt ); 40 41 Statement *mutate( SwitchStmt *switchStmt ); 41 42 Statement *mutate( ChooseStmt *switchStmt ); … … 48 49 class Entry { 49 50 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) {} 52 53 53 54 bool operator==( const Statement *stmt ) { return ( loop == stmt ); } … … 58 59 Statement *get_loop() const { return loop; } 59 60 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; } 62 63 63 Label get_breakExit() const { return breakExit; }64 void set_breakExit( Label );64 bool isContUsed() const { return contUsed; } 65 bool isBreakUsed() const { return breakUsed; } 65 66 66 67 private: 67 68 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; 71 71 }; 72 72 … … 76 76 LabelGenerator *generator; 77 77 78 template< typename LoopClass > 79 Statement *handleLoopStmt( LoopClass *loopStmt ); 80 78 81 template< typename SwitchClass > 79 friend Statement *handleSwitchStmt( SwitchClass *switchStmt, MLEMutator &mutator ); 82 Statement *handleSwitchStmt( SwitchClass *switchStmt ); 83 84 void fixBlock( std::list< Statement * > &kids ); 80 85 }; 81 86 } // namespace ControlStruct
Note: See TracChangeset
for help on using the changeset viewer.