@@ -67,36 +67,36 @@ static SILValue buildReturnValue(SILGenFunction &SGF, SILLocation loc,
6767 return SGF.B .createTuple (loc, resultType, directResults);
6868}
6969
70- std::pair<Optional<SILValue>, SILLocation>
71- SILGenFunction::emitEpilogBB (SILLocation TopLevel) {
72- assert (ReturnDest.getBlock () && " no epilog bb prepared?!" );
73- SILBasicBlock *epilogBB = ReturnDest.getBlock ();
74- SILLocation ImplicitReturnFromTopLevel =
75- ImplicitReturnLocation::getImplicitReturnLoc (TopLevel);
76- SmallVector<SILValue, 4 > directResults;
77- Optional<SILLocation> returnLoc = None;
78-
79- // If the current BB isn't terminated, and we require a return, then we
70+ static Optional<SILLocation>
71+ prepareForEpilogBlockEmission (SILGenFunction &SGF, SILLocation topLevel,
72+ SILBasicBlock *epilogBB,
73+ SmallVectorImpl<SILValue> &directResults) {
74+ SILLocation implicitReturnFromTopLevel =
75+ ImplicitReturnLocation::getImplicitReturnLoc (topLevel);
76+
77+ // If the current BB we are inserting into isn't terminated, and we require a
78+ // return, then we
8079 // are not allowed to fall off the end of the function and can't reach here.
81- if (NeedsReturn && B.hasValidInsertionPoint ())
82- B.createUnreachable (ImplicitReturnFromTopLevel );
80+ if (SGF. NeedsReturn && SGF. B .hasValidInsertionPoint ())
81+ SGF. B .createUnreachable (implicitReturnFromTopLevel );
8382
8483 if (epilogBB->pred_empty ()) {
8584 // If the epilog was not branched to at all, kill the BB and
8685 // just emit the epilog into the current BB.
8786 while (!epilogBB->empty ())
8887 epilogBB->back ().eraseFromParent ();
89- eraseBasicBlock (epilogBB);
88+ SGF. eraseBasicBlock (epilogBB);
9089
9190 // If the current bb is terminated then the epilog is just unreachable.
92- if (!B.hasValidInsertionPoint ())
93- return { None, TopLevel } ;
91+ if (!SGF. B .hasValidInsertionPoint ())
92+ return None;
9493
9594 // We emit the epilog at the current insertion point.
96- returnLoc = ImplicitReturnFromTopLevel;
95+ return implicitReturnFromTopLevel;
96+ }
9797
98- } else if (std::next (epilogBB->pred_begin ()) == epilogBB->pred_end ()
99- && ! B.hasValidInsertionPoint ()) {
98+ if (std::next (epilogBB->pred_begin ()) == epilogBB->pred_end () &&
99+ !SGF. B .hasValidInsertionPoint ()) {
100100 // If the epilog has a single predecessor and there's no current insertion
101101 // point to fall through from, then we can weld the epilog to that
102102 // predecessor BB.
@@ -113,52 +113,71 @@ SILGenFunction::emitEpilogBB(SILLocation TopLevel) {
113113 epilogBB->getArgument (index)->replaceAllUsesWith (result);
114114 }
115115
116+ Optional<SILLocation> returnLoc;
116117 // If we are optimizing, we should use the return location from the single,
117118 // previously processed, return statement if any.
118119 if (predBranch->getLoc ().is <ReturnLocation>()) {
119120 returnLoc = predBranch->getLoc ();
120121 } else {
121- returnLoc = ImplicitReturnFromTopLevel ;
122+ returnLoc = implicitReturnFromTopLevel ;
122123 }
123-
124+
124125 // Kill the branch to the now-dead epilog BB.
125126 pred->erase (predBranch);
126127
127128 // Move any instructions from the EpilogBB to the end of the 'pred' block.
128129 pred->spliceAtEnd (epilogBB);
129130
130131 // Finally we can erase the epilog BB.
131- eraseBasicBlock (epilogBB);
132+ SGF. eraseBasicBlock (epilogBB);
132133
133134 // Emit the epilog into its former predecessor.
134- B.setInsertionPoint (pred);
135- } else {
136- // Move the epilog block to the end of the ordinary section.
137- auto endOfOrdinarySection = StartOfPostmatter;
138- B.moveBlockTo (epilogBB, endOfOrdinarySection);
135+ SGF.B .setInsertionPoint (pred);
136+ return returnLoc;
137+ }
139138
140- // Emit the epilog into the epilog bb. Its arguments are the
141- // direct results.
142- directResults. append (epilogBB-> args_begin (), epilogBB-> args_end () );
139+ // Move the epilog block to the end of the ordinary section.
140+ auto endOfOrdinarySection = SGF. StartOfPostmatter ;
141+ SGF. B . moveBlockTo (epilogBB, endOfOrdinarySection );
143142
144- // If we are falling through from the current block, the return is implicit.
145- B.emitBlock (epilogBB, ImplicitReturnFromTopLevel);
146- }
147-
148- // Emit top-level cleanups into the epilog block.
149- assert (!Cleanups.hasAnyActiveCleanups (getCleanupsDepth (),
150- ReturnDest.getDepth ()) &&
151- " emitting epilog in wrong scope" );
143+ // Emit the epilog into the epilog bb. Its arguments are the
144+ // direct results.
145+ directResults.append (epilogBB->args_begin (), epilogBB->args_end ());
152146
153- auto cleanupLoc = CleanupLocation::get (TopLevel);
154- Cleanups. emitCleanupsForReturn (cleanupLoc );
147+ // If we are falling through from the current block, the return is implicit.
148+ SGF. B . emitBlock (epilogBB, implicitReturnFromTopLevel );
155149
156150 // If the return location is known to be that of an already
157151 // processed return, use it. (This will get triggered when the
158152 // epilog logic is simplified.)
159153 //
160154 // Otherwise make the ret instruction part of the cleanups.
161- if (!returnLoc) returnLoc = cleanupLoc;
155+ auto cleanupLoc = CleanupLocation::get (topLevel);
156+ return cleanupLoc;
157+ }
158+
159+ std::pair<Optional<SILValue>, SILLocation>
160+ SILGenFunction::emitEpilogBB (SILLocation topLevel) {
161+ assert (ReturnDest.getBlock () && " no epilog bb prepared?!" );
162+ SILBasicBlock *epilogBB = ReturnDest.getBlock ();
163+ SmallVector<SILValue, 8 > directResults;
164+
165+ // Prepare the epilog block for emission. If we need to actually emit the
166+ // block, we return a real SILLocation. Otherwise, the epilog block is
167+ // actually unreachable and we can just return early.
168+ auto returnLoc =
169+ prepareForEpilogBlockEmission (*this , topLevel, epilogBB, directResults);
170+ if (!returnLoc.hasValue ()) {
171+ return {None, topLevel};
172+ }
173+
174+ // Emit top-level cleanups into the epilog block.
175+ assert (!Cleanups.hasAnyActiveCleanups (getCleanupsDepth (),
176+ ReturnDest.getDepth ()) &&
177+ " emitting epilog in wrong scope" );
178+
179+ auto cleanupLoc = CleanupLocation::get (topLevel);
180+ Cleanups.emitCleanupsForReturn (cleanupLoc);
162181
163182 // Build the return value. We don't do this if there are no direct
164183 // results; this can happen for void functions, but also happens when
@@ -167,10 +186,10 @@ SILGenFunction::emitEpilogBB(SILLocation TopLevel) {
167186 SILValue returnValue;
168187 if (!directResults.empty ()) {
169188 assert (directResults.size () == F.getConventions ().getNumDirectSILResults ());
170- returnValue = buildReturnValue (*this , TopLevel , directResults);
189+ returnValue = buildReturnValue (*this , topLevel , directResults);
171190 }
172191
173- return { returnValue, *returnLoc };
192+ return {returnValue, *returnLoc};
174193}
175194
176195SILLocation SILGenFunction::
0 commit comments