Changes in / [c1c0928:4d3ca1d8]
- Location:
- src
- Files:
-
- 3 added
- 23 edited
Legend:
- Unmodified
- Added
- Removed
-
src/CodeGen/CodeGenerator.cc
rc1c0928 r4d3ca1d8 806 806 807 807 for ( std::list< Label >::iterator i = l.begin(); i != l.end(); i++ ) 808 str += *i+ ": ";808 str += (*i).get_name() + ": "; 809 809 810 810 return str; -
src/ControlStruct/LabelFixer.cc
rc1c0928 r4d3ca1d8 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // LabelFixer.cc -- 7 // LabelFixer.cc -- 8 8 // 9 9 // Author : Rodolfo G. Esteves … … 86 86 87 87 88 // sets the definition of the labelTable entry to be the provided 88 // sets the definition of the labelTable entry to be the provided 89 89 // statement for every label in the list parameter. Happens for every kind of statement 90 90 Label LabelFixer::setLabelsDef( std::list< Label > &llabel, Statement *definition ) { … … 95 95 96 96 for ( std::list< Label >::iterator i = llabel.begin(); i != llabel.end(); i++ ) { 97 if ( labelTable.find( *i ) == labelTable.end() ) { 97 Label & l = *i; 98 l.set_statement( definition ); // attach statement to the label to be used later 99 if ( labelTable.find( l ) == labelTable.end() ) { 98 100 // all labels on this statement need to use the same entry, so this should only be created once 99 101 // undefined and unused until now, add an entry 100 labelTable[ *i] = e;101 } else if ( labelTable[ *i]->defined() ) {102 labelTable[ l ] = e; 103 } else if ( labelTable[ l ]->defined() ) { 102 104 // defined twice, error 103 throw SemanticError( "Duplicate definition of label: " + *i);105 throw SemanticError( "Duplicate definition of label: " + l.get_name() ); 104 106 } else { 105 107 // used previously, but undefined until now -> link with this entry 106 delete labelTable[ *i];107 labelTable[ *i] = e;108 delete labelTable[ l ]; 109 labelTable[ l ] = e; 108 110 } // if 109 111 } // for 110 112 111 // produce one of the labels attached to this statement to be 113 // produce one of the labels attached to this statement to be 112 114 // temporarily used as the canonical label 113 115 return labelTable[ llabel.front() ]->get_label(); 114 116 } 115 117 116 // A label was used, add it otthe table if it isn't already there118 // A label was used, add it to the table if it isn't already there 117 119 template< typename UsageNode > 118 120 void LabelFixer::setLabelsUsg( Label orgValue, UsageNode *use ) { … … 130 132 for ( std::map< Label, Entry * >::iterator i = labelTable.begin(); i != labelTable.end(); ++i ) { 131 133 if ( ! i->second->defined() ) { 132 throw SemanticError( "Use of undefined label: " + i->first );134 throw SemanticError( "Use of undefined label: " + i->first.get_name() ); 133 135 } 134 136 (*ret)[ i->first ] = i->second->get_definition(); -
src/ControlStruct/LabelFixer.h
rc1c0928 r4d3ca1d8 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // LabelFixer.h -- 7 // LabelFixer.h -- 8 8 // 9 9 // Author : Rodolfo G. Esteves … … 20 20 #include "SynTree/SynTree.h" 21 21 #include "SynTree/Visitor.h" 22 #include "SynTree/Label.h" 22 23 #include "LabelGenerator.h" 23 24 24 #include <map> 25 25 … … 74 74 75 75 private: 76 Label label; 76 Label label; 77 77 Statement *definition; 78 78 }; 79 79 80 80 std::map < Label, Entry *> labelTable; 81 81 LabelGenerator *generator; -
src/ControlStruct/LabelGenerator.cc
rc1c0928 r4d3ca1d8 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // LabelGenerator.cc -- 7 // LabelGenerator.cc -- 8 8 // 9 9 // Author : Rodolfo G. Esteves … … 18 18 19 19 #include "LabelGenerator.h" 20 #include "SynTree/Label.h" 20 21 21 22 namespace ControlStruct { -
src/ControlStruct/MLEMutator.cc
rc1c0928 r4d3ca1d8 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // MLEMutator.cc -- 7 // MLEMutator.cc -- 8 8 // 9 9 // Author : Rodolfo G. Esteves … … 14 14 // 15 15 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++ 17 17 // generates for the same input 18 18 // -CFA puts the break label inside at the end of a switch, uC++ puts it after … … 34 34 } 35 35 36 // break labels have to come after the statement they break out of, 36 // break labels have to come after the statement they break out of, 37 37 // 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 38 // tha they need a place to jump to on a break statement, add the break label 39 39 // to the body of statements 40 40 void MLEMutator::fixBlock( std::list< Statement * > &kids ) { … … 44 44 if ( ! get_breakLabel().empty() ) { 45 45 std::list< Statement * >::iterator next = k+1; 46 Statement * stmt = 0; 46 47 if ( next == kids.end() ) { 47 48 std::list<Label> ls; ls.push_back( get_breakLabel() ); 48 kids.push_back( new NullStmt( ls ) );49 kids.push_back( stmt = new NullStmt( ls ) ); 49 50 } else { 50 ( *next)->get_labels().push_back( get_breakLabel() );51 (stmt = *next)->get_labels().push_back( get_breakLabel() ); 51 52 } 53 stmt->get_labels().front().set_statement( stmt ); 52 54 53 55 set_breakLabel(""); … … 81 83 template< typename LoopClass > 82 84 Statement *MLEMutator::handleLoopStmt( LoopClass *loopStmt ) { 83 // remember this as the most recent enclosing loop, then mutate 85 // remember this as the most recent enclosing loop, then mutate 84 86 // the body of the loop -- this will determine whether brkLabel 85 87 // and contLabel are used with branch statements … … 111 113 template< typename SwitchClass > 112 114 Statement *MLEMutator::handleSwitchStmt( SwitchClass *switchStmt ) { 113 // generate a label for breaking out of a labeled switch 115 // generate a label for breaking out of a labeled switch 114 116 Label brkLabel = generator->newLabel("switchBreak"); 115 117 enclosingSwitches.push_back( Entry(switchStmt, brkLabel) ); 116 mutateAll( switchStmt->get_branches(), *this ); 118 mutateAll( switchStmt->get_branches(), *this ); 117 119 118 120 Entry &e = enclosingSwitches.back(); … … 121 123 // only generate break label if labeled break is used 122 124 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 125 // for the purposes of keeping switch statements uniform (i.e. all statements that are 126 // direct children of a switch should be CastStmts), append the exit label + break to the 125 127 // last case statement; create a default case if there are no cases 126 128 std::list< Statement * > &branches = switchStmt->get_branches(); … … 131 133 if ( CaseStmt * c = dynamic_cast< CaseStmt * >( branches.back() ) ) { 132 134 std::list<Label> temp; temp.push_back( brkLabel ); 133 c->get_statements().push_back( new BranchStmt( temp, Label(""), BranchStmt::Break ) ); 135 Statement * stmt = new BranchStmt( temp, Label(""), BranchStmt::Break ); 136 stmt->get_labels().front().set_statement( stmt ); 137 c->get_statements().push_back( stmt ); 134 138 } else assert(0); // as of this point, all branches of a switch are still CaseStmts 135 139 } … … 206 210 // continue label goes in the body as the last statement 207 211 std::list< Label > labels; labels.push_back( e.useContExit() ); 208 newBody->get_kids().push_back( new NullStmt( labels ) ); 212 Statement * stmt = new NullStmt( labels ); 213 stmt->get_labels().front().set_statement( stmt ); 214 newBody->get_kids().push_back( stmt ); 209 215 } 210 216 211 217 if ( e.isBreakUsed() ) { 212 // break label goes after the loop -- it'll get set by the 218 // break label goes after the loop -- it'll get set by the 213 219 // outer mutator if we do this 214 set_breakLabel( e.useBreakExit() ); 220 set_breakLabel( e.useBreakExit() ); 215 221 } 216 222 … … 231 237 232 238 Statement *MLEMutator::mutate( ChooseStmt *switchStmt ) { 233 return handleSwitchStmt( switchStmt ); 239 return handleSwitchStmt( switchStmt ); 234 240 } 235 241 -
src/ControlStruct/MLEMutator.h
rc1c0928 r4d3ca1d8 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // MLEMutator.h -- 7 // MLEMutator.h -- 8 8 // 9 9 // Author : Rodolfo G. Esteves … … 23 23 #include "SynTree/SynTree.h" 24 24 #include "SynTree/Mutator.h" 25 #include "SynTree/Label.h" 25 26 26 27 #include "LabelGenerator.h" … … 38 39 Statement *mutate( BranchStmt *branchStmt ) throw ( SemanticError ); 39 40 40 Statement *mutate( CaseStmt *caseStmt ); 41 Statement *mutate( CaseStmt *caseStmt ); 41 42 Statement *mutate( SwitchStmt *switchStmt ); 42 43 Statement *mutate( ChooseStmt *switchStmt ); … … 79 80 Statement *handleLoopStmt( LoopClass *loopStmt ); 80 81 81 template< typename SwitchClass > 82 template< typename SwitchClass > 82 83 Statement *handleSwitchStmt( SwitchClass *switchStmt ); 83 84 -
src/GenPoly/Specialize.cc
rc1c0928 r4d3ca1d8 99 99 } // if 100 100 // create new thunk with same signature as formal type (C linkage, empty body) 101 FunctionDecl *thunkFunc = new FunctionDecl( thunkNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, newType, new CompoundStmt( std::list< std::string >()), false, false );101 FunctionDecl *thunkFunc = new FunctionDecl( thunkNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, newType, new CompoundStmt( noLabels ), false, false ); 102 102 thunkFunc->fixUniqueId(); 103 103 -
src/InitTweak/FixInit.cc
rc1c0928 r4d3ca1d8 16 16 #include <stack> 17 17 #include <list> 18 #include <iterator> 19 #include <algorithm> 18 20 #include "FixInit.h" 19 21 #include "InitTweak.h" … … 28 30 #include "SymTab/Indexer.h" 29 31 #include "GenPoly/PolyMutator.h" 32 #include "SynTree/AddStmtVisitor.h" 30 33 31 34 bool ctordtorp = false; 35 bool ctorp = false; 36 bool cpctorp = false; 37 bool dtorp = true; 32 38 #define PRINT( text ) if ( ctordtorp ) { text } 39 #define CP_CTOR_PRINT( text ) if ( ctordtorp || cpctorp ) { text } 40 #define DTOR_PRINT( text ) if ( ctordtorp || dtorp ) { text } 33 41 34 42 namespace InitTweak { … … 36 44 const std::list<Label> noLabels; 37 45 const std::list<Expression*> noDesignators; 38 } 39 40 class InsertImplicitCalls : public GenPoly::PolyMutator { 41 public: 42 /// wrap function application expressions as ImplicitCopyCtorExpr nodes 43 /// so that it is easy to identify which function calls need their parameters 44 /// to be copy constructed 45 static void insert( std::list< Declaration * > & translationUnit ); 46 47 virtual Expression * mutate( ApplicationExpr * appExpr ); 48 }; 49 50 class ResolveCopyCtors : public SymTab::Indexer { 51 public: 52 /// generate temporary ObjectDecls for each argument and return value of each 53 /// ImplicitCopyCtorExpr, generate/resolve copy construction expressions for each, 54 /// and generate/resolve destructors for both arguments and return value temporaries 55 static void resolveImplicitCalls( std::list< Declaration * > & translationUnit ); 56 57 virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr ); 58 59 /// create and resolve ctor/dtor expression: fname(var, [cpArg]) 60 ApplicationExpr * makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg = NULL ); 61 /// true if type does not need to be copy constructed to ensure correctness 62 bool skipCopyConstruct( Type * ); 63 private: 64 TypeSubstitution * env; 65 }; 66 67 class FixInit : public GenPoly::PolyMutator { 68 public: 69 /// expand each object declaration to use its constructor after it is declared. 70 /// insert destructor calls at the appropriate places 71 static void fixInitializers( std::list< Declaration * > &translationUnit ); 72 73 virtual DeclarationWithType * mutate( ObjectDecl *objDecl ); 74 75 virtual CompoundStmt * mutate( CompoundStmt * compoundStmt ); 76 virtual Statement * mutate( ReturnStmt * returnStmt ); 77 virtual Statement * mutate( BranchStmt * branchStmt ); 78 79 private: 80 // stack of list of statements - used to differentiate scopes 81 std::list< std::list< Statement * > > dtorStmts; 82 }; 83 84 class FixCopyCtors : public GenPoly::PolyMutator { 85 public: 86 /// expand ImplicitCopyCtorExpr nodes into the temporary declarations, copy constructors, 87 /// call expression, and destructors 88 static void fixCopyCtors( std::list< Declaration * > &translationUnit ); 89 90 virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr ); 91 92 private: 93 // stack of list of statements - used to differentiate scopes 94 std::list< std::list< Statement * > > dtorStmts; 95 }; 46 47 class InsertImplicitCalls : public GenPoly::PolyMutator { 48 public: 49 /// wrap function application expressions as ImplicitCopyCtorExpr nodes 50 /// so that it is easy to identify which function calls need their parameters 51 /// to be copy constructed 52 static void insert( std::list< Declaration * > & translationUnit ); 53 54 virtual Expression * mutate( ApplicationExpr * appExpr ); 55 }; 56 57 class ResolveCopyCtors : public SymTab::Indexer { 58 public: 59 /// generate temporary ObjectDecls for each argument and return value of each 60 /// ImplicitCopyCtorExpr, generate/resolve copy construction expressions for each, 61 /// and generate/resolve destructors for both arguments and return value temporaries 62 static void resolveImplicitCalls( std::list< Declaration * > & translationUnit ); 63 64 virtual void visit( ImplicitCopyCtorExpr * impCpCtorExpr ); 65 66 /// create and resolve ctor/dtor expression: fname(var, [cpArg]) 67 ApplicationExpr * makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg = NULL ); 68 /// true if type does not need to be copy constructed to ensure correctness 69 bool skipCopyConstruct( Type * ); 70 private: 71 TypeSubstitution * env; 72 }; 73 74 /// collects constructed object decls - used as a base class 75 class ObjDeclCollector : public AddStmtVisitor { 76 public: 77 typedef AddStmtVisitor Parent; 78 using Parent::visit; 79 typedef std::set< ObjectDecl * > ObjectSet; 80 virtual void visit( CompoundStmt *compoundStmt ); 81 virtual void visit( DeclStmt *stmt ); 82 protected: 83 ObjectSet curVars; 84 }; 85 86 struct printSet { 87 typedef ObjDeclCollector::ObjectSet ObjectSet; 88 printSet( const ObjectSet & objs ) : objs( objs ) {} 89 const ObjectSet & objs; 90 }; 91 std::ostream & operator<<( std::ostream & out, const printSet & set) { 92 out << "{ "; 93 for ( ObjectDecl * obj : set.objs ) { 94 out << obj->get_name() << ", " ; 95 } 96 out << " }"; 97 return out; 98 } 99 100 class LabelFinder : public ObjDeclCollector { 101 public: 102 typedef ObjDeclCollector Parent; 103 typedef std::map< Label, ObjectSet > LabelMap; 104 // map of Label -> live variables at that label 105 LabelMap vars; 106 107 void handleStmt( Statement * stmt ); 108 109 // xxx - This needs to be done better. 110 // allow some generalization among different kinds of nodes with 111 // with similar parentage (e.g. all expressions, all statements, etc.) 112 // important to have this to provide a single entry point so that as 113 // new subclasses are added, there is only one place that the code has 114 // to be updated, rather than ensure that every specialized class knows 115 // about every new kind of statement that might be added. 116 virtual void visit( CompoundStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 117 virtual void visit( ExprStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 118 virtual void visit( AsmStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 119 virtual void visit( IfStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 120 virtual void visit( WhileStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 121 virtual void visit( ForStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 122 virtual void visit( SwitchStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 123 virtual void visit( ChooseStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 124 virtual void visit( FallthruStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 125 virtual void visit( CaseStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 126 virtual void visit( BranchStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 127 virtual void visit( ReturnStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 128 virtual void visit( TryStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 129 virtual void visit( CatchStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 130 virtual void visit( FinallyStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 131 virtual void visit( NullStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 132 virtual void visit( DeclStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 133 virtual void visit( ImplicitCtorDtorStmt *stmt ) { handleStmt( stmt ); return Parent::visit( stmt ); } 134 }; 135 136 class InsertDtors : public ObjDeclCollector { 137 public: 138 /// insert destructor calls at the appropriate places. 139 /// must happen before CtorInit nodes are removed (currently by FixInit) 140 static void insert( std::list< Declaration * > & translationUnit ); 141 142 typedef ObjDeclCollector Parent; 143 typedef std::list< ObjectDecl * > OrderedDecls; 144 typedef std::list< OrderedDecls > OrderedDeclsStack; 145 146 InsertDtors( LabelFinder & finder ) : labelVars( finder.vars ) {} 147 148 virtual void visit( ObjectDecl * objDecl ); 149 150 virtual void visit( CompoundStmt * compoundStmt ); 151 virtual void visit( ReturnStmt * returnStmt ); 152 virtual void visit( BranchStmt * stmt ); 153 private: 154 void handleGoto( BranchStmt * stmt ); 155 156 LabelFinder::LabelMap & labelVars; 157 OrderedDeclsStack reverseDeclOrder; 158 }; 159 160 class FixInit : public GenPoly::PolyMutator { 161 public: 162 /// expand each object declaration to use its constructor after it is declared. 163 static void fixInitializers( std::list< Declaration * > &translationUnit ); 164 165 virtual DeclarationWithType * mutate( ObjectDecl *objDecl ); 166 }; 167 168 class FixCopyCtors : public GenPoly::PolyMutator { 169 public: 170 /// expand ImplicitCopyCtorExpr nodes into the temporary declarations, copy constructors, 171 /// call expression, and destructors 172 static void fixCopyCtors( std::list< Declaration * > &translationUnit ); 173 174 virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr ); 175 }; 176 } // namespace 96 177 97 178 void fix( std::list< Declaration * > & translationUnit ) { 98 179 InsertImplicitCalls::insert( translationUnit ); 99 180 ResolveCopyCtors::resolveImplicitCalls( translationUnit ); 181 InsertDtors::insert( translationUnit ); 100 182 FixInit::fixInitializers( translationUnit ); 183 101 184 // FixCopyCtors must happen after FixInit, so that destructors are placed correctly 102 185 FixCopyCtors::fixCopyCtors( translationUnit ); 103 186 } 104 187 105 void InsertImplicitCalls::insert( std::list< Declaration * > & translationUnit ) { 106 InsertImplicitCalls inserter; 107 mutateAll( translationUnit, inserter ); 108 } 109 110 void ResolveCopyCtors::resolveImplicitCalls( std::list< Declaration * > & translationUnit ) { 111 ResolveCopyCtors resolver; 112 acceptAll( translationUnit, resolver ); 113 } 114 115 void FixInit::fixInitializers( std::list< Declaration * > & translationUnit ) { 116 FixInit fixer; 117 mutateAll( translationUnit, fixer ); 118 } 119 120 void FixCopyCtors::fixCopyCtors( std::list< Declaration * > & translationUnit ) { 121 FixCopyCtors fixer; 122 mutateAll( translationUnit, fixer ); 123 } 124 125 Expression * InsertImplicitCalls::mutate( ApplicationExpr * appExpr ) { 126 appExpr = dynamic_cast< ApplicationExpr * >( Mutator::mutate( appExpr ) ); 127 assert( appExpr ); 128 129 if ( VariableExpr * function = dynamic_cast< VariableExpr * > ( appExpr->get_function() ) ) { 130 if ( function->get_var()->get_linkage() == LinkageSpec::Intrinsic ) { 131 // optimization: don't need to copy construct in order to call intrinsic functions 132 return appExpr; 133 } else if ( DeclarationWithType * funcDecl = dynamic_cast< DeclarationWithType * > ( function->get_var() ) ) { 134 FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) ); 135 assert( ftype ); 136 if ( (funcDecl->get_name() == "?{}" || funcDecl->get_name() == "?=?") && ftype->get_parameters().size() == 2 ) { 137 Type * t1 = ftype->get_parameters().front()->get_type(); 138 Type * t2 = ftype->get_parameters().back()->get_type(); 139 PointerType * ptrType = dynamic_cast< PointerType * > ( t1 ); 140 assert( ptrType ); 141 142 if ( ResolvExpr::typesCompatible( ptrType->get_base(), t2, SymTab::Indexer() ) ) { 143 // optimization: don't need to copy construct in order to call a copy constructor or 144 // assignment operator 188 namespace { 189 void InsertImplicitCalls::insert( std::list< Declaration * > & translationUnit ) { 190 InsertImplicitCalls inserter; 191 mutateAll( translationUnit, inserter ); 192 } 193 194 void ResolveCopyCtors::resolveImplicitCalls( std::list< Declaration * > & translationUnit ) { 195 ResolveCopyCtors resolver; 196 acceptAll( translationUnit, resolver ); 197 } 198 199 void FixInit::fixInitializers( std::list< Declaration * > & translationUnit ) { 200 FixInit fixer; 201 mutateAll( translationUnit, fixer ); 202 } 203 204 void InsertDtors::insert( std::list< Declaration * > & translationUnit ) { 205 LabelFinder finder; 206 InsertDtors inserter( finder ); 207 acceptAll( translationUnit, finder ); 208 acceptAll( translationUnit, inserter ); 209 } 210 211 void FixCopyCtors::fixCopyCtors( std::list< Declaration * > & translationUnit ) { 212 FixCopyCtors fixer; 213 mutateAll( translationUnit, fixer ); 214 } 215 216 Expression * InsertImplicitCalls::mutate( ApplicationExpr * appExpr ) { 217 appExpr = dynamic_cast< ApplicationExpr * >( Mutator::mutate( appExpr ) ); 218 assert( appExpr ); 219 220 if ( VariableExpr * function = dynamic_cast< VariableExpr * > ( appExpr->get_function() ) ) { 221 if ( function->get_var()->get_linkage() == LinkageSpec::Intrinsic ) { 222 // optimization: don't need to copy construct in order to call intrinsic functions 223 return appExpr; 224 } else if ( DeclarationWithType * funcDecl = dynamic_cast< DeclarationWithType * > ( function->get_var() ) ) { 225 FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) ); 226 assert( ftype ); 227 if ( (funcDecl->get_name() == "?{}" || funcDecl->get_name() == "?=?") && ftype->get_parameters().size() == 2 ) { 228 Type * t1 = ftype->get_parameters().front()->get_type(); 229 Type * t2 = ftype->get_parameters().back()->get_type(); 230 PointerType * ptrType = dynamic_cast< PointerType * > ( t1 ); 231 assert( ptrType ); 232 233 if ( ResolvExpr::typesCompatible( ptrType->get_base(), t2, SymTab::Indexer() ) ) { 234 // optimization: don't need to copy construct in order to call a copy constructor or 235 // assignment operator 236 return appExpr; 237 } 238 } else if ( funcDecl->get_name() == "^?{}" ) { 239 // correctness: never copy construct arguments to a destructor 145 240 return appExpr; 146 241 } 147 } else if ( funcDecl->get_name() == "^?{}" ) {148 // correctness: never copy construct arguments to a destructor149 return appExpr;150 242 } 151 243 } 152 } 153 PRINT( std::cerr << "InsertImplicitCalls: adding a wrapper " << appExpr << std::endl; ) 154 155 // wrap each function call so that it is easy to identify nodes that have to be copy constructed 156 ImplicitCopyCtorExpr * expr = new ImplicitCopyCtorExpr( appExpr ); 157 // save the type substitution onto the new node so that it is easy to find. 158 // Ensure it is not deleted with the ImplicitCopyCtorExpr by removing it before deletion. 159 // The substitution is needed to obtain the type of temporary variables so that copy constructor 160 // calls can be resolved. Normally this is what PolyMutator is for, but the pass that resolves 161 // copy constructor calls must be an Indexer. We could alternatively make a PolyIndexer which 162 // saves the environment, or compute the types of temporaries here, but it's much simpler to 163 // save the environment here, and more cohesive to compute temporary variables and resolve copy 164 // constructor calls together. 165 assert( env ); 166 expr->set_env( env ); 167 return expr; 168 } 169 170 bool ResolveCopyCtors::skipCopyConstruct( Type * type ) { 171 return dynamic_cast< VarArgsType * >( type ) || GenPoly::getFunctionType( type ); 172 } 173 174 ApplicationExpr * ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) { 175 assert( var ); 176 UntypedExpr * untyped = new UntypedExpr( new NameExpr( fname ) ); 177 untyped->get_args().push_back( new AddressExpr( new VariableExpr( var ) ) ); 178 if (cpArg) untyped->get_args().push_back( cpArg ); 179 180 // resolve copy constructor 181 // should only be one alternative for copy ctor and dtor expressions, since 182 // all arguments are fixed (VariableExpr and already resolved expression) 183 PRINT( std::cerr << "ResolvingCtorDtor " << untyped << std::endl; ) 184 ApplicationExpr * resolved = dynamic_cast< ApplicationExpr * >( ResolvExpr::findVoidExpression( untyped, *this ) ); 185 if ( resolved->get_env() ) { 186 env->add( *resolved->get_env() ); 187 } 188 189 assert( resolved ); 190 delete untyped; 191 return resolved; 192 } 193 194 void ResolveCopyCtors::visit( ImplicitCopyCtorExpr *impCpCtorExpr ) { 195 static UniqueName tempNamer("_tmp_cp"); 196 static UniqueName retNamer("_tmp_cp_ret"); 197 198 PRINT( std::cerr << "ResolveCopyCtors: " << impCpCtorExpr << std::endl; ) 199 Visitor::visit( impCpCtorExpr ); 200 env = impCpCtorExpr->get_env(); // xxx - maybe we really should just have a PolyIndexer... 201 202 ApplicationExpr * appExpr = impCpCtorExpr->get_callExpr(); 203 204 // take each argument and attempt to copy construct it. 205 for ( Expression * & arg : appExpr->get_args() ) { 206 PRINT( std::cerr << "Type Substitution: " << *impCpCtorExpr->get_env() << std::endl; ) 207 // xxx - need to handle tuple arguments 208 assert( ! arg->get_results().empty() ); 209 Type * result = arg->get_results().front(); 210 if ( skipCopyConstruct( result ) ) continue; // skip certain non-copyable types 211 // type may involve type variables, so apply type substitution to get temporary variable's actual type 212 result = result->clone(); 213 impCpCtorExpr->get_env()->apply( result ); 214 ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, result, 0 ); 215 tmp->get_type()->set_isConst( false ); 216 217 // create and resolve copy constructor 218 PRINT( std::cerr << "makeCtorDtor for an argument" << std::endl; ) 219 ApplicationExpr * cpCtor = makeCtorDtor( "?{}", tmp, arg ); 220 221 // if the chosen constructor is intrinsic, the copy is unnecessary, so 222 // don't create the temporary and don't call the copy constructor 223 VariableExpr * function = dynamic_cast< VariableExpr * >( cpCtor->get_function() ); 224 assert( function ); 225 if ( function->get_var()->get_linkage() != LinkageSpec::Intrinsic ) { 226 // replace argument to function call with temporary 227 arg = new CommaExpr( cpCtor, new VariableExpr( tmp ) ); 228 impCpCtorExpr->get_tempDecls().push_back( tmp ); 229 impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", tmp ) ); 230 } 231 } 232 233 // each return value from the call needs to be connected with an ObjectDecl 234 // at the call site, which is initialized with the return value and is destructed 235 // later 236 // xxx - handle multiple return values 237 ApplicationExpr * callExpr = impCpCtorExpr->get_callExpr(); 238 // xxx - is this right? callExpr may not have the right environment, because it was attached 239 // at a higher level. Trying to pass that environment along. 240 callExpr->set_env( impCpCtorExpr->get_env()->clone() ); 241 for ( Type * result : appExpr->get_results() ) { 242 result = result->clone(); 243 impCpCtorExpr->get_env()->apply( result ); 244 ObjectDecl * ret = new ObjectDecl( retNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, result, 0 ); 245 ret->get_type()->set_isConst( false ); 246 impCpCtorExpr->get_returnDecls().push_back( ret ); 247 PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; ) 248 impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", ret ) ); 249 } 250 PRINT( std::cerr << "after Resolving: " << impCpCtorExpr << std::endl; ) 251 } 252 253 254 Expression * FixCopyCtors::mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) { 255 PRINT( std::cerr << "FixCopyCtors: " << impCpCtorExpr << std::endl; ) 256 257 impCpCtorExpr = dynamic_cast< ImplicitCopyCtorExpr * >( Mutator::mutate( impCpCtorExpr ) ); 258 assert( impCpCtorExpr ); 259 260 std::list< ObjectDecl * > & tempDecls = impCpCtorExpr->get_tempDecls(); 261 std::list< ObjectDecl * > & returnDecls = impCpCtorExpr->get_returnDecls(); 262 std::list< Expression * > & dtors = impCpCtorExpr->get_dtors(); 263 264 // add all temporary declarations and their constructors 265 for ( ObjectDecl * obj : tempDecls ) { 266 stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) ); 267 } 268 for ( ObjectDecl * obj : returnDecls ) { 269 stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) ); 270 } 271 272 // add destructors after current statement 273 for ( Expression * dtor : dtors ) { 274 stmtsToAddAfter.push_back( new ExprStmt( noLabels, dtor ) ); 275 } 276 277 // xxx - update to work with multiple return values 278 ObjectDecl * returnDecl = returnDecls.empty() ? NULL : returnDecls.front(); 279 Expression * callExpr = impCpCtorExpr->get_callExpr(); 280 281 PRINT( std::cerr << "Coming out the back..." << impCpCtorExpr << std::endl; ) 282 283 // xxx - some of these aren't necessary, and can be removed once this is stable 284 dtors.clear(); 285 tempDecls.clear(); 286 returnDecls.clear(); 287 impCpCtorExpr->set_callExpr( NULL ); 288 impCpCtorExpr->set_env( NULL ); 289 delete impCpCtorExpr; 290 291 if ( returnDecl ) { 292 UntypedExpr * assign = new UntypedExpr( new NameExpr( "?=?" ) ); 293 assign->get_args().push_back( new VariableExpr( returnDecl ) ); 294 assign->get_args().push_back( callExpr ); 295 // know the result type of the assignment is the type of the LHS (minus the pointer), so 296 // add that onto the assignment expression so that later steps have the necessary information 297 assign->add_result( returnDecl->get_type()->clone() ); 298 299 Expression * retExpr = new CommaExpr( assign, new VariableExpr( returnDecl ) ); 300 if ( callExpr->get_results().front()->get_isLvalue() ) { 301 // lvalue returning functions are funny. Lvalue.cc inserts a *? in front of any 302 // lvalue returning non-intrinsic function. Add an AddressExpr to the call to negate 303 // the derefence and change the type of the return temporary from T to T* to properly 304 // capture the return value. Then dereference the result of the comma expression, since 305 // the lvalue returning call was originally wrapped with an AddressExpr. 306 // Effectively, this turns 307 // lvalue T f(); 308 // &*f() 309 // into 310 // T * tmp_cp_retN; 311 // tmp_cp_ret_N = &*(tmp_cp_ret_N = &*f(), tmp_cp_ret); 312 // which work out in terms of types, but is pretty messy. It would be nice to find a better way. 313 assign->get_args().back() = new AddressExpr( assign->get_args().back() ); 314 315 Type * resultType = returnDecl->get_type()->clone(); 316 returnDecl->set_type( new PointerType( Type::Qualifiers(), returnDecl->get_type() ) ); 317 UntypedExpr * deref = new UntypedExpr( new NameExpr( "*?" ) ); 318 deref->get_args().push_back( retExpr ); 319 deref->add_result( resultType ); 320 retExpr = deref; 321 } 322 // xxx - might need to set env on retExpr... 323 // retExpr->set_env( env->clone() ); 324 return retExpr; 325 } else { 326 return callExpr; 327 } 328 } 329 330 DeclarationWithType *FixInit::mutate( ObjectDecl *objDecl ) { 331 // first recursively handle pieces of ObjectDecl so that they aren't missed by other visitors 332 // when the init is removed from the ObjectDecl 333 objDecl = dynamic_cast< ObjectDecl * >( Mutator::mutate( objDecl ) ); 334 335 if ( ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ) ) { 336 // a decision should have been made by the resolver, so ctor and init are not both non-NULL 337 assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() ); 338 if ( Statement * ctor = ctorInit->get_ctor() ) { 339 if ( objDecl->get_storageClass() == DeclarationNode::Static ) { 340 // generate: 341 // static bool __objName_uninitialized = true; 342 // if (__objName_uninitialized) { 343 // __ctor(__objName); 344 // void dtor_atexit() { 345 // __dtor(__objName); 346 // } 347 // on_exit(dtorOnExit, &__objName); 348 // __objName_uninitialized = false; 349 // } 350 351 // generate first line 352 BasicType * boolType = new BasicType( Type::Qualifiers(), BasicType::Bool ); 353 SingleInit * boolInitExpr = new SingleInit( new ConstantExpr( Constant( boolType->clone(), "1" ) ), noDesignators ); 354 ObjectDecl * isUninitializedVar = new ObjectDecl( objDecl->get_mangleName() + "_uninitialized", DeclarationNode::Static, LinkageSpec::Cforall, 0, boolType, boolInitExpr ); 355 isUninitializedVar->fixUniqueId(); 356 357 // void dtor_atexit(...) {...} 358 FunctionDecl * dtorCaller = new FunctionDecl( objDecl->get_mangleName() + "_dtor_atexit", DeclarationNode::NoStorageClass, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false ); 359 dtorCaller->fixUniqueId(); 360 dtorCaller->get_statements()->get_kids().push_back( ctorInit->get_dtor() ); 361 362 // on_exit(dtor_atexit); 363 UntypedExpr * callAtexit = new UntypedExpr( new NameExpr( "atexit" ) ); 364 callAtexit->get_args().push_back( new VariableExpr( dtorCaller ) ); 365 366 // __objName_uninitialized = false; 367 UntypedExpr * setTrue = new UntypedExpr( new NameExpr( "?=?" ) ); 368 setTrue->get_args().push_back( new VariableExpr( isUninitializedVar ) ); 369 setTrue->get_args().push_back( new ConstantExpr( Constant( boolType->clone(), "0" ) ) ); 370 371 // generate body of if 372 CompoundStmt * initStmts = new CompoundStmt( noLabels ); 373 std::list< Statement * > & body = initStmts->get_kids(); 374 body.push_back( ctor ); 375 body.push_back( new DeclStmt( noLabels, dtorCaller ) ); 376 body.push_back( new ExprStmt( noLabels, callAtexit ) ); 377 body.push_back( new ExprStmt( noLabels, setTrue ) ); 378 379 // put it all together 380 IfStmt * ifStmt = new IfStmt( noLabels, new VariableExpr( isUninitializedVar ), initStmts, 0 ); 381 stmtsToAddAfter.push_back( new DeclStmt( noLabels, isUninitializedVar ) ); 382 stmtsToAddAfter.push_back( ifStmt ); 244 CP_CTOR_PRINT( std::cerr << "InsertImplicitCalls: adding a wrapper " << appExpr << std::endl; ) 245 246 // wrap each function call so that it is easy to identify nodes that have to be copy constructed 247 ImplicitCopyCtorExpr * expr = new ImplicitCopyCtorExpr( appExpr ); 248 // save the type substitution onto the new node so that it is easy to find. 249 // Ensure it is not deleted with the ImplicitCopyCtorExpr by removing it before deletion. 250 // The substitution is needed to obtain the type of temporary variables so that copy constructor 251 // calls can be resolved. Normally this is what PolyMutator is for, but the pass that resolves 252 // copy constructor calls must be an Indexer. We could alternatively make a PolyIndexer which 253 // saves the environment, or compute the types of temporaries here, but it's much simpler to 254 // save the environment here, and more cohesive to compute temporary variables and resolve copy 255 // constructor calls together. 256 assert( env ); 257 expr->set_env( env ); 258 return expr; 259 } 260 261 bool ResolveCopyCtors::skipCopyConstruct( Type * type ) { 262 return dynamic_cast< VarArgsType * >( type ) || GenPoly::getFunctionType( type ); 263 } 264 265 ApplicationExpr * ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) { 266 assert( var ); 267 UntypedExpr * untyped = new UntypedExpr( new NameExpr( fname ) ); 268 untyped->get_args().push_back( new AddressExpr( new VariableExpr( var ) ) ); 269 if (cpArg) untyped->get_args().push_back( cpArg ); 270 271 // resolve copy constructor 272 // should only be one alternative for copy ctor and dtor expressions, since 273 // all arguments are fixed (VariableExpr and already resolved expression) 274 CP_CTOR_PRINT( std::cerr << "ResolvingCtorDtor " << untyped << std::endl; ) 275 ApplicationExpr * resolved = dynamic_cast< ApplicationExpr * >( ResolvExpr::findVoidExpression( untyped, *this ) ); 276 if ( resolved->get_env() ) { 277 env->add( *resolved->get_env() ); 278 } 279 280 assert( resolved ); 281 delete untyped; 282 return resolved; 283 } 284 285 void ResolveCopyCtors::visit( ImplicitCopyCtorExpr *impCpCtorExpr ) { 286 static UniqueName tempNamer("_tmp_cp"); 287 static UniqueName retNamer("_tmp_cp_ret"); 288 289 CP_CTOR_PRINT( std::cerr << "ResolveCopyCtors: " << impCpCtorExpr << std::endl; ) 290 Visitor::visit( impCpCtorExpr ); 291 env = impCpCtorExpr->get_env(); // xxx - maybe we really should just have a PolyIndexer... 292 293 ApplicationExpr * appExpr = impCpCtorExpr->get_callExpr(); 294 295 // take each argument and attempt to copy construct it. 296 for ( Expression * & arg : appExpr->get_args() ) { 297 CP_CTOR_PRINT( std::cerr << "Type Substitution: " << *impCpCtorExpr->get_env() << std::endl; ) 298 // xxx - need to handle tuple arguments 299 assert( ! arg->get_results().empty() ); 300 Type * result = arg->get_results().front(); 301 if ( skipCopyConstruct( result ) ) continue; // skip certain non-copyable types 302 // type may involve type variables, so apply type substitution to get temporary variable's actual type 303 result = result->clone(); 304 impCpCtorExpr->get_env()->apply( result ); 305 ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, result, 0 ); 306 tmp->get_type()->set_isConst( false ); 307 308 // create and resolve copy constructor 309 CP_CTOR_PRINT( std::cerr << "makeCtorDtor for an argument" << std::endl; ) 310 ApplicationExpr * cpCtor = makeCtorDtor( "?{}", tmp, arg ); 311 312 // if the chosen constructor is intrinsic, the copy is unnecessary, so 313 // don't create the temporary and don't call the copy constructor 314 VariableExpr * function = dynamic_cast< VariableExpr * >( cpCtor->get_function() ); 315 assert( function ); 316 if ( function->get_var()->get_linkage() != LinkageSpec::Intrinsic ) { 317 // replace argument to function call with temporary 318 arg = new CommaExpr( cpCtor, new VariableExpr( tmp ) ); 319 impCpCtorExpr->get_tempDecls().push_back( tmp ); 320 impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", tmp ) ); 321 } 322 } 323 324 // each return value from the call needs to be connected with an ObjectDecl 325 // at the call site, which is initialized with the return value and is destructed 326 // later 327 // xxx - handle multiple return values 328 ApplicationExpr * callExpr = impCpCtorExpr->get_callExpr(); 329 // xxx - is this right? callExpr may not have the right environment, because it was attached 330 // at a higher level. Trying to pass that environment along. 331 callExpr->set_env( impCpCtorExpr->get_env()->clone() ); 332 for ( Type * result : appExpr->get_results() ) { 333 result = result->clone(); 334 impCpCtorExpr->get_env()->apply( result ); 335 ObjectDecl * ret = new ObjectDecl( retNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, result, 0 ); 336 ret->get_type()->set_isConst( false ); 337 impCpCtorExpr->get_returnDecls().push_back( ret ); 338 CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; ) 339 impCpCtorExpr->get_dtors().push_front( makeCtorDtor( "^?{}", ret ) ); 340 } 341 CP_CTOR_PRINT( std::cerr << "after Resolving: " << impCpCtorExpr << std::endl; ) 342 } 343 344 345 Expression * FixCopyCtors::mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) { 346 CP_CTOR_PRINT( std::cerr << "FixCopyCtors: " << impCpCtorExpr << std::endl; ) 347 348 impCpCtorExpr = dynamic_cast< ImplicitCopyCtorExpr * >( Mutator::mutate( impCpCtorExpr ) ); 349 assert( impCpCtorExpr ); 350 351 std::list< ObjectDecl * > & tempDecls = impCpCtorExpr->get_tempDecls(); 352 std::list< ObjectDecl * > & returnDecls = impCpCtorExpr->get_returnDecls(); 353 std::list< Expression * > & dtors = impCpCtorExpr->get_dtors(); 354 355 // add all temporary declarations and their constructors 356 for ( ObjectDecl * obj : tempDecls ) { 357 stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) ); 358 } 359 for ( ObjectDecl * obj : returnDecls ) { 360 stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) ); 361 } 362 363 // add destructors after current statement 364 for ( Expression * dtor : dtors ) { 365 stmtsToAddAfter.push_back( new ExprStmt( noLabels, dtor ) ); 366 } 367 368 // xxx - update to work with multiple return values 369 ObjectDecl * returnDecl = returnDecls.empty() ? NULL : returnDecls.front(); 370 Expression * callExpr = impCpCtorExpr->get_callExpr(); 371 372 CP_CTOR_PRINT( std::cerr << "Coming out the back..." << impCpCtorExpr << std::endl; ) 373 374 // detach fields from wrapper node so that it can be deleted without deleting too much 375 dtors.clear(); 376 tempDecls.clear(); 377 returnDecls.clear(); 378 impCpCtorExpr->set_callExpr( NULL ); 379 impCpCtorExpr->set_env( NULL ); 380 delete impCpCtorExpr; 381 382 if ( returnDecl ) { 383 UntypedExpr * assign = new UntypedExpr( new NameExpr( "?=?" ) ); 384 assign->get_args().push_back( new VariableExpr( returnDecl ) ); 385 assign->get_args().push_back( callExpr ); 386 // know the result type of the assignment is the type of the LHS (minus the pointer), so 387 // add that onto the assignment expression so that later steps have the necessary information 388 assign->add_result( returnDecl->get_type()->clone() ); 389 390 Expression * retExpr = new CommaExpr( assign, new VariableExpr( returnDecl ) ); 391 if ( callExpr->get_results().front()->get_isLvalue() ) { 392 // lvalue returning functions are funny. Lvalue.cc inserts a *? in front of any 393 // lvalue returning non-intrinsic function. Add an AddressExpr to the call to negate 394 // the derefence and change the type of the return temporary from T to T* to properly 395 // capture the return value. Then dereference the result of the comma expression, since 396 // the lvalue returning call was originally wrapped with an AddressExpr. 397 // Effectively, this turns 398 // lvalue T f(); 399 // &*f() 400 // into 401 // T * tmp_cp_retN; 402 // tmp_cp_ret_N = &*(tmp_cp_ret_N = &*f(), tmp_cp_ret); 403 // which work out in terms of types, but is pretty messy. It would be nice to find a better way. 404 assign->get_args().back() = new AddressExpr( assign->get_args().back() ); 405 406 Type * resultType = returnDecl->get_type()->clone(); 407 returnDecl->set_type( new PointerType( Type::Qualifiers(), returnDecl->get_type() ) ); 408 UntypedExpr * deref = new UntypedExpr( new NameExpr( "*?" ) ); 409 deref->get_args().push_back( retExpr ); 410 deref->add_result( resultType ); 411 retExpr = deref; 412 } 413 // xxx - might need to set env on retExpr... 414 // retExpr->set_env( env->clone() ); 415 return retExpr; 416 } else { 417 return callExpr; 418 } 419 } 420 421 DeclarationWithType *FixInit::mutate( ObjectDecl *objDecl ) { 422 // first recursively handle pieces of ObjectDecl so that they aren't missed by other visitors 423 // when the init is removed from the ObjectDecl 424 objDecl = dynamic_cast< ObjectDecl * >( Mutator::mutate( objDecl ) ); 425 426 if ( ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ) ) { 427 // a decision should have been made by the resolver, so ctor and init are not both non-NULL 428 assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() ); 429 if ( Statement * ctor = ctorInit->get_ctor() ) { 430 if ( objDecl->get_storageClass() == DeclarationNode::Static ) { 431 // generate: 432 // static bool __objName_uninitialized = true; 433 // if (__objName_uninitialized) { 434 // __ctor(__objName); 435 // void dtor_atexit() { 436 // __dtor(__objName); 437 // } 438 // on_exit(dtorOnExit, &__objName); 439 // __objName_uninitialized = false; 440 // } 441 442 // generate first line 443 BasicType * boolType = new BasicType( Type::Qualifiers(), BasicType::Bool ); 444 SingleInit * boolInitExpr = new SingleInit( new ConstantExpr( Constant( boolType->clone(), "1" ) ), noDesignators ); 445 ObjectDecl * isUninitializedVar = new ObjectDecl( objDecl->get_mangleName() + "_uninitialized", DeclarationNode::Static, LinkageSpec::Cforall, 0, boolType, boolInitExpr ); 446 isUninitializedVar->fixUniqueId(); 447 448 // void dtor_atexit(...) {...} 449 FunctionDecl * dtorCaller = new FunctionDecl( objDecl->get_mangleName() + "_dtor_atexit", DeclarationNode::NoStorageClass, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false ); 450 dtorCaller->fixUniqueId(); 451 dtorCaller->get_statements()->get_kids().push_back( ctorInit->get_dtor() ); 452 453 // on_exit(dtor_atexit); 454 UntypedExpr * callAtexit = new UntypedExpr( new NameExpr( "atexit" ) ); 455 callAtexit->get_args().push_back( new VariableExpr( dtorCaller ) ); 456 457 // __objName_uninitialized = false; 458 UntypedExpr * setTrue = new UntypedExpr( new NameExpr( "?=?" ) ); 459 setTrue->get_args().push_back( new VariableExpr( isUninitializedVar ) ); 460 setTrue->get_args().push_back( new ConstantExpr( Constant( boolType->clone(), "0" ) ) ); 461 462 // generate body of if 463 CompoundStmt * initStmts = new CompoundStmt( noLabels ); 464 std::list< Statement * > & body = initStmts->get_kids(); 465 body.push_back( ctor ); 466 body.push_back( new DeclStmt( noLabels, dtorCaller ) ); 467 body.push_back( new ExprStmt( noLabels, callAtexit ) ); 468 body.push_back( new ExprStmt( noLabels, setTrue ) ); 469 470 // put it all together 471 IfStmt * ifStmt = new IfStmt( noLabels, new VariableExpr( isUninitializedVar ), initStmts, 0 ); 472 stmtsToAddAfter.push_back( new DeclStmt( noLabels, isUninitializedVar ) ); 473 stmtsToAddAfter.push_back( ifStmt ); 474 } else { 475 stmtsToAddAfter.push_back( ctor ); 476 } 477 objDecl->set_init( NULL ); 478 ctorInit->set_ctor( NULL ); 479 } else if ( Initializer * init = ctorInit->get_init() ) { 480 objDecl->set_init( init ); 481 ctorInit->set_init( NULL ); 383 482 } else { 384 stmtsToAddAfter.push_back( ctor );385 dtorStmts.back().push_front( ctorInit->get_dtor());483 // no constructor and no initializer, which is okay 484 objDecl->set_init( NULL ); 386 485 } 387 objDecl->set_init( NULL ); 388 ctorInit->set_ctor( NULL ); 389 ctorInit->set_dtor( NULL ); // xxx - only destruct when constructing? Probably not? 390 } else if ( Initializer * init = ctorInit->get_init() ) { 391 objDecl->set_init( init ); 392 ctorInit->set_init( NULL ); 393 } else { 394 // no constructor and no initializer, which is okay 395 objDecl->set_init( NULL ); 396 } 397 delete ctorInit; 398 } 399 return objDecl; 400 } 401 402 namespace { 486 delete ctorInit; 487 } 488 return objDecl; 489 } 490 491 void ObjDeclCollector::visit( CompoundStmt *compoundStmt ) { 492 std::set< ObjectDecl * > prevVars = curVars; 493 Parent::visit( compoundStmt ); 494 curVars = prevVars; 495 } 496 497 void ObjDeclCollector::visit( DeclStmt *stmt ) { 498 if ( ObjectDecl * objDecl = dynamic_cast< ObjectDecl * > ( stmt->get_decl() ) ) { 499 curVars.insert( objDecl ); 500 } 501 return Parent::visit( stmt ); 502 } 503 504 void LabelFinder::handleStmt( Statement * stmt ) { 505 for ( Label l : stmt->get_labels() ) { 506 vars[l] = curVars; 507 } 508 } 509 403 510 template<typename Iterator, typename OutputIterator> 404 511 void insertDtors( Iterator begin, Iterator end, OutputIterator out ) { 405 512 for ( Iterator it = begin ; it != end ; ++it ) { 406 // remove if instrinsic destructor statement. Note that this is only called 407 // on lists of implicit dtors, so if the user manually calls an intrinsic 408 // dtor then the call must (and will) still be generated since the argument 409 // may contain side effects. 410 if ( ! isInstrinsicSingleArgCallStmt( *it ) ) { 411 // don't need to call intrinsic dtor, because it does nothing, but 412 // non-intrinsic dtors must be called 413 *out++ = (*it)->clone(); 513 // extract destructor statement from the object decl and 514 // insert it into the output. Note that this is only called 515 // on lists of non-static objects with implicit non-intrinsic 516 // dtors, so if the user manually calls an intrinsic dtor 517 // then the call must (and will) still be generated since 518 // the argument may contain side effects. 519 ObjectDecl * objDecl = *it; 520 ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ); 521 assert( ctorInit && ctorInit->get_dtor() ); 522 *out++ = ctorInit->get_dtor()->clone(); 523 } 524 } 525 526 void InsertDtors::visit( ObjectDecl * objDecl ) { 527 // remember non-static destructed objects so that their destructors can be inserted later 528 if ( objDecl->get_storageClass() != DeclarationNode::Static ) { 529 if ( ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ) ) { 530 // a decision should have been made by the resolver, so ctor and init are not both non-NULL 531 assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() ); 532 Statement * dtor = ctorInit->get_dtor(); 533 if ( dtor && ! isInstrinsicSingleArgCallStmt( dtor ) ) { 534 // don't need to call intrinsic dtor, because it does nothing, but 535 // non-intrinsic dtors must be called 536 reverseDeclOrder.front().push_front( objDecl ); 537 } 414 538 } 415 539 } 416 } 417 } 418 419 CompoundStmt * FixInit::mutate( CompoundStmt * compoundStmt ) { 420 // mutate statements - this will also populate dtorStmts list. 421 // don't want to dump all destructors when block is left, 422 // just the destructors associated with variables defined in this block, 423 // so push a new list to the top of the stack so that we can differentiate scopes 424 dtorStmts.push_back( std::list<Statement *>() ); 425 426 compoundStmt = PolyMutator::mutate( compoundStmt ); 427 std::list< Statement * > & statements = compoundStmt->get_kids(); 428 429 insertDtors( dtorStmts.back().begin(), dtorStmts.back().end(), back_inserter( statements ) ); 430 431 deleteAll( dtorStmts.back() ); 432 dtorStmts.pop_back(); 433 return compoundStmt; 434 } 435 436 Statement * FixInit::mutate( ReturnStmt * returnStmt ) { 437 for ( std::list< std::list< Statement * > >::reverse_iterator list = dtorStmts.rbegin(); list != dtorStmts.rend(); ++list ) { 438 insertDtors( list->begin(), list->end(), back_inserter( stmtsToAdd ) ); 439 } 440 return Mutator::mutate( returnStmt ); 441 } 442 443 Statement * FixInit::mutate( BranchStmt * branchStmt ) { 444 // TODO: adding to the end of a block isn't sufficient, since 445 // return/break/goto should trigger destructor when block is left. 446 switch( branchStmt->get_type() ) { 447 case BranchStmt::Continue: 448 case BranchStmt::Break: 449 insertDtors( dtorStmts.back().begin(), dtorStmts.back().end(), back_inserter( stmtsToAdd ) ); 450 break; 451 case BranchStmt::Goto: 452 // xxx 453 // if goto leaves a block, generate dtors for every block it leaves 454 // if goto is in same block but earlier statement, destruct every object that was defined after the statement 455 break; 456 default: 457 assert( false ); 458 } 459 return Mutator::mutate( branchStmt ); 460 } 461 462 540 Parent::visit( objDecl ); 541 } 542 543 void InsertDtors::visit( CompoundStmt * compoundStmt ) { 544 // visit statements - this will also populate reverseDeclOrder list. 545 // don't want to dump all destructors when block is left, 546 // just the destructors associated with variables defined in this block, 547 // so push a new list to the top of the stack so that we can differentiate scopes 548 reverseDeclOrder.push_front( OrderedDecls() ); 549 Parent::visit( compoundStmt ); 550 551 std::list< Statement * > & statements = compoundStmt->get_kids(); 552 insertDtors( reverseDeclOrder.front().begin(), reverseDeclOrder.front().end(), back_inserter( statements ) ); 553 554 // xxx - ?? 555 // deleteAll( dtorStmts.back() ); 556 reverseDeclOrder.pop_front(); 557 } 558 559 void InsertDtors::visit( ReturnStmt * returnStmt ) { 560 for ( OrderedDecls & od : reverseDeclOrder ) { 561 insertDtors( od.begin(), od.end(), back_inserter( stmtsToAdd ) ); 562 } 563 } 564 565 void InsertDtors::handleGoto( BranchStmt * stmt ) { 566 assert( stmt->get_type() == BranchStmt::Goto ); 567 // S_L = lvars = set of objects in scope at label definition 568 // S_G = curVars = set of objects in scope at goto statement 569 ObjectSet & lvars = labelVars[ stmt->get_target() ]; 570 571 DTOR_PRINT( 572 std::cerr << "at goto label: " << stmt->get_target().get_name() << std::endl; 573 std::cerr << "S_G = " << printSet( curVars ) << std::endl; 574 std::cerr << "S_L = " << printSet( lvars ) << std::endl; 575 ) 576 577 ObjectSet diff; 578 // S_L-S_G results in set of objects whose construction is skipped - it's an error if this set is non-empty 579 std::set_difference( lvars.begin(), lvars.end(), curVars.begin(), curVars.end(), std::inserter( diff, diff.begin() ) ); 580 DTOR_PRINT( 581 std::cerr << "S_L-S_G = " << printSet( diff ) << std::endl; 582 ) 583 if ( ! diff.empty() ) { 584 throw SemanticError( std::string("jump to label '") + stmt->get_target().get_name() + "' crosses initialization of " + (*diff.begin())->get_name() + " ", stmt ); 585 } 586 // S_G-S_L results in set of objects that must be destructed 587 diff.clear(); 588 std::set_difference( curVars.begin(), curVars.end(), lvars.begin(), lvars.end(), std::inserter( diff, diff.end() ) ); 589 DTOR_PRINT( 590 std::cerr << "S_G-S_L = " << printSet( diff ) << std::endl; 591 ) 592 if ( ! diff.empty() ) { 593 // go through decl ordered list of objectdecl. for each element that occurs in diff, output destructor 594 OrderedDecls ordered; 595 for ( OrderedDecls & rdo : reverseDeclOrder ) { 596 // add elements from reverseDeclOrder into ordered if they occur in diff - it is key that this happens in reverse declaration order. 597 copy_if( rdo.begin(), rdo.end(), back_inserter( ordered ), [&]( ObjectDecl * objDecl ) { return diff.count( objDecl ); } ); 598 } 599 insertDtors( ordered.begin(), ordered.end(), back_inserter( stmtsToAdd ) ); 600 } 601 } 602 603 void InsertDtors::visit( BranchStmt * stmt ) { 604 // TODO: adding to the end of a block isn't sufficient, since 605 // return/break/goto should trigger destructor when block is left. 606 switch( stmt->get_type() ) { 607 case BranchStmt::Continue: 608 case BranchStmt::Break: 609 // xxx - easiest thing to do: generate a label for every break/continue 610 // this label is unused, so attach unused attribute to it 611 // finally, all of these cases can be the same (this is less efficient than it could be, 612 // because the S_L-S_G check is unnecessary [the set should always be empty], but this 613 // serves as a bit of a sanity check, so I'm okay with it.) 614 // xxx - this is insufficient, because multiple blocks can be opened in a switch or loop 615 insertDtors( reverseDeclOrder.front().begin(), reverseDeclOrder.front().end(), back_inserter( stmtsToAdd ) ); 616 break; 617 case BranchStmt::Goto: 618 handleGoto( stmt ); 619 break; 620 default: 621 assert( false ); 622 } 623 } 624 } // namespace 463 625 } // namespace InitTweak 464 626 -
src/InitTweak/InitTweak.cc
rc1c0928 r4d3ca1d8 115 115 116 116 namespace { 117 template<typename CallExpr> 118 std::string funcName( CallExpr * expr ) { 119 Expression * func = expr->get_function(); 117 std::string funcName( Expression * func ) { 120 118 if ( NameExpr * nameExpr = dynamic_cast< NameExpr * >( func ) ) { 121 119 return nameExpr->get_name(); 122 120 } else if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( func ) ) { 123 121 return varExpr->get_var()->get_name(); 122 } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( func ) ) { 123 return funcName( castExpr->get_arg() ); 124 124 } else { 125 125 assert( false && "Unexpected expression type being called as a function in call expression" ); … … 130 130 std::string getFunctionName( Expression * expr ) { 131 131 if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr ) ) { 132 return funcName( appExpr );132 return funcName( appExpr->get_function() ); 133 133 } else if ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * > ( expr ) ) { 134 return funcName( untypedExpr );134 return funcName( untypedExpr->get_function() ); 135 135 } else { 136 std::cerr << expr << std::endl; 136 137 assert( false && "Unexpected expression type passed to getFunctionName" ); 137 138 } -
src/Makefile.in
rc1c0928 r4d3ca1d8 194 194 SynTree/driver_cfa_cpp-Visitor.$(OBJEXT) \ 195 195 SynTree/driver_cfa_cpp-Mutator.$(OBJEXT) \ 196 SynTree/driver_cfa_cpp-AddStmtVisitor.$(OBJEXT) \ 196 197 SynTree/driver_cfa_cpp-TypeSubstitution.$(OBJEXT) \ 197 198 SynTree/driver_cfa_cpp-Attribute.$(OBJEXT) \ … … 412 413 SynTree/NamedTypeDecl.cc SynTree/TypeDecl.cc \ 413 414 SynTree/Initializer.cc SynTree/Visitor.cc SynTree/Mutator.cc \ 414 SynTree/ TypeSubstitution.cc SynTree/Attribute.cc \415 Tuples/Mutate.cc Tuples/AssignExpand.cc \415 SynTree/AddStmtVisitor.cc SynTree/TypeSubstitution.cc \ 416 SynTree/Attribute.cc Tuples/Mutate.cc Tuples/AssignExpand.cc \ 416 417 Tuples/FunctionFixer.cc Tuples/TupleAssignment.cc \ 417 418 Tuples/FunctionChecker.cc Tuples/NameMatcher.cc … … 782 783 SynTree/driver_cfa_cpp-Mutator.$(OBJEXT): SynTree/$(am__dirstamp) \ 783 784 SynTree/$(DEPDIR)/$(am__dirstamp) 785 SynTree/driver_cfa_cpp-AddStmtVisitor.$(OBJEXT): \ 786 SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp) 784 787 SynTree/driver_cfa_cpp-TypeSubstitution.$(OBJEXT): \ 785 788 SynTree/$(am__dirstamp) SynTree/$(DEPDIR)/$(am__dirstamp) … … 878 881 -rm -f SymTab/driver_cfa_cpp-TypeEquality.$(OBJEXT) 879 882 -rm -f SymTab/driver_cfa_cpp-Validate.$(OBJEXT) 883 -rm -f SynTree/driver_cfa_cpp-AddStmtVisitor.$(OBJEXT) 880 884 -rm -f SynTree/driver_cfa_cpp-AddressExpr.$(OBJEXT) 881 885 -rm -f SynTree/driver_cfa_cpp-AggregateDecl.$(OBJEXT) … … 988 992 @AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-TypeEquality.Po@am__quote@ 989 993 @AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-Validate.Po@am__quote@ 994 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-AddStmtVisitor.Po@am__quote@ 990 995 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-AddressExpr.Po@am__quote@ 991 996 @AMDEP_TRUE@@am__include@ @am__quote@SynTree/$(DEPDIR)/driver_cfa_cpp-AggregateDecl.Po@am__quote@ … … 2415 2420 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 2416 2421 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-Mutator.obj `if test -f 'SynTree/Mutator.cc'; then $(CYGPATH_W) 'SynTree/Mutator.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/Mutator.cc'; fi` 2422 2423 SynTree/driver_cfa_cpp-AddStmtVisitor.o: SynTree/AddStmtVisitor.cc 2424 @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-AddStmtVisitor.o -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-AddStmtVisitor.Tpo -c -o SynTree/driver_cfa_cpp-AddStmtVisitor.o `test -f 'SynTree/AddStmtVisitor.cc' || echo '$(srcdir)/'`SynTree/AddStmtVisitor.cc 2425 @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-AddStmtVisitor.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-AddStmtVisitor.Po 2426 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='SynTree/AddStmtVisitor.cc' object='SynTree/driver_cfa_cpp-AddStmtVisitor.o' libtool=no @AMDEPBACKSLASH@ 2427 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 2428 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-AddStmtVisitor.o `test -f 'SynTree/AddStmtVisitor.cc' || echo '$(srcdir)/'`SynTree/AddStmtVisitor.cc 2429 2430 SynTree/driver_cfa_cpp-AddStmtVisitor.obj: SynTree/AddStmtVisitor.cc 2431 @am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SynTree/driver_cfa_cpp-AddStmtVisitor.obj -MD -MP -MF SynTree/$(DEPDIR)/driver_cfa_cpp-AddStmtVisitor.Tpo -c -o SynTree/driver_cfa_cpp-AddStmtVisitor.obj `if test -f 'SynTree/AddStmtVisitor.cc'; then $(CYGPATH_W) 'SynTree/AddStmtVisitor.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/AddStmtVisitor.cc'; fi` 2432 @am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) SynTree/$(DEPDIR)/driver_cfa_cpp-AddStmtVisitor.Tpo SynTree/$(DEPDIR)/driver_cfa_cpp-AddStmtVisitor.Po 2433 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='SynTree/AddStmtVisitor.cc' object='SynTree/driver_cfa_cpp-AddStmtVisitor.obj' libtool=no @AMDEPBACKSLASH@ 2434 @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 2435 @am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SynTree/driver_cfa_cpp-AddStmtVisitor.obj `if test -f 'SynTree/AddStmtVisitor.cc'; then $(CYGPATH_W) 'SynTree/AddStmtVisitor.cc'; else $(CYGPATH_W) '$(srcdir)/SynTree/AddStmtVisitor.cc'; fi` 2417 2436 2418 2437 SynTree/driver_cfa_cpp-TypeSubstitution.o: SynTree/TypeSubstitution.cc -
src/Parser/ExpressionNode.cc
rc1c0928 r4d3ca1d8 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // ExpressionNode.cc -- 8 // 7 // ExpressionNode.cc -- 8 // 9 9 // Author : Rodolfo G. Esteves 10 10 // Created On : Sat May 16 13:17:07 2015 … … 12 12 // Last Modified On : Mon Jun 13 14:46:17 2016 13 13 // Update Count : 307 14 // 14 // 15 15 16 16 #include <cassert> … … 231 231 // "abc" "def" "ghi" => "abcdefghi", remove new text from quotes and insert before last quote in old string. 232 232 value.insert( value.length() - 1, newValue->substr( 1, newValue->length() - 2 ) ); 233 233 234 234 delete newValue; // allocated by lexer 235 235 return this; … … 347 347 348 348 if ( isArrayIndex ) { 349 // need to traverse entire structure and change any instances of 0 or 1 to 349 // need to traverse entire structure and change any instances of 0 or 1 to 350 350 // ConstantExpr 351 351 DesignatorFixer fixer; … … 440 440 } 441 441 442 CompositeExprNode::CompositeExprNode( const CompositeExprNode &other ) : ExpressionNode( other ), function( maybeClone( other.function ) ) {442 CompositeExprNode::CompositeExprNode( const CompositeExprNode &other ) : ExpressionNode( other ), function( maybeClone( other.function ) ), arguments( 0 ) { 443 443 ParseNode *cur = other.arguments; 444 444 while ( cur ) { … … 608 608 { 609 609 assert( args.size() == 2 ); 610 610 611 611 if ( TypeValueNode * arg = dynamic_cast<TypeValueNode *>( get_args() ) ) { 612 612 NameExpr *member = dynamic_cast<NameExpr *>( args.back() ); -
src/Parser/ParseNode.h
rc1c0928 r4d3ca1d8 28 28 //#include "SynTree/Declaration.h" 29 29 #include "Common/UniqueName.h" 30 #include "SynTree/Label.h" 30 31 31 32 class ExpressionNode; … … 284 285 virtual void printOneLine( std::ostream &, int indent = 0) const; 285 286 286 const std::list< std::string> &get_labels() const { return labels; };287 const std::list< Label > &get_labels() const { return labels; }; 287 288 void append_label( std::string *label ) { labels.push_back( *label ); delete label; } 288 289 private: 289 std::list< std::string> labels;290 std::list< Label > labels; 290 291 }; 291 292 … … 524 525 ExpressionNode *output, *input; 525 526 ConstantNode *clobber; 526 std::list< std::string> gotolabels;527 std::list< Label > gotolabels; 527 528 }; 528 529 -
src/Parser/StatementNode.cc
rc1c0928 r4d3ca1d8 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // StatementNode.cc -- 7 // StatementNode.cc -- 8 8 // 9 9 // Author : Rodolfo G. Esteves … … 27 27 28 28 const char *StatementNode::StType[] = { 29 "Exp", "If", "Switch", "Case", "Default", "Choose", "Fallthru", 30 "While", "Do", "For", 29 "Exp", "If", "Switch", "Case", "Default", "Choose", "Fallthru", 30 "While", "Do", "For", 31 31 "Goto", "Continue", "Break", "Return", "Throw", 32 32 "Try", "Catch", "Finally", "Asm", … … 62 62 StatementNode::StatementNode( Type t, ExpressionNode *ctrl_label, StatementNode *block ) : type( t ), control( ctrl_label ), block( block ), labels( 0 ), target( 0 ), decl( 0 ), isCatchRest ( false ) { 63 63 this->control = ( t == Default ) ? 0 : control; 64 } 64 } 65 65 66 66 StatementNode::StatementNode( Type t, string *target ) : type( t ), control( 0 ), block( 0 ), labels( 0 ), target( target ), decl( 0 ), isCatchRest ( false ) {} … … 74 74 75 75 StatementNode * StatementNode::newCatchStmt( DeclarationNode *d, StatementNode *s, bool catchRestP ) { 76 StatementNode *ret = new StatementNode( StatementNode::Catch, 0, s ); 76 StatementNode *ret = new StatementNode( StatementNode::Catch, 0, s ); 77 77 ret->addDeclaration( d ); 78 78 ret->setCatchRest( catchRestP ); … … 101 101 StatementNode *StatementNode::add_label( const std::string *l ) { 102 102 if ( l != 0 ) { 103 labels.push_front( *l ); 103 labels.push_front( *l ); 104 104 delete l; 105 105 } // if … … 156 156 control->print( os, indent ); 157 157 os << endl; 158 } else 158 } else 159 159 os << string( indent, ' ' ) << "Null Statement" << endl; 160 160 break; … … 177 177 if ( block ) { 178 178 os << string( indent + ParseNode::indent_by, ' ' ) << "Branches of execution: " << endl; 179 block->printList( os, indent + 2 * ParseNode::indent_by ); 179 block->printList( os, indent + 2 * ParseNode::indent_by ); 180 180 } // if 181 181 if ( target ) { … … 258 258 case Fallthru: 259 259 return new FallthruStmt( labs ); 260 case Case: 260 case Case: 261 261 return new CaseStmt( labs, maybeBuild<Expression>(get_control()), branches ); 262 262 case Default: … … 394 394 os << string( indent + ParseNode::indent_by, ' ' ) << "Goto Labels:" << endl; 395 395 os << string( indent + 2 * ParseNode::indent_by, ' ' ); 396 for ( std::list< std::string>::const_iterator i = gotolabels.begin();; ) {396 for ( std::list<Label>::const_iterator i = gotolabels.begin();; ) { 397 397 os << *i; 398 398 i++; … … 426 426 } 427 427 428 Statement *NullStmtNode::build() const { 428 Statement *NullStmtNode::build() const { 429 429 return new NullStmt; 430 430 } -
src/ResolvExpr/Resolver.cc
rc1c0928 r4d3ca1d8 503 503 delete ctorInit->get_ctor(); 504 504 ctorInit->set_ctor( NULL ); 505 delete ctorInit->get_dtor(); 506 ctorInit->set_dtor( NULL ); 505 507 maybeAccept( ctorInit->get_init(), *this ); 506 508 } -
src/SymTab/Autogen.cc
rc1c0928 r4d3ca1d8 482 482 ObjectDecl *dst = new ObjectDecl( "_dst", DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), typeInst->clone() ), 0 ); 483 483 if ( typeDecl->get_base() ) { 484 // xxx - generate ctor/dtors for typedecls, e.g. 485 // otype T = int *; 484 486 stmts = new CompoundStmt( std::list< Label >() ); 485 487 UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) ); -
src/SymTab/Autogen.h
rc1c0928 r4d3ca1d8 24 24 25 25 namespace SymTab { 26 static const std::list< std::string > noLabels;27 28 26 /// Generates assignment operators, constructors, and destructor for aggregate types as required 29 27 void autogenerateRoutines( std::list< Declaration * > &translationUnit ); -
src/SymTab/Indexer.h
rc1c0928 r4d3ca1d8 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // Indexer.h -- 7 // Indexer.h -- 8 8 // 9 9 // Author : Richard C. Bilson … … 33 33 Indexer& operator= ( Indexer &&that ); 34 34 35 //using Visitor::visit;35 using Visitor::visit; 36 36 virtual void visit( ObjectDecl *objectDecl ); 37 37 virtual void visit( FunctionDecl *functionDecl ); … … 54 54 virtual void visit( MemberExpr *memberExpr ); 55 55 virtual void visit( VariableExpr *variableExpr ); 56 virtual void visit( ConstantExpr *constantExpr ); 56 virtual void visit( ConstantExpr *constantExpr ); 57 57 virtual void visit( SizeofExpr *sizeofExpr ); 58 58 virtual void visit( AlignofExpr *alignofExpr ); … … 93 93 /// Gets the top-most trait declaration with the given ID 94 94 TraitDecl *lookupTrait( const std::string &id ) const; 95 95 96 96 void print( std::ostream &os, int indent = 0 ) const; 97 97 private: … … 106 106 UnionDecl *lookupUnionAtScope( const std::string &id, unsigned long scope ) const; 107 107 TraitDecl *lookupTraitAtScope( const std::string &id, unsigned long scope ) const; 108 108 109 109 void addId( DeclarationWithType *decl ); 110 110 void addType( NamedTypeDecl *decl ); … … 115 115 void addUnion( UnionDecl *decl ); 116 116 void addTrait( TraitDecl *decl ); 117 117 118 118 struct Impl; 119 119 Impl *tables; ///< Copy-on-write instance of table data structure -
src/SynTree/Statement.cc
rc1c0928 r4d3ca1d8 87 87 Statement( labels ), originalTarget( _target ), target( _target ), computedTarget( NULL ), type( _type ) { 88 88 //actually this is a syntactic error signaled by the parser 89 if ( type == BranchStmt::Goto && target. size() == 0)89 if ( type == BranchStmt::Goto && target.empty() ) 90 90 throw SemanticError("goto without target"); 91 91 } -
src/SynTree/Statement.h
rc1c0928 r4d3ca1d8 22 22 #include "Common/SemanticError.h" 23 23 #include "Type.h" 24 #include "Label.h" 24 25 25 26 class Statement { -
src/SynTree/SynTree.h
rc1c0928 r4d3ca1d8 113 113 class Constant; 114 114 115 typedef std::string Label; 115 // typedef std::string Label; 116 class Label; 116 117 typedef unsigned int UniqueId; 117 118 -
src/SynTree/Visitor.cc
rc1c0928 r4d3ca1d8 39 39 } 40 40 41 void Visitor:: visit( AggregateDecl *aggregateDecl ) {41 void Visitor::handleAggregateDecl( AggregateDecl *aggregateDecl ) { 42 42 acceptAll( aggregateDecl->get_parameters(), *this ); 43 43 acceptAll( aggregateDecl->get_members(), *this ); … … 45 45 46 46 void Visitor::visit( StructDecl *aggregateDecl ) { 47 visit( static_cast< AggregateDecl* >( aggregateDecl ) );47 handleAggregateDecl( static_cast< AggregateDecl* >( aggregateDecl ) ); 48 48 } 49 49 50 50 void Visitor::visit( UnionDecl *aggregateDecl ) { 51 visit( static_cast< AggregateDecl* >( aggregateDecl ) );51 handleAggregateDecl( static_cast< AggregateDecl* >( aggregateDecl ) ); 52 52 } 53 53 54 54 void Visitor::visit( EnumDecl *aggregateDecl ) { 55 visit( static_cast< AggregateDecl* >( aggregateDecl ) );55 handleAggregateDecl( static_cast< AggregateDecl* >( aggregateDecl ) ); 56 56 } 57 57 58 58 void Visitor::visit( TraitDecl *aggregateDecl ) { 59 visit( static_cast< AggregateDecl* >( aggregateDecl ) );60 } 61 62 void Visitor:: visit( NamedTypeDecl *typeDecl ) {59 handleAggregateDecl( static_cast< AggregateDecl* >( aggregateDecl ) ); 60 } 61 62 void Visitor::handleNamedTypeDecl( NamedTypeDecl *typeDecl ) { 63 63 acceptAll( typeDecl->get_parameters(), *this ); 64 64 acceptAll( typeDecl->get_assertions(), *this ); … … 67 67 68 68 void Visitor::visit( TypeDecl *typeDecl ) { 69 visit( static_cast< NamedTypeDecl* >( typeDecl ) );69 handleNamedTypeDecl( static_cast< NamedTypeDecl* >( typeDecl ) ); 70 70 } 71 71 72 72 void Visitor::visit( TypedefDecl *typeDecl ) { 73 visit( static_cast< NamedTypeDecl* >( typeDecl ) );73 handleNamedTypeDecl( static_cast< NamedTypeDecl* >( typeDecl ) ); 74 74 } 75 75 … … 330 330 } 331 331 332 void Visitor:: visit( ReferenceToType *aggregateUseType ) {332 void Visitor::handleReferenceToType( ReferenceToType *aggregateUseType ) { 333 333 acceptAll( aggregateUseType->get_forall(), *this ); 334 334 acceptAll( aggregateUseType->get_parameters(), *this ); … … 336 336 337 337 void Visitor::visit( StructInstType *aggregateUseType ) { 338 visit( static_cast< ReferenceToType * >( aggregateUseType ) );338 handleReferenceToType( static_cast< ReferenceToType * >( aggregateUseType ) ); 339 339 } 340 340 341 341 void Visitor::visit( UnionInstType *aggregateUseType ) { 342 visit( static_cast< ReferenceToType * >( aggregateUseType ) );342 handleReferenceToType( static_cast< ReferenceToType * >( aggregateUseType ) ); 343 343 } 344 344 345 345 void Visitor::visit( EnumInstType *aggregateUseType ) { 346 visit( static_cast< ReferenceToType * >( aggregateUseType ) );346 handleReferenceToType( static_cast< ReferenceToType * >( aggregateUseType ) ); 347 347 } 348 348 349 349 void Visitor::visit( TraitInstType *aggregateUseType ) { 350 visit( static_cast< ReferenceToType * >( aggregateUseType ) );350 handleReferenceToType( static_cast< ReferenceToType * >( aggregateUseType ) ); 351 351 acceptAll( aggregateUseType->get_members(), *this ); 352 352 } 353 353 354 354 void Visitor::visit( TypeInstType *aggregateUseType ) { 355 visit( static_cast< ReferenceToType * >( aggregateUseType ) );355 handleReferenceToType( static_cast< ReferenceToType * >( aggregateUseType ) ); 356 356 } 357 357 -
src/SynTree/Visitor.h
rc1c0928 r4d3ca1d8 104 104 virtual void visit( Constant *constant ); 105 105 private: 106 virtual void visit( AggregateDecl *aggregateDecl );107 virtual void visit( NamedTypeDecl *typeDecl );108 virtual void visit( ReferenceToType *aggregateUseType );106 virtual void handleAggregateDecl( AggregateDecl *aggregateDecl ); 107 virtual void handleNamedTypeDecl( NamedTypeDecl *typeDecl ); 108 virtual void handleReferenceToType( ReferenceToType *aggregateUseType ); 109 109 }; 110 110 -
src/SynTree/module.mk
rc1c0928 r4d3ca1d8 46 46 SynTree/Visitor.cc \ 47 47 SynTree/Mutator.cc \ 48 SynTree/AddStmtVisitor.cc \ 48 49 SynTree/TypeSubstitution.cc \ 49 50 SynTree/Attribute.cc
Note: See TracChangeset
for help on using the changeset viewer.