Changes in src/InitTweak/RemoveInit.cc [cf16f94:db4ecc5]
- File:
-
- 1 edited
-
src/InitTweak/RemoveInit.cc (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/RemoveInit.cc
rcf16f94 rdb4ecc5 5 5 // file "LICENCE" distributed with Cforall. 6 6 // 7 // RemoveInit.cc -- 7 // RemoveInit.cc -- 8 8 // 9 9 // Author : Rob Schluntz 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Tue Dec 15 15:37:26 2015 13 // Update Count : 15 14 // 15 11 // Last Modified By : Rob Schluntz 12 // Last Modified On : Thu Apr 14 15:09:36 2016 13 // Update Count : 166 14 // 15 16 #include <stack> 17 #include <list> 16 18 #include "RemoveInit.h" 17 19 #include "SynTree/Declaration.h" … … 21 23 #include "SynTree/Initializer.h" 22 24 #include "SynTree/Mutator.h" 25 #include "SymTab/Autogen.h" 26 #include "GenPoly/PolyMutator.h" 23 27 24 28 namespace InitTweak { 25 29 namespace { 26 30 const std::list<Label> noLabels; 27 } 28 29 class RemoveInit : public Mutator { 31 const std::list<Expression *> noDesignators; 32 } 33 34 class RemoveInit : public GenPoly::PolyMutator { 30 35 public: 36 /// removes and replaces initialization for polymorphic value objects 37 /// with assignment (TODO: constructor) statements. 38 /// also consistently allocates a temporary variable for the return value 39 /// of a function so that anything which the resolver decides can be assigned 40 /// into the return type of a function can be returned. 41 static void removeInitializers( std::list< Declaration * > &translationUnit ); 42 31 43 RemoveInit(); 32 virtual ObjectDecl * mutate(ObjectDecl *objDecl); 44 45 virtual ObjectDecl * mutate( ObjectDecl *objDecl ); 33 46 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ); 34 47 35 48 virtual Statement * mutate( ReturnStmt * returnStmt ); 36 37 virtual CompoundStmt * mutate(CompoundStmt * compoundStmt); 38 49 39 50 protected: 40 std::list< Statement* > stmtsToAddBefore;41 std::list< Statement* > stmtsToAddAfter;42 void mutateStatementList( std::list< Statement* > &statements );43 44 51 std::list<DeclarationWithType*> returnVals; 45 52 UniqueName tempNamer; … … 47 54 }; 48 55 49 void tweak( std::list< Declaration * > translationUnit ) { 56 class CtorDtor : public GenPoly::PolyMutator { 57 public: 58 /// create constructor and destructor statements for object declarations. 59 /// Destructors are inserted directly into the code, whereas constructors 60 /// will be added in after the resolver has run so that the initializer expression 61 /// is only removed if a constructor is found 62 static void generateCtorDtor( std::list< Declaration * > &translationUnit ); 63 64 CtorDtor() : inFunction( false ) {} 65 66 virtual DeclarationWithType * mutate( ObjectDecl * ); 67 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ); 68 virtual Declaration* mutate( StructDecl *aggregateDecl ); 69 virtual Declaration* mutate( UnionDecl *aggregateDecl ); 70 virtual Declaration* mutate( EnumDecl *aggregateDecl ); 71 virtual Declaration* mutate( TraitDecl *aggregateDecl ); 72 virtual TypeDecl* mutate( TypeDecl *typeDecl ); 73 virtual Declaration* mutate( TypedefDecl *typeDecl ); 74 75 virtual Type * mutate( FunctionType *funcType ); 76 77 protected: 78 bool inFunction; 79 }; 80 81 void tweak( std::list< Declaration * > & translationUnit ) { 82 RemoveInit::removeInitializers( translationUnit ); 83 CtorDtor::generateCtorDtor( translationUnit ); 84 } 85 86 void RemoveInit::removeInitializers( std::list< Declaration * > & translationUnit ) { 50 87 RemoveInit remover; 51 88 mutateAll( translationUnit, remover ); … … 53 90 54 91 RemoveInit::RemoveInit() : tempNamer( "_retVal" ) {} 55 56 void RemoveInit::mutateStatementList( std::list< Statement* > &statements ) {57 for ( std::list< Statement* >::iterator i = statements.begin(); i != statements.end(); ++i ) {58 if ( ! stmtsToAddAfter.empty() ) {59 statements.splice( i, stmtsToAddAfter );60 } // if61 *i = (*i)->acceptMutator( *this );62 if ( ! stmtsToAddBefore.empty() ) {63 statements.splice( i, stmtsToAddBefore );64 } // if65 } // for66 if ( ! stmtsToAddAfter.empty() ) {67 statements.splice( statements.end(), stmtsToAddAfter );68 } // if69 }70 71 CompoundStmt *RemoveInit::mutate(CompoundStmt *compoundStmt) {72 mutateStatementList( compoundStmt->get_kids() );73 return compoundStmt;74 }75 92 76 93 // in the case where an object has an initializer and a polymorphic type, insert an assignment immediately after the … … 79 96 if (objDecl->get_init() && dynamic_cast<TypeInstType*>(objDecl->get_type())) { 80 97 if (SingleInit * single = dynamic_cast<SingleInit*>(objDecl->get_init())) { 81 UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) ); 82 assign->get_args().push_back( new AddressExpr (new NameExpr( objDecl->get_name() ) ) ); 98 // xxx this can be more complicated - consider ListInit 99 UntypedExpr *assign = new UntypedExpr( new NameExpr( "?{}" ) ); 100 assign->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) ); 83 101 assign->get_args().push_back( single->get_value()->clone() ); 84 102 stmtsToAddAfter.push_back(new ExprStmt(noLabels, assign)); … … 93 111 // hands off if the function returns an lvalue - we don't want to allocate a temporary if a variable's address 94 112 // is being returned 95 if ( returnStmt->get_expr() && returnVals.size() == 1 && funcName != "?=?" && ! returnVals.front()->get_type()->get_isLvalue() ) { 96 ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, returnVals.front()->get_type()->clone(), 0 ); 97 stmtsToAddBefore.push_back( new DeclStmt( noLabels, newObj ) ); 98 99 UntypedExpr *assign = new UntypedExpr( new NameExpr( "?=?" ) ); 100 assign->get_args().push_back( new AddressExpr (new NameExpr( newObj->get_name() ) ) ); 101 assign->get_args().push_back( returnStmt->get_expr() ); 102 stmtsToAddBefore.push_back(new ExprStmt(noLabels, assign)); 113 if ( returnStmt->get_expr() && returnVals.size() == 1 && funcName != "?=?" && ! returnVals.front()->get_type()->get_isLvalue() ) { 114 // ensure return value is not destructed by explicitly creating 115 // an empty SingleInit node wherein maybeConstruct is false 116 ObjectDecl *newObj = new ObjectDecl( tempNamer.newName(), DeclarationNode::NoStorageClass, LinkageSpec::C, 0, returnVals.front()->get_type()->clone(), new ListInit( std::list<Initializer*>(), noDesignators, false ) ); 117 stmtsToAdd.push_back( new DeclStmt( noLabels, newObj ) ); 118 119 // and explicitly create the constructor expression separately 120 UntypedExpr *construct = new UntypedExpr( new NameExpr( "?{}" ) ); 121 construct->get_args().push_back( new AddressExpr( new VariableExpr( newObj ) ) ); 122 construct->get_args().push_back( returnStmt->get_expr() ); 123 stmtsToAdd.push_back(new ExprStmt(noLabels, construct)); 103 124 104 125 returnStmt->set_expr( new VariableExpr( newObj ) ); … … 110 131 std::list<DeclarationWithType*> oldReturnVals = returnVals; 111 132 std::string oldFuncName = funcName; 112 133 113 134 FunctionType * type = functionDecl->get_functionType(); 114 135 returnVals = type->get_returnVals(); … … 119 140 return decl; 120 141 } 142 143 144 void CtorDtor::generateCtorDtor( std::list< Declaration * > & translationUnit ) { 145 CtorDtor ctordtor; 146 mutateAll( translationUnit, ctordtor ); 147 } 148 149 namespace { 150 bool tryConstruct( ObjectDecl * objDecl ) { 151 // xxx - handle designations 152 return ! LinkageSpec::isBuiltin( objDecl->get_linkage() ) && 153 (objDecl->get_init() == NULL || 154 ( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() )); 155 } 156 157 Expression * makeCtorDtorExpr( std::string name, ObjectDecl * objDecl, std::list< Expression * > args ) { 158 UntypedExpr * expr = new UntypedExpr( new NameExpr( name ) ); 159 expr->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) ); 160 expr->get_args().splice( expr->get_args().end(), args ); 161 return expr; 162 } 163 164 class InitExpander : public Visitor { 165 public: 166 InitExpander() {} 167 // ~InitExpander() {} 168 virtual void visit( SingleInit * singleInit ); 169 virtual void visit( ListInit * listInit ); 170 std::list< Expression * > argList; 171 }; 172 173 void InitExpander::visit( SingleInit * singleInit ) { 174 argList.push_back( singleInit->get_value()->clone() ); 175 } 176 177 void InitExpander::visit( ListInit * listInit ) { 178 // xxx - for now, assume no nested list inits 179 std::list<Initializer*>::iterator it = listInit->begin_initializers(); 180 for ( ; it != listInit->end_initializers(); ++it ) { 181 (*it)->accept( *this ); 182 } 183 } 184 185 std::list< Expression * > makeInitList( Initializer * init ) { 186 InitExpander expander; 187 maybeAccept( init, expander ); 188 return expander.argList; 189 } 190 } 191 192 DeclarationWithType * CtorDtor::mutate( ObjectDecl * objDecl ) { 193 // hands off if designated or if @= 194 if ( tryConstruct( objDecl ) ) { 195 if ( inFunction ) { 196 if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->get_type() ) ) { 197 // call into makeArrayFunction from validate.cc to generate calls to ctor/dtor for each element of array 198 // TODO: walk initializer and generate appropriate copy ctor if element has initializer 199 std::list< Statement * > ctor; 200 std::list< Statement * > dtor; 201 202 SymTab::makeArrayFunction( NULL, new VariableExpr( objDecl ), at, "?{}", back_inserter( ctor ) ); 203 SymTab::makeArrayFunction( NULL, new VariableExpr( objDecl ), at, "^?{}", front_inserter( dtor ), false ); 204 205 // Currently makeArrayFunction produces a single Statement - a CompoundStmt 206 // which wraps everything that needs to happen. As such, it's technically 207 // possible to use a Statement ** in the above calls, but this is inherently 208 // unsafe, so instead we take the slightly less efficient route, but will be 209 // immediately informed if somehow the above assumption is broken. In this case, 210 // we could always wrap the list of statements at this point with a CompoundStmt, 211 // but it seems reasonable at the moment for this to be done by makeArrayFunction 212 // itself 213 assert( ctor.size() == 1 ); 214 assert( dtor.size() == 1 ); 215 216 objDecl->set_init( new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ) ); 217 } else { 218 // it's sufficient to attempt to call the ctor/dtor for the given object and its initializer 219 Expression * ctor = makeCtorDtorExpr( "?{}", objDecl, makeInitList( objDecl->get_init() ) ); 220 Expression * dtor = makeCtorDtorExpr( "^?{}", objDecl, std::list< Expression * >() ); 221 222 // need to remember init expression, in case no ctors exist 223 // if ctor does exist, want to use ctor expression instead of init 224 // push this decision to the resolver 225 ExprStmt * ctorStmt = new ExprStmt( noLabels, ctor ); 226 ExprStmt * dtorStmt = new ExprStmt( noLabels, dtor ); 227 objDecl->set_init( new ConstructorInit( ctorStmt, dtorStmt, objDecl->get_init() ) ); 228 } 229 } else { 230 // xxx - find a way to construct/destruct globals 231 // hack: implicit "static" initialization routine for each struct type? or something similar? 232 // --ties into module system 233 // this can be done by mangling main and replacing it with our own main which calls each 234 // module initialization routine in some decided order (order given in link command?) 235 // and finally calls mangled main 236 } 237 } 238 return Mutator::mutate( objDecl ); 239 } 240 241 DeclarationWithType * CtorDtor::mutate( FunctionDecl *functionDecl ) { 242 // parameters should not be constructed and destructed, so don't mutate FunctionType 243 bool oldInFunc = inFunction; 244 mutateAll( functionDecl->get_oldDecls(), *this ); 245 inFunction = true; 246 functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) ); 247 inFunction = oldInFunc; 248 return functionDecl; 249 } 250 251 // should not traverse into any of these declarations to find objects 252 // that need to be constructed or destructed 253 Declaration* CtorDtor::mutate( StructDecl *aggregateDecl ) { return aggregateDecl; } 254 Declaration* CtorDtor::mutate( UnionDecl *aggregateDecl ) { return aggregateDecl; } 255 Declaration* CtorDtor::mutate( EnumDecl *aggregateDecl ) { return aggregateDecl; } 256 Declaration* CtorDtor::mutate( TraitDecl *aggregateDecl ) { return aggregateDecl; } 257 TypeDecl* CtorDtor::mutate( TypeDecl *typeDecl ) { return typeDecl; } 258 Declaration* CtorDtor::mutate( TypedefDecl *typeDecl ) { return typeDecl; } 259 Type* CtorDtor::mutate( FunctionType *funcType ) { return funcType; } 260 121 261 } // namespace InitTweak 122 262
Note:
See TracChangeset
for help on using the changeset viewer.