source: translator/ControlStruct/MLEMutator.cc@ 643a2e1

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors ctor deferred_resn demangler enum forall-pointer-decay gc_noraii jacob/cs343-translation jenkins-sandbox memory new-ast new-ast-unique-expr new-env no_list persistent-indexer pthread-emulation qualifiedEnum resolv-new string with_gc
Last change on this file since 643a2e1 was 6c3744e, checked in by Peter A. Buhr <pabuhr@…>, 11 years ago

add list initializer, formatting changes

  • 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 block
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 unnecessary)
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 {
105 newLabel = generator->newLabel();
106 check->set_breakExit( newLabel );
107 } // if
108 break;
109 case BranchStmt::Continue:
110 if ( check->get_contExit() != "" )
111 newLabel = check->get_contExit();
112 else {
113 newLabel = generator->newLabel();
114 check->set_contExit( newLabel );
115 } // if
116 break;
117 default:
118 return 0; // shouldn't be here
119 } // switch
120
121 return new BranchStmt( std::list<Label>(), newLabel, BranchStmt::Goto );
122 }
123
124
125 Statement *MLEMutator::mutate( SwitchStmt *switchStmt ) {
126 Label brkLabel = generator->newLabel();
127 enclosingSwitches.push_back( Entry(switchStmt, "", brkLabel) );
128 mutateAll( switchStmt->get_branches(), *this ); {
129 // check if this is necessary (if there is a break to this point, otherwise do not generate
130 std::list<Label> temp; temp.push_back( brkLabel );
131 switchStmt->get_branches().push_back( new BranchStmt( temp, Label(""), BranchStmt::Break ) );
132 }
133 assert ( enclosingSwitches.back() == switchStmt );
134 enclosingSwitches.pop_back();
135 return switchStmt;
136 }
137
138 Statement *MLEMutator::mutate( ChooseStmt *switchStmt ) {
139 Label brkLabel = generator->newLabel();
140 enclosingSwitches.push_back( Entry(switchStmt,"", brkLabel) );
141 mutateAll( switchStmt->get_branches(), *this ); {
142 // check if this is necessary (if there is a break to this point, otherwise do not generate
143 std::list<Label> temp; temp.push_back( brkLabel );
144 switchStmt->get_branches().push_back( new BranchStmt( temp, Label(""), BranchStmt::Break ) );
145 }
146 assert ( enclosingSwitches.back() == switchStmt );
147 enclosingSwitches.pop_back();
148 return switchStmt;
149 }
150
151 Statement *MLEMutator::mutateLoop( Statement *bodyLoop, Entry &e ) {
152 CompoundStmt *newBody;
153 if ( ! (newBody = dynamic_cast<CompoundStmt *>( bodyLoop )) ) {
154 newBody = new CompoundStmt( std::list< Label >() );
155 newBody->get_kids().push_back( bodyLoop );
156 } // if
157
158 Label endLabel = e.get_contExit();
159
160 if ( e.get_breakExit() != "" ) {
161 if ( endLabel == "" ) endLabel = generator->newLabel();
162 // check for whether this label is used or not, so as to not generate extraneous gotos
163 if (e.breakExitUsed)
164 newBody->get_kids().push_back( new BranchStmt( std::list< Label >(), endLabel, BranchStmt::Goto ) );
165 // xxx
166 //std::list< Label > ls; ls.push_back( e.get_breakExit() );
167 set_breakLabel( e.get_breakExit() );
168 //newBody->get_kids().push_back( new BranchStmt( ls, "", BranchStmt::Break ) );
169 } // if
170
171 if ( e.get_breakExit() != "" || e.get_contExit() != "" ){
172 if (dynamic_cast< NullStmt *>( newBody->get_kids().back() ))
173 newBody->get_kids().back()->get_labels().push_back( endLabel );
174 else {
175 std::list < Label > ls; ls.push_back( endLabel );
176 newBody->get_kids().push_back( new NullStmt( ls ) );
177 } // if
178 } // if
179
180 return newBody;
181 }
182
183 //*** Entry's methods
184 void MLEMutator::Entry::set_contExit( Label l ) {
185 assert ( contExit == "" || contExit == l );
186 contExit = l;
187 }
188
189 void MLEMutator::Entry::set_breakExit( Label l ) {
190 assert ( breakExit == "" || breakExit == l );
191 breakExit = l;
192 }
193} // namespace ControlStruct
Note: See TracBrowser for help on using the repository browser.