Changeset 1cdfa82 for src/ControlStruct
- Timestamp:
- Apr 25, 2018, 4:55:53 PM (6 years ago)
- Branches:
- new-env, with_gc
- Children:
- 42107b4
- Parents:
- 2efe4b8 (diff), 9d5fb67 (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. - Location:
- src/ControlStruct
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
src/ControlStruct/ExceptTranslate.cc
r2efe4b8 r1cdfa82 34 34 #include "SynTree/Statement.h" // for CompoundStmt, CatchStmt, ThrowStmt 35 35 #include "SynTree/Type.h" // for FunctionType, Type, noQualifiers 36 #include "SynTree/ VarExprReplacer.h" // for VarExprReplacer, VarExprReplace...36 #include "SynTree/DeclReplacer.h" // for DeclReplacer 37 37 #include "SynTree/Visitor.h" // for acceptAll 38 38 … … 311 311 // Update variables in the body to point to this local copy. 312 312 { 313 VarExprReplacer::DeclMap mapping;313 DeclReplacer::DeclMap mapping; 314 314 mapping[ handler_decl ] = local_except; 315 VarExprReplacer::replace( handler->body, mapping );315 DeclReplacer::replace( handler->body, mapping ); 316 316 } 317 317 -
src/ControlStruct/MLEMutator.cc
r2efe4b8 r1cdfa82 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Aug 4 11:21:32 201613 // Update Count : 2 0212 // Last Modified On : Thu Mar 8 17:08:25 2018 13 // Update Count : 219 14 14 // 15 15 … … 38 38 } 39 39 namespace { 40 Statement * isLoop( Statement * stmt ) { return dynamic_cast< WhileStmt * >( stmt ) ? stmt : dynamic_cast< ForStmt * >( stmt ) ? stmt : 0; } 41 } 40 bool isLoop( const MLEMutator::Entry & e ) { return dynamic_cast< WhileStmt * >( e.get_controlStructure() ) || dynamic_cast< ForStmt * >( e.get_controlStructure() ); } 41 bool isSwitch( const MLEMutator::Entry & e ) { return dynamic_cast< SwitchStmt *>( e.get_controlStructure() ); } 42 43 bool isBreakTarget( const MLEMutator::Entry & e ) { return isLoop( e ) || isSwitch( e ) || dynamic_cast< CompoundStmt *>( e.get_controlStructure() ); } 44 bool isContinueTarget( const MLEMutator::Entry & e ) { return isLoop( e ); } 45 bool isFallthroughTarget( const MLEMutator::Entry & e ) { return dynamic_cast< CaseStmt *>( e.get_controlStructure() );; } 46 bool isFallthroughDefaultTarget( const MLEMutator::Entry & e ) { return isSwitch( e ); } 47 } // namespace 42 48 43 49 // break labels have to come after the statement they break out of, so mutate a statement, then if they inform us 44 50 // through the breakLabel field tha they need a place to jump to on a break statement, add the break label to the 45 51 // body of statements 46 void MLEMutator::fixBlock( std::list< Statement * > &kids ) { 52 void MLEMutator::fixBlock( std::list< Statement * > &kids, bool caseClause ) { 53 SemanticErrorException errors; 54 47 55 for ( std::list< Statement * >::iterator k = kids.begin(); k != kids.end(); k++ ) { 48 *k = (*k)->acceptMutator(*visitor); 56 if ( caseClause ) { 57 // once a label is seen, it's no longer a valid fallthrough target 58 for ( Label & l : (*k)->labels ) { 59 fallthroughLabels.erase( l ); 60 } 61 } 62 63 // aggregate errors since the PassVisitor mutate loop was unrollled 64 try { 65 *k = (*k)->acceptMutator(*visitor); 66 } catch( SemanticErrorException &e ) { 67 errors.append( e ); 68 } 49 69 50 70 if ( ! get_breakLabel().empty() ) { … … 55 75 } // if 56 76 } // for 77 78 if ( ! errors.isEmpty() ) { 79 throw errors; 80 } 57 81 } 58 82 … … 63 87 Label brkLabel = generator->newLabel("blockBreak", cmpndStmt); 64 88 enclosingControlStructures.push_back( Entry( cmpndStmt, brkLabel ) ); 89 GuardAction( [this]() { enclosingControlStructures.pop_back(); } ); 65 90 } // if 66 91 … … 74 99 set_breakLabel( enclosingControlStructures.back().useBreakExit() ); 75 100 } // if 76 enclosingControlStructures.pop_back();77 101 } // if 78 102 } … … 112 136 if ( isContinue ) { 113 137 // continue target is outermost loop 114 targetEntry = std::find_if( enclosingControlStructures.rbegin(), enclosingControlStructures.rend(), [](Entry &e) { return isLoop( e.get_controlStructure() ); });138 targetEntry = std::find_if( enclosingControlStructures.rbegin(), enclosingControlStructures.rend(), isContinueTarget ); 115 139 } else { 116 // break target is out mostcontrol structure117 if ( enclosingControlStructures.empty() ) SemanticError( branchStmt->location, "'break' outside a loop, switch, or labelled block" );118 targetEntry = enclosingControlStructures.rbegin();140 // break target is outermost loop, switch, or block control structure 141 if ( enclosingControlStructures.empty() ) SemanticError( branchStmt->location, "'break' outside a loop, 'switch', or labelled block" ); 142 targetEntry = std::find_if( enclosingControlStructures.rbegin(), enclosingControlStructures.rend(), isBreakTarget ); 119 143 } // if 120 144 } else { … … 123 147 } // if 124 148 // ensure that selected target is valid 125 if ( targetEntry == enclosingControlStructures.rend() || (isContinue && ! is Loop( targetEntry->get_controlStructure()) ) ) {149 if ( targetEntry == enclosingControlStructures.rend() || (isContinue && ! isContinueTarget( *targetEntry ) ) ) { 126 150 SemanticError( branchStmt->location, toString( (isContinue ? "'continue'" : "'break'"), " target must be an enclosing ", (isContinue ? "loop: " : "control structure: "), originalTarget ) ); 127 151 } // if 128 152 break; 129 153 } 154 case BranchStmt::FallThrough: 155 targetEntry = std::find_if( enclosingControlStructures.rbegin(), enclosingControlStructures.rend(), isFallthroughTarget ); 156 // ensure that selected target is valid 157 if ( targetEntry == enclosingControlStructures.rend() ) { 158 SemanticError( branchStmt->location, "'fallthrough' must be enclosed in a 'switch' or 'choose'" ); 159 } // if 160 if ( branchStmt->get_target() != "" ) { 161 // labelled fallthrough 162 // target must be in the set of valid fallthrough labels 163 if ( ! fallthroughLabels.count( branchStmt->get_target() ) ) { 164 SemanticError( branchStmt->location, toString( "'fallthrough' target must be a later case statement: ", originalTarget ) ); 165 } 166 return new BranchStmt( originalTarget, BranchStmt::Goto ); 167 } 168 break; 169 case BranchStmt::FallThroughDefault: { 170 // fallthrough default 171 targetEntry = std::find_if( enclosingControlStructures.rbegin(), enclosingControlStructures.rend(), isFallthroughDefaultTarget ); 172 173 // ensure that fallthrough is within a switch or choose 174 if ( targetEntry == enclosingControlStructures.rend() ) { 175 SemanticError( branchStmt->location, "'fallthrough' must be enclosed in a 'switch' or 'choose'" ); 176 } // if 177 178 // ensure that switch or choose has a default clause 179 SwitchStmt * switchStmt = strict_dynamic_cast< SwitchStmt * >( targetEntry->get_controlStructure() ); 180 bool foundDefault = false; 181 for ( Statement * stmt : switchStmt->statements ) { 182 CaseStmt * caseStmt = strict_dynamic_cast< CaseStmt * >( stmt ); 183 if ( caseStmt->isDefault() ) { 184 foundDefault = true; 185 } // if 186 } // for 187 if ( ! foundDefault ) { 188 SemanticError( branchStmt->location, "'fallthrough default' must be enclosed in a 'switch' or 'choose' control structure with a 'default' clause" ); 189 } 190 break; 191 } 192 130 193 default: 131 194 assert( false ); … … 142 205 assert( targetEntry->useContExit() != ""); 143 206 exitLabel = targetEntry->useContExit(); 207 break; 208 case BranchStmt::FallThrough: 209 assert( targetEntry->useFallExit() != ""); 210 exitLabel = targetEntry->useFallExit(); 211 break; 212 case BranchStmt::FallThroughDefault: 213 assert( targetEntry->useFallDefaultExit() != ""); 214 exitLabel = targetEntry->useFallDefaultExit(); 215 // check that fallthrough default comes before the default clause 216 if ( ! targetEntry->isFallDefaultValid() ) { 217 SemanticError( branchStmt->location, "'fallthrough default' must precede the 'default' clause" ); 218 } 144 219 break; 145 220 default: … … 186 261 Label contLabel = generator->newLabel("loopContinue", loopStmt); 187 262 enclosingControlStructures.push_back( Entry( loopStmt, brkLabel, contLabel ) ); 263 GuardAction( [this]() { enclosingControlStructures.pop_back(); } ); 188 264 } 189 265 … … 196 272 197 273 // this will take the necessary steps to add definitions of the previous two labels, if they are used. 198 loopStmt->set_body( mutateLoop( loopStmt->get_body(), e ) ); 199 enclosingControlStructures.pop_back(); 274 loopStmt->body = mutateLoop( loopStmt->get_body(), e ); 200 275 return loopStmt; 201 276 } … … 223 298 Label brkLabel = generator->newLabel("blockBreak", ifStmt); 224 299 enclosingControlStructures.push_back( Entry( ifStmt, brkLabel ) ); 300 GuardAction( [this]() { enclosingControlStructures.pop_back(); } ); 225 301 } // if 226 302 } … … 232 308 set_breakLabel( enclosingControlStructures.back().useBreakExit() ); 233 309 } // if 234 enclosingControlStructures.pop_back();235 310 } // if 236 311 return ifStmt; … … 239 314 void MLEMutator::premutate( CaseStmt *caseStmt ) { 240 315 visit_children = false; 316 317 // mark default as seen before visiting its statements to catch default loops 318 if ( caseStmt->isDefault() ) { 319 enclosingControlStructures.back().seenDefault(); 320 } // if 321 241 322 caseStmt->condition = maybeMutate( caseStmt->condition, *visitor ); 242 fixBlock( caseStmt->stmts ); 323 Label fallLabel = generator->newLabel( "fallThrough", caseStmt ); 324 { 325 // ensure that stack isn't corrupted by exceptions in fixBlock 326 auto guard = makeFuncGuard( [&]() { enclosingControlStructures.push_back( Entry( caseStmt, fallLabel ) ); }, [this]() { enclosingControlStructures.pop_back(); } ); 327 328 // empty case statement 329 if( ! caseStmt->stmts.empty() ) { 330 // the parser ensures that all statements in a case are grouped into a block 331 CompoundStmt * block = strict_dynamic_cast< CompoundStmt * >( caseStmt->stmts.front() ); 332 fixBlock( block->kids, true ); 333 334 // add fallthrough label if necessary 335 assert( ! enclosingControlStructures.empty() ); 336 if ( enclosingControlStructures.back().isFallUsed() ) { 337 std::list<Label> ls{ enclosingControlStructures.back().useFallExit() }; 338 caseStmt->stmts.push_back( new NullStmt( ls ) ); 339 } // if 340 } // if 341 } 342 assert( ! enclosingControlStructures.empty() ); 343 assertf( dynamic_cast<SwitchStmt *>( enclosingControlStructures.back().get_controlStructure() ), "Control structure enclosing a case clause must be a switch, but is: %s", toCString( enclosingControlStructures.back().get_controlStructure() ) ); 344 if ( caseStmt->isDefault() ) { 345 if ( enclosingControlStructures.back().isFallDefaultUsed() ) { 346 // add fallthrough default label if necessary 347 std::list<Label> ls{ enclosingControlStructures.back().useFallDefaultExit() }; 348 caseStmt->stmts.push_front( new NullStmt( ls ) ); 349 } // if 350 } // if 243 351 } 244 352 … … 246 354 // generate a label for breaking out of a labeled switch 247 355 Label brkLabel = generator->newLabel("switchBreak", switchStmt); 248 enclosingControlStructures.push_back( Entry(switchStmt, brkLabel) ); 356 auto it = std::find_if( switchStmt->statements.rbegin(), switchStmt->statements.rend(), [](Statement * stmt) { 357 CaseStmt * caseStmt = strict_dynamic_cast< CaseStmt * >( stmt ); 358 return caseStmt->isDefault(); 359 }); 360 CaseStmt * defaultCase = it != switchStmt->statements.rend() ? strict_dynamic_cast<CaseStmt *>( *it ) : nullptr; 361 Label fallDefaultLabel = defaultCase ? generator->newLabel( "fallThroughDefault", defaultCase ) : ""; 362 enclosingControlStructures.push_back( Entry(switchStmt, brkLabel, fallDefaultLabel) ); 363 GuardAction( [this]() { enclosingControlStructures.pop_back(); } ); 364 365 // Collect valid labels for fallthrough. This is initially all labels at the same level as a case statement. 366 // As labels are seen during traversal, they are removed, since fallthrough is not allowed to jump backwards. 367 for ( Statement * stmt : switchStmt->statements ) { 368 CaseStmt * caseStmt = strict_dynamic_cast< CaseStmt * >( stmt ); 369 if ( caseStmt->stmts.empty() ) continue; 370 CompoundStmt * block = dynamic_cast< CompoundStmt * >( caseStmt->stmts.front() ); 371 for ( Statement * stmt : block->kids ) { 372 for ( Label & l : stmt->labels ) { 373 fallthroughLabels.insert( l ); 374 } 375 } 376 } 249 377 } 250 378 … … 271 399 272 400 assert ( enclosingControlStructures.back() == switchStmt ); 273 enclosingControlStructures.pop_back();274 401 return switchStmt; 275 402 } -
src/ControlStruct/MLEMutator.h
r2efe4b8 r1cdfa82 10 10 // Created On : Mon May 18 07:44:20 2015 11 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Sat Jul 22 09:19:59 201713 // Update Count : 3512 // Last Modified On : Thu Mar 8 16:42:32 2018 13 // Update Count : 41 14 14 // 15 15 … … 19 19 #include <map> // for map 20 20 #include <string> // for string 21 #include <set> // for unordered_set 21 22 22 23 #include "Common/PassVisitor.h" … … 29 30 class LabelGenerator; 30 31 31 class MLEMutator : public WithVisitorRef<MLEMutator>, public WithShortCircuiting { 32 class MLEMutator : public WithVisitorRef<MLEMutator>, public WithShortCircuiting, public WithGuards { 33 public: 32 34 class Entry; 33 34 public:35 35 MLEMutator( std::map<Label, Statement *> *t, LabelGenerator *gen = 0 ) : targetTable( t ), breakLabel(std::string("")), generator( gen ) {} 36 36 ~MLEMutator(); … … 52 52 Label &get_breakLabel() { return breakLabel; } 53 53 void set_breakLabel( Label newValue ) { breakLabel = newValue; } 54 private: 54 55 55 class Entry { 56 56 public: 57 explicit Entry( Statement *_loop, Label _breakExit, Label _contExit = Label("") ) : 58 loop( _loop ), breakExit( _breakExit ), contExit( _contExit ), breakUsed(false), contUsed(false) {} 57 // specialized constructors for each combination of statement with labelled break/continue/fallthrough that is valid to cleanup the use cases 58 explicit Entry( ForStmt *stmt, Label breakExit, Label contExit ) : 59 stmt( stmt ), breakExit( breakExit ), contExit( contExit ) {} 59 60 60 bool operator==( const Statement *stmt ) { return loop == stmt; }61 bool operator!=( const Statement *stmt ) { return loop != stmt;}61 explicit Entry( WhileStmt *stmt, Label breakExit, Label contExit ) : 62 stmt( stmt ), breakExit( breakExit ), contExit( contExit ) {} 62 63 63 bool operator==( const Entry &other ) { return loop == other.get_controlStructure(); } 64 explicit Entry( CompoundStmt *stmt, Label breakExit ) : 65 stmt( stmt ), breakExit( breakExit ) {} 64 66 65 Statement *get_controlStructure() const { return loop; } 67 explicit Entry( IfStmt *stmt, Label breakExit ) : 68 stmt( stmt ), breakExit( breakExit ) {} 69 70 explicit Entry( CaseStmt *stmt, Label fallExit ) : 71 stmt( stmt ), fallExit( fallExit ) {} 72 73 explicit Entry( SwitchStmt *stmt, Label breakExit, Label fallDefaultExit ) : 74 stmt( stmt ), breakExit( breakExit ), fallDefaultExit( fallDefaultExit ) {} 75 76 bool operator==( const Statement *other ) { return stmt == other; } 77 bool operator!=( const Statement *other ) { return stmt != other; } 78 79 bool operator==( const Entry &other ) { return stmt == other.get_controlStructure(); } 80 81 Statement *get_controlStructure() const { return stmt; } 66 82 67 83 Label useContExit() { contUsed = true; return contExit; } 68 84 Label useBreakExit() { breakUsed = true; return breakExit; } 85 Label useFallExit() { fallUsed = true; return fallExit; } 86 Label useFallDefaultExit() { fallDefaultUsed = true; return fallDefaultExit; } 69 87 70 88 bool isContUsed() const { return contUsed; } 71 89 bool isBreakUsed() const { return breakUsed; } 90 bool isFallUsed() const { return fallUsed; } 91 bool isFallDefaultUsed() const { return fallDefaultUsed; } 92 void seenDefault() { fallDefaultValid = false; } 93 bool isFallDefaultValid() const { return fallDefaultValid; } 72 94 private: 73 Statement *loop; 74 Label breakExit, contExit; 75 bool breakUsed, contUsed; 95 Statement *stmt; 96 Label breakExit, contExit, fallExit, fallDefaultExit; 97 bool breakUsed = false, contUsed = false, fallUsed = false, fallDefaultUsed = false; 98 bool fallDefaultValid = true; 76 99 }; 77 100 101 private: 78 102 std::map< Label, Statement * > *targetTable; 103 std::set< Label > fallthroughLabels; 79 104 std::list< Entry > enclosingControlStructures; 80 105 Label breakLabel; … … 87 112 Statement * posthandleLoopStmt( LoopClass * loopStmt ); 88 113 89 void fixBlock( std::list< Statement * > &kids );114 void fixBlock( std::list< Statement * > &kids, bool caseClause = false ); 90 115 }; 91 116 } // namespace ControlStruct
Note: See TracChangeset
for help on using the changeset viewer.