Changeset f9cebb5 for src/InitTweak
- Timestamp:
- Aug 4, 2016, 4:10:06 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:
- 4819cac
- Parents:
- 73bf8cf2
- Location:
- src/InitTweak
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/FixGlobalInit.cc
r73bf8cf2 rf9cebb5 107 107 108 108 Statement * dtor = ctorInit->get_dtor(); 109 if ( dtor && ! isIn strinsicSingleArgCallStmt( dtor ) ) {109 if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) { 110 110 // don't need to call intrinsic dtor, because it does nothing, but 111 111 // non-intrinsic dtors must be called -
src/InitTweak/FixInit.cc
r73bf8cf2 rf9cebb5 26 26 #include "SynTree/Type.h" 27 27 #include "SynTree/Expression.h" 28 #include "SynTree/Attribute.h" 28 29 #include "SynTree/Statement.h" 29 30 #include "SynTree/Initializer.h" … … 208 209 try { 209 210 *i = maybeMutate( *i, fixer ); 210 // if (! fixer.staticDtorDecls.empty() ) { 211 translationUnit.splice( i, fixer.staticDtorDecls ); 212 // } 211 translationUnit.splice( i, fixer.staticDtorDecls ); 213 212 } catch( SemanticError &e ) { 214 213 errors.append( e ); … … 446 445 if ( objDecl->get_storageClass() == DeclarationNode::Static ) { 447 446 // originally wanted to take advantage of gcc nested functions, but 448 // we get memory errors with this approach. To remedy this, create a 449 // global static pointer that is set to refer to the object and make 450 // the dtor-caller function global so that. 447 // we get memory errors with this approach. To remedy this, the static 448 // variable is hoisted when the destructor needs to be called. 451 449 // 452 450 // generate: 453 // T * __objName_static_ptrN;451 // static T __objName_static_varN; 454 452 // void __objName_dtor_atexitN() { 455 // __dtor (__objName_static_ptrN);453 // __dtor__...; 456 454 // } 457 455 // int f(...) { 458 456 // ... 459 // static T __objName;460 457 // static bool __objName_uninitialized = true; 461 458 // if (__objName_uninitialized) { 462 // __objName_ptr = &__objName;463 459 // __ctor(__objName); 464 // on_exit(__objName_dtor_atexitN, &__objName);465 460 // __objName_uninitialized = false; 461 // atexit(__objName_dtor_atexitN); 466 462 // } 467 463 // ... 468 464 // } 469 465 470 static UniqueName ptrNamer( "_static_ptr" );471 466 static UniqueName dtorCallerNamer( "_dtor_atexit" ); 472 473 // T * __objName_ptrN474 ObjectDecl * objPtr = new ObjectDecl( objDecl->get_mangleName() + ptrNamer.newName(), DeclarationNode::Static, LinkageSpec::C, 0, new PointerType( Type::Qualifiers(), objDecl->get_type()->clone() ), 0 );475 objPtr->fixUniqueId();476 477 // void __objName_dtor_atexitN(...) {...}478 // need to modify dtor call so that it refers to objPtr, since function will be global479 Statement * dtorStmt = ctorInit->get_dtor()->clone();480 ApplicationExpr * dtor = dynamic_cast< ApplicationExpr * >( InitTweak::getCtorDtorCall( dtorStmt ) );481 assert( dtor );482 delete dtor->get_args().front();483 dtor->get_args().front() = new VariableExpr( objPtr );484 485 FunctionDecl * dtorCaller = new FunctionDecl( objDecl->get_mangleName() + dtorCallerNamer.newName(), DeclarationNode::Static, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false );486 dtorCaller->fixUniqueId();487 dtorCaller->get_statements()->get_kids().push_back( dtorStmt );488 467 489 468 // static bool __objName_uninitialized = true … … 493 472 isUninitializedVar->fixUniqueId(); 494 473 495 // __objName_static_ptrN = &__objName;496 UntypedExpr * ptrAssign = new UntypedExpr( new NameExpr( "?=?" ) );497 ptrAssign->get_args().push_back( new VariableExpr( objPtr ) );498 ptrAssign->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) );499 500 // atexit(dtor_atexit);501 UntypedExpr * callAtexit = new UntypedExpr( new NameExpr( "atexit" ) );502 callAtexit->get_args().push_back( new VariableExpr( dtorCaller ) );503 504 474 // __objName_uninitialized = false; 505 475 UntypedExpr * setTrue = new UntypedExpr( new NameExpr( "?=?" ) ); … … 511 481 std::list< Statement * > & body = initStmts->get_kids(); 512 482 body.push_back( ctor ); 513 body.push_back( new ExprStmt( noLabels, ptrAssign ) );514 body.push_back( new ExprStmt( noLabels, callAtexit ) );515 483 body.push_back( new ExprStmt( noLabels, setTrue ) ); 516 484 … … 520 488 stmtsToAddAfter.push_back( ifStmt ); 521 489 522 // add pointer and dtor caller decls to list of decls that will be added into global scope 523 staticDtorDecls.push_back( objPtr ); 524 staticDtorDecls.push_back( dtorCaller ); 490 if ( ctorInit->get_dtor() ) { 491 // if the object has a non-trivial destructor, have to 492 // hoist it and the object into the global space and 493 // call the destructor function with atexit. 494 495 Statement * dtorStmt = ctorInit->get_dtor()->clone(); 496 497 // void __objName_dtor_atexitN(...) {...} 498 FunctionDecl * dtorCaller = new FunctionDecl( objDecl->get_mangleName() + dtorCallerNamer.newName(), DeclarationNode::Static, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false ); 499 dtorCaller->fixUniqueId(); 500 dtorCaller->get_statements()->get_kids().push_back( dtorStmt ); 501 502 // atexit(dtor_atexit); 503 UntypedExpr * callAtexit = new UntypedExpr( new NameExpr( "atexit" ) ); 504 callAtexit->get_args().push_back( new VariableExpr( dtorCaller ) ); 505 506 body.push_back( new ExprStmt( noLabels, callAtexit ) ); 507 508 // hoist variable and dtor caller decls to list of decls that will be added into global scope 509 staticDtorDecls.push_back( objDecl ); 510 staticDtorDecls.push_back( dtorCaller ); 511 512 // need to rename object uniquely since it now appears 513 // at global scope and there could be multiple function-scoped 514 // static variables with the same name in different functions. 515 static UniqueName staticNamer( "_static_var" ); 516 objDecl->set_mangleName( objDecl->get_mangleName() + staticNamer.newName() ); 517 518 objDecl->set_init( NULL ); 519 ctorInit->set_ctor( NULL ); 520 delete ctorInit; 521 522 // xxx - temporary hack: need to return a declaration, but want to hoist the current object out of this scope 523 // create a new object which is never used 524 static UniqueName dummyNamer( "_dummy" ); 525 ObjectDecl * dummy = new ObjectDecl( dummyNamer.newName(), DeclarationNode::Static, LinkageSpec::Cforall, 0, new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) ), 0, std::list< Attribute * >{ new Attribute("unused") } ); 526 return dummy; 527 } 525 528 } else { 526 529 stmtsToAddAfter.push_back( ctor ); … … 582 585 assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() ); 583 586 Statement * dtor = ctorInit->get_dtor(); 584 if ( dtor && ! isIn strinsicSingleArgCallStmt( dtor ) ) {587 if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) { 585 588 // don't need to call intrinsic dtor, because it does nothing, but 586 589 // non-intrinsic dtors must be called -
src/InitTweak/GenInit.cc
r73bf8cf2 rf9cebb5 172 172 // if in function, generate const size_t var 173 173 static UniqueName dimensionName( "_array_dim" ); 174 175 // C doesn't allow variable sized arrays at global scope or for static variables, 176 // so don't hoist dimension. 177 if ( ! inFunction ) return; 178 if ( storageclass == DeclarationNode::Static ) return; 179 174 180 if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) { 175 if ( ! inFunction ) return;176 177 181 if ( ! arrayType->get_dimension() ) return; // xxx - recursive call to hoist? 178 182 … … 203 207 CtorDtor ctordtor; 204 208 mutateAll( translationUnit, ctordtor ); 205 }206 207 namespace {208 Expression * makeCtorDtorExpr( std::string name, ObjectDecl * objDecl, std::list< Expression * > args ) {209 UntypedExpr * expr = new UntypedExpr( new NameExpr( name ) );210 expr->get_args().push_back( new AddressExpr( new VariableExpr( objDecl ) ) );211 expr->get_args().splice( expr->get_args().end(), args );212 return expr;213 }214 209 } 215 210 -
src/InitTweak/InitTweak.cc
r73bf8cf2 rf9cebb5 5 5 #include "SynTree/Initializer.h" 6 6 #include "SynTree/Expression.h" 7 #include "SynTree/Attribute.h" 7 8 #include "GenPoly/GenPoly.h" 8 9 … … 125 126 126 127 namespace { 128 /// given index i, dimension d, initializer init, and callExpr f, generates 129 /// if (i < d) f(..., init) 130 /// ++i; 131 /// so that only elements within the range of the array are constructed 127 132 template< typename OutIterator > 128 void dothething( UntypedExpr * callExpr, Expression * index, Expression * dimension, Initializer * init, OutIterator out ) {133 void buildCallExpr( UntypedExpr * callExpr, Expression * index, Expression * dimension, Initializer * init, OutIterator out ) { 129 134 UntypedExpr * cond = new UntypedExpr( new NameExpr( "?<?") ); 130 135 cond->get_args().push_back( index->clone() ); … … 148 153 Expression * dimension = *idx++; 149 154 155 // xxx - may want to eventually issue a warning here if we can detect 156 // that the number of elements exceeds to dimension of the array 150 157 if ( idx == idxEnd ) { 151 158 if ( ListInit * listInit = dynamic_cast< ListInit * >( init ) ) { 152 159 for ( Initializer * init : *listInit ) { 153 dothething( callExpr->clone(), index, dimension, init, out );160 buildCallExpr( callExpr->clone(), index, dimension, init, out ); 154 161 } 155 162 } else { 156 dothething( callExpr->clone(), index, dimension, init, out );163 buildCallExpr( callExpr->clone(), index, dimension, init, out ); 157 164 } 158 165 } else { … … 166 173 throw SemanticError( "unbalanced list initializers" ); 167 174 } 175 176 static UniqueName targetLabel( "L__autogen__" ); 177 Label switchLabel( targetLabel.newName(), 0, std::list< Attribute * >{ new Attribute("unused") } ); 168 178 for ( Initializer * init : *listInit ) { 169 179 Expression * condition; … … 178 188 std::list< Statement * > stmts; 179 189 build( callExpr, idx, idxEnd, init, back_inserter( stmts ) ); 190 stmts.push_back( new BranchStmt( noLabels, switchLabel, BranchStmt::Break ) ); 180 191 CaseStmt * caseStmt = new CaseStmt( noLabels, condition, stmts ); 181 192 branches.push_back( caseStmt ); 182 193 } 183 194 *out++ = new SwitchStmt( noLabels, index->clone(), branches ); 195 *out++ = new NullStmt( std::list<Label>{ switchLabel } ); 184 196 } 185 197 } … … 194 206 Statement * InitImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) { 195 207 if ( ! init ) return NULL; 196 std::list< Statement * > results;197 build( dst, indices.begin(), indices.end(), init, back_inserter( results) );198 assert( results.size() <= 1 );199 if ( results.empty() ) {208 CompoundStmt * block = new CompoundStmt( noLabels ); 209 build( dst, indices.begin(), indices.end(), init, back_inserter( block->get_kids() ) ); 210 if ( block->get_kids().empty() ) { 211 delete block; 200 212 return NULL; 201 213 } else { 202 214 init = NULL; // init was consumed in creating the list init 203 return results.front(); 204 } 205 return ! results.empty() ? results.front() : NULL; 215 return block; 216 } 206 217 } 207 218 … … 280 291 } 281 292 282 bool isIn strinsicSingleArgCallStmt( Statement * stmt ) {293 bool isIntrinsicSingleArgCallStmt( Statement * stmt ) { 283 294 std::list< Expression * > callExprs; 284 295 collectCtorDtorCalls( stmt, callExprs ); -
src/InitTweak/InitTweak.h
r73bf8cf2 rf9cebb5 41 41 /// Intended to be used for default ctor/dtor calls, but might have use elsewhere. 42 42 /// Currently has assertions that make it less than fully general. 43 bool isIn strinsicSingleArgCallStmt( Statement * expr );43 bool isIntrinsicSingleArgCallStmt( Statement * expr ); 44 44 45 45 /// get all Ctor/Dtor call expressions from a Statement
Note:
See TracChangeset
for help on using the changeset viewer.