Changeset 6cf27a07
- Timestamp:
- Jul 21, 2016, 2:07:01 PM (8 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
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
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 } -
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 ); -
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 -
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 } -
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 -
src/SymTab/Autogen.h
rb81adcc4 r6cf27a07 144 144 genCall( srcParam, dstParam, fname, back_inserter( stmts ), obj->get_type(), forward ); 145 145 146 // currently genCall should produce only one element, but if that changes then the next line needs to be updated to grab the statement which contains the call 147 assert( stmts.size() == 1 ); 148 Statement * callStmt = stmts.front(); 149 if ( (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && obj->get_bitfieldWidth() == NULL ) ) ) { 150 // implicitly generated ctor/dtor calls should be wrapped 151 // so that later passes are aware they were generated. 152 // xxx - don't mark as an implicit ctor/dtor if obj is a bitfield, 153 // because this causes the address to be taken at codegen, which is illegal in C. 154 callStmt = new ImplicitCtorDtorStmt( callStmt ); 155 } 156 *out++ = callStmt; 146 // currently genCall should produce at most one element, but if that changes then the next line needs to be updated to grab the statement which contains the call 147 assert( stmts.size() <= 1 ); 148 if ( stmts.size() == 1 ) { 149 Statement * callStmt = stmts.front(); 150 if ( (fname == "?{}" || fname == "^?{}") && ( !obj || ( obj && obj->get_bitfieldWidth() == NULL ) ) ) { 151 // implicitly generated ctor/dtor calls should be wrapped 152 // so that later passes are aware they were generated. 153 // xxx - don't mark as an implicit ctor/dtor if obj is a bitfield, 154 // because this causes the address to be taken at codegen, which is illegal in C. 155 callStmt = new ImplicitCtorDtorStmt( callStmt ); 156 } 157 *out++ = callStmt; 158 } 157 159 } 158 160 } // namespace SymTab -
src/main.cc
rb81adcc4 r6cf27a07 42 42 #include "InitTweak/GenInit.h" 43 43 #include "InitTweak/FixInit.h" 44 #include "InitTweak/FixGlobalInit.h"45 44 //#include "Explain/GenProlog.h" 46 45 //#include "Try/Visit.h" … … 282 281 OPTPRINT( "fixNames" ) 283 282 CodeGen::fixNames( translationUnit ); 284 OPTPRINT( "fixGlobalInit" );285 InitTweak::fixGlobalInit( translationUnit, filename, libcfap || treep );286 283 OPTPRINT( "tweakInit" ) 287 284 InitTweak::genInit( translationUnit ); … … 304 301 } 305 302 303 // fix ObjectDecl - replaces ConstructorInit nodes 306 304 OPTPRINT( "fixInit" ) 307 // fix ObjectDecl - replaces ConstructorInit nodes 308 InitTweak::fix( translationUnit ); 305 InitTweak::fix( translationUnit, filename, libcfap || treep ); 309 306 if ( ctorinitp ) { 310 307 dump ( translationUnit ); -
src/tests/.expect/extension.txt
rb81adcc4 r6cf27a07 100 100 ((void)((__extension__ __a__i_2 , __extension__ __b__i_2) , __extension__ __c__i_2)); 101 101 } 102 __attribute__ ((constructor(),)) static void _init_extension(void){103 int _global_init0;104 ((void)((*((int *)(&__a__i_1)))=_global_init0) /* ?{} */);105 int _global_init1;106 ((void)((*((int *)(&__b__i_1)))=_global_init1) /* ?{} */);107 int _global_init2;108 ((void)((*((int *)(&__c__i_1)))=_global_init2) /* ?{} */);109 }110 __attribute__ ((destructor(),)) static void _destroy_extension(void){111 ((void)((*((int *)(&__c__i_1)))) /* ^?{} */);112 ((void)((*((int *)(&__b__i_1)))) /* ^?{} */);113 ((void)((*((int *)(&__a__i_1)))) /* ^?{} */);114 }
Note: See TracChangeset
for help on using the changeset viewer.