14
14
// / memory locations such as a stack locations. This is mandatory for IRGen.
15
15
// /
16
16
// / 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.
19
19
// /
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.
25
24
// /
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().
32
34
// /
33
35
// / ## Step #1: Map opaque values
34
36
// /
58
60
// / during rewriting.
59
61
// /
60
62
// / 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
62
65
// / interference among the phi operands and reuses storage allocated to other
63
66
// / values.
64
67
// /
@@ -169,7 +172,7 @@ cleanupAfterCall(FullApplySite apply,
169
172
// Calls are currently SILValues, but when the result type is a tuple, the call
170
173
// value does not represent a real value with storage. This is a bad situation
171
174
// 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
173
176
// implementation of call lowering doesn't fall out naturally from the algorithm
174
177
// that lowers values to storage.
175
178
// ===----------------------------------------------------------------------===//
@@ -218,7 +221,7 @@ visitCallResults(FullApplySite apply,
218
221
219
222
// / Return true if the given value is either a "fake" tuple that represents all
220
223
// / 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.
222
225
static bool isPseudoCallResult (SILValue value) {
223
226
if (auto *apply = dyn_cast<ApplyInst>(value))
224
227
return ApplySite (apply).getSubstCalleeConv ().getNumDirectSILResults () > 1 ;
@@ -255,7 +258,7 @@ static bool isPseudoReturnValue(SILValue value) {
255
258
// / the tuple is a pseudo-return value, return the indirect function argument
256
259
// / for the corresponding result after lowering.
257
260
// /
258
- // / bb0(%loweredIndirectResult : $*T, ...)
261
+ // / bb0(..., %loweredIndirectResult : $*T, ...)
259
262
// / ....
260
263
// / %tuple = tuple(..., %operand, ...)
261
264
// / return %tuple
@@ -268,16 +271,12 @@ static bool isPseudoReturnValue(SILValue value) {
268
271
// / (see insertIndirectReturnArgs()).
269
272
static SILValue getTupleStorageValue (Operand *operand) {
270
273
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))
277
275
return tuple;
278
276
279
277
unsigned resultIdx = tuple->getElementIndex (operand);
280
278
279
+ auto *function = tuple->getFunction ();
281
280
auto loweredFnConv = getLoweredFnConv (function);
282
281
assert (loweredFnConv.getResults ().size () == tuple->getElements ().size ());
283
282
@@ -286,24 +285,22 @@ static SILValue getTupleStorageValue(Operand *operand) {
286
285
if (loweredFnConv.isSILIndirect (result))
287
286
++indirectResultIdx;
288
287
}
289
- // Cannot call F ->getIndirectSILResults here because that API uses the
288
+ // Cannot call function ->getIndirectSILResults here because that API uses the
290
289
// function conventions before address lowering.
291
290
return function->getArguments ()[indirectResultIdx];
292
291
}
293
292
294
293
// / Return the value representing storage for a single return value.
295
294
// /
296
- // / bb0(%loweredIndirectResult : $*T, ...) // function entry
295
+ // / bb0(..., %loweredIndirectResult : $*T, ...) // function entry
297
296
// / return %oper
298
297
// /
299
298
// / For %oper, return %loweredIndirectResult
300
299
static SILValue getSingleReturnAddress (Operand *operand) {
301
300
assert (!isPseudoReturnValue (operand->get ()));
302
301
303
302
auto *function = operand->getParentFunction ();
304
- auto loweredFnConv = getLoweredFnConv (function);
305
- assert (loweredFnConv.getNumIndirectSILResults () == 1 );
306
- (void )loweredFnConv;
303
+ assert (getLoweredFnConv (function).getNumIndirectSILResults () == 1 );
307
304
308
305
// Cannot call getIndirectSILResults here because that API uses the
309
306
// function conventions before address lowering.
@@ -331,17 +328,15 @@ static bool isStoreCopy(SILValue value) {
331
328
return isa<StoreInst>(user) || isa<AssignInst>(user);
332
329
}
333
330
334
- ValueStorage & ValueStorageMap::insertValue (SILValue value) {
331
+ void ValueStorageMap::insertValue (SILValue value, SILValue storageAddress ) {
335
332
assert (!stableStorage && " cannot grow stable storage map" );
336
333
337
334
auto hashResult =
338
335
valueHashMap.insert (std::make_pair (value, valueVector.size ()));
339
336
(void )hashResult;
340
337
assert (hashResult.second && " SILValue already mapped" );
341
338
342
- valueVector.emplace_back (value, ValueStorage ());
343
-
344
- return valueVector.back ().storage ;
339
+ valueVector.emplace_back (value, ValueStorage (storageAddress));
345
340
}
346
341
347
342
void ValueStorageMap::replaceValue (SILValue oldValue, SILValue newValue) {
@@ -409,7 +404,7 @@ struct AddressLoweringState {
409
404
SmallBlotSetVector<FullApplySite, 16 > indirectApplies;
410
405
411
406
// All function-exiting terminators (return or throw instructions).
412
- SmallVector<SILInstruction *, 8 > exitingInsts;
407
+ SmallVector<TermInst *, 8 > exitingInsts;
413
408
414
409
// Copies from a phi's operand storage to the phi storage. These logically
415
410
// occur on the CFG edge. Keep track of them to resolve anti-dependencies.
@@ -462,7 +457,7 @@ struct AddressLoweringState {
462
457
// / Before populating the ValueStorageMap, replace each value-typed argument to
463
458
// / the current function with an address-typed argument by inserting a temporary
464
459
// / load instruction.
465
- static void convertIndirectFunctionArgs (AddressLoweringState &pass) {
460
+ static void convertDirectToIndirectFunctionArgs (AddressLoweringState &pass) {
466
461
// Insert temporary argument loads at the top of the function.
467
462
SILBuilder argBuilder =
468
463
pass.getBuilder (pass.function ->getEntryBlock ()->begin ());
@@ -490,9 +485,7 @@ static void convertIndirectFunctionArgs(AddressLoweringState &pass) {
490
485
// Indirect calling convention may be used for loadable types. In that
491
486
// case, generating the argument loads is sufficient.
492
487
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);
496
489
}
497
490
}
498
491
++argIdx;
@@ -520,10 +513,9 @@ static unsigned insertIndirectReturnArgs(AddressLoweringState &pass) {
520
513
argIdx, bodyResultTy.getAddressType (), OwnershipKind::None, var);
521
514
// Insert function results into valueStorageMap so that the caller storage
522
515
// can be projected onto values inside the function as use projections.
523
- auto &storage = pass. valueStorageMap . insertValue (funcArg);
516
+ //
524
517
// 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);
527
519
528
520
++argIdx;
529
521
}
@@ -621,10 +613,11 @@ void OpaqueValueVisitor::visitValue(SILValue value) {
621
613
pass.valueStorageMap .getStorage (value).storageAddress ));
622
614
return ;
623
615
}
624
- pass.valueStorageMap .insertValue (value);
616
+ pass.valueStorageMap .insertValue (value, SILValue () );
625
617
}
626
618
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.
628
621
//
629
622
// Given $() -> @out (T, T):
630
623
// %t = def : $(T, T)
@@ -688,7 +681,7 @@ void OpaqueValueVisitor::canonicalizeReturnValues() {
688
681
// / function.
689
682
static void prepareValueStorage (AddressLoweringState &pass) {
690
683
// Fixup this function's argument types with temporary loads.
691
- convertIndirectFunctionArgs (pass);
684
+ convertDirectToIndirectFunctionArgs (pass);
692
685
693
686
// Create a new function argument for each indirect result.
694
687
insertIndirectReturnArgs (pass);
@@ -2012,7 +2005,7 @@ void ApplyRewriter::rewriteApply(ArrayRef<SILValue> newCallArgs) {
2012
2005
2013
2006
// Replace \p tryApply with a new try_apply using \p newCallArgs.
2014
2007
//
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
2016
2009
// fake load that takes its place in the storage map. Otherwise, return an
2017
2010
// invalid SILValue.
2018
2011
//
@@ -3056,8 +3049,8 @@ static void removeOpaquePhis(SILBasicBlock *bb, AddressLoweringState &pass) {
3056
3049
}
3057
3050
}
3058
3051
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
3061
3054
// by visiting valuestorageMap.
3062
3055
//
3063
3056
// Phis are removed here after all other instructions.
@@ -3145,12 +3138,12 @@ void AddressLowering::runOnFunction(SILFunction *function) {
3145
3138
// ## Step #1: Map opaque values
3146
3139
//
3147
3140
// 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.
3149
3142
prepareValueStorage (pass);
3150
3143
3151
3144
// ## Step #2: Allocate storage
3152
3145
//
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
3154
3147
// alloc_stack/dealloc_stack pair, or mark its ValueStorage entry as a
3155
3148
// def-projection out of its operand's def or a use projection into its
3156
3149
// composing use or into a phi (branch operand).
@@ -3162,7 +3155,7 @@ void AddressLowering::runOnFunction(SILFunction *function) {
3162
3155
3163
3156
// ## Step #3. Rewrite opaque values
3164
3157
//
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.
3166
3159
// Creates new '_addr' variants of instructions, obtaining the storage
3167
3160
// address from the 'valueStorageMap'. This materializes projections in
3168
3161
// forward order, setting 'storageAddress' for each projection as it goes.
0 commit comments