Skip to content

Commit 69b226b

Browse files
committed
[SILVerifier] Add detection of conflicting debug variables
(cherry picked from commit fed03cc)
1 parent 910d63e commit 69b226b

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed

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;

0 commit comments

Comments
 (0)