mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Audit all SILPasses to ensure that new instructions are never created
without a valid SILDebugScope. An assertion in IRGenSIL prevents future optimizations from regressing in this regard. Introducing SILBuilderWithScope and SILBuilderwithPostprocess to ease the transition. This patch is large, but mostly mechanical. <rdar://problem/18494573> Swift: Debugger is not stopping at the set breakpoint Swift SVN r22978
This commit is contained in:
@@ -15,6 +15,7 @@
|
||||
|
||||
#include "swift/SIL/SILFunction.h"
|
||||
#include "swift/SIL/SILModule.h"
|
||||
#include "swift/SIL/SILDebugScope.h"
|
||||
|
||||
namespace swift {
|
||||
|
||||
@@ -1057,6 +1058,37 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// An RAII version of SILBuilder that automatically sets up identical
|
||||
/// SILDebugScopes for all instructions. This is useful for
|
||||
/// situations where a single SIL instruction is lowered into a
|
||||
/// sequence of SIL instructions.
|
||||
template<unsigned N = 4> class SILBuilderWithScope : public SILBuilder {
|
||||
SmallVector<SILInstruction*, N> InsertedInstrs;
|
||||
SILDebugScope *DebugScope;
|
||||
|
||||
public:
|
||||
explicit SILBuilderWithScope(SILInstruction *I)
|
||||
: SILBuilder(I, &InsertedInstrs), DebugScope(I->getDebugScope()) {
|
||||
assert((DebugScope || maybeScopeless(*I)) && "no debug scope");
|
||||
}
|
||||
|
||||
explicit SILBuilderWithScope(SILInstruction *I, SILDebugScope *DS)
|
||||
: SILBuilder(I, &InsertedInstrs), DebugScope(DS) {
|
||||
}
|
||||
|
||||
explicit SILBuilderWithScope(SILBasicBlock *BB, SILDebugScope *DS)
|
||||
: SILBuilder(BB, &InsertedInstrs), DebugScope(DS) {
|
||||
}
|
||||
|
||||
~SILBuilderWithScope() {
|
||||
for (auto *I : InsertedInstrs) {
|
||||
assert(!I->getDebugScope() && "instruction was already assigned a scope");
|
||||
I->setDebugScope(DebugScope);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // end swift namespace
|
||||
|
||||
#endif
|
||||
|
||||
@@ -52,6 +52,7 @@ public:
|
||||
return getBuilder().getTrackingList();
|
||||
}
|
||||
|
||||
SILBuilder &getBuilder() { return Builder; }
|
||||
|
||||
protected:
|
||||
#define VALUE(CLASS, PARENT) \
|
||||
@@ -64,8 +65,6 @@ protected:
|
||||
|
||||
void visitSILBasicBlock(SILBasicBlock* BB);
|
||||
|
||||
SILBuilder &getBuilder() { return Builder; }
|
||||
|
||||
// Derived classes of SILCloner using the CRTP can implement the following
|
||||
// functions to customize behavior; the remap functions are called before
|
||||
// cloning to modify constructor arguments and the post process function is
|
||||
@@ -224,10 +223,16 @@ protected:
|
||||
SILBasicBlock *getOpBasicBlock(SILBasicBlock *BB) {
|
||||
return asImpl().remapBasicBlock(BB);
|
||||
}
|
||||
|
||||
public:
|
||||
void doPostProcess(SILInstruction *Orig, SILInstruction *Cloned) {
|
||||
asImpl().postProcess(Orig, Cloned);
|
||||
assert((Orig->getDebugScope() ? Cloned->getDebugScope()!=nullptr : true) &&
|
||||
"cloned instruction dropped debug scope");
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
SILBuilder Builder;
|
||||
SILBasicBlock *InsertBeforeBB;
|
||||
llvm::DenseMap<SILValue, SILValue> ValueMap;
|
||||
@@ -236,6 +241,31 @@ protected:
|
||||
TypeSubstitutionMap OpenedExistentialSubs;
|
||||
};
|
||||
|
||||
/// \brief A SILBuilder that automatically invokes postprocess on each
|
||||
/// inserted instruction.
|
||||
template<class SomeSILCloner, unsigned N = 4>
|
||||
class SILBuilderWithPostProcess : public SILBuilder {
|
||||
SomeSILCloner &SC;
|
||||
SILInstruction *Orig;
|
||||
SmallVector<SILInstruction*, N> InsertedInstrs;
|
||||
|
||||
public:
|
||||
SILBuilderWithPostProcess(SomeSILCloner *sc, SILInstruction *Orig)
|
||||
: SILBuilder(sc->getBuilder().getInsertionBB(), &InsertedInstrs),
|
||||
SC(*sc), Orig(Orig)
|
||||
{
|
||||
setInsertionPoint(SC.getBuilder().getInsertionBB(),
|
||||
SC.getBuilder().getInsertionPoint());
|
||||
}
|
||||
|
||||
~SILBuilderWithPostProcess() {
|
||||
for (auto *I : InsertedInstrs) {
|
||||
SC.doPostProcess(Orig, I);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// SILClonerWithScopes - a SILCloner that automatically clones
|
||||
/// SILDebugScopes. In contrast to inline scopes, this generates a
|
||||
/// deep copy of the scope tree.
|
||||
|
||||
@@ -68,6 +68,11 @@ public:
|
||||
void setParent(SILDebugScope *P) { Parent = P; }
|
||||
};
|
||||
|
||||
#ifndef NDEBUG
|
||||
/// Determine whether an instruction may not have a SILDebugScope.
|
||||
bool maybeScopeless(SILInstruction &I);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -154,17 +154,15 @@ protected:
|
||||
// the newly specialized function.
|
||||
SILValue CalleeVal = Inst->getCallee();
|
||||
FunctionRefInst *FRI = dyn_cast<FunctionRefInst>(CalleeVal);
|
||||
SILBuilder &Builder = getBuilder();
|
||||
SILBuilderWithPostProcess<TypeSubstCloner, 4> Builder(this, Inst);
|
||||
if (FRI && FRI->getReferencedFunction() == Inst->getFunction()) {
|
||||
FRI = Builder.createFunctionRef(getOpLocation(Inst->getLoc()),
|
||||
&Builder.getFunction());
|
||||
PartialApplyInst *NPAI =
|
||||
Builder.createPartialApply(getOpLocation(Inst->getLoc()), FRI,
|
||||
getOpType(Inst->getSubstCalleeSILType()),
|
||||
ArrayRef<Substitution>(),
|
||||
Args,
|
||||
getOpType(Inst->getType()));
|
||||
doPostProcess(Inst, NPAI);
|
||||
Builder.createPartialApply(getOpLocation(Inst->getLoc()), FRI,
|
||||
getOpType(Inst->getSubstCalleeSILType()),
|
||||
ArrayRef<Substitution>(),
|
||||
Args,
|
||||
getOpType(Inst->getType()));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -173,11 +171,10 @@ protected:
|
||||
TempSubstList.push_back(asImpl().getOpSubstitution(Sub));
|
||||
}
|
||||
|
||||
PartialApplyInst *N = Builder.createPartialApply(
|
||||
Builder.createPartialApply(
|
||||
getOpLocation(Inst->getLoc()), getOpValue(CalleeVal),
|
||||
getOpType(Inst->getSubstCalleeSILType()), TempSubstList, Args,
|
||||
getOpType(Inst->getType()));
|
||||
doPostProcess(Inst, N);
|
||||
}
|
||||
|
||||
void visitWitnessMethodInst(WitnessMethodInst *Inst) {
|
||||
@@ -236,7 +233,7 @@ protected:
|
||||
SILType sourceType = getOpType(inst->getOperand().getType());
|
||||
SILType targetType = getOpType(inst->getType());
|
||||
SILLocation loc = getOpLocation(inst->getLoc());
|
||||
SILBuilder &B = getBuilder();
|
||||
SILBuilderWithPostProcess<TypeSubstCloner, 16> B(this, inst);
|
||||
|
||||
// The non-addr CheckedCastInsts can currently only be used for
|
||||
// types that don't have abstraction differences, so this is okay.
|
||||
@@ -279,7 +276,7 @@ protected:
|
||||
SILLocation loc = getOpLocation(inst->getLoc());
|
||||
SILValue src = getOpValue(inst->getSrc());
|
||||
SILValue dest = getOpValue(inst->getDest());
|
||||
SILBuilder &B = getBuilder();
|
||||
SILBuilderWithPostProcess<TypeSubstCloner, 16> B(this, inst);
|
||||
|
||||
CanType sourceType = getOpASTType(inst->getSourceType());
|
||||
CanType targetType = getOpASTType(inst->getTargetType());
|
||||
@@ -295,11 +292,9 @@ protected:
|
||||
|
||||
case DynamicCastFeasibility::MaySucceed: {
|
||||
// TODO: simplify?
|
||||
auto newInst =
|
||||
B.createUnconditionalCheckedCastAddr(loc, inst->getConsumptionKind(),
|
||||
src, sourceType,
|
||||
dest, targetType);
|
||||
doPostProcess(inst, newInst);
|
||||
B.createUnconditionalCheckedCastAddr(loc, inst->getConsumptionKind(),
|
||||
src, sourceType,
|
||||
dest, targetType);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -307,8 +302,7 @@ protected:
|
||||
// runtime as the spec for the instruction requires and propagate
|
||||
// undef to all uses.
|
||||
case DynamicCastFeasibility::WillFail: {
|
||||
auto newInst = B.createBuiltinTrap(loc);
|
||||
doPostProcess(inst, newInst);
|
||||
B.createBuiltinTrap(loc);
|
||||
|
||||
// mem2reg's invariants get unhappy if we don't try to
|
||||
// initialize a loadable result.
|
||||
@@ -335,15 +329,14 @@ protected:
|
||||
SILBasicBlock *succBB = getOpBasicBlock(inst->getSuccessBB());
|
||||
SILBasicBlock *failBB = getOpBasicBlock(inst->getFailureBB());
|
||||
|
||||
SILBuilder &B = getBuilder();
|
||||
SILBuilderWithPostProcess<TypeSubstCloner, 16> B(this, inst);
|
||||
switch (classifyDynamicCast(SwiftMod, sourceType, targetType)) {
|
||||
case DynamicCastFeasibility::WillSucceed: {
|
||||
emitSuccessfulIndirectUnconditionalCast(B, SwiftMod, loc,
|
||||
inst->getConsumptionKind(),
|
||||
src, sourceType,
|
||||
dest, targetType);
|
||||
auto br = B.createBranch(loc, succBB);
|
||||
doPostProcess(inst, br);
|
||||
B.createBranch(loc, succBB);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -360,11 +353,10 @@ protected:
|
||||
}
|
||||
|
||||
// Otherwise, use the indirect cast.
|
||||
auto br = B.createCheckedCastAddrBranch(loc, inst->getConsumptionKind(),
|
||||
src, sourceType,
|
||||
dest, targetType,
|
||||
succBB, failBB);
|
||||
doPostProcess(inst, br);
|
||||
B.createCheckedCastAddrBranch(loc, inst->getConsumptionKind(),
|
||||
src, sourceType,
|
||||
dest, targetType,
|
||||
succBB, failBB);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -373,7 +365,7 @@ protected:
|
||||
auto &srcTL = B.getModule().getTypeLowering(src.getType());
|
||||
srcTL.emitDestroyAddress(B, loc, src);
|
||||
}
|
||||
doPostProcess(inst, B.createBranch(loc, failBB));
|
||||
B.createBranch(loc, failBB);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -391,7 +383,7 @@ protected:
|
||||
SILLocation loc = getOpLocation(inst->getLoc());
|
||||
SILBasicBlock *succBB = getOpBasicBlock(inst->getSuccessBB());
|
||||
SILBasicBlock *failBB = getOpBasicBlock(inst->getFailureBB());
|
||||
SILBuilder &B = getBuilder();
|
||||
SILBuilderWithPostProcess<TypeSubstCloner, 16> B(this, inst);
|
||||
|
||||
SILValue operand = getOpValue(inst->getOperand());
|
||||
|
||||
@@ -406,8 +398,7 @@ protected:
|
||||
// we're still using checked_cast_branch for address-only stuff.
|
||||
if (loweredTargetType.isAddress()) {
|
||||
if (sourceType == targetType) {
|
||||
auto br = B.createBranch(loc, succBB, operand);
|
||||
doPostProcess(inst, br);
|
||||
B.createBranch(loc, succBB, operand);
|
||||
return;
|
||||
}
|
||||
goto maySucceed;
|
||||
@@ -418,21 +409,19 @@ protected:
|
||||
loweredTargetType, sourceType,
|
||||
targetType);
|
||||
|
||||
auto br = B.createBranch(loc, succBB, result);
|
||||
doPostProcess(inst, br);
|
||||
B.createBranch(loc, succBB, result);
|
||||
return;
|
||||
}
|
||||
|
||||
maySucceed:
|
||||
case DynamicCastFeasibility::MaySucceed: {
|
||||
auto br = B.createCheckedCastBranch(loc, /*exact*/ false, operand,
|
||||
loweredTargetType, succBB, failBB);
|
||||
doPostProcess(inst, br);
|
||||
B.createCheckedCastBranch(loc, /*exact*/ false, operand,
|
||||
loweredTargetType, succBB, failBB);
|
||||
return;
|
||||
}
|
||||
|
||||
case DynamicCastFeasibility::WillFail:
|
||||
doPostProcess(inst, B.createBranch(loc, failBB));
|
||||
B.createBranch(loc, failBB);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user