Changeset 6cf27a07 for src/InitTweak
- Timestamp:
- Jul 21, 2016, 2:07:01 PM (9 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, ctor, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, memory, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- ccb447e
- Parents:
- b81adcc4
- Location:
- src/InitTweak
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified src/InitTweak/FixGlobalInit.cc ¶
rb81adcc4 r6cf27a07 97 97 std::list< Statement * > & destroyStatements = destroyFunction->get_statements()->get_kids(); 98 98 99 if ( ! tryConstruct( objDecl ) ) return; // don't construct @= or designated objects100 if ( objDecl->get_storageClass() == DeclarationNode::Extern ) return;101 99 // C allows you to initialize objects with constant expressions 102 100 // xxx - this is an optimization. Need to first resolve constructors before we decide … … 104 102 // if ( isConstExpr( objDecl->get_init() ) ) return; 105 103 106 if ( dynamic_cast< ArrayType * > ( objDecl->get_type() ) ) { 107 // xxx - initialize each element of the array 108 } else { 109 // insert constructor for objDecl into global init function 110 UntypedExpr * init = new UntypedExpr( new NameExpr( "?{}" ) ); 111 init->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) ); 112 init->get_args().splice( init->get_args().end(), makeInitList( objDecl->get_init() ) ); 113 objDecl->set_init( NULL ); 114 initStatements.push_back( new ImplicitCtorDtorStmt( new ExprStmt( noLabels, init ) ) ); 104 if ( ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ) ) { 105 // a decision should have been made by the resolver, so ctor and init are not both non-NULL 106 assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() ); 115 107 116 // add destructor calls to global destroy function 117 UntypedExpr * destroy = new UntypedExpr( new NameExpr( "^?{}" ) ); 118 destroy->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) ); 119 destroyStatements.push_front( new ImplicitCtorDtorStmt( new ExprStmt( noLabels, destroy ) ) ); 108 Statement * dtor = ctorInit->get_dtor(); 109 if ( dtor && ! isInstrinsicSingleArgCallStmt( dtor ) ) { 110 // don't need to call intrinsic dtor, because it does nothing, but 111 // non-intrinsic dtors must be called 112 destroyStatements.push_front( dtor ); 113 ctorInit->set_dtor( NULL ); 114 } // if 115 if ( Statement * ctor = ctorInit->get_ctor() ) { 116 initStatements.push_back( ctor ); 117 objDecl->set_init( NULL ); 118 ctorInit->set_ctor( NULL ); 119 } else if ( Initializer * init = ctorInit->get_init() ) { 120 objDecl->set_init( init ); 121 ctorInit->set_init( NULL ); 122 } else { 123 // no constructor and no initializer, which is okay 124 objDecl->set_init( NULL ); 125 } // if 126 delete ctorInit; 120 127 } // if 121 128 } -
TabularUnified src/InitTweak/FixInit.cc ¶
rb81adcc4 r6cf27a07 18 18 #include <iterator> 19 19 #include <algorithm> 20 #include "InitTweak.h" 20 21 #include "FixInit.h" 21 #include " InitTweak.h"22 #include "FixGlobalInit.h" 22 23 #include "ResolvExpr/Resolver.h" 23 24 #include "ResolvExpr/typeops.h" … … 83 84 }; 84 85 86 // debug 85 87 struct printSet { 86 88 typedef ObjDeclCollector::ObjectSet ObjectSet; … … 171 173 } // namespace 172 174 173 void fix( std::list< Declaration * > & translationUnit ) { 175 void fix( std::list< Declaration * > & translationUnit, const std::string & filename, bool inLibrary ) { 176 // fixes ConstructorInit for global variables. should happen before fixInitializers. 177 InitTweak::fixGlobalInit( translationUnit, filename, inLibrary ); 178 174 179 InsertImplicitCalls::insert( translationUnit ); 175 180 ResolveCopyCtors::resolveImplicitCalls( translationUnit ); -
TabularUnified src/InitTweak/FixInit.h ¶
rb81adcc4 r6cf27a07 27 27 /// replace constructor initializers with expression statements 28 28 /// and unwrap basic C-style initializers 29 void fix( std::list< Declaration * > & translationUnit );29 void fix( std::list< Declaration * > & translationUnit, const std::string & name, bool inLibrary ); 30 30 } // namespace 31 31 -
TabularUnified src/InitTweak/GenInit.cc ¶
rb81adcc4 r6cf27a07 61 61 static void generateCtorDtor( std::list< Declaration * > &translationUnit ); 62 62 63 CtorDtor() : inFunction( false ) {}64 65 63 virtual DeclarationWithType * mutate( ObjectDecl * ); 66 64 virtual DeclarationWithType * mutate( FunctionDecl *functionDecl ); … … 77 75 78 76 protected: 79 bool inFunction;80 77 }; 81 78 … … 216 213 217 214 DeclarationWithType * CtorDtor::mutate( ObjectDecl * objDecl ) { 218 // hands off if designated or if @=215 // hands off if designated, if @=, or if extern 219 216 if ( tryConstruct( objDecl ) ) { 220 if ( inFunction ) { 221 if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->get_type() ) ) { 222 // call into makeArrayFunction from validate.cc to generate calls to ctor/dtor for each element of array 223 // TODO: walk initializers and generate appropriate ctor if element has initializer. 224 // Initializer could be nested (depends on the depth of the array type on the object) 225 226 std::list< Expression * > args = makeInitList( objDecl->get_init() ); 227 if ( args.empty() ) { 228 std::list< Statement * > ctor; 229 std::list< Statement * > dtor; 230 231 SymTab::genImplicitCall( NULL, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl ); 232 SymTab::genImplicitCall( NULL, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false ); 233 234 // Currently genArrayCall produces a single Statement - a CompoundStmt 235 // which wraps everything that needs to happen. As such, it's technically 236 // possible to use a Statement ** in the above calls, but this is inherently 237 // unsafe, so instead we take the slightly less efficient route, but will be 238 // immediately informed if somehow the above assumption is broken. In this case, 239 // we could always wrap the list of statements at this point with a CompoundStmt, 240 // but it seems reasonable at the moment for this to be done by genArrayCall 241 // itself 242 assert( ctor.size() == 1 && dynamic_cast< ImplicitCtorDtorStmt * >( ctor.front() ) ); 243 assert( dtor.size() == 1 && dynamic_cast< ImplicitCtorDtorStmt * >( dtor.front() ) ); 217 if ( ArrayType * at = dynamic_cast< ArrayType * >( objDecl->get_type() ) ) { 218 // call into makeArrayFunction from validate.cc to generate calls to ctor/dtor for each element of array 219 // TODO: walk initializers and generate appropriate ctor if element has initializer. 220 // Initializer could be nested (depends on the depth of the array type on the object) 221 222 std::list< Expression * > args = makeInitList( objDecl->get_init() ); 223 if ( args.empty() ) { 224 std::list< Statement * > ctor; 225 std::list< Statement * > dtor; 226 227 SymTab::genImplicitCall( NULL, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl ); 228 SymTab::genImplicitCall( NULL, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false ); 229 230 // Currently genImplicitCall produces a single Statement - a CompoundStmt 231 // which wraps everything that needs to happen. As such, it's technically 232 // possible to use a Statement ** in the above calls, but this is inherently 233 // unsafe, so instead we take the slightly less efficient route, but will be 234 // immediately informed if somehow the above assumption is broken. In this case, 235 // we could always wrap the list of statements at this point with a CompoundStmt, 236 // but it seems reasonable at the moment for this to be done by genImplicitCall 237 // itself. It is possible that genImplicitCall produces no statements (e.g. if 238 // an array type does not have a dimension). In this case, it's fine to ignore 239 // the object for the purposes of construction. 240 assert( ctor.size() == dtor.size() && ctor.size() <= 1 ); 241 if ( ctor.size() == 1 ) { 242 assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) ); 244 243 objDecl->set_init( new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() ) ); 245 } else {246 // array came with an initializer list: initialize each element247 // may have more initializers than elements in the array - need to check at each index that248 // we haven't exceeded size. This requires precomputing the size because it might be a side-effecting249 // computation.250 // may have fewer initializers than elements in the array - need to default construct251 // remaining elements.252 // might be able to merge this with the case above.253 254 244 } 255 245 } else { 256 // it's sufficient to attempt to call the ctor/dtor for the given object and its initializer 257 Expression * ctor = makeCtorDtorExpr( "?{}", objDecl, makeInitList( objDecl->get_init() ) ); 258 Expression * dtor = makeCtorDtorExpr( "^?{}", objDecl, std::list< Expression * >() ); 259 260 // need to remember init expression, in case no ctors exist 261 // if ctor does exist, want to use ctor expression instead of init 262 // push this decision to the resolver 263 ExprStmt * ctorStmt = new ExprStmt( noLabels, ctor ); 264 ExprStmt * dtorStmt = new ExprStmt( noLabels, dtor ); 265 objDecl->set_init( new ConstructorInit( new ImplicitCtorDtorStmt( ctorStmt ), new ImplicitCtorDtorStmt( dtorStmt ), objDecl->get_init() ) ); 246 // array came with an initializer list: initialize each element 247 // may have more initializers than elements in the array - need to check at each index that 248 // we haven't exceeded size. This requires precomputing the size because it might be a side-effecting 249 // computation. 250 // may have fewer initializers than elements in the array - need to default construct 251 // remaining elements. 252 // might be able to merge this with the case above. 253 266 254 } 255 } else { 256 // it's sufficient to attempt to call the ctor/dtor for the given object and its initializer 257 Expression * ctor = makeCtorDtorExpr( "?{}", objDecl, makeInitList( objDecl->get_init() ) ); 258 Expression * dtor = makeCtorDtorExpr( "^?{}", objDecl, std::list< Expression * >() ); 259 260 // need to remember init expression, in case no ctors exist 261 // if ctor does exist, want to use ctor expression instead of init 262 // push this decision to the resolver 263 ExprStmt * ctorStmt = new ExprStmt( noLabels, ctor ); 264 ExprStmt * dtorStmt = new ExprStmt( noLabels, dtor ); 265 objDecl->set_init( new ConstructorInit( new ImplicitCtorDtorStmt( ctorStmt ), new ImplicitCtorDtorStmt( dtorStmt ), objDecl->get_init() ) ); 267 266 } 268 267 } … … 272 271 DeclarationWithType * CtorDtor::mutate( FunctionDecl *functionDecl ) { 273 272 // parameters should not be constructed and destructed, so don't mutate FunctionType 274 bool oldInFunc = inFunction;275 273 mutateAll( functionDecl->get_oldDecls(), *this ); 276 inFunction = true;277 274 functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) ); 278 inFunction = oldInFunc;279 275 return functionDecl; 280 276 } -
TabularUnified src/InitTweak/InitTweak.cc ¶
rb81adcc4 r6cf27a07 57 57 (objDecl->get_init() == NULL || 58 58 ( objDecl->get_init() != NULL && objDecl->get_init()->get_maybeConstructed() )) && 59 ! isDesignated( objDecl->get_init() ); 59 ! isDesignated( objDecl->get_init() ) 60 && objDecl->get_storageClass() != DeclarationNode::Extern; 60 61 } 61 62
Note: See TracChangeset
for help on using the changeset viewer.