Changeset 3f7e12cb for src/InitTweak/FixInit.cc
- Timestamp:
- Nov 8, 2017, 5:43:33 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:
- 954908d
- Parents:
- 78315272 (diff), e35f30a (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
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/FixInit.cc
r78315272 r3f7e12cb 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 … … 97 93 /// true if type does not need to be copy constructed to ensure correctness 98 94 bool skipCopyConstruct( Type * type ); 99 void copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr );95 void copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr, Type * formal ); 100 96 void destructRet( ObjectDecl * ret, ImplicitCopyCtorExpr * impCpCtorExpr ); 101 97 … … 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; … … 220 214 void emit( CodeLocation, const Params &... params ); 221 215 222 FunctionDecl * function = 0;216 FunctionDecl * function = nullptr; 223 217 std::set< DeclarationWithType * > unhandled; 224 218 std::map< DeclarationWithType *, CodeLocation > usedUninit; 225 ObjectDecl * thisParam = 0;219 ObjectDecl * thisParam = nullptr; 226 220 bool isCtor = false; // true if current function is a constructor 227 StructDecl * structDecl = 0;221 StructDecl * structDecl = nullptr; 228 222 }; 229 223 … … 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 … … 268 260 269 261 GenStructMemberCalls::generate( translationUnit ); 262 270 263 // xxx - ctor expansion currently has to be after FixCopyCtors, because there is currently a 271 264 // hack in the way untyped assignments are generated, where the first argument cannot have … … 297 290 for ( std::list< Declaration * >::iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) { 298 291 try { 299 *i =maybeMutate( *i, fixer );292 maybeMutate( *i, fixer ); 300 293 translationUnit.splice( i, fixer.pass.staticDtorDecls ); 301 294 } catch( SemanticError &e ) { … … 316 309 317 310 void FixCopyCtors::fixCopyCtors( std::list< Declaration * > & translationUnit, UnqCount & unqCount ) { 318 FixCopyCtorsfixer( unqCount );311 PassVisitor<FixCopyCtors> fixer( unqCount ); 319 312 mutateAll( translationUnit, fixer ); 320 313 } … … 326 319 327 320 void FixCtorExprs::fix( std::list< Declaration * > & translationUnit ) { 328 FixCtorExprsfixer;329 fixer.mutateDeclarationList( translationUnit);321 PassVisitor<FixCtorExprs> fixer; 322 mutateAll( translationUnit, fixer ); 330 323 } 331 324 332 325 Expression * InsertImplicitCalls::postmutate( ApplicationExpr * appExpr ) { 333 assert( appExpr );334 335 326 if ( VariableExpr * function = dynamic_cast< VariableExpr * > ( appExpr->get_function() ) ) { 336 if ( LinkageSpec::isBuiltin( function->get_var()->get_linkage() )) {327 if ( function->var->linkage.is_builtin ) { 337 328 // optimization: don't need to copy construct in order to call intrinsic functions 338 329 return appExpr; 339 330 } else if ( DeclarationWithType * funcDecl = dynamic_cast< DeclarationWithType * > ( function->get_var() ) ) { 340 331 FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) ); 341 assert ( ftype);342 if ( CodeGen::isConstructor( funcDecl->get_name() ) && ftype-> get_parameters().size() == 2 ) {343 Type * t1 = getPointerBase( ftype-> get_parameters().front()->get_type() );344 Type * t2 = ftype-> get_parameters().back()->get_type();332 assertf( ftype, "Function call without function type: %s", toString( funcDecl ).c_str() ); 333 if ( CodeGen::isConstructor( funcDecl->get_name() ) && ftype->parameters.size() == 2 ) { 334 Type * t1 = getPointerBase( ftype->parameters.front()->get_type() ); 335 Type * t2 = ftype->parameters.back()->get_type(); 345 336 assert( t1 ); 346 337 … … 368 359 } 369 360 370 bool ResolveCopyCtors::skipCopyConstruct( Type * type ) { 371 return dynamic_cast< VarArgsType * >( type ) || dynamic_cast< ReferenceType * >( type ) || GenPoly::getFunctionType( type ) || Tuples::isTtype( type ); 372 } 361 bool ResolveCopyCtors::skipCopyConstruct( Type * type ) { return ! isConstructable( type ); } 373 362 374 363 Expression * ResolveCopyCtors::makeCtorDtor( const std::string & fname, ObjectDecl * var, Expression * cpArg ) { … … 377 366 ImplicitCtorDtorStmt * stmt = genCtorDtor( fname, var, cpArg ); 378 367 ExprStmt * exprStmt = strict_dynamic_cast< ExprStmt * >( stmt->get_callStmt() ); 379 Expression * untyped = exprStmt->get_expr(); 368 Expression * resolved = exprStmt->expr; 369 exprStmt->expr = nullptr; // take ownership of expr 380 370 381 371 // resolve copy constructor 382 372 // should only be one alternative for copy ctor and dtor expressions, since all arguments are fixed 383 373 // (VariableExpr and already resolved expression) 384 CP_CTOR_PRINT( std::cerr << "ResolvingCtorDtor " << untyped << std::endl; )385 Expression * resolved = ResolvExpr::findVoidExpression( untyped, indexer );374 CP_CTOR_PRINT( std::cerr << "ResolvingCtorDtor " << resolved << std::endl; ) 375 ResolvExpr::findVoidExpression( resolved, indexer ); 386 376 assert( resolved ); 387 377 if ( resolved->get_env() ) { … … 391 381 resolved->set_env( nullptr ); 392 382 } // if 393 394 383 delete stmt; 395 384 return resolved; 396 385 } 397 386 398 void ResolveCopyCtors::copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr ) {387 void ResolveCopyCtors::copyConstructArg( Expression *& arg, ImplicitCopyCtorExpr * impCpCtorExpr, Type * formal ) { 399 388 static UniqueName tempNamer("_tmp_cp"); 400 389 assert( env ); 401 390 CP_CTOR_PRINT( std::cerr << "Type Substitution: " << *env << std::endl; ) 402 assert( arg-> has_result());403 Type * result = arg-> get_result();391 assert( arg->result ); 392 Type * result = arg->result; 404 393 if ( skipCopyConstruct( result ) ) return; // skip certain non-copyable types 405 394 406 // type may involve type variables, so apply type substitution to get temporary variable's actual type 395 // type may involve type variables, so apply type substitution to get temporary variable's actual type. 396 // Use applyFree so that types bound in function pointers are not substituted, e.g. in forall(dtype T) void (*)(T). 407 397 result = result->clone(); 408 env->apply ( result );409 ObjectDecl * tmp = new ObjectDecl( tempNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0);398 env->applyFree( result ); 399 ObjectDecl * tmp = ObjectDecl::newObject( "__tmp", result, nullptr ); 410 400 tmp->get_type()->set_const( false ); 411 401 … … 417 407 // if the chosen constructor is intrinsic, the copy is unnecessary, so 418 408 // don't create the temporary and don't call the copy constructor 419 VariableExpr * function = dynamic_cast< VariableExpr * >( appExpr->get_function() ); 420 assert( function ); 421 if ( function->get_var()->get_linkage() == LinkageSpec::Intrinsic ) return; 422 } 409 VariableExpr * function = strict_dynamic_cast< VariableExpr * >( appExpr->function ); 410 if ( function->var->linkage == LinkageSpec::Intrinsic ) { 411 // arguments that need to be boxed need a temporary regardless of whether the copy constructor is intrinsic, 412 // so that the object isn't changed inside of the polymorphic function 413 if ( ! GenPoly::needsBoxing( formal, result, impCpCtorExpr->callExpr, env ) ) return; 414 } 415 } 416 417 // set a unique name for the temporary once it's certain the call is necessary 418 tmp->name = tempNamer.newName(); 423 419 424 420 // replace argument to function call with temporary 425 421 arg = new CommaExpr( cpCtor, new VariableExpr( tmp ) ); 426 impCpCtorExpr-> get_tempDecls().push_back( tmp );427 impCpCtorExpr-> get_dtors().push_front( makeCtorDtor( "^?{}", tmp ) );422 impCpCtorExpr->tempDecls.push_back( tmp ); 423 impCpCtorExpr->dtors.push_front( makeCtorDtor( "^?{}", tmp ) ); 428 424 } 429 425 … … 435 431 CP_CTOR_PRINT( std::cerr << "ResolveCopyCtors: " << impCpCtorExpr << std::endl; ) 436 432 437 ApplicationExpr * appExpr = impCpCtorExpr-> get_callExpr();433 ApplicationExpr * appExpr = impCpCtorExpr->callExpr; 438 434 439 435 // take each argument and attempt to copy construct it. 440 for ( Expression * & arg : appExpr->get_args() ) { 441 copyConstructArg( arg, impCpCtorExpr ); 436 FunctionType * ftype = GenPoly::getFunctionType( appExpr->function->result ); 437 assert( ftype ); 438 auto & params = ftype->parameters; 439 auto iter = params.begin(); 440 for ( Expression * & arg : appExpr->args ) { 441 Type * formal = nullptr; 442 if ( iter != params.end() ) { 443 DeclarationWithType * param = *iter++; 444 formal = param->get_type(); 445 } 446 447 copyConstructArg( arg, impCpCtorExpr, formal ); 442 448 } // for 443 449 … … 445 451 // initialized with the return value and is destructed later 446 452 // xxx - handle named return values? 447 Type * result = appExpr-> get_result();453 Type * result = appExpr->result; 448 454 if ( ! result->isVoid() ) { 449 455 static UniqueName retNamer("_tmp_cp_ret"); 450 456 result = result->clone(); 451 457 env->apply( result ); 452 ObjectDecl * ret = new ObjectDecl( retNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0);453 ret-> get_type()->set_const( false );454 impCpCtorExpr-> get_returnDecls().push_back( ret );458 ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr ); 459 ret->type->set_const( false ); 460 impCpCtorExpr->returnDecls.push_back( ret ); 455 461 CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; ) 456 462 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 temporary463 // destructing reference returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary 458 464 destructRet( ret, impCpCtorExpr ); 459 465 } … … 472 478 result = result->clone(); 473 479 env->apply( result ); 474 ObjectDecl * ret = new ObjectDecl( retNamer.newName(), Type::StorageClasses(), LinkageSpec::C, 0, result, 0);480 ObjectDecl * ret = ObjectDecl::newObject( retNamer.newName(), result, nullptr ); 475 481 ret->get_type()->set_const( false ); 476 482 stmtExpr->get_returnDecls().push_front( ret ); … … 493 499 visit_children = false; 494 500 } 501 } 502 503 // to prevent warnings (‘_unq0’ may be used uninitialized in this function), 504 // insert an appropriate zero initializer for UniqueExpr temporaries. 505 Initializer * makeInit( Type * t ) { 506 if ( StructInstType * inst = dynamic_cast< StructInstType * >( t ) ) { 507 // initizer for empty struct must be empty 508 if ( inst->baseStruct->members.empty() ) return new ListInit({}); 509 } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( t ) ) { 510 // initizer for empty union must be empty 511 if ( inst->baseUnion->members.empty() ) return new ListInit({}); 512 } 513 514 return new ListInit( { new SingleInit( new ConstantExpr( Constant::from_int( 0 ) ) ) } ); 495 515 } 496 516 … … 509 529 } else { 510 530 // 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) );531 unqExpr->set_object( ObjectDecl::newObject( toString("_unq", unqExpr->get_id()), unqExpr->get_result()->clone(), makeInit( unqExpr->get_result() ) ) ); 512 532 unqExpr->set_var( new VariableExpr( unqExpr->get_object() ) ); 513 533 } … … 515 535 } 516 536 517 Expression * FixCopyCtors:: mutate( ImplicitCopyCtorExpr * impCpCtorExpr ) {537 Expression * FixCopyCtors::postmutate( ImplicitCopyCtorExpr * impCpCtorExpr ) { 518 538 CP_CTOR_PRINT( std::cerr << "FixCopyCtors: " << impCpCtorExpr << std::endl; ) 519 539 520 impCpCtorExpr = strict_dynamic_cast< ImplicitCopyCtorExpr * >( Parent::mutate( impCpCtorExpr ) );521 540 std::list< ObjectDecl * > & tempDecls = impCpCtorExpr->get_tempDecls(); 522 541 std::list< ObjectDecl * > & returnDecls = impCpCtorExpr->get_returnDecls(); … … 525 544 // add all temporary declarations and their constructors 526 545 for ( ObjectDecl * obj : tempDecls ) { 527 stmtsToAdd .push_back( new DeclStmt( noLabels, obj ) );546 stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) ); 528 547 } // for 529 548 for ( ObjectDecl * obj : returnDecls ) { 530 stmtsToAdd .push_back( new DeclStmt( noLabels, obj ) );549 stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) ); 531 550 } // for 532 551 … … 536 555 } // for 537 556 538 // xxx - update to work with multiple return values539 557 ObjectDecl * returnDecl = returnDecls.empty() ? nullptr : returnDecls.front(); 540 558 Expression * callExpr = impCpCtorExpr->get_callExpr(); … … 561 579 Expression * retExpr = new CommaExpr( assign, new VariableExpr( returnDecl ) ); 562 580 // move env from callExpr to retExpr 563 retExpr->set_env( callExpr->get_env() ); 564 callExpr->set_env( nullptr ); 581 std::swap( retExpr->env, callExpr->env ); 565 582 return retExpr; 566 583 } else { … … 569 586 } 570 587 571 Expression * FixCopyCtors::mutate( StmtExpr * stmtExpr ) {588 void FixCopyCtors::premutate( StmtExpr * stmtExpr ) { 572 589 // function call temporaries should be placed at statement-level, rather than nested inside of a new statement expression, 573 590 // since temporaries can be shared across sub-expressions, e.g. 574 591 // [A, A] f(); 575 592 // g([A] x, [A] y); 576 // f(g());593 // g(f()); 577 594 // f is executed once, so the return temporary is shared across the tuple constructors for x and y. 595 // Explicitly mutating children instead of mutating the inner compound statment forces the temporaries to be added 596 // to the outer context, rather than inside of the statement expression. 597 visit_children = false; 578 598 std::list< Statement * > & stmts = stmtExpr->get_statements()->get_kids(); 579 599 for ( Statement *& stmt : stmts ) { 580 stmt = stmt->acceptMutator( * this);600 stmt = stmt->acceptMutator( *visitor ); 581 601 } // for 582 // stmtExpr = strict_dynamic_cast< StmtExpr * >( Parent::mutate( stmtExpr ) );583 602 assert( stmtExpr->get_result() ); 584 603 Type * result = stmtExpr->get_result(); 585 604 if ( ! result->isVoid() ) { 586 605 for ( ObjectDecl * obj : stmtExpr->get_returnDecls() ) { 587 stmtsToAdd .push_back( new DeclStmt( noLabels, obj ) );606 stmtsToAddBefore.push_back( new DeclStmt( noLabels, obj ) ); 588 607 } // for 589 608 // add destructors after current statement … … 592 611 } // for 593 612 // 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() ); 613 assert( ! stmts.empty() ); 596 614 assert( ! stmtExpr->get_returnDecls().empty() ); 597 body->get_kids().push_back( new ExprStmt( noLabels, new VariableExpr( stmtExpr->get_returnDecls().front() ) ) );615 stmts.push_back( new ExprStmt( noLabels, new VariableExpr( stmtExpr->get_returnDecls().front() ) ) ); 598 616 stmtExpr->get_returnDecls().clear(); 599 617 stmtExpr->get_dtors().clear(); … … 601 619 assert( stmtExpr->get_returnDecls().empty() ); 602 620 assert( stmtExpr->get_dtors().empty() ); 603 return stmtExpr;604 } 605 606 Expression * FixCopyCtors::mutate( UniqueExpr * unqExpr ) {621 } 622 623 void FixCopyCtors::premutate( UniqueExpr * unqExpr ) { 624 visit_children = false; 607 625 unqCount[ unqExpr->get_id() ]--; 608 626 static std::unordered_map< int, std::list< Statement * > > dtors; 609 627 static std::unordered_map< int, UniqueExpr * > unqMap; 610 static std::unordered_set< int > addDeref;611 628 // has to be done to clean up ImplicitCopyCtorExpr nodes, even when this node was skipped in previous passes 612 629 if ( unqMap.count( unqExpr->get_id() ) ) { … … 619 636 stmtsToAddAfter.splice( stmtsToAddAfter.end(), dtors[ unqExpr->get_id() ] ); 620 637 } 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 ); 638 return; 639 } 640 PassVisitor<FixCopyCtors> fixer( unqCount ); 628 641 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);642 stmtsToAddBefore.splice( stmtsToAddBefore.end(), fixer.pass.stmtsToAddBefore ); 630 643 unqMap[unqExpr->get_id()] = unqExpr; 631 644 if ( unqCount[ unqExpr->get_id() ] == 0 ) { // insert destructor after the last use of the unique expression 632 645 stmtsToAddAfter.splice( stmtsToAddAfter.end(), dtors[ unqExpr->get_id() ] ); 633 646 } 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; 647 } 648 649 DeclarationWithType *FixInit::postmutate( ObjectDecl *objDecl ) { 647 dtors[ unqExpr->get_id() ] = fixer.pass.stmtsToAddAfter; 648 } 649 return; 650 } 651 652 DeclarationWithType * FixInit::postmutate( ObjectDecl *objDecl ) { 650 653 // since this removes the init field from objDecl, it must occur after children are mutated (i.e. postmutate) 651 654 if ( ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ) ) { … … 745 748 } else { 746 749 ImplicitCtorDtorStmt * implicit = strict_dynamic_cast< ImplicitCtorDtorStmt * > ( ctor ); 747 ExprStmt * ctorStmt = dynamic_cast< ExprStmt * >( implicit-> get_callStmt());750 ExprStmt * ctorStmt = dynamic_cast< ExprStmt * >( implicit->callStmt ); 748 751 ApplicationExpr * ctorCall = nullptr; 749 if ( ctorStmt && (ctorCall = isIntrinsicCallExpr( ctorStmt-> get_expr())) && ctorCall->get_args().size() == 2 ) {752 if ( ctorStmt && (ctorCall = isIntrinsicCallExpr( ctorStmt->expr )) && ctorCall->get_args().size() == 2 ) { 750 753 // clean up intrinsic copy constructor calls by making them into SingleInits 751 objDecl->set_init( new SingleInit( ctorCall->get_args().back() ) ); 752 ctorCall->get_args().pop_back(); 754 Expression * ctorArg = ctorCall->args.back(); 755 std::swap( ctorArg->env, ctorCall->env ); 756 objDecl->init = new SingleInit( ctorArg ); 757 758 ctorCall->args.pop_back(); 753 759 } else { 754 760 stmtsToAddAfter.push_back( ctor ); 755 objDecl-> set_init( nullptr );756 ctorInit-> set_ctor( nullptr );761 objDecl->init = nullptr; 762 ctorInit->ctor = nullptr; 757 763 } 758 764 } // if 759 } else if ( Initializer * init = ctorInit-> get_init()) {760 objDecl-> set_init( init );761 ctorInit-> set_init( nullptr );765 } else if ( Initializer * init = ctorInit->init ) { 766 objDecl->init = init; 767 ctorInit->init = nullptr; 762 768 } else { 763 769 // no constructor and no initializer, which is okay 764 objDecl-> set_init( nullptr );770 objDecl->init = nullptr; 765 771 } // if 766 772 delete ctorInit; … … 819 825 assert( ! ctorInit->get_ctor() || ! ctorInit->get_init() ); 820 826 Statement * dtor = ctorInit->get_dtor(); 827 // don't need to call intrinsic dtor, because it does nothing, but 828 // non-intrinsic dtors must be called 821 829 if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) { 822 // don't need to call intrinsic dtor, because it does nothing, but823 // non-intrinsic dtors must be called830 // set dtor location to the object's location for error messages 831 ctorInit->dtor->location = objDecl->location; 824 832 reverseDeclOrder.front().push_front( objDecl ); 825 833 } // if … … 832 840 GuardValue( labelVars ); 833 841 labelVars.clear(); 842 // LabelFinder does not recurse into FunctionDecl, so need to visit 843 // its children manually. 834 844 maybeAccept( funcDecl->type, finder ); 835 845 maybeAccept( funcDecl->statements, finder ); … … 933 943 } 934 944 945 void addIds( SymTab::Indexer & indexer, const std::list< DeclarationWithType * > & decls ) { 946 for ( auto d : decls ) { 947 indexer.addId( d ); 948 } 949 } 950 951 void addTypes( SymTab::Indexer & indexer, const std::list< TypeDecl * > & tds ) { 952 for ( auto td : tds ) { 953 indexer.addType( td ); 954 addIds( indexer, td->assertions ); 955 } 956 } 957 935 958 void GenStructMemberCalls::previsit( FunctionDecl * funcDecl ) { 936 GuardValue( func Decl);959 GuardValue( function ); 937 960 GuardValue( unhandled ); 938 961 GuardValue( usedUninit ); … … 967 990 } 968 991 969 void addIds( SymTab::Indexer & indexer, const std::list< DeclarationWithType * > & decls ) {970 for ( auto d : decls ) {971 indexer.addId( d );972 }973 }974 975 void addTypes( SymTab::Indexer & indexer, const std::list< TypeDecl * > & tds ) {976 for ( auto td : tds ) {977 indexer.addType( td );978 addIds( indexer, td->assertions );979 }980 }981 982 992 void GenStructMemberCalls::postvisit( FunctionDecl * funcDecl ) { 983 993 // remove the unhandled objects from usedUninit, because a call is inserted … … 1012 1022 // skip non-DWT members 1013 1023 if ( ! field ) continue; 1024 // skip non-constructable members 1025 if ( ! tryConstruct( field ) ) continue; 1014 1026 // skip handled members 1015 1027 if ( ! unhandled.count( field ) ) continue; … … 1130 1142 } 1131 1143 1132 DeclarationWithType * MutatingResolver::mutate( ObjectDecl * objectDecl ) {1144 DeclarationWithType * MutatingResolver::mutate( ObjectDecl * objectDecl ) { 1133 1145 // add object to the indexer assumes that there will be no name collisions 1134 1146 // in generated code. If this changes, add mutate methods for entities with … … 1138 1150 } 1139 1151 1140 Expression* MutatingResolver::mutate( UntypedExpr *untypedExpr ) { 1141 return strict_dynamic_cast< ApplicationExpr * >( ResolvExpr::findVoidExpression( untypedExpr, indexer ) ); 1142 } 1143 1144 Expression * FixCtorExprs::mutate( ConstructorExpr * ctorExpr ) { 1152 Expression * MutatingResolver::mutate( UntypedExpr * untypedExpr ) { 1153 Expression * newExpr = untypedExpr; 1154 ResolvExpr::findVoidExpression( newExpr, indexer ); 1155 return newExpr; 1156 } 1157 1158 Expression * FixCtorExprs::postmutate( ConstructorExpr * ctorExpr ) { 1145 1159 static UniqueName tempNamer( "_tmp_ctor_expr" ); 1146 1160 // xxx - is the size check necessary? 1147 assert( ctorExpr-> has_result()&& ctorExpr->get_result()->size() == 1 );1161 assert( ctorExpr->result && ctorExpr->get_result()->size() == 1 ); 1148 1162 1149 1163 // 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 );1164 ObjectDecl * tmp = ObjectDecl::newObject( tempNamer.newName(), ctorExpr->get_result()->clone(), nullptr ); 1165 declsToAddBefore.push_back( tmp ); 1152 1166 1153 1167 // xxx - this can be TupleAssignExpr now. Need to properly handle this case. … … 1158 1172 delete ctorExpr; 1159 1173 1174 // build assignment and replace constructor's first argument with new temporary 1160 1175 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 ); 1176 Expression * assign = new UntypedExpr( new NameExpr( "?=?" ), { new AddressExpr( new VariableExpr( tmp ) ), new AddressExpr( firstArg ) } ); 1181 1177 firstArg = new VariableExpr( tmp ); 1178 1179 // resolve assignment and dispose of new env 1180 ResolvExpr::findVoidExpression( assign, indexer ); 1181 delete assign->env; 1182 assign->env = nullptr; 1182 1183 1183 1184 // for constructor expr:
Note:
See TracChangeset
for help on using the changeset viewer.