Ignore:
Timestamp:
Jun 30, 2016, 4:32:56 PM (10 years ago)
Author:
Thierry Delisle <tdelisle@…>
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, with_gc
Children:
ea29e73
Parents:
1b5c81ed (diff), 84d4d6f (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.
Message:

Merge branch 'master' into gc_noraii

Conflicts:

Jenkinsfile
src/SymTab/Validate.cc

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ControlStruct/MLEMutator.cc

    r1b5c81ed rf80e0218  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // MLEMutator.cc -- 
     7// MLEMutator.cc --
    88//
    99// Author           : Rodolfo G. Esteves
     
    1414//
    1515
    16 // NOTE: There are two known subtle differences from the code that uC++ 
     16// NOTE: There are two known subtle differences from the code that uC++
    1717// generates for the same input
    1818// -CFA puts the break label inside at the end of a switch, uC++ puts it after
     
    2727#include "SynTree/Statement.h"
    2828#include "SynTree/Expression.h"
     29#include "SynTree/Attribute.h"
    2930
    3031namespace ControlStruct {
     
    3334                targetTable = 0;
    3435        }
    35 
    36         // break labels have to come after the statement they break out of,
     36        namespace {
     37                Statement * isLoop( Statement * stmt ) { return dynamic_cast< WhileStmt * >( stmt ) ? stmt : dynamic_cast< ForStmt * >( stmt ) ? stmt : 0; }
     38        }
     39
     40        // break labels have to come after the statement they break out of,
    3741        // so mutate a statement, then if they inform us through the breakLabel field
    38         // tha they need a place to jump to on a break statement, add the break label 
     42        // tha they need a place to jump to on a break statement, add the break label
    3943        // to the body of statements
    4044        void MLEMutator::fixBlock( std::list< Statement * > &kids ) {
     
    4448                        if ( ! get_breakLabel().empty() ) {
    4549                                std::list< Statement * >::iterator next = k+1;
    46                                 if ( next == kids.end() ) {
    47                                         std::list<Label> ls; ls.push_back( get_breakLabel() );
    48                                         kids.push_back( new NullStmt( ls ) );
    49                                 } else {
    50                                         (*next)->get_labels().push_back( get_breakLabel() );
    51                                 }
    52 
     50                                std::list<Label> ls; ls.push_back( get_breakLabel() );
     51                                kids.insert( next, new NullStmt( ls ) );
    5352                                set_breakLabel("");
    5453                        } // if
     
    6059                if ( labeledBlock ) {
    6160                        Label brkLabel = generator->newLabel("blockBreak");
    62                         enclosingBlocks.push_back( Entry( cmpndStmt, brkLabel ) );
     61                        enclosingControlStructures.push_back( Entry( cmpndStmt, brkLabel ) );
    6362                } // if
    6463
     
    6968
    7069                if ( labeledBlock ) {
    71                         assert( ! enclosingBlocks.empty() );
    72                         if ( ! enclosingBlocks.back().useBreakExit().empty() ) {
    73                                 set_breakLabel( enclosingBlocks.back().useBreakExit() );
    74                         }
    75                         enclosingBlocks.pop_back();
     70                        assert( ! enclosingControlStructures.empty() );
     71                        if ( ! enclosingControlStructures.back().useBreakExit().empty() ) {
     72                                set_breakLabel( enclosingControlStructures.back().useBreakExit() );
     73                        }
     74                        enclosingControlStructures.pop_back();
    7675                } // if
    7776
     
    8180        template< typename LoopClass >
    8281        Statement *MLEMutator::handleLoopStmt( LoopClass *loopStmt ) {
    83                 // remember this as the most recent enclosing loop, then mutate 
     82                // remember this as the most recent enclosing loop, then mutate
    8483                // the body of the loop -- this will determine whether brkLabel
    8584                // and contLabel are used with branch statements
     
    8786                Label brkLabel = generator->newLabel("loopBreak");
    8887                Label contLabel = generator->newLabel("loopContinue");
    89                 enclosingLoops.push_back( Entry( loopStmt, brkLabel, contLabel ) );
     88                enclosingControlStructures.push_back( Entry( loopStmt, brkLabel, contLabel ) );
    9089                loopStmt->set_body ( loopStmt->get_body()->acceptMutator( *this ) );
    9190
    9291                // sanity check that the enclosing loops have been popped correctly
    93                 Entry &e = enclosingLoops.back();
     92                Entry &e = enclosingControlStructures.back();
    9493                assert ( e == loopStmt );
    9594
     
    9796                // two labels, if they are used.
    9897                loopStmt->set_body( mutateLoop( loopStmt->get_body(), e ) );
    99                 enclosingLoops.pop_back();
     98                enclosingControlStructures.pop_back();
    10099
    101100                return loopStmt;
     
    111110        template< typename SwitchClass >
    112111        Statement *MLEMutator::handleSwitchStmt( SwitchClass *switchStmt ) {
    113                 // generate a label for breaking out of a labeled switch 
     112                // generate a label for breaking out of a labeled switch
    114113                Label brkLabel = generator->newLabel("switchBreak");
    115                 enclosingSwitches.push_back( Entry(switchStmt, brkLabel) );
    116                 mutateAll( switchStmt->get_branches(), *this ); 
    117 
    118                 Entry &e = enclosingSwitches.back();
     114                enclosingControlStructures.push_back( Entry(switchStmt, brkLabel) );
     115                mutateAll( switchStmt->get_branches(), *this );
     116
     117                Entry &e = enclosingControlStructures.back();
    119118                assert ( e == switchStmt );
    120119
    121120                // only generate break label if labeled break is used
    122121                if (e.isBreakUsed()) {
    123                         // for the purposes of keeping switch statements uniform (i.e. all statements that are 
    124                         // direct children of a switch should be CastStmts), append the exit label + break to the 
     122                        // for the purposes of keeping switch statements uniform (i.e. all statements that are
     123                        // direct children of a switch should be CastStmts), append the exit label + break to the
    125124                        // last case statement; create a default case if there are no cases
    126125                        std::list< Statement * > &branches = switchStmt->get_branches();
     
    131130                        if ( CaseStmt * c = dynamic_cast< CaseStmt * >( branches.back() ) ) {
    132131                                std::list<Label> temp; temp.push_back( brkLabel );
    133                                 c->get_statements().push_back( new BranchStmt( temp, Label(""), BranchStmt::Break ) );
     132                                c->get_statements().push_back( new BranchStmt( temp, Label("brkLabel"), BranchStmt::Break ) );
    134133                        } else assert(0); // as of this point, all branches of a switch are still CaseStmts
    135134                }
    136135
    137                 assert ( enclosingSwitches.back() == switchStmt );
    138                 enclosingSwitches.pop_back();
     136                assert ( enclosingControlStructures.back() == switchStmt );
     137                enclosingControlStructures.pop_back();
    139138                return switchStmt;
    140139        }
     
    143142                std::string originalTarget = branchStmt->get_originalTarget();
    144143
    145                 if ( branchStmt->get_type() == BranchStmt::Goto )
     144                std::list< Entry >::reverse_iterator targetEntry;
     145                if ( branchStmt->get_type() == BranchStmt::Goto ) {
    146146                        return branchStmt;
    147 
    148                 // test if continue target is a loop
    149                 if ( branchStmt->get_type() == BranchStmt::Continue) {
    150                         if ( enclosingLoops.empty() ) {
    151                                 throw SemanticError( "'continue' outside a loop" );
    152                         } else if ( branchStmt->get_target() != "" && std::find( enclosingLoops.begin(), enclosingLoops.end(), (*targetTable)[branchStmt->get_target()] ) == enclosingLoops.end() ) {
    153                                 throw SemanticError( "'continue' target label must be an enclosing loop: " + originalTarget );
    154                         }
    155                 }
    156 
    157                 if ( branchStmt->get_type() == BranchStmt::Break && (enclosingLoops.empty() && enclosingSwitches.empty() && enclosingBlocks.empty() ) )
    158                         throw SemanticError( "'break' outside a loop or switch" );
    159 
    160                 if ( branchStmt->get_target() == "" ) return branchStmt;
    161 
    162                 if ( targetTable->find( branchStmt->get_target() ) == targetTable->end() )
     147                } else if ( branchStmt->get_type() == BranchStmt::Continue) {
     148                        // continue target must be a loop
     149                        if ( branchStmt->get_target() == "" ) {
     150                                targetEntry = std::find_if( enclosingControlStructures.rbegin(), enclosingControlStructures.rend(), [](Entry &e) { return isLoop( e.get_controlStructure() ); } );
     151                        } else {
     152                                // labelled continue - lookup label in table ot find attached control structure
     153                                targetEntry = std::find( enclosingControlStructures.rbegin(), enclosingControlStructures.rend(), (*targetTable)[branchStmt->get_target()] );
     154                        }
     155                        if ( targetEntry == enclosingControlStructures.rend() || ! isLoop( targetEntry->get_controlStructure() ) ) {
     156                                throw SemanticError( "'continue' target must be an enclosing loop: " + originalTarget );
     157                        }
     158                } else if ( branchStmt->get_type() == BranchStmt::Break ) {
     159                        if ( enclosingControlStructures.empty() ) throw SemanticError( "'break' outside a loop, switch, or labelled block" );
     160                        targetEntry = enclosingControlStructures.rbegin();
     161                } else {
     162                        assert( false );
     163                }
     164
     165                if ( branchStmt->get_target() != "" && targetTable->find( branchStmt->get_target() ) == targetTable->end() ) {
    163166                        throw SemanticError("The label defined in the exit loop statement does not exist: " + originalTarget );  // shouldn't happen (since that's already checked)
    164 
    165                 std::list< Entry >::iterator check;
    166                 if ( ( check = std::find( enclosingLoops.begin(), enclosingLoops.end(), (*targetTable)[branchStmt->get_target()] ) ) == enclosingLoops.end() )
    167                         // not in loop, checking if in block
    168                         if ( (check = std::find( enclosingBlocks.begin(), enclosingBlocks.end(), (*targetTable)[branchStmt->get_target()] )) == enclosingBlocks.end() )
    169                                 // neither in loop nor in block, checking if in switch/choose
    170                                 if ( (check = std::find( enclosingSwitches.begin(), enclosingSwitches.end(), (*targetTable)[branchStmt->get_target()] )) == enclosingSwitches.end() )
    171                                         throw SemanticError("The target specified in the exit loop statement does not correspond to an enclosing control structure: " + originalTarget );
    172 
    173                 // what about exiting innermost block or switch???
    174                 if ( enclosingLoops.back() == (*check) )
    175                         return branchStmt;                              // exit the innermost loop (labels unnecessary)
     167                }
    176168
    177169                // branch error checks, get the appropriate label name and create a goto
     
    179171                switch ( branchStmt->get_type() ) {
    180172                  case BranchStmt::Break:
    181                                 assert( check->useBreakExit() != "");
    182                                 exitLabel = check->useBreakExit();
     173                                assert( targetEntry->useBreakExit() != "");
     174                                exitLabel = targetEntry->useBreakExit();
    183175                                break;
    184176                  case BranchStmt::Continue:
    185                                 assert( check->useContExit() != "");
    186                                 exitLabel = check->useContExit();
     177                                assert( targetEntry->useContExit() != "");
     178                                exitLabel = targetEntry->useContExit();
    187179                                break;
    188180                  default:
     
    190182                } // switch
    191183
    192                 return new BranchStmt( std::list<Label>(), exitLabel, BranchStmt::Goto );
     184                if ( branchStmt->get_target() == "" && branchStmt->get_type() != BranchStmt::Continue ) {
     185                        // unlabelled break/continue - can keep branch as break/continue for extra semantic information, but add
     186                        // exitLabel as its destination so that label passes can easily determine where the break/continue goes to
     187                        branchStmt->set_target( exitLabel );
     188                        return branchStmt;
     189                } else {
     190                        // labelled break/continue - can't easily emulate this with break and continue, so transform into a goto
     191                        delete branchStmt;
     192                        return new BranchStmt( std::list<Label>(), exitLabel, BranchStmt::Goto );
     193                }
    193194        }
    194195
     
    206207                        // continue label goes in the body as the last statement
    207208                        std::list< Label > labels; labels.push_back( e.useContExit() );
    208                         newBody->get_kids().push_back( new NullStmt( labels ) );                       
     209                        newBody->get_kids().push_back( new NullStmt( labels ) );
    209210                }
    210211
    211212                if ( e.isBreakUsed() ) {
    212                         // break label goes after the loop -- it'll get set by the 
     213                        // break label goes after the loop -- it'll get set by the
    213214                        // outer mutator if we do this
    214                         set_breakLabel( e.useBreakExit() );                     
     215                        set_breakLabel( e.useBreakExit() );
    215216                }
    216217
     
    231232
    232233        Statement *MLEMutator::mutate( ChooseStmt *switchStmt ) {
    233                 return handleSwitchStmt( switchStmt );         
     234                return handleSwitchStmt( switchStmt );
    234235        }
    235236
Note: See TracChangeset for help on using the changeset viewer.