1414// / memory locations such as a stack locations. This is mandatory for IRGen.
1515// /
1616// / Lowering to LLVM IR requires each SILValue's type to be a valid "SIL storage
17- // / type". Opaque SILValues have address-only types. Address-only values require
18- // / indirect storage in LLVM, so their SIL storage type must be an address type.
17+ // / type". Opaque SILValues have address-only types. These require indirect
18+ // / storage in LLVM, so their SIL storage type must be an address type.
1919// /
20- // / This pass should not introduce any semantic copies. Guaranteed values always
21- // / reuse the borrowed value's storage. This means that we SIL cannot allow
22- // / guaranteed opaque uses unless they are projections of the definition. In
23- // / particular, borrowed structs, tuples, and enums of address-only types are
24- // / not allowed.
20+ // / This pass never creates copies except to replace explicit value copies
21+ // / (copy_value, load [copy], store). For move-only values, this allows complete
22+ // / diagnostics. And in general, it makes it impossible for SIL passes to
23+ // / "accidentally" create copies.
2524// /
26- // / When owned values are consumed by phis, multiple storage locations are
27- // / required to avoid interfering with other phi operands. However, the value
28- // / never needs to be live in multiple storage locations a once. When the value
29- // / is consumed by a phi, either it's own storage is coalesced with the phi
30- // / storage (they have the same address), or the value is bitwise moved into the
31- // / phi's storage.
25+ // / This pass inserts moves (copy_addr [take] [initialize]) of owned values to
26+ // / - compose aggregates
27+ // / - resolve phi interference
28+ // /
29+ // / For guarantee values, this pass inserts neither copies nor moves. Opaque
30+ // / values are potentially unmovable when borrowed. This means that guaranteed
31+ // / address-only aggregates and phis are prohibited. This SIL invariant is
32+ // / enforced by SILVerifier::checkOwnershipForwardingInst() and
33+ // / SILVerifier::visitSILPhiArgument().
3234// /
3335// / ## Step #1: Map opaque values
3436// /
5860// / during rewriting.
5961// /
6062// / After allocating storage for all non-phi opaque values, phi storage is
61- // / allocated. This is handled by a PhiStorageOptimizer that checks for
63+ // / allocated. (Phi values are block arguments in which phi's arguments are
64+ // / branch operands). This is handled by a PhiStorageOptimizer that checks for
6265// / interference among the phi operands and reuses storage allocated to other
6366// / values.
6467// /
@@ -169,7 +172,7 @@ cleanupAfterCall(FullApplySite apply,
169172// Calls are currently SILValues, but when the result type is a tuple, the call
170173// value does not represent a real value with storage. This is a bad situation
171174// for address lowering because there's no way to tell from any given value
172- // whether its legal to assign storage to that value. As a result, the
175+ // whether it's legal to assign storage to that value. As a result, the
173176// implementation of call lowering doesn't fall out naturally from the algorithm
174177// that lowers values to storage.
175178// ===----------------------------------------------------------------------===//
@@ -218,7 +221,7 @@ visitCallResults(FullApplySite apply,
218221
219222// / Return true if the given value is either a "fake" tuple that represents all
220223// / of a call's results or an empty tuple of no results. This may return true
221- // / for either tuple_inst or a block argument.
224+ // / for either an apply instruction or a block argument.
222225static bool isPseudoCallResult (SILValue value) {
223226 if (auto *apply = dyn_cast<ApplyInst>(value))
224227 return ApplySite (apply).getSubstCalleeConv ().getNumDirectSILResults () > 1 ;
@@ -255,7 +258,7 @@ static bool isPseudoReturnValue(SILValue value) {
255258// / the tuple is a pseudo-return value, return the indirect function argument
256259// / for the corresponding result after lowering.
257260// /
258- // / bb0(%loweredIndirectResult : $*T, ...)
261+ // / bb0(..., %loweredIndirectResult : $*T, ...)
259262// / ....
260263// / %tuple = tuple(..., %operand, ...)
261264// / return %tuple
@@ -268,16 +271,12 @@ static bool isPseudoReturnValue(SILValue value) {
268271// / (see insertIndirectReturnArgs()).
269272static SILValue getTupleStorageValue (Operand *operand) {
270273 auto *tuple = cast<TupleInst>(operand->getUser ());
271- Operand *singleUse = tuple->getSingleUse ();
272- if (!singleUse || !isa<ReturnInst>(singleUse->getUser ()))
273- return tuple;
274-
275- SILFunction *function = tuple->getFunction ();
276- if (function->getConventions ().getNumDirectSILResults () < 2 )
274+ if (!isPseudoReturnValue (tuple))
277275 return tuple;
278276
279277 unsigned resultIdx = tuple->getElementIndex (operand);
280278
279+ auto *function = tuple->getFunction ();
281280 auto loweredFnConv = getLoweredFnConv (function);
282281 assert (loweredFnConv.getResults ().size () == tuple->getElements ().size ());
283282
@@ -286,24 +285,22 @@ static SILValue getTupleStorageValue(Operand *operand) {
286285 if (loweredFnConv.isSILIndirect (result))
287286 ++indirectResultIdx;
288287 }
289- // Cannot call F ->getIndirectSILResults here because that API uses the
288+ // Cannot call function ->getIndirectSILResults here because that API uses the
290289 // function conventions before address lowering.
291290 return function->getArguments ()[indirectResultIdx];
292291}
293292
294293// / Return the value representing storage for a single return value.
295294// /
296- // / bb0(%loweredIndirectResult : $*T, ...) // function entry
295+ // / bb0(..., %loweredIndirectResult : $*T, ...) // function entry
297296// / return %oper
298297// /
299298// / For %oper, return %loweredIndirectResult
300299static SILValue getSingleReturnAddress (Operand *operand) {
301300 assert (!isPseudoReturnValue (operand->get ()));
302301
303302 auto *function = operand->getParentFunction ();
304- auto loweredFnConv = getLoweredFnConv (function);
305- assert (loweredFnConv.getNumIndirectSILResults () == 1 );
306- (void )loweredFnConv;
303+ assert (getLoweredFnConv (function).getNumIndirectSILResults () == 1 );
307304
308305 // Cannot call getIndirectSILResults here because that API uses the
309306 // function conventions before address lowering.
@@ -331,17 +328,15 @@ static bool isStoreCopy(SILValue value) {
331328 return isa<StoreInst>(user) || isa<AssignInst>(user);
332329}
333330
334- ValueStorage & ValueStorageMap::insertValue (SILValue value) {
331+ void ValueStorageMap::insertValue (SILValue value, SILValue storageAddress ) {
335332 assert (!stableStorage && " cannot grow stable storage map" );
336333
337334 auto hashResult =
338335 valueHashMap.insert (std::make_pair (value, valueVector.size ()));
339336 (void )hashResult;
340337 assert (hashResult.second && " SILValue already mapped" );
341338
342- valueVector.emplace_back (value, ValueStorage ());
343-
344- return valueVector.back ().storage ;
339+ valueVector.emplace_back (value, ValueStorage (storageAddress));
345340}
346341
347342void ValueStorageMap::replaceValue (SILValue oldValue, SILValue newValue) {
@@ -409,7 +404,7 @@ struct AddressLoweringState {
409404 SmallBlotSetVector<FullApplySite, 16 > indirectApplies;
410405
411406 // All function-exiting terminators (return or throw instructions).
412- SmallVector<SILInstruction *, 8 > exitingInsts;
407+ SmallVector<TermInst *, 8 > exitingInsts;
413408
414409 // Copies from a phi's operand storage to the phi storage. These logically
415410 // occur on the CFG edge. Keep track of them to resolve anti-dependencies.
@@ -462,7 +457,7 @@ struct AddressLoweringState {
462457// / Before populating the ValueStorageMap, replace each value-typed argument to
463458// / the current function with an address-typed argument by inserting a temporary
464459// / load instruction.
465- static void convertIndirectFunctionArgs (AddressLoweringState &pass) {
460+ static void convertDirectToIndirectFunctionArgs (AddressLoweringState &pass) {
466461 // Insert temporary argument loads at the top of the function.
467462 SILBuilder argBuilder =
468463 pass.getBuilder (pass.function ->getEntryBlock ()->begin ());
@@ -490,9 +485,7 @@ static void convertIndirectFunctionArgs(AddressLoweringState &pass) {
490485 // Indirect calling convention may be used for loadable types. In that
491486 // case, generating the argument loads is sufficient.
492487 if (addrType.isAddressOnly (*pass.function )) {
493- auto &storage = pass.valueStorageMap .insertValue (loadArg);
494- storage.storageAddress = arg;
495- storage.isRewritten = true ;
488+ pass.valueStorageMap .insertValue (loadArg, arg);
496489 }
497490 }
498491 ++argIdx;
@@ -520,10 +513,9 @@ static unsigned insertIndirectReturnArgs(AddressLoweringState &pass) {
520513 argIdx, bodyResultTy.getAddressType (), OwnershipKind::None, var);
521514 // Insert function results into valueStorageMap so that the caller storage
522515 // can be projected onto values inside the function as use projections.
523- auto &storage = pass. valueStorageMap . insertValue (funcArg);
516+ //
524517 // This is the only case where a value defines its own storage.
525- storage.storageAddress = funcArg;
526- storage.isRewritten = true ;
518+ pass.valueStorageMap .insertValue (funcArg, funcArg);
527519
528520 ++argIdx;
529521 }
@@ -621,10 +613,11 @@ void OpaqueValueVisitor::visitValue(SILValue value) {
621613 pass.valueStorageMap .getStorage (value).storageAddress ));
622614 return ;
623615 }
624- pass.valueStorageMap .insertValue (value);
616+ pass.valueStorageMap .insertValue (value, SILValue () );
625617}
626618
627- // Canonicalize returned values.
619+ // Canonicalize returned values. For multiple direct results, the operand of the
620+ // return instruction must be a tuple with no other uses.
628621//
629622// Given $() -> @out (T, T):
630623// %t = def : $(T, T)
@@ -688,7 +681,7 @@ void OpaqueValueVisitor::canonicalizeReturnValues() {
688681// / function.
689682static void prepareValueStorage (AddressLoweringState &pass) {
690683 // Fixup this function's argument types with temporary loads.
691- convertIndirectFunctionArgs (pass);
684+ convertDirectToIndirectFunctionArgs (pass);
692685
693686 // Create a new function argument for each indirect result.
694687 insertIndirectReturnArgs (pass);
@@ -2012,7 +2005,7 @@ void ApplyRewriter::rewriteApply(ArrayRef<SILValue> newCallArgs) {
20122005
20132006// Replace \p tryApply with a new try_apply using \p newCallArgs.
20142007//
2015- // If the old result was a single address-only value, then create and return a
2008+ // If the old result was a single opaque value, then create and return a
20162009// fake load that takes its place in the storage map. Otherwise, return an
20172010// invalid SILValue.
20182011//
@@ -3056,8 +3049,8 @@ static void removeOpaquePhis(SILBasicBlock *bb, AddressLoweringState &pass) {
30563049 }
30573050}
30583051
3059- // Instructions that use an address-only value without producing one are already
3060- // deleted. The rest of the address-only definitions are now removed bottom-up
3052+ // Instructions that use an opaque value without producing one are already
3053+ // deleted. The rest of the opaque definitions are now removed bottom-up
30613054// by visiting valuestorageMap.
30623055//
30633056// Phis are removed here after all other instructions.
@@ -3145,12 +3138,12 @@ void AddressLowering::runOnFunction(SILFunction *function) {
31453138 // ## Step #1: Map opaque values
31463139 //
31473140 // First, rewrite this function's arguments and return values, then populate
3148- // pass.valueStorageMap with an entry for each address-only value.
3141+ // pass.valueStorageMap with an entry for each opaque value.
31493142 prepareValueStorage (pass);
31503143
31513144 // ## Step #2: Allocate storage
31523145 //
3153- // For each address-only value mapped in step #1, either create an
3146+ // For each opaque value mapped in step #1, either create an
31543147 // alloc_stack/dealloc_stack pair, or mark its ValueStorage entry as a
31553148 // def-projection out of its operand's def or a use projection into its
31563149 // composing use or into a phi (branch operand).
@@ -3162,7 +3155,7 @@ void AddressLowering::runOnFunction(SILFunction *function) {
31623155
31633156 // ## Step #3. Rewrite opaque values
31643157 //
3165- // Rewrite all instructions that either define or use an address-only value.
3158+ // Rewrite all instructions that either define or use an opaque value.
31663159 // Creates new '_addr' variants of instructions, obtaining the storage
31673160 // address from the 'valueStorageMap'. This materializes projections in
31683161 // forward order, setting 'storageAddress' for each projection as it goes.
0 commit comments