|
| 1 | +//===--- MoveOnlyDeinitInsertion.cpp --------------------------------------===// |
| 2 | +// |
| 3 | +// This source file is part of the Swift.org open source project |
| 4 | +// |
| 5 | +// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors |
| 6 | +// Licensed under Apache License v2.0 with Runtime Library Exception |
| 7 | +// |
| 8 | +// See https://swift.org/LICENSE.txt for license information |
| 9 | +// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| 10 | +// |
| 11 | +//===----------------------------------------------------------------------===// |
| 12 | +/// |
| 13 | +/// \file |
| 14 | +/// |
| 15 | +/// This pass runs after move only checking has occured and transforms last |
| 16 | +/// destroy_value of move only types into a call to the move only types deinit. |
| 17 | +/// |
| 18 | +//===----------------------------------------------------------------------===// |
| 19 | + |
| 20 | +#define DEBUG_TYPE "sil-move-only-checker" |
| 21 | + |
| 22 | +#include "swift/AST/DiagnosticEngine.h" |
| 23 | +#include "swift/AST/DiagnosticsSIL.h" |
| 24 | +#include "swift/AST/SubstitutionMap.h" |
| 25 | +#include "swift/Basic/Defer.h" |
| 26 | +#include "swift/Basic/FrozenMultiMap.h" |
| 27 | +#include "swift/SIL/ApplySite.h" |
| 28 | +#include "swift/SIL/BasicBlockBits.h" |
| 29 | +#include "swift/SIL/BasicBlockData.h" |
| 30 | +#include "swift/SIL/BasicBlockDatastructures.h" |
| 31 | +#include "swift/SIL/BasicBlockUtils.h" |
| 32 | +#include "swift/SIL/Consumption.h" |
| 33 | +#include "swift/SIL/DebugUtils.h" |
| 34 | +#include "swift/SIL/InstructionUtils.h" |
| 35 | +#include "swift/SIL/MemAccessUtils.h" |
| 36 | +#include "swift/SIL/OwnershipUtils.h" |
| 37 | +#include "swift/SIL/PostOrder.h" |
| 38 | +#include "swift/SIL/PrunedLiveness.h" |
| 39 | +#include "swift/SIL/SILArgument.h" |
| 40 | +#include "swift/SIL/SILArgumentConvention.h" |
| 41 | +#include "swift/SIL/SILBasicBlock.h" |
| 42 | +#include "swift/SIL/SILBuilder.h" |
| 43 | +#include "swift/SIL/SILFunction.h" |
| 44 | +#include "swift/SIL/SILInstruction.h" |
| 45 | +#include "swift/SIL/SILMoveOnlyDeinit.h" |
| 46 | +#include "swift/SIL/SILUndef.h" |
| 47 | +#include "swift/SIL/SILValue.h" |
| 48 | +#include "swift/SILOptimizer/Analysis/Analysis.h" |
| 49 | +#include "swift/SILOptimizer/PassManager/Passes.h" |
| 50 | +#include "swift/SILOptimizer/PassManager/Transforms.h" |
| 51 | + |
| 52 | +using namespace swift; |
| 53 | + |
| 54 | +static bool performTransform(SILFunction &fn) { |
| 55 | + bool changed = false; |
| 56 | + |
| 57 | + auto &mod = fn.getModule(); |
| 58 | + for (auto &block : fn) { |
| 59 | + for (auto ii = block.begin(), ie = block.end(); ii != ie;) { |
| 60 | + auto *inst = &*ii; |
| 61 | + ++ii; |
| 62 | + |
| 63 | + if (auto *dvi = dyn_cast<DestroyValueInst>(inst)) { |
| 64 | + auto destroyType = dvi->getOperand()->getType(); |
| 65 | + if (destroyType.isMoveOnlyType()) { |
| 66 | + LLVM_DEBUG(llvm::dbgs() << "Handling: " << *dvi); |
| 67 | + auto *nom = destroyType.getNominalOrBoundGenericNominal(); |
| 68 | + assert(nom); |
| 69 | + auto *deinitFunc = mod.lookUpMoveOnlyDeinitFunction(nom); |
| 70 | + if (!deinitFunc) { |
| 71 | + LLVM_DEBUG(llvm::dbgs() |
| 72 | + << "Failed to find deinit func for type! Skipping!\n"); |
| 73 | + continue; |
| 74 | + } |
| 75 | + |
| 76 | + auto astType = destroyType.getASTType(); |
| 77 | + auto subMap = |
| 78 | + astType->getContextSubstitutionMap(nom->getModuleContext(), nom); |
| 79 | + SILBuilderWithScope builder(dvi); |
| 80 | + auto *funcRef = builder.createFunctionRef(dvi->getLoc(), deinitFunc); |
| 81 | + builder.createApply(dvi->getLoc(), funcRef, subMap, |
| 82 | + dvi->getOperand()); |
| 83 | + dvi->eraseFromParent(); |
| 84 | + changed = true; |
| 85 | + continue; |
| 86 | + } |
| 87 | + } |
| 88 | + |
| 89 | + if (auto *dai = dyn_cast<DestroyAddrInst>(inst)) { |
| 90 | + auto destroyType = dai->getOperand()->getType(); |
| 91 | + if (destroyType.isLoadable(fn) && destroyType.isMoveOnlyType()) { |
| 92 | + LLVM_DEBUG(llvm::dbgs() << "Handling: " << *dai); |
| 93 | + auto *nom = destroyType.getNominalOrBoundGenericNominal(); |
| 94 | + assert(nom); |
| 95 | + auto *deinitFunc = mod.lookUpMoveOnlyDeinitFunction(nom); |
| 96 | + if (!deinitFunc) { |
| 97 | + LLVM_DEBUG(llvm::dbgs() |
| 98 | + << "Failed to find deinit func for type! Skipping!\n"); |
| 99 | + continue; |
| 100 | + } |
| 101 | + |
| 102 | + SILBuilderWithScope builder(dai); |
| 103 | + auto *funcRef = builder.createFunctionRef(dai->getLoc(), deinitFunc); |
| 104 | + auto subMap = destroyType.getASTType()->getContextSubstitutionMap( |
| 105 | + nom->getModuleContext(), nom); |
| 106 | + auto loadedValue = builder.emitLoadValueOperation( |
| 107 | + dai->getLoc(), dai->getOperand(), LoadOwnershipQualifier::Take); |
| 108 | + builder.createApply(dai->getLoc(), funcRef, subMap, loadedValue); |
| 109 | + dai->eraseFromParent(); |
| 110 | + changed = true; |
| 111 | + continue; |
| 112 | + } |
| 113 | + } |
| 114 | + } |
| 115 | + } |
| 116 | + |
| 117 | + return changed; |
| 118 | +} |
| 119 | + |
| 120 | +//===----------------------------------------------------------------------===// |
| 121 | +// Top Level Entrypoint |
| 122 | +//===----------------------------------------------------------------------===// |
| 123 | + |
| 124 | +namespace { |
| 125 | + |
| 126 | +class SILMoveOnlyDeinitInsertionPass : public SILFunctionTransform { |
| 127 | + void run() override { |
| 128 | + auto *fn = getFunction(); |
| 129 | + |
| 130 | + // Don't rerun diagnostics on deserialized functions. |
| 131 | + if (getFunction()->wasDeserializedCanonical()) |
| 132 | + return; |
| 133 | + |
| 134 | + assert(fn->getModule().getStage() == SILStage::Raw && |
| 135 | + "Should only run on Raw SIL"); |
| 136 | + LLVM_DEBUG(llvm::dbgs() << "===> MoveOnly Deinit Insertion. Visiting: " |
| 137 | + << fn->getName() << '\n'); |
| 138 | + if (performTransform(*fn)) { |
| 139 | + invalidateAnalysis(SILAnalysis::InvalidationKind::CallsAndInstructions); |
| 140 | + } |
| 141 | + } |
| 142 | +}; |
| 143 | + |
| 144 | +} // anonymous namespace |
| 145 | + |
| 146 | +SILTransform *swift::createMoveOnlyDeinitInsertion() { |
| 147 | + return new SILMoveOnlyDeinitInsertionPass(); |
| 148 | +} |
0 commit comments