Skip to content

Commit 0ad5044

Browse files
committed
[SILVerifier] Add detection of conflicting debug variables
1 parent a624939 commit 0ad5044

File tree

1 file changed

+51
-0
lines changed

1 file changed

+51
-0
lines changed

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,32 @@ static void checkAddressWalkerCanVisitAllTransitiveUses(SILValue address) {
792792
llvm::report_fatal_error("invoking standard assertion failure");
793793
}
794794

795+
} // end anonymous namespace
796+
797+
namespace llvm {
798+
799+
template<>
800+
struct DenseMapInfo<SILLocation> {
801+
static inline SILLocation getEmptyKey() {
802+
return SILLocation::invalid();
803+
}
804+
static inline SILLocation getTombstoneKey() {
805+
return SILLocation::invalid().asAutoGenerated();
806+
}
807+
static inline unsigned getHashValue(SILLocation id) {
808+
if (id.isFilenameAndLocation())
809+
return hash_value(id);
810+
return 0;
811+
}
812+
static bool isEqual(SILLocation a, SILLocation b) {
813+
return a == b;
814+
}
815+
};
816+
817+
} // end namespace llvm
818+
819+
namespace {
820+
795821
/// The SIL verifier walks over a SIL function / basic block / instruction,
796822
/// checking and enforcing its invariants.
797823
class SILVerifier : public SILVerifierBase<SILVerifier> {
@@ -820,6 +846,11 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
820846
/// fix this for each of its uses.
821847
llvm::DenseSet<std::pair<SILValue, const Operand *>> isOperandInValueUsesCache;
822848

849+
/// Used for checking all equivalent variables have the same type
850+
using VarID = std::tuple<const SILDebugScope *, llvm::StringRef, SILLocation>;
851+
llvm::DenseMap<VarID, SILType> DebugVarTypes;
852+
llvm::StringSet<> VarNames;
853+
823854
/// Check that this operand appears in the use-chain of the value it uses.
824855
bool isOperandInValueUses(const Operand *operand) {
825856
SILValue value = operand->get();
@@ -1520,6 +1551,26 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
15201551
"Scope of the debug variable should have the same parent function"
15211552
" as that of instruction.");
15221553

1554+
// Check that every var info with the same name, scope and location, refer
1555+
// to a variable of the same type
1556+
llvm::StringRef UniqueName = VarNames.insert(varInfo->Name).first->getKey();
1557+
if (!varInfo->Loc)
1558+
varInfo->Loc = inst->getLoc();
1559+
if (!varInfo->Loc)
1560+
varInfo->Loc = SILLocation::invalid();
1561+
VarID Key(varInfo->Scope ? varInfo->Scope : debugScope,
1562+
UniqueName, *varInfo->Loc);
1563+
auto CachedVar = DebugVarTypes.insert({Key, DebugVarTy});
1564+
if (!CachedVar.second) {
1565+
auto lhs = CachedVar.first->second.removingMoveOnlyWrapper();
1566+
auto rhs = DebugVarTy.removingMoveOnlyWrapper();
1567+
1568+
require(lhs == rhs ||
1569+
(lhs.isAddress() && lhs.getObjectType() == rhs) ||
1570+
(DebugVarTy.isAddress() && lhs == rhs.getObjectType()),
1571+
"Two variables with different type but same scope!");
1572+
}
1573+
15231574
// Check debug info expression
15241575
if (const auto &DIExpr = varInfo->DIExpr) {
15251576
bool HasFragment = false;

0 commit comments

Comments
 (0)