source: translator/ControlStruct/MLEMutator.cc @ 01aeade

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 01aeade was 51587aa, checked in by Peter A. Buhr <pabuhr@…>, 9 years ago

licencing: fourth groups of files

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