source: translator/ControlStruct/MLEMutator.cc@ d3d8c3f

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 d3d8c3f was 8c17ab0, checked in by Peter A. Buhr <pabuhr@…>, 11 years ago

add quoted identifiers, add compilation include directory, reformatted some files

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