Changeset bcc0946
- Timestamp:
- Aug 31, 2018, 9:27:38 AM (6 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, cleanup-dtors, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 029e330
- Parents:
- 2bfc6b2
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/FixInit.cc
r2bfc6b2 rbcc0946 255 255 GenStructMemberCalls::generate( translationUnit ); 256 256 257 // xxx - ctor expansion currently has to be after FixCopyCtors, because there is currently a 258 // hack in the way untyped assignments are generated, where the first argument cannot have 259 // its address taken because of the way codegeneration handles UntypedExpr vs. ApplicationExpr. 260 // Thus such assignment exprs must never pushed through expression resolution (and thus should 261 // not go through the FixCopyCtors pass), otherwise they will fail -- guaranteed. 262 // Also needs to happen after GenStructMemberCalls, since otherwise member constructors exprs 263 // don't look right, and a member can be constructed more than once. 257 // Needs to happen after GenStructMemberCalls, since otherwise member constructors exprs 258 // don't have the correct form, and a member can be constructed more than once. 264 259 FixCtorExprs::fix( translationUnit ); 265 260 } 266 261 267 262 namespace { 263 /// find and return the destructor used in `input`. If `input` is not a simple destructor call, generate a thunk 264 /// that wraps the destructor, insert it into `stmtsToAdd` and return the new function declaration 265 DeclarationWithType * getDtorFunc( ObjectDecl * objDecl, Statement * input, std::list< Statement * > & stmtsToAdd ) { 266 // unwrap implicit statement wrapper 267 Statement * dtor = input; 268 if ( ImplicitCtorDtorStmt * implicit = dynamic_cast< ImplicitCtorDtorStmt * >( input ) ) { 269 // dtor = implicit->callStmt; 270 // implicit->callStmt = nullptr; 271 } 272 assert( dtor ); 273 std::list< Expression * > matches; 274 collectCtorDtorCalls( dtor, matches ); 275 276 if ( dynamic_cast< ExprStmt * >( dtor ) ) { 277 // only one destructor call in the expression 278 if ( matches.size() == 1 ) { 279 DeclarationWithType * func = getFunction( matches.front() ); 280 assertf( func, "getFunction failed to find function in %s", toString( matches.front() ).c_str() ); 281 282 // cleanup argument must be a function, not an object (including function pointer) 283 if ( FunctionDecl * dtorFunc = dynamic_cast< FunctionDecl * > ( func ) ) { 284 if ( dtorFunc->type->forall.empty() ) { 285 // simple case where the destructor is a monomorphic function call - can simply 286 // use that function as the cleanup function. 287 delete dtor; 288 return func; 289 } 290 } 291 } 292 } 293 294 // otherwise the cleanup is more complicated - need to build a single argument cleanup function that 295 // wraps the more complicated code. 296 static UniqueName dtorNamer( "__cleanup_dtor" ); 297 FunctionDecl * dtorFunc = FunctionDecl::newFunction( dtorNamer.newName(), SymTab::genDefaultType( objDecl->type->stripReferences(), false ), new CompoundStmt() ); 298 stmtsToAdd.push_back( new DeclStmt( dtorFunc ) ); 299 300 // the original code contains uses of objDecl - replace them with the newly generated 'this' parameter. 301 ObjectDecl * thisParam = getParamThis( dtorFunc->type ); 302 Expression * replacement = new VariableExpr( thisParam ); 303 304 Type * base = replacement->result->stripReferences(); 305 if ( dynamic_cast< ArrayType * >( base ) || dynamic_cast< TupleType * > ( base ) ) { 306 // need to cast away reference for array types, since the destructor is generated without the reference type, 307 // and for tuple types since tuple indexing does not work directly on a reference 308 replacement = new CastExpr( replacement, base->clone() ); 309 } 310 DeclReplacer::replace( dtor, { std::make_pair( objDecl, replacement ) } ); 311 dtorFunc->statements->push_back( strict_dynamic_cast<Statement *>( dtor ) ); 312 313 return dtorFunc; 314 } 315 268 316 void InsertImplicitCalls::insert( std::list< Declaration * > & translationUnit ) { 269 317 PassVisitor<InsertImplicitCalls> inserter; … … 602 650 603 651 // it should never be necessary to wrap a void-returning expression in a UniqueExpr - if this assumption changes, this needs to be rethought 604 assert( unqExpr-> get_result());605 if ( ImplicitCopyCtorExpr * impCpCtorExpr = dynamic_cast<ImplicitCopyCtorExpr*>( unqExpr-> get_expr()) ) {652 assert( unqExpr->result ); 653 if ( ImplicitCopyCtorExpr * impCpCtorExpr = dynamic_cast<ImplicitCopyCtorExpr*>( unqExpr->expr ) ) { 606 654 // note the variable used as the result from the call 607 assert( impCpCtorExpr-> get_result() && impCpCtorExpr->get_returnDecls().size() == 1 );608 unqExpr->set_var( new VariableExpr( impCpCtorExpr-> get_returnDecls().front() ) );655 assert( impCpCtorExpr->result && impCpCtorExpr->returnDecls.size() == 1 ); 656 unqExpr->set_var( new VariableExpr( impCpCtorExpr->returnDecls.front() ) ); 609 657 } else { 610 658 // expr isn't a call expr, so create a new temporary variable to use to hold the value of the unique expression 611 unqExpr-> set_object( ObjectDecl::newObject( toString("_unq", unqExpr->get_id()), unqExpr->get_result()->clone(), makeInit( unqExpr->get_result() )) );612 unqExpr-> set_var( new VariableExpr( unqExpr->get_object() ));659 unqExpr->object = ObjectDecl::newObject( toString("_unq", unqExpr->get_id()), unqExpr->result->clone(), makeInit( unqExpr->result ) ); 660 unqExpr->var = new VariableExpr( unqExpr->object ); 613 661 } 614 662 vars.insert( unqExpr->get_id() ); … … 618 666 CP_CTOR_PRINT( std::cerr << "FixCopyCtors: " << impCpCtorExpr << std::endl; ) 619 667 620 std::list< ObjectDecl * > & tempDecls = impCpCtorExpr-> get_tempDecls();621 std::list< ObjectDecl * > & returnDecls = impCpCtorExpr-> get_returnDecls();622 std::list< Expression * > & dtors = impCpCtorExpr-> get_dtors();668 std::list< ObjectDecl * > & tempDecls = impCpCtorExpr->tempDecls; 669 std::list< ObjectDecl * > & returnDecls = impCpCtorExpr->returnDecls; 670 std::list< Expression * > & dtors = impCpCtorExpr->dtors; 623 671 624 672 // add all temporary declarations and their constructors … … 647 695 tempDecls.clear(); 648 696 returnDecls.clear(); 649 impCpCtorExpr-> set_callExpr( nullptr );697 impCpCtorExpr->callExpr = nullptr; 650 698 std::swap( impCpCtorExpr->env, callExpr->env ); 651 699 assert( impCpCtorExpr->env == nullptr ); … … 730 778 } 731 779 732 DeclarationWithType * getDtorFunc( ObjectDecl * objDecl, Statement * input, std::list< Statement * > & stmtsToAdd ) {733 // unwrap implicit statement wrapper734 Statement * dtor = input;735 if ( ImplicitCtorDtorStmt * implicit = dynamic_cast< ImplicitCtorDtorStmt * >( input ) ) {736 // dtor = implicit->callStmt;737 // implicit->callStmt = nullptr;738 }739 assert( dtor );740 std::list< Expression * > matches;741 collectCtorDtorCalls( dtor, matches );742 743 if ( dynamic_cast< ExprStmt * >( dtor ) ) {744 // only one destructor call in the expression745 if ( matches.size() == 1 ) {746 DeclarationWithType * func = getFunction( matches.front() );747 assertf( func, "getFunction failed to find function in %s", toString( matches.front() ).c_str() );748 749 // cleanup argument must be a function, not an object (including function pointer)750 if ( FunctionDecl * dtorFunc = dynamic_cast< FunctionDecl * > ( func ) ) {751 if ( dtorFunc->type->forall.empty() ) {752 // simple case where the destructor is a monomorphic function call - can simply753 // use that function as the cleanup function.754 delete dtor;755 return func;756 }757 }758 }759 }760 761 // otherwise the cleanup is more complicated - need to build a single argument cleanup function that762 // wraps the more complicated code.763 static UniqueName dtorNamer( "__cleanup_dtor" );764 FunctionDecl * dtorFunc = FunctionDecl::newFunction( dtorNamer.newName(), SymTab::genDefaultType( objDecl->type->stripReferences(), false ), new CompoundStmt() );765 stmtsToAdd.push_back( new DeclStmt( dtorFunc ) );766 767 // the original code contains uses of objDecl - replace them with the newly generated 'this' parameter.768 ObjectDecl * thisParam = getParamThis( dtorFunc->type );769 Expression * replacement = new VariableExpr( thisParam );770 771 Type * base = replacement->result->stripReferences();772 if ( dynamic_cast< ArrayType * >( base ) || dynamic_cast< TupleType * > ( base ) ) {773 // need to cast away reference for array types, since the destructor is generated without the reference type,774 // and for tuple types since tuple indexing does not work directly on a reference775 replacement = new CastExpr( replacement, base->clone() );776 }777 DeclReplacer::replace( dtor, { std::make_pair( objDecl, replacement ) } );778 dtorFunc->statements->push_back( strict_dynamic_cast<Statement *>( dtor ) );779 780 return dtorFunc;781 }782 783 780 DeclarationWithType * FixInit::postmutate( ObjectDecl *objDecl ) { 784 781 // since this removes the init field from objDecl, it must occur after children are mutated (i.e. postmutate)
Note: See TracChangeset
for help on using the changeset viewer.