17
17
// ===----------------------------------------------------------------------===//
18
18
19
19
#define DEBUG_TYPE " address-lowering"
20
+ #include " swift/SIL/DebugUtils.h"
20
21
#include " swift/SIL/SILArgument.h"
21
22
#include " swift/SIL/SILBuilder.h"
22
23
#include " swift/SIL/SILVisitor.h"
@@ -107,11 +108,18 @@ struct AddressLoweringState {
107
108
SmallVector<Operand *, 16 > indirectOperands;
108
109
// All call instruction's with formally indirect result conventions.
109
110
SmallVector<SILInstruction *, 16 > indirectResults;
111
+ // All function-exiting terminators (return or throw instructions).
112
+ SmallVector<TermInst *, 8 > returnInsts;
110
113
// Delete these instructions after performing transformations.
111
114
// They must not have any remaining users.
112
115
SmallSetVector<SILInstruction *, 16 > instsToDelete;
113
116
114
117
AddressLoweringState (SILFunction *F) : F(F) {}
118
+
119
+ void markDeadInst (SILInstruction *inst) {
120
+ assert (onlyHaveDebugUses (inst));
121
+ instsToDelete.insert (inst);
122
+ }
115
123
};
116
124
} // end anonymous namespace
117
125
@@ -148,6 +156,9 @@ class OpaqueValueVisitor {
148
156
// / to valueStorageMap in RPO.
149
157
void OpaqueValueVisitor::mapValueStorage () {
150
158
for (auto *BB : postorderInfo.getReversePostOrder ()) {
159
+ if (BB->getTerminator ()->isFunctionExiting ())
160
+ pass.returnInsts .push_back (BB->getTerminator ());
161
+
151
162
// Opaque function arguments have already been replaced.
152
163
if (BB != pass.F ->getEntryBlock ()) {
153
164
for (auto argI = BB->args_begin (), argEnd = BB->args_end ();
@@ -220,11 +231,8 @@ namespace {
220
231
class OpaqueStorageAllocation {
221
232
AddressLoweringState &pass;
222
233
223
- SILBuilder allocBuilder;
224
-
225
234
public:
226
- explicit OpaqueStorageAllocation (AddressLoweringState &pass)
227
- : pass(pass), allocBuilder(*pass.F) {}
235
+ explicit OpaqueStorageAllocation (AddressLoweringState &pass) : pass(pass) {}
228
236
229
237
void allocateOpaqueStorage ();
230
238
@@ -265,13 +273,6 @@ void OpaqueStorageAllocation::allocateOpaqueStorage() {
265
273
// Populate valueStorageMap.
266
274
OpaqueValueVisitor (pass).mapValueStorage ();
267
275
268
- // Find an insertion point for new AllocStack instructions.
269
- SILBasicBlock::iterator insertionPoint = pass.F ->begin ()->begin ();
270
- while (isa<AllocStackInst>(*insertionPoint))
271
- ++insertionPoint;
272
-
273
- allocBuilder.setInsertionPoint (insertionPoint);
274
-
275
276
// Create an AllocStack for every opaque value defined in the function.
276
277
for (auto &valueStorageI : pass.valueStorageMap )
277
278
allocateForValue (valueStorageI.first , valueStorageI.second );
@@ -289,7 +290,7 @@ void OpaqueStorageAllocation::allocateOpaqueStorage() {
289
290
// / inserting a temprorary load instruction.
290
291
void OpaqueStorageAllocation::replaceFunctionArgs () {
291
292
// Insert temporary argument loads at the top of the function.
292
- allocBuilder. setInsertionPoint (pass.F ->getEntryBlock ()->begin ());
293
+ SILBuilder argBuilder (pass.F ->getEntryBlock ()->begin ());
293
294
294
295
auto fnConv = pass.F ->getConventions ();
295
296
unsigned argIdx = fnConv.getSILArgIndexOfFirstParam ();
@@ -300,7 +301,7 @@ void OpaqueStorageAllocation::replaceFunctionArgs() {
300
301
SILArgument *arg = pass.F ->getArgument (argIdx);
301
302
SILType addrType = arg->getType ().getAddressType ();
302
303
303
- LoadInst *loadArg = allocBuilder .createLoad (
304
+ LoadInst *loadArg = argBuilder .createLoad (
304
305
RegularLocation (const_cast <ValueDecl *>(arg->getDecl ())),
305
306
SILUndef::get (addrType, pass.F ->getModule ()),
306
307
LoadOwnershipQualifier::Unqualified);
@@ -374,14 +375,6 @@ static SILLocation getLocForValue(SILValue value) {
374
375
return value->getFunction ()->getLocation ();
375
376
}
376
377
377
- // / Create a dealloc_stack instruction.
378
- static DeallocStackInst *
379
- createDeallocStackAfterBlock (SILBasicBlock *deallocBlock,
380
- AllocStackInst *allocInstr) {
381
- SILBuilder deallocBuilder (deallocBlock->getTerminator ());
382
- return deallocBuilder.createDeallocStack (allocInstr->getLoc (), allocInstr);
383
- }
384
-
385
378
// / Allocate storage for a single opaque/resilient value.
386
379
void OpaqueStorageAllocation::allocateForValue (SILValue value,
387
380
ValueStorage &storage) {
@@ -397,26 +390,25 @@ void OpaqueStorageAllocation::allocateForValue(SILValue value,
397
390
return ;
398
391
}
399
392
393
+ SILBuilder allocBuilder (pass.F ->begin ()->begin ());
400
394
AllocStackInst *allocInstr =
401
395
allocBuilder.createAllocStack (getLocForValue (value), value->getType ());
402
396
403
397
storage.storageAddress = allocInstr;
404
398
405
- // TODO: insert deallocation at reasonable points.
406
- auto blockI = pass.F ->findReturnBB ();
407
- if (blockI != pass.F ->end ())
408
- createDeallocStackAfterBlock (&*blockI, allocInstr);
409
-
410
- if (pass.F ->findThrowBB () != pass.F ->end ())
411
- createDeallocStackAfterBlock (&*blockI, allocInstr);
399
+ // Insert stack deallocations.
400
+ for (TermInst *termInst : pass.returnInsts ) {
401
+ SILBuilder deallocBuilder (termInst);
402
+ deallocBuilder.createDeallocStack (allocInstr->getLoc (), allocInstr);
403
+ }
412
404
}
413
405
414
406
// / Deallocate temporary call-site stack storage.
415
407
static void insertStackDeallocationAtCall (AllocStackInst *allocInst,
416
408
SILInstruction *applyInst) {
417
409
switch (applyInst->getKind ()) {
418
410
case ValueKind::ApplyInst: {
419
- SILBuilder deallocBuilder (applyInst);
411
+ SILBuilder deallocBuilder (&* std::next ( applyInst-> getIterator ()) );
420
412
deallocBuilder.createDeallocStack (allocInst->getLoc (), allocInst);
421
413
break ;
422
414
}
@@ -509,8 +501,8 @@ void OpaqueStorageAllocation::allocateForResults(SILInstruction *origInst) {
509
501
switch (origInst->getKind ()) {
510
502
case ValueKind::ApplyInst:
511
503
callInst = callBuilder.createApply (
512
- loc, apply.getCallee (), apply.getSubstCalleeSILType (), apply. getType (),
513
- apply.getSubstitutions (), args,
504
+ loc, apply.getCallee (), apply.getSubstCalleeSILType (),
505
+ loweredFnConv. getSILResultType (), apply.getSubstitutions (), args,
514
506
cast<ApplyInst>(origInst)->isNonThrowing ());
515
507
break ;
516
508
case ValueKind::TryApplyInst:
@@ -528,15 +520,15 @@ void OpaqueStorageAllocation::allocateForResults(SILInstruction *origInst) {
528
520
// origInst remains in the map but has no users.
529
521
}
530
522
origInst->replaceAllUsesWith (callInst);
531
- pass.instsToDelete . insert (origInst);
532
- // Load a concrete args, and mark the extract for deletion.
523
+ pass.markDeadInst (origInst);
524
+ // Load concrete args, and mark the extract for deletion.
533
525
for (TupleExtractInst *extract : concreteResults) {
534
526
unsigned argIdx = firstResultIdx + extract->getFieldNo ();
535
527
SILValue arg = args[argIdx];
536
528
LoadInst *loadArg = callBuilder.createLoad (
537
529
extract->getLoc (), arg, LoadOwnershipQualifier::Unqualified);
538
530
extract->replaceAllUsesWith (loadArg);
539
- pass.instsToDelete . insert (extract);
531
+ pass.markDeadInst (extract);
540
532
}
541
533
}
542
534
@@ -600,16 +592,12 @@ class AddressOnlyRewriter : SILInstructionVisitor<AddressOnlyRewriter, void> {
600
592
B.createCopyAddr (copyInst->getLoc (), srcAddr, destAddr, IsNotTake,
601
593
IsInitialization);
602
594
}
603
-
604
- void visitTupleInst (TupleInst *tupleInst) {
605
- // Tuple elements have their own storage. Tuple instructions are dead.
606
- assert (!pass.valueStorageMap .getStorage (tupleInst).storageAddress );
607
- }
608
-
609
- void visitTupleExtractInst (TupleExtractInst *TEI) {
610
- // Tuple element instructions don't require rewrite. They are dead.
611
- llvm_unreachable (" Untested." );
612
- return ;
595
+
596
+ void visitDestroyValueInst (DestroyValueInst *destroyInst) {
597
+ SILValue src = destroyInst->getOperand ();
598
+ SILValue addr = pass.valueStorageMap .getStorage (src).storageAddress ;
599
+ B.createDestroyAddr (destroyInst->getLoc (), addr);
600
+ pass.markDeadInst (destroyInst);
613
601
}
614
602
615
603
void visitReturnInst (ReturnInst *returnInst) {
@@ -640,6 +628,17 @@ class AddressOnlyRewriter : SILInstructionVisitor<AddressOnlyRewriter, void> {
640
628
auto *tupleInst = B.createTuple (returnInst->getLoc (), emptyTy, {});
641
629
returnInst->setOperand (tupleInst);
642
630
}
631
+
632
+ void visitTupleInst (TupleInst *tupleInst) {
633
+ // Tuple elements have their own storage. Tuple instructions are dead.
634
+ assert (!pass.valueStorageMap .getStorage (tupleInst).storageAddress );
635
+ }
636
+
637
+ void visitTupleExtractInst (TupleExtractInst *extractInst) {
638
+ // Tuple element instructions don't require rewrite. They are dead.
639
+ llvm_unreachable (" Untested." );
640
+ return ;
641
+ }
643
642
};
644
643
} // end anonymous namespace
645
644
@@ -659,6 +658,8 @@ class AddressLowering : public SILModuleTransform {
659
658
} // end anonymous namespace
660
659
661
660
void AddressLowering::runOnFunction (SILFunction *F) {
661
+ DEBUG (llvm::dbgs () << " LOWER " ; F->dump ());
662
+
662
663
AddressLoweringState pass (F);
663
664
664
665
// Rewrite function args and insert alloc_stack/dealloc_stack.
0 commit comments