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:
Adrian Prantl
2014-10-28 01:49:11 +00:00
parent 35488903d3
commit c41b30299f
36 changed files with 383 additions and 211 deletions

View File

@@ -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

View File

@@ -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.

View File

@@ -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

View File

@@ -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;
}
}