Changes in src/InitTweak/FixInit.cc [888339e:698ec72]
- File:
-
- 1 edited
-
src/InitTweak/FixInit.cc (modified) (28 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/FixInit.cc
r888339e r698ec72 36 36 #include "FixGlobalInit.h" // for fixGlobalInit 37 37 #include "GenInit.h" // for genCtorDtor 38 #include "GenPoly/DeclMutator.h" // for DeclMutator 38 39 #include "GenPoly/GenPoly.h" // for getFunctionType 40 #include "GenPoly/PolyMutator.h" // for PolyMutator 39 41 #include "InitTweak.h" // for getFunctionName, getCallArg 40 42 #include "Parser/LinkageSpec.h" // for C, Spec, Cforall, isBuiltin … … 44 46 #include "SymTab/Indexer.h" // for Indexer 45 47 #include "SymTab/Mangler.h" // for Mangler 48 #include "SynTree/AddStmtVisitor.h" // for AddStmtVisitor 46 49 #include "SynTree/Attribute.h" // for Attribute 47 50 #include "SynTree/Constant.h" // for Constant … … 55 58 #include "SynTree/TypeSubstitution.h" // for TypeSubstitution, operator<< 56 59 #include "SynTree/Visitor.h" // for acceptAll, maybeAccept 60 #include "Tuples/Tuples.h" // for isTtype 57 61 58 62 bool ctordtorp = false; // print all debug … … 183 187 }; 184 188 185 class FixCopyCtors final : public WithStmtsToAdd, public WithShortCircuiting, public WithVisitorRef<FixCopyCtors>{189 class FixCopyCtors final : public GenPoly::PolyMutator { 186 190 public: 187 191 FixCopyCtors( UnqCount & unqCount ) : unqCount( unqCount ){} … … 190 194 static void fixCopyCtors( std::list< Declaration * > &translationUnit, UnqCount & unqCount ); 191 195 192 Expression * postmutate( ImplicitCopyCtorExpr * impCpCtorExpr ); 193 void premutate( StmtExpr * stmtExpr ); 194 void premutate( UniqueExpr * unqExpr ); 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; 195 201 196 202 UnqCount & unqCount; … … 237 243 }; 238 244 239 struct FixCtorExprs final : public WithDeclsToAdd, public WithIndexer { 245 class FixCtorExprs final : public GenPoly::DeclMutator { 246 public: 240 247 /// expands ConstructorExpr nodes into comma expressions, using a temporary for the first argument 241 248 static void fix( std::list< Declaration * > & translationUnit ); 242 249 243 Expression * postmutate( ConstructorExpr * ctorExpr ); 250 using GenPoly::DeclMutator::mutate; 251 virtual Expression * mutate( ConstructorExpr * ctorExpr ) override; 244 252 }; 245 253 } // namespace … … 308 316 309 317 void FixCopyCtors::fixCopyCtors( std::list< Declaration * > & translationUnit, UnqCount & unqCount ) { 310 PassVisitor<FixCopyCtors>fixer( unqCount );318 FixCopyCtors fixer( unqCount ); 311 319 mutateAll( translationUnit, fixer ); 312 320 } … … 318 326 319 327 void FixCtorExprs::fix( std::list< Declaration * > & translationUnit ) { 320 PassVisitor<FixCtorExprs>fixer;321 mutateAll( translationUnit, fixer);328 FixCtorExprs fixer; 329 fixer.mutateDeclarationList( translationUnit ); 322 330 } 323 331 … … 331 339 } else if ( DeclarationWithType * funcDecl = dynamic_cast< DeclarationWithType * > ( function->get_var() ) ) { 332 340 FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) ); 333 assert f( ftype, "Function call without function type: %s", toString( funcDecl ).c_str());341 assert( ftype ); 334 342 if ( CodeGen::isConstructor( funcDecl->get_name() ) && ftype->get_parameters().size() == 2 ) { 335 343 Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() ); … … 360 368 } 361 369 362 bool ResolveCopyCtors::skipCopyConstruct( Type * type ) { return ! isConstructable( type ); } 370 bool ResolveCopyCtors::skipCopyConstruct( Type * type ) { 371 return dynamic_cast< VarArgsType * >( type ) || dynamic_cast< ReferenceType * >( type ) || GenPoly::getFunctionType( type ) || Tuples::isTtype( type ); 372 } 363 373 364 374 Expression * ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) { … … 397 407 result = result->clone(); 398 408 env->apply( result ); 399 ObjectDecl * tmp = ObjectDecl::newObject( "__tmp", result, nullptr);409 ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0 ); 400 410 tmp->get_type()->set_const( false ); 401 411 … … 411 421 if ( function->get_var()->get_linkage() == LinkageSpec::Intrinsic ) return; 412 422 } 413 414 // set a unique name for the temporary once it's certain the call is necessary415 tmp->name = tempNamer.newName();416 423 417 424 // replace argument to function call with temporary … … 443 450 result = result->clone(); 444 451 env->apply( result ); 445 ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr);452 ObjectDecl * ret = new ObjectDecl( retNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0 ); 446 453 ret->get_type()->set_const( false ); 447 454 impCpCtorExpr->get_returnDecls().push_back( ret ); 448 455 CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; ) 449 456 if ( ! dynamic_cast< ReferenceType * >( result ) ) { 450 // destructing reference returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary457 // destructing lvalue returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary 451 458 destructRet( ret, impCpCtorExpr ); 452 459 } … … 465 472 result = result->clone(); 466 473 env->apply( result ); 467 ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr);474 ObjectDecl * ret = new ObjectDecl( retNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0 ); 468 475 ret->get_type()->set_const( false ); 469 476 stmtExpr->get_returnDecls().push_front( ret ); … … 502 509 } else { 503 510 // expr isn't a call expr, so create a new temporary variable to use to hold the value of the unique expression 504 unqExpr->set_object( ObjectDecl::newObject( toString("_unq", unqExpr->get_id()), unqExpr->get_result()->clone(), nullptr ) );511 unqExpr->set_object( new ObjectDecl( toString("_unq", unqExpr->get_id()), Type::StorageClasses(), LinkageSpec::C, nullptr, unqExpr->get_result()->clone(), nullptr ) ); 505 512 unqExpr->set_var( new VariableExpr( unqExpr->get_object() ) ); 506 513 } … … 508 515 } 509 516 510 Expression * FixCopyCtors:: postmutate( ImplicitCopyCtorExpr * impCpCtorExpr ) {517 Expression * FixCopyCtors::mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) { 511 518 CP_CTOR_PRINT( std::cerr << "FixCopyCtors: " << impCpCtorExpr << std::endl; ) 512 519 520 impCpCtorExpr = strict_dynamic_cast< ImplicitCopyCtorExpr * >( Parent::mutate( impCpCtorExpr ) ); 513 521 std::list< ObjectDecl * > & tempDecls = impCpCtorExpr->get_tempDecls(); 514 522 std::list< ObjectDecl * > & returnDecls = impCpCtorExpr->get_returnDecls(); … … 517 525 // add all temporary declarations and their constructors 518 526 for ( ObjectDecl * obj : tempDecls ) { 519 stmtsToAdd Before.push_back( new DeclStmt( noLabels, obj ) );527 stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) ); 520 528 } // for 521 529 for ( ObjectDecl * obj : returnDecls ) { 522 stmtsToAdd Before.push_back( new DeclStmt( noLabels, obj ) );530 stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) ); 523 531 } // for 524 532 … … 528 536 } // for 529 537 538 // xxx - update to work with multiple return values 530 539 ObjectDecl * returnDecl = returnDecls.empty() ? nullptr : returnDecls.front(); 531 540 Expression * callExpr = impCpCtorExpr->get_callExpr(); … … 560 569 } 561 570 562 void FixCopyCtors::premutate( StmtExpr * stmtExpr ) {571 Expression * FixCopyCtors::mutate( StmtExpr * stmtExpr ) { 563 572 // function call temporaries should be placed at statement-level, rather than nested inside of a new statement expression, 564 573 // since temporaries can be shared across sub-expressions, e.g. 565 574 // [A, A] f(); 566 575 // g([A] x, [A] y); 567 // g(f());576 // f(g()); 568 577 // 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 added570 // to the outer context, rather than inside of the statement expression.571 visit_children = false;572 578 std::list< Statement * > & stmts = stmtExpr->get_statements()->get_kids(); 573 579 for ( Statement *& stmt : stmts ) { 574 stmt = stmt->acceptMutator( * visitor);580 stmt = stmt->acceptMutator( *this ); 575 581 } // for 582 // stmtExpr = strict_dynamic_cast< StmtExpr * >( Parent::mutate( stmtExpr ) ); 576 583 assert( stmtExpr->get_result() ); 577 584 Type * result = stmtExpr->get_result(); 578 585 if ( ! result->isVoid() ) { 579 586 for ( ObjectDecl * obj : stmtExpr->get_returnDecls() ) { 580 stmtsToAdd Before.push_back( new DeclStmt( noLabels, obj ) );587 stmtsToAdd.push_back( new DeclStmt( noLabels, obj ) ); 581 588 } // for 582 589 // add destructors after current statement … … 585 592 } // for 586 593 // must have a non-empty body, otherwise it wouldn't have a result 587 assert( ! stmts.empty() ); 594 CompoundStmt * body = stmtExpr->get_statements(); 595 assert( ! body->get_kids().empty() ); 588 596 assert( ! stmtExpr->get_returnDecls().empty() ); 589 stmts.push_back( new ExprStmt( noLabels, new VariableExpr( stmtExpr->get_returnDecls().front() ) ) );597 body->get_kids().push_back( new ExprStmt( noLabels, new VariableExpr( stmtExpr->get_returnDecls().front() ) ) ); 590 598 stmtExpr->get_returnDecls().clear(); 591 599 stmtExpr->get_dtors().clear(); … … 593 601 assert( stmtExpr->get_returnDecls().empty() ); 594 602 assert( stmtExpr->get_dtors().empty() ); 595 }596 597 void FixCopyCtors::premutate( UniqueExpr * unqExpr ) { 598 visit_children = false;603 return stmtExpr; 604 } 605 606 Expression * FixCopyCtors::mutate( UniqueExpr * unqExpr ) { 599 607 unqCount[ unqExpr->get_id() ]--; 600 608 static std::unordered_map< int, std::list< Statement * > > dtors; 601 609 static std::unordered_map< int, UniqueExpr * > unqMap; 610 static std::unordered_set< int > addDeref; 602 611 // has to be done to clean up ImplicitCopyCtorExpr nodes, even when this node was skipped in previous passes 603 612 if ( unqMap.count( unqExpr->get_id() ) ) { … … 610 619 stmtsToAddAfter.splice( stmtsToAddAfter.end(), dtors[ unqExpr->get_id() ] ); 611 620 } 612 return; 613 } 614 PassVisitor<FixCopyCtors> fixer( unqCount ); 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 ); 615 628 unqExpr->set_expr( unqExpr->get_expr()->acceptMutator( fixer ) ); // stmtexprs contained should not be separately fixed, so this must occur after the lookup 616 stmtsToAdd Before.splice( stmtsToAddBefore.end(), fixer.pass.stmtsToAddBefore);629 stmtsToAdd.splice( stmtsToAdd.end(), fixer.stmtsToAdd ); 617 630 unqMap[unqExpr->get_id()] = unqExpr; 618 631 if ( unqCount[ unqExpr->get_id() ] == 0 ) { // insert destructor after the last use of the unique expression 619 632 stmtsToAddAfter.splice( stmtsToAddAfter.end(), dtors[ unqExpr->get_id() ] ); 620 633 } else { // remember dtors for last instance of unique expr 621 dtors[ unqExpr->get_id() ] = fixer.pass.stmtsToAddAfter; 622 } 623 return; 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; 624 647 } 625 648 … … 796 819 assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() ); 797 820 Statement * dtor = ctorInit->get_dtor(); 798 // don't need to call intrinsic dtor, because it does nothing, but799 // non-intrinsic dtors must be called800 821 if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) { 801 // set dtor location to the object's location for error messages802 ctorInit->dtor->location = objDecl->location;822 // don't need to call intrinsic dtor, because it does nothing, but 823 // non-intrinsic dtors must be called 803 824 reverseDeclOrder.front().push_front( objDecl ); 804 825 } // if … … 991 1012 // skip non-DWT members 992 1013 if ( ! field ) continue; 993 // skip non-constructable members994 if ( ! tryConstruct( field ) ) continue;995 1014 // skip handled members 996 1015 if ( ! unhandled.count( field ) ) continue; … … 1123 1142 } 1124 1143 1125 Expression * FixCtorExprs:: postmutate( ConstructorExpr * ctorExpr ) {1144 Expression * FixCtorExprs::mutate( ConstructorExpr * ctorExpr ) { 1126 1145 static UniqueName tempNamer( "_tmp_ctor_expr" ); 1127 1146 // xxx - is the size check necessary? … … 1129 1148 1130 1149 // 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. 1131 ObjectDecl * tmp = ObjectDecl::newObject( tempNamer.newName(), ctorExpr->get_result()->clone(), nullptr );1132 declsToAddBefore.push_back( tmp );1150 ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, nullptr, ctorExpr->get_result()->clone(), nullptr ); 1151 addDeclaration( tmp ); 1133 1152 1134 1153 // xxx - this can be TupleAssignExpr now. Need to properly handle this case. … … 1139 1158 delete ctorExpr; 1140 1159 1141 // build assignment and replace constructor's first argument with new temporary1142 1160 Expression *& firstArg = callExpr->get_args().front(); 1143 Expression * assign = new UntypedExpr( new NameExpr( "?=?" ), { new AddressExpr( new VariableExpr( tmp ) ), new AddressExpr( firstArg ) } ); 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 ); 1144 1181 firstArg = new VariableExpr( tmp ); 1145 1146 // resolve assignment and dispose of new env1147 Expression * resolvedAssign = ResolvExpr::findVoidExpression( assign, indexer );1148 delete resolvedAssign->env;1149 resolvedAssign->env = nullptr;1150 delete assign;1151 1182 1152 1183 // for constructor expr: … … 1157 1188 // T & tmp; 1158 1189 // &tmp = &x, ?{}(tmp), tmp 1159 CommaExpr * commaExpr = new CommaExpr( resolvedAssign, new CommaExpr( callExpr, new VariableExpr( tmp ) ) );1190 CommaExpr * commaExpr = new CommaExpr( assign, new CommaExpr( callExpr, new VariableExpr( tmp ) ) ); 1160 1191 commaExpr->set_env( env ); 1161 1192 return commaExpr;
Note:
See TracChangeset
for help on using the changeset viewer.