@@ -38,7 +38,7 @@ import dmd.dsymbol;
3838import dmd.dstruct;
3939import dmd.dtemplate;
4040import dmd.expression;
41- import dmd.expressionsem : getDsymbol, toInteger;
41+ import dmd.expressionsem : canElideCopy, getDsymbol, toInteger;
4242import dmd.func;
4343import dmd.id;
4444import dmd.init;
@@ -559,29 +559,34 @@ void Statement_toIR(Statement s, ref IRState irs, StmtState* stmtstate)
559559 void visitReturn (ReturnStatement s)
560560 {
561561 // printf("s2ir.ReturnStatement: %s\n", toChars(s.exp));
562- BlockState* blx = irs.blx;
563- BC bc;
564562
565563 incUsage(irs, s.loc);
566- void finish ()
564+ void finish (elem * e = null )
567565 {
568- block * finallyBlock ;
569- if (config.ehmethod != EHmethod. EH_DWARF &&
570- ! irs.isNothrow() &&
571- (finallyBlock = stmtstate.getFinallyBlock()) != null )
566+ BC bc = BC .ret ;
567+ BlockState * blx = irs.blx;
568+
569+ if (e )
572570 {
573- assert (finallyBlock.bc == BC .finally_);
574- blx.curblock.Bsucc.push(finallyBlock);
571+ elem_setLoc(e, s.loc);
572+ block_appendexp(blx.curblock, e);
573+ bc = BC .retexp;
574+ }
575+
576+ if (config.ehmethod != EHmethod.EH_DWARF && ! irs.isNothrow())
577+ {
578+ if (block* finallyBlock = stmtstate.getFinallyBlock())
579+ {
580+ assert (finallyBlock.bc == BC .finally_);
581+ blx.curblock.Bsucc.push(finallyBlock);
582+ }
575583 }
576584
577585 block_setLoc(blx.curblock, s.loc);
578586 block_next(blx, bc, null );
579587 }
580588 if (! s.exp)
581- {
582- bc = BC .ret;
583589 return finish ();
584- }
585590
586591 elem* e;
587592
@@ -590,78 +595,30 @@ void Statement_toIR(Statement s, ref IRState irs, StmtState* stmtstate)
590595 auto tf = func.type.isTypeFunction();
591596 assert (tf);
592597
593- RET retmethod = retStyle(tf, func.needThis());
594- if (retmethod == RET .stack)
598+ if (retStyle(tf, func.needThis()) == RET .stack)
595599 {
596- elem * es ;
597- bool writetohp ;
600+ bool nrvo = func.isNRVO && func.nrvo_var ;
601+ bool urvo = ! nrvo && canElideCopy(s.exp, s.exp.type) ;
598602
599- /* If returning struct literal, write result
600- * directly into return value
601- */
602- if (auto sle = s.exp.isStructLiteralExp())
603- {
604- sle.sym = irs.shidden;
605- writetohp = true ;
606- }
607- /* Detect function call that returns the same struct
608- * and construct directly into *shidden
609- */
610- else if (auto ce = s.exp.isCallExp())
611- {
612- if (ce.e1.op == EXP .variable || ce.e1.op == EXP .star)
613- {
614- Type t = ce.e1.type.toBasetype();
615- if (t.ty == Tdelegate)
616- t = t.nextOf();
617- if (t.ty == Tfunction && retStyle(cast (TypeFunction)t, ce.f && ce.f.needThis()) == RET .stack)
618- {
619- e = toElemDtor(s.exp, irs, el_var(irs.shidden));
620- e = el_una(OPaddr, TYnptr, e);
621- goto L1 ;
622- }
623- }
624- else if (auto dve = ce.e1.isDotVarExp())
625- {
626- auto fd = dve.var.isFuncDeclaration();
627- if (fd && fd.isCtorDeclaration())
628- {
629- if (auto sle = dve.e1.isStructLiteralExp())
630- {
631- sle.sym = irs.shidden;
632- writetohp = true ;
633- }
634- }
635- Type t = ce.e1.type.toBasetype();
636- if (t.ty == Tdelegate)
637- t = t.nextOf();
638- if (t.ty == Tfunction && retStyle(cast (TypeFunction)t, fd && fd.needThis()) == RET .stack)
639- {
640- e = toElemDtor(s.exp, irs, el_var(irs.shidden));
641- e = el_una(OPaddr, TYnptr, e);
642- goto L1 ;
643- }
644- }
645- }
646- e = toElemDtor(s.exp, irs);
603+ // Pass shidden in ehidden for URVO
604+ elem* ehidden = urvo ? el_var(irs.shidden) : null ;
605+ e = toElemDtor(s.exp, irs, ehidden);
647606 assert (e);
648607
649- if (writetohp ||
650- (func.isNRVO && func.nrvo_var))
608+ if (nrvo || urvo)
651609 {
652- // Return value via hidden pointer passed as parameter
653- // Write exp; return shidden;
654- es = e ;
610+ // For URVO, toElemDtor already returns the hidden pointer
611+ // so there is no need to rewrite
612+ e = el_una(OPaddr, TYnptr, e) ;
655613 }
656614 else
657615 {
658616 // Return value via hidden pointer passed as parameter
659617 // Write *shidden=exp; return shidden;
660- es = el_una(OPind,e.Ety,el_var(irs.shidden));
618+ elem * es = el_una(OPind, e.Ety, el_var(irs.shidden));
661619 es = elAssign(es, e, s.exp.type, null );
620+ e = el_combine(es, el_var(irs.shidden));
662621 }
663- e = el_var(irs.shidden);
664- e = el_bin(OPcomma, e.Ety, es, e);
665622 }
666623 else if (tf.isRef)
667624 {
@@ -674,13 +631,8 @@ void Statement_toIR(Statement s, ref IRState irs, StmtState* stmtstate)
674631 e = toElemDtor(s.exp, irs);
675632 assert (e);
676633 }
677- L1 :
678- elem_setLoc(e, s.loc);
679- block_appendexp(blx.curblock, e);
680- bc = BC .retexp;
681- // if (type_zeroCopy(Type_toCtype(s.exp.type)))
682- // bc = BC.ret;
683- finish();
634+
635+ finish(e);
684636 }
685637
686638 /* *************************************
0 commit comments