Changeset af68f0a


Ignore:
Timestamp:
Apr 5, 2017, 6:07:58 PM (4 years ago)
Author:
Rob Schluntz <rschlunt@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, deferred_resn, demangler, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, resolv-new, with_gc
Children:
c51b5a3
Parents:
fbd7ad6
Message:

change all break/continue statements into goto for consistency and fix bug with labeled break

Location:
src/ControlStruct
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/ControlStruct/LabelGenerator.cc

    rfbd7ad6 raf68f0a  
    2020#include "SynTree/Label.h"
    2121#include "SynTree/Attribute.h"
     22#include "SynTree/Statement.h"
    2223
    2324namespace ControlStruct {
     
    3132        }
    3233
    33         Label LabelGenerator::newLabel( std::string suffix ) {
     34        Label LabelGenerator::newLabel( std::string suffix, Statement * stmt ) {
    3435                std::ostringstream os;
    3536                os << "__L" << current++ << "__" << suffix;
     37                if ( stmt && ! stmt->get_labels().empty() ) {
     38                        os << "_" << stmt->get_labels().front() << "__";
     39                }
    3640                std::string ret = os.str();
    3741                Label l( ret );
  • src/ControlStruct/LabelGenerator.h

    rfbd7ad6 raf68f0a  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // LabelGenerator.h -- 
     7// LabelGenerator.h --
    88//
    99// Author           : Rodolfo G. Esteves
     
    2424          public:
    2525                static LabelGenerator *getGenerator();
    26                 Label newLabel(std::string suffix = "");
     26                Label newLabel(std::string suffix, Statement * stmt = nullptr);
    2727                void reset() { current = 0; }
    2828                void rewind() { current--; }
  • src/ControlStruct/MLEMutator.cc

    rfbd7ad6 raf68f0a  
    5656                bool labeledBlock = !(cmpndStmt->get_labels().empty());
    5757                if ( labeledBlock ) {
    58                         Label brkLabel = generator->newLabel("blockBreak");
     58                        Label brkLabel = generator->newLabel("blockBreak", cmpndStmt);
    5959                        enclosingControlStructures.push_back( Entry( cmpndStmt, brkLabel ) );
    6060                } // if
     
    8080                // whether brkLabel and contLabel are used with branch statements and will recursively do the same to nested
    8181                // loops
    82                 Label brkLabel = generator->newLabel("loopBreak");
    83                 Label contLabel = generator->newLabel("loopContinue");
     82                Label brkLabel = generator->newLabel("loopBreak", loopStmt);
     83                Label contLabel = generator->newLabel("loopContinue", loopStmt);
    8484                enclosingControlStructures.push_back( Entry( loopStmt, brkLabel, contLabel ) );
    8585                loopStmt->set_body ( loopStmt->get_body()->acceptMutator( *this ) );
    8686
     87                assert( ! enclosingControlStructures.empty() );
    8788                Entry &e = enclosingControlStructures.back();
    8889                // sanity check that the enclosing loops have been popped correctly
     
    108109                bool labeledBlock = !(ifStmt->get_labels().empty());
    109110                if ( labeledBlock ) {
    110                         Label brkLabel = generator->newLabel("blockBreak");
     111                        Label brkLabel = generator->newLabel("blockBreak", ifStmt);
    111112                        enclosingControlStructures.push_back( Entry( ifStmt, brkLabel ) );
    112113                } // if
    113114
    114115                Parent::mutate( ifStmt );
    115                
     116
    116117                if ( labeledBlock ) {
    117118                        if ( ! enclosingControlStructures.back().useBreakExit().empty() ) {
     
    126127        Statement *MLEMutator::handleSwitchStmt( SwitchClass *switchStmt ) {
    127128                // generate a label for breaking out of a labeled switch
    128                 Label brkLabel = generator->newLabel("switchBreak");
     129                Label brkLabel = generator->newLabel("switchBreak", switchStmt);
    129130                enclosingControlStructures.push_back( Entry(switchStmt, brkLabel) );
    130131                mutateAll( switchStmt->get_statements(), *this );
     
    158159
    159160                std::list< Entry >::reverse_iterator targetEntry;
    160                 if ( branchStmt->get_type() == BranchStmt::Goto ) {
    161                         return branchStmt;
    162                 } else if ( branchStmt->get_type() == BranchStmt::Continue) {
    163                         // continue target must be a loop
    164                         if ( branchStmt->get_target() == "" ) {
    165                                 targetEntry = std::find_if( enclosingControlStructures.rbegin(), enclosingControlStructures.rend(), [](Entry &e) { return isLoop( e.get_controlStructure() ); } );
    166                         } else {
    167                                 // labelled continue - lookup label in table ot find attached control structure
    168                                 targetEntry = std::find( enclosingControlStructures.rbegin(), enclosingControlStructures.rend(), (*targetTable)[branchStmt->get_target()] );
    169                         } // if
    170                         if ( targetEntry == enclosingControlStructures.rend() || ! isLoop( targetEntry->get_controlStructure() ) ) {
    171                                 throw SemanticError( "'continue' target must be an enclosing loop: " + originalTarget );
    172                         } // if
    173                 } else if ( branchStmt->get_type() == BranchStmt::Break ) {
    174                         if ( enclosingControlStructures.empty() ) throw SemanticError( "'break' outside a loop, switch, or labelled block" );
    175                         targetEntry = enclosingControlStructures.rbegin();
    176                 } else {
    177                         assert( false );
    178                 } // if
    179 
    180                 if ( branchStmt->get_target() != "" && targetTable->find( branchStmt->get_target() ) == targetTable->end() ) {
    181                         throw SemanticError("The label defined in the exit loop statement does not exist: " + originalTarget );  // shouldn't happen (since that's already checked)
    182                 } // if
     161                switch ( branchStmt->get_type() ) {
     162                        case BranchStmt::Goto:
     163                                return branchStmt;
     164                        case BranchStmt::Continue:
     165                        case BranchStmt::Break: {
     166                                bool isContinue = branchStmt->get_type() == BranchStmt::Continue;
     167                                // unlabeled break/continue
     168                                if ( branchStmt->get_target() == "" ) {
     169                                        if ( isContinue ) {
     170                                                // continue target is outermost loop
     171                                                targetEntry = std::find_if( enclosingControlStructures.rbegin(), enclosingControlStructures.rend(), [](Entry &e) { return isLoop( e.get_controlStructure() ); } );
     172                                        } else {
     173                                                // break target is outmost control structure
     174                                                if ( enclosingControlStructures.empty() ) throw SemanticError( "'break' outside a loop, switch, or labelled block" );
     175                                                targetEntry = enclosingControlStructures.rbegin();
     176                                        } // if
     177                                } else {
     178                                        // labeled break/continue - lookup label in table to find attached control structure
     179                                        targetEntry = std::find( enclosingControlStructures.rbegin(), enclosingControlStructures.rend(), (*targetTable)[branchStmt->get_target()] );
     180                                } // if
     181                                // ensure that selected target is valid
     182                                if ( targetEntry == enclosingControlStructures.rend() || (isContinue && ! isLoop( targetEntry->get_controlStructure() ) ) ) {
     183                                        throw SemanticError( toString( (isContinue ? "'continue'" : "'break'"), " target must be an enclosing ", (isContinue ? "loop: " : "control structure: "), originalTarget ) );
     184                                } // if
     185                                break;
     186                        }
     187                        default:
     188                                assert( false );
     189                } // switch
    183190
    184191                // branch error checks, get the appropriate label name and create a goto
     
    197204                } // switch
    198205
    199                 if ( branchStmt->get_target() == "" && branchStmt->get_type() != BranchStmt::Continue ) {
    200                         // unlabelled break/continue - can keep branch as break/continue for extra semantic information, but add
    201                         // exitLabel as its destination so that label passes can easily determine where the break/continue goes to
    202                         branchStmt->set_target( exitLabel );
    203                         return branchStmt;
    204                 } else {
    205                         // labelled break/continue - can't easily emulate this with break and continue, so transform into a goto
    206                         delete branchStmt;
    207                         return new BranchStmt( std::list<Label>(), exitLabel, BranchStmt::Goto );
    208                 } // if
     206                // transform break/continue statements into goto to simplify later handling of branches
     207                delete branchStmt;
     208                return new BranchStmt( std::list<Label>(), exitLabel, BranchStmt::Goto );
    209209        }
    210210
Note: See TracChangeset for help on using the changeset viewer.