// // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // MLEMutator.cc -- // // Author : Rodolfo G. Esteves // Created On : Mon May 18 07:44:20 2015 // Last Modified By : Andrew Beach // Last Modified On : Thr Jan 16 15:33:00 2020 // Update Count : 221 // // NOTE: There are two known subtle differences from the code that uC++ generates for the same input // -CFA puts the break label inside at the end of a switch, uC++ puts it after // -CFA puts the break label after a block, uC++ puts it inside at the end // It is unclear if these differences are important, but if they are, then the fix would go in this file, since this is // where these labels are generated. #include // for __alloc_traits<>::value_type #include // for find, find_if #include // for assert, assertf #include // for allocator_traits<>::value_... #include "Common/utility.h" // for toString, operator+ #include "ControlStruct/LabelGenerator.h" // for LabelGenerator #include "MLEMutator.h" #include "SynTree/Attribute.h" // for Attribute #include "SynTree/Expression.h" // for Expression #include "SynTree/Statement.h" // for BranchStmt, CompoundStmt namespace ControlStruct { MLEMutator::~MLEMutator() { delete targetTable; targetTable = 0; } namespace { bool isLoop( const MLEMutator::Entry & e ) { return dynamic_cast< WhileStmt * >( e.get_controlStructure() ) || dynamic_cast< ForStmt * >( e.get_controlStructure() ); } bool isSwitch( const MLEMutator::Entry & e ) { return dynamic_cast< SwitchStmt *>( e.get_controlStructure() ); } bool isBreakTarget( const MLEMutator::Entry & e ) { return isLoop( e ) || isSwitch( e ) || dynamic_cast< CompoundStmt *>( e.get_controlStructure() ); } bool isContinueTarget( const MLEMutator::Entry & e ) { return isLoop( e ); } bool isFallthroughTarget( const MLEMutator::Entry & e ) { return dynamic_cast< CaseStmt *>( e.get_controlStructure() );; } bool isFallthroughDefaultTarget( const MLEMutator::Entry & e ) { return isSwitch( e ); } } // namespace // break labels have to come after the statement they break out of, so mutate a statement, then if they inform us // through the breakLabel field tha they need a place to jump to on a break statement, add the break label to the // body of statements void MLEMutator::fixBlock( std::list< Statement * > &kids, bool caseClause ) { SemanticErrorException errors; for ( std::list< Statement * >::iterator k = kids.begin(); k != kids.end(); k++ ) { if ( caseClause ) { // once a label is seen, it's no longer a valid fallthrough target for ( Label & l : (*k)->labels ) { fallthroughLabels.erase( l ); } } // aggregate errors since the PassVisitor mutate loop was unrollled try { *k = (*k)->acceptMutator(*visitor); } catch( SemanticErrorException &e ) { errors.append( e ); } if ( ! get_breakLabel().empty() ) { std::list< Statement * >::iterator next = k+1; std::list