Changeset 74bba15 for src/InitTweak/FixInit.cc
- Timestamp:
- Sep 26, 2017, 5:19:32 PM (8 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- 5dc26f5
- Parents:
- af58ee0 (diff), a7d151f (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - File:
-
- 1 edited
-
src/InitTweak/FixInit.cc (modified) (28 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/FixInit.cc
raf58ee0 r74bba15 36 36 #include "FixGlobalInit.h" // for fixGlobalInit 37 37 #include "GenInit.h" // for genCtorDtor 38 #include "GenPoly/DeclMutator.h" // for DeclMutator39 38 #include "GenPoly/GenPoly.h" // for getFunctionType 40 #include "GenPoly/PolyMutator.h" // for PolyMutator41 39 #include "InitTweak.h" // for getFunctionName, getCallArg 42 40 #include "Parser/LinkageSpec.h" // for C, Spec, Cforall, isBuiltin … … 46 44 #include "SymTab/Indexer.h" // for Indexer 47 45 #include "SymTab/Mangler.h" // for Mangler 48 #include "SynTree/AddStmtVisitor.h" // for AddStmtVisitor49 46 #include "SynTree/Attribute.h" // for Attribute 50 47 #include "SynTree/Constant.h" // for Constant … … 58 55 #include "SynTree/TypeSubstitution.h" // for TypeSubstitution, operator<< 59 56 #include "SynTree/Visitor.h" // for acceptAll, maybeAccept 60 #include "Tuples/Tuples.h" // for isTtype61 57 62 58 bool ctordtorp = false; // print all debug … … 187 183 }; 188 184 189 class FixCopyCtors final : public GenPoly::PolyMutator{185 class FixCopyCtors final : public WithStmtsToAdd, public WithShortCircuiting, public WithVisitorRef<FixCopyCtors> { 190 186 public: 191 187 FixCopyCtors( UnqCount & unqCount ) : unqCount( unqCount ){} … … 194 190 static void fixCopyCtors( std::list< Declaration * > &translationUnit, UnqCount & unqCount ); 195 191 196 typedef GenPoly::PolyMutator Parent; 197 using Parent::mutate; 198 virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) override; 199 virtual Expression * mutate( UniqueExpr * unqExpr ) override; 200 virtual Expression * mutate( StmtExpr * stmtExpr ) override; 192 Expression * postmutate( ImplicitCopyCtorExpr * impCpCtorExpr ); 193 void premutate( StmtExpr * stmtExpr ); 194 void premutate( UniqueExpr * unqExpr ); 201 195 202 196 UnqCount & unqCount; … … 243 237 }; 244 238 245 class FixCtorExprs final : public GenPoly::DeclMutator { 246 public: 239 struct FixCtorExprs final : public WithDeclsToAdd, public WithIndexer { 247 240 /// expands ConstructorExpr nodes into comma expressions, using a temporary for the first argument 248 241 static void fix( std::list< Declaration * > & translationUnit ); 249 242 250 using GenPoly::DeclMutator::mutate; 251 virtual Expression * mutate( ConstructorExpr * ctorExpr ) override; 243 Expression * postmutate( ConstructorExpr * ctorExpr ); 252 244 }; 253 245 } // namespace … … 316 308 317 309 void FixCopyCtors::fixCopyCtors( std::list< Declaration * > & translationUnit, UnqCount & unqCount ) { 318 FixCopyCtorsfixer( unqCount );310 PassVisitor<FixCopyCtors> fixer( unqCount ); 319 311 mutateAll( translationUnit, fixer ); 320 312 } … … 326 318 327 319 void FixCtorExprs::fix( std::list< Declaration * > & translationUnit ) { 328 FixCtorExprsfixer;329 fixer.mutateDeclarationList( translationUnit);320 PassVisitor<FixCtorExprs> fixer; 321 mutateAll( translationUnit, fixer ); 330 322 } 331 323 … … 339 331 } else if ( DeclarationWithType * funcDecl = dynamic_cast< DeclarationWithType * > ( function->get_var() ) ) { 340 332 FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) ); 341 assert ( ftype);333 assertf( ftype, "Function call without function type: %s", toString( funcDecl ).c_str() ); 342 334 if ( CodeGen::isConstructor( funcDecl->get_name() ) && ftype->get_parameters().size() == 2 ) { 343 335 Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() ); … … 368 360 } 369 361 370 bool ResolveCopyCtors::skipCopyConstruct( Type * type ) { 371 return dynamic_cast< VarArgsType * >( type ) || dynamic_cast< ReferenceType * >( type ) || GenPoly::getFunctionType( type ) || Tuples::isTtype( type ); 372 } 362 bool ResolveCopyCtors::skipCopyConstruct( Type * type ) { return ! isConstructable( type ); } 373 363 374 364 Expression * ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) { … … 407 397 result = result->clone(); 408 398 env->apply( result ); 409 ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0);399 ObjectDecl * tmp = ObjectDecl::newObject( "__tmp", result, nullptr ); 410 400 tmp->get_type()->set_const( false ); 411 401 … … 421 411 if ( function->get_var()->get_linkage() == LinkageSpec::Intrinsic ) return; 422 412 } 413 414 // set a unique name for the temporary once it's certain the call is necessary 415 tmp->name = tempNamer.newName(); 423 416 424 417 // replace argument to function call with temporary … … 450 443 result = result->clone(); 451 444 env->apply( result ); 452 ObjectDecl * ret = new ObjectDecl( retNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0);445 ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr ); 453 446 ret->get_type()->set_const( false ); 454 447 impCpCtorExpr->get_returnDecls().push_back( ret ); 455 448 CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; ) 456 449 if ( ! dynamic_cast< ReferenceType * >( result ) ) { 457 // destructing lvalue returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary450 // destructing reference returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary 458 451 destructRet( ret, impCpCtorExpr ); 459 452 } … … 472 465 result = result->clone(); 473 466 env->apply( result ); 474 ObjectDecl * ret = new ObjectDecl( retNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0);467 ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr ); 475 468 ret->get_type()->set_const( false ); 476 469 stmtExpr->get_returnDecls().push_front( ret ); … … 509 502 } else { 510 503 // expr isn't a call expr, so create a new temporary variable to use to hold the value of the unique expression 511 unqExpr->set_object( new ObjectDecl( toString("_unq", unqExpr->get_id()), Type::StorageClasses(), LinkageSpec::C, nullptr, unqExpr->get_result()->clone(), nullptr ) );504 unqExpr->set_object( ObjectDecl::newObject( toString("_unq", unqExpr->get_id()), unqExpr->get_result()->clone(), nullptr ) ); 512 505 unqExpr->set_var( new VariableExpr( unqExpr->get_object() ) ); 513 506 } … … 515 508 } 516 509 517 Expression * FixCopyCtors:: mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) {510 Expression * FixCopyCtors::postmutate( ImplicitCopyCtorExpr * impCpCtorExpr ) { 518 511 CP_CTOR_PRINT( std::cerr << "FixCopyCtors: " << impCpCtorExpr << std::endl; ) 519 512 520 impCpCtorExpr = strict_dynamic_cast< ImplicitCopyCtorExpr * >( Parent::mutate( impCpCtorExpr ) );521 513 std::list< ObjectDecl * > & tempDecls = impCpCtorExpr->get_tempDecls(); 522 514 std::list< ObjectDecl * > & returnDecls = impCpCtorExpr->get_returnDecls(); … … 525 517 // add all temporary declarations and their constructors 526 518 for ( ObjectDecl * obj : tempDecls ) { 527 stmtsToAdd .push_back( new DeclStmt( noLabels, obj ) );519 stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) ); 528 520 } // for 529 521 for ( ObjectDecl * obj : returnDecls ) { 530 stmtsToAdd .push_back( new DeclStmt( noLabels, obj ) );522 stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) ); 531 523 } // for 532 524 … … 536 528 } // for 537 529 538 // xxx - update to work with multiple return values539 530 ObjectDecl * returnDecl = returnDecls.empty() ? nullptr : returnDecls.front(); 540 531 Expression * callExpr = impCpCtorExpr->get_callExpr(); … … 569 560 } 570 561 571 Expression * FixCopyCtors::mutate( StmtExpr * stmtExpr ) {562 void FixCopyCtors::premutate( StmtExpr * stmtExpr ) { 572 563 // function call temporaries should be placed at statement-level, rather than nested inside of a new statement expression, 573 564 // since temporaries can be shared across sub-expressions, e.g. 574 565 // [A, A] f(); 575 566 // g([A] x, [A] y); 576 // f(g());567 // g(f()); 577 568 // f is executed once, so the return temporary is shared across the tuple constructors for x and y. 569 // Explicitly mutating children instead of mutating the inner compound statment forces the temporaries to be added 570 // to the outer context, rather than inside of the statement expression. 571 visit_children = false; 578 572 std::list< Statement * > & stmts = stmtExpr->get_statements()->get_kids(); 579 573 for ( Statement *& stmt : stmts ) { 580 stmt = stmt->acceptMutator( * this);574 stmt = stmt->acceptMutator( *visitor ); 581 575 } // for 582 // stmtExpr = strict_dynamic_cast< StmtExpr * >( Parent::mutate( stmtExpr ) );583 576 assert( stmtExpr->get_result() ); 584 577 Type * result = stmtExpr->get_result(); 585 578 if ( ! result->isVoid() ) { 586 579 for ( ObjectDecl * obj : stmtExpr->get_returnDecls() ) { 587 stmtsToAdd .push_back( new DeclStmt( noLabels, obj ) );580 stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) ); 588 581 } // for 589 582 // add destructors after current statement … … 592 585 } // for 593 586 // must have a non-empty body, otherwise it wouldn't have a result 594 CompoundStmt * body = stmtExpr->get_statements(); 595 assert( ! body->get_kids().empty() ); 587 assert( ! stmts.empty() ); 596 588 assert( ! stmtExpr->get_returnDecls().empty() ); 597 body->get_kids().push_back( new ExprStmt( noLabels, new VariableExpr( stmtExpr->get_returnDecls().front() ) ) );589 stmts.push_back( new ExprStmt( noLabels, new VariableExpr( stmtExpr->get_returnDecls().front() ) ) ); 598 590 stmtExpr->get_returnDecls().clear(); 599 591 stmtExpr->get_dtors().clear(); … … 601 593 assert( stmtExpr->get_returnDecls().empty() ); 602 594 assert( stmtExpr->get_dtors().empty() ); 603 return stmtExpr;604 } 605 606 Expression * FixCopyCtors::mutate( UniqueExpr * unqExpr ) {595 } 596 597 void FixCopyCtors::premutate( UniqueExpr * unqExpr ) { 598 visit_children = false; 607 599 unqCount[ unqExpr->get_id() ]--; 608 600 static std::unordered_map< int, std::list< Statement * > > dtors; 609 601 static std::unordered_map< int, UniqueExpr * > unqMap; 610 static std::unordered_set< int > addDeref;611 602 // has to be done to clean up ImplicitCopyCtorExpr nodes, even when this node was skipped in previous passes 612 603 if ( unqMap.count( unqExpr->get_id() ) ) { … … 619 610 stmtsToAddAfter.splice( stmtsToAddAfter.end(), dtors[ unqExpr->get_id() ] ); 620 611 } 621 if ( addDeref.count( unqExpr->get_id() ) ) { 622 // other UniqueExpr was dereferenced because it was an lvalue return, so this one should be too 623 return UntypedExpr::createDeref( unqExpr ); 624 } 625 return unqExpr; 626 } 627 FixCopyCtors fixer( unqCount ); 612 return; 613 } 614 PassVisitor<FixCopyCtors> fixer( unqCount ); 628 615 unqExpr->set_expr( unqExpr->get_expr()->acceptMutator( fixer ) ); // stmtexprs contained should not be separately fixed, so this must occur after the lookup 629 stmtsToAdd .splice( stmtsToAdd.end(), fixer.stmtsToAdd);616 stmtsToAddBefore.splice( stmtsToAddBefore.end(), fixer.pass.stmtsToAddBefore ); 630 617 unqMap[unqExpr->get_id()] = unqExpr; 631 618 if ( unqCount[ unqExpr->get_id() ] == 0 ) { // insert destructor after the last use of the unique expression 632 619 stmtsToAddAfter.splice( stmtsToAddAfter.end(), dtors[ unqExpr->get_id() ] ); 633 620 } else { // remember dtors for last instance of unique expr 634 dtors[ unqExpr->get_id() ] = fixer.stmtsToAddAfter; 635 } 636 if ( UntypedExpr * deref = dynamic_cast< UntypedExpr * >( unqExpr->get_expr() ) ) { 637 // unique expression is now a dereference, because the inner expression is an lvalue returning function call. 638 // Normalize the expression by dereferencing the unique expression, rather than the inner expression 639 // (i.e. move the dereference out a level) 640 assert( getFunctionName( deref ) == "*?" ); 641 unqExpr->set_expr( getCallArg( deref, 0 ) ); 642 getCallArg( deref, 0 ) = unqExpr; 643 addDeref.insert( unqExpr->get_id() ); 644 return deref; 645 } 646 return unqExpr; 621 dtors[ unqExpr->get_id() ] = fixer.pass.stmtsToAddAfter; 622 } 623 return; 647 624 } 648 625 … … 819 796 assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() ); 820 797 Statement * dtor = ctorInit->get_dtor(); 798 // don't need to call intrinsic dtor, because it does nothing, but 799 // non-intrinsic dtors must be called 821 800 if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) { 822 // don't need to call intrinsic dtor, because it does nothing, but823 // non-intrinsic dtors must be called801 // set dtor location to the object's location for error messages 802 ctorInit->dtor->location = objDecl->location; 824 803 reverseDeclOrder.front().push_front( objDecl ); 825 804 } // if … … 1012 991 // skip non-DWT members 1013 992 if ( ! field ) continue; 993 // skip non-constructable members 994 if ( ! tryConstruct( field ) ) continue; 1014 995 // skip handled members 1015 996 if ( ! unhandled.count( field ) ) continue; … … 1142 1123 } 1143 1124 1144 Expression * FixCtorExprs:: mutate( ConstructorExpr * ctorExpr ) {1125 Expression * FixCtorExprs::postmutate( ConstructorExpr * ctorExpr ) { 1145 1126 static UniqueName tempNamer( "_tmp_ctor_expr" ); 1146 1127 // xxx - is the size check necessary? … … 1148 1129 1149 1130 // xxx - ideally we would reuse the temporary generated from the copy constructor passes from within firstArg if it exists and not generate a temporary if it's unnecessary. 1150 ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, nullptr, ctorExpr->get_result()->clone(), nullptr );1151 addDeclaration( tmp );1131 ObjectDecl * tmp = ObjectDecl::newObject( tempNamer.newName(), ctorExpr->get_result()->clone(), nullptr ); 1132 declsToAddBefore.push_back( tmp ); 1152 1133 1153 1134 // xxx - this can be TupleAssignExpr now. Need to properly handle this case. … … 1158 1139 delete ctorExpr; 1159 1140 1141 // build assignment and replace constructor's first argument with new temporary 1160 1142 Expression *& firstArg = callExpr->get_args().front(); 1161 1162 // xxx - hack in 'fake' assignment operator until resolver can easily be called in this pass. Once the resolver can be used in PassVisitor, this hack goes away. 1163 1164 // generate the type of assignment operator using the type of tmp minus any reference types 1165 Type * type = tmp->get_type()->stripReferences(); 1166 FunctionType * ftype = SymTab::genAssignType( type ); 1167 1168 // generate fake assignment decl and call it using &tmp and &firstArg 1169 // since tmp is guaranteed to be a reference and we want to assign pointers 1170 FunctionDecl * assignDecl = new FunctionDecl( "?=?", Type::StorageClasses(), LinkageSpec::Intrinsic, ftype, nullptr ); 1171 ApplicationExpr * assign = new ApplicationExpr( VariableExpr::functionPointer( assignDecl ) ); 1172 assign->get_args().push_back( new AddressExpr( new VariableExpr( tmp ) ) ); 1173 Expression * addrArg = new AddressExpr( firstArg ); 1174 // if firstArg has type T&&, then &firstArg has type T*&. 1175 // Cast away the reference to a value type so that the argument 1176 // matches the assignment's parameter types 1177 if ( dynamic_cast<ReferenceType *>( addrArg->get_result() ) ) { 1178 addrArg = new CastExpr( addrArg, addrArg->get_result()->stripReferences()->clone() ); 1179 } 1180 assign->get_args().push_back( addrArg ); 1143 Expression * assign = new UntypedExpr( new NameExpr( "?=?" ), { new AddressExpr( new VariableExpr( tmp ) ), new AddressExpr( firstArg ) } ); 1181 1144 firstArg = new VariableExpr( tmp ); 1145 1146 // resolve assignment and dispose of new env 1147 Expression * resolvedAssign = ResolvExpr::findVoidExpression( assign, indexer ); 1148 delete resolvedAssign->env; 1149 resolvedAssign->env = nullptr; 1150 delete assign; 1182 1151 1183 1152 // for constructor expr: … … 1188 1157 // T & tmp; 1189 1158 // &tmp = &x, ?{}(tmp), tmp 1190 CommaExpr * commaExpr = new CommaExpr( assign, new CommaExpr( callExpr, new VariableExpr( tmp ) ) );1159 CommaExpr * commaExpr = new CommaExpr( resolvedAssign, new CommaExpr( callExpr, new VariableExpr( tmp ) ) ); 1191 1160 commaExpr->set_env( env ); 1192 1161 return commaExpr;
Note:
See TracChangeset
for help on using the changeset viewer.