source: translator/ControlStruct/MLEMutator.cc @ d9a0e76

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsctordeferred_resndemanglerenumforall-pointer-decaygc_noraiijacob/cs343-translationjenkins-sandboxmemorynew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newstringwith_gc
Last change on this file since d9a0e76 was d9a0e76, checked in by Peter A. Buhr <pabuhr@…>, 10 years ago

remove Parser.old, add -XCFA to driver, copy ptrdiff_t from stddef.h in preclude, remove casts from initialization constants, adjust formatting

  • Property mode set to 100644
File size: 6.7 KB
Line 
1#include <cassert>
2#include <algorithm>
3
4#include "MLEMutator.h"
5#include "SynTree/Statement.h"
6
7
8namespace ControlStruct {
9    MLEMutator::~MLEMutator() {
10        delete targetTable;
11        targetTable = 0;
12    }
13
14    CompoundStmt* MLEMutator::mutate(CompoundStmt *cmpndStmt) {
15        bool labeledBlock = false;
16        if ( !((cmpndStmt->get_labels()).empty()) ) {
17            labeledBlock = true;
18            enclosingBlocks.push_back( Entry( cmpndStmt ) );
19        }
20
21        std::list< Statement * > &kids = cmpndStmt->get_kids();
22        for ( std::list< Statement * >::iterator k = kids.begin(); k != kids.end(); k++ ) {
23            *k = (*k)->acceptMutator(*this);
24
25            if ( !get_breakLabel().empty() ) {
26                std::list< Statement * >::iterator next = k; next++;
27                if ( next == kids.end() ) {
28                    std::list<Label> ls; ls.push_back( get_breakLabel() );
29                    kids.push_back( new NullStmt(ls) );
30                } else
31                    (*next)->get_labels().push_back( get_breakLabel() );
32
33                set_breakLabel("");
34            } // if
35        } // for
36
37        if ( labeledBlock ) {
38            assert( ! enclosingBlocks.empty() );
39            if ( ! enclosingBlocks.back().get_breakExit().empty() )
40                set_breakLabel( enclosingBlocks.back().get_breakExit() );
41            enclosingBlocks.pop_back();
42        } // if
43
44        //mutateAll( cmpndStmt->get_kids(), *this );
45        return cmpndStmt;
46    }
47
48    Statement *MLEMutator::mutate( WhileStmt *whileStmt ) {
49        enclosingLoops.push_back( Entry( whileStmt ) );
50        whileStmt->set_body ( whileStmt->get_body()->acceptMutator( *this ) );
51
52        Entry &e = enclosingLoops.back();
53        assert ( e == whileStmt );
54        whileStmt->set_body( mutateLoop( whileStmt->get_body(), e ) );
55        enclosingLoops.pop_back();
56
57        return whileStmt;
58    }
59
60    Statement *MLEMutator::mutate( ForStmt *forStmt ) {
61        enclosingLoops.push_back( Entry( forStmt ) );
62        maybeMutate( forStmt->get_body(), *this );
63
64        Entry &e = enclosingLoops.back();
65        assert ( e == forStmt );
66        forStmt->set_body( mutateLoop( forStmt->get_body(), e ) );
67        enclosingLoops.pop_back();
68
69        return forStmt;
70    }
71
72    Statement *MLEMutator::mutate( BranchStmt *branchStmt ) throw ( SemanticError ) {
73        if ( branchStmt->get_type() == BranchStmt::Goto )
74            return branchStmt;
75
76        // test if continue target is a loop
77        if ( branchStmt->get_type() == BranchStmt::Continue && enclosingLoops.empty() )
78            throw SemanticError( "'continue' outside a loop" );
79
80        if ( branchStmt->get_type() == BranchStmt::Break && (enclosingLoops.empty() && enclosingSwitches.empty() && enclosingBlocks.empty() ) )
81            throw SemanticError( "'break' outside a loop or switch" );
82
83        if ( branchStmt->get_target() == "" ) return branchStmt;
84
85        if ( targetTable->find( branchStmt->get_target() ) == targetTable->end() )
86            throw SemanticError("The label defined in the exit loop statement does not exist." );  // shouldn't happen (since that's already checked)
87
88        std::list< Entry >::iterator check;
89        if ( ( check = std::find( enclosingLoops.begin(), enclosingLoops.end(), (*targetTable)[branchStmt->get_target()] ) ) == enclosingLoops.end() )
90            // not in loop, checking if in switch/choose
91            if ( (check = std::find( enclosingBlocks.begin(), enclosingBlocks.end(), (*targetTable)[branchStmt->get_target()] )) == enclosingBlocks.end() )
92                // neither in loop nor in block, checking if in switch/choose
93                if ( (check = std::find( enclosingSwitches.begin(), enclosingSwitches.end(), (*targetTable)[branchStmt->get_target()] )) == enclosingSwitches.end() )
94                    throw SemanticError("The target specified in the exit loop statement does not correspond to an enclosing loop.");
95
96        if ( enclosingLoops.back() == (*check) )
97            return branchStmt;                      // exit the innermost loop (labels not necessary)
98
99        Label newLabel;
100        switch( branchStmt->get_type() ) {
101          case BranchStmt::Break:
102            if ( check->get_breakExit() != "" )
103                newLabel = check->get_breakExit();
104            else { newLabel = generator->newLabel(); check->set_breakExit( newLabel ); }
105            break;
106          case BranchStmt::Continue:
107            if ( check->get_contExit() != "" )
108                newLabel = check->get_contExit();
109            else { newLabel = generator->newLabel(); check->set_contExit( newLabel ); }
110            break;
111          default:
112            // shouldn't be here
113            return 0;
114        } // switch
115
116        return new BranchStmt(std::list<Label>(), newLabel, BranchStmt::Goto );
117    }
118
119
120    Statement *MLEMutator::mutate(SwitchStmt *switchStmt) {
121        Label brkLabel = generator->newLabel();
122        enclosingSwitches.push_back( Entry(switchStmt, "", brkLabel) );
123        mutateAll( switchStmt->get_branches(), *this ); {
124            // check if this is necessary (if there is a break to this point, otherwise do not generate
125            std::list<Label> temp; temp.push_back( brkLabel );
126            switchStmt->get_branches().push_back( new BranchStmt( temp, Label(""), BranchStmt::Break ) );
127        }
128        assert ( enclosingSwitches.back() == switchStmt );
129        enclosingSwitches.pop_back();
130        return switchStmt;
131    }
132
133    Statement *MLEMutator::mutate(ChooseStmt *switchStmt) {
134        Label brkLabel = generator->newLabel();
135        enclosingSwitches.push_back( Entry(switchStmt,"", brkLabel) );
136        mutateAll( switchStmt->get_branches(), *this ); {
137            // check if this is necessary (if there is a break to this point, otherwise do not generate
138            std::list<Label> temp; temp.push_back( brkLabel );
139            switchStmt->get_branches().push_back( new BranchStmt( temp, Label(""), BranchStmt::Break ) );
140        }
141        assert ( enclosingSwitches.back() == switchStmt );
142        enclosingSwitches.pop_back();
143        return switchStmt;
144    }
145
146    Statement *MLEMutator::mutateLoop( Statement *bodyLoop, Entry &e ) {
147        CompoundStmt *newBody;
148        if ( ! (newBody = dynamic_cast<CompoundStmt *>( bodyLoop )) ) {
149            newBody = new CompoundStmt( std::list< Label >() );
150            newBody->get_kids().push_back( bodyLoop );
151        } // if
152
153        Label endLabel = e.get_contExit();
154
155        if ( e.get_breakExit() != "" ) {
156            if ( endLabel == "" ) endLabel = generator->newLabel();
157            // check for whether this label is used or not, so as to not generate extraneous gotos
158            if (e.breakExitUsed)
159                newBody->get_kids().push_back( new BranchStmt( std::list< Label >(), endLabel, BranchStmt::Goto ) );
160            // xxx
161            //std::list< Label > ls; ls.push_back( e.get_breakExit() );
162            set_breakLabel( e.get_breakExit() );
163            //newBody->get_kids().push_back( new BranchStmt( ls, "", BranchStmt::Break ) );
164        } // if
165
166        if ( e.get_breakExit() != "" || e.get_contExit() != "" ){
167            if (dynamic_cast< NullStmt *>( newBody->get_kids().back() ))
168                newBody->get_kids().back()->get_labels().push_back( endLabel );
169            else {
170                std::list < Label > ls; ls.push_back( endLabel );
171                newBody->get_kids().push_back( new NullStmt( ls ) );
172            } // if
173        } // if
174
175        return newBody;
176    }
177
178    //*** Entry's methods
179    void MLEMutator::Entry::set_contExit( Label l ) {
180        assert ( contExit == "" || contExit == l );
181        contExit = l;
182    }
183
184    void MLEMutator::Entry::set_breakExit( Label l ) {
185        assert ( breakExit == "" || breakExit == l );
186        breakExit = l;
187    }
188} // namespace ControlStruct
Note: See TracBrowser for help on using the repository browser.