Skip to content

Commit a5c10d9

Browse files
Merge pull request #72576 from Snowy1803/6.0-verifier-conflicting-debug-value-types
[6.0] [SILVerifier] Add detection of conflicting debug variables
2 parents bda5952 + 69b226b commit a5c10d9

File tree

8 files changed

+80
-8
lines changed

8 files changed

+80
-8
lines changed

include/swift/SIL/SILCloner.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,8 @@ SILCloner<ImplClass>::visitAllocStackInst(AllocStackInst *Inst) {
875875
Loc = MandatoryInlinedLocation::getAutoGeneratedLocation();
876876
VarInfo = std::nullopt;
877877
}
878+
if (VarInfo && VarInfo->Type)
879+
VarInfo->Type = getOpType(*VarInfo->Type);
878880
auto *NewInst = getBuilder().createAllocStack(
879881
Loc, getOpType(Inst->getElementType()), VarInfo,
880882
Inst->hasDynamicLifetime(), Inst->isLexical(), Inst->isFromVarDecl(),
@@ -1408,6 +1410,8 @@ SILCloner<ImplClass>::visitDebugValueInst(DebugValueInst *Inst) {
14081410
// Since we want the debug info to survive, we do not remap the location here.
14091411
SILDebugVariable VarInfo = *Inst->getVarInfo();
14101412
getBuilder().setCurrentDebugScope(getOpScope(Inst->getDebugScope()));
1413+
if (VarInfo.Type)
1414+
VarInfo.Type = getOpType(*VarInfo.Type);
14111415
auto *NewInst = getBuilder().createDebugValue(
14121416
Inst->getLoc(), getOpValue(Inst->getOperand()), VarInfo,
14131417
Inst->poisonRefs(), Inst->usesMoveableValueDebugInfo(), Inst->hasTrace());

include/swift/SIL/SILLocation.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -773,4 +773,26 @@ class SILDebugLocation {
773773

774774
} // end swift namespace
775775

776+
namespace llvm {
777+
778+
template<>
779+
struct DenseMapInfo<swift::SILLocation> {
780+
static inline swift::SILLocation getEmptyKey() {
781+
return swift::SILLocation::invalid();
782+
}
783+
static inline swift::SILLocation getTombstoneKey() {
784+
return swift::SILLocation::invalid().asAutoGenerated();
785+
}
786+
static inline unsigned getHashValue(swift::SILLocation id) {
787+
if (id.isFilenameAndLocation())
788+
return hash_value(id);
789+
return 0;
790+
}
791+
static bool isEqual(swift::SILLocation a, swift::SILLocation b) {
792+
return a == b;
793+
}
794+
};
795+
796+
} // end namespace llvm
797+
776798
#endif

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -820,6 +820,11 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
820820
/// fix this for each of its uses.
821821
llvm::DenseSet<std::pair<SILValue, const Operand *>> isOperandInValueUsesCache;
822822

823+
/// Used for checking all equivalent variables have the same type
824+
using VarID = std::tuple<const SILDebugScope *, llvm::StringRef, SILLocation>;
825+
llvm::DenseMap<VarID, SILType> DebugVarTypes;
826+
llvm::StringSet<> VarNames;
827+
823828
/// Check that this operand appears in the use-chain of the value it uses.
824829
bool isOperandInValueUses(const Operand *operand) {
825830
SILValue value = operand->get();
@@ -1520,6 +1525,26 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
15201525
"Scope of the debug variable should have the same parent function"
15211526
" as that of instruction.");
15221527

1528+
// Check that every var info with the same name, scope and location, refer
1529+
// to a variable of the same type
1530+
llvm::StringRef UniqueName = VarNames.insert(varInfo->Name).first->getKey();
1531+
if (!varInfo->Loc)
1532+
varInfo->Loc = inst->getLoc();
1533+
if (!varInfo->Loc)
1534+
varInfo->Loc = SILLocation::invalid();
1535+
VarID Key(varInfo->Scope ? varInfo->Scope : debugScope,
1536+
UniqueName, *varInfo->Loc);
1537+
auto CachedVar = DebugVarTypes.insert({Key, DebugVarTy});
1538+
if (!CachedVar.second) {
1539+
auto lhs = CachedVar.first->second.removingMoveOnlyWrapper();
1540+
auto rhs = DebugVarTy.removingMoveOnlyWrapper();
1541+
1542+
require(lhs == rhs ||
1543+
(lhs.isAddress() && lhs.getObjectType() == rhs) ||
1544+
(DebugVarTy.isAddress() && lhs == rhs.getObjectType()),
1545+
"Two variables with different type but same scope!");
1546+
}
1547+
15231548
// Check debug info expression
15241549
if (const auto &DIExpr = varInfo->DIExpr) {
15251550
bool HasFragment = false;

lib/SILGen/SILGenPattern.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2870,7 +2870,12 @@ void PatternMatchEmission::emitAddressOnlyAllocations() {
28702870
if (!ty.isAddressOnly(SGF.F))
28712871
continue;
28722872
assert(!Temporaries[vd]);
2873-
Temporaries[vd] = SGF.emitTemporaryAllocation(vd, ty);
2873+
// Don't generate debug info for the temporary, as another debug_value
2874+
// will be created in the body, with the same scope and a different type
2875+
// Not sure if this is the best way to avoid that?
2876+
Temporaries[vd] = SGF.emitTemporaryAllocation(
2877+
vd, ty, DoesNotHaveDynamicLifetime, IsNotLexical, IsNotFromVarDecl,
2878+
/* generateDebugInfo = */ false);
28742879
}
28752880
}
28762881

lib/SILGen/SILGenProlog.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1297,7 +1297,7 @@ void SILGenFunction::emitProlog(
12971297

12981298
emitExpectedExecutor();
12991299

1300-
// IMPORTANT: This block should be the last one in `emitProlog`,
1300+
// IMPORTANT: This block should be the last one in `emitProlog`,
13011301
// since it terminates BB and no instructions should be insterted after it.
13021302
// Emit an unreachable instruction if a parameter type is
13031303
// uninhabited
@@ -1501,5 +1501,18 @@ uint16_t SILGenFunction::emitBasicProlog(
15011501
B.createDebugValue(loc, undef.getValue(), dbgVar);
15021502
}
15031503

1504+
for (auto &i : *B.getInsertionBB()) {
1505+
auto *alloc = dyn_cast<AllocStackInst>(&i);
1506+
if (!alloc)
1507+
continue;
1508+
auto varInfo = alloc->getVarInfo();
1509+
if (!varInfo || varInfo->ArgNo)
1510+
continue;
1511+
// The allocation has a varinfo but no argument number, which should not
1512+
// happen in the prolog. Unfortunately, some copies can generate wrong
1513+
// debug info, so we have to fix it here, by invalidating it.
1514+
alloc->invalidateVarInfo();
1515+
}
1516+
15041517
return ArgNo;
15051518
}

lib/SILOptimizer/Differentiation/PullbackCloner.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1552,8 +1552,11 @@ class PullbackCloner::Implementation final
15521552
auto adjVal = materializeAdjointDirect(getAdjointValue(bb, inst), loc);
15531553
// Allocate a local buffer and store the adjoint value. This buffer will
15541554
// be used for accumulation into the adjoint buffer.
1555-
auto adjBuf = builder.createAllocStack(
1556-
loc, adjVal->getType(), SILDebugVariable());
1555+
auto adjBuf = builder.createAllocStack(loc, adjVal->getType(), {},
1556+
DoesNotHaveDynamicLifetime,
1557+
IsNotLexical, IsNotFromVarDecl,
1558+
DoesNotUseMoveableValueDebugInfo,
1559+
/* skipVarDeclAssert = */ true);
15571560
auto copy = builder.emitCopyValueOperation(loc, adjVal);
15581561
builder.emitStoreValueOperation(loc, copy, adjBuf,
15591562
StoreOwnershipQualifier::Init);

test/SILGen/switch.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1461,9 +1461,9 @@ func testVoidType() {
14611461

14621462
// CHECK-LABEL: sil hidden [ossa] @$s6switch28addressOnlyFallthroughCalleeyyAA015MultipleAddressC8CaseEnumOyxGSzRzlF : $@convention(thin) <T where T : BinaryInteger> (@in_guaranteed MultipleAddressOnlyCaseEnum<T>) -> () {
14631463
// CHECK: bb0([[ARG:%.*]] :
1464-
// CHECK: [[AB_PHI:%.*]] = alloc_stack $T, let, name "x"
1465-
// CHECK: [[ABB_PHI:%.*]] = alloc_stack $T, let, name "x"
1466-
// CHECK: [[ABBC_PHI:%.*]] = alloc_stack $T, let, name "x"
1464+
// CHECK: [[AB_PHI:%.*]] = alloc_stack $T
1465+
// CHECK: [[ABB_PHI:%.*]] = alloc_stack $T
1466+
// CHECK: [[ABBC_PHI:%.*]] = alloc_stack $T
14671467
// CHECK: [[SWITCH_ENUM_ARG:%.*]] = alloc_stack $MultipleAddressOnlyCaseEnum<T>
14681468
// CHECK: copy_addr [[ARG]] to [init] [[SWITCH_ENUM_ARG]]
14691469
// CHECK: switch_enum_addr [[SWITCH_ENUM_ARG]] : $*MultipleAddressOnlyCaseEnum<T>, case #MultipleAddressOnlyCaseEnum.a!enumelt: [[BB_A:bb[0-9]+]], case #MultipleAddressOnlyCaseEnum.b!enumelt: [[BB_B:bb[0-9]+]], case #MultipleAddressOnlyCaseEnum.c!enumelt: [[BB_C:bb[0-9]+]]

test/SILOptimizer/init_accessors.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ struct TestGenericTuple<T, U> {
330330
//
331331
// CHECK: bb0([[A_REF:%.*]] : $*T, [[B_REF:%.*]] : $*(T, U), [[A_VALUE:%.*]] : $*T, [[B_VALUE:%.*]] : $*T, [[C_VALUE:%.*]] : $*U, [[METATYPE:%.*]] : $@thin TestGenericTuple<T, U>.Type):
332332
//
333-
// CHECK: [[INIT_VALUE_1:%.*]] = alloc_stack $(T, U), let, name "initialValue"
333+
// CHECK: [[INIT_VALUE_1:%.*]] = alloc_stack $(T, U)
334334
// CHECK-NEXT: [[INIT_VALUE_1_0:%.*]] = tuple_element_addr [[INIT_VALUE_1]] : $*(T, U), 0
335335
// CHECK-NEXT: copy_addr [take] [[B_VALUE]] to [init] [[INIT_VALUE_1_0]]
336336
// CHECK-NEXT: [[INIT_VALUE_1_1:%.*]] = tuple_element_addr [[INIT_VALUE_1]] : $*(T, U), 1

0 commit comments

Comments
 (0)